Подпись и проверка Docker-образов Yandex Container Registry в Yandex Managed Service for Kubernetes
В этом сценарии описано, как подписать Docker-образы с помощью Cosign
Чтобы подписать и настроить проверку Docker-образов:
- Подпишите Docker-образ с помощью Cosign.
- Создайте политику для проверки подписей.
- Проверьте результат.
Если созданные ресурсы вам больше не нужны, удалите их.
Перед началом работы
Подготовьте инфраструктуру
-
- Сервисный аккаунт для ресурсов с ролью editor на каталог, в котором создается кластер Managed Service for Kubernetes. От его имени будут создаваться ресурсы, необходимые кластеру Managed Service for Kubernetes.
- Сервисный аккаунт для узлов с ролью container-registry.images.puller на каталог с реестром Docker-образов. От его имени узлы будут скачивать из реестра необходимые Docker-образы.
Вы можете использовать один и тот же сервисный аккаунт для обеих операций.
-
Создайте группы безопасности для кластера Managed Service for Kubernetes и входящих в него групп узлов.
Важно
От настройки групп безопасности зависит работоспособность и доступность кластера, а также запущенных в нем сервисов и приложений.
-
Создайте кластер Managed Service for Kubernetes и группу узлов. При создании кластера укажите ранее созданные сервисные аккаунты для ресурсов и узлов и группы безопасности.
-
Если у вас еще нет Terraform, установите его.
-
Получите данные для аутентификации. Вы можете добавить их в переменные окружения или указать далее в файле с настройками провайдера.
-
Настройте и инициализируйте провайдер. Чтобы не создавать конфигурационный файл с настройками провайдера вручную, скачайте его
. -
Поместите конфигурационный файл в отдельную рабочую директорию и укажите значения параметров. Если данные для аутентификации не были добавлены в переменные окружения, укажите их в конфигурационном файле.
-
Скачайте в ту же рабочую директорию файл конфигурации k8s-validate-cr-image.tf
.В этом файле описаны:
-
Сеть.
-
Реестр Container Registry.
-
Кластер Managed Service for Kubernetes.
-
Сервисный аккаунт, необходимый для работы кластера и группы узлов Managed Service for Kubernetes.
-
Группы безопасности, которые содержат необходимые правила для кластера Managed Service for Kubernetes и входящих в него групп узлов.
Важно
От настройки групп безопасности зависит работоспособность и доступность кластера, а также запущенных в нем сервисов и приложений.
-
-
Укажите в файле
k8s-validate-cr-image.tf
:- Идентификатор каталога.
- Версию Kubernetes для кластера и групп узлов Managed Service for Kubernetes.
- CIDR кластера Managed Service for Kubernetes.
- Имя сервисного аккаунта кластера.
- Имя реестра Container Registry.
-
Проверьте корректность файлов конфигурации Terraform с помощью команды:
terraform validate
Если в файлах конфигурации есть ошибки, Terraform на них укажет.
-
Создайте необходимую инфраструктуру:
-
Выполните команду для просмотра планируемых изменений:
terraform plan
Если конфигурации ресурсов описаны верно, в терминале отобразится список изменяемых ресурсов и их параметров. Это проверочный этап: ресурсы не будут изменены.
-
Если вас устраивают планируемые изменения, внесите их:
-
Выполните команду:
terraform apply
-
Подтвердите изменение ресурсов.
-
Дождитесь завершения операции.
-
В указанном каталоге будут созданы все требуемые ресурсы. Проверить появление ресурсов и их настройки можно в консоли управления
. -
Подготовьтесь к работе с кластером Managed Service for Kubernetes
-
Установите kubectl
и настройте его на работу с созданным кластером. - Установите менеджер пакетов Kubernetes Helm
.
Добавьте несколько Docker-образов в реестр Container Registry
- Настройте Docker и аутентифицируйтесь в Container Registry.
- Создайте несколько Docker-образов. Один из образов в дальнейшем будет подписан с помощью Cosign, остальные образы будут неподписанными.
- Загрузите Docker-образы в реестр Container Registry.
Подпишите Docker-образ с помощью утилиты Cosign
-
Установите специальную сборку Cosign для вашей операционной системы:
-
Получите Yandex Identity and Access Management-токен и сохраните его в переменную среды
$YC_IAM_TOKEN
:-
Bash:
export YC_IAM_TOKEN=$(yc iam create-token)
-
PowerShell:
$env:YC_IAM_TOKEN = $(yc iam create-token)
-
-
Авторизуйтесь в Container Registry:
-
Bash:
docker login \ --username iam \ --password $YC_IAM_TOKEN \ cr.yandex
-
PowerShell:
docker login ` --username iam ` --password $Env:YC_IAM_TOKEN ` cr.yandex
Результат:
WARNING! Using --password via the CLI is insecure. Use --password-stdin. Login Succeeded
Примечание
Чтобы не использовать Credential helper при аутентификации, удалите в конфигурационном файле
${HOME}/.docker/config.json
из блокаcredHelpers
строку доменаcr.yandex
. -
-
Создайте и сохраните в Key Management Service ключевую пару электронной подписи:
cosign generate-key-pair \ --kms yckms:///folder/<идентификатор_каталога>/keyname/<имя_ключевой_пары>
Где:
<идентификатор_каталога>
— идентификатор каталога, в котором будет сохранена создаваемая ключевая пара.<имя_ключевой_пары>
— имя создаваемой ключевой пары подписи.
Результат:
client.go:183: Using IAM Token from 'YC_IAM_TOKEN' environment variable as credentials client.go:310: generated yckms KEY_ID: '<идентификатор_ключевой_пары>' Public key written to cosign.pub
Утилита вернет идентификатор созданной ключевой пары подписи и сохранит открытый ключ подписи в локальный файл. Сохраните идентификатор ключевой пары, он понадобится вам на следующих шагах.
Идентификатор ключевой пары подписи всегда можно получить в консоли управления
или с помощью команды CLI. -
Подпишите образ в Container Registry:
cosign sign \ --key yckms:///<идентификатор_ключевой_пары> \ cr.yandex/<идентификатор_реестра>/<имя_Docker-образа>:<тег> \ --tlog-upload=false
Где:
<идентификатор_ключевой_пары>
— идентификатор ключевой пары подписи, полученный на предыдущем шаге.<идентификатор_реестра>
— идентификатор реестра Container Registry, в котором находится подписываемый образ.<имя_Docker-образа>
— имя подписываемого Docker-образа в реестре Container Registry.<тег>
— тег версии образа, которую требуется подписать.
Результат:
Pushing signature to: cr.yandex/<идентификатор_реестра>/<имя_Docker-образа>
В реестре Container Registry должен появиться второй объект с тегом
sha256-....sig
и хэшемcr.yandex/<идентификатор_реестра>/<имя_Docker-образа>@sha256:...
. -
Вручную проверьте, что подпись Docker-образа корректна:
cosign verify \ --key yckms:///<идентификатор_ключевой_пары> \ cr.yandex/<идентификатор_реестра>/<имя_Docker-образа>:<тег> \ --insecure-ignore-tlog
Где:
<идентификатор_ключевой_пары>
— полученный ранее идентификатор ключевой пары подписи.<идентификатор_реестра>
— идентификатор реестра Container Registry, в котором находится образ.<имя_Docker-образа>
— имя Docker-образа в реестре Container Registry.<тег>
— тег версии образа, для которой требуется проверить подпись.
Результат:
Verification for cr.yandex/<идентификатор_реестра>/<имя_Docker-образа>:<тег> -- The following checks were performed on each of these signatures: - The cosign claims were validated - The signatures were verified against the specified public key [{"critical":{"identity":{"docker-reference":"cr.yandex/<идентификатор_реестра>/<имя_Docker-образа>"},"image":{"docker-manifest-digest":"sha256:..."},"type":"cosign container image signature"},"optional":null}]
-
Создайте пару ключей с помощью Cosign:
cosign generate-key-pair
Задайте и дважды введите пароль для закрытого ключа.
Результат:
Enter password for private key: Enter password for private key again: Private key written to cosign.key Public key written to cosign.pub
-
Подпишите Docker-образ в реестре Container Registry:
cosign sign \ --key cosign.key \ cr.yandex/<идентификатор_реестра>/<имя_Docker-образа>:<тег>
Подписанный образ будет использоваться при проверке результата.
Укажите пароль закрытого ключа. Результат:
Enter password for private key: Pushing signature to: cr.yandex/<идентификатор_реестра>/<имя_Docker-образа>
В реестре Container Registry должен появиться второй объект с тегом
sha256-....sig
и хэшемcr.yandex/<идентификатор_реестра>/<имя_Docker-образа>@sha256:...
. -
Вручную проверьте, что подпись Docker-образа корректна:
cosign verify \ --key cosign.pub \ cr.yandex/<идентификатор_реестра>/<имя_Docker-образа>:<тег>
Результат:
Verification for cr.yandex/<идентификатор_реестра>/<имя_Docker-образа>:<тег> -- The following checks were performed on each of these signatures: - The cosign claims were validated - The signatures were verified against the specified public key [{"critical":{"identity":{"docker-reference":"cr.yandex/<идентификатор_реестра>/<имя_Docker-образа>"},"image":{"docker-manifest-digest":"sha256:..."},"type":"cosign container image signature"},"optional":null}]
Создайте политику для проверки подписей
-
Создайте авторизованный ключ для сервисного аккаунта с ролью container-registry.images.puller и запишите его в файл:
yc iam key create \ --service-account-name=<имя_сервисного_аккаунта> \ --output authorized-key.json
Где
--service-account-name
— имя сервисного аккаунта с ролью container-registry.images.puller. -
Установите приложение Kyverno
в кластер Managed Service for Kubernetes. Оно необходимо для создания политики, которой проверяются подписи Docker-образов.-
Добавьте репозиторий
kyverno
:helm repo add kyverno https://kyverno.github.io/kyverno/
Результат:
"kyverno" has been added to your repositories
-
Установите приложение Kyverno в пространство имен
kyverno
:helm install kyverno kyverno/kyverno \ --namespace kyverno \ --create-namespace \ --set replicaCount=1 \ --set imagePullSecrets.regcred.registry=cr.yandex \ --set imagePullSecrets.regcred.username=json_key \ --set-file imagePullSecrets.regcred.password=./authorized-key.json
Результат:
NAME: kyverno LAST DEPLOYED: Thu Sep 8 10:43:00 2022 NAMESPACE: kyverno STATUS: deployed ...
-
-
Создайте политику:
-
Сохраните спецификацию для создания объекта
ClusterPolicy
в YAML-файл с названиемpolicy.yaml
:apiVersion: kyverno.io/v1 kind: ClusterPolicy metadata: name: check-image spec: validationFailureAction: enforce background: false webhookTimeoutSeconds: 30 failurePolicy: Fail rules: - name: check-image match: any: - resources: kinds: - Pod verifyImages: - imageReferences: - "cr.yandex/<идентификатор_реестра>/*" attestors: - count: 1 entries: - keys: publicKeys: |- <содержимое_cosign.pub>
Пример заполненного файла policy.yaml.
apiVersion: kyverno.io/v1 kind: ClusterPolicy metadata: name: check-image spec: validationFailureAction: enforce background: false webhookTimeoutSeconds: 30 failurePolicy: Fail rules: - name: check-image match: any: - resources: kinds: - Pod verifyImages: - imageReferences: - "cr.yandex/crpd2f2bnrlb********/*" attestors: - count: 1 entries: - keys: publicKeys: |- -----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE1jTu/9rJZZvUFi4bGhlvgMQdIY97 7NuGl2zzpV7olAyIu/WiywxI7Fny5tk6JmNPIFvSAtys3c08gfEc******** -----END PUBLIC KEY-----
Примечание
По умолчанию при создании политики выполняется запрос проверки подписи в хранилище неизменяемых записей Transparency Log. Вы можете отключить его — для этого добавьте в элемент
keys
спецификации политики параметрrekor: ignoreTlog: true
. Подробнее см. в документации Kyverno . -
Выполните команду:
kubectl apply -f ./policy.yaml
Результат:
clusterpolicy.kyverno.io/check-image configured
-
-
(Опционально) Установите Policy Reporter в кластер Managed Service for Kubernetes, чтобы получить возможность сохранять и обрабатывать результаты срабатывания политики.
Проверьте результат
-
Создайте под из подписанного Docker-образа:
kubectl run pod --image=cr.yandex/<идентификатор_реестра>/<имя_Docker-образа>:<тег>
Результат:
pod/pod created
-
Создайте под из неподписанного Docker-образа:
kubectl run pod2 --image=cr.yandex/<идентификатор_реестра>/<имя_неподписанного_Docker-образа>:<тег>
Результат:
Error from server: admission webhook "mutate.kyverno.svc-fail" denied the request: resource Pod/default/pod2 was blocked due to the following policies check-image: check-image: failed to verify signature for cr.yandex/crpsere9njsa********/alpine:2.0: .attestors[0].entries[0].keys: no matching signatures:
Удалите созданные ресурсы
Некоторые ресурсы платные. Чтобы за них не списывалась плата, удалите ресурсы, которые вы больше не будете использовать:
- Удалите кластер Managed Service for Kubernetes.
- Если вы зарезервировали для кластера публичный статический IP-адрес, удалите его.
- Удалите сервисные аккаунты.
- Удалите все Docker-образы из реестра Container Registry.
- Удалите реестр Container Registry.
-
В терминале перейдите в директорию с планом инфраструктуры.
Важно
Убедитесь, что в директории нет Terraform-манифестов с ресурсами, которые вы хотите сохранить. Terraform удаляет все ресурсы, которые были созданы с помощью манифестов в текущей директории.
-
Удалите ресурсы:
-
Выполните команду:
terraform destroy
-
Подтвердите удаление ресурсов и дождитесь завершения операции.
Все ресурсы, которые были описаны в Terraform-манифестах, будут удалены.
-