Skip to content

IAM Policies

Cloudrift includes 3 built-in policies for AWS Identity and Access Management, covering least-privilege enforcement, policy management best practices, and trust relationship controls.

Summary

ID Policy Name Severity Frameworks
IAM-001 No Wildcard IAM Actions CRITICAL HIPAA, PCI DSS, ISO 27001, GDPR, SOC 2
IAM-002 No Inline Policies on Users MEDIUM PCI DSS, ISO 27001, SOC 2
IAM-003 IAM Role Trust Too Broad HIGH PCI DSS, ISO 27001, SOC 2

IAM-001

No Wildcard IAM Actions

CRITICAL

Frameworks: HIPAA, PCI DSS, ISO 27001, GDPR, SOC 2

Resource type: aws_iam_policy

Description: IAM policy contains a wildcard (*) action with Allow effect. Wildcard actions grant unrestricted permissions across all AWS services and API calls, violating the principle of least privilege. A compromised principal with Action: "*" has full administrative access to the AWS account, enabling data exfiltration, resource destruction, and privilege escalation.

Remediation:

Replace wildcard Action with specific actions following the least-privilege principle. Identify the exact API calls required by the workload and grant only those permissions.

resource "aws_iam_policy" "example" {
  name        = "application-policy"
  description = "Least-privilege policy for application workload"

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid    = "AllowS3ReadAccess"
        Effect = "Allow"
        Action = [
          "s3:GetObject",
          "s3:ListBucket"
        ]
        Resource = [
          "arn:aws:s3:::my-app-bucket",
          "arn:aws:s3:::my-app-bucket/*"
        ]
      },
      {
        Sid    = "AllowDynamoDBAccess"
        Effect = "Allow"
        Action = [
          "dynamodb:GetItem",
          "dynamodb:PutItem",
          "dynamodb:Query"
        ]
        Resource = "arn:aws:dynamodb:us-east-1:123456789012:table/my-app-table"
      }
    ]
  })
}

IAM-002

No Inline Policies on Users

MEDIUM

Frameworks: PCI DSS, ISO 27001, SOC 2

Resource type: aws_iam_user_policy

Description: IAM user policy uses an inline policy. Inline policies are embedded directly in a single IAM user and cannot be reused, versioned, or centrally managed. This makes auditing permissions difficult and increases the risk of policy sprawl. AWS best practice recommends using managed policies attached to groups or roles instead of inline policies on individual users.

Remediation:

Convert inline policies to managed policies and attach them to IAM groups or roles using aws_iam_user_policy_attachment. Users should inherit permissions through group membership rather than direct policy attachment.

# Instead of an inline policy:
#
# resource "aws_iam_user_policy" "inline" {
#   name   = "user-inline-policy"
#   user   = aws_iam_user.example.name
#   policy = jsonencode({ ... })
# }

# Use a managed policy attached via group membership:

resource "aws_iam_policy" "app_read" {
  name        = "app-read-policy"
  description = "Read access for application resources"

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        Action = [
          "s3:GetObject",
          "s3:ListBucket"
        ]
        Resource = [
          "arn:aws:s3:::my-app-bucket",
          "arn:aws:s3:::my-app-bucket/*"
        ]
      }
    ]
  })
}

resource "aws_iam_group" "developers" {
  name = "developers"
}

resource "aws_iam_group_policy_attachment" "developers_app_read" {
  group      = aws_iam_group.developers.name
  policy_arn = aws_iam_policy.app_read.arn
}

resource "aws_iam_user_group_membership" "example" {
  user   = aws_iam_user.example.name
  groups = [aws_iam_group.developers.name]
}

IAM-003

IAM Role Trust Too Broad

HIGH

Frameworks: PCI DSS, ISO 27001, SOC 2

Resource type: aws_iam_role

Description: IAM role has an overly broad trust policy allowing any principal. A trust policy with Principal: "*" or Principal: {"AWS": "*"} allows any AWS account, user, or service to assume the role. This effectively makes the role's permissions available to the entire internet (any AWS account) and can lead to unauthorized cross-account access and privilege escalation.

Remediation:

Restrict the Principal in the trust policy to specific AWS accounts, services, or IAM entities that legitimately need to assume the role.

resource "aws_iam_role" "example" {
  name = "application-role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid    = "AllowEC2Assume"
        Effect = "Allow"
        Principal = {
          Service = "ec2.amazonaws.com"
        }
        Action = "sts:AssumeRole"
      },
      {
        Sid    = "AllowCrossAccountAccess"
        Effect = "Allow"
        Principal = {
          AWS = "arn:aws:iam::123456789012:root"
        }
        Action = "sts:AssumeRole"
        Condition = {
          StringEquals = {
            "sts:ExternalId" = "unique-external-id"
          }
        }
      }
    ]
  })
}