iam-role

Category Security
Latest Version 0.1.0current

- Create IAM roles with customizable trust policies

Add to your Terraform configuration
module "iam_role" {
  source  = "registry.patterneddesigns.ca/patterneddesigns/iam-role/aws"
  version = "0.1.0"

  # Required inputs
  name = "..."
}

Overview

The iam-role module creates AWS IAM roles with:

  • Customizable trust policies for service principals
  • Managed policy attachments for standard permissions
  • Inline policies for custom permissions
  • Configurable session duration
  • Optional permissions boundaries for security guardrails

Category: Security Provider: AWS Latest Version: 2.0.0

Quick Start

module "lambda_role" {
  source  = "registry.patterneddesigns.ca/patterneddesigns/iam-role/aws"
  version = "2.0.0"

  name = "lambda-execution-role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect    = "Allow"
      Principal = { Service = "lambda.amazonaws.com" }
      Action    = "sts:AssumeRole"
    }]
  })

  managed_policy_arns = [
    "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
  ]
}

Key Features

Service-Linked Roles

Create roles for AWS services:

# Lambda execution role
module "lambda_role" {
  source  = "registry.patterneddesigns.ca/patterneddesigns/iam-role/aws"
  version = "2.0.0"

  name = "lambda-api-handler"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect    = "Allow"
      Principal = { Service = "lambda.amazonaws.com" }
      Action    = "sts:AssumeRole"
    }]
  })

  managed_policy_arns = [
    "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
  ]
}

Cross-Account Access

Allow principals from other accounts:

module "cross_account_role" {
  source  = "registry.patterneddesigns.ca/patterneddesigns/iam-role/aws"
  version = "2.0.0"

  name = "cross-account-admin"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect    = "Allow"
      Principal = { AWS = "arn:aws:iam::123456789012:root" }
      Action    = "sts:AssumeRole"
      Condition = {
        StringEquals = { "sts:ExternalId" = "shared-secret" }
      }
    }]
  })

  managed_policy_arns = [
    "arn:aws:iam::aws:policy/AdministratorAccess"
  ]
}

Custom Inline Policies

Attach custom permissions directly:

module "s3_processor_role" {
  source  = "registry.patterneddesigns.ca/patterneddesigns/iam-role/aws"
  version = "2.0.0"

  name = "s3-processor"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect    = "Allow"
      Principal = { Service = "lambda.amazonaws.com" }
      Action    = "sts:AssumeRole"
    }]
  })

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

Documentation

Registry

View specification on Registry

Inputs

name Required
string

The name of the IAM role. Must be unique within your AWS account. **Naming conventions:** - Use lowercase with hyphens: `my-service-role` - Include purpose: `lambda-processor-role`, `ecs-task-role` - Include environment for clarity: `prod-api-gateway-role` **Constraints:** - Maximum 64 characters - Alphanumeric characters, plus `+=,.@-_` - Cannot begin with `aws-`

Human-readable description of the role's purpose. A good description helps with: - Auditing and compliance reviews - Understanding role purpose months later - Identifying roles for cleanup **Example descriptions:** - "Allows Lambda functions to process S3 events and write to DynamoDB" - "ECS task execution role for production API containers" - "Cross-account access for CI/CD pipeline deployment"

string Default: /

Path for the IAM role. Use paths to organize roles hierarchically. **Path patterns:** - `/service-roles/` - AWS service-linked roles - `/application/{app-name}/` - Application-specific roles - `/environment/{env}/` - Environment-based organization - `/team/{team-name}/` - Team ownership **Benefits of using paths:** - Organize roles by application, team, or environment - Apply IAM policies that scope to path prefixes - Easier auditing and role discovery **Example:** `/production/api/` would allow policies like: ```json { "Effect": "Allow", "Action": "iam:PassRole", "Resource": "arn:aws:iam::*:role/production/api/*" } ```

Set of managed policy ARNs to attach to the role. **AWS managed policies** (recommended for common use cases): - `arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole` - `arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy` - `arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess` - `arn:aws:iam::aws:policy/CloudWatchLogsFullAccess` **Customer managed policies** (for custom permissions): - `arn:aws:iam::123456789012:policy/MyCustomPolicy` **Best practices:** - Prefer managed policies over inline for reusability - Use AWS managed policies when they fit your needs - Create customer managed policies for organization-specific permissions - Maximum 10 managed policies per role (AWS limit)

