Skip to content

Commit 3eca351

Browse files
feat: Add support for custom trust policy conditions on iam-github-oidc-role (#547)
Co-authored-by: Anton Babenko <[email protected]>
1 parent e803e25 commit 3eca351

File tree

5 files changed

+54
-14
lines changed

5 files changed

+54
-14
lines changed

examples/iam-github-oidc/main.tf

+18
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,24 @@ module "iam_github_oidc_role" {
4646
"terraform-aws-modules/terraform-aws-iam:ref:refs/heads/master",
4747
]
4848

49+
# As per the Github documentation for security hardening with OpenID Connect
50+
# (https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/about-security-hardening-with-openid-connect)
51+
# This document makes many references to the fact that you can leverage any of the available
52+
# OIDC claims to when configuring the cloud providers trust relation. For example in
53+
# https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/about-security-hardening-with-openid-connect#customizing-the-token-claims
54+
# it is specified that granular OIDC policies can be defined using additional OIDC token claims.
55+
# In this example, we ensure that the OIDC token GitHub uses to assume the AWS IAM role has the correct
56+
# `actor` scope.
57+
additional_trust_policy_conditions = [
58+
{
59+
test = "StringEquals"
60+
variable = "${module.iam_github_oidc_provider.url}:actor"
61+
# This should be the list of GitHub usernames for which you want to restrict
62+
# access to the role.
63+
values = ["username"]
64+
}
65+
]
66+
4967
policies = {
5068
additional = aws_iam_policy.additional.arn
5169
S3ReadOnly = "arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess"

modules/iam-github-oidc-role/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ No modules.
8282

8383
| Name | Description | Type | Default | Required |
8484
|------|-------------|------|---------|:--------:|
85+
| <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 |
8586
| <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 |
8687
| <a name="input_create"></a> [create](#input\_create) | Controls if resources should be created (affects all resources) | `bool` | `true` | no |
8788
| <a name="input_description"></a> [description](#input\_description) | IAM Role description | `string` | `null` | no |

modules/iam-github-oidc-role/main.tf

+10
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,16 @@ data "aws_iam_policy_document" "this" {
4747
# Strip `repo:` to normalize for cases where users may prepend it
4848
values = [for subject in var.subjects : "repo:${trimprefix(subject, "repo:")}"]
4949
}
50+
51+
dynamic "condition" {
52+
for_each = var.additional_trust_policy_conditions
53+
54+
content {
55+
test = condition.value.test
56+
values = condition.value.values
57+
variable = condition.value.variable
58+
}
59+
}
5060
}
5161
}
5262

modules/iam-github-oidc-role/variables.tf

+10
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,13 @@ variable "provider_url" {
8585
type = string
8686
default = "token.actions.githubusercontent.com"
8787
}
88+
89+
variable "additional_trust_policy_conditions" {
90+
description = "Additional conditions for the constraint to apply to the trust policy"
91+
type = list(object({
92+
test = string
93+
variable = string
94+
values = list(string)
95+
}))
96+
default = []
97+
}

wrappers/iam-github-oidc-role/main.tf

+15-14
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,19 @@ module "wrapper" {
33

44
for_each = var.items
55

6-
audience = try(each.value.audience, var.defaults.audience, "sts.amazonaws.com")
7-
create = try(each.value.create, var.defaults.create, true)
8-
description = try(each.value.description, var.defaults.description, null)
9-
force_detach_policies = try(each.value.force_detach_policies, var.defaults.force_detach_policies, true)
10-
max_session_duration = try(each.value.max_session_duration, var.defaults.max_session_duration, null)
11-
name = try(each.value.name, var.defaults.name, null)
12-
name_prefix = try(each.value.name_prefix, var.defaults.name_prefix, null)
13-
path = try(each.value.path, var.defaults.path, "/")
14-
permissions_boundary_arn = try(each.value.permissions_boundary_arn, var.defaults.permissions_boundary_arn, null)
15-
policies = try(each.value.policies, var.defaults.policies, {})
16-
provider_url = try(each.value.provider_url, var.defaults.provider_url, "token.actions.githubusercontent.com")
17-
subject_condition = try(each.value.subject_condition, var.defaults.subject_condition, "StringLike")
18-
subjects = try(each.value.subjects, var.defaults.subjects, [])
19-
tags = try(each.value.tags, var.defaults.tags, {})
6+
additional_trust_policy_conditions = try(each.value.additional_trust_policy_conditions, var.defaults.additional_trust_policy_conditions, [])
7+
audience = try(each.value.audience, var.defaults.audience, "sts.amazonaws.com")
8+
create = try(each.value.create, var.defaults.create, true)
9+
description = try(each.value.description, var.defaults.description, null)
10+
force_detach_policies = try(each.value.force_detach_policies, var.defaults.force_detach_policies, true)
11+
max_session_duration = try(each.value.max_session_duration, var.defaults.max_session_duration, null)
12+
name = try(each.value.name, var.defaults.name, null)
13+
name_prefix = try(each.value.name_prefix, var.defaults.name_prefix, null)
14+
path = try(each.value.path, var.defaults.path, "/")
15+
permissions_boundary_arn = try(each.value.permissions_boundary_arn, var.defaults.permissions_boundary_arn, null)
16+
policies = try(each.value.policies, var.defaults.policies, {})
17+
provider_url = try(each.value.provider_url, var.defaults.provider_url, "token.actions.githubusercontent.com")
18+
subject_condition = try(each.value.subject_condition, var.defaults.subject_condition, "StringLike")
19+
subjects = try(each.value.subjects, var.defaults.subjects, [])
20+
tags = try(each.value.tags, var.defaults.tags, {})
2021
}

0 commit comments

Comments
 (0)