aws-iam-cost-explorer-cli
AWS IAM AND COST EXPLORER CLI SETUP.
The old version of this note created a permanent IAM admin user and granted a
wide Cost Explorer policy. That is more access than this job needs.
This version keeps the browser out of the way as much as possible:
- start from an existing administrator-capable CLI profile
- create one dedicated CLI user with no console password
- attach only the permissions needed for the commands below
- keep Cost Explorer on `us-east-1`, where the API lives
If you can use temporary credentials via IAM Identity Center or a role, do
that. AWS recommends temporary credentials over long-lived IAM user access
keys. If you still need a simple CLI-only teaching setup, the user below is the
smallest durable pattern that gets the job done.
One console-only prerequisite remains: Cost Explorer has to be enabled in the
Billing and Cost Management console first. AWS does not let you enable it via
the API.
[ assumptions ]
---------------
```sh
export BOOTSTRAP_PROFILE="bootstrap-admin"
export TARGET_USER="cost-reader"
export COST_REGION="us-east-1"
```
[ minimal cost explorer policy ]
--------------------------------
This is enough for the basic current-cost command.
```sh
cat > cost-explorer-min.json <<'EOF'
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ce:GetCostAndUsage"
],
"Resource": "*"
}
]
}
EOF
```
[ optional query helpers ]
--------------------------
Add these only if you want Cost Explorer filters, tag lookups, or forecasts.
```sh
cat > cost-explorer-extra.json <<'EOF'
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ce:GetCostForecast",
"ce:GetDimensionValues",
"ce:GetTags"
],
"Resource": "*"
}
]
}
EOF
```
[ optional ec2 inventory policy ]
---------------------------------
Add this only if you also want the EC2 inventory helper at the end.
```sh
cat > ec2-inventory-readonly.json <<'EOF'
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:DescribeImages",
"ec2:DescribeInstances",
"ec2:DescribeSnapshots",
"ec2:DescribeVolumes"
],
"Resource": "*"
}
]
}
EOF
```
[ create the cli user ]
-----------------------
No console password. No IAM admin permissions. No group needed for a single
user.
```sh
AWS_PROFILE="${BOOTSTRAP_PROFILE}" aws iam create-user \
--user-name "${TARGET_USER}"
AWS_PROFILE="${BOOTSTRAP_PROFILE}" aws iam put-user-policy \
--user-name "${TARGET_USER}" \
--policy-name cost-explorer-min \
--policy-document file://cost-explorer-min.json
```
Only attach the next policies if you plan to use those features.
```sh
AWS_PROFILE="${BOOTSTRAP_PROFILE}" aws iam put-user-policy \
--user-name "${TARGET_USER}" \
--policy-name cost-explorer-extra \
--policy-document file://cost-explorer-extra.json
AWS_PROFILE="${BOOTSTRAP_PROFILE}" aws iam put-user-policy \
--user-name "${TARGET_USER}" \
--policy-name ec2-inventory-readonly \
--policy-document file://ec2-inventory-readonly.json
```
[ create and store the access key ]
-----------------------------------
AWS only shows the secret once. Configure the profile immediately.
```sh
read -r ACCESS_KEY_ID SECRET_ACCESS_KEY <> ~/.profile <<'EOF'
awsCurrentBill() {
start="$(date -u +%Y-%m-01)"
label="$(date -u -v-1d +%F 2>/dev/null || date -u -d yesterday +%F)"
end="$(date -u +%F)"
amount="$(AWS_PROFILE=cost-reader aws ce get-cost-and-usage \
--region us-east-1 \
--time-period Start="${start}",End="${end}" \
--granularity MONTHLY \
--metrics UnblendedCost \
--query 'ResultsByTime[0].Total.UnblendedCost.Amount' \
--output text)"
printf 'AWS month-to-date through %s: $%.2f\n' "${label}" "${amount}"
}
awsListResources() {
AWS_PROFILE=cost-reader aws ec2 describe-images \
--owners self \
--query 'Images[].{ImageId:ImageId,Snapshot:BlockDeviceMappings[0].Ebs.SnapshotId,Name:Name}' \
--output table
AWS_PROFILE=cost-reader aws ec2 describe-snapshots \
--owner-ids self \
--query 'Snapshots[].{SnapshotId:SnapshotId,Started:StartTime}' \
--output table
AWS_PROFILE=cost-reader aws ec2 describe-instances \
--query 'Reservations[].Instances[].{InstanceId:InstanceId,State:State.Name,DNS:PublicDnsName}' \
--output table
AWS_PROFILE=cost-reader aws ec2 describe-volumes \
--query 'Volumes[].{VolumeId:VolumeId,Created:CreateTime,AttachedTo:Attachments[0].InstanceId}' \
--output table
}
EOF
```
[ note ]
--------
Cost Explorer API requests are billed at $0.01 per paginated request. Keep
that in mind before running `awsCurrentBill()` from a login shell or cron job.
[ reference ]
-------------
IAM users
Manage access keys for IAM users
Getting started with Cost Explorer
Identity-based policy examples for AWS Cost Management
Cost Explorer DateInterval
Analyzing your costs and usage with AWS Cost Explorer
AWS Cost Explorer Pricing