ARN of the policy to use as a permissions boundary. **What is a permissions boundary?** A permissions boundary sets the maximum permissions a role can have, regardless of what policies are attached. The effective permissions are the intersection of the identity-based policies and the boundary. **Use cases:** - Delegate role creation to developers while limiting maximum permissions - Enforce organization-wide security controls - Prevent privilege escalation in multi-tenant environments **Example boundary policy:** A boundary that prevents IAM modifications: ```json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "*", "Resource": "*" }, { "Effect": "Deny", "Action": [ "iam:CreateRole", "iam:DeleteRole", "iam:AttachRolePolicy", "iam:PutRolePolicy" ], "Resource": "*" } ] } ``` **Best practices:** - Apply boundaries to all roles created by delegated administrators - Include the boundary in the boundary policy itself to prevent removal - Test thoroughly - boundaries can cause unexpected permission denials

number Default: 3600

Maximum session duration in seconds for role assumption. **Range:** 3600 (1 hour) to 43200 (12 hours) **Default:** 3600 (1 hour) **When to increase:** - Long-running CI/CD pipelines - Cross-account access requiring extended sessions - Interactive console sessions for debugging **Security consideration:** Use the shortest duration that meets your needs. Shorter sessions reduce the window of exposure if credentials are compromised. **Common durations:** - 1 hour (3600): Default, suitable for most automated tasks - 4 hours (14400): Long CI/CD pipelines - 8 hours (28800): Workday console sessions - 12 hours (43200): Maximum, rarely needed

Whether to force detach policies before destroying the role. **Default:** false When set to `true`, Terraform will automatically detach all managed and inline policies before attempting to delete the role. **When to enable:** - Development environments where roles are frequently recreated - Automated cleanup processes - When policies might be attached outside of Terraform **Caution:** In production, keeping this `false` ensures you're aware of all policies attached to a role before deletion.

Whether to create an EC2 instance profile for this role. **What is an instance profile?** An instance profile is a container for an IAM role that allows EC2 instances to assume the role. EC2 instances cannot directly use IAM roles - they must use instance profiles. **When to enable:** - The role will be used by EC2 instances - The role will be used by ECS container instances (not Fargate) - You need to pass credentials to applications running on EC2 **When NOT needed:** - Lambda functions (use role ARN directly) - ECS Fargate tasks (use task role ARN) - Cross-account access (use role ARN with AssumeRole)

Name of the instance profile. Defaults to the role name if not specified. Only used when `create_instance_profile = true`. **When to customize:** - You need a different name for the instance profile than the role - Migrating from an existing instance profile with a specific name - Organization naming conventions differ for profiles vs roles

map(string)

Map of tags to apply to all resources created by this module. **Required tags (recommended):** - `Environment`: prod, staging, dev - `Owner`: Team or individual responsible **Optional tags:** - `CostCenter`: For cost allocation - `Service`: Application or service name - `Compliance`: Regulatory requirements (PCI, HIPAA, etc.) **Example:** ```hcl tags = { Environment = "production" Owner = "platform-team" Service = "payment-api" CostCenter = "engineering" } ``` **Note:** The module automatically adds: - `ManagedBy = "terraform"` - `Module = "patterneddesigns/iam-role/aws"`

Outputs

role_arn

role_name

Name of the IAM role. Use the name (not ARN) when: - Attaching policies via aws_iam_role_policy_attachment - Referencing in aws_iam_instance_profile - Using with AWS CLI commands Use the ARN instead when: - Configuring cross-account access - Setting up service-linked resources

role_id

Stable and unique string identifying the role. This ID remains constant even if the role is recreated with the same name. Use for: - CloudWatch log group policies scoped to specific roles - S3 bucket policies with aws:userId condition - Audit trails requiring stable identifiers

unique_id

Unique identifier assigned by AWS (format: AROA...). This is the principal ID used in: - CloudTrail logs for role assumption events - S3 access logs identifying the caller - Resource policies using aws:userId conditions Unlike role_id, this is the AWS-assigned identifier that appears in audit logs and can be used to trace actions back to this role.

create_date

Timestamp when the role was created (ISO 8601 format). Useful for: - Auditing role age - Identifying stale roles for cleanup - Compliance reporting

instance_profile_arn

ARN of the instance profile (if created). Only populated when create_instance_profile = true. Use this ARN when: - Launching EC2 instances with aws_instance.iam_instance_profile - Configuring Auto Scaling launch templates - Setting up ECS container instances

instance_profile_name

Name of the instance profile (if created). Only populated when create_instance_profile = true. Use the name when referencing in: - AWS CLI commands (aws ec2 associate-iam-instance-profile) - CloudFormation templates - Launch configurations

instance_profile_id

Unique identifier for the instance profile (if created). Only populated when create_instance_profile = true. Format: AIPA... (similar to role unique_id but for profiles)

Verification & Attestation

Checksum
map[algorithm:sha256 scope:module source files]
Build System github-actions