Google容器注册表每个图片ACL

时间:2018-06-28 20:28:40

标签: docker google-cloud-platform google-container-registry google-iam

我们在平台内拥有一个结构,如果可能的话,它需要在单个和/或几个项目中包含大量私有映像。此外,我们在很大程度上是GCP商店,并且希望保留在Google环境中。

当前-据我了解-GCR ACL结构需要附加到服务帐户(在这种情况下)的storage.objects.get和storage.objects.list权限(或objectViewer角色)才能访问GCR。通常,这不是问题,使用gsutil为容器注册表在项目级别启用读取访问权限时,我们没有任何直接的问题。下面是一个工作流示例,说明了我们为实现常规访问而正在做的事情。但是,它无法达到我们限制每次图片访问服务帐户的目标。


使用exproj代替使用的项目名称,将简单的Docker Image构建,标记并推送到GCR中。

sudo docker build -t hello_example:latest
sudo docker tag hello_example:latest gcr.io/exproj/hello_example:latest
sudo docker push gcr.io/exproj/hello_example:latest

这为我们提供了ex_proj项目中的hello_example存储库。  我们创建一个服务帐户,并为其授予读取存储桶的权限。

gsutil acl ch -u gcr-read-2@exproj.iam.gserviceaccount.com:R gs://artifacts.exproj.appspot.com/
Updated ACL on gs://artifacts.exproj.appspot.com

然后允许我们通过密钥使用Docker登录。

sudo docker login -u _json_key --password-stdin https://gcr.io < gcr-read-2.json
Login Succeeded

然后按预期从注册表中拉出图像

sudo docker run gcr.io/exproj/hello_example

但是,出于我们的目的,我们不想允许服务帐户访问每个项目的整个注册表,而只能访问上述的hello_example。在使用gsutil进行测试时,我无法定义基于图像的特定ACL,但是,我想知道是否只是缺少一些东西。

gsutil acl ch -u gcr-read-2@exproj.iam.gserviceaccount.com:R gs://artifacts.exproj.appspot.com/hello_example/
CommandException: No URLs matched: gs://artifacts.exproj.appspot.com/hello_example/

在这一切的宏伟计划中,我们想使用以下模型:

  • AccountA在ExampleProj中创建了ImageA:TagA
  • 已生成ServiceAccountA
  • 为ServiceAccountA设置了ACL,以仅访问ExampleProj / ImageA及其下面的所有标签
  • ServiceAccountA JSON提供给AccountA
  • AccountA现在只能访问ExampleProj / ImageA,AccountB无法访问AccountA的ExampleProj / ImageA

虽然我们可以按项目进行每个帐户的容器注册表,但在大量使用期间,需要跟踪每个帐户中的项目以及在GCP项目限制的限制下的可扩展性令人担忧。

除了上述之外,我也欢迎任何可以实现这一目标的构想!


编辑

感谢强约翰逊的回应!我按照与斑点读取有关的建议行编写了一个快速且肮脏的脚本。我仍在努力验证它是否成功,但是,我确实想声明我们可以控制何时发生推送,因此与其他情况相比,跟踪结果的脆弱性要小。

这是我整理成一个脚本作为清单->摘要权限修改的示例。

require 'json'

# POC GCR Blob Handler
# ---
# Hardcoded params and system calls for speed
# Content pushed into gcr.io will be at gs://artifacts.{projectid}.appspot.com/containers/images/ per digest

def main()
    puts "Running blob gathering from manifest for org_b and example_b"
    manifest = `curl -u _token:$(gcloud auth print-access-token) --fail --silent --show-error https://gcr.io/v2/exproj/org_b/manifests/example_b`
    manifest = JSON.parse(manifest)
    # Manifest is parsed, gather digests to ensure we allow permissions to correct blobs
    puts "Gathering digests to allow permissions"
    digests = Array.new
    digests.push(manifest["config"]["digest"])
    manifest["layers"].each {|l| digests.push(l["digest"])}
    # Digests are now gathered for the config and layers, loop through the digests and allow permissions to the account
    puts "Digests are gathered, allowing read permissions to no-perms account"
    digests.each do |d|
        puts "Allowing permissions for #{d}"
        res = `gsutil acl ch -u no-perms@exproj.iam.gserviceaccount.com:R gs://artifacts.exproj.appspot.com/containers/images/#{d}`
        puts res
    end
    puts "Permissions changed for org_b:example_b for no-perms@exproj.iam.gserviceaccount.com"
end

main()

虽然这样做有适当的设置权限,但我看到对Docker的实际身份验证存在相当多的脆弱性,并且由于未识别Docker登录而被拉低。

这是否与您所指的约翰逊相似?本质上是否允许基于与该图像/标签关联的清单/层的每个服务帐户的每个Blob访问?

谢谢!

1 个答案:

答案 0 :(得分:1)

目前还没有一种轻松的方法来完成您想要的事情。

您可以做的一件事就是为每个图像授予对存储桶中各个blob的访问权限。这不是超级优雅,因为每次推送后都必须更新权限。

您可以使用GCR中的pubsub支持来自动执行操作,以监听推送,查看该映像所引用的Blob,将存储库路径与需要访问的服务帐户进行匹配,然后为这些服务帐户授予访问权限到每个blob对象。

一个缺点是每个服务帐户仍将能够查看映像清单(本质上是层摘要列表和某些映像运行时配置)。但是,他们将无法提取实际的图像内容。

此外,这有点依赖GCR的一些实现细节,因此将来可能会中断。