Overview
The OIDC provider module (modules/oidc-provider/) creates a GitHub Actions OpenID Connect provider and IAM role, enabling keyless authentication from GitHub workflows to AWS.
Benefits:
- No AWS credentials stored in GitHub Secrets
- Temporary credentials with automatic expiration
- Repository-scoped access control
- Full audit trail via CloudTrail
Module structure
modules/oidc-provider/
├── main.tf # OIDC provider and IAM role
├── variables.tf # Input variables
├── outputs.tf # Module outputs
└── versions.tf # Provider requirements
Usage examples
Basic usage
module "oidc_provider" {
source = "../../modules/oidc-provider"
github_repo = "your-org/your-repo"
}
With managed policies
module "oidc_provider" {
source = "../../modules/oidc-provider"
github_repo = "your-org/your-repo"
role_name = "GitHubActionsServiceRole-Terraform-staging"
managed_policy_arns = [
"arn:aws:iam::aws:policy/PowerUserAccess"
]
}
With inline policies
module "oidc_provider" {
source = "../../modules/oidc-provider"
github_repo = "your-org/your-repo"
inline_policies = {
"S3Access" = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = ["s3:GetObject", "s3:PutObject"]
Resource = "arn:aws:s3:::my-bucket/*"
}
]
})
}
}
Reusing existing OIDC provider
When deploying multiple environments to the same AWS account:
module "oidc_provider" {
source = "../../modules/oidc-provider"
github_repo = "your-org/your-repo"
use_existing_oidc_provider = true
role_name = "GitHubActionsServiceRole-Terraform-staging"
}
Input variables
| Name | Type | Default | Required | Description |
|---|---|---|---|---|
github_repo | string | - | Yes | GitHub repository (owner/repo) |
use_existing_oidc_provider | bool | false | No | Use existing OIDC provider |
github_thumbprint | string | 6938fd4d... | No | GitHub OIDC thumbprint |
audience_list | list(string) | ["sts.amazonaws.com"] | No | Allowed audiences |
role_name | string | GitHubActionsServiceRole-Terraform | No | IAM role name |
path | string | / | No | IAM path for the role |
managed_policy_arns | list(string) | [] | No | Managed policy ARNs |
inline_policies | map(string) | {} | No | Inline policy documents |
max_session_duration | number | 3600 | No | Max session duration (3600-43200) |
tags | map(string) | {} | No | Resource tags |
Outputs
| Name | Type | Description |
|---|---|---|
oidc_provider_arn | string | ARN of the OIDC provider |
oidc_provider_url | string | URL of the OIDC provider |
role_arn | string | ARN of the IAM role |
role_name | string | Name of the IAM role |
role_id | string | ID of the IAM role |
role_unique_id | string | Unique ID of the IAM role |
How it works
OIDC provider management
The module automatically detects and reuses existing OIDC providers:
data "aws_iam_openid_connect_provider" "github_actions" {
count = var.use_existing_oidc_provider ? 1 : 0
url = "https://token.actions.githubusercontent.com"
}
resource "aws_iam_openid_connect_provider" "github_actions" {
count = var.use_existing_oidc_provider ? 0 : 1
url = "https://token.actions.githubusercontent.com"
client_id_list = var.audience_list
thumbprint_list = [var.github_thumbprint]
}
Why this matters:
- AWS allows only one OIDC provider per issuer URL per account
- Setting
use_existing_oidc_provider = trueprevents errors when deploying multiple environments
Trust policy
The IAM role trusts GitHub Actions for your specific repository:
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Principal = {
Federated = local.oidc_provider_arn
}
Action = "sts:AssumeRoleWithWebIdentity"
Condition = {
StringLike = {
"token.actions.githubusercontent.com:sub" = "repo:${var.github_repo}:*"
}
StringEquals = {
"token.actions.githubusercontent.com:aud" = "sts.amazonaws.com"
}
}
}
]
})
Security features:
- Repository-scoped: Only your repository can assume the role
- Audience validation: Token must be intended for AWS STS
- Wildcard subject: Allows all branches and environments
Requirements
terraform {
required_version = ">= 1.5.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.0"
}
}
}
Next steps
- Creating Modules - Build custom modules
- CI/CD Workflows - How this module is used
- Environments - Multi-environment setup