What Draftt creates in your account
The CloudFormation template athttps://draftt-public.s3.amazonaws.com/draftt-onboarding-cloudformation.json is the canonical definition. It creates exactly two resources:
The role also has two AWS managed policies attached:
arn:aws:iam::aws:policy/job-function/ViewOnlyAccessarn:aws:iam::aws:policy/SecurityAudit
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.
The IAM role
Draftt assumes the role with the session namedraftt-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.
Trust policy
The trust policy controls who can assume the role. This is the exact document the CloudFormation template applies:- Principal
arn:aws:iam::339712924365:rootis 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:PrincipalArncondition restricts the caller to one specific role in the Draftt account,draftt-fetcher. No other Draftt identity can assume your role.sts:ExternalIdcondition 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-fetcherrole, but it should not be published. - The CloudFormation template accepts the External ID as a plain parameter and echoes it in the
ExternalIDstack output. Anyone withcloudformation:DescribeStacksin the account can read it. The Terraform configuration 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.AWS managed policies
AWS managed policies
ViewOnlyAccessprovidesList*,Describe*, andGet*access to metadata across most AWS services. This is the baseline for resource discovery.SecurityAuditadds 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.
DrafttReadOnlyPolicy
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.The S3 permissions cover bucket listing and bucket configuration only. Draftt does not read object contents.
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.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.
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 walks through this in the console. The moving parts are:
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, fororganizations:ListAccountsAWSCloudFormationReadOnlyAccess, to describe the StackSet and list its stack instances
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, 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 calledsts: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:
- Confirm all three policies are attached to the role:
ViewOnlyAccess,SecurityAudit, andDrafttReadOnlyPolicy. - Compare your copy of
DrafttReadOnlyPolicywith the published version. Draftt adds services over time, and a stale copy silently returns nothing for newer services. - Check for a service control policy or permissions boundary that denies read actions to the role.
AssumeRole events where the session name is draftt-fetcher. Every subsequent API call made by Draftt carries that session in its userIdentity field.