99import json
1010import boto3
1111import botocore
12+ import os
13+ import datetime
14+
15+ NOTIFIER_ENABLED = os .environ ["notifierEnabled" ]
16+ NOTIFIER_FUNCTION = os .environ ["notifierFnName" ]
1217
1318def remediate_violation_acl (bucket_name ):
1419 """
@@ -37,7 +42,6 @@ def remediate_violation_acl(bucket_name):
3742 )
3843 log_message = {"action" : "PutBucketAcl" , "bucketName" : bucket_name , "accessControlPolicy" : json .dumps (acp )}
3944 print json .dumps (log_message )
40- return True
4145 except botocore .exceptions .ClientError as client_error :
4246 if client_error .response ['Error' ]['Code' ] == 'OperationAborted' :
4347 log_message = {
@@ -53,7 +57,8 @@ def remediate_violation_acl(bucket_name):
5357 "bucketName" : bucket_name ,
5458 "accessControlPolicy" : "Unexpected error: {0}" .format (client_error )}
5559 print json .dumps (log_message )
56- return False
60+ return False , log_message
61+ return True , log_message
5762
5863
5964def remediate_violation_policy (bucket_name ):
@@ -94,7 +99,47 @@ def remediate_violation_policy(bucket_name):
9499 "bucketName" : bucket_name ,
95100 "accessControlPolicy" : "Unexpected error: {0}" .format (client_error )}
96101 print json .dumps (log_message )
97- return False
102+ return False , log_message
103+ return True , log_message
104+
105+
106+ def notify (log_message , source , account_id ):
107+ """
108+ Calls the Notifier Lambda function to notify slack that action has been taken.
109+ :param log_message: The log message string
110+ """
111+ #pylint: disable=unused-variable
112+ lambda_client = boto3 .client ('lambda' )
113+
114+ message = ""
115+ if log_message ["action" ] == "PutBucketPolicy" :
116+ template = "A \" *\" Principal in an Allow policy statement was fixed by applying an updated bucket policy to {0}:\n ```\n {1}\n ```"
117+ bucket_policy = json .loads (log_message ["bucketPolicy" ])
118+ bucket_policy = json .dumps (bucket_policy , indent = 4 , sort_keys = True )
119+ message = template .format (log_message ["bucketName" ], bucket_policy )
120+ elif log_message ["action" ] == "PutBucketAcl" :
121+ template = "An AllUsers or AllAuthenticatedUsers grant was fixed by applying an updated access control policy to {0}:\n ```\n {1}\n ```"
122+ acp = json .loads (log_message ["accessControlPolicy" ])
123+ acp = json .dumps (acp , indent = 4 , sort_keys = True )
124+ message = template .format (log_message ["bucketName" ], acp )
125+
126+ payload = {
127+ "remediationSource" : source ,
128+ "resourceId" : log_message ["bucketName" ],
129+ "resourceType" : "AWS::S3::Bucket" ,
130+ "action" : log_message ["action" ],
131+ "actionCompleteTime" : datetime .datetime .utcnow ().isoformat () + "+00:00" ,
132+ "awsAccountId" : account_id ,
133+ "message" : message
134+ }
135+
136+ payload_bytes = json .dumps (payload ).encode ('utf-8' )
137+
138+ invoke_response = lambda_client .invoke (
139+ FunctionName = NOTIFIER_FUNCTION ,
140+ InvocationType = 'Event' ,
141+ Payload = payload_bytes
142+ )
98143 return True
99144
100145
@@ -126,11 +171,19 @@ def lambda_handler(event, context):
126171
127172 success = False
128173 if violation_type == "S3_BUCKET_PUBLIC_ACL" :
129- success = remediate_violation_acl (bucket_name )
174+ result = remediate_violation_acl (bucket_name )
130175 elif violation_type == "S3_BUCKET_PUBLIC_POLICY" :
131- success = remediate_violation_policy (bucket_name )
176+ result = remediate_violation_policy (bucket_name )
177+
178+ success = result [0 ]
179+ message = result [1 ]
132180
133181 if success :
134182 dequeue_message (sqs_url , receipt_handle )
135-
183+ if NOTIFIER_ENABLED == "true" :
184+ if (message ["action" ] == "PutBucketPolicy" or message ["action" ] == "PutBucketAcl" ):
185+ fn_name = context .function_name
186+ account_id = context .invoked_function_arn .split (":" )[4 ]
187+ notify (message , fn_name , account_id )
188+
136189 return True
0 commit comments