Creating a Custom AWS Config Rule with a Lambda Function to Encrypt S3 Buckets
Tags: s3, awsconfig, security, automation
Published: 2023-10-12 06:02:09

In this detailed guide, we'll walk you through the process of creating a custom AWS Config Rule with a Lambda function to automatically encrypt S3 buckets if they are not encrypted when created or if their configuration is changed. This solution ensures that your S3 buckets remain secure by enforcing encryption policies.

**Architecture:**
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k2ituit29bhpir63ooic.png)

**Steps:**
**Step 1: Create a CloudFormation Template to Enable AWS Config Service**

```
AWSTemplateFormatVersion: 2010-09-09
Description: Enable AWS Config

Parameters:
  AllSupported:
    Type: String
    Default: False
    Description: Indicates whether to record all supported resource types.
    AllowedValues:
      - True  
      - False

  IncludeGlobalResourceTypes:
    Type: String
    Default: False
    Description: Indicates whether AWS Config records all supported global resource types.
    AllowedValues:
      - True
      - False

  ResourceTypes:
    Type: List<String>
    Description: A list of valid AWS resource types to include in this recording group, such as AWS::EC2::Instance or AWS::CloudTrail::Trail.
    Default: AWS::S3::Bucket

Conditions:
  IsAllSupported: !Equals
    - !Ref AllSupported
    - True

Resources:
  ConfigRecorderRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - config.amazonaws.com
            Action:
              - sts:AssumeRole
      Path: /
      ManagedPolicyArns:
        - !Sub "arn:${AWS::Partition}:iam::aws:policy/service-role/AWS_ConfigRole"

  ConfigRecorder:
    Type: AWS::Config::ConfigurationRecorder
    Properties:
      RoleARN: !GetAtt ConfigRecorderRole.Arn
      RecordingGroup:
        AllSupported: !Ref AllSupported
        IncludeGlobalResourceTypes: !Ref IncludeGlobalResourceTypes
        ResourceTypes: !If
          - IsAllSupported
          - !Ref AWS::NoValue
          - !Ref ResourceTypes
```
**Step 2: Create a CloudFormation Template to Create a Custom AWS Config Rule with a Lambda Function**

```
Resources:
  # Give permission to AWS Config to call/use the lambda function
  ConfigPermissionToCallLambda: 
    Type: AWS::Lambda::Permission
    Properties: 
      FunctionName: !GetAtt EncryptS3Bucket.Arn
      Action: "lambda:InvokeFunction"
      Principal: "config.amazonaws.com"
  
  # Create the Custom Config Rule
  ConfigRule:
    Type: 'AWS::Config::ConfigRule'
    Properties:
        ConfigRuleName: s3-bucket-encrypted
        Scope:
            ComplianceResourceTypes:
            - 'AWS::S3::Bucket'
        Source:
            # Owner: Indicates whether AWS or the customer owns and manages the AWS Config rule.
            Owner: CUSTOM_LAMBDA
            # SourceDetails: Provides the source and the event type that causes AWS Config to evaluate your AWS resources.
            SourceDetails: 
                - EventSource: "aws.config"
                  MessageType: "ConfigurationItemChangeNotification"
            # For custom rules, the identifier is the AWS Resource ARN of the rule's AWS Lambda function
            SourceIdentifier: !GetAtt EncryptS3Bucket.Arn
    DependsOn: ConfigPermissionToCallLambda

  # Grant lambda access to S3 buckets and AWS Config
  LambdaIamRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
            - Effect: Allow
              Principal:
                Service:
                - lambda.amazonaws.com
              Action:
                - 'sts:AssumeRole'            
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaRole
        - arn:aws:iam::aws:policy/AmazonS3FullAccess            
      Policies:
        - PolicyName: ConfigPolicy
          PolicyDocument:
            Statement:
                - Effect: Allow
                  Action:
                    - 'config:Put*'
                  Resource: '*'
    
  # Lambda Function that encrypts the S3 Buckets
  EncryptS3Bucket: 
    Type: AWS::Lambda::Function
    Properties: 
      Code: 
        ZipFile: 
          !Sub |
            const aws = require('aws-sdk');
            const config = new aws.ConfigService();
            exports.handler = (event, callback) => {
                // Lambda function code here
            };
      Handler: "index.handler"
      Runtime: nodejs12.x
      Timeout: 30
      Role: 
        Fn::GetAtt: 
          - LambdaIamRole
          - Arn
```

**Step 3: Deploy and Test the Configuration**
Once you've created the CloudFormation stacks, deploy them to AWS. This will set up the AWS Config rule and Lambda function. Test the setup by creating new S3 buckets and changing their encryption configurations. The custom Lambda function should automatically encrypt S3 buckets that are not encrypted.

**Conclusion:**
By following these steps and using AWS Config Rules with a Lambda function, you can ensure that your S3 buckets remain encrypted, enhancing the security of your AWS environment. This automation helps enforce encryption policies and maintain a secure AWS infrastructure.

Feel free to customize the Lambda function further to meet your specific needs and security policies.

Happy AWS Configuring! 💡🔒 #AWS #Security #Automation