Подпишите образы контейнеров с помощью Notation, Azure Key Vault и сертификата, выданного УЦ

Эта статья является частью серии по обеспечению целостности и подлинности образов контейнеров и других артефактов Open Container Initiative (OCI). Для полного рисунка начните с обзора, в котором объясняется, почему подписывание имеет значение и описывает различные сценарии.

Подписывание и проверка образов контейнеров с помощью сертификата из доверенного центра сертификации (ЦС) является полезной практикой безопасности. Эта функция помогает ответственно идентифицировать, авторизовать и аутентифицировать как личность издателя образа контейнера, так и сам образ контейнера. Доверенные ЦС, такие как GlobalSign, DigiCert и другие, играют важную роль в:

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

Ниже приведены некоторые важные компоненты, которые обеспечивают возможность подписания и проверки образов контейнера с помощью сертификата от доверенного центра сертификации:

  • Нотация — это средство безопасности цепочки поставок с открытым исходным кодом, разработанное сообществом нотаричного проекта и поддерживаемым корпорацией Майкрософт. Он поддерживает подписывание и проверку образов контейнеров и других артефактов.
  • Azure Key Vault — это облачная служба для управления криптографическими ключами, секретами и сертификатами. Он помогает безопасно хранить сертификат с помощью ключа подписи и управлять им.
  • Подключаемый модуль Key Vault (notation-azure-kv) — это расширение Notation. В нем используются ключи, хранящиеся в Key Vault, для подписывания и проверки цифровых подписей образов контейнеров и артефактов.
  • Реестр контейнеров Azure — это частный реестр, который можно использовать для присоединения подписей к образам контейнеров, а также хранения и управления ими.

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

В этой статье вы узнаете, как:

  • Установите командный интерфейс Notation (CLI) и подключаемый модуль для Key Vault.
  • Создайте или импортируйте выданный ЦС сертификат в Key Vault.
  • Создание и отправка образа контейнера с помощью задач реестра контейнеров.
  • Подпишите образ контейнера, используя Notation CLI и подключаемый модуль Key Vault.
  • Проверьте подпись образа контейнера, используя Notation CLI.
  • Используйте метку времени.

Предварительные требования

  • Создайте или используйте реестр контейнеров для хранения образов и подписей контейнеров.
  • Создание или использование хранилища ключей. Рекомендуется создать новое хранилище ключей только для хранения сертификатов.
  • Установите и настройте последнюю версию Azure CLI или выполните команды в Azure Cloud Shell.

Установите CLI Notation и подключаемый модуль Key Vault

  1. Установите нотацию версии 1.3.2 в среде Linux AMD64. Чтобы скачать пакет для других сред, следуйте инструкциям по установке нотации.

    # Download, extract, and install
    curl -Lo notation.tar.gz https://github.com/notaryproject/notation/releases/download/v1.3.2/notation_1.3.2_linux_amd64.tar.gz
    tar xvzf notation.tar.gz
    
    # Copy the Notation CLI to the desired bin directory in PATH, for example
    cp ./notation /usr/local/bin
    
  2. Установите плагин Key Vault версии 1.2.1 (notation-azure-kv) в среде Linux AMD64.

    Примечание.

    Вы можете найти URL-адрес и контрольную сумму SHA256 для подключаемого модуля на странице выпуска подключаемого модуля.

    notation plugin install --url https://github.com/Azure/notation-azure-kv/releases/download/v1.2.1/notation-azure-kv_1.2.1_linux_amd64.tar.gz --sha256sum 67c5ccaaf28dd44d2b6572684d84e344a02c2258af1d65ead3910b3156d3eaf5
    
  3. Выведите список доступных подключаемых модулей и убедитесь, что notation-azure-kv подключаемый модуль с версией 1.2.1 включен в список:

    notation plugin ls
    

Настройка переменных среды

