Enforce S3 Bucket Encryption


It happens most of the times that users/developers create S3 buckets and leave them unencrypted. That leads to security violation and your data is at risk. There are number of scenarios to counter this issue. The best one is to publish S3 creation template to Service Catalog and let users create buckets using Service Catalog product. However, in this article I'm going to explain how to create a workflow which detects unencrypted buckets and encrypt them automatically.
Let's first create an SNS topic and call it s3encryption and note down it's ARN. Then create a Lambda function using following code written in Python.

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
import json
import boto3
import logging

def lambda_handler(event, context):
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)
    
    s3 = boto3.client('s3')
    sns = boto3.resource('sns')
    topic = sns.Topic('arn:aws:sns:us-east-1:<accountid:s3encryption')
    
    bucketName = str(event['detail']['requestParameters']['bucketName'])
    logger.info('got event{}'.format(event))
    eventdetails='\nBucket Name: ' + str(event['detail']['requestParameters']['bucketName'])
    eventdetails+='\nCreated by: '+ str(event['detail']['userIdentity']['arn'])
    eventdetails+='\nBucket is now encrypted and Server Side Logging Enabled'
    
    s3.put_bucket_encryption(
            Bucket = bucketName,
            ServerSideEncryptionConfiguration = {
                'Rules': [
                        {
                            'ApplyServerSideEncryptionByDefault': {
                                'SSEAlgorithm': 'AES256'
                            }
                        }
                    ]
            }
        )
    response = topic.publish(
        Message=  'Event Details:'+str(eventdetails),
        Subject= 'New Bucket Created',
        MessageStructure='String',
        MessageAttributes={
            's3bucket': {
                'DataType': 'String',
                'StringValue': 'Bucket Properties'
    
            }
        }
    )

Next, create a CloudWatch Event Rule with eventName set to CreateBucket and eventSource set to s3.amazonaws.com. Finally set the target to Lambda function created before.