如何正确设置IAM执行角色和存储桶策略,以使Lambda写入公共读取S3存储桶?

时间:2019-05-11 08:12:50

标签: amazon-s3 amazon-cloudformation amazon-iam serverless-framework

对于上下文,我正在使用无服务器框架,因此发生了一些事情:

  • 使用附加的策略创建一个角色,然后将lambda函数获取分配为执行角色的函数。 S3策略是(列出了更相关的策略):
    • ListBucket到存储桶ARN作为资源
    • GetObjectPutObject DeleteObjet到存储桶ARN作为/*前缀的资源
  • 我正在使用Cloudformation资源语法创建存储桶,并设置了公共读取策略,以便将其用作静态网站主机。
  • 我还在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/*"
        }
    ]
}

所以,我尝试了一下:

  • 允许角色具有写权限,没有运气
  • 从存储桶策略中为该角色分配写权限,不走运

我想念什么?

2 个答案:

答案 0 :(得分:1)

要考虑的一些想法:

  1. 该策略中不需要主体(lambda.amazonaws.com)。主体已经出现在无服务器创建的角色中(至少默认情况下)。现在很可能它可以工作,因为您授予了它所有权限。
  2. 您可能需要ListBucket。不是因为严格需要它,而是因为它可能掩盖了另一个问题。参见此excellent response。实际上,当您在资源部分中放置不带星号的存储桶名称时,可能是因为这个原因。
  3. 文件小吗?对于大文件,您可能会触发分段操作,并且还需要其他放置权限。
  4. 您要标记或放置其他ACL权限或所有者吗?这还需要其他权限。

答案 1 :(得分:0)

所以我的情况是:

  • 我必须包含getObjectTaggingputObjectTagging动作。

适用于有类似问题的任何人。请在下面阅读!

从课程中学习(我花了一天半的时间在此上),并意识到Stackoverflow是经验和知识的存储库。

我要指出:

  • 确定您的代码正在执行哪些API操作,然后转到文档并进行检查。有些操作act on buckets,而另一些则是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
          - "/*"