【问题标题】:Hosting on amazon s3 for private group在 amazon s3 上托管私人团体
【发布时间】:2018-03-16 05:13:19
【问题描述】:

我正在研究如何在 Amazon S3 上托管一个静态网站,但需要使其仅可供知道凭据的特定群体访问。

在下面找不到除 IP 限制以外的任何选项。我不能这样做,因为我不知道每个会访问它的人的 IP。

{
  "Version": "2012-10-17",
    "Statement": [
      {
        "Sid": "PublicReadGetObject",
        "Effect": "Allow",
        "Principal": "*",
        "Action": "s3:GetObject",
        "Resource": "arn:aws:s3:::testfoo/*",
        "Condition": {
          "IpAddress": {
            "aws:SourceIp": "150.101.204.0/24"
          },
          "NotIpAddress": {
            "aws:SourceIp": "150.101.204.188/32"
          }
        }
      }
    ]
}

我正在寻找一个选项,就像我们在 apache 中使用 .htaccess 一样,在授予访问权限之前将请求基本身份验证用户名和密码。

【问题讨论】:

    标签: amazon-web-services security authentication amazon-s3 web


    【解决方案1】:

    我正在编辑此答案以扩展有关如何使用 cloudfront 和 lambda@edge 为托管在 S3 存储桶上的静态网站实施基本身份验证的答案。我使用此 article 作为参考,了解如何使用 lambda@Edge 为您的 s3 存储桶实现无服务器基本身份验证。

    简而言之,Lambda@Edge 允许您将 AWS Lambda 函数附加到 CloudFront 行为。 CloudFront 是 Amazon 的 CDN 解决方案,可以位于 S3 存储桶的前面,提供低延迟响应、高传输速度、支持使用来自 Amazon 的免费 SSL 证书的自定义域,并且它与其他 AWS 服务集成,现在包括 Lambda。


    S3 存储桶设置

    我不会详细介绍如何创建 S3 存储桶,但基本上在您创建 S3 存储桶(例如 s3-bucket-secure-example)之后,上传您的文件并在属性中启用静态网站托管。此时无需启用任何权限。如果您尝试使用 URL 访问您的 s3 存储桶,您应该会被拒绝访问。


    设置 Cloudfront

    注意:这是将云端用于 s3 存储桶的最低基本设置

    引用此walkthrough,从here 创建一个云端分发。

    1. 创建分布
    2. 点击网络入门
    3. 在源域名下,放置您的 S3 存储桶静态网站端点。
    4. 在源设置下,为限制存储桶访问选择“是”。这将防止用户绕过云端分发并直接访问 S3 存储桶 URL。然后,您可以在“原始访问身份”下创建一个新身份,或使用现有身份,并让它更新存储桶策略以授予此云端分发的读取权限,或者您可以手动更新它们。
    5. 您现在可以将“默认缓存行为设置”的其余设置保留为默认设置,或者根据您的需要进行调整。
    6. 在 Distribution settings 下,您可以选择所需的价格等级,在 Default Root Object 下,您可以放置​​要从存储桶中返回的对象(例如 index.html)。
    7. 创建分发。此过程需要一段时间才能完成。您可以前往 Cloudfront Distributions 主页并转到它为您提供的域名(例如 d3xxxxxxxx.cloudfront.net)以查看您的 s3 存储桶静态网站。

    设置lambda@Edge 函数

    注意:在撰写本文时,此函数使用的触发器(云端)仅适用于美国东部(弗吉尼亚北部)区域 (us-east-1)。

    1. 在您的 aws 控制台主页中,转到 Compute 下的 Lambda。
    2. 点击创建函数。
    3. 填写详细信息:为您的函数命名您想要的任何名称,然后选择“从模板创建新角色”。对于角色名称,您也可以输入任何名称,并且您可以选择基本的边缘 lambda 权限。
    4. 点击创建函数。
    5. 在函数内部,在函数代码部分下,添加您的身份验证代码(上面引用的article 有一个示例函数可供使用)。然后点击保存。然后在操作下,发布一个新版本。给它一个描述,然后点击发布。
    6. 从右上角复制 ARN 并返回到您的云端分发。单击 id,然后转到行为选项卡。选择您的行为并单击编辑。然后在页面底部您会找到 Lambda 函数关联。
    7. 为事件类型选择“查看器请求”,然后粘贴到您的 lambda 函数 ARN。 然后单击“是,编辑”。给它一些时间来更新。

      您还可以通过返回函数并立即查看其关联来检查 Cloudfront 分发是否已与您的函数关联。

    【讨论】:

    • 虽然这些链接都提供了良好且有价值的信息,但 Stack Overflow 上的答案需要提供 answers —— 而不仅仅是(或主要不是)指向场外资源的链接。请考虑扩展答案,至少给出一个概述,最好是这些帖子推荐的一些细节,特别是第一个,因为它实际上为手头的确切问题提供了解决方案。同时,请确保您清楚哪些词是您的,哪些是别人的,使用块引用和明确的归属。
    【解决方案2】:

    Amazon S3 不是 Web 服务器。它无法处理页面的内容。

    要有选择地控制访问,您需要一些表单计算逻辑来确定是否应允许访问。这在 S3 中不可用。

    最接近的等价物是使用Amazon CloudFront cookies 来授予访问权限,但您仍然需要一种最初提供 cookie 的方法。

    可以创建一个功能更强大的解决方案,调用 API Gateway 和 Lambda,但对于一个简单的静态网站来说这有点太复杂了。

    【讨论】:

      【解决方案3】:

      到目前为止,这在 AWS 上变得相对简单。这基本上是需要做的三件事:

      1. 创建 CloudFront 函数以将基本身份验证添加到请求中。
      2. 在几个地方正确配置 CloudFront 分配的来源。
      3. 激活 CloudFront 功能。 就是这样,没有特别的花里胡哨。这是我所做的:

      首先,转到 CloudFront,然后单击左侧的函数,使用您选择的名称创建一个新函数(无需区域等),然后添加以下代码作为函数的代码:

      function handler(event) {
      
          var user = "myuser";
          var pass = "mypassword";
      
          function encodeToBase64(str) {
              var chars =
              "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
              for (
                  // initialize result and counter
                  var block, charCode, idx = 0, map = chars, output = "";
                  // if the next str index does not exist:
                  //   change the mapping table to "="
                  //   check if d has no fractional digits
                  str.charAt(idx | 0) || ((map = "="), idx % 1);
                  // "8 - idx % 1 * 8" generates the sequence 2, 4, 6, 8
                  output += map.charAt(63 & (block >> (8 - (idx % 1) * 8)))
              ) {
              charCode = str.charCodeAt((idx += 3 / 4));
              if (charCode > 0xff) {
                  throw new InvalidCharacterError("'btoa' failed: The string to be encoded contains characters outside of the Latin1 range."
              );
              }
              block = (block << 8) | charCode;
            }
            return output;
          }
      
      
          var requiredBasicAuth = "Basic " + encodeToBase64(`${user}:${pass}`);
          var match = false;
          if (event.request.headers.authorization) {
              if (event.request.headers.authorization.value === requiredBasicAuth) {
                  match = true;
              }
          }
      
          if (!match) {
            return {
              statusCode: 401,
              statusDescription: "Unauthorized",
              headers: {
                "www-authenticate": { value: "Basic" },
              },
            };
          } 
      
          return event.request;
      }
      

      然后您可以直接在 UI 上进行测试并假设它可以正常工作并假设您已经自定义了用户名和密码,然后发布函数。

      请注意,我在 Internet 上找到了上述函数的各个部分,因此这不是我自己的代码(除了拼凑)。我希望我仍然能找到来源,所以我可以在这里引用它们,但我再也找不到它们了。归功于创作者! :-)

      接下来,打开您的 CloudFront 分配并执行以下操作:

      1. 确保源中的 S3 存储桶配置为 REST 端点而不是网站端点,即它必须以 .s3.amazonaws.com 结尾,并且主机名中没有单词 website

      2. 同样在 Origin 设置中,在“S3 存储桶访问”下,选择“是使用 OAI(存储桶只能限制对 CloudFront 的访问)”。在下面的设置中单击“创建 OAI”以创建一个新的 OAI(除非您有一个现有的并且知道您在做什么)。并选择“是,更新存储桶策略”以允许 AWS 将必要的权限添加到您的 OAI。

      3. 最后,打开 CloudFront 分配的行为并滚动到底部。在“函数关联”下,对于“查看器请求”,选择“CloudFront 函数”并选择您新创建的 CloudFront 函数。保存您的更改。

      应该就是这样。运气好的话只需几分钟(我知道实际上更多),尤其是在完成所有设置后不会增加额外的复杂性。

      【讨论】:

        猜你喜欢
        • 2011-03-31
        • 1970-01-01
        • 2013-06-20
        • 2012-01-08
        • 1970-01-01
        • 2011-04-15
        • 1970-01-01
        • 2012-04-04
        • 1970-01-01
        相关资源
        最近更新 更多