Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/google-cloud-platform/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Docker Google容器注册表每映像ACL_Docker_Google Cloud Platform_Google Container Registry_Google Iam - Fatal编程技术网

Docker Google容器注册表每映像ACL

Docker Google容器注册表每映像ACL,docker,google-cloud-platform,google-container-registry,google-iam,Docker,Google Cloud Platform,Google Container Registry,Google Iam,我们的平台结构要求在单个和/或少数项目(如果可能)中提供大量私有图像。此外,我们在很大程度上是一家GCP商店,希望留在谷歌环境中 目前,据我所知,GCR ACL结构需要附加到服务帐户(在本例中)的storage.objects.get和storage.objects.list权限(或objectViewer角色)才能访问GCR。这通常不是问题,使用gsutil在项目级别为容器注册表启用读取访问也没有任何直接问题。下面是一个工作流示例,说明了我们为实现通用访问所做的工作。但是,它并没有实现我们限制

我们的平台结构要求在单个和/或少数项目(如果可能)中提供大量私有图像。此外,我们在很大程度上是一家GCP商店,希望留在谷歌环境中

目前,据我所知,GCR ACL结构需要附加到服务帐户(在本例中)的storage.objects.get和storage.objects.list权限(或objectViewer角色)才能访问GCR。这通常不是问题,使用gsutil在项目级别为容器注册表启用读取访问也没有任何直接问题。下面是一个工作流示例,说明了我们为实现通用访问所做的工作。但是,它并没有实现我们限制每个映像访问的服务帐户的目标


简单的Docker映像被构建、标记并推送到GCR中,使用exproj代替使用的项目名称

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_示例存储库。 我们创建一个服务帐户,并授予它读取bucket的权限

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

但是,出于我们的目的,我们不希望允许服务帐户访问每个项目的整个注册表,而是只访问上面标识的hello_示例。在使用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项目限制的扩展潜力令人担忧

除上述内容外,我愿意接受任何能够实现这一目标的想法或结构


编辑

感谢强生的回应!我按照推荐的关于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登录未被识别

这就是你所说的约翰逊吗?基本上允许基于与该图像/标记关联的清单/层对每个服务帐户的每个blob进行访问


谢谢

目前没有一种简单的方法来做你想做的事

您可以做的一件事是为每个图像授予对bucket中单个blob的访问权限。这并不是非常优雅,因为每次推送后都必须更新权限

通过使用GCR中的支持来监听推送,查看该映像引用的blob,将存储库路径匹配到需要访问的服务帐户,然后授予这些服务帐户访问每个blob对象的权限,您可以自己实现自动化

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


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

嘿,感谢您的回复!我根据您的建议和围绕它的潜在问题将编辑添加到我的顶层。接受这一回答,因为我能够围绕blob ACL工作,以使其正常工作。然而,我们可能会朝着另一个方向前进,以确保分离,但仍然在内部使用容器注册表。谢谢你能试着定位gs://artifacts.exproj.appspot.com/containers/repositories/library/hello_example/?错误消息意味着您的目标URL不正确,请尝试运行gsutil ls gs://artifacts.exproj.appspot.com/,并继续运行向下移动到存储桶的命令,直到找到您的图像谢谢您的想法!我确实检查过,也许是我如何将docker图像推送到GCR中的,但是,我的bucket是这样构造的,没有上面的结构。我看到了gs://artifacts.exproj.appspot.com/containers/images/,并且/images文件夹包含了我与清单相关的摘要。Re:docker login--您可能遇到了过期的凭据。GCR人员建议使用docker凭证助手或(如果您不能使用cred助手)JSON密钥:我使用的是
sudo docker login-u\u JSON\u密钥——密码stdinhttps://gcr.io 
method,但是,很有可能是过期或计时问题。我将对generation->ACL定义->和access运行一些测试。谢谢
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()