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

1k Views Asked by At

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.
1

There are 1 best solutions below

13
On BEST ANSWER

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)