-
Notifications
You must be signed in to change notification settings - Fork 49
/
IAM-ExpireUsers-Template.yaml
336 lines (311 loc) · 10.2 KB
/
IAM-ExpireUsers-Template.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
---
AWSTemplateFormatVersion: '2010-09-09'
Description: Deploys Lambda to notify users when their AWS Creds are about to expire. Locks them out if they do expire.
Parameters:
# Lambda Deploy Params
pArtifactBucket:
Description: Bucket Holding Lambdas
Type: String
pArtifactPrefix:
Description: Directory where lambdas are
Type: String
Default: aws-security-automation-ExpireUsers
pLambdaVersion:
Description: VersionPath of the Lambda zip
Type: String
pExpireUsersLambdaZipFile:
Description: Filename of theLambda Zip
Type: String
Default: aws-security-automation-ExpireUsers.zip
# Function Info
pLambdaFunctionName:
Description: Name of the Lambda Function
Type: String
Default: aws-security-automation-ExpireIAMUsers
pLambdaAlias:
Description: Alias of this Lambda Function
Type: String
Default: MyAWSAccount
pAlarmTopicArn:
Description: SNS Topic the Cloudwatch Alarm will notify on invocation failures
Type: String
# Parameters sent to Lambda via Env vars
pActionTopicArn:
Description: SNS Topic to send Lockout actions to
Type: String
pGracePeriodInDays:
Description: How many days to send the user a warning email before the lockout occurs
Type: Number
Default: 14
pDisableUsers:
Description: Set to True if you want to disabled expired users
Type: String
Default: "false" # Be safe
pSendEmail:
Description: Set to True if SES is setup to allow you to email your user base
Type: String
Default: "false"
pFromAddress:
Description: Email address from which emails to users come. It should be monitored.
Type: String
Default: "My AWS Account Name <[email protected]>"
pEmailHeader:
Description: Preamble in the email you send users
Type: String
Default: "Company Policy requires passwords and access keys to be changed every 90 days."
pEmailFooter:
Description: Footer in the email you send users
Type: String
Default: "If you have any questions or need assistance please reply to this email."
Resources:
# Users who are locked out will be added to this group.
# Since Deny trumps any Allow, we must use a NotAction on the things we wish to allow
ExpiredUsersGroup:
Type: "AWS::IAM::Group"
Properties:
GroupName: UsersWithExpiredCredentials
Path: "/"
Policies:
- PolicyName: DenyNotManageMyCredentials
PolicyDocument:
Version: '2012-10-17'
Statement:
- Sid: DenyAllActionsButSome
Effect: Deny
NotAction:
- iam:*LoginProfile
- iam:CreateVirtualMFADevice
- iam:ListVirtualMFADevices
- iam:EnableMFADevice
- iam:ChangePassword
- iam:ListUsers
- iam:GetAccountPasswordPolicy
NotResource:
- !Join ['', ['arn:aws:iam::', !Ref 'AWS::AccountId', ':user/${aws:username}']]
- !Join ['', ['arn:aws:iam::', !Ref 'AWS::AccountId', ':mfa/${aws:username}']]
- Sid: DenyTheseIAMActionsOutRight
Effect: Deny
Action:
- iam:*SSHPublicKey*
- iam:*AccessKey*
- iam:*UserPolicy
- iam:CreateLoginProfile
- iam:DeactivateMFADevice
- iam:DeleteLoginProfile
- iam:List*UserPolicies
- iam:ListSigningCertificates
Resource: "*"
# Here we explictly allow the actions needed to configure MFA
# Only to the Resources necessary (the IAM user and said user's MFA)
- PolicyName: AllowManageMyCredentials
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- iam:*LoginProfile
- iam:*AccessKey*
- iam:*MFADevice
- iam:*SSHPublicKey*
- iam:ChangePassword
Resource:
- !Join ['', ['arn:aws:iam::', !Ref 'AWS::AccountId', ':user/${aws:username}']]
- !Join ['', ['arn:aws:iam::', !Ref 'AWS::AccountId', ':mfa/${aws:username}']]
- Effect: Allow
Action:
- iam:ListUsers
- iam:ListVirtualMFADevices
Resource:
- !Join ['', ['arn:aws:iam::', !Ref 'AWS::AccountId', ':user/*']]
- !Join ['', ['arn:aws:iam::', !Ref 'AWS::AccountId', ':mfa/']]
ExpireUsersLambdaRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- sts:AssumeRole
Path: /
ManagedPolicyArns:
# We need to read info about IAM Users
# This is probably too permissive.
- arn:aws:iam::aws:policy/IAMReadOnlyAccess
Policies:
- PolicyName: CloudWatchAllActions
# Is this policy needed?
PolicyDocument:
Version: '2012-10-17'
Statement:
- Action:
- cloudwatch:*
Effect: Allow
Resource: '*'
- PolicyName: logs
PolicyDocument:
Version: '2012-10-17'
Statement:
- Resource: '*'
Action:
- logs:*
Effect: Allow
- PolicyName: AddAndRemoveFromGroup
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- iam:AddUserToGroup
- iam:RemoveUserFromGroup
Resource: !GetAtt ExpiredUsersGroup.Arn
- PolicyName: EnableAndDisableAccessKeys
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- iam:UpdateAccessKey
Resource: "*"
- PolicyName: SendSESEmails
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- ses:SendEmail
Resource: "*"
- PolicyName: PublishToActionTopic
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- sns:Publish
Resource: !Ref pActionTopicArn
ExpireUsersLambda:
Type: AWS::Lambda::Function
Properties:
Description: Add Users who have allowed their Password Or API Crednetials to Expire to a blackhole Group
Runtime: python2.7
Handler: ExpireUsers.lambda_handler
Timeout: '80'
FunctionName: !Ref pLambdaFunctionName
Role: !GetAtt ExpireUsersLambdaRole.Arn
Code:
S3Bucket: !Ref pArtifactBucket
S3Key: !Sub ${pArtifactPrefix}/${pLambdaVersion}/${pExpireUsersLambdaZipFile}
Environment:
Variables:
BLACKHOLE_GROUPNAME: !Ref ExpiredUsersGroup
ACTION_TOPIC_ARN: !Ref pActionTopicArn
GRACE_PERIOD: !Ref pGracePeriodInDays
DISABLE_USERS: !Ref pDisableUsers
SEND_EMAIL: !Ref pSendEmail
FROM_ADDRESS: !Ref pFromAddress
EXPLANATION_FOOTER: !Ref pEmailFooter
EXPLANATION_HEADER: !Ref pEmailHeader
ExpireUsersLambdaAlias:
Type: AWS::Lambda::Alias
Properties:
FunctionName: !Ref ExpireUsersLambda
FunctionVersion: $LATEST
Name: !Ref pLambdaAlias
ExpireUsersLambdaInvocationRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- events.amazonaws.com
- sns.amazonaws.com
Action:
- sts:AssumeRole
Path: /
Policies:
- PolicyName: ExecuteRequireMfaLambda
PolicyDocument:
Version: '2012-10-17'
Statement:
- Action:
- lambda:InvokeFunction
Effect: Allow
Resource: !GetAtt ExpireUsersLambda.Arn
# Version One of this template will just lock out the users. Manual intervention is required to unlock
# IAMActivityRule:
# Type: AWS::Events::Rule
# Properties:
# Description: Send IAM Activity to ExpireUsers Lambda
# EventPattern:
# detail-type:
# - AWS API Call via CloudTrail
# detail:
# eventSource:
# - iam.amazonaws.com
# eventName:
# - EnableMFADevice
# - CreateLoginProfile
# - DeactivateMFADevice
# - DeleteAccessKey
# - UpdateAccessKey
# - UpdateLoginProfile
# - ChangePassword
# State: ENABLED
# RoleArn: !GetAtt ExpireUsersLambdaInvocationRole.Arn
# Targets:
# - Arn: !Ref ExpireUsersLambdaAlias
# Id: TargetFunctionV1
# ExpireUsersLambdaPermissionIAMActivityRule:
# Type: AWS::Lambda::Permission
# Properties:
# FunctionName: !GetAtt ExpireUsersLambda.Arn
# Principal: events.amazonaws.com
# SourceArn: !GetAtt IAMActivityRule.Arn
# Action: lambda:invokeFunction
ExpireUsersLambdaInvocationFailureAlarm:
Type: "AWS::CloudWatch::Alarm"
Properties:
ActionsEnabled: true
AlarmActions:
- !Ref pAlarmTopicArn
AlarmDescription: Send an alert if the ExpireUsersLambda throws invocation errors
AlarmName: !Sub "${pLambdaFunctionName}-InvocationFailureAlarm"
ComparisonOperator: GreaterThanThreshold
Dimensions:
- Name: FunctionName
Value: !Ref ExpireUsersLambda
EvaluationPeriods: 1
# InsufficientDataActions:
# - String
MetricName: Errors
Namespace: AWS/Lambda
# OKActions:
# - String
Period: 60
Statistic: Sum
Threshold: 0
# Unit: String
ExpireUsersLamabdaCronEvent:
Type: "AWS::Events::Rule"
Properties:
Description: !Sub "Execute the ${pLambdaFunctionName} on a scheduled basis"
RoleArn: !GetAtt ExpireUsersLambdaInvocationRole.Arn
ScheduleExpression: "cron(0 10 * * ? *)"
State: ENABLED
Targets:
- Arn: !GetAtt ExpireUsersLambda.Arn
Id: TargetFunctionV1
Outputs:
ExpireUsersLambda:
Value: !GetAtt ExpireUsersLambda.Arn
Description: ARN for the ExpireUsers Lambda
StackName:
Value: !Ref AWS::StackName
TemplateVersion:
Value: "0.1.0"