Skip to content

AWS account setup

StaleSweep connects by assuming a read-only IAM role that you create with a one-click CloudFormation deploy. No access keys are ever exchanged or stored.

Connecting a standalone AWS account

  1. In StaleSweep, go to Providers → Connect AWS account.
  2. Enter your 12-digit AWS account ID and a friendly alias (e.g. production).
  3. Click Deploy to AWS. This opens the AWS CloudFormation console with a quick-create link — the template URL and your unique External ID are pre-filled. Make sure you’re signed in to the AWS account you want to connect.
  4. Review the stack, acknowledge that CloudFormation will create IAM resources, and click Create stack.
  5. When the stack reaches CREATE_COMPLETE (usually under a minute), open its Outputs tab and copy the RoleArn value.
  6. Paste the Role ARN back into the StaleSweep wizard and click Verify & connect. StaleSweep performs a test sts:AssumeRole call to confirm the role and External ID are correct.
  7. That’s it — run your first scan from the Dashboard or Scans page.

What the template creates

A single IAM role named StaleSweepScanRole. Its trust policy allows only StaleSweep’s scanning principal to assume it, and only when it presents your account’s unique External ID:

AssumeRolePolicyDocument:
  Version: '2012-10-17'
  Statement:
    - Effect: Allow
      Principal:
        AWS: <StaleSweep scanning principal>
      Action: 'sts:AssumeRole'
      Condition:
        StringEquals:
          sts:ExternalId: <your unique External ID>

Permissions are two AWS-managed read-only policies plus a small inline policy for the metrics the usage detectors need. None of these grant write, delete, or data-read access (no s3:GetObject, no dynamodb:GetItem — inventory and metrics only):

ManagedPolicyArns:
  - arn:aws:iam::aws:policy/SecurityAudit
  - arn:aws:iam::aws:policy/job-function/ViewOnlyAccess
Policies:
  - PolicyName: StaleSweepScanRead
    PolicyDocument:
      Version: '2012-10-17'
      Statement:
        - Effect: Allow
          Action:
            - 'cloudwatch:GetMetricStatistics'
            - 'cloudwatch:GetMetricData'
            - 'cloudwatch:ListMetrics'
            - 'cloudwatch:DescribeAlarms'
            - 'ec2:DescribeNatGateways'
            - 'pricing:GetProducts'
          Resource: '*'
Tip: Turning on cost insights later adds one narrow policy to this same role: read-only access (s3:GetObject, s3:ListBucket, s3:GetBucketLocation) scoped to the single S3 bucket your Cost & Usage Report is delivered to — nothing else. It’s a separate opt-in step, not part of this base template.
Tip: Prefer not to use CloudFormation? Create the same role manually in the IAM console: custom trust policy as above, attach SecurityAudit and ViewOnlyAccess, add the inline policy, then paste the resulting ARN into the wizard. The External ID shown in the wizard must go into the trust policy’s sts:ExternalId condition exactly as displayed.

Security best practices

  • Never remove the External ID condition. It protects you against the confused-deputy problem — each StaleSweep workspace gets its own External ID.
  • Don't widen the role. The scanner needs nothing beyond the template.
  • Deleting the stack disconnects the account instantly — CloudFormation removes the role and StaleSweep can no longer assume it.
  • Review the role periodically with IAM Access Analyzer; the only external principal should be StaleSweep's scanning identity.

Connecting an AWS Organization

For multi-account environments, one deploy in your management account (or a delegated administrator account) connects the entire organization. The same template is used — setting the parameter EnableOrganizations=true does two things:

1. Adds a read-only Organizations policy to the scan role in that account, so StaleSweep can discover member accounts:

- Effect: Allow
  Action:
    - 'organizations:DescribeAccount'
    - 'organizations:DescribeOrganization'
    - 'organizations:ListAccounts'
    - 'organizations:ListAccountsForParent'
    - 'organizations:ListOrganizationalUnitsForParent'
    - 'organizations:ListRoots'
    - 'organizations:ListTagsForResource'
    - 'ec2:DescribeRegions'
  Resource: '*'

2. Activates an embedded CloudFormation StackSet that automatically rolls the plain scan role out to every member account. Member accounts get only the read-only scan role — no Organizations permissions. New accounts joining the organization receive the role automatically via StackSet auto-deployment.

Warning: Prerequisite: CloudFormation StackSets trusted access must be enabled. In the management account, go to AWS Organizations → Services → CloudFormation StackSets → Enable trusted access.
  1. In the connect wizard, choose AWS Organization mode and enter the management account ID and an alias.
  2. Click Deploy to AWS — the quick-create link opens with EnableOrganizations=true pre-set. Confirm you’re signed in to the management (or delegated-admin) account.
  3. Create the stack and wait for CREATE_COMPLETE. StackSet rollout to member accounts continues in the background and can take several minutes for large organizations.
  4. Copy the RoleArn output and paste it into StaleSweep to verify.
  5. StaleSweep discovers member accounts through the Organizations API; scans then assume the per-account role in each member.

Recommended architecture: only the management/delegated-admin account holds Organizations read permissions; member accounts hold nothing but the read-only scan role. Use a delegated administrator for StackSets if your security baseline restricts management-account workloads. Members and standalone accounts deploy the identical template with the default EnableOrganizations=false, so auditing is straightforward.