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

# AWS IAM resources

> Reference for the IAM role, trust policy, and permissions Draftt needs in your AWS accounts, and how to provision them with CloudFormation or Terraform.

This page explains what the Draftt AWS integration creates in your account, why each piece exists, and how to provision it with your own tooling. For the click-through setup flow, see [Amazon Web Services](/aws). To provision the resources with Terraform, see [Deploy with Terraform](/aws/terraform).

Draftt never stores AWS credentials. Instead, a Draftt service assumes a read-only IAM role in your account using AWS Security Token Service (STS). Everything on this page is about defining that role.

## What Draftt creates in your account

The CloudFormation template at `https://draftt-public.s3.amazonaws.com/draftt-onboarding-cloudformation.json` is the canonical definition. It creates exactly two resources:

| Resource               | Type                                    | Purpose                                                                   |
| ---------------------- | --------------------------------------- | ------------------------------------------------------------------------- |
| `DrafttAccess-Role`    | `AWS::IAM::Role`                        | The role Draftt assumes. Its trust policy restricts who can assume it.    |
| `DrafttReadOnlyPolicy` | `AWS::IAM::Policy` (inline on the role) | Additional read-only permissions not covered by the AWS managed policies. |

The role also has two AWS managed policies attached:

* `arn:aws:iam::aws:policy/job-function/ViewOnlyAccess`
* `arn:aws:iam::aws:policy/SecurityAudit`

The template takes two parameters and returns two outputs:

| Parameter        | Default             | Description                                       |
| ---------------- | ------------------- | ------------------------------------------------- |
| `DrafttRoleName` | `DrafttAccess-Role` | Name of the role to create.                       |
| `ExternalId`     | none, required      | The External ID shown in the Draftt setup dialog. |

| Output          | Value                              |
| --------------- | ---------------------------------- |
| `DrafttRoleArn` | The role ARN to paste into Draftt. |
| `ExternalID`    | The External ID you provided.      |

<Note>
  The template does not set a permissions boundary, path, tags, or a custom maximum session duration. If your organization requires any of these, use the manual or Terraform method and add them yourself. The default one-hour maximum session duration is sufficient. Draftt requests 30-minute sessions.
</Note>

## The IAM role

Draftt assumes the role with the session name `draftt-fetcher` and a 30-minute session duration. You can find these sessions in CloudTrail by filtering `AssumeRole` events for that session name. The integration health check uses a separate session name, `draftt-integration-validator`, with a 15-minute duration.

IAM is global, so the region you deploy the template in does not matter. Draftt scans all commercial AWS regions through the single role. GovCloud and China partitions are not supported.

<Warning>
  Keep the role name identical in every account you connect. For organization-wide setups, Draftt constructs each member account's role ARN as `arn:aws:iam::<account-id>:role/<DrafttRoleName>` from the single role name you provide. An account with a different role name will fail to connect.
</Warning>

## Trust policy

The trust policy controls who can assume the role. This is the exact document the CloudFormation template applies:

```json theme={null}
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::339712924365:root"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "aws:PrincipalArn": "arn:aws:iam::339712924365:role/draftt-fetcher",
          "sts:ExternalId": "<provided-in-draftt>"
        }
      }
    }
  ]
}
```

Each part narrows access further:

* **Principal `arn:aws:iam::339712924365:root`** is Draftt's production AWS account. Using the account root as the principal, rather than a role ARN, keeps the trust relationship stable even if Draftt recreates the role on its side. The root principal alone would allow any identity in the Draftt account, so the two conditions below restrict it.
* **`aws:PrincipalArn` condition** restricts the caller to one specific role in the Draftt account, `draftt-fetcher`. No other Draftt identity can assume your role.
* **`sts:ExternalId` condition** requires the caller to present your External ID. This is the standard AWS defense against the confused deputy problem, where a third party could trick Draftt into accessing your account on their behalf.

## External ID

Draftt generates the External ID for your Draftt organization and shows it in the setup dialog under **Integrations > AWS**. You do not choose it.

* The External ID is per Draftt organization, not per AWS account. Use the same value in every account you connect.
* Treat it like a shared secret. It is not sufficient on its own to access your account, because the caller must also be the `draftt-fetcher` role, but it should not be published.
* The CloudFormation template accepts the External ID as a plain parameter and echoes it in the `ExternalID` stack output. Anyone with `cloudformation:DescribeStacks` in the account can read it. The [Terraform configuration](/aws/terraform) marks it as sensitive instead.

## Permissions

The role's permissions come from three policies. All of them are read-only. None grant the ability to create, modify, or delete resources.

