如何正确设置 IAM 执行角色和存储桶策略以使 lambda 写入 public 读取 S3 存储桶?
How to properly setup an IAM execution role and a bucket policy for getting lambda writing to a public read S3 bucket?
对于上下文,我正在使用无服务器框架,所以发生了一些事情:
- 创建了一个带有一些附加策略的角色,一个 lambda 函数将其分配为执行角色。 S3 政策是(列出更相关的政策):
ListBucket
到存储桶 ARN 作为资源
GetObject
、PutObject
DeleteObjet
到存储桶 ARN 作为前缀为 /*
的资源
- 我正在使用 Cloudformation 资源语法创建存储桶,我设置了 public 读取策略以便将其用作静态网站主机。
- 我还在 S3 存储桶策略中包含另一个策略声明,我在其中分配写入操作并将执行角色 ARN 设置为委托人。
我得到以下 iamRoleStatements
部分:
- Effect: "Allow"
Action:
- "s3:ListBucket"
Resource:
- Fn::Join:
- ""
- - "arn:aws:s3:::"
- Ref: StaticSiteBucket
- Effect: "Allow"
Action:
- "s3:GetObject"
- "s3:PutObject"
- "s3:DeleteObject"
- "s3:GetObjectVersionTagging"
- "s3:PutObjectVersionTagging"
Resource:
- Fn::Join:
- ""
- - "arn:aws:s3:::"
- Ref: StaticSiteBucket
- "/*"
我实际上可以确认它为生成的角色生成了以下策略:
{
"Action": [
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::bucket-name-here"
],
"Effect": "Allow"
},
{
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject",
"s3:GetObjectVersionTagging",
"s3:PutObjectVersionTagging"
],
"Resource": [
"arn:aws:s3:::bucket-name-here/*"
],
"Effect": "Allow"
}
有了这个,我 运行 lambda 函数在那个桶上执行 putObject
。得到一个'Access denied error'
,所以我想如果桶本身需要允许写入怎么办,所以我在桶策略中包含了一个写语句:
StaticSiteBucket:
Type: AWS::S3::Bucket
Properties:
AccessControl: PublicRead
BucketName: ${self:service}-static-site-${self:provider.stage}
WebsiteConfiguration:
IndexDocument: index.html
StaticSiteBucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket:
Ref: StaticSiteBucket
PolicyDocument:
Statement:
- Sid: PublicReadGetObject
Effect: Allow
Principal: "*"
Action:
- s3:GetObject
Resource:
Fn::Join: [
"", [
"arn:aws:s3:::",
{
"Ref": "StaticSiteBucket"
},
"/*"
]
]
- Sid: AllowLambdaRoleWrite
Effect: Allow
Action:
- "s3:GetObject"
- "s3:PutObject"
- "s3:DeleteObject"
- "s3:GetObjectVersionTagging"
- "s3:PutObjectVersionTagging"
Principal:
AWS:
- Fn::GetAtt: [ IamRoleLambdaExecution, Arn ]
Resource:
Fn::Join:
- ""
- - "arn:aws:s3:::"
- Ref: StaticSiteBucket
- "/*"
在 S3 存储桶中生成以下策略:
{
"Version": "2008-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::bucket-name-here/*"
},
{
"Sid": "AllowLambdaRoleWrite",
"Effect": "Allow",
"Principal": {
"AWS": "<role-arn>"
},
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject",
"s3:GetObjectVersionTagging",
"s3:PutObjectVersionTagging"
],
"Resource": "arn:aws:s3:::bucket-name-here/*"
}
]
}
所以,我试过几句话:
- 允许角色有写权限,运气不好
- 从存储桶策略向该角色附加写入权限,失败
我错过了什么?
需要考虑的一些想法:
- 策略中不需要委托人 (lambda.amazonaws.com)。委托人已经出现在无服务器创建的角色中(至少在默认情况下是这样)。很可能现在它可以工作了,因为你给了它所有的权限。
- 您可能需要 ListBucket。不是因为它是严格需要的,而是因为它可能掩盖了另一个问题。看到这个 excellent response。事实上,当你把没有星号的桶的名称放在资源部分时,可能是因为这个。
- 文件小吗?对于大文件,您可能会触发多部分,这也需要其他放置权限。
- 您是否要标记或放置额外的 ACL 权限或所有者?这也需要额外的权限。
因此,就我而言,我缺少的是:
- 我必须包括
getObjectTagging
和 putObjectTagging
操作。
对于有类似问题的人。阅读下面的内容!
从课程中吸取教训(我花了一天半的时间坚持这一点)并意识到 Whosebug 是经验和知识的宝库。
我要指出:
- 确定您的代码正在执行哪些 API 操作,然后转到文档并进行检查。一些操作act on buckets while other on objects
- 在我的例子中,我可以在存储桶上删除任何额外的策略声明,换句话说,
- 执行角色是获得权力的角色。
- 我无法做到这一点,但如果有更明确的错误日志的方法,至少在 aws-sdk 节点的库中,将节省大量时间。 Stacktrace 还不够。欢迎提出建议。
这是我的 StaticSiteBucket 资源声明现在的样子:
- Effect: "Allow"
Action:
- "s3:ListBucket"
Resource:
- Fn::Join:
- ""
- - "arn:aws:s3:::"
- Ref: StaticSiteBucket
- Effect: "Allow"
Action:
- "s3:GetObject"
- "s3:PutObject"
- "s3:DeleteObject"
- "s3:GetObjectTagging"
- "s3:PutObjectTagging"
Resource:
- Fn::Join:
- ""
- - "arn:aws:s3:::"
- Ref: StaticSiteBucket
- "/*"
对于上下文,我正在使用无服务器框架,所以发生了一些事情:
- 创建了一个带有一些附加策略的角色,一个 lambda 函数将其分配为执行角色。 S3 政策是(列出更相关的政策):
ListBucket
到存储桶 ARN 作为资源GetObject
、PutObject
DeleteObjet
到存储桶 ARN 作为前缀为/*
的资源
- 我正在使用 Cloudformation 资源语法创建存储桶,我设置了 public 读取策略以便将其用作静态网站主机。
- 我还在 S3 存储桶策略中包含另一个策略声明,我在其中分配写入操作并将执行角色 ARN 设置为委托人。
我得到以下 iamRoleStatements
部分:
- Effect: "Allow"
Action:
- "s3:ListBucket"
Resource:
- Fn::Join:
- ""
- - "arn:aws:s3:::"
- Ref: StaticSiteBucket
- Effect: "Allow"
Action:
- "s3:GetObject"
- "s3:PutObject"
- "s3:DeleteObject"
- "s3:GetObjectVersionTagging"
- "s3:PutObjectVersionTagging"
Resource:
- Fn::Join:
- ""
- - "arn:aws:s3:::"
- Ref: StaticSiteBucket
- "/*"
我实际上可以确认它为生成的角色生成了以下策略:
{
"Action": [
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::bucket-name-here"
],
"Effect": "Allow"
},
{
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject",
"s3:GetObjectVersionTagging",
"s3:PutObjectVersionTagging"
],
"Resource": [
"arn:aws:s3:::bucket-name-here/*"
],
"Effect": "Allow"
}
有了这个,我 运行 lambda 函数在那个桶上执行 putObject
。得到一个'Access denied error'
,所以我想如果桶本身需要允许写入怎么办,所以我在桶策略中包含了一个写语句:
StaticSiteBucket:
Type: AWS::S3::Bucket
Properties:
AccessControl: PublicRead
BucketName: ${self:service}-static-site-${self:provider.stage}
WebsiteConfiguration:
IndexDocument: index.html
StaticSiteBucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket:
Ref: StaticSiteBucket
PolicyDocument:
Statement:
- Sid: PublicReadGetObject
Effect: Allow
Principal: "*"
Action:
- s3:GetObject
Resource:
Fn::Join: [
"", [
"arn:aws:s3:::",
{
"Ref": "StaticSiteBucket"
},
"/*"
]
]
- Sid: AllowLambdaRoleWrite
Effect: Allow
Action:
- "s3:GetObject"
- "s3:PutObject"
- "s3:DeleteObject"
- "s3:GetObjectVersionTagging"
- "s3:PutObjectVersionTagging"
Principal:
AWS:
- Fn::GetAtt: [ IamRoleLambdaExecution, Arn ]
Resource:
Fn::Join:
- ""
- - "arn:aws:s3:::"
- Ref: StaticSiteBucket
- "/*"
在 S3 存储桶中生成以下策略:
{
"Version": "2008-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::bucket-name-here/*"
},
{
"Sid": "AllowLambdaRoleWrite",
"Effect": "Allow",
"Principal": {
"AWS": "<role-arn>"
},
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject",
"s3:GetObjectVersionTagging",
"s3:PutObjectVersionTagging"
],
"Resource": "arn:aws:s3:::bucket-name-here/*"
}
]
}
所以,我试过几句话:
- 允许角色有写权限,运气不好
- 从存储桶策略向该角色附加写入权限,失败
我错过了什么?
需要考虑的一些想法:
- 策略中不需要委托人 (lambda.amazonaws.com)。委托人已经出现在无服务器创建的角色中(至少在默认情况下是这样)。很可能现在它可以工作了,因为你给了它所有的权限。
- 您可能需要 ListBucket。不是因为它是严格需要的,而是因为它可能掩盖了另一个问题。看到这个 excellent response。事实上,当你把没有星号的桶的名称放在资源部分时,可能是因为这个。
- 文件小吗?对于大文件,您可能会触发多部分,这也需要其他放置权限。
- 您是否要标记或放置额外的 ACL 权限或所有者?这也需要额外的权限。
因此,就我而言,我缺少的是:
- 我必须包括
getObjectTagging
和putObjectTagging
操作。
对于有类似问题的人。阅读下面的内容!
从课程中吸取教训(我花了一天半的时间坚持这一点)并意识到 Whosebug 是经验和知识的宝库。
我要指出:
- 确定您的代码正在执行哪些 API 操作,然后转到文档并进行检查。一些操作act on buckets while other on objects
- 在我的例子中,我可以在存储桶上删除任何额外的策略声明,换句话说,
- 执行角色是获得权力的角色。
- 我无法做到这一点,但如果有更明确的错误日志的方法,至少在 aws-sdk 节点的库中,将节省大量时间。 Stacktrace 还不够。欢迎提出建议。
这是我的 StaticSiteBucket 资源声明现在的样子:
- Effect: "Allow"
Action:
- "s3:ListBucket"
Resource:
- Fn::Join:
- ""
- - "arn:aws:s3:::"
- Ref: StaticSiteBucket
- Effect: "Allow"
Action:
- "s3:GetObject"
- "s3:PutObject"
- "s3:DeleteObject"
- "s3:GetObjectTagging"
- "s3:PutObjectTagging"
Resource:
- Fn::Join:
- ""
- - "arn:aws:s3:::"
- Ref: StaticSiteBucket
- "/*"