123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 |
- #! /usr/bin/env python3
- import boto3
- import json
- import logging
- import os
- import re
- logger = logging.getLogger('FCM')
- def determine_compliance(ec2client, detail):
- if ec2client.get_ebs_encryption_by_default().get('EbsEncryptionByDefault') is not True:
- logger.info('Determined not to be compliant')
- return False
- logger.debug('Determined to be compliant')
- return True
- def report(compliant, detail):
- return
- def remediate(detail):
- return
- def lambda_handler(event, context):
- init_logger()
- # Extract the useful stuff out of the input data
- if isinstance(event, (str, )):
- event = json.loads(event)
- body = json.loads(event['Records'][0]['body'])
- detail = body.get('detail', {})
- logger.debug(f'Inbound event: {json.dumps(event, default=str)}')
- logger.debug(f'Inbound body: {json.dumps(body, default=str)}')
- logger.debug(f'Inbound detail: {json.dumps(detail, default=str)}')
- if prevent_loop(detail):
- logger.info('Probable loop detected. Exiting.')
- return {}
- account = body['account']
- region = body['region']
- # Get a session on the destination account
- logger.info(f'Assuming role into account {account} in region {region}')
- client = boto3.client('sts')
- assumed_role_obj = client.assume_role(
- RoleArn=f'arn:aws:iam::{account}:role/fcm/fcm-analysis-EbsEncryptionByDefault',
- RoleSessionName='fcm-analysis-EbsEncryptionByDefault',
- DurationSeconds=900
- )
- credentials = assumed_role_obj['Credentials']
- logger.debug(f'Creating ec2client with credentials: {json.dumps(credentials, default=str)}')
- ec2client = boto3.client(
- 'ec2',
- aws_access_key_id = credentials['AccessKeyId'],
- aws_secret_access_key = credentials['SecretAccessKey'],
- aws_session_token = credentials['SessionToken'],
- region_name = region
- )
- compliant = determine_compliance(ec2client, detail)
- report(compliant, detail)
- if not compliant:
- remediate(detail)
- return True
- def init_logger():
- global logger
- try:
- logger.setLevel(os.environ['LOGLEVEL'])
- except:
- logger.setLevel('DEBUG')
- logger.warning('Logging level not set or set to invalid value.')
- def prevent_loop(detail):
- arn = r'^arn:aws:sts::\d{12}:assumed-role/fcm-'
- useragent = r'exec-env/AWS_Lambda'
- if re.search(arn, detail.get('userIdentity', {}).get('arn', '')):
- # We're in an fcm assumed role
- if re.search(useragent, detail.get('userAgent', '')):
- return True
- return False
- if __name__ == "__main__":
- # For testing only:
- handler = logging.StreamHandler()
- formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
- handler.setFormatter(formatter)
- logger.addHandler(handler)
- event = {
- "Records": [
- {
- "messageId": "39647048-eb52-4393-a39a-fda3a8d3fdfc",
- "receiptHandle": "AQEBXWJnH5nZjA5CYGceVCf/S8Rxy0MK0leslGeCZy5BNzejyqUNfmItzpc2D8AiapnByQk5AmR1UDMtfm6eptnEuKerBebtw0zJDXa/ed5joiWYKo8v2evl8Kun8dj77MRr70vsVqXenvSY5neNUSmtwKcnfNpsxL1qBYA7fatI/xLSOy08i4C8jsntJLA93Xag1IN0/+xiuzkYoBHm5oFf24Ed1EZ5izKJsWjKQc9bAzd4EKSuUXbNpFjW8WWDcr1c9Sdi6NS0F2P/qFRNinwCYRENicQZ5KSNISxqZgLe+nBfQRipn1kGMMNsgBfGgonOakkFB7KI1GGXFspxEYIPrIcUUJt7XwYKgvqUOF/gKezOdAPpVOSoAYkVdV4BjWxCTbw8L03wuDsqe0ihanB6oE/6GTachRsPg0WiSQcq2tw=",
- "body": "{\"version\":\"0\",\"id\":\"8e098047-456d-45b1-9ac4-2c2571bafcbd\",\"detail-type\":\"AWS API Call via CloudTrail\",\"source\":\"aws.ec2\",\"account\":\"082012130604\",\"time\":\"2019-09-26T19:37:50Z\",\"region\":\"us-east-2\",\"resources\":[],\"detail\":{\"eventVersion\":\"1.05\",\"userIdentity\":{\"type\":\"Root\",\"principalId\":\"082012130604\",\"arn\":\"arn:aws:iam::082012130604:root\",\"accountId\":\"082012130604\",\"accessKeyId\":\"ASIARGGCNZUWBA2LEEP3\",\"sessionContext\":{\"sessionIssuer\":{},\"webIdFederationData\":{},\"attributes\":{\"mfaAuthenticated\":\"true\",\"creationDate\":\"2019-09-26T13:53:54Z\"}}},\"eventTime\":\"2019-09-26T19:37:50Z\",\"eventSource\":\"ec2.amazonaws.com\",\"eventName\":\"DisableEbsEncryptionByDefault\",\"awsRegion\":\"us-east-2\",\"sourceIPAddress\":\"99.56.213.129\",\"userAgent\":\"console.ec2.amazonaws.com\",\"requestParameters\":{\"DisableEbsEncryptionByDefaultRequest\":{}},\"responseElements\":{\"DisableEbsEncryptionByDefaultResponse\":{\"xmlns\":\"http://ec2.amazonaws.com/doc/2016-11-15/\",\"ebsEncryptionByDefault\":false,\"requestId\":\"5e6d6a10-a7b9-4e55-9dd3-c04ec7db7198\"}},\"requestID\":\"5e6d6a10-a7b9-4e55-9dd3-c04ec7db7198\",\"eventID\":\"014d99f8-ac9b-41c6-8d8a-a7bb1dffd20a\",\"eventType\":\"AwsApiCall\"}}",
- "attributes": {
- "ApproximateReceiveCount": "1",
- "SentTimestamp": "1569526676382",
- "SenderId": "AIDAJQR6QDGQ7PATMSYEY",
- "ApproximateFirstReceiveTimestamp": "1569526676385"
- },
- "messageAttributes": {},
- "md5OfBody": "41bfacdf79a8139308b1790eac435955",
- "eventSource": "aws:sqs",
- "eventSourceARN": "arn:aws:sqs:us-east-2:082012130604:fcm-analysis-EbsEncryptionByDefault",
- "awsRegion": "us-east-2"
- }
- ]
- }
- lambda_handler(event = event, context={})
|