Amazon S3策略阻止创建根级文件夹

时间:2017-01-31 18:52:33

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

我们希望阻止我们的S3用户在我们的存储桶根目录中创建新文件夹。换句话说,他们必须使用存储桶中的现有文件夹来上载或修改文件。如果他们愿意,他们可以选择在这些现有文件夹中创建子文件夹。

注意:使用S3策略。用户选择任何现有文件夹。他们没有分配文件夹。

我知道S3将文件和文件夹视为对象,所以我不确定这是否可以完成,但我相信社区的潜力。

这就是我想要的:

Bucket-name: test-bucket

  • 操作:在测试堆的根目录中创建文件夹。 期望的结果:拒绝

  • 操作:在test-bucket的root中上传随机文件。 期望的结果:拒绝

  • 操作:在test-bucket的现有“folder1”文件夹(test-bucket / folder1 / file1)中上传文件“file1”。 期望的结果:成功

  • 操作:在test-bucket的现有“folder1”文件夹(test-bucket / folder1 / sub-folder1 /)中创建文件夹“sub-folder1”。 期望的结果:成功

2 个答案:

答案 0 :(得分:3)

您的概念模型存在缺陷。

  

我知道S3将文件和文件夹视为对象

这不正确。

这是正确的版本:

  • S3服务和API没有文件夹概念。
  • S3对象没有任何真正意义上的层次结构。
  • S3控制台是唯一具有文件夹概念的实体。
  • S3服务和API支持前缀分隔符公共前缀的概念。

当对API的列表对象请求附带指定的前缀时,只返回带有以该前缀开头的键的对象,而不管前缀后的对象键中是否有/

当列表对象请求附带前缀和分隔符(通常为/)时,API仅返回其键与给定前缀匹配且没有后续{的对象密钥中的{1}}(在请求中指定的前缀之后)。这些类似于文件夹中的"文件。"

与给定前缀匹配但具有后续(在指定前缀之后)/的任何对象的键的前缀被合并为其前缀的唯一列表,被截断为其下一个{{1 }}。这些是常见的前缀,类似于文件夹中的"文件夹。"

但实际上,"""别的什么。

控制台通过从API列表对象请求中读取公共前缀并将其显示为文件夹来创建文件夹幻觉。

控制台通过允许您创建文件夹来增强幻觉。 - 但它实际上不是一个文件夹,甚至不需要它。它只是一个空对象,其最后一个字符为/。 S3的正常操作不需要此对象,但是为方便起见而创建,因此您可以导入"进入"一个"空文件夹"并将文件"上传到"空文件夹。

但是,真正发生的是:

/

现在......如果您使用空桶并使用API​​(而非控制台),您只需/即可在控制台中获得完全相同的结果 - 你会看到一个名为" foo"的文件夹。包含" bar.txt。"该文件夹显示为,因为有一个前缀为Console: "create folder foo in the root of the bucket" API: PUT /foo/ Content-Length: 0 Console: "click folder foo" API: GET /?prefix=foo/&delimiter=/ Console: "upload file bar.txt inside folder foo" API: PUT /foo/bar.txt 的对象。删除对象,文件夹消失。

相反,如果您使用控制台从顶部执行此操作,则删除" bar.txt"仍然会有文件夹" foo"因为它实际上只是一个空对象,其唯一目的是当没有其他具有该公共前缀的对象时,使文件夹出现在控制台导航中。

所以,没有...... S3不会将文件和文件夹都视为对象。 S3 控制台创建欺骗文件夹的对象,严格地作为导航的辅助,这里的魔力是对象的键以PUT /foo/bar.txt结束。另一方面,如果那些空对象不在那里,控制台仍然会显示对象,就好像它们在文件夹中一样。

然后您会看到出现的问题。不能要求S3服务测试它不知道的事实,实际上不需要存在。

因此,技术上不可能完全按照你的要求行事;然而,似乎有一个有限的解决方法。主要限制是您无法指定"文件夹必须存在,"但你可以指定"对象键前缀必须与预定义的一组模式匹配。"

存储桶或用户策略的相关部分可能看起来像这样......

foo/

受此政策影响的用户将能够在" examplebucket"中创建以taxdocuments /或人员/或独角兽/开头的任何对象。如果没有这些前缀之一,将无法创建对象。除此之外,可以创建控制台文件夹" in"文件夹" in"文件夹整天都在,只要其中一个前缀位于每个假文件夹的对象键的开头。

当然,限制是使另一个文件夹符合访问权限需要修改策略。

这可能也有效,但请谨慎行事:

/

直观地看起来这可能有用,但这里存在缺陷 - 假设 "Action": "s3:PutObject", "Resource": [ "arn:aws:s3:::examplebucket/taxdocuments/*", "arn:aws:s3:::examplebucket/personnel/*", "arn:aws:s3:::examplebucket/unicorns/*" ... ], 有效(it seems to be)且"Resource": "arn:aws:s3:::examplebucket/?*/?*", ?*/?*的方式不匹配0 {{1}确实 - 这允许用户在根目录中创建一个新的(伪)文件夹,只要它们使用API​​同时在其中创建一个名称至少有一个字符长的内容 - 即创建键为?"的对象创建" " pics"文件夹,如果它还没有,如上所述。从控制台,这个应该阻止在根目录中创建新文件夹,但是从API中它不会产生这样的限制。

答案 1 :(得分:0)

感谢您的精心回复@Michael。您完全正确地说API和CLI调用可以在非空时继续创建根级文件夹。控制台和S3浏览器访问按预期工作。这是妥协,但它是我们能够达到我们想要的最接近的。这是我正在使用的存储桶策略:

{
  "Version": "2012-10-17",
  "Id": "Policy1486492608325",
  "Statement": [

    {
      "Sid": "Stmt1486492495770",
      "Effect": "Allow",
      "Principal": {
        "*"
      },
      "Action": [
        "s3:DeleteObject",
        "s3:Get*",
        "s3:List*",
        "s3:PutObject"
      ],
      "Resource": [
        "arn:aws:s3:::test-storage",
        "arn:aws:s3:::test-storage/*"
      ]
    },
    {
      "Sid": "Stmt1486492534643",
      "Effect": "Deny",
      "Principal": {
        "*"
      },
      "Action": [
        "s3:DeleteObject",
        "s3:PutObject"
      ],
      "NotResource": "arn:aws:s3:::test-storage/?*/?*"
    }
  ]
}