amazon-web-servicesaws-lambdaamazon-cloudwatchamazon-cloudwatch-events

Getting an error with this lambda function that is triggered by the createbucket event


I set up a Cloudwatch Event CreateBucket that triggers this automatic policy generating script:

import json

s3 = boto3.client('s3')

def lambda_handler(event, context):

    # Get bucket name from the S3 event
    bucket_name = event['Records'][0]['s3']['bucket']['name']


    # Create a bucket policy
    bucket_policy =json.dumps({
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "MustBeEncryptedAtRest",
            "Effect": "Deny",
            "Principal": "*",
            "Action": "s3:PutObject",
            "Resource": [
                "arn:aws:s3:::{bucket_name}",
                "arn:aws:s3:::{bucket_name}/*"
            ],
            "Condition": {
                "StringNotEquals": {
                    "s3:x-amz-server-side-encryption": [
         
                        "aws:kms"
                    ]
                }
            }
        },
        {
            "Sid": "MustBeEncryptedInTransit",
            "Effect": "Deny",
            "Principal": "*",
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::{bucket_name}",
                "arn:aws:s3:::{bucket_name}/*"
            ],
            "Condition": {
                "Bool": {
                    "aws:SecureTransport": "false"
                    }
            }
        } ] })


    # Set the new policy
    s3.put_bucket_policy(Bucket=bucket_name, Policy=bucket_policy)

This lambda function should run and place this policy in the created bucket. However, it isnt running properly and testing through lambda interface give me this error:

  "stackTrace": [
    [
      "/var/task/lambda_function.py",
      9,
      "lambda_handler",
      "bucket_name = event['Records'][0]['s3']['bucket']['name']"
    ]
  ],
  "errorType": "KeyError",
  "errorMessage": "'Records'"
}

I need that policy to be attached to a new bucket everytime, no matter the name, but cant seem to figure out why it isnt working

EDIT::

  File "/var/task/lambda_function.py", line 10, in lambda_handler
    bucket_name = event['details']['requestParameters']['bucketName']
KeyError: 'details'```

Is the new error i get.

Solution

  • The structure you’re using is not correct for the event, in fact AWS have examples of events in their documentation.

    The real event looks like the below json

    {
        "version": "0",
        "id": "36eb8523-97d0-4518-b33d-ee3579ff19f0",
        "detail-type": "AWS API Call via CloudTrail",
        "source": "aws.s3",
        "account": "123456789012",
        "time": "2016-02-20T01:09:13Z",
        "region": "us-east-1",
        "resources": [],
        "detail": {
            "eventVersion": "1.03",
            "userIdentity": {
                "type": "Root",
                "principalId": "123456789012",
                "arn": "arn:aws:iam::123456789012:root",
                "accountId": "123456789012",
                "sessionContext": {
                    "attributes": {
                        "mfaAuthenticated": "false",
                        "creationDate": "2016-02-20T01:05:59Z"
                    }
                }
            },
            "eventTime": "2016-02-20T01:09:13Z",
            "eventSource": "s3.amazonaws.com",
            "eventName": "CreateBucket",
            "awsRegion": "us-east-1",
            "sourceIPAddress": "100.100.100.100",
            "userAgent": "[S3Console/0.4]",
            "requestParameters": {
                "bucketName": "bucket-test-iad"
            },
            "responseElements": null,
            "requestID": "9D767BCC3B4E7487",
            "eventID": "24ba271e-d595-4e66-a7fd-9c16cbf8abae",
            "eventType": "AwsApiCall"
        }
    }
    

    To resolve the error your Lambda needs to use this structure for accessing the bucket name property.

    To do this update your code to assign the bucket_name variable like the below.

    bucket_name = event['detail']['requestParameters']['bucketName']
    

    The above event should be used as the event to test.

    The working function is below

    import json
    import boto3
    
    s3 = boto3.client('s3')
    
    def lambda_handler(event, context):
        # Get bucket name from the S3 event
        print(event)
    
        bucket_name = event['detail']['requestParameters']['bucketName']
    
        # Create a bucket policy
        bucket_policy =json.dumps({
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Sid": "MustBeEncryptedAtRest",
                    "Effect": "Deny",
                    "Principal": "*",
                    "Action": "s3:PutObject",
                    "Resource": [
                        "arn:aws:s3:::{}".format(bucket_name),
                        "arn:aws:s3:::{}/*".format(bucket_name)
                    ],
                    "Condition": {
                        "StringNotEquals": {
                            "s3:x-amz-server-side-encryption": [
                                "AES256",
                                "aws:kms"
                            ]
                        }
                    }
                },
                {
                    "Sid": "MustBeEncryptedInTransit",
                    "Effect": "Deny",
                    "Principal": "*",
                    "Action": "s3:*",
                    "Resource": [
                        "arn:aws:s3:::{}".format(bucket_name),
                        "arn:aws:s3:::{}/*".format(bucket_name)
                    ],
                    "Condition": {
                        "Bool": {
                            "aws:SecureTransport": "false"
                            }
                    }
                } ] })
    
    
        # Set the new policy
        s3.put_bucket_policy(Bucket=bucket_name, Policy=bucket_policy)