Skip to content

Commit 0e979ff

Browse files
committed
feat: Remove permission variable defaults, add updates from upstream issues/PRs
1 parent a4ef1f5 commit 0e979ff

File tree

6 files changed

+233
-26
lines changed

6 files changed

+233
-26
lines changed

modules/iam-group/main.tf

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,10 @@ data "aws_iam_policy_document" "this" {
5555
content {
5656
sid = "ViewAccountInfo"
5757
actions = [
58+
"iam:GetAccountSummary",
5859
"iam:GetAccountPasswordPolicy",
59-
"iam:ListVirtualMFADevices"
60+
"iam:ListAccountAliases",
61+
"iam:ListVirtualMFADevices",
6062
]
6163
resources = ["*"]
6264
}
@@ -69,7 +71,9 @@ data "aws_iam_policy_document" "this" {
6971
sid = "ManageOwnPasswords"
7072
actions = [
7173
"iam:ChangePassword",
72-
"iam:GetUser"
74+
"iam:GetLoginProfile",
75+
"iam:GetUser",
76+
"iam:UpdateLoginProfile",
7377
]
7478
resources = local.user_resources
7579
}
@@ -84,7 +88,11 @@ data "aws_iam_policy_document" "this" {
8488
"iam:CreateAccessKey",
8589
"iam:DeleteAccessKey",
8690
"iam:ListAccessKeys",
87-
"iam:UpdateAccessKey"
91+
"iam:UpdateAccessKey",
92+
"iam:GetAccessKeyLastUsed",
93+
"iam:TagUser",
94+
"iam:ListUserTags",
95+
"iam:UntagUser",
8896
]
8997
resources = local.user_resources
9098
}
@@ -168,14 +176,15 @@ data "aws_iam_policy_document" "this" {
168176
content {
169177
sid = "DenyAllExceptListedIfNoMFA"
170178
not_actions = [
171-
"iam:ChangePassword",
172179
"iam:CreateVirtualMFADevice",
173180
"iam:EnableMFADevice",
174181
"iam:GetUser",
182+
"iam:GetMFADevice",
175183
"iam:ListMFADevices",
176184
"iam:ListVirtualMFADevices",
177185
"iam:ResyncMFADevice",
178-
"sts:GetSessionToken"
186+
"sts:GetSessionToken",
187+
"iam:ChangePassword",
179188
]
180189
resources = ["*"]
181190

modules/iam-read-only-policy/main.tf

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ data "aws_iam_policy_document" "this" {
2828
actions = [
2929
"${statement.value}:List*",
3030
"${statement.value}:Get*",
31+
"${statement.value}:BatchGet*",
3132
"${statement.value}:Describe*",
3233
"${statement.value}:View*",
3334
]
@@ -44,6 +45,7 @@ data "aws_iam_policy_document" "this" {
4445
actions = [
4546
"${statement.value}:List*",
4647
"${statement.value}:Get*",
48+
"${statement.value}:BatchGet*",
4749
"${statement.value}:Describe*",
4850
"${statement.value}:View*",
4951
]

modules/iam-role/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,10 @@ No modules.
141141
|------|------|
142142
| [aws_iam_instance_profile.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_instance_profile) | resource |
143143
| [aws_iam_role.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
144+
| [aws_iam_role_policy.inline](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource |
144145
| [aws_iam_role_policy_attachment.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
145146
| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source |
147+
| [aws_iam_policy_document.inline](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
146148
| [aws_iam_policy_document.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
147149
| [aws_partition.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/partition) | data source |
148150

@@ -151,13 +153,16 @@ No modules.
151153
| Name | Description | Type | Default | Required |
152154
|------|-------------|------|---------|:--------:|
153155
| <a name="input_assume_role_policy_statements"></a> [assume\_role\_policy\_statements](#input\_assume\_role\_policy\_statements) | A map of IAM policy [statements](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#statement) for custom permission usage | <pre>map(object({<br/> sid = optional(string)<br/> actions = optional(list(string))<br/> not_actions = optional(list(string))<br/> effect = optional(string, "Allow")<br/> resources = optional(list(string))<br/> not_resources = optional(list(string))<br/> principals = optional(list(object({<br/> type = string<br/> identifiers = list(string)<br/> })))<br/> not_principals = optional(list(object({<br/> type = string<br/> identifiers = list(string)<br/> })))<br/> condition = optional(list(object({<br/> test = string<br/> variable = string<br/> values = list(string)<br/> })))<br/> }))</pre> | `null` | no |
156+
| <a name="input_condition"></a> [condition](#input\_condition) | [Condition constraints](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#condition) applied to the trust policy(s) enabled | <pre>list(object({<br/> test = string<br/> variable = string<br/> values = list(string)<br/> }))</pre> | `[]` | no |
154157
| <a name="input_create"></a> [create](#input\_create) | Controls if resources should be created (affects all resources) | `bool` | `true` | no |
155158
| <a name="input_create_instance_profile"></a> [create\_instance\_profile](#input\_create\_instance\_profile) | Determines whether to create an instance profile | `bool` | `false` | no |
156159
| <a name="input_description"></a> [description](#input\_description) | Description of the role | `string` | `null` | no |
157160
| <a name="input_enable_bitbucket_oidc"></a> [enable\_bitbucket\_oidc](#input\_enable\_bitbucket\_oidc) | Enable Bitbucket OIDC provider trust for the role | `bool` | `false` | no |
158161
| <a name="input_enable_github_oidc"></a> [enable\_github\_oidc](#input\_enable\_github\_oidc) | Enable GitHub OIDC provider trust for the role | `bool` | `false` | no |
159162
| <a name="input_enable_oidc"></a> [enable\_oidc](#input\_enable\_oidc) | Enable OIDC provider trust for the role | `bool` | `false` | no |
160163
| <a name="input_enable_saml"></a> [enable\_saml](#input\_enable\_saml) | Enable SAML provider trust for the role | `bool` | `false` | no |
164+
| <a name="input_github_provider"></a> [github\_provider](#input\_github\_provider) | The GitHub OIDC provider URL *without the `https://` prefix | `string` | `"token.actions.githubusercontent.com"` | no |
165+
| <a name="input_inline_policy_statements"></a> [inline\_policy\_statements](#input\_inline\_policy\_statements) | A map of IAM policy [statements](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#statement) for inline policy permissions | <pre>map(object({<br/> sid = optional(string)<br/> actions = optional(list(string))<br/> not_actions = optional(list(string))<br/> effect = optional(string, "Allow")<br/> resources = optional(list(string))<br/> not_resources = optional(list(string))<br/> principals = optional(list(object({<br/> type = string<br/> identifiers = list(string)<br/> })))<br/> not_principals = optional(list(object({<br/> type = string<br/> identifiers = list(string)<br/> })))<br/> condition = optional(list(object({<br/> test = string<br/> variable = string<br/> values = list(string)<br/> })))<br/> }))</pre> | `null` | no |
161166
| <a name="input_max_session_duration"></a> [max\_session\_duration](#input\_max\_session\_duration) | Maximum session duration (in seconds) that you want to set for the specified role. If you do not specify a value for this setting, the default maximum of one hour is applied. This setting can have a value from 1 hour to 12 hours | `number` | `null` | no |
162167
| <a name="input_name"></a> [name](#input\_name) | Name to use on IAM role created | `string` | `null` | no |
163168
| <a name="input_oidc_account_id"></a> [oidc\_account\_id](#input\_oidc\_account\_id) | An overriding AWS account ID where the OIDC provider lives; leave empty to use the current account ID for the AWS provider | `string` | `null` | no |

modules/iam-role/main.tf

Lines changed: 163 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ locals {
1010
partition = try(data.aws_partition.current[0].partition, "")
1111

1212
oidc_providers = [for url in var.oidc_provider_urls : replace(url, "https://", "")]
13-
github_provider = coalesce(one(local.oidc_providers), "token.actions.githubusercontent.com")
1413
bitbucket_provider = one(local.oidc_providers)
1514
}
1615

@@ -26,8 +25,11 @@ data "aws_iam_policy_document" "this" {
2625
for_each = var.enable_oidc ? local.oidc_providers : []
2726

2827
content {
29-
effect = "Allow"
30-
actions = ["sts:AssumeRoleWithWebIdentity"]
28+
effect = "Allow"
29+
actions = [
30+
"sts:TagSession",
31+
"sts:AssumeRoleWithWebIdentity",
32+
]
3133

3234
principals {
3335
type = "Federated"
@@ -59,11 +61,22 @@ data "aws_iam_policy_document" "this" {
5961
for_each = length(var.oidc_audiences) > 0 ? local.oidc_providers : []
6062

6163
content {
62-
test = "StringLike"
64+
test = "StringEquals"
6365
variable = "${statement.value}:aud"
6466
values = var.oidc_audiences
6567
}
6668
}
69+
70+
# Generic conditions
71+
dynamic "condition" {
72+
for_each = var.condition
73+
74+
content {
75+
test = condition.value.test
76+
variable = condition.value.variable
77+
values = condition.value.values
78+
}
79+
}
6780
}
6881
}
6982

@@ -75,31 +88,57 @@ data "aws_iam_policy_document" "this" {
7588
sid = "GithubOidcAuth"
7689
actions = [
7790
"sts:TagSession",
78-
"sts:AssumeRoleWithWebIdentity"
91+
"sts:AssumeRoleWithWebIdentity",
7992
]
8093

8194
principals {
8295
type = "Federated"
83-
identifiers = ["arn:${local.partition}:iam::${local.account_id}:oidc-provider/${local.github_provider}"]
96+
identifiers = ["arn:${local.partition}:iam::${local.account_id}:oidc-provider/${var.github_provider}"]
8497
}
8598

8699
condition {
87100
test = "ForAllValues:StringEquals"
88-
variable = "token.actions.githubusercontent.com:iss"
89-
values = ["http://token.actions.githubusercontent.com"]
101+
variable = "${var.github_provider}:iss"
102+
values = ["https://${var.github_provider}"]
90103
}
91104

92105
condition {
93106
test = "ForAllValues:StringEquals"
94-
variable = "${local.github_provider}:aud"
107+
variable = "${var.github_provider}:aud"
95108
values = coalescelist(var.oidc_audiences, ["sts.amazonaws.com"])
96109
}
97110

98-
condition {
99-
test = "StringLike"
100-
variable = "${local.github_provider}:sub"
101-
# Strip `repo:` to normalize for cases where users may prepend it
102-
values = [for subject in var.oidc_subjects : "repo:${trimprefix(subject, "repo:")}"]
111+
dynamic "condition" {
112+
for_each = length(var.oidc_subjects) > 0 ? [1] : []
113+
114+
content {
115+
test = "StringEquals"
116+
variable = "${var.github_provider}:sub"
117+
# Strip `repo:` to normalize for cases where users may prepend it
118+
values = [for subject in var.oidc_subjects : "repo:${trimprefix(subject, "repo:")}"]
119+
}
120+
}
121+
122+
dynamic "condition" {
123+
for_each = length(var.oidc_wildcard_subjects) > 0 ? [1] : []
124+
125+
content {
126+
test = "StringLike"
127+
variable = "${var.github_provider}:sub"
128+
# Strip `repo:` to normalize for cases where users may prepend it
129+
values = [for subject in var.oidc_wildcard_subjects : "repo:${trimprefix(subject, "repo:")}"]
130+
}
131+
}
132+
133+
# Generic conditions
134+
dynamic "condition" {
135+
for_each = var.condition
136+
137+
content {
138+
test = condition.value.test
139+
variable = condition.value.variable
140+
values = condition.value.values
141+
}
103142
}
104143
}
105144
}
@@ -112,7 +151,7 @@ data "aws_iam_policy_document" "this" {
112151
sid = "BitbucketOidcAuth"
113152
actions = [
114153
"sts:TagSession",
115-
"sts:AssumeRoleWithWebIdentity"
154+
"sts:AssumeRoleWithWebIdentity",
116155
]
117156

118157
principals {
@@ -126,10 +165,35 @@ data "aws_iam_policy_document" "this" {
126165
values = coalescelist(var.oidc_audiences, ["sts.amazonaws.com"])
127166
}
128167

129-
condition {
130-
test = "StringLike"
131-
variable = "${local.bitbucket_provider}:sub"
132-
values = var.oidc_subjects
168+
dynamic "condition" {
169+
for_each = length(var.oidc_subjects) > 0 ? [1] : []
170+
171+
content {
172+
test = "StringEquals"
173+
variable = "${local.bitbucket_provider}:sub"
174+
values = var.oidc_subjects
175+
}
176+
}
177+
178+
dynamic "condition" {
179+
for_each = length(var.oidc_wildcard_subjects) > 0 ? [1] : []
180+
181+
content {
182+
test = "StringLike"
183+
variable = "${local.bitbucket_provider}:sub"
184+
values = var.oidc_wildcard_subjects
185+
}
186+
}
187+
188+
# Generic conditions
189+
dynamic "condition" {
190+
for_each = var.condition
191+
192+
content {
193+
test = condition.value.test
194+
variable = condition.value.variable
195+
values = condition.value.values
196+
}
133197
}
134198
}
135199
}
@@ -139,8 +203,13 @@ data "aws_iam_policy_document" "this" {
139203
for_each = var.enable_saml ? [1] : []
140204

141205
content {
142-
effect = "Allow"
143-
actions = compact(distinct(concat(["sts:AssumeRoleWithSAML"], var.saml_trust_actions)))
206+
effect = "Allow"
207+
actions = compact(distinct(concat(
208+
[
209+
"sts:TagSession",
210+
"sts:AssumeRoleWithSAML",
211+
],
212+
var.saml_trust_actions)))
144213

145214
principals {
146215
type = "Federated"
@@ -152,6 +221,17 @@ data "aws_iam_policy_document" "this" {
152221
variable = "SAML:aud"
153222
values = var.saml_endpoints
154223
}
224+
225+
# Generic conditions
226+
dynamic "condition" {
227+
for_each = var.condition
228+
229+
content {
230+
test = condition.value.test
231+
variable = condition.value.variable
232+
values = condition.value.values
233+
}
234+
}
155235
}
156236
}
157237

@@ -221,6 +301,68 @@ resource "aws_iam_role_policy_attachment" "this" {
221301
role = aws_iam_role.this[0].name
222302
}
223303

304+
################################################################################
305+
# IAM Role Inline policy
306+
################################################################################
307+
308+
locals {
309+
create_iam_role_inline_policy = var.create && length(var.inline_policy_statements) > 0
310+
}
311+
312+
data "aws_iam_policy_document" "inline" {
313+
count = local.create_iam_role_inline_policy ? 1 : 0
314+
315+
dynamic "statement" {
316+
for_each = var.inline_policy_statements != null ? var.inline_policy_statements : {}
317+
318+
content {
319+
sid = try(coalesce(statement.value.sid, statement.key))
320+
actions = statement.value.actions
321+
not_actions = statement.value.not_actions
322+
effect = statement.value.effect
323+
resources = statement.value.resources
324+
not_resources = statement.value.not_resources
325+
326+
dynamic "principals" {
327+
for_each = statement.value.principals != null ? statement.value.principals : []
328+
329+
content {
330+
type = principals.value.type
331+
identifiers = principals.value.identifiers
332+
}
333+
}
334+
335+
dynamic "not_principals" {
336+
for_each = statement.value.not_principals != null ? statement.value.not_principals : []
337+
338+
content {
339+
type = not_principals.value.type
340+
identifiers = not_principals.value.identifiers
341+
}
342+
}
343+
344+
dynamic "condition" {
345+
for_each = statement.value.condition != null ? statement.value.condition : []
346+
347+
content {
348+
test = condition.value.test
349+
values = condition.value.values
350+
variable = condition.value.variable
351+
}
352+
}
353+
}
354+
}
355+
}
356+
357+
resource "aws_iam_role_policy" "inline" {
358+
count = local.create_iam_role_inline_policy ? 1 : 0
359+
360+
role = aws_iam_role.this[0].name
361+
name = var.use_name_prefix ? null : var.name
362+
name_prefix = var.use_name_prefix ? "${var.name}-" : null
363+
policy = data.aws_iam_policy_document.inline[0].json
364+
}
365+
224366
################################################################################
225367
# IAM Instance Profile
226368
################################################################################

0 commit comments

Comments
 (0)