-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathtemplate.yml
168 lines (149 loc) · 5.29 KB
/
template.yml
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
---
AWSTemplateFormatVersion: '2010-09-09'
Parameters:
LambdaMemorySize:
Type: Number
Default: 512
AllowedValues:
- 128
- 256
- 512
Description: Its a short running program it wont cost much no matter what you select.
LoggingLevel:
Type: String
Default: WARNING
AllowedValues:
- WARNING
- DEBUG
Description: If you are experiencing issues. Select debug for more logging.
Resources:
LambdaFunctionCloudWatchEvent:
Type: AWS::Events::Rule
Properties:
Name: awsMfaEntityAlreadyExistsFixTrigger
Description: "Entity Already Exists Exception"
EventPattern:
source:
- aws.iam
detail-type:
- AWS API Call via CloudTrail
detail:
eventName:
- CreateVirtualMFADevice
errorCode:
- EntityAlreadyExistsException
Targets:
- Id: TriggerLambda
Arn:
Fn::GetAtt:
- LambdaFunction
- Arn
State: ENABLED
LambdaTriggerPermission:
Type: "AWS::Lambda::Permission"
Properties:
Action: 'lambda:InvokeFunction'
FunctionName:
Fn::GetAtt:
- LambdaFunction
- Arn
Principal: 'events.amazonaws.com'
SourceArn:
Fn::GetAtt:
- LambdaFunctionCloudWatchEvent
- Arn
LambdaFunction:
Type: AWS::Lambda::Function
DependsOn:
- LambdaFunctionExecutionRole
Properties:
FunctionName: awsMfaEntityAlreadyExistsFix
Handler: index.lambda_handler
Role:
Fn::GetAtt:
- LambdaFunctionExecutionRole
- Arn
MemorySize:
Ref: LambdaMemorySize
Code:
ZipFile: |
import logging
import os
import boto3
logger = logging.getLogger(__name__)
LOGLEVEL = os.environ.get('LOGLEVEL', 'WARNING').upper()
logging.basicConfig(level=LOGLEVEL) # Set logging level based on env variable LOGLEVEL. Defaults to Warning.
def lambda_handler(event, context):
event_detail = event["detail"] # As cloudwatch sends us some useless stuff we just want the detail
error_code = event_detail.get("errorCode", None)
# Does a quick check to make sure that the program was run against the correct exception. Even though the cloudwatch
# event should do this. This is just in case.
if error_code != "EntityAlreadyExistsException" or error_code is None:
logging.error(f"Application ran against event that was not the correct exception please check the cloudwatch."
f"event. Error was {error_code}")
raise SystemExit # Exit
account_id = event_detail["userIdentity"]["accountId"]
mfa_device_name = event_detail["requestParameters"]["virtualMFADeviceName"]
mfa_device_path = event_detail["requestParameters"]["path"]
logger.info(f"MFA Device Information - Name {mfa_device_name}, path: {mfa_device_path}, accountId: {account_id}")
mfa_device_arn = form_mfa_arn(account_id, mfa_device_name, mfa_device_path) # Get the MFA device arn
delete_mfa_device(mfa_device_arn) # Delete it
return
def form_mfa_arn(account_id: str, device_name: str, device_path: str) -> str:
"""Forms the MFA arn string
Args:
account_id (str): The account id where the MFA device lives
device_name (str): The mfa devices name (Generally the username but can be different if using API/CLI)
device_path (str): The mfa device path (Generally just / but can be different if using CLI/API)
Returns:
The full MFA arn for the device as a string
"""
return f"arn:aws:iam::{account_id}:mfa{device_path}{device_name}"
def delete_mfa_device(mfa_arn: str):
"""Deletes the MFA device
Args:
mfa_arn (str): The virtual MFA devices arn
"""
res = boto3.client("iam").delete_virtual_mfa_device(
SerialNumber=mfa_arn
)
logger.debug(f"Delete Virtual MFA Device Response : {res}")
return
Runtime: python3.7
Timeout: 10
Environment:
Variables:
LOGLEVEL: WARNING
LambdaFunctionExecutionRole:
Type: AWS::IAM::Role
Properties:
RoleName: awsMfaEntityAlreadyExistsFix-Role
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- sts:AssumeRole
Path: "/"
Policies:
- PolicyName: AWSLambdaBasicExecutionRole
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource: "*"
- PolicyName: DeleteVirtualMFADevice
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- "iam:DeleteVirtualMFADevice"
Resource: "*"