【问题标题】:Only allow EC2 instance to access static website on S3只允许 EC2 实例访问 S3 上的静态网站
【发布时间】:2017-06-06 06:23:35
【问题描述】:

我有一个托管在 S3 上的静态网站,我已将所有文件设置为公开。 另外,我有一个带有 nginx 的 EC2 实例,它充当反向代理,可以访问静态网站,所以 S3 扮演了源站的角色。

我现在想做的是将 S3 上的所有文件设置为私有文件,以便网站只能通过来自 nginx (EC2) 的流量访问。

到目前为止,我已经尝试了以下方法。我已经使用

创建了一个新的策略角色并将其附加到 EC2 实例

授予权限的策略:AmazonS3ReadOnlyAccess

并且已经重启了 EC2 实例。

然后我在我的 S3 存储桶控制台 > 权限 > 存储桶策略中创建了一个策略

{
    "Version": "xxxxx",
    "Id": "xxxxxxx",
    "Statement": [
        {
            "Sid": "xxxxxxx",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::XXXXXXXXXX:role/MyROLE"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::XXX-bucket/*"
        }
    ]
}

作为委托人,我设置了在为 EC2 实例创建角色时获得的 ARN。

"Principal": {
                "AWS": "arn:aws:iam::XXXXXXXXXX:role/MyROLE"
            },

但是,这不起作用,感谢任何帮助。

【问题讨论】:

    标签: amazon-web-services amazon-s3 amazon-ec2


    【解决方案1】:

    如果带有 nginx 的 Amazon EC2 实例只是向 Amazon S3 发出通用 Web 请求,那么问题就变成了如何将来自 nginx 的请求识别为“允许”,同时拒绝所有其他请求。

    一种方法是使用 S3 的 VPC 端点,它允许从 VPC 到 Amazon S3 的直接通信(而不是通过 Internet 网关)。

    存储桶策略然后可以限制对存储桶的访问,使其只能通过该端点访问。

    这是来自Example Bucket Policies for VPC Endpoints for Amazon S3 的存储桶策略:

    以下是 S3 存储桶策略示例,该策略仅允许从 ID 为 vpce-1a2b3c4d 的 VPC 终端节点访问特定存储桶 examplebucket。该策略使用 aws:sourceVpce 条件键来限制对指定 VPC 终端节点的访问。

    {
       "Version": "2012-10-17",
       "Id": "Policy",
       "Statement": [
         {
           "Sid": "Access-to-specific-VPCE-only",
           "Action": "s3:*",
           "Effect": "Allow",
           "Resource": ["arn:aws:s3:::examplebucket",
                        "arn:aws:s3:::examplebucket/*"],
           "Condition": {
             "StringEquals": {
               "aws:sourceVpce": "vpce-1a2b3c4d"
             }
           },
           "Principal": "*"
         }
       ]
    }
    

    所以,完整的设计应该是:

    • 对象 ACL:仅限私有(删除任何当前的公共权限)
    • 存储桶策略:同上
    • IAM 角色:不需要
    • 为 VPC 端点配置的路由表

    【讨论】:

    • 似乎合法。我没有测试 VPC 端点和托管端点的网站之间的交互,假设这是正在使用的,但它似乎应该可以工作。
    【解决方案2】:

    可以通过多种方式授予 Amazon S3 中的权限:

    • 直接在对象(称为访问控制列表或 ACL)上
    • 通过存储桶策略(适用于整个存储桶或目录)
    • IAM 用户/组/角色

    如果上述任何一项授予访问权限,则可以公开访问该对象。

    您的场景需要以下配置:

    • 每个对象上的 ACL 应该允许公共访问
    • 应该有没有存储桶策略
    • 您应该在附加到 IAM 角色的策略中分配权限

    当您拥有与用户/组/角色相关的权限时,最好在 IAM 中而不是在存储桶中分配权限。使用存储桶策略对所有用户进行一般访问。

    角色的政策是:

    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Sid": "AllowBucketAccess",
                "Effect": "Allow",
                "Action": [
                    "s3:GetObject"
                ],
                "Resource": [
                    "arn:aws:s3:::my-bucket/*"
                ]
            }
        ]
    }
    

    此策略直接应用于 IAM 角色,因此不需要 principal 字段。

    请注意,此政策仅允许GetObject -- 它不允许列出存储桶、上传对象等。

    您还提到“我已将所有文件设置为公开”。如果您通过使每个单独的对象公开可读来做到这一点,那么任何人仍然可以访问这些对象。有两种方法可以防止这种情况发生——要么从每个对象中删除权限,要么创建一个带有拒绝语句的存储桶策略,该语句停止访问,但仍允许角色获得访问权限。

    这开始变得有点棘手且难以维护,因此我建议从每个对象中删除权限。这可以通过管理控制台通过编辑每个对象的权限来完成,或者通过使用AWS Command-Line Interface (CLI) 和如下命令来完成:

    aws s3 cp s3://my-bucket s3://my-bucket --recursive --acl private
    

    这会就地复制文件,但会更改访问设置。

    (我不能 100% 确定是使用 --acl private 还是 --acl bucket-owner-full-control,所以玩一下吧。)

    【讨论】:

    • 这个问题是static website endpoints do not support IAM authentication.但是,它们确实尊重存储桶策略的其他方面,因此解决方案是将对象作为私有上传,为实例分配 EIP,然后在存储桶策略中允许来自该 IP 的访问:"Condition": { "IpAddress": { "aws:SourceIp": [ "203.0.113.200/32" ] } }(假设 EIP 为 203.0 .113.200)。只要您不使用 S3 VPC 终端节点(不支持 aws:SourceIp 条件),这将按预期工作。
    • 另外,看起来 OP 可能期望实例上的 IAM 角色允许 Nginx 神奇地能够从存储桶中获取对象,因为 Nginx 运行在具有一个 IAM 角色,忽略了您仍然需要从实例元数据中获取临时凭证并使用它们对请求进行签名和身份验证的事实......这将适用于 REST 端点,但不适用于网站端点。
    • 啊!是的,我没有考虑 Amazon EC2 实例如何从 Amazon S3 获取数据。我的上述建议仅在通过 API 请求获取时有效,但仅在发出 Web 请求时无效。
    • 谢谢 John Rotenstein 和 @Michael-sqlbot 我想我太天真了,以为 EC2 实例可以不受限制地访问 S3,并且从它到 S3 的任何 Web 请求都不需要任何身份验证.是的,想法是所有资产都是私有的,因此访问它们的唯一方法应该是通过 EC2 实例。我是否正确地假设我走在正确的道路上并且我错过了使用亚马逊身份验证标头装饰源自 nginx 的请求?
    • 在 cmets 中使用 John 的其他答案或我的方法(如果需要,我可以将其扩展为完整的答案——我在 HAProxy 后面使用该策略),您应该能够避免签署通过使用不同的信任机制来请求......但是,是的,按照您最初的计划使用实例角色需要使用来自实例角色的临时凭证(easy enough to get)对请求进行签名,但它们会定期到期,您必须重新拿来。凌乱。
    猜你喜欢
    • 2016-07-23
    • 1970-01-01
    • 2023-03-05
    • 1970-01-01
    • 1970-01-01
    • 2016-07-21
    • 2020-11-02
    • 1970-01-01
    • 2011-01-09
    相关资源
    最近更新 更多