AWS Connection
Connect an AWS account to Escher by registering a local AWS CLI profile with the required read-only IAM permissions.
Prerequisites
- AWS CLI v2 installed (
aws --version) - An AWS account with permission to create IAM policies and users/roles
- Escher desktop app installed and running
How Escher reads AWS
Escher does not create new AWS connections. It reads credentials from your local AWS CLI configuration (~/.aws/credentials and ~/.aws/config) and uses them to make read-only API calls during estate scans.
Escher never:
- Creates, modifies, or deletes AWS resources during a scan
- Stores your AWS credentials outside your local machine
- Transmits raw estate data to Escher's servers
Step 1 — Create the IAM policy
Attach this read-only policy to the IAM user or role that Escher will use:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "EscherEstateReadOnly",
"Effect": "Allow",
"Action": [
"ec2:Describe*",
"ec2:Get*",
"ec2:List*",
"s3:ListAllMyBuckets",
"s3:GetBucketLocation",
"s3:GetBucketAcl",
"s3:GetBucketPolicy",
"s3:GetBucketPolicyStatus",
"s3:GetBucketPublicAccessBlock",
"s3:GetEncryptionConfiguration",
"iam:GenerateCredentialReport",
"iam:Get*",
"iam:List*",
"rds:Describe*",
"rds:ListTagsForResource",
"lambda:ListFunctions",
"lambda:GetFunctionConfiguration",
"lambda:ListTags",
"cloudtrail:DescribeTrails",
"cloudtrail:GetTrailStatus",
"cloudtrail:LookupEvents",
"cloudwatch:DescribeAlarms",
"cloudwatch:GetMetricStatistics",
"logs:DescribeLogGroups",
"logs:DescribeLogStreams",
"logs:FilterLogEvents",
"logs:GetLogEvents",
"ce:GetCostAndUsage",
"ce:GetCostForecast",
"ce:GetDimensionValues",
"ce:GetReservationUtilization",
"ce:GetSavingsPlansCoverage",
"sts:GetCallerIdentity",
"organizations:ListAccounts",
"organizations:DescribeOrganization",
"config:DescribeConfigRules",
"config:GetComplianceDetailsByConfigRule",
"securityhub:GetFindings",
"guardduty:ListDetectors",
"guardduty:GetFindings"
],
"Resource": "*"
}
]
}TIP
If you only need a subset of Escher's verticals (e.g. FinOps only), you can restrict to the relevant ce:*, ec2:Describe*, and s3:List* actions. The full policy above enables all skill verticals.
Create the policy via CLI:
aws iam create-policy \
--policy-name EscherReadOnly \
--policy-document file://escher-readonly-policy.json
# Expected output:
# {
# "Policy": {
# "PolicyName": "EscherReadOnly",
# "PolicyId": "ANPAXXXXXXXXXXXXXXXXX",
# "Arn": "arn:aws:iam::123456789012:policy/EscherReadOnly",
# ...
# }
# }Step 2 — Create or configure the IAM principal
Option A — Dedicated IAM user (for local machine access)
# Create the user
aws iam create-user --user-name escher-readonly
# Attach the policy
aws iam attach-user-policy \
--user-name escher-readonly \
--policy-arn arn:aws:iam::123456789012:policy/EscherReadOnly
# Create access keys
aws iam create-access-key --user-name escher-readonly
# Expected:
# {
# "AccessKey": {
# "AccessKeyId": "AKIAXXXXXXXXXXXXXXXXX",
# "SecretAccessKey": "xxxx...",
# ...
# }
# }Option B — IAM role with profile (for cross-account or SSO)
If using AWS SSO or an assume-role pattern, configure a named profile in ~/.aws/config:
[profile escher-prod]
role_arn = arn:aws:iam::123456789012:role/EscherReadOnly
source_profile = default
region = us-east-1Step 3 — Configure the AWS CLI profile
aws configure --profile escher-prod
# AWS Access Key ID: AKIAXXXXXXXXXXXXXXXXX
# AWS Secret Access Key: xxxx...
# Default region name: us-east-1
# Default output format: jsonVerify the profile works:
aws sts get-caller-identity --profile escher-prod
# Expected:
# {
# "UserId": "AIDAXXXXXXXXXXXXXXXXX",
# "Account": "123456789012",
# "Arn": "arn:aws:iam::123456789012:user/escher-readonly"
# }Step 4 — Register the profile in Escher
- Open Escher → Estate in the left nav
- Click Discover Profiles
escher-prodappears in the profile list with statusDiscovered- Click Enable on the profile
- Click Test Access
Profile: escher-prod
Provider: AWS
Account: 123456789012
Status: ✓ Connected
Permissions: Sufficient for estate scan- Click Refresh Estate to run the first scan
Step 5 — Verify scan coverage
After the scan completes, check coverage in Estate → Overview:
escher-prod (AWS 123456789012)
EC2 Instances: OK (48 resources)
S3 Buckets: OK (22 resources)
IAM: OK (142 users, 38 roles)
RDS: OK (6 instances)
Lambda: OK (31 functions)
Cost Explorer: OK (billing data available)
CloudTrail: OK (3 trails found)If any domain shows PARTIAL or ERROR, the permissions for that service are missing. Add the relevant actions from the policy above.
Troubleshooting
An error occurred (AccessDenied) during scan
A specific API call is not covered by the IAM policy. Check the CloudTrail event for the denied call and add the corresponding action.
aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=EventName,AttributeValue=DescribeInstances \
--profile escher-prodProfile status shows PARTIAL
One or more service domains could not be fully scanned. This is non-fatal — Escher marks the EstateView as partial and continues. Check Estate → Profile Diagnostics for the specific errors.
Unable to locate credentials
The profile is not found in ~/.aws/credentials or ~/.aws/config. Run aws configure --profile escher-prod again and verify ~/.aws/credentials contains the [escher-prod] section.
Cost data not available
ce:* (Cost Explorer) requires that the account has Cost Explorer enabled. Enable it at: AWS Console → Billing → Cost Explorer → Enable Cost Explorer.
Next steps
- Azure Connection — Connect Azure subscriptions
- Profiles — Manage multiple profiles and environments
- FinOps — Run your first cost analysis
- IAM — Audit IAM configurations with the connected account