Google 每个镜像 ACL 的容器注册表
Google Container Registry Per Image ACLs
我们平台的结构要求在单个 and/or 只有几个项目中包含大量私有图像(如果可能的话)。此外,我们主要是一家 GCP 商店,很乐意留在 Google 环境中。
目前 - 据我所知 - GCR ACL 结构需要附加到服务帐户(在本例中)的 storage.objects.get 和 storage.objects.list 权限(或 objectViewer 角色)才能访问 GCR。这通常不是问题,我们在使用 gsutil 为容器注册表在项目级别启用读取访问时没有遇到任何直接问题。以下是我们为实现一般访问所做的工作流程示例。但是,它并没有实现我们限制服务帐户访问每个图像的目标。
简单 Docker 使用 exproj 代替使用的项目名称构建、标记图像并将其推送到 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
- 账户 A 现在只能访问 ExampleProj/ImageA,账户 B 无法访问账户 A 的 ExampleProj/ImageA
虽然我们可以按项目按帐户进行容器注册,但在大量使用期间需要跨每个帐户跟踪项目以及随心所欲地受到 GCP 项目限制的扩展潜力令人担忧。
除了上述之外,我对任何可以实现这一目标的想法或结构持开放态度!
编辑
感谢 jonjohnson 的回复!我按照与 blob 读取相关的推荐行编写了一个快速而肮脏的脚本。我仍在努力验证它是否成功,但是,我确实想声明我们确实控制了何时发生推送,因此跟踪结果不像在其他情况下那样脆弱。
这是我整理的一个脚本,作为清单 -> 摘要权限修改的示例。
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 登录方面下拉。
这是否符合您所说的 jonjohnson?根据与 image/tag?
相关联的 manifest/layers 本质上允许每个服务帐户访问每个 blob
谢谢!
目前没有一种简单的方法可以满足您的需求。
您可以做的一件事是为每张图像授予对存储桶中各个 blob 的访问权限。这不是超级优雅,因为您必须在每次推送后更新权限。
您可以通过使用 GCR 中的 pubsub 支持来自动执行此操作以侦听推送、查看该图像引用的 blob、将存储库路径与需要访问的任何服务帐户匹配,然后授予这些服务帐户访问每个 blob 对象。
一个缺点是每个服务帐户仍然可以查看图像清单(本质上是层摘要列表 + 一些图像运行时配置)。不过,他们将无法提取实际的图像内容。
此外,这有点依赖于 GCR 的一些实现细节,因此将来可能会中断。
我们平台的结构要求在单个 and/or 只有几个项目中包含大量私有图像(如果可能的话)。此外,我们主要是一家 GCP 商店,很乐意留在 Google 环境中。
目前 - 据我所知 - GCR ACL 结构需要附加到服务帐户(在本例中)的 storage.objects.get 和 storage.objects.list 权限(或 objectViewer 角色)才能访问 GCR。这通常不是问题,我们在使用 gsutil 为容器注册表在项目级别启用读取访问时没有遇到任何直接问题。以下是我们为实现一般访问所做的工作流程示例。但是,它并没有实现我们限制服务帐户访问每个图像的目标。
简单 Docker 使用 exproj 代替使用的项目名称构建、标记图像并将其推送到 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
- 账户 A 现在只能访问 ExampleProj/ImageA,账户 B 无法访问账户 A 的 ExampleProj/ImageA
虽然我们可以按项目按帐户进行容器注册,但在大量使用期间需要跨每个帐户跟踪项目以及随心所欲地受到 GCP 项目限制的扩展潜力令人担忧。
除了上述之外,我对任何可以实现这一目标的想法或结构持开放态度!
编辑
感谢 jonjohnson 的回复!我按照与 blob 读取相关的推荐行编写了一个快速而肮脏的脚本。我仍在努力验证它是否成功,但是,我确实想声明我们确实控制了何时发生推送,因此跟踪结果不像在其他情况下那样脆弱。
这是我整理的一个脚本,作为清单 -> 摘要权限修改的示例。
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 登录方面下拉。
这是否符合您所说的 jonjohnson?根据与 image/tag?
相关联的 manifest/layers 本质上允许每个服务帐户访问每个 blob谢谢!
目前没有一种简单的方法可以满足您的需求。
您可以做的一件事是为每张图像授予对存储桶中各个 blob 的访问权限。这不是超级优雅,因为您必须在每次推送后更新权限。
您可以通过使用 GCR 中的 pubsub 支持来自动执行此操作以侦听推送、查看该图像引用的 blob、将存储库路径与需要访问的任何服务帐户匹配,然后授予这些服务帐户访问每个 blob 对象。
一个缺点是每个服务帐户仍然可以查看图像清单(本质上是层摘要列表 + 一些图像运行时配置)。不过,他们将无法提取实际的图像内容。
此外,这有点依赖于 GCR 的一些实现细节,因此将来可能会中断。