AWS Provider
Deep dive into scanning AWS resources with Cloud Cost Analyzer.
Supported Services
CCA analyzes the following AWS services:
| Service | Resource Types | Optimization Rules |
|---|---|---|
| EC2 | Instances, Reserved Instances | Rightsizing, idle detection, RI coverage |
| EBS | Volumes, Snapshots | Unattached volumes, old snapshots, GP2 to GP3 |
| RDS | Instances, Aurora clusters | Rightsizing, idle, RI coverage, storage |
| S3 | Buckets | Lifecycle policies, storage class optimization |
| Lambda | Functions | Memory optimization, unused functions |
| ELB | ALB, NLB, Classic | Idle load balancers, cross-AZ traffic |
| ElastiCache | Clusters | Node sizing, RI coverage |
| NAT Gateway | Gateways | Idle gateways, excessive data transfer |
| ECS/EKS | Clusters, Services | Rightsizing, Fargate Spot opportunities |
Authentication
CCA uses the standard AWS credential chain:
- Environment variables (
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY) - Shared credentials file (
~/.aws/credentials) - IAM role (EC2, ECS, Lambda)
- AWS SSO / IAM Identity Center
Environment Variables
export AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
export AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
export AWS_REGION=us-east-1
cca scan --provider aws
Named Profiles
CCA uses the standard AWS credential chain: select a profile with the AWS_PROFILE environment variable (there is no --profile flag):
# For a single command
AWS_PROFILE=production cca scan --provider aws
# Or export it for the session
export AWS_PROFILE=production
cca scan --provider aws
IAM Role (EC2/ECS/Lambda)
No configuration needed. CCA automatically retrieves credentials from the instance metadata service.
AWS SSO
# Login via SSO
aws sso login --profile my-sso-profile
# Run scan with the SSO profile
AWS_PROFILE=my-sso-profile cca scan --provider aws
Assume Role
# Assume a role first
aws sts assume-role \
--role-arn arn:aws:iam::123456789012:role/CostAnalyzerRole \
--role-session-name cca-scan
# Or use a profile with role_arn configured
# ~/.aws/config
[profile cross-account]
role_arn = arn:aws:iam::123456789012:role/CostAnalyzerRole
source_profile = default
AWS_PROFILE=cross-account cca scan --provider aws
Provisioning access
cca setup --provider aws provisions the read-only access a scan needs. Who runs
it depends on your environment.
Self-service (you have cloud-admin rights)
cca setup --provider aws --output-template # preview the exact read-only policy (changes nothing)
cca setup --provider aws --deploy # create the role + policy via CloudFormation
--deploy requires permission to deploy CloudFormation and create IAM resources
(iam:CreateRole, iam:CreatePolicy, iam:AttachRolePolicy, and the
CAPABILITY_NAMED_IAM acknowledgement). It uses your current AWS session, so
authenticate first (corporate accounts are usually SSO), and select the profile
via AWS_PROFILE (there is no --profile flag):
aws sso login --profile my-profile
AWS_PROFILE=my-profile cca setup --provider aws --deploy
--deploy always targets --region (default us-east-1), which overrides the
profile's region; pass --region to place the stack elsewhere. Re-running is
safe: CloudFormation applies only the diff (idempotent).
Restricted (you cannot create IAM roles)
Most enterprises lock this down. Do not fight --deploy; hand off the policy
instead:
cca setup --provider aws --output-template -f cca-role.yaml
Give cca-role.yaml to your cloud/platform team (a ticket, or a PR into their
Terraform/CloudFormation repo). They deploy it once; you then consume the result:
- read-only credentials, or
- an assumable role ARN (add it to
~/.aws/config, see Assume Role), or - OIDC federation for CI, with no long-lived secrets (see the GitHub Actions guide).
For many accounts at once, provision the role across the org with CloudFormation StackSets (see Multi-Account Scanning).
Required IAM Permissions
CCA requires read-only access to analyze resources. Here's a minimal IAM policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "CCAReadAccess",
"Effect": "Allow",
"Action": [
"ec2:Describe*",
"rds:Describe*",
"rds:ListTagsForResource",
"s3:GetBucketLocation",
"s3:GetBucketTagging",
"s3:GetLifecycleConfiguration",
"s3:GetBucketVersioning",
"s3:ListAllMyBuckets",
"elasticloadbalancing:Describe*",
"lambda:List*",
"lambda:GetFunction",
"lambda:GetFunctionConfiguration",
"elasticache:Describe*",
"ecs:Describe*",
"ecs:List*",
"eks:Describe*",
"eks:List*",
"cloudwatch:GetMetricStatistics",
"cloudwatch:ListMetrics",
"ce:GetCostAndUsage",
"ce:GetReservationUtilization",
"ce:GetSavingsPlansCoverage",
"pricing:GetProducts",
"organizations:DescribeOrganization",
"tag:GetResources"
],
"Resource": "*"
}
]
}
CloudFormation Template
Deploy the IAM role via CloudFormation:
AWSTemplateFormatVersion: '2010-09-09'
Description: IAM role for Cloud Cost Analyzer
Resources:
CCARole:
Type: AWS::IAM::Role
Properties:
RoleName: CloudCostAnalyzerRole
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
AWS: !Sub 'arn:aws:iam::${AWS::AccountId}:root'
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/ReadOnlyAccess
Policies:
- PolicyName: CostExplorerAccess
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- ce:GetCostAndUsage
- ce:GetReservationUtilization
- ce:GetSavingsPlansCoverage
- pricing:GetProducts
Resource: '*'
Outputs:
RoleArn:
Value: !GetAtt CCARole.Arn
Description: ARN of the CCA role
Scanning Options
Region Selection
# Scan the default region (us-east-1)
cca scan --provider aws
# Scan a specific region
cca scan --provider aws --regions us-west-2
# Scan multiple regions (comma-separated)
cca scan --provider aws --regions us-east-1,us-west-2,eu-west-1
Filtering
# Limit to specific service categories (comma-separated):
# compute, storage, database, networking, serverless, analytics,
# containers, ai, security, monitoring, cdn, other
cca scan --provider aws --services compute,storage,database
# Filter resources by tag
# Combine filters
To filter findings by severity, re-render a saved dump with cca report --severity ….
AWS-Specific Rules
EC2 Rightsizing
Identifies instances with low CPU/memory utilization:
Rule ID: ec2-rightsizing
Severity: High
Triggers when:
- Average CPU < 10% over 14 days
- Or max CPU < 40% over 14 days
Example finding:
{
"rule_id": "ec2-rightsizing",
"resource_id": "i-0abc123def456",
"title": "Instance oversized",
"recommendation": "Consider downsizing from m5.2xlarge to m5.large",
"estimated_monthly_savings": 210.00,
"metadata": {
"current_type": "m5.2xlarge",
"recommended_type": "m5.large",
"avg_cpu_percent": 8.5,
"max_cpu_percent": 25.0
}
}
EBS Optimization
Unattached Volumes:
Rule ID: ebs-unattached
Triggers when: Volume has no attachment for 7+ days
GP2 to GP3 Migration:
Rule ID: ebs-gp2-to-gp3
Triggers when: Volume is GP2 type
Note: GP3 is 20% cheaper than GP2 for most workloads
Old Snapshots:
Rule ID: ebs-old-snapshots
Triggers when: Snapshot is older than 90 days with no recent access
RDS Optimization
Idle Instances:
Rule ID: rds-idle
Triggers when: Zero connections for 7+ days
Storage Over-provisioned:
Rule ID: rds-storage-overprovisioned
Triggers when: Storage utilization < 20% for 30+ days
S3 Optimization
Missing Lifecycle Policies:
Rule ID: s3-no-lifecycle
Triggers when: Bucket has no lifecycle rules configured
Intelligent Tiering:
Rule ID: s3-intelligent-tiering
Triggers when: Bucket has mixed access patterns
Reserved Instance Coverage
Rule ID: ec2-reserved-opportunity
Triggers when:
- Instance running 24/7 for 30+ days
- No RI coverage for this instance type
- Estimated savings > $50/month
Multi-Account Scanning
AWS Organizations
Scan all accounts in an organization:
# List all accounts
aws organizations list-accounts --query 'Accounts[*].Id' --output text
# Create a role in each account (use StackSets)
# Then scan each account
for account_id in 111111111111 222222222222 333333333333; do
AWS_PROFILE="account-${account_id}" cca scan \
--provider aws \
--mode managed
done
Cross-Account Role
Configure cross-account access in ~/.aws/config:
[profile account-111111111111]
role_arn = arn:aws:iam::111111111111:role/CCARole
source_profile = default
[profile account-222222222222]
role_arn = arn:aws:iam::222222222222:role/CCARole
source_profile = default
Troubleshooting
First: run cca doctor
Before digging in, run the preflight check: it verifies credentials, IAM permissions, and connectivity in one pass and reports exactly what's wrong:
cca doctor --provider aws
If a scan ran but isn't showing up in the dashboard, doctor surfaces the likely cause (invalid API key, expired credentials, a missing read permission, or an unreachable service URL).
"Access Denied" Errors
Check that the IAM policy includes all required permissions:
# Test permissions
aws ec2 describe-instances --dry-run
aws rds describe-db-instances
aws s3 ls
"Region not enabled"
Some regions require opt-in. Enable them in the AWS Console:
# List enabled regions
aws ec2 describe-regions --query 'Regions[*].RegionName'
Slow Scans
For large accounts, scan regions in parallel:
# Using xargs
echo "us-east-1 us-west-2 eu-west-1" | xargs -n1 -P3 -I{} \
cca scan --provider aws --regions {}
Cost Explorer Data Unavailable
Cost Explorer must be enabled in the AWS Console:
- Go to AWS Cost Management > Cost Explorer
- Click Enable Cost Explorer
- Wait 24 hours for data to populate
cca setup --deploy fails to create the role
--deploy needs rights to deploy CloudFormation and create IAM resources
(CAPABILITY_NAMED_IAM). An AccessDenied on iam:CreateRole or CloudFormation
means you lack provisioning rights, use the hand-off path in
Provisioning access. If the session is expired, run
aws sso login (or aws configure) first.
Next Steps
- Azure Provider - Scan Azure resources
- CLI Commands - Full CLI reference
- CI/CD Integration - Automate scans