【问题标题】:How to properly setup an IAM execution role and a bucket policy for getting lambda writing to a public read S3 bucket?如何正确设置 IAM 执行角色和存储桶策略以将 lambda 写入公共读取 S3 存储桶?
【发布时间】:2019-09-29 00:06:35
【问题描述】:

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

  • 使用一些附加策略创建一个角色,一个 lambda 函数将其分配为执行角色。 S3 政策是(列出更多相关政策):
    • ListBucket 到桶 ARN 作为资源
    • GetObject, PutObject 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/*"
        }
    ]
}

所以,我尝试了几句话:

  • 允许角色有写权限,不走运
  • 从存储桶策略将写入权限附加到该角色,没有运气

我错过了什么?

【问题讨论】:

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


    【解决方案1】:

    需要考虑的一些想法:

    1. 策略中不应需要委托人 (lambda.amazonaws.com)。主体已经出现在无服务器创建的角色中(至少默认情况下)。很可能现在它可以工作了,因为您授予了它所有权限。
    2. 您可能需要 ListBucket。不是因为它是严格需要的,而是因为它可能掩盖了另一个问题。请参阅此excellent response。其实,当你把bucket的名字放在resource部分不带星号的时候,很可能就是这个原因。
    3. 文件小吗?对于大文件,您可能会触发 multipart,这也需要其他 put 权限。
    4. 您是否标记或添加了额外的 ACL 权限或所有者?这也需要额外的权限。

    【讨论】:

    • 问题是,如果我将 Principal 设置为“*”,我就会让它工作,这当然不是我想要保留的东西。我不确定问题是否在于创建策略以使存储桶成为公共读取存储桶之后,我需要声明额外的写入权限
    • 1.尝试从策略中删除 Principal(这也是角色的一部分)。2.不确定您对存储桶的公开阅读的意思。
    【解决方案2】:

    所以就我而言,我缺少什么:

    • 我必须包含 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
              - "/*"
    

    【讨论】:

      猜你喜欢
      • 2016-12-23
      • 1970-01-01
      • 2018-06-08
      • 1970-01-01
      • 2019-02-26
      • 2021-08-13
      • 1970-01-01
      • 2012-11-23
      • 1970-01-01
      相关资源
      最近更新 更多