<AccordionGroup>
  <Accordion title="AWS managed policies">
    * **`ViewOnlyAccess`** provides `List*`, `Describe*`, and `Get*` access to metadata across most AWS services. This is the baseline for resource discovery.
    * **`SecurityAudit`** adds read access to security configuration, including IAM users, roles, access keys, policies, Secrets Manager metadata, CloudTrail, and Config. Draftt uses this for IAM and secrets inventory.
  </Accordion>

  <Accordion title="DrafttReadOnlyPolicy">
    The custom policy fills the gaps in the managed policies: cost and billing data, Compute Optimizer and Trusted Advisor recommendations, AWS Health events, container image metadata, and newer services such as Bedrock. It contains 45 statements, all `Allow` on `Resource: "*"`.

    The policy is published at `https://draftt-public.s3.amazonaws.com/DrafttReadOnlyPolicy.js`. Despite the file extension, it is a plain IAM policy JSON document and is identical to the policy embedded in the CloudFormation template.

    | Service                     | Actions                                                                                                                                                                                                      |
    | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
    | ACM                         | `acm:Describe*`, `acm:List*`                                                                                                                                                                                 |
    | Airflow (MWAA)              | `airflow:Get*`, `airflow:List*`                                                                                                                                                                              |
    | Bedrock                     | `bedrock:List*`, `bedrock:Get*`                                                                                                                                                                              |
    | Billing and Cost Management | `billing:ListBillingViews`, `billing:GetBillingView*`, `ce:Get*`, `ce:List*`, `budgets:ViewBudget`, `budgets:ListTagsForResource`                                                                            |
    | CodeBuild                   | `codebuild:BatchGet*`, `codebuild:List*`, `codebuild:Describe*`                                                                                                                                              |
    | Compute Optimizer           | `compute-optimizer:Describe*`, `compute-optimizer:Get*`, `compute-optimizer:Export*`                                                                                                                         |
    | DMS Fleet Advisor           | `dms:DescribeFleetAdvisor*`, `dms:GetFleetAdvisor*`, `dms:ListFleetAdvisor*`                                                                                                                                 |
    | DynamoDB                    | `dynamodb:Describe*`, `dynamodb:List*`                                                                                                                                                                       |
    | EC2                         | `ec2:Describe*`, `ec2:Get*`, `ec2:Search*`                                                                                                                                                                   |
    | ECR                         | `ecr:Get*`, `ecr:List*`, `ecr:Describe*`, `ecr:BatchGetImage`, `ecr:RegisterPullTimeUpdateExclusion`, `ecr:DeregisterPullTimeUpdateExclusion`, `ecr-public:Get*`, `ecr-public:List*`, `ecr-public:Describe*` |
    | ECS                         | `ecs:List*`, `ecs:Describe*`                                                                                                                                                                                 |
    | EKS                         | `eks:List*`, `eks:Describe*`                                                                                                                                                                                 |
    | ElastiCache                 | `elasticache:Describe*`, `elasticache:List*`                                                                                                                                                                 |
    | Elastic Load Balancing      | `elasticloadbalancing:Describe*`                                                                                                                                                                             |
    | EMR                         | `elasticmapreduce:Describe*`, `elasticmapreduce:Get*`, `elasticmapreduce:List*`                                                                                                                              |
    | EventBridge                 | `events:List*`, `events:Describe*`                                                                                                                                                                           |
    | FinSpace                    | `finspace:Describe*`, `finspace:List*`                                                                                                                                                                       |
    | Glue                        | `glue:Get*`, `glue:List*`, `glue:BatchGet*`                                                                                                                                                                  |
    | Health                      | `health:Describe*`                                                                                                                                                                                           |
    | Kinesis                     | `kinesis:Describe*`, `kinesis:Get*`, `kinesis:List*`                                                                                                                                                         |
    | Kinesis Data Analytics      | `kinesisanalytics:Describe*`, `kinesisanalytics:List*`                                                                                                                                                       |
    | Kinesis Video Streams       | `kinesisvideo:Describe*`, `kinesisvideo:Get*`, `kinesisvideo:List*`                                                                                                                                          |
    | KMS                         | `kms:Describe*`, `kms:List*`                                                                                                                                                                                 |
    | Lambda                      | `lambda:Get*`, `lambda:List*`                                                                                                                                                                                |
    | Lightsail                   | `lightsail:Get*`, `lightsail:List*`                                                                                                                                                                          |
    | MemoryDB                    | `memorydb:Describe*`, `memorydb:List*`                                                                                                                                                                       |
    | MQ                          | `mq:Describe*`, `mq:List*`                                                                                                                                                                                   |
    | MSK                         | `kafka:Describe*`, `kafka:Get*`, `kafka:List*`                                                                                                                                                               |
    | Neptune                     | `neptune-db:Get*`, `neptune-db:List*`                                                                                                                                                                        |
    | OpenSearch                  | `es:Describe*`, `es:Get*`, `es:List*`                                                                                                                                                                        |
    | Organizations               | `organizations:ListAccounts` (optional, used to resolve account names)                                                                                                                                       |
    | ParallelCluster             | `parallelcluster:Describe*`, `parallelcluster:List*`                                                                                                                                                         |
    | RDS                         | `rds:Describe*`, `rds:List*`                                                                                                                                                                                 |
    | Redshift                    | `redshift:Describe*`                                                                                                                                                                                         |
    | Resource Groups Tagging     | `tag:Get*`, `tag:Describe*`                                                                                                                                                                                  |
    | ROSA                        | `ros:Get*`, `ros:List*`                                                                                                                                                                                      |
    | Route 53                    | `route53:Get*`, `route53:List*`                                                                                                                                                                              |
    | S3                          | `s3:ListAllMyBuckets`, `s3:ListBucket*`, `s3:GetBucket*`, and bucket configuration reads (replication, acceleration, encryption, lifecycle, analytics, inventory, metrics, intelligent tiering)              |
    | Service Catalog             | `servicecatalog:Describe*`, `servicecatalog:List*`                                                                                                                                                           |
    | SES                         | `ses:Describe*`, `ses:Get*`, `ses:List*`                                                                                                                                                                     |
    | SNS                         | `sns:Get*`, `sns:List*`                                                                                                                                                                                      |
    | SQS                         | `sqs:Get*`, `sqs:List*`                                                                                                                                                                                      |
    | SSM                         | `ssm:Describe*`, `ssm:Get*`, `ssm:List*`                                                                                                                                                                     |
    | Trusted Advisor             | `trustedadvisor:Describe*`, `trustedadvisor:List*`                                                                                                                                                           |

    The S3 permissions cover bucket listing and bucket configuration only. Draftt does not read object contents.

    <Note>
      Two ECR actions, `ecr:RegisterPullTimeUpdateExclusion` and `ecr:DeregisterPullTimeUpdateExclusion`, are not `Describe`, `List`, or `Get` calls. They exclude Draftt's own image reads from the ECR "last pull time" statistic, so Draftt's scans do not make unused images appear active. They do not modify images or repositories.
    </Note>

    <Note>
      When you create this policy manually as a customer managed policy, the IAM console asks you to **Optimize for size**. Customer managed policies are limited to 6,144 characters excluding whitespace, and this policy is close to that limit. The CloudFormation template avoids the issue by attaching the policy inline, where the limit is 10,240 characters.
    </Note>
  </Accordion>
