AWS Account Setup Guide
Enterprise-Grade Security Architecture
CloudWise implements a three-tier security model that follows AWS Well-Architected Framework principles and industry best practices for multi-tenant SaaS applications.
Why This Architecture?
- Defense in Depth: Multiple security layers prevent unauthorized access
- Principle of Least Privilege: Each role has minimal required permissions
- Confused Deputy Prevention: External ID prevents attack vectors
- Automatic Credential Rotation: Temporary tokens expire automatically
- Full Audit Trail: All access logged by AWS CloudTrail
Security Flow
1. Your Account Role: CloudWiseCostAccessRole - Created in your AWS account
2. CloudWise Service Role: cloudwise-customer-access-service-role - Intermediate security layer
3. Lambda Execution Role: Minimal permissions for CloudWise functions
Each role can only assume the next level - no direct access to your resources
Required Information
513158236564cloudwise-cost-access-2025CloudWiseCostAccessRoleChoose Your Setup Method
Method 1: AWS Console Setup
Step 1: Create Custom Policy for Cost Explorer
- Navigate to IAM → Policies
- Click "Create policy"
- Switch to the "JSON" tab
- Copy and paste the policy JSON below
- Name the policy "CloudWiseCostPolicy"
- Click "Create policy"
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "CostExplorerAccess",
"Effect": "Allow",
"Action": [
"ce:GetCostAndUsage",
"cur:GetUsageReport",
"ce:GetCostCategories",
"ce:GetDimensionValues",
"ce:GetReservationCoverage",
"ce:GetReservationPurchaseRecommendation",
"ce:GetReservationUtilization",
"ce:GetSavingsPlansUtilization",
"ce:GetSavingsPlansCoverage",
"ce:ListCostCategoryDefinitions",
"ce:DescribeCostCategoryDefinition",
"ce:GetRightsizingRecommendation"
],
"Resource": "*"
},
{
"Sid": "OrganizationsAccess",
"Effect": "Allow",
"Action": [
"organizations:ListAccounts",
"organizations:DescribeOrganization"
],
"Resource": "*"
},
{
"Sid": "CloudWatchMetricsAccess",
"Effect": "Allow",
"Action": [
"cloudwatch:GetMetricStatistics",
"cloudwatch:GetMetricData",
"cloudwatch:ListMetrics"
],
"Resource": "*"
},
{
"Sid": "PricingAccess",
"Effect": "Allow",
"Action": [
"pricing:GetProducts",
"pricing:DescribeServices",
"pricing:GetAttributeValues"
],
"Resource": "*"
},
{
"Sid": "WasteDetectionReadAccess",
"Effect": "Allow",
"Action": [
"ec2:DescribeInstances",
"ec2:DescribeVolumes",
"ec2:DescribeSnapshots",
"ec2:DescribeAddresses",
"ec2:DescribeNatGateways",
"ec2:DescribeVpcEndpoints",
"ec2:DescribeImages",
"rds:DescribeDBInstances",
"rds:DescribeDBClusters",
"rds:DescribeDBSnapshots",
"elasticache:DescribeCacheClusters",
"elasticache:DescribeReplicationGroups",
"lambda:ListFunctions",
"lambda:GetFunctionConfiguration",
"s3:ListAllMyBuckets",
"s3:GetBucketLifecycleConfiguration",
"s3:GetBucketTagging",
"dynamodb:ListTables",
"dynamodb:DescribeTable",
"elasticloadbalancing:DescribeLoadBalancers",
"elasticloadbalancing:DescribeTargetGroups",
"redshift:DescribeClusters",
"es:ListDomainNames",
"es:DescribeElasticsearchDomain",
"kinesis:ListStreams",
"kinesis:DescribeStream",
"sagemaker:ListEndpoints",
"sagemaker:DescribeEndpoint",
"sagemaker:ListNotebookInstances",
"efs:DescribeFileSystems",
"efs:DescribeMountTargets",
"neptune:DescribeDBClusters",
"neptune:DescribeDBInstances",
"docdb:DescribeDBClusters",
"docdb:DescribeDBInstances",
"mq:ListBrokers",
"mq:DescribeBroker",
"fsx:DescribeFileSystems",
"qldb:ListLedgers",
"qldb:DescribeLedger",
"kafka:ListClusters",
"kafka:DescribeCluster",
"ecs:ListClusters",
"ecs:DescribeClusters",
"ecs:ListServices",
"eks:ListClusters",
"eks:DescribeCluster",
"cloudfront:ListDistributions",
"secretsmanager:ListSecrets",
"kms:ListKeys",
"kms:DescribeKey",
"workspaces:DescribeWorkspaces",
"lightsail:GetInstances",
"lightsail:GetInstanceMetricData",
"lightsail:GetRelationalDatabases",
"lightsail:GetRelationalDatabaseMetricData",
"sqs:ListQueues",
"sqs:GetQueueAttributes",
"glue:GetJobs",
"glue:GetDevEndpoints",
"states:ListStateMachines",
"apigateway:GET",
"route53:ListHostedZones",
"elasticbeanstalk:DescribeEnvironments",
"ecr:DescribeRepositories",
"ecr:ListImages",
"logs:DescribeLogGroups",
"logs:DescribeLogStreams",
"backup:ListBackupVaults",
"backup:ListRecoveryPointsByBackupVault"
],
"Resource": "*"
}
]
}Step 2: Create IAM Role with Secure Trust Policy
Security Note: This role will trust CloudWise's service role, not just the account. This implements defense-in-depth security.
- Navigate to IAM > Roles in the AWS Console
- Click "Create role"
- Select Custom trust policy (not "AWS account")
- Replace the default trust policy with this secure policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::513158236564:role/cloudwise-customer-access-service-role"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "cloudwise-cost-access-2025"
}
}
}
]
}- Click "Next"
Step 3: Attach Policies
Search for and attach the following policies:
- CloudWiseCostPolicy - The custom read-only policy you created. This is the only policy CloudWise needs.
Click "Next" when all policies are selected.
Step 4: Finalize Role
- Role name: CloudWiseCostAccessRole
- Add a description: "CloudWise cost monitoring access"
- Review the configuration and click "Create role"
- Click on the newly created role
- Copy the Role ARN - you'll need this for CloudWise setup
Important Security & Configuration Notes
Security Architecture Details
- Service Role ARN:
arn:aws:iam::513158236564:role/cloudwise-customer-access-service-role - Account ID 513158236564: CloudWise production AWS account
- Role Chaining: Lambda → Service Role → Your Customer Role (three-layer security)
- External ID: Prevents confused deputy attacks with shared secret
- Temporary Credentials: All access uses 1-hour expiring tokens
Operational Considerations
- The role will appear in your IAM console after creation
- The External ID "cloudwise-cost-access-2025" is pre-configured and required for security
- You can revoke access at any time by deleting the role
- Ensure your AWS account has Cost Explorer enabled (it's enabled by default for most accounts)
- Your first scan runs within ~1 hour of connecting; cost data typically appears within 2-4 hours (for brand-new AWS Cost and Usage Report configurations, AWS itself may take up to 24 hours to deliver the first report)
- The role name "CloudWiseCostAccessRole" is recommended but can be customized
Troubleshooting Common Issues
"AccessDenied" Error
- Verify the CloudWise Account ID is exactly:
513158236564 - Ensure the External ID is exactly:
cloudwise-cost-access-2025 - Check that all three required policies are attached
"Role not found" Error
- Double-check the Role ARN is correct
- Ensure the role name is
CloudWiseCostAccessRole(case-sensitive) - Verify you're using the correct AWS account ID in the ARN
"Cost Explorer not available" Error
- Cost Explorer must be enabled in your AWS account
- Brand-new AWS accounts may need up to 24 hours for Cost Explorer data to become available (this is an AWS-side delay; CloudWise itself scans hourly)
- Verify your account has billing permissions enabled
Need Help?
AWS Documentation
CloudWise Support
If you continue experiencing issues, please contact our support team with:
- Your AWS Account ID
- The Role ARN you created
- Any error messages