Skip to content

Commit 57a5d70

Browse files
authored
feat: Allow multiple MFA devices and users to manage MFA devices (#313)
1 parent aa7ddba commit 57a5d70

File tree

1 file changed

+107
-44
lines changed

1 file changed

+107
-44
lines changed

modules/iam-group-with-policies/policies.tf

Lines changed: 107 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -9,83 +9,146 @@ locals {
99
partition = data.aws_partition.current.partition
1010
}
1111

12+
# Allows MFA-authenticated IAM users to manage their own credentials on the My security credentials page
13+
# https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_examples_aws_my-sec-creds-self-manage.html
1214
data "aws_iam_policy_document" "iam_self_management" {
1315
statement {
14-
sid = "AllowSelfManagement"
16+
sid = "AllowViewAccountInfo"
17+
18+
effect = "Allow"
19+
20+
actions = [
21+
"iam:GetAccountPasswordPolicy",
22+
"iam:ListVirtualMFADevices"
23+
]
24+
25+
resources = ["*"]
26+
}
27+
28+
statement {
29+
sid = "AllowManageOwnPasswords"
1530

1631
effect = "Allow"
1732

1833
actions = [
1934
"iam:ChangePassword",
35+
"iam:GetUser"
36+
]
37+
38+
resources = ["arn:${local.partition}:iam::${local.aws_account_id}:user/$${aws:username}"]
39+
}
40+
41+
statement {
42+
sid = "AllowManageOwnAccessKeys"
43+
44+
effect = "Allow"
45+
46+
actions = [
2047
"iam:CreateAccessKey",
21-
"iam:CreateLoginProfile",
22-
"iam:CreateVirtualMFADevice",
2348
"iam:DeleteAccessKey",
24-
"iam:DeleteLoginProfile",
25-
"iam:DeleteVirtualMFADevice",
26-
"iam:EnableMFADevice",
27-
"iam:GenerateCredentialReport",
28-
"iam:GenerateServiceLastAccessedDetails",
29-
"iam:Get*",
30-
"iam:List*",
31-
"iam:ResyncMFADevice",
32-
"iam:UpdateAccessKey",
33-
"iam:UpdateLoginProfile",
34-
"iam:UpdateUser",
35-
"iam:UploadSigningCertificate",
36-
"iam:UploadSSHPublicKey",
37-
"iam:TagUser",
38-
"iam:ListUserTags",
39-
"iam:UntagUser",
49+
"iam:ListAccessKeys",
50+
"iam:UpdateAccessKey"
4051
]
4152

42-
# Allow for both users with "path" and without it
43-
resources = [
44-
"arn:${local.partition}:iam::${local.aws_account_id}:user/*/$${aws:username}",
45-
"arn:${local.partition}:iam::${local.aws_account_id}:user/$${aws:username}",
46-
"arn:${local.partition}:iam::${local.aws_account_id}:mfa/$${aws:username}",
53+
resources = ["arn:${local.partition}:iam::${local.aws_account_id}:user/$${aws:username}"]
54+
}
55+
56+
statement {
57+
sid = "AllowManageOwnSigningCertificates"
58+
59+
effect = "Allow"
60+
61+
actions = [
62+
"iam:DeleteSigningCertificate",
63+
"iam:ListSigningCertificates",
64+
"iam:UpdateSigningCertificate",
65+
"iam:UploadSigningCertificate"
4766
]
67+
68+
resources = ["arn:${local.partition}:iam::${local.aws_account_id}:user/$${aws:username}"]
4869
}
4970

5071
statement {
51-
sid = "AllowIAMReadOnly"
72+
sid = "AllowManageOwnSSHPublicKeys"
73+
74+
effect = "Allow"
5275

5376
actions = [
54-
"iam:Get*",
55-
"iam:List*",
77+
"iam:DeleteSSHPublicKey",
78+
"iam:GetSSHPublicKey",
79+
"iam:ListSSHPublicKeys",
80+
"iam:UpdateSSHPublicKey",
81+
"iam:UploadSSHPublicKey"
5682
]
5783

58-
resources = ["*"]
59-
effect = "Allow"
84+
resources = ["arn:${local.partition}:iam::${local.aws_account_id}:user/$${aws:username}"]
6085
}
6186

62-
# Allow to deactivate MFA only when logging in with MFA
6387
statement {
64-
sid = "AllowDeactivateMFADevice"
88+
sid = "AllowManageOwnGitCredentials"
89+
90+
effect = "Allow"
91+
92+
actions = [
93+
"iam:CreateServiceSpecificCredential",
94+
"iam:DeleteServiceSpecificCredential",
95+
"iam:ListServiceSpecificCredentials",
96+
"iam:ResetServiceSpecificCredential",
97+
"iam:UpdateServiceSpecificCredential"
98+
]
99+
100+
resources = ["arn:${local.partition}:iam::${local.aws_account_id}:user/$${aws:username}"]
101+
}
102+
103+
statement {
104+
sid = "AllowManageOwnVirtualMFADevice"
105+
106+
effect = "Allow"
107+
108+
actions = [
109+
"iam:CreateVirtualMFADevice"
110+
]
111+
112+
resources = ["arn:${local.partition}:iam::${local.aws_account_id}:mfa/*"]
113+
}
114+
115+
statement {
116+
sid = "AllowManageOwnUserMFA"
65117

66118
effect = "Allow"
67119

68120
actions = [
69121
"iam:DeactivateMFADevice",
122+
"iam:EnableMFADevice",
123+
"iam:ListMFADevices",
124+
"iam:ResyncMFADevice"
70125
]
71126

72-
# Allow for both users with "path" and without it
73-
resources = [
74-
"arn:${local.partition}:iam::${local.aws_account_id}:user/*/$${aws:username}",
75-
"arn:${local.partition}:iam::${local.aws_account_id}:user/$${aws:username}",
76-
"arn:${local.partition}:iam::${local.aws_account_id}:mfa/$${aws:username}",
127+
resources = ["arn:${local.partition}:iam::${local.aws_account_id}:user/$${aws:username}"]
128+
129+
}
130+
131+
statement {
132+
sid = "DenyAllExceptListedIfNoMFA"
133+
134+
effect = "Deny"
135+
136+
not_actions = [
137+
"iam:CreateVirtualMFADevice",
138+
"iam:EnableMFADevice",
139+
"iam:GetUser",
140+
"iam:ListMFADevices",
141+
"iam:ListVirtualMFADevices",
142+
"iam:ResyncMFADevice",
143+
"sts:GetSessionToken"
77144
]
78145

79-
condition {
80-
test = "Bool"
81-
variable = "aws:MultiFactorAuthPresent"
82-
values = ["true"]
83-
}
146+
resources = ["*"]
84147

85148
condition {
86-
test = "NumericLessThan"
87-
variable = "aws:MultiFactorAuthAge"
88-
values = ["3600"]
149+
test = "BoolIfExists"
150+
variable = "aws:MultiFactorAuthPresent"
151+
values = ["false"]
89152
}
90153
}
91154
}

0 commit comments

Comments
 (0)