Asim
Asim

Reputation: 47

CDK - An error occurred (AccessDenied) when calling the PutBucketNotificationConfiguration operation:

I am trying to add S3 event notification using CDK package. This CDK package deploys a lambda function in Account A to trigger everytime a S3 object is added into Account B's "testfolder/" path

const source_bucket = s3.Bucket.fromBucketName(this, 'source_bucket', bucket_in_account_B);

  const lambdaPermission = new CfnPermission(this, "S3InvokePermission", {
      action: "lambda:InvokeFunction",
      principal: "s3.amazonaws.com",
      sourceAccount: accountId,
      sourceArn: 'arn:aws:s3:::' + bucket_in_account_B,
      functionName: this.lambdaFunction.functionName
    });

source_bucket.addEventNotification(s3.EventType.OBJECT_CREATED, new s3n.LambdaDestination(this.lambdaFunction), {
      prefix: 'testfolder/',
      suffix: '.tsv');

source_bucket.grantReadWrite(this.lambdaFunction)

I have s3:PutBucketNotification and s3:GetBucketNotification in my bucket policy in Account A for the lambda role and the lambda role has AmazonS3FullAccess and AWSLambdaBasicExecutionRole policy attached.

Everything else in my code works when I comment out .addEventNotification part but when I add .addEventNotification it throws error - Error: An error occurred (AccessDenied) when calling the PutBucketNotificationConfiguration operation: Access Denied.

Bucket Policy:
{
            "Sid": "AllowBucketNotification",
            "Effect": "Allow",
            "Principal": {
                "AWS": "my_lambda_role"
            },
            "Action": [
                "s3:Get*",
                "s3:List*",
                "s3:PutBucketNotification"
            ],
            "Resource": [
                "arn:aws:s3:::bucket_in_account_B",
                "arn:aws:s3:::bucket_in_account_B/*"
            ]
        }




Lambda Role Policy: This role also has AmazonS3FullAccess and AWSLambdaBasicExecutionRole  policy attached. 
        {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Action": [
                    "s3:GetObject*",
                    "s3:GetBucket*",
                    "s3:List*",
                    "s3:DeleteObject*",
                    "s3:PutObject",
                    "s3:PutObjectLegalHold",
                    "s3:PutObjectRetention",
                    "s3:PutObjectTagging",
                    "s3:PutObjectVersionTagging",
                    "s3:Abort*"
                ],
                "Resource": [
                    "arn:aws:s3:::bucket_in_account_B",
                    "arn:aws:s3:::bucket_in_account_B/*"
                ],
                "Effect": "Allow"
            }
        ]
    }


{
    "Statement": [
        {
            "Action": [
                "sts:AssumeRole"
            ],
            "Resource": "*",
            "Effect": "Allow"
        }
    ]
}

Upvotes: 2

Views: 604

Answers (1)

gshpychka
gshpychka

Reputation: 11588

S3 Bucket notifications in AWS CDK are added via a Lambda-backed custom resource. This custom resource is what needs the cross-account access.

The most straightforward way to fix this is to specify the entire account A as the principal in the Bucket policy in Account B. This is a common pattern with cross-account access - resource policies typically only include the account name to encapsulate implementation details on the other side.

Upvotes: 1

Related Questions