Connect a cloud · AWS

AWS setup — IAM role + External ID.

Axiom connects to your AWS account by assuming a read-only IAM role. You create the role; Axiom never sees access keys, never stores credentials, and only ever has the permissions you explicitly grant.

The model: assume-role, read-only, External-ID-bound

Axiom runs in our AWS account and assumes a role in your AWS account. The role's trust policy requires a unique External ID we generate per connection — preventing confused-deputy attacks. The role's permission policy contains only Describe, Get, and List actions. No write, no delete, no modify.

00 · Overview

How the connection works

The full handshake when Axiom assumes the role:

  • You create a role in your account with our trust policy (Axiom AWS account + your External ID)
  • You attach the read-only permission policy (below)
  • You paste the Role ARN into Axiom
  • Axiom calls sts:AssumeRole with the External ID — only succeeds if both match
  • Axiom receives temporary credentials valid for 1 hour, used only for the scan
  • When credentials expire, they are discarded — never persisted

01

Option 1 — One-click CloudFormation (recommended)

1

From the Axiom onboarding wizard

On the AWS step, click Launch with CloudFormation. This opens the AWS Console pre-filled with our stack template.

2

Review the stack — accept the IAM acknowledgment

The stack creates exactly one IAM role with the trust policy and the read-only permission policy. The template is published — you can review it before deploying.

3

Copy the Role ARN output back to Axiom

After the stack creates (~30 seconds), copy the AxiomAgentRoleArn output and paste it into the Axiom onboarding wizard. Hit Test connection.

02

Option 2 — Manual IAM role creation

If your organization disallows CloudFormation auto-deploys, create the role manually:

1

Open AWS IAM Console → Roles → Create role

Choose Custom trust policy and paste:

trust policy{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": { "AWS": "arn:aws:iam::AXIOM_ACCOUNT_ID:root" },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "sts:ExternalId": "YOUR_EXTERNAL_ID_HERE"
        }
      }
    }
  ]
}

Replace AXIOM_ACCOUNT_ID and YOUR_EXTERNAL_ID_HERE with the values shown in the Axiom onboarding screen.

2

Attach the permission policy

Create an inline policy on the role:

permission policy{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AxiomReadOnlyOps",
      "Effect": "Allow",
      "Action": [
        "ec2:Describe*",
        "s3:GetBucket*",
        "s3:ListBucket",
        "s3:ListAllMyBuckets",
        "rds:Describe*",
        "rds:ListTagsForResource",
        "iam:Get*",
        "iam:List*",
        "iam:Simulate*",
        "cloudwatch:Get*",
        "cloudwatch:List*",
        "cloudwatch:Describe*",
        "logs:Describe*",
        "logs:Get*",
        "logs:List*",
        "ce:Get*",
        "ce:List*",
        "sts:GetCallerIdentity",
        "tag:GetResources"
      ],
      "Resource": "*"
    }
  ]
}
3

Name and create

Suggested role name: axiom-agent-role. Maximum session duration: 1 hour is sufficient.

4

Copy the Role ARN and paste into Axiom

From the role's summary page in IAM, copy the ARN (looks like arn:aws:iam::123456789012:role/axiom-agent-role) and paste into Axiom. Test the connection.

03 · Why each line

What each permission does

Every action in the policy maps to a specific Axiom capability. Nothing is requested speculatively.

  • ec2:Describe*

    Enumerate EC2 instances, volumes, security groups, VPCs, NAT gateways, ELBs for inventory + rightsizing.

  • s3:GetBucket* / ListBucket

    Detect public buckets, encryption settings, lifecycle rules, versioning posture. We never read object contents.

  • rds:Describe* / ListTagsForResource

    Inventory RDS instances and clusters; identify oversized DBs, missing backups, unencrypted instances.

  • iam:Get* / List* / Simulate*

    Audit IAM roles, policies, and trust relationships for over-permissive grants. Simulate is read-only policy analysis.

  • cloudwatch:Get* / List* / Describe*

    Pull utilization metrics for rightsizing recommendations.

  • logs:Describe* / Get* / List*

    Detect missing or stale log groups, retention misconfigurations.

  • ce:Get* / List*

    Cost Explorer signals — used to validate that cost optimizations land in your actual bill.

  • sts:GetCallerIdentity

    Confirms successful role assumption during the connection test.

  • tag:GetResources

    Aggregate cross-service tag inventory for ownership graphs.

04 · Hard guarantees

What Axiom cannot do with this role

  • Create, modify, or delete any resource
  • Read object content in S3 buckets (only metadata — encryption, ACL, lifecycle)
  • Read database row contents in RDS (only configuration metadata)
  • Decrypt secrets in Secrets Manager or KMS
  • Modify IAM policies, users, roles, or permission boundaries
  • Launch, stop, or modify EC2 instances
  • Access CloudTrail data history (only configuration)

For execution flows (Agent tier and above), Axiom uses a separate, more-scoped role that you create per-action — never the read-only scan role. See permissions model (doc coming).

05 · Self-serve trust

Trust questions

Why External ID?

Prevents confused-deputy: another Axiom customer cannot trick our service into assuming your role. Each connection gets a unique External ID; nobody can guess it.

What if I lose the External ID?

It's stored on the Axiom side per connection. Rotate by deleting the connection and re-onboarding — the trust policy updates with a new ID.

Does Axiom store my Role ARN?

Yes, encrypted at rest. It's needed to assume the role each scan. The ARN by itself grants nothing — assumption requires our AWS account + your External ID.

Can I limit which regions Axiom sees?

Yes. The onboarding wizard lets you select regions. You can also add an explicit Condition block on the trust policy to limit by AWS Region.

What if my org requires SCPs?

Service Control Policies are fully compatible. The role inherits SCP constraints automatically. If an SCP blocks a Describe action, that resource simply won't appear in scans.

How do I revoke?

Delete the IAM role in your AWS console. Axiom immediately loses all access on the next assume attempt. Connection state in Axiom dashboard flips to 'disconnected' within seconds.

06 · Troubleshooting

Common errors during AWS setup

  • AccessDenied (sts:AssumeRole)

    Trust policy is missing or has wrong Axiom account ID. Recopy the trust policy from the onboarding screen.

  • InvalidExternalId

    External ID in the trust policy condition doesn't match what Axiom sent. Re-paste from the onboarding screen exactly.

  • MalformedPolicyDocumentException

    JSON syntax error in the trust or permission policy. Use AWS Console's built-in validator before saving.

  • Empty scan result

    Either the role has no permission to describe resources, or no resources exist in the selected regions. Verify with sts:GetCallerIdentity in CloudShell.

See the full troubleshooting guide for additional scenarios.

Need a human?

Most flows are documented — but we'll help if anything is unclear.

Talk to Vision XIX Labs