我正在尝试使用AWS Lambda将对象从assets.myapp.com
下的Account-A
S3存储桶备份到backup-assets.myapp.com
下的Account-B
S3存储桶,但我得到了Access Denied
无论我使用的是IAM
还是Bucket Policy
配置。
我有一个名为Backup-S3-Object
的Lambda函数,它被s3:PutObject
存储桶上的assets.myapp.com
事件触发器触发。
所需的结果是Backup-S3-Object
函数将使用适用于Javascript的AWS-SDK执行s3.copyObject
到backup-assets.myapp.com
。
Lambda代码
var aws = require('aws-sdk');
var s3 = new aws.S3({ apiVersion: '2006-03-01' });
exports.backupObject = function(event, context, callback) {
var data = event.Records[0];
var sourceBucket = data.s3.bucket.name;
var targetBucket = 'backup-' + data.s3.bucket.name;
var key = data.s3.object.key;
console.log('BACKUP: ' + sourceBucket + '/' + key + ' to ' + targetBucket);
s3.copyObject({
Bucket : targetBucket,
CopySource : sourceBucket + '/' + key,
Key : key,
ACL : 'private',
ServerSideEncryption : 'AES256'
}, function(error, data) {
if (error) return context.done(error);
return context.done(null, 'Successful backup of ' + sourceBucket + '/' + key);
});
};
Lambda角色S3政策
我为Backup-S3-Lambda-Role
分配了我的Lambda函数的以下策略。这允许Lambda函数从List
下的任何存储桶访问Get
或Account-A
任何对象,这是源帐户。因此,此策略将允许Lambda函数从assets.myapp.com
获取对象,这是源存储桶。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:ListBucketVersions",
"s3:GetObject",
"s3:GetObjectVersion"
],
"Resource": [
"arn:aws:s3:::*"
]
}
]
}
backup-assets.myapp.com
广告管理政策
然后,在Account-B
下,我将backup-assets.myapp.com
附加了以下存储桶策略,该策略旨在允许在Account-A
下运行的Lambda函数写入backup-assets.myapp.com
Account-B
广告管理系统
{
"Version": "2008-10-17",
"Statement": [
{
"Sid": "Allow PUT from Account-A Lambda function",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::ACCOUNT-A-NUMBER-HERE:role/Backup-S3-Lambda-Role"
},
"Action": "s3:PutObject",
"Resource": [
"arn:aws:s3:::backup-assets.myapp.com",
"arn:aws:s3:::backup-assets.myapp.com/*"
]
}
]
}
发生了什么?
assets.myapp.com
水桶上的触发器发射得很好。它触发Backup-S3-Object
Lambda函数,函数逻辑能够确定要复制的正确的存储桶名称和对象密钥,但它始终以Access Denied
失败。
我已经使用相同的设置进行了测试并转移到同样位于Account-A
下的其他存储桶,并且工作正常。所以问题显然在于跨帐户权限,但我尝试过的任何工作都没有。
我还尝试在CanonicalID
广告管理系统政策中使用Account-A
Principal
作为backup-assets.myapp.com
,但仍然得到Access Denied
作为结果错误
我尝试使用"AWS": "arn:aws:iam::ACCOUNT-A-NUMBER-HERE:root"
作为主体,同样的错误。
任何帮助?
解决方案:如下面的Matt所述,解决方案是您需要在Lambda角色策略中包含
s3:PutObject
权限。 这对我来说有点奇怪,但总体思路是任何 您在您的Bucket Policy中授予Lambda角色的权限 还必须在您的域下的Lambda策略中复制目标存储桶 来源帐户。似乎Lambda角色完全被采用 当您在Bucket Policy中引用它时。为此我已经补充说 我的Lambda角色的第二个内联策略允许s3:PutObject
backup-assets.myapp.com
下的Account-B
广告管理系统。这是不允许的 Lambda函数写入任何源桶,但确实如此 允许它写入备份桶。
答案 0 :(得分:2)
我看到两个可能的问题。
尝试将s3:PutObject
添加到您的政策中,如下所示:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:ListBucketVersions",
"s3:GetObject",
"s3:GetObjectVersion",
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::*"
]
}
]
}
或者,如果您希望继续将Lambda函数限制为读取仅在源存储桶上访问,则可以向Lambda角色添加第二个策略,允许其{ {1}}在备份存储桶上,将备份存储桶命名为资源,如下所示:
s3:PutObject
现在,只需让您的目标帐户访问源存储桶:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::backup-assets.myapp.com",
"arn:aws:s3:::backup-assets.myapp.com/*"
]
}
]
}
复制工作完成后,您可以尝试重新添加角色。