В этой статье используются переменные среды для удобства в конфигурации Key Vault и реестра контейнеров. Обновите значения этих переменных среды для определенных ресурсов.

  1. Настройте переменные среды для Key Vault и сертификатов:

    AKV_SUB_ID=myAkvSubscriptionId
    AKV_RG=myAkvResourceGroup
    AKV_NAME=myakv 
    
    # Name of the certificate created or imported in Key Vault 
    CERT_NAME=wabbit-networks-io 
    
    # X.509 certificate subject
    CERT_SUBJECT="CN=wabbit-networks.io,O=Notation,L=Seattle,ST=WA,C=US"
    
  2. Настройте переменные среды для реестра контейнеров и образов:

    ACR_SUB_ID=myAcrSubscriptionId
    ACR_RG=myAcrResourceGroup
    # Name of the existing registry example: myregistry.azurecr.io 
    ACR_NAME=myregistry 
    # Existing full domain of the container registry 
    REGISTRY=$ACR_NAME.azurecr.io 
    # Container name inside the container registry where the image will be stored 
    REPO=net-monitor 
    TAG=v1 
    # Source code directory that contains the Dockerfile to build 
    IMAGE_SOURCE=https://github.com/wabbit-networks/net-monitor.git#main  
    

Вход с помощью Azure CLI

az login

Дополнительные сведения см. в статье "Аутентификация в Azure" с помощью Azure CLI.

Создание или импорт сертификата, выданного ЦС, в Key Vault

Общие сведения о требованиях к сертификату

При создании сертификатов для подписи и проверки сертификаты должны соответствовать требованиям сертификата нотаричного проекта.

Ниже приведены требования к корневым и промежуточным сертификатам:

  • Расширение basicConstraints должно присутствовать и помечено как critical. Поле CA должно иметь trueзначение .
  • Расширение keyUsage должно присутствовать и помечено как critical. Битовые позиции для keyCertSign должны быть заданы.

Ниже приведены требования к сертификатам, которые выдаются ЦС:

  • Свойства сертификата X.509:
    • Тема должна содержать общее имя (), страну или регион (CNC), штат или провинцию (ST) и организацию (O). В этой статье $CERT_SUBJECT используется в качестве темы.
    • Флаг использования ключа X.509 должен быть только DigitalSignature.
    • Расширенные использования ключей (EKUs) должны быть пустыми или 1.3.6.1.5.5.7.3.3 (для подписывания кода).
  • Ключевые свойства:
    • Свойство exportable должно иметь значение false.
    • Выберите поддерживаемый тип ключа и размер из спецификации нотаричного проекта.

Внимание

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

В этом руководстве используется подключаемый модуль Key Vault версии 1.0.1. Предыдущие версии подключаемого модуля имели ограничение, требующее определенного порядка сертификатов в цепочке сертификатов. Версия 1.0.1 подключаемого модуля не имеет этого ограничения, поэтому рекомендуется использовать версию 1.0.1 или более позднюю.

Создание сертификата, выданного ЦС

Создайте запрос на подпись сертификата (CSR), следуя инструкциям в разделе "Создание и слияние запроса на подпись сертификата" в Key Vault.

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

Импорт сертификата в Key Vault

Чтобы импортировать сертификат, выполните следующие действия.

  1. Получите файл сертификата от поставщика ЦС со всей цепочкой сертификатов.
  2. Импортируйте сертификат в Key Vault, выполнив инструкции по импорту сертификата в Azure Key Vault.

Если сертификат не содержит цепочку сертификатов после создания или импорта, вы можете получить промежуточные и корневые сертификаты от поставщика ЦС. Вы можете попросить поставщика предоставить вам PEM-файл, содержащий промежуточные сертификаты (если таковые) и корневой сертификат. Затем этот файл можно использовать при подписи образов контейнеров.

Подпишите образ контейнера, используя CLI Notation и модуль Key Vault.

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

Авторизация доступа к реестру контейнеров

Для реестров, поддерживающих управление доступом на основе атрибутов Microsoft Entra (ABAC), роли Container Registry Repository Reader и Container Registry Repository Writer необходимы для создания и подписания образов контейнеров в реестре контейнеров.

