Автор статьи: Рустем Галиев

IBM Senior DevOps Engineer & Integration Architect. Официальный DevOps ментор и коуч в IBM

Открытые контейнерные платформы, такие как OpenShift, стали неотъемлемой частью современной разработки и управления приложениями. Они обеспечивают удобство и надежность развертывания приложений в контейнерах, обеспечивая изоляцию, масштабируемость и управление ресурсами. Однако, для того чтобы максимально использовать преимущества контейнеризации, необходимо правильно настроить образы контейнеров.

В данной статье мы погрузимся в мир контейнеризации и OpenShift и углубимся в процесс создания и подписывания образов для контейнеров. Рассмотрим, почему безопасность и целостность образов играют важную роль в современных разработках и какие инструменты предоставляет OpenShift для обеспечения этой безопасности. Также разберем шаги по созданию, настройке и подписыванию образов, чтобы вы могли быть уверены в их надежности и готовности к развертыванию в вашем кластере OpenShift. Давайте начнем с основ и перейдем к более глубоким аспектам создания образов для контейнеров в OpenShift.

Есть разные инструменты для этого, например:

  • GPG (GNU Privacy Guard). Для обеспечения безопасности контейнерных образов вы можете использовать GPG при создании и управлении ключевой пары, а затем подписывать образы с использованием вашего приватного ключа.

  • Cosign - это инструмент, разработанный командой Google, который предоставляет возможность подписывать и проверять подписи контейнерных образов. Он разработан с целью обеспечения безопасности и доверия при работе с контейнерами, особенно в контексте поставки и развертывания контейнерных образов.

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

    Подписание контейнерных образов - это важная практика в мире контейнеризации по нескольким ключевым причинам:

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

  • Подлинность и идентификация. Подписи образов позволяют удостовериться в подлинности создателя образа. Это означает, что вы можете доверять образам, которые были подписаны известными и доверенными источниками. Это особенно важно при использовании образов из открытых источников, таких как общедоступные реестры Docker Hub.

  • Управление версиями и репозиториями. Подписи образов помогают в управлении версиями образов и репозиториями. Они могут служить как индикаторы доверия к определенной версии образа, и они облегчают отслеживание изменений и управление различными версиями образов.

  • Безопасность. Подписанные образы усиливают безопасность контейнерных приложений и инфраструктуры. Проверка подписей позволяет обнаруживать потенциальные угрозы и недопустимые изменения в образах до их развертывания.

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

  • Доверие в распределенных системах. В распределенных окружениях, таких как Kubernetes и OpenShift, где контейнеры могут развертываться на разных узлах и в разных средах, подписи образов помогают обеспечить доверие и безопасность.

Мы решили использовать cosign. Для начала установим:

$ git clone https://github.com/sigstore/cosign
$ cd cosign
$ go install ./cmd/cosign
$ $(go env GOPATH)/bin/cosign

Сгенерируем ключ:

cosign generate-key-pair

Мы генерируем совершенно новую пару ключей: cosign.key и cosign.pub.

Закрытые ключи должны быть безопасными и их можно расшифровать/подписать с помощью пароля, хранящегося в секретном менеджере как часть CI. Для этого мы используем HashiCorp Vault, но из альтернатив, хорошим вариантом может быть Amazon KMS. Важно убедиться, что доступ к секретам ограничен областью конвейера и не доступен глобально в используемом вами инструменте ci/cd.

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

Прежде всего, необходимо опубликовать образ в реестре, где у нас есть права на запись. Невозможно подписать образы из реестра, в котором у нас нет разрешения на запись.

cosign sign --key cosign.key atntqa:signed

Эта команда создает новый тег SHAxxx.sig в нашем реестре OCI. Вы можете убедиться, что имя тега содержит дайджест изображения, загруженного с тегом «signed».

Чтобы запустить проверку подписи на подписанном образе, мы теперь используем открытый ключ cosign.pub.

cosign verify --key cosign.pub guillermopal/contenttrust:signed | jq .

Это все, что нужно было сделать.

