> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dynamosql.com/llms.txt
> Use this file to discover all available pages before exploring further.

# IAM Setup

> Grant DynamoSQL read access to your DynamoDB tables by creating a schema in the portal.

DynamoSQL queries DynamoDB in your own AWS account. Instead of storing long-lived credentials, DynamoSQL's data plane assumes an IAM role you create and control. This means your data never leaves your account — DynamoSQL receives only the query results it fetches on your behalf.

The portal walks you through this end-to-end when you create a schema. It generates the exact trust policy and permissions policy JSON for you to copy into AWS.

## Step 1: Create a schema in the portal

In the portal, navigate to **Schemas** and click **Create schema**. Fill in the following fields:

| Field               | Description                                                                                                                                 |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| **Schema name**     | Logical name used in SQL (`schema.table`). Cannot be changed after creation.                                                                |
| **Region**          | AWS region where your DynamoDB tables live (e.g., `us-east-1`).                                                                             |
| **Account ID**      | Your 12-digit AWS account number.                                                                                                           |
| **Role name**       | The IAM role name you will create in Step 2 (e.g., `DynamoSqlReadRole`).                                                                    |
| **External ID**     | Auto-generated. Used in the trust policy to prevent confused-deputy attacks. You can regenerate it, but do so before creating the IAM role. |
| **Table allowlist** | Table names DynamoSQL is allowed to query, one per line — or check **Allow all tables (\*)** for wildcard access.                           |

The portal derives the full role ARN from your account ID and role name and shows it to you before you submit.

## Step 2: Copy the generated IAM policies

Expand **Role setup instructions (AWS Console + CLI)** on the schema creation form. The portal generates two ready-to-use JSON documents based on your inputs:

**Trust policy** — allows DynamoSQL's data plane to assume the role, scoped to your ExternalId:

```json theme={null}
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowDynamoSqlAssumeRole",
      "Effect": "Allow",
      "Principal": {
        "AWS": ["arn:aws:iam::<dynamosql-account-id>:root"]
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "sts:ExternalId": "<your-external-id>"
        }
      }
    }
  ]
}
```

**DynamoDB read policy** — grants the read permissions DynamoSQL needs, scoped to your allowlisted tables:

```json theme={null}
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowDynamoSqlReadQueries",
      "Effect": "Allow",
      "Action": [
        "dynamodb:BatchGetItem",
        "dynamodb:DescribeTable",
        "dynamodb:GetItem",
        "dynamodb:Query",
        "dynamodb:Scan"
      ],
      "Resource": [
        "arn:aws:dynamodb:*:<your-account-id>:table/<table-name>"
      ]
    }
  ]
}
```

<Note>
  When **Allow all tables (\*)** is enabled, the portal adds a `dynamodb:ListTables` statement on `Resource: "*"` so DynamoSQL can enumerate your tables.
</Note>

Use the **Copy** buttons in the portal to copy each JSON block exactly — the values are pre-filled with your account ID, role name, and ExternalId.

## Step 3: Create the IAM role in AWS

The portal also shows a ready-to-run **AWS CLI script**. The fastest path is to copy it, save the two JSON files (`trust-policy.json` and `dsql-read-policy.json`), then run:

```bash theme={null}
aws iam create-role \
  --role-name "DynamoSqlReadRole" \
  --assume-role-policy-document file://trust-policy.json

aws iam put-role-policy \
  --role-name "DynamoSqlReadRole" \
  --policy-name DynamoSqlReadPolicy \
  --policy-document file://dsql-read-policy.json
```

Alternatively, use the AWS Console:

1. IAM → Roles → **Create role**
2. Choose **Custom trust policy** and paste the trust policy JSON from the portal
3. Name the role exactly as entered in the schema form
4. Add an inline policy and paste the DynamoDB read policy JSON
5. Save the role

## Step 4: Save the schema and validate

Back in the portal, click **Create schema**. The portal saves the schema configuration and redirects you to the schema detail page, where it automatically attempts to assume the role and validate access.

If validation passes, the schema status shows **Active** and you're ready to query. If it fails, the portal shows a **Failed — Please Review** status. Common causes:

* Role name or account ID typo (the derived ARN won't match the role you created)
* Trust policy principal ARN does not match DynamoSQL's data plane ARN exactly
* ExternalId in the trust policy doesn't match the one generated by the portal
* IAM propagation delay — wait 10–15 seconds and re-validate from the schema detail page

## Step 5: Run a test query

Open the **SQL** tab in the portal and run a plan-mode query to confirm the role assumption succeeds without consuming DynamoDB capacity:

```sql theme={null}
SELECT * FROM myschema.orders LIMIT 10
```

Set the mode to **Plan** before running. A successful plan response confirms DynamoSQL can resolve your schema and table metadata. Switch to **Execute** to verify full read access.