Для реестров, не поддерживающих ABAC, требуются роли AcrPull и AcrPush.

Дополнительные сведения об ABAC см. в разделе "Управление доступом на основе атрибутов Microsoft Entra" для разрешений репозитория.

  1. Задайте подписку, содержащую ресурс реестра контейнеров:

    az account set --subscription $ACR_SUB_ID
    
  2. Назначьте роли:

    USER_ID=$(az ad signed-in-user show --query id -o tsv)
    ROLE1="Container Registry Repository Reader" # For ABAC-enabled registries. Otherwise, use "AcrPull" for non-ABAC-enabled registries.
    ROLE2="Container Registry Repository Writer" # For ABAC-enabled registries. Otherwise, use "AcrPush" for non-ABAC-enabled registries.
    az role assignment create --role "$ROLE1" --role "$ROLE2" --assignee $USER_ID --scope "/subscriptions/$ACR_SUB_ID/resourceGroups/$ACR_RG/providers/Microsoft.ContainerRegistry/registries/$ACR_NAME"
    

Создание и отправка образов контейнеров в реестр контейнеров

  1. Аутентификация в реестре контейнеров с использованием вашего индивидуального удостоверения Azure.

    az acr login --name $ACR_NAME
    

    Внимание

    Если у вас установлен Docker в системе, и вы использовали az acr login или docker login для аутентификации в реестре контейнеров, ваши учетные данные уже хранятся и доступны для Notation. В этом случае вам не нужно снова запускать notation login, чтобы выполнить аутентификацию в вашем реестре контейнеров. Чтобы узнать больше о параметрах аутентификации для нотации, см. статью «Аутентификация с помощью реестров, совместимых с OCI».

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

    DIGEST=$(az acr build -r $ACR_NAME -t $REGISTRY/${REPO}:$TAG $IMAGE_SOURCE --no-logs --query "outputImages[0].digest" -o tsv)
    IMAGE=$REGISTRY/${REPO}@$DIGEST
    

    В этой статье, если образ уже создан и хранится в реестре, тег служит идентификатором этого образа для удобства:

    IMAGE=$REGISTRY/${REPO}@$TAG
    

Авторизация доступа к Key Vault

В этом разделе рассматриваются два варианта авторизации доступа к Key Vault.

  1. Задайте подписку, содержащую ресурс Key Vault:

    az account set --subscription $AKV_SUB_ID
    
  2. Назначьте роли.

    Если сертификат содержит всю цепочку сертификатов, пользователь должен быть назначен на следующие роли:

    • Key Vault Secrets User для чтения секретов
    • Key Vault Certificates User для чтения сертификатов
    • Key Vault Crypto User для операций подписывания
    USER_ID=$(az ad signed-in-user show --query id -o tsv)
    az role assignment create --role "Key Vault Secrets User" --role "Key Vault Certificates User" --role "Key Vault Crypto User" --assignee $USER_ID --scope "/subscriptions/$AKV_SUB_ID/resourceGroups/$AKV_RG/providers/Microsoft.KeyVault/vaults/$AKV_NAME"
    

    Если сертификат не содержит цепочку, субъект должен быть назначен со следующими ролями:

    • Key Vault Certificates User для чтения сертификатов
    • Key Vault Crypto User для операций подписывания
    USER_ID=$(az ad signed-in-user show --query id -o tsv)
    az role assignment create --role "Key Vault Certificates User" --role "Key Vault Crypto User" --assignee $USER_ID --scope "/subscriptions/$AKV_SUB_ID/resourceGroups/$AKV_RG/providers/Microsoft.KeyVault/vaults/$AKV_NAME"
    

Дополнительные сведения о доступе Key Vault с помощью управления доступом на основе ролей Azure (RBAC) см. в статье Предоставление доступа к ключам Key Vault, сертификатам и секретам с помощью управления доступом на основе ролей Azure.

Использование политики доступа (устаревшая версия)

Чтобы задать подписку, содержащую ресурсы Key Vault, выполните следующую команду:

