| name | aws-github-oidc-scoped-role |
| description | OpenTofu/Terraform pattern for GitHub Actions OIDC trust with AWS IAM. Covers the non-obvious `job_workflow_ref` condition (vs just `sub` for repo+branch), the Bedrock inference profile ARN patterns, required `aws-marketplace` permissions alongside Bedrock, and the ReadOnlyAccess + explicit Deny pattern for AI agent roles. Use when wiring GitHub Actions to AWS via OIDC. |
AWS GitHub Actions OIDC — Scoped IAM Role
OIDC Provider Setup
data "tls_certificate" "github_oidc" {
url = "https://token.actions.githubusercontent.com"
}
resource "aws_iam_openid_connect_provider" "github" {
url = "https://token.actions.githubusercontent.com"
client_id_list = ["sts.amazonaws.com"]
thumbprint_list = [data.tls_certificate.github_oidc.certificates[0].sha1_fingerprint]
}
One provider per AWS account. If it already exists, use a data source instead.
Scope: sub (repo+branch) vs job_workflow_ref (specific workflow file)
Most tutorials scope the OIDC trust to a repo+branch using the sub claim:
# Minimal scope — any workflow in the repo on main can assume this role
condition {
test = "StringLike"
variable = "token.actions.githubusercontent.com:sub"
values = ["repo:ORG/REPO:ref:refs/heads/main"]
}
For privileged roles (e.g., AI agents, deploy roles), scope to a specific workflow file using job_workflow_ref. This prevents any new workflow added to the repo from assuming the role:
# Tight scope — only the specific workflow file from main can assume this role
condition {
test = "StringLike"
variable = "token.actions.githubusercontent.com:sub"
values = ["repo:ORG/REPO:*"] # AWS requires sub to be non-empty; use wildcard here
}
condition {
test = "StringEquals"
variable = "token.actions.githubusercontent.com:job_workflow_ref"
values = ["ORG/REPO/.github/workflows/my-workflow.yml@refs/heads/main"]
}