IAM Roles, Policies & OIDC Trust
Least-privilege IAM roles, managed policies, and GitHub/EKS OIDC federation in one composable module.
Verification
Live-testedReally deployed, verified, idempotent and destroyed in a cloud sandbox.
Conformance
- Static validation (fmt · validate · tflint)
- Security scan clean (Checkov)
- Plan tests (mocked: validation rules · outputs)
Provenance
- SHA-256 checksum
- Signature (pending)
Functional
- Live-tested — applied, verified, destroyed
Last verified 2026-06-11 · how we verify
Documentation
aws-iam-roles
Least-privilege IAM roles, managed policies, and GitHub/EKS OIDC federation in
one composable module. Works with Terraform and OpenTofu (>= 1.6), AWS
provider >= 6.0, < 7.0. Roles, customer-managed policies, OIDC identity
providers, and instance profiles are all driven from maps, so a single module
call provisions an account's whole role layout — and the policy-document
plumbing (trust statements, aud/sub conditions, attachment fan-out) is
already correct.
Secure defaults:
- Trust policies are composed per-role from explicit sources only
(
trusted_services,trusted_role_arnswith optionalexternal_id, GitHub OIDC subjects, custom OIDC issuers) — no wildcard principals - GitHub OIDC trust pins the
audclaim and usesrepo:-prefixedsubpatterns; built on v6-era standalone attachment resources (the removedinline_policy/managed_policy_arnsrole arguments are not used) max_session_durationdefaults to 1 hour;force_detach_policieson; permissions-boundary support per role
Usage
module "iam" {
source = "./aws-iam-roles"
create_github_oidc_provider = true
policies = {
artifact-read = {
policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Action = ["s3:GetObject", "s3:ListBucket"]
Resource = ["arn:aws:s3:::my-artifacts", "arn:aws:s3:::my-artifacts/*"]
}]
})
}
}
roles = {
github-deploy = {
github_repositories = ["my-org/my-app:ref:refs/heads/main"]
policy_keys = ["artifact-read"]
}
ec2-app = {
trusted_services = ["ec2.amazonaws.com"]
managed_policy_arns = ["arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"]
create_instance_profile = true
}
}
tags = { Environment = "prod" }
}
Inputs
| Name | Type | Default | Description |
|---|---|---|---|
roles | map(object) | {} | Roles keyed by logical name. Trust sources: trusted_services, trusted_role_arns (+ external_id), github_repositories (sub patterns without repo: prefix), oidc (list of {provider_arn, provider_url, audiences, subjects}). Permissions: managed_policy_arns, policy_keys, inline_policies. Extras: name, description, path, max_session_duration, permissions_boundary_arn, force_detach_policies, create_instance_profile |
policies | map(object) | {} | Customer-managed policies keyed by logical name: {name, description, path, policy} (JSON document) |
create_github_oidc_provider | bool | false | Create the token.actions.githubusercontent.com provider (one per account) |
github_oidc_provider_arn | string | null | ARN of a pre-existing GitHub OIDC provider (alternative to creating one) |
oidc_providers | map(object) | {} | Additional OIDC providers to create: {url, client_id_list, thumbprint_list} |
tags | map(string) | {} | Tags applied to all resources |
Outputs
| Name | Description |
|---|---|
role_arns / role_names | Map of role key => ARN / name |
instance_profile_arns / instance_profile_names | Map of role key => instance profile ARN / name |
policy_arns | Map of policy key => customer-managed policy ARN |
github_oidc_provider_arn | GitHub OIDC provider ARN (created or passed in) |
oidc_provider_arns | Map of oidc_providers key => provider ARN |
Requirements
- Terraform or OpenTofu
>= 1.6 hashicorp/aws>= 6.0, < 7.0
Notes
github_repositoriestrust requires eithercreate_github_oidc_provider = trueorgithub_oidc_provider_arn(enforced by a plan-time precondition).- Roles referencing module-created
oidc_providersfrom the same call should pass the issuer viaoidcwith the provider's ARN from a prior apply, or split providers and roles across two module calls — IAM allows only one provider per issuer URL per account.
Verification
Static-validated (fmt, validate, tflint). Live apply/destroy testing pending cloud sandbox availability — see catalog status.
License
Commercial — IaC Bazaar EULA. © IaC Bazaar. Original work (not derived from a third-party module).