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
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:AssumeRolewith 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)
From the Axiom onboarding wizard
On the AWS step, click Launch with CloudFormation. This opens the AWS Console pre-filled with our stack template.
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.
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:
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.
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": "*"
}
]
}Name and create
Suggested role name: axiom-agent-role. Maximum session duration: 1 hour is sufficient.
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.