我正在尝试使用 CDK 包添加 S3 事件通知。此 CDK 包在账户 A 中部署了一个 lambda 函数,每次将 S3 对象添加到账户 B 的“testfolder/”路径中时都会触发
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)
我在账户 A 的存储桶策略中为 lambda 角色添加了 s3:PutBucketNotification 和 s3:GetBucketNotification,并且 lambda 角色附加了 AmazonS3FullAccess 和 AWSLambdaBasicExecutionRole 策略。
当我注释掉 .addEventNotification 部分时,代码中的其他所有内容都有效,但当我添加 .addEventNotification 时,它会抛出错误 - 错误:调用 PutBucketNotificationConfiguration 操作时发生错误(AccessDenied):访问被拒绝。
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"
}
]
}
AWS CDK 中的 S3 存储桶通知是通过 Lambda 支持的自定义资源添加的。这个自定义资源就是需要跨账户访问的。
解决此问题最直接的方法是在账户 B 的存储桶策略中指定整个账户 A 作为主体。这是跨账户访问的常见模式 - 资源策略通常仅包含账户名称来封装实现细节另一边。