Skip to content

Commit 0e7b829

Browse files
make deny optional. allow users to change passwords without mfa
1 parent b427717 commit 0e7b829

File tree

3 files changed

+95
-102
lines changed

3 files changed

+95
-102
lines changed

README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ module enforce_mfa {
6464
policy_name = "managed-mfa-enforce"
6565
account_id = data.aws_caller_identity.current.id
6666
groups = [aws_iam_group.support.name]
67-
manage_own_password_without_mfa = true
6867
manage_own_signing_certificates = true
6968
manage_own_ssh_public_keys = true
7069
manage_own_git_credentials = true
@@ -96,9 +95,9 @@ module enforce_mfa {
9695
|------|-------------|------|---------|:--------:|
9796
| account\_id | Account identification. (Optional, default '\*') | `string` | `"*"` | no |
9897
| groups | Enforce MFA for the members in these groups. (Optional, default '[]') | `list(string)` | `[]` | no |
98+
| manage\_explicit\_deny | Manage explicit deny. | `bool` | `false` | no |
9999
| manage\_own\_access\_keys | Allow a new AWS secret access key and corresponding AWS access key ID for the specified user. | `bool` | `false` | no |
100100
| manage\_own\_git\_credentials | Allow managing git credentials. | `bool` | `false` | no |
101-
| manage\_own\_password\_without\_mfa | Whethehr password management without mfa is allowd | `bool` | `true` | no |
102101
| manage\_own\_signing\_certificates | Allow managing signing certificates. | `bool` | `false` | no |
103102
| manage\_own\_ssh\_public\_keys | Allow managing ssh public keys. | `bool` | `false` | no |
104103
| path | Path in which to create the policy. (Optional, default '/') | `string` | `"/"` | no |

data.tf

Lines changed: 88 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,27 @@
11
data aws_iam_policy_document this {
2+
3+
statement {
4+
sid = "AllowBasicVisiiblityWithoutMfa"
5+
effect = "Allow"
6+
actions = [
7+
"iam:ListUsers",
8+
"iam:GetAccountSummary",
9+
"iam:ListAccountAliases",
10+
"iam:ListVirtualMFADevices",
11+
"iam:GetAccountPasswordPolicy"
12+
]
13+
resources = ["*", ]
14+
}
15+
216
statement {
317
sid = "MFAPersonalCreate"
418
effect = "Allow"
519
actions = [
620
"iam:CreateVirtualMFADevice",
21+
"iam:DeleteVirtualMFADevice"
722
]
823
resources = [
924
"arn:aws:iam::${var.account_id}:mfa/&{aws:username}",
10-
"arn:aws:iam::${var.account_id}:user/&{aws:username}",
1125
]
1226
}
1327

@@ -16,7 +30,6 @@ data aws_iam_policy_document this {
1630
effect = "Allow"
1731
actions = [
1832
"iam:DeleteVirtualMFADevice",
19-
"iam:DeactivateMFADevice",
2033
]
2134
resources = [
2235
"arn:aws:iam::${var.account_id}:mfa/&{aws:username}",
@@ -32,7 +45,6 @@ data aws_iam_policy_document this {
3245
statement {
3346
effect = "Allow"
3447
actions = [
35-
"iam:EnableMFADevice",
3648
"iam:GetUser",
3749
"iam:ListGroupsForUser",
3850
]
@@ -42,59 +54,75 @@ data aws_iam_policy_document this {
4254
}
4355

4456
statement {
45-
sid = "AllowIndividualUserToManageTheirOwnMFA"
4657
effect = "Allow"
4758
actions = [
48-
"iam:CreateVirtualMFADevice",
49-
"iam:DeleteVirtualMFADevice",
50-
"iam:EnableMFADevice",
51-
"iam:ResyncMFADevice",
59+
"iam:ListGroups",
5260
]
5361
resources = [
54-
"arn:aws:iam::${var.account_id}:user/&{aws:username}",
55-
"arn:aws:iam::${var.account_id}:mfa/&{aws:username}",
62+
"arn:aws:iam::${var.account_id}:group/",
5663
]
5764
}
5865

5966
statement {
6067
effect = "Allow"
6168
actions = [
62-
"iam:ListGroups",
69+
"iam:ListGroupPolicies",
70+
"iam:ListAttachedGroupPolicies",
6371
]
6472
resources = [
65-
"arn:aws:iam::${var.account_id}:group/",
73+
"arn:aws:iam::${var.account_id}:group/*",
6674
]
6775
}
6876

6977
statement {
78+
sid = "AllowToListOnlyOwnMFA"
7079
effect = "Allow"
7180
actions = [
72-
"iam:ListGroupPolicies",
73-
"iam:ListAttachedGroupPolicies",
81+
"iam:ListMFADevices",
7482
]
7583
resources = [
76-
"arn:aws:iam::${var.account_id}:group/*",
84+
"arn:aws:iam::*:mfa/*",
85+
"arn:aws:iam::*:user/&{aws:username}"
7786
]
87+
7888
}
7989

8090
statement {
91+
sid = "AllowManageOwnUserMFA"
8192
effect = "Allow"
8293
actions = [
8394
"iam:ChangePassword",
95+
"iam:CreateLoginProfile",
8496
"iam:UpdateLoginProfile",
97+
"iam:ListAccessKeys",
8598
"iam:UpdateUser",
8699
"iam:ListAttachedUserPolicies",
87100
"iam:ListSSHPublicKeys",
88101
"iam:ListAccessKeys",
89102
"iam:GetLoginProfile",
90-
"iam:ListMFADevices",
91-
"iam:ListVirtualMFADevices",
92103
]
93104
resources = [
94105
"arn:aws:iam::${var.account_id}:user/&{aws:username}",
95106
]
96107
}
97108

109+
statement {
110+
sid = "AllowUserToManageOwnMFA"
111+
effect = "Allow"
112+
113+
actions = [
114+
"iam:CreateVirtualMFADevice",
115+
"iam:DeleteVirtualMFADevice",
116+
"iam:EnableMFADevice",
117+
"iam:ResyncMFADevice"
118+
]
119+
120+
resources = [
121+
"arn:aws:iam::*:mfa/&{aws:username}",
122+
"arn:aws:iam::*:user/&{aws:username}"
123+
]
124+
}
125+
98126
statement {
99127
sid = "KeysAndCertificates"
100128
effect = "Allow"
@@ -108,25 +136,36 @@ data aws_iam_policy_document this {
108136
]
109137
}
110138

139+
statement {
140+
sid = "AllowUserToDeactivateOnlyOwnMFAWhenUsingMFA"
141+
effect = "Allow"
142+
actions = [
143+
"iam:DeactivateMFADevice"
144+
]
145+
resources = [
146+
"arn:aws:iam::*:mfa/&{aws:username}",
147+
"arn:aws:iam::*:user/&{aws:username}"
148+
]
149+
condition {
150+
test = "Bool"
151+
variable = "aws:MultiFactorAuthPresent"
152+
values = ["true"]
153+
}
154+
}
155+
111156
statement {
112157
sid = "AllowBasicVisiiblityWhenLoggedInWithMFA"
113158
effect = "Allow"
114159
actions = [
115-
"iam:GetAccountSummary",
116-
"iam:ListAccountAliases",
117-
"iam:GetAccountSummary",
118160
"iam:ListUserTags",
119161
"iam:ListGroupsForUser",
120162
"iam:ListPolicies",
121-
"iam:ListUsers",
122163
"iam:GetGroup",
123164
"iam:GenerateServiceLastAccessedDetails",
124165
"iam:ListUserPolicies",
125166
"iam:GetUser",
126167
"iam:ListServiceSpecificCredentials",
127168
"iam:ListAttachedUserPolicies",
128-
"iam:ListVirtualMFADevices",
129-
"iam:ListMFADevices"
130169
]
131170
resources = ["*", ]
132171
condition {
@@ -136,77 +175,6 @@ data aws_iam_policy_document this {
136175
}
137176
}
138177

139-
statement {
140-
sid = "BlockMostAccessUnlessSignedInWithMFA"
141-
effect = "Deny"
142-
not_actions = [
143-
"iam:CreateVirtualMFADevice",
144-
"iam:DeleteVirtualMFADevice",
145-
"iam:ListVirtualMFADevices",
146-
"iam:EnableMFADevice",
147-
"iam:ResyncMFADevice",
148-
"iam:ListAccountAliases",
149-
"iam:ListUsers",
150-
"iam:ListSSHPublicKeys",
151-
"iam:ListAccessKeys",
152-
"iam:ListServiceSpecificCredentials",
153-
"iam:ListMFADevices",
154-
"iam:GetAccountSummary",
155-
"sts:GetSessionToken"
156-
]
157-
resources = ["*"]
158-
condition {
159-
test = "BoolIfExists"
160-
variable = "aws:MultiFactorAuthPresent"
161-
values = ["false", ]
162-
}
163-
}
164-
165-
statement {
166-
sid = "BlockReadActionsUnlessSignedInWithMFA"
167-
effect = "Deny"
168-
169-
actions = [
170-
"iam:ListMFADevices",
171-
"iam:ListVirtualMFADevices",
172-
"iam:ListUsers",
173-
]
174-
175-
resources = [
176-
"arn:aws:iam::${var.account_id}:user/",
177-
"arn:aws:iam::${var.account_id}:user/&{aws:username}",
178-
"arn:aws:iam::${var.account_id}:mfa/",
179-
"arn:aws:iam::${var.account_id}:mfa/&{aws:username}",
180-
]
181-
182-
condition {
183-
test = "BoolIfExists"
184-
variable = "aws:MultiFactorAuthPresent"
185-
values = ["false", ]
186-
}
187-
}
188-
189-
dynamic "statement" {
190-
for_each = var.manage_own_password_without_mfa ? [] : [1]
191-
192-
content {
193-
sid = "ChangePasswordOnlyIfMFASet"
194-
effect = "Deny"
195-
actions = [
196-
"iam:ChangePassword",
197-
"iam:CreateLoginProfile",
198-
]
199-
resources = [
200-
"arn:aws:iam::${var.account_id}:user/&{aws:username}"
201-
]
202-
condition {
203-
test = "BoolIfExists"
204-
variable = "aws:MultiFactorAuthPresent"
205-
values = ["false", ]
206-
}
207-
}
208-
}
209-
210178
dynamic "statement" {
211179
for_each = var.manage_own_access_keys ? [1] : []
212180

@@ -302,4 +270,30 @@ data aws_iam_policy_document this {
302270
}
303271
}
304272
}
273+
274+
# Deny
275+
276+
dynamic "statement" {
277+
for_each = var.manage_explicit_deny ? [1] : []
278+
279+
content {
280+
sid = "DenyAllExceptListedIfNoMFA"
281+
effect = "Deny"
282+
actions = [
283+
"iam:CreateVirtualMFADevice",
284+
"iam:EnableMFADevice",
285+
"iam:GetUser",
286+
"iam:ListMFADevices",
287+
"iam:ListVirtualMFADevices",
288+
"iam:ResyncMFADevice",
289+
"sts:GetSessionToken"
290+
]
291+
resources = ["*"]
292+
condition {
293+
test = "BoolIfExists"
294+
variable = "aws:MultiFactorAuthPresent"
295+
values = ["false", ]
296+
}
297+
}
298+
}
305299
}

variables.tf

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,6 @@ variable "account_id" {
1010
type = string
1111
}
1212

13-
variable "manage_own_password_without_mfa" {
14-
default = true
15-
description = "Whethehr password management without mfa is allowd"
16-
type = bool
17-
}
18-
1913
variable "manage_own_access_keys" {
2014
default = false
2115
description = "Allow a new AWS secret access key and corresponding AWS access key ID for the specified user."
@@ -40,6 +34,12 @@ variable "manage_own_git_credentials" {
4034
type = bool
4135
}
4236

37+
variable "manage_explicit_deny" {
38+
default = false
39+
description = "Manage explicit deny."
40+
type = bool
41+
}
42+
4343

4444
variable "groups" {
4545
default = []

0 commit comments

Comments
 (0)