Skip to content

Commit

Permalink
feat: Add support for custom trust policy conditions on `iam-github-o…
Browse files Browse the repository at this point in the history
…idc-role` (#547)

Co-authored-by: Anton Babenko <anton@antonbabenko.com>
  • Loading branch information
JBSchami and antonbabenko authored Mar 7, 2025
1 parent e803e25 commit 3eca351
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 14 deletions.
18 changes: 18 additions & 0 deletions examples/iam-github-oidc/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,24 @@ module "iam_github_oidc_role" {
"terraform-aws-modules/terraform-aws-iam:ref:refs/heads/master",
]

# As per the Github documentation for security hardening with OpenID Connect
# (https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/about-security-hardening-with-openid-connect)
# This document makes many references to the fact that you can leverage any of the available
# OIDC claims to when configuring the cloud providers trust relation. For example in
# https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/about-security-hardening-with-openid-connect#customizing-the-token-claims
# it is specified that granular OIDC policies can be defined using additional OIDC token claims.
# In this example, we ensure that the OIDC token GitHub uses to assume the AWS IAM role has the correct
# `actor` scope.
additional_trust_policy_conditions = [
{
test = "StringEquals"
variable = "${module.iam_github_oidc_provider.url}:actor"
# This should be the list of GitHub usernames for which you want to restrict
# access to the role.
values = ["username"]
}
]

policies = {
additional = aws_iam_policy.additional.arn
S3ReadOnly = "arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess"
Expand Down
1 change: 1 addition & 0 deletions modules/iam-github-oidc-role/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ No modules.

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_additional_trust_policy_conditions"></a> [additional\_trust\_policy\_conditions](#input\_additional\_trust\_policy\_conditions) | Additional conditions for the constraint to apply to the trust policy | <pre>list(object({<br/> test = string<br/> variable = string<br/> values = list(string)<br/> }))</pre> | `[]` | no |
| <a name="input_audience"></a> [audience](#input\_audience) | Audience to use for OIDC role. Defaults to `sts.amazonaws.com` for use with the [official AWS GitHub action](https://github.com/aws-actions/configure-aws-credentials) | `string` | `"sts.amazonaws.com"` | no |
| <a name="input_create"></a> [create](#input\_create) | Controls if resources should be created (affects all resources) | `bool` | `true` | no |
| <a name="input_description"></a> [description](#input\_description) | IAM Role description | `string` | `null` | no |
Expand Down
10 changes: 10 additions & 0 deletions modules/iam-github-oidc-role/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,16 @@ data "aws_iam_policy_document" "this" {
# Strip `repo:` to normalize for cases where users may prepend it
values = [for subject in var.subjects : "repo:${trimprefix(subject, "repo:")}"]
}

dynamic "condition" {
for_each = var.additional_trust_policy_conditions

content {
test = condition.value.test
values = condition.value.values
variable = condition.value.variable
}
}
}
}

Expand Down
10 changes: 10 additions & 0 deletions modules/iam-github-oidc-role/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,13 @@ variable "provider_url" {
type = string
default = "token.actions.githubusercontent.com"
}

variable "additional_trust_policy_conditions" {
description = "Additional conditions for the constraint to apply to the trust policy"
type = list(object({
test = string
variable = string
values = list(string)
}))
default = []
}
29 changes: 15 additions & 14 deletions wrappers/iam-github-oidc-role/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,19 @@ module "wrapper" {

for_each = var.items

audience = try(each.value.audience, var.defaults.audience, "sts.amazonaws.com")
create = try(each.value.create, var.defaults.create, true)
description = try(each.value.description, var.defaults.description, null)
force_detach_policies = try(each.value.force_detach_policies, var.defaults.force_detach_policies, true)
max_session_duration = try(each.value.max_session_duration, var.defaults.max_session_duration, null)
name = try(each.value.name, var.defaults.name, null)
name_prefix = try(each.value.name_prefix, var.defaults.name_prefix, null)
path = try(each.value.path, var.defaults.path, "/")
permissions_boundary_arn = try(each.value.permissions_boundary_arn, var.defaults.permissions_boundary_arn, null)
policies = try(each.value.policies, var.defaults.policies, {})
provider_url = try(each.value.provider_url, var.defaults.provider_url, "token.actions.githubusercontent.com")
subject_condition = try(each.value.subject_condition, var.defaults.subject_condition, "StringLike")
subjects = try(each.value.subjects, var.defaults.subjects, [])
tags = try(each.value.tags, var.defaults.tags, {})
additional_trust_policy_conditions = try(each.value.additional_trust_policy_conditions, var.defaults.additional_trust_policy_conditions, [])
audience = try(each.value.audience, var.defaults.audience, "sts.amazonaws.com")
create = try(each.value.create, var.defaults.create, true)
description = try(each.value.description, var.defaults.description, null)
force_detach_policies = try(each.value.force_detach_policies, var.defaults.force_detach_policies, true)
max_session_duration = try(each.value.max_session_duration, var.defaults.max_session_duration, null)
name = try(each.value.name, var.defaults.name, null)
name_prefix = try(each.value.name_prefix, var.defaults.name_prefix, null)
path = try(each.value.path, var.defaults.path, "/")
permissions_boundary_arn = try(each.value.permissions_boundary_arn, var.defaults.permissions_boundary_arn, null)
policies = try(each.value.policies, var.defaults.policies, {})
provider_url = try(each.value.provider_url, var.defaults.provider_url, "token.actions.githubusercontent.com")
subject_condition = try(each.value.subject_condition, var.defaults.subject_condition, "StringLike")
subjects = try(each.value.subjects, var.defaults.subjects, [])
tags = try(each.value.tags, var.defaults.tags, {})
}

0 comments on commit 3eca351

Please sign in to comment.