# main.tf — IAM compliance fixture # Produces zero IAM policy violations terraform { required_providers { aws = { source = "hashicorp/aws" version = "~> 5.0" } } } # No hardcoded credentials — IAM-006 passes provider "aws" { region = "ap-south-1" } # IAM-001 — Policies attached to group, not user resource "aws_iam_group" "app_group" { name = "app-group" } resource "aws_iam_group_policy" "app_group_policy" { name = "app-group-policy" group = aws_iam_group.app_group.name policy = jsonencode({ Version = "2012-10-17" Statement = [{ Effect = "Allow" Action = ["s3:GetObject"] Resource = "arn:aws:s3:::my-bucket/*" }] }) } # IAM-002 — No access keys created # IAM-003 — KMS permissions scoped to specific key ARN resource "aws_iam_role" "app_role" { name = "app-role" permissions_boundary = "arn:aws:iam::123456789012:policy/boundary-policy" assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [{ Effect = "Allow" Principal = { Service = "ec2.amazonaws.com" } Action = "sts:AssumeRole" }] }) } resource "aws_iam_role_policy" "scoped_kms" { name = "scoped-kms-policy" role = aws_iam_role.app_role.name policy = jsonencode({ Version = "2012-10-17" Statement = [{ Effect = "Allow" Action = ["kms:Decrypt"] Resource = "arn:aws:kms:ap-south-1:123456789012:key/mrk-1234abcd" }] }) } # IAM-004 — Permissions boundary set (see app_role above) # IAM-005 — Cross-account trust scoped to specific account with condition resource "aws_iam_role" "cross_account_role" { name = "cross-account-role" permissions_boundary = "arn:aws:iam::123456789012:policy/boundary-policy" assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [{ Effect = "Allow" Principal = { AWS = "arn:aws:iam::999999999999:root" } Action = "sts:AssumeRole" Condition = { StringEquals = { "sts:ExternalId" = "unique-external-id" } } }] }) }