Google Container Registry Per Image ACLs

У нас есть структура внутри нашей платформы, которая требует большого количества частных изображений в рамках одного и / или только нескольких проектов, если это возможно. Кроме того, мы в значительной степени являемся магазином GCP и хотели бы оставаться в среде Google.

В настоящее время - насколько я понимаю - структуры ACL GCR требуют разрешений storage.objects.get и storage.objects.list (или роли objectViewer), прикрепленных к учетной записи службы (в данном случае) для доступа к GCR. Обычно это не проблема, и у нас не было никаких прямых проблем с использованием gsutil для включения доступа на чтение на уровне проекта для реестра контейнеров. Ниже приведен пример рабочего процесса того, что мы делаем для обеспечения общего доступа. Однако это не позволяет достичь нашей цели - ограничить учетную запись службы для доступа к изображениям.


Simple Docker Image создается, помечается и помещается в 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

Это дает нам репозиторий hello_example в проекте ex_proj. Мы создаем учетную запись службы и даем ей разрешение на чтение из корзины.

gsutil acl ch -u [email protected]: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 [email protected]:R gs://artifacts.exproj.appspot.com/hello_example/
CommandException: No URLs matched: gs://artifacts.exproj.appspot.com/hello_example/

В общей схеме мы хотели бы поразить следующую модель:

  • АккаунтA создал ImageA: TagA в ExampleProj
  • ServiceAccountA создается
  • ACL настроены для ServiceAccountA только для доступа к ExampleProj / ImageA и всем тегам под ним.
  • ServiceAccountA JSON предоставляется AccountA
  • AccountA теперь может получить доступ только к ExampleProj / ImageA, AccountB не может получить доступ к ExampleProj / ImageA AccountA.

Хотя мы могли бы создать реестр контейнеров для каждого проекта, для каждой учетной записи, возможность масштабирования, связанная с необходимостью отслеживать проекты для каждой учетной записи и зависеть от прихоти ограничений проекта GCP в период интенсивного использования, вызывает беспокойство.

Я открыт для любых идей или структур, которые могли бы достичь этого, кроме перечисленных выше!


РЕДАКТИРОВАТЬ

Спасибо jonjohnson за ответ! Я написал быстрый и грязный сценарий в соответствии с рекомендованными строками, относящимися к чтению блобов. Я все еще работаю над подтверждением его успеха, но я хотел заявить, что мы контролируем, когда происходят нажатия, поэтому отслеживание результатов менее хрупкое, чем могло бы быть в других ситуациях.

Вот сценарий, который я собрал в качестве примера для изменения разрешений manifest -> digest.

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 [email protected]:R gs://artifacts.exproj.appspot.com/containers/images/#{d}`
        puts res
    end
    puts "Permissions changed for org_b:example_b for [email protected]"
end

main()

Несмотря на то, что это соответствует установленным разрешениям, я вижу изрядную хрупкость фактической аутентификации в Docker и отказ от того, что логины Docker не идентифицируются.

Это было похоже на то, что вы имели в виду Джонджонсон? По сути, разрешая доступ для каждого большого двоичного объекта для каждой учетной записи службы на основе манифеста / слоев, связанных с этим изображением / тегом?

Спасибо!


person Matt Warner    schedule 28.06.2018    source источник
comment
Можете ли вы попробовать настроить таргетинг на gs: //artifacts.exproj.appspot.com/containers/repositories/library/hello_example/? Сообщение об ошибке означает, что вы выбрали неверный URL-адрес, попробуйте запустить gsutil ls gs: //artifacts.exproj.appspot.com/ и продолжайте выполнять команду, перемещаясь вниз по корзине, пока не найдете свое изображение.   -  person Patrick W    schedule 29.06.2018
comment
Спасибо за идею! Я действительно проверил, и, возможно, именно так я вставил образы докеров в GCR, но мои корзины структурированы как таковые без указанной выше структуры. Я вижу gs: //artifacts.exproj.appspot.com/containers/images/, а папка / images содержит мои дайджесты, связанные с манифестом.   -  person Matt Warner    schedule 29.06.2018
comment
Re: вход в докер - вы, вероятно, столкнулись с просроченными учетными данными. Ребята из GCR рекомендуют использовать помощник по учетным данным докера или (если вы не можете использовать помощник по кредитам) ключ JSON: cloud.google.com/container-registry/docs/   -  person jonjohnson    schedule 29.06.2018
comment
Я использую метод sudo docker login -u _json_key --password-stdin https://gcr.io < access-key.json, однако, вполне возможно, что в него добавлена ​​проблема с истечением срока действия или временем. Я проведу несколько тестов против генерации - ›Определение ACL -› и доступа. Спасибо!   -  person Matt Warner    schedule 29.06.2018


Ответы (1)


В настоящее время нет простого способа делать то, что вы хотите.

Одна вещь, которую вы можете сделать, - это предоставить доступ к отдельным каплям в вашей корзине для каждого изображения. Это не очень элегантно, потому что вам придется обновлять разрешения после каждого нажатия.

Вы можете автоматизировать это самостоятельно, используя поддержку pubsub в GCR для прослушивания для push-запросов посмотрите на большие двоичные объекты, на которые ссылается это изображение, сопоставьте путь репозитория с любыми учетными записями служб, которым необходим доступ, а затем предоставьте этим учетным записям служб доступ к каждому объекту большого двоичного объекта.

Одним из недостатков является то, что каждая учетная запись службы по-прежнему сможет просматривать манифест изображения (по сути, список дайджестов уровня + некоторая конфигурация времени выполнения изображения). Однако они не смогут извлечь фактическое содержимое изображения.

Кроме того, это немного зависит от некоторых деталей реализации GCR, поэтому в будущем он может сломаться.

person jonjohnson    schedule 28.06.2018
comment
Привет, спасибо за ответ! Я добавил правку на свой верхний уровень, следуя вашим рекомендациям и потенциальным проблемам, связанным с этим. - person Matt Warner; 29.06.2018
comment
Принимая это как ответ, я могу обойти ACL-списки BLOB-объектов, чтобы заставить это работать. Однако мы, вероятно, собираемся двигаться в другом направлении, чтобы обеспечить разделение, но по-прежнему использовать реестр контейнеров для внутренних целей. Спасибо! - person Matt Warner; 02.07.2018