5
5
import json
6
6
import logging
7
7
8
- from utils import (
9
- is_scheduled_notification ,
10
- check_required_parameters ,
11
- flatten_dict ,
12
- check_guardrail_requirement_by_cloud_usage_profile ,
13
- get_cloud_profile_from_tags ,
14
- GuardrailType ,
15
- GuardrailRequirementType ,
16
- )
8
+ from utils import is_scheduled_notification , check_required_parameters , flatten_dict , check_guardrail_requirement_by_cloud_usage_profile , get_cloud_profile_from_tags , GuardrailType , GuardrailRequirementType
17
9
from boto_util .organizations import get_account_tags
18
10
from boto_util .client import get_client
19
11
from boto_util .config import build_evaluation , submit_evaluations
@@ -33,7 +25,7 @@ def subscription_is_confirmed(sns_client, subscription_arn):
33
25
attributes = response .get ("Attributes" )
34
26
logger .info ("Subscription attributes: %s" , attributes )
35
27
36
- if attributes is None :
28
+ if attributes == None :
37
29
return False
38
30
39
31
return attributes .get ("PendingConfirmation" ) == "false"
@@ -52,7 +44,7 @@ def subscription_is_confirmed(sns_client, subscription_arn):
52
44
53
45
def rule_matches_against_cb_role_identity (rule_event_pattern , cb_role_arn ):
54
46
logger .info ("rule_event_pattern: %s" , rule_event_pattern )
55
- if rule_event_pattern is None :
47
+ if rule_event_pattern == None :
56
48
return False
57
49
58
50
event_pattern_dict = json .loads (rule_event_pattern )
@@ -64,31 +56,23 @@ def rule_matches_against_cb_role_identity(rule_event_pattern, cb_role_arn):
64
56
) and "Role" in ep_detail .get ("userIdentity.sessionContext.sessionIssuer.type" , [])
65
57
66
58
67
- def get_role_arn (iam_client , cb_role_pattern : str ) -> str | None :
68
- """
69
- aws iam list-roles --query "Roles[?contains(RoleName, 'CloudBrokering')].[RoleName, Arn]"
70
- """
59
+ def get_role_arn (iam_client , cb_role : str ) -> str | None :
71
60
try :
72
- paginator = iam_client .get_paginator ("list_roles" )
73
- matched_roles = []
74
-
75
- for page in paginator .paginate ():
76
- for role in page ["Roles" ]:
77
- if cb_role_pattern in role ["RoleName" ]:
78
- matched_roles .append (role )
79
-
80
- if not matched_roles :
81
- return None
82
-
83
- # Return the ARN of the first matched role
84
- return matched_roles [0 ]["Arn" ]
61
+ response = iam_client .get_role (RoleName = cb_role )
62
+ return response .get ("Role" ).get ("Arn" )
85
63
except botocore .exceptions .ClientError as ex :
86
- ex .response ["Error" ]["Message" ] = "Error listing or matching roles."
87
- ex .response ["Error" ]["Code" ] = "InternalError"
64
+ if "NoSuchEntity" in ex .response ["Error" ]["Code" ]:
65
+ return None
66
+ elif "ServiceFailure" in ex .response ["Error" ]["Code" ]:
67
+ ex .response ["Error" ]["Message" ] = "get_role operation failed due to a Service Failure error."
68
+ else :
69
+ ex .response ["Error" ]["Message" ] = "InternalError"
70
+ ex .response ["Error" ]["Code" ] = "InternalError"
88
71
raise ex
89
72
90
73
91
74
def check_cb_role (cloud_trail_client , cb_role , event , aws_account_id ):
75
+ """Checks cloudtrail events to see if the CloudBroker role has been changed. Build evaluation based on discovery."""
92
76
93
77
role_change_events = [
94
78
"DeleteRolePolicy" ,
@@ -133,8 +117,8 @@ def check_rule_sns_target_is_setup(sns_client, event_bridge_client, rule, event)
133
117
134
118
for target in targets :
135
119
logger .info ("Checking rule target: %s" , target )
136
- target_arn : str = target .get ("Arn" )
137
120
# is target an SNS input transformer?
121
+ target_arn : str = target .get ("Arn" )
138
122
if target_arn .startswith ("arn:aws:sns:" ):
139
123
# yes, get a list of topic subscriptions
140
124
subscriptions = list_all_sns_subscriptions_by_topic (sns_client , target_arn )
@@ -184,6 +168,7 @@ def lambda_handler(event, context):
184
168
execution_role_name = rule_parameters .get ("ExecutionRoleName" )
185
169
audit_account_id = rule_parameters .get ("AuditAccountID" , "" )
186
170
aws_account_id = event ["accountId" ]
171
+ is_not_audit_account = aws_account_id != audit_account_id
187
172
188
173
evaluations = []
189
174
@@ -192,60 +177,44 @@ def lambda_handler(event, context):
192
177
aws_sns_client = get_client ("sns" , aws_account_id , execution_role_name )
193
178
aws_cloud_trail_client = get_client ("cloudtrail" , aws_account_id , execution_role_name )
194
179
aws_iam_client = get_client ("iam" , aws_account_id , execution_role_name )
195
-
180
+
196
181
# Check cloud profile
197
182
tags = get_account_tags (get_client ("organizations" , assume_role = False ), aws_account_id )
198
183
cloud_profile = get_cloud_profile_from_tags (tags )
199
184
gr_requirement_type = check_guardrail_requirement_by_cloud_usage_profile (GuardrailType .Guardrail4 , cloud_profile )
200
-
185
+
201
186
# If the guardrail is recommended
202
187
if gr_requirement_type == GuardrailRequirementType .Recommended :
203
- return submit_evaluations (
204
- aws_config_client ,
188
+ return submit_evaluations (aws_config_client , event , [build_evaluation (
189
+ aws_account_id ,
190
+ "COMPLIANT" ,
205
191
event ,
206
- [
207
- build_evaluation (
208
- aws_account_id ,
209
- "COMPLIANT" ,
210
- event ,
211
- gr_requirement_type = gr_requirement_type ,
212
- )
213
- ],
214
- )
192
+ gr_requirement_type = gr_requirement_type
193
+ )])
215
194
# If the guardrail is not required
216
195
elif gr_requirement_type == GuardrailRequirementType .Not_Required :
217
- return submit_evaluations (
218
- aws_config_client ,
196
+ return submit_evaluations (aws_config_client , event , [build_evaluation (
197
+ aws_account_id ,
198
+ "NOT_APPLICABLE" ,
219
199
event ,
220
- [
221
- build_evaluation (
222
- aws_account_id ,
223
- "NOT_APPLICABLE" ,
224
- event ,
225
- gr_requirement_type = gr_requirement_type ,
226
- )
227
- ],
228
- )
229
-
200
+ gr_requirement_type = gr_requirement_type
201
+ )])
202
+
203
+ rules_are_compliant = False
230
204
rules = list_all_event_bridge_rules (aws_event_bridge_client )
231
- cb_role_pattern = rule_parameters ["IAM_Role_Name" ]
205
+ cb_role = rule_parameters ["IAM_Role_Name" ]
232
206
233
- # Now we lookup the CloudBroker role by partial match
234
- cb_role_arn = get_role_arn (aws_iam_client , cb_role_pattern )
207
+ cb_role_arn = get_role_arn (aws_iam_client , cb_role )
235
208
236
209
if not cb_role_arn :
237
210
compliance_type = "NON_COMPLIANT"
238
- annotation = f"Cloud Broker Role containing ' { cb_role_pattern } ' in the name was not found."
211
+ annotation = f"Cloud Broker Role with name ' { cb_role } ' not found."
239
212
evaluation = build_evaluation (aws_account_id , compliance_type , event , annotation = annotation )
240
213
logger .info (f"{ compliance_type } : { annotation } " )
241
214
submit_evaluations (aws_config_client , event , [evaluation ])
242
215
return
243
216
244
- cb_rules = [
245
- rule
246
- for rule in rules
247
- if rule_matches_against_cb_role_identity (rule .get ("EventPattern" ), cb_role_arn )
248
- ]
217
+ cb_rules = [rule for rule in rules if rule_matches_against_cb_role_identity (rule .get ("EventPattern" ), cb_role_arn )]
249
218
250
219
if len (cb_rules ) == 0 :
251
220
evaluations .append (
@@ -257,7 +226,6 @@ def lambda_handler(event, context):
257
226
)
258
227
)
259
228
else :
260
- rules_are_compliant = False
261
229
for rule in cb_rules :
262
230
logger .info (f"Checking rule: { rule } " )
263
231
rule_evaluation = check_rule_sns_target_is_setup (aws_sns_client , aws_event_bridge_client , rule , event )
@@ -266,8 +234,7 @@ def lambda_handler(event, context):
266
234
evaluations .append (rule_evaluation )
267
235
268
236
if rules_are_compliant :
269
- extracted_role_name = cb_role_arn .split ("/" )[- 1 ] if "/" in cb_role_arn else cb_role_arn
270
- evaluations .append (check_cb_role (aws_cloud_trail_client , extracted_role_name , event , aws_account_id ))
237
+ evaluations .append (check_cb_role (aws_cloud_trail_client , cb_role , event , aws_account_id ))
271
238
else :
272
239
evaluations .append (
273
240
build_evaluation (
@@ -278,4 +245,4 @@ def lambda_handler(event, context):
278
245
)
279
246
)
280
247
281
- submit_evaluations (aws_config_client , event , evaluations )
248
+ submit_evaluations (aws_config_client , event , evaluations )
0 commit comments