我有一个AWS Lambda函数,通过它的URL访问S3资源(即 https://s3-eu-west-1.amazonaws.com/bucketname/key )。
我在S3 Bucket上添加了一个Bucket Policy,允许我的Lambda Function访问S3 Bucket(通过Lambda Functions IAM Role)。此Bucket Policy如下所示:
{
"Version": "2012-10-17",
"Id": "Access control to S3 bucket",
"Statement": [
{
"Sid": "Allow Get and List Requests from IAM Role",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123412341234:role/role-name“
},
"Action": [
"s3:Get*",
"s3:List*"
],
"Resource": [
"arn:aws:s3:::bucket-name”,
"arn:aws:s3:::bucket-name/*"
]
}
]
}
当Lambda函数被触发器“自动”激活时,一切正常。但是当我手动测试Lambda函数时(通过AWS控制台),我收到403错误。
如果我然后将S3 Bucket Policy中的Principal更改为“*”,则会解决403异常。
我的猜测是手动触发Lambda函数时会使用不同的Principal,但我不知道这可能是什么。我已经尝试添加一个新策略,允许访问我的规范用户,但这不起作用。
有什么建议吗?
答案 0 :(得分:0)
如果您希望授予特定IAM用户/组/角色的权限,那么您应该直接在该用户/组/角色上添加权限,而不是将其作为特例添加到一个桶政策。
这可以使您的存储桶策略保持干净,减少特殊情况。
我建议:
以下是一个示例政策:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "BucketAccess",
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::my-bucket",
"arn:aws:s3:::my-bucket/*"
]
}
]
}
实际上,这是过于宽松,因为它允许Lambda函数在存储桶中执行任何(例如删除存储桶),因此您只应授予您知道Lambda函数需要的权限。
答案 1 :(得分:0)
我遇到了类似的问题,问题是我的政策没有考虑到Lambda在执行时承担角色的事实。我在Principal部分中添加了假定的角色,一切开始工作:
"Principal": {
"AWS": [
"arn:aws:sts::123412341234:assumed-role/role-name/function-name"
]
},
答案 2 :(得分:-1)
正如@JohnRotenstein所建议的,我删除了存储桶策略,而是实现了预先签名的URL。现在一切都很好。
Node.js中预签名URL生成的示例(URL有效期为360秒):
s3.getSignedUrl('getObject', {Bucket: bucket, Key: filename, Expires: 360})
在Java中(有效期为1小时):
private URL createSignedURL(String s3Bucket, String s3Key){
AmazonS3 s3client = AmazonS3ClientBuilder.defaultClient();
// Set expiration to 1 hour
java.util.Date expiration = new java.util.Date();
long msec = expiration.getTime();
msec += 1000 * 60 * 60;
expiration.setTime(msec);
// Generate signed key
GeneratePresignedUrlRequest generatePresignedUrlRequest =
new GeneratePresignedUrlRequest(s3Bucket, s3Key);
generatePresignedUrlRequest.setMethod(HttpMethod.GET);
generatePresignedUrlRequest.setExpiration(expiration);
// Return key
return s3client.generatePresignedUrl(generatePresignedUrlRequest);
}