The IAM policy

The IAM policy Kulshan runs with.

Every action in this policy is a Get, List, or Describe. There is no Put, Create, Update, Modify, or Delete because the source code does not call any. Verify the hash. Read the plain-language allow list. Decide if you trust it.

version
0.1.0 (Kulshan v0.1.0, released 2026-04-21)
total actions
146
aws services
30
sha256
fd39f19d6781488fe54ceb46e76fc2345a9e77a9c6caf33286f2eca1f1889217
file
Kulshan-readonly.json (composed policy, 6.7 KB)
source
Generated from per-pack policies in Kulshan/iam/per-check/. Composed at release time, attested by hash.

What the policy allows.

Plain-language summary. Every line below maps to read-only AWS APIs. The full action list is in the JSON file above.

spend
Cost Explorer queries (cost and usage, anomaly history, RI/SP coverage and recommendations, forecast). Aggregate cost data only. ce:Get*
compute
EC2 instances, EBS volumes and snapshots, security groups, route tables, NAT gateways, Auto Scaling groups, Lambda function configuration. ec2:Describe*, autoscaling:Describe*, lambda:List*, lambda:GetFunction*
containers
ECS clusters and services, EKS clusters, ECR repositories, image scan findings. Configuration only.
storage
S3 bucket inventory, encryption, versioning, public-access settings, lifecycle policies, replication. Bucket configuration only, no object data.
database
RDS clusters and instances, parameter groups, snapshots, DynamoDB tables, ElastiCache clusters. Configuration only.
network
VPC topology, subnets, route tables, peering, transit gateways, ELB / ALB / NLB, Route 53 hosted zones. Configuration only.
identity
IAM users, roles, groups, policies (their configuration, not their secrets), Access Analyzer findings, organization structure, caller identity. iam:Get*, iam:List*, access-analyzer:*, organizations:Describe*, sts:GetCallerIdentity
audit log
CloudTrail trail configuration and integrity validation status, AWS Config recorders and rules, X-Ray traces. Whether logging is on, not the log contents.
monitoring
CloudWatch metrics, alarms, dashboards, log-group existence and retention. Log-group names and retention, not the log lines.
encryption
KMS key configuration (rotation, policy, grants). No Decrypt. No GenerateDataKey. No cryptographic operations.
backup
AWS Backup vaults, plans, recovery points, protected resources. Configuration and inventory only.
threat data
GuardDuty detector configuration and findings.
tags
Resource Groups Tagging API queries to compute tag coverage and ownership gaps.
capacity
Service Quotas (current usage and limits), CloudFormation stack drift detection status.
delivery
SNS topic configuration. Used by the observability pack to map alarm-to-channel wiring.

What it explicitly does NOT allow.

Verbs the policy never grants. If you find a Kulshan code path that calls one of these, that is a bug, and it should be reported to [email protected].

  • No Put, Create, Update, Modify, Delete, or Terminate on any service.
  • No iam:CreateAccessKey, iam:UpdateLoginProfile, iam:CreateUser, or any IAM mutation.
  • No sts:AssumeRole in the policy itself. Kulshan uses your existing credential chain; assuming a role is your decision, not the policy's.
  • No s3:GetObject. The bucket configuration is readable; the bucket contents are not.
  • No kms:Decrypt, kms:GenerateDataKey, kms:Encrypt, or any cryptographic operation.
  • No ec2:RunInstances, ec2:TerminateInstances, ec2:CreateTags, or any compute-lifecycle action.
  • No rds:Modify*, lambda:UpdateFunctionCode, secretsmanager:GetSecretValue, or any other resource modification or secret access.

Verify it yourself.

Download the JSON, hash it locally, and compare to the SHA256 above. If the two match, the file you have is the file we ship.

$ shasum -a 256 Kulshan-readonly.json fd39f19d6781488fe54ceb46e76fc2345a9e77a9c6caf33286f2eca1f1889217 Kulshan-readonly.json

If the hash does not match, something is wrong. Email [email protected].

Per-pack policies.

Each pack ships its own minimum-viable policy. Attach only the packs you intend to run. Per-pack totals do not add up to 146 because some read-only actions are reused across multiple checks. The composed policy de-duplicates shared actions into 146 unique IAM actions.

Pack
Actions
Services
Download
age
16
7
cost
13
2
dr
29
10
drift
12
6
limit
19
10
pulse
23
14
security
72
13
sweep
24
9
tag
33
11
topo
14
2

Reuse

Reuse freely under CC BY 4.0. Credit: MissionFinOps, missionfinops.com.

This applies to the policy file (kulshan-readonly.json and the per-pack files in kulshan/iam/per-check/) only. The CC BY 4.0 license on the policy file is in addition to the Apache 2.0 license that covers the rest of the Kulshan codebase.

If your team or tool adopts this policy as a baseline, no permission needed. A link back is appreciated, not required.