az account set --subscription $AKV_SUB_ID

Если сертификат содержит всю цепочку сертификатов, субъекту необходимо предоставить разрешение Signключа, разрешение Getсекрета и разрешение Getсертификата. Чтобы предоставить эти разрешения субъекту, используйте следующую команду:

USER_ID=$(az ad signed-in-user show --query id -o tsv)
az keyvault set-policy -n $AKV_NAME --key-permissions sign --secret-permissions get --certificate-permissions get --object-id $USER_ID

Если сертификат не содержит цепочку, основному субъекту необходимо предоставить разрешение Sign ключа и разрешение Get сертификата. Чтобы предоставить эти разрешения субъекту, используйте следующую команду:

USER_ID=$(az ad signed-in-user show --query id -o tsv)
az keyvault set-policy -n $AKV_NAME --key-permissions sign --certificate-permissions get --object-id $USER_ID

Чтобы узнать больше о назначении политики принципалу, см. статью "Назначение политики доступа к хранилищу ключей (версия для устаревших систем)."

Подписывайте образы контейнеров с помощью сертификата в Key Vault

  1. Получите идентификатор ключа для сертификата. Сертификат в Key Vault может иметь несколько версий. Следующая команда получает идентификатор ключа для последней $CERT_NAME версии сертификата:

    KEY_ID=$(az keyvault certificate show -n $CERT_NAME --vault-name $AKV_NAME --query 'kid' -o tsv) 
    
  2. Подпишите образ контейнера с использованием формата подписи и шифрования объектов CBOR (COSE) и идентификатора ключа.

    Если сертификат содержит всю цепочку сертификатов, выполните следующую команду:

    notation sign --signature-format cose $IMAGE --id $KEY_ID --plugin azure-kv 
    

    Если сертификат не содержит цепочку, используйте параметр --plugin-config ca_certs=<ca_bundle_file> для передачи сертификатов CA (ЦС) в файле PEM в подключаемый модуль Key Vault. Выполните следующую команду:

    notation sign --signature-format cose $IMAGE --id $KEY_ID --plugin azure-kv --plugin-config ca_certs=<ca_bundle_file> 
    

    Для аутентификации в Key Vault по умолчанию поочередно используются следующие типы учетных данных (если они включены).

    Если вы хотите указать тип учетных данных, используйте дополнительную конфигурацию credential_type подключаемого модуля. Например, вы можете явно установить credential_type как azurecli для использования учетных данных Azure CLI, как показано в этом примере:

    notation sign --signature-format cose --id $KEY_ID --plugin azure-kv --plugin-config credential_type=azurecli $IMAGE
    

    В следующей таблице показаны значения credential_type для различных типов учетных данных.

    Тип учетных данных Значение для credential_type
    Учетные данные для среды environment
    Идентификационные данные рабочей нагрузки workloadid
    Учетные данные для управляемого удостоверения managedid
    Учетные данные для входа с помощью Azure CLI azurecli
  3. Просмотрите график подписанных изображений и связанных подписей:

    notation ls $IMAGE
    

    В следующем примере выходных данных сигнатура типа application/vnd.cncf.notary.signature , определяемого дайджестом sha256:d7258166ca820f5ab7190247663464f2dcb149df4d1b6c4943dcaac59157de8e , связана с $IMAGE:

    myregistry.azurecr.io/net-monitor@sha256:17cc5dd7dfb8739e19e33e43680e43071f07497ed716814f3ac80bd4aac1b58f
    └── application/vnd.cncf.notary.signature
        └── sha256:d7258166ca820f5ab7190247663464f2dcb149df4d1b6c4943dcaac59157de8e
    

Примечание.

С версии 1.2.0, Notation использует схему тега ссылок OCI для хранения подписи в реестре контейнеров по умолчанию. При необходимости можно включить API ссылок OCI с помощью флага --force-referrers-tag false. Функции реестра контейнеров поддерживают API ссылок OCI, за исключением реестра, зашифрованного с помощью ключей, управляемых клиентом (CMKs).

