【问题标题】:AWS ApiGateway Proxy to non-Public S3 BucketAWS ApiGateway 代理到非公共 S3 存储桶
【发布时间】:2019-02-21 05:44:52
【问题描述】:

以下 cloudformation 脚本设置了一个代理到 S3 存储桶的 Api Gateway 方法。

S3BucketPolicy 将存储桶开放给公共读取访问,但 AWS UI 警告说永远不要这样做。

我尝试将 S3BucketPolicy Principal 设置为 service apigateway.amazonaws.com 但这会导致访问被拒绝。

1) 限制桶访问API网关功能的正确方法是什么? (示例 YAML 会很棒)

2) 我如何调试此拒绝访问失败以获取有关失败原因的更多信息?

3) 我应该在哪里寻找关于什么应该是非常标准的模板 sn-p 的示例代码?

尝试 #1 - 有效,但只能通过将 S3 存储桶设为公开否则拒绝访问

AWSTemplateFormatVersion: 2010-09-09

Parameters:
  S3BucketName:
    Type: String
    Description: >
      Name for the S3 bucket that contains the nested templates.

Resources:
  RestAPI:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      BinaryMediaTypes: 
            - '*/*'
      Name: !Ref 'AWS::StackName'

  RestAPIRootGET:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      AuthorizationType: NONE
      HttpMethod: GET
      Integration:
        IntegrationHttpMethod: GET
        PassthroughBehavior: WHEN_NO_MATCH
        Type: HTTP_PROXY
        Uri: !Sub https://${S3BucketName}.s3.amazonaws.com/static-assets/index.html
      ResourceId: !GetAtt RestAPI.RootResourceId
      RestApiId: !Ref RestAPI
    DependsOn:
      - RestAPI

  BucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket: !Ref S3BucketName
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          -
            Sid: GetObject
            Effect: Allow
            Principal: "*"
            Action:
              - s3:*
            Resource:
              - !Sub 'arn:aws:s3:::${S3BucketName}/static-assets/*'

我认为也许立即创建一个有权访问存储桶的角色,然后让 ApiGateway 承担此角色,但我很难找到解释如何在 cloudformation 模板中执行此操作的文档。 (另请参阅 Michael - sqlbot 评论建议使用该方法的凭据属性)

这是我的尝试,但仍因拒绝访问而失败

尝试 #2 - 拒绝访问

AWSTemplateFormatVersion: 2010-09-09

Parameters:
  S3BucketName:
    Type: String
    Description: >
      Name for the S3 bucket that contains the nested templates.


Resources:

  RestAPI:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      BinaryMediaTypes: 
            - '*/*'
      Name: !Ref 'AWS::StackName'

  RestAPIRootGET:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      AuthorizationType: NONE
      HttpMethod: GET
      Integration:
        IntegrationHttpMethod: GET
        PassthroughBehavior: WHEN_NO_MATCH
        Type: HTTP_PROXY
        Uri: !Sub https://${S3BucketName}.s3.amazonaws.com/static-assets/index.html
        Credentials: !GetAtt AllowStaticAccessRole.Arn
      ResourceId: !GetAtt RestAPI.RootResourceId
      RestApiId: !Ref RestAPI
    DependsOn:
      - RestAPI
      - AllowStaticAccessRole

  AllowStaticAccessRole: 
    Type: "AWS::IAM::Role"
    Properties: 
      AssumeRolePolicyDocument: 
        Version: "2012-10-17"
        Statement: 
          - 
            Effect: "Allow"
            Principal: 
              Service: 
                - "apigateway.amazonaws.com"
            Action: 
              - "sts:AssumeRole"
      Path: "/"
      Policies: 
        - 
          PolicyName: "AllowStaticAccessPolicy"
          PolicyDocument: 
            Version: "2012-10-17"
            Statement: 
              - 
                Effect: "Allow"
                Action:
                  - s3:*
                Resource:
                  - !Sub 'arn:aws:s3:::${S3BucketName}/static-assets/*'

【问题讨论】:

  • 查看Integration->credentials 并与credentials 进行比较。这看起来像是 API Gateway 在联系 S3 之前需要承担的 IAM 角色的 ARN 的位置。 apigateway.amazonaws.com 可能是该角色的信任策略上的Principal,并且角色策略将授予对存储桶的权限。
  • 我会试试这个并更新
  • @Michael-sqlbot。我尝试按照您的建议进行操作,但仍然导致“访问被拒绝”
  • 对于遇到类似问题的其他人来说,“访问被拒绝”的另一个可能原因是 s3 存储桶中的对象是否已加密 - 您赋予 API Gateway 的角色必须有权使用 KMS 和特定密钥。

标签: amazon-cloudformation aws-api-gateway


【解决方案1】:

正如 cmets 中已经提到的,拒绝访问错误可能来自 KMS,而不是来自 S3 本身。

要解决此问题,您至少需要将这些权限添加到 Api 网关承担的角色:"kms:Decrypt", "kms:ReEncryptFrom",最好还说明这也应适用于正确的最小权限实施。

【讨论】:

    猜你喜欢
    • 2016-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-07
    • 2021-10-08
    • 2020-08-21
    • 2022-11-05
    • 2014-12-23
    相关资源
    最近更新 更多