Есть еще один вариант подписи образов, это использование Garantir, gpg-key и skopeo.

Первым шагом будет регистрация на платформе Garantir, создание ключа в web-ui и скачивание клиента:

После этого установим клиент, скачиваем tgz с клиентом и используем следующий скрипт:

rm -rf ~/.cache/Garantir/
sudo /opt/Garantir/bin/grsgpgconfig.sh
/opt/Garantir/bin/GrsGPGLoader

LD_LIBRARY_PATH=/opt/Garantir/lib:$LD_LIBRARY_PATH
LIBRARY_PATH=/opt/Garantir/lib:$LIBRARY_PATH
PATH=/opt/Garantir/bin:$PATH
GNUPGHOME=~/.gnupggrs
GPGCONF_PATH=/opt/Garantir/bin/gpgconf
export PATH=/opt/Garantir/bin:$PATH

# Run the agent
/opt/Garantir/bin/gpg-agent --daemon --homedir $HOME/.gnupggrs --options $HOME/.gnupggrs/gpg-agent.conf

/opt/Garantir/bin/gpg --homedir $HOME/.gnupggrs/ -k
export FINGERPRINT=$(/opt/Garantir/bin/gpg --homedir $HOME/.gnupggrs/ --fingerprint --with-colons | grep fpr | tr -d 'fpr:')

Находим gpg-key:

/opt/Garantir/bin/gpg --homedir $HOME/.gnupggrs/ -k
export FINGERPRINT=$(/opt/Garantir/bin/gpg --homedir $HOME/.gnupggrs/ --fingerprint --with-colons | grep fpr | tr -d 'fpr:')

Подписываем:

GNUPGHOME=~/.gnupggrs skopeo copy dir:<imagedir> docker://icr.io/<repo:newimage:tag> --dest-creds iamapikey:key  --sign-by <gpgkeyfingerprint>  


GNUPGHOME=~/.gnupggrs skopeo copy docker://icr.io/<repo:image:tag> docker://icr.io/<repo:newimage:tag> --dest-creds iamapikey:key --src-creds iamapikey:key --sign-by <gpgkeyfingerprint>

Экспортируем publickey и certificate

export certkeyalias=$(/opt/Garantir/bin/garasign listkeys | grep -i key | awk 'NR==2{print $8 }')

/opt/Garantir/bin/garasign export --key $certkeyalias --outputDirectory /Path/ToStorePublicKeys/

Теперь проверяем подпись.

Создаем файл /etc/containers/policy.json

{
 	"default": [
    	{
        	"type":"reject"
    	}
	],
	"transports":
    	{
        	"docker":
            	{
                	"": [{ "type": "signedBy", "keyType": "GPGKeys", "keyPath": "<public key>"}]
            	}
    	}
}

Валидируем:

skopeo copy --policy ~/policy.json docker://icr.io/myproduct/myimage@sha256:abc123... dir:./temp

Также проверим Chain of trust:

export gpgkeyfingerprint=$(/opt/Garantir/bin/gpg --homedir /root/.gnupggrs/ --fingerprint --with-colons | grep fpr | tr -d 'fpr:')

export certkeyalias=$(/opt/Garantir/bin/garasign listkeys | grep -i key | awk 'NR==2{print $8 }')
/opt/Garantir/bin/garasign export --key $certkeyalias --outputDirectory /tmp

openssl x509 -text -in CertKeyAlias.pem.cer
gpg2 -v --list-packets CertKeyAlias.pub.asc

Готово, вы восхитительны!

В мире DevSecOps, где безопасность, надежность и производительность становятся неотъемлемой частью процессов разработки и развертывания, подписание контейнерных образов играет ключевую роль. Это не просто техническая деталь, но и важное стратегическое решение, направленное на снижение рисков и обеспечение бесперебойной работы вашей инфраструктуры.

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

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

В завершение хочу порекомендовать вам бесплатный урок, посвященный разбору уязвимостей OWASP Top 10 Web. Регистрация доступна по ссылке.

Комментарии (0)