Проверьте образ контейнера с помощью Notation CLI

  1. Добавьте корневой сертификат в именованное хранилище доверия для проверки подписи. Если у вас нет корневого сертификата, вы можете его получить у вашего центра сертификации. В следующем примере корневой сертификат $ROOT_CERT добавляется в $STORE_NAME хранилище доверия:

    STORE_TYPE="ca" 
    STORE_NAME="wabbit-networks.io" 
    notation cert add --type $STORE_TYPE --store $STORE_NAME $ROOT_CERT  
    
  2. Перечислите корневой сертификат, чтобы убедиться, что $ROOT_CERT он успешно добавлен:

    notation cert ls 
    
  3. Настройте политику доверия перед проверкой. Политики доверия позволяют пользователям указывать настраиваемые политики проверки подлинности. Используйте следующую команду:

    cat <<EOF > ./trustpolicy.json
    {
        "version": "1.0",
        "trustPolicies": [
            {
                "name": "wabbit-networks-images",
                "registryScopes": [ "$REGISTRY/$REPO" ],
                "signatureVerification": {
                    "level" : "strict" 
                },
                "trustStores": [ "$STORE_TYPE:$STORE_NAME" ],
                "trustedIdentities": [
                    "x509.subject: $CERT_SUBJECT"
                ]
            }
        ]
    }
    EOF
    

    trustpolicy.json Предыдущий файл определяет одну политику доверия с именемwabbit-networks-images. Эта политика доверия применяется ко всем артефактам, хранящимся в $REGISTRY/$REPO репозиториях. Именованное хранилище $STORE_NAME доверия типа $STORE_TYPE содержит корневые сертификаты. Эта политика также предполагает, что пользователь доверяет определенной идентичности с субъектом X.509 $CERT_SUBJECT. Дополнительные сведения см. в спецификации политики доверия и хранилища доверия.

  4. Используется notation policy для импорта конфигурации политики доверия из trustpolicy.json:

    notation policy import ./trustpolicy.json
    
  5. Отображение конфигурации политики доверия для подтверждения успешного импорта:

    notation policy show
    
  6. Используется notation verify для проверки целостности изображения:

    notation verify $IMAGE
    

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

    Successfully verified signature for myregistry.azurecr.io/net-monitor@sha256:17cc5dd7dfb8739e19e33e43680e43071f07497ed716814f3ac80bd4aac1b58f

Используйте метки времени

С момента выпуска версии 1.2.0, Нотация поддерживает совместимую с RFC 3161 метку времени. Это улучшение увеличивает доверие к подписям, созданным в течение срока действия сертификата, посредством доверия центру метки времени (TSA). Это доверие обеспечивает успешную проверку подписи даже после истечения срока действия сертификатов.

В качестве подписывающего контейнерные образы, убедитесь, что вы подписываете их с метками времени, созданными доверенной службой временной отметки (TSA). В качестве верификатора изображений необходимо убедиться, что вы доверяете как подписанту образа, так и связанному TSA, и устанавливаете это доверие через хранилища и политики доверия.

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

Вопросы и ответы

  • Что делать, если срок действия сертификата истекает?

    Если срок действия сертификата истекает, необходимо получить новый из доверенного поставщика ЦС вместе с новым закрытым ключом. Сертификат с истекшим сроком действия нельзя использовать для подписывания образов контейнеров.

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

  • Что делать, если сертификат отозван?

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

    Чтобы устранить эту проблему, сначала необходимо убедиться, что исходный код и среда сборки обновлены и защищены. Затем создайте образы контейнеров из исходного кода, получите новый сертификат от доверенного поставщика ЦС вместе с новым закрытым ключом и подписыв новые образы контейнеров новым сертификатом, следуя этому руководству.

Notation предоставляет решения для непрерывной интеграции и непрерывной доставки (CI/CD) в Azure Pipelines и GitHub Actions.

Чтобы обеспечить развертывание только доверенных образов контейнеров в службе Azure Kubernetes (AKS):