</AccordionGroup>

## Single account vs. AWS Organization

For a single account, the role and policies above are everything Draftt needs.

For an AWS Organization, Draftt needs one additional role in the management account plus the standard role in every member account. The [StackSet setup](/aws) walks through this in the console. The moving parts are:

| Resource                                 | Where                | Purpose                                                                        |
| ---------------------------------------- | -------------------- | ------------------------------------------------------------------------------ |
| `DrafttReadOnlyAccess-OrganizationLevel` | Management account   | Lets Draftt list member accounts and read the StackSet rollout status.         |
| CloudFormation StackSet                  | Management account   | Deploys `DrafttAccess-Role` into every member account using the same template. |
| `DrafttAccess-Role`                      | Every member account | The standard read-only role, created by the StackSet.                          |

The organization-level role uses the same trust policy and the same External ID as the member account roles. It has two AWS managed policies attached and nothing else:

* `AWSOrganizationsReadOnlyAccess`, for `organizations:ListAccounts`
* `AWSCloudFormationReadOnlyAccess`, to describe the StackSet and list its stack instances

When you provide the StackSet ARN, Draftt reads the region from the ARN and queries CloudFormation in that region. Draftt then waits up to 30 minutes for stack instances to finish deploying, and creates an integration for each account whose instance reached `SUCCEEDED`. Accounts that failed or were skipped are not connected. Check the StackSet's stack instances in the console if an account is missing.

## Provision with Terraform

An optional Terraform configuration is available at [Deploy with Terraform](/aws/terraform), with options for a single account, a Terraform-managed CloudFormation stack, and a multi-account StackSet.

## Verifying and auditing

The **Healthy** status in **Integrations > AWS** means Draftt successfully called `sts:AssumeRole` on your role with the External ID. It confirms the trust policy, not the permissions. A role with a correct trust policy but missing permission policies shows as Healthy while returning an empty or partial inventory.

If the inventory is incomplete:

1. Confirm all three policies are attached to the role: `ViewOnlyAccess`, `SecurityAudit`, and `DrafttReadOnlyPolicy`.
2. Compare your copy of `DrafttReadOnlyPolicy` with the published version. Draftt adds services over time, and a stale copy silently returns nothing for newer services.
3. Check for a service control policy or permissions boundary that denies read actions to the role.

To audit Draftt's activity, search CloudTrail for `AssumeRole` events where the session name is `draftt-fetcher`. Every subsequent API call made by Draftt carries that session in its `userIdentity` field.
