Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions terraform/aws/iam-role/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# iam-role

<!-- BEGIN_TF_DOCS -->
## Requirements

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.0 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | ~> 5.0 |

## Providers

| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | 5.100.0 |

## Modules

No modules.

## Resources

| Name | Type |
|------|------|
| [aws_iam_role.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
| [aws_iam_role_policy.inline](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource |
| [aws_iam_role_policy_attachment.managed](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_assume_role_policy"></a> [assume\_role\_policy](#input\_assume\_role\_policy) | JSON-formatted assume role policy document (trust policy) | `string` | n/a | yes |
| <a name="input_description"></a> [description](#input\_description) | Description of the IAM role | `string` | `"IAM role created by Terraform"` | no |
| <a name="input_force_detach_policies"></a> [force\_detach\_policies](#input\_force\_detach\_policies) | Whether to force detach policies when destroying the role | `bool` | `false` | no |
| <a name="input_inline_policies"></a> [inline\_policies](#input\_inline\_policies) | Map of inline policy names to policy documents (JSON strings) | `map(string)` | `{}` | no |
| <a name="input_managed_policy_arns"></a> [managed\_policy\_arns](#input\_managed\_policy\_arns) | List of ARNs of managed policies to attach to the role | `list(string)` | `[]` | no |
| <a name="input_max_session_duration"></a> [max\_session\_duration](#input\_max\_session\_duration) | Maximum session duration (in seconds) for the role (3600-43200) | `number` | `3600` | no |
| <a name="input_name"></a> [name](#input\_name) | Name of the IAM role | `string` | n/a | yes |
| <a name="input_path"></a> [path](#input\_path) | Path for the IAM role | `string` | `"/"` | no |
| <a name="input_permissions_boundary"></a> [permissions\_boundary](#input\_permissions\_boundary) | ARN of the policy that is used to set the permissions boundary for the role | `string` | `null` | no |
| <a name="input_tags"></a> [tags](#input\_tags) | Tags to apply to the IAM role | `map(string)` | `{}` | no |

## Outputs

| Name | Description |
|------|-------------|
| <a name="output_role_arn"></a> [role\_arn](#output\_role\_arn) | ARN of the IAM role |
| <a name="output_role_id"></a> [role\_id](#output\_role\_id) | ID of the IAM role |
| <a name="output_role_name"></a> [role\_name](#output\_role\_name) | Name of the IAM role |
| <a name="output_role_unique_id"></a> [role\_unique\_id](#output\_role\_unique\_id) | Unique ID assigned by AWS |
<!-- END_TF_DOCS -->
60 changes: 60 additions & 0 deletions terraform/aws/iam-role/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# -----------------------------------------------------------------------------
# IAM Role Module
# Creates an IAM role with assume role policy and optional inline/managed policies
# -----------------------------------------------------------------------------

terraform {
required_version = ">= 1.0"

required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}

# -----------------------------------------------------------------------------
# IAM Role
# -----------------------------------------------------------------------------

resource "aws_iam_role" "this" {
name = var.name
description = var.description
assume_role_policy = var.assume_role_policy

max_session_duration = var.max_session_duration
path = var.path
permissions_boundary = var.permissions_boundary
force_detach_policies = var.force_detach_policies

tags = merge(
var.tags,
{
Name = var.name
}
)
}

# -----------------------------------------------------------------------------
# Managed Policy Attachments
# -----------------------------------------------------------------------------

resource "aws_iam_role_policy_attachment" "managed" {
for_each = toset(var.managed_policy_arns)

role = aws_iam_role.this.name
policy_arn = each.value
}

# -----------------------------------------------------------------------------
# Inline Policies
# -----------------------------------------------------------------------------

resource "aws_iam_role_policy" "inline" {
for_each = var.inline_policies

name = each.key
role = aws_iam_role.this.id
policy = each.value
}
23 changes: 23 additions & 0 deletions terraform/aws/iam-role/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# -----------------------------------------------------------------------------
# IAM Role Outputs
# -----------------------------------------------------------------------------

output "role_arn" {
description = "ARN of the IAM role"
value = aws_iam_role.this.arn
}

output "role_name" {
description = "Name of the IAM role"
value = aws_iam_role.this.name
}

output "role_id" {
description = "ID of the IAM role"
value = aws_iam_role.this.id
}

output "role_unique_id" {
description = "Unique ID assigned by AWS"
value = aws_iam_role.this.unique_id
}
86 changes: 86 additions & 0 deletions terraform/aws/iam-role/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# -----------------------------------------------------------------------------
# IAM Role Variables
# -----------------------------------------------------------------------------

variable "name" {
description = "Name of the IAM role"
type = string

validation {
condition = can(regex("^[a-zA-Z][a-zA-Z0-9-_+=,.@-]*$", var.name)) && length(var.name) <= 64
error_message = "Role name must start with a letter, contain only alphanumeric characters and -_+=,.@- symbols, and be up to 64 characters long."
}
}

variable "description" {
description = "Description of the IAM role"
type = string
default = "IAM role created by Terraform"
}

variable "assume_role_policy" {
description = "JSON-formatted assume role policy document (trust policy)"
type = string

validation {
condition = can(jsondecode(var.assume_role_policy))
error_message = "The assume role policy must be a valid JSON document."
}
}

variable "managed_policy_arns" {
description = "List of ARNs of managed policies to attach to the role"
type = list(string)
default = []
}

variable "inline_policies" {
description = "Map of inline policy names to policy documents (JSON strings)"
type = map(string)
default = {}

validation {
condition = alltrue([for policy in values(var.inline_policies) : can(jsondecode(policy))])
error_message = "All inline policies must be valid JSON documents."
}
}

variable "max_session_duration" {
description = "Maximum session duration (in seconds) for the role (3600-43200)"
type = number
default = 3600

validation {
condition = var.max_session_duration >= 3600 && var.max_session_duration <= 43200
error_message = "Max session duration must be between 3600 (1 hour) and 43200 (12 hours)."
}
}

variable "path" {
description = "Path for the IAM role"
type = string
default = "/"

validation {
condition = can(regex("^/.*/$", var.path)) || var.path == "/"
error_message = "Path must begin and end with /."
}
}

variable "permissions_boundary" {
description = "ARN of the policy that is used to set the permissions boundary for the role"
type = string
default = null
}

variable "force_detach_policies" {
description = "Whether to force detach policies when destroying the role"
type = bool
default = false
}

variable "tags" {
description = "Tags to apply to the IAM role"
type = map(string)
default = {}
}