次の方法で共有


Notation、Azure Key Vault、自己署名証明書を使用してコンテナー イメージに署名する

この記事は、コンテナー イメージとその他の Open Container Initiative (OCI) 成果物の整合性と信頼性を確保するためのシリーズの一部です。 全体像を把握するには、概要から始めて、署名が重要な理由を説明し、さまざまなシナリオを詳細にわたって説明します。

コンテナー イメージの署名は、信頼性と整合性を確保するのに役立つプロセスです。 コンテナー イメージに追加されたデジタル署名は、デプロイ中に検証されます。 署名は、イメージが信頼できる発行元からのものであり、変更されていないことを確認するのに役立ちます。

この記事では、署名プロセスに関連する次のツールについて説明します。

  • Notation は、 Notary Project コミュニティ によって開発され、Microsoft によってサポートされているオープンソースのサプライ チェーン セキュリティ ツールです。 コンテナー イメージとその他の成果物の署名と検証がサポートされています。

    継続的インテグレーションおよび継続的デリバリー (CI/CD) パイプラインで Notation を使用してコンテナー イメージに署名する場合は、 Azure Pipelines または GitHub Actions のガイダンスに従ってください。

  • Azure Key Vault は、署名キーを使用して証明書を格納するためのサービスです。 ノーテーションは、Key Vaultプラグイン (notation-azure-kv) を通じてこれらのキーを使用して、コンテナーイメージおよびその他のアーティファクトの署名と検証を行うことができます。

  • Azure Container Registry は、コンテナー イメージやその他の成果物に署名をアタッチし、それらの署名を表示するために使用できるプライベート レジストリです。

この記事では、次の方法について説明します。

  • Notation コマンド ライン インターフェイス (CLI) と Key Vault プラグインをインストールします。
  • Key Vault で自己署名証明書を作成します。
  • Container Registry タスクを使用してコンテナー イメージをビルドしてプッシュします。
  • Notation CLI と Key Vault プラグインを使用してコンテナー イメージに署名します。
  • Notation CLI を使用して、署名に対してコンテナー イメージを検証します。
  • タイムスタンプを使用します。

前提条件

Notation CLI と Key Vault プラグインをインストールする

  1. Linux AMD64 環境に Notation v1.3.2 をインストールします。 他の環境用のパッケージをダウンロードするには、 Notation インストール ガイドに従ってください。

    # 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 binary to the desired bin directory in $PATH, for example
    cp ./notation /usr/local/bin
    
  2. Linux AMD64 環境に Key Vault プラグイン (notation-azure-kv) v1.2.1 をインストールします。

    プラグインの 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
    

環境変数を構成する

この記事のコマンドを簡単に実行するには、既存の Container Registry と Key Vault のリソースと一致するように Azure リソースの値を指定します。

  1. Key Vault リソース名を構成します。

    AKV_SUB_ID=myAkvSubscriptionId
    AKV_RG=myAkvResourceGroup
    # Name of the existing key vault used to store the signing keys
    AKV_NAME=myakv
    # Name of the certificate created in the key vault
    CERT_NAME=wabbit-networks-io
    CERT_SUBJECT="CN=wabbit-networks.io,O=Notation,L=Seattle,ST=WA,C=US"
    CERT_PATH=./${CERT_NAME}.pem
    
  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
    IMAGE=$REGISTRY/${REPO}:$TAG
    # 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 CLI を使用した Azure への認証」を参照してください。

Container Registry と Key Vault へのアクセス許可を付与する

Container Registry と Key Vault を使用する場合は、セキュリティで保護された制御されたアクセスを確保するために、適切なアクセス許可を付与することが不可欠です。 特定のシナリオに応じて、ユーザー プリンシパル、サービス プリンシパル、マネージド ID など、さまざまなエンティティのアクセスを承認できます。 この記事では、サインインしている Azure ユーザーに対してアクセスが承認されています。

Container Registry へのアクセスを承認する

Microsoft Entra 属性ベースのアクセス制御 (ABAC) が有効になっているレジストリの場合、Container Registry でコンテナー イメージを構築および署名するために、 Container Registry Repository Reader ロールと Container Registry Repository Writer ロールが必要です。

ABAC に対して有効になっていないレジストリの場合は、 AcrPull ロールと AcrPush ロールが必要です。

ABAC の詳細については、リポジトリのアクセス許可に関する Microsoft Entra 属性ベースのアクセス制御に関するページを参照してください。

  1. Container Registry リソースを含むサブスクリプションを設定します。

    az account set --subscription $ACR_SUB_ID
    
  2. ロールを割り当てます。 ロールの割り当てで使用する正しいロールは、レジストリが ABAC 有効かどうかによって異なります。

    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"
    

Key Vault へのアクセスを承認する

このセクションでは、Key Vault へのアクセスを承認するための 2 つのオプションについて説明します。

自己署名証明書を使用した署名には、次のロールが必要です。

  • 証明書の作成と読み取り用の Key Vault Certificates Officer
  • Key Vault Certificates User 既存の証明書を読み取る場合
  • 署名操作用の Key Vault Crypto User

Azure ロールベースのアクセス制御 (RBAC) による Key Vault アクセスの詳細については、「Azure ロールベースのアクセス制御 を使用して Key Vault のキー、証明書、シークレットへのアクセスを提供する」を参照してください。

  1. Key Vault リソースを含むサブスクリプションを設定します。

    az account set --subscription $AKV_SUB_ID
    
  2. ロールを割り当てます。

    USER_ID=$(az ad signed-in-user show --query id -o tsv)
    az role assignment create --role "Key Vault Certificates Officer" --role "Key Vault Crypto User" --assignee $USER_ID --scope "/subscriptions/$AKV_SUB_ID/resourceGroups/$AKV_RG/providers/Microsoft.KeyVault/vaults/$AKV_NAME"
    

Key Vault でアクセス ポリシーを割り当てる (レガシ)

ID には以下のアクセス許可が必要です。

  • 証明書の作成用の Create アクセス許可
  • 既存の証明書の読み取り用の Get アクセス許可
  • 署名操作用の Sign アクセス許可

プリンシパルへのポリシーの割り当ての詳細については、「 Key Vault アクセス ポリシー (レガシ) の割り当て」を参照してください。

  1. Key Vault リソースを含むサブスクリプションを設定します。

    az account set --subscription $AKV_SUB_ID
    
  2. Key Vault でアクセス ポリシーを設定します。

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

重要

この例では、証明書を作成してコンテナー イメージに署名するために必要な最小限のアクセス許可を示します。 要件によっては、さらにアクセス許可を付与する必要がある場合があります。

Key Vault で自己署名証明書を作成する (Azure CLI)

次の手順では、テスト目的で自己署名証明書を作成する方法を示します。

  1. 証明書のポリシー ファイルを作成します。

    次のコードを使用して証明書ポリシー ファイルを実行すると、Key Vault の Notary Project 証明書要件 と互換性のある有効な証明書が作成されます。 ekusの値はコード署名用ですが、Notation で成果物に署名する必要はありません。 サブジェクトは、後で検証中に信頼できる ID として使用されます。

    cat <<EOF > ./my_policy.json
    {
        "issuerParameters": {
        "certificateTransparency": null,
        "name": "Self"
        },
        "keyProperties": {
          "exportable": false,
          "keySize": 2048,
          "keyType": "RSA",
          "reuseKey": true
        },
        "secretProperties": {
          "contentType": "application/x-pem-file"
        },
        "x509CertificateProperties": {
        "ekus": [
            "1.3.6.1.5.5.7.3.3"
        ],
        "keyUsage": [
            "digitalSignature"
        ],
        "subject": "$CERT_SUBJECT",
        "validityInMonths": 12
        }
    }
    EOF
    
  2. 証明書を作成します。

    az keyvault certificate create -n $CERT_NAME --vault-name $AKV_NAME -p @my_policy.json
    

Notation CLI と Key Vault プラグインを使用してコンテナー イメージに署名する

  1. 個々の Azure ID を使用して、コンテナー レジストリに対して認証を行います。

    az acr login --name $ACR_NAME
    

    重要

    Docker がシステムにインストールされていて、 az acr login または docker login を使用してコンテナー レジストリに対する認証を行った場合、資格情報は既に保存されており、Notation で使用できます。 この場合、コンテナー レジストリに対する認証を行うために notation login をもう一度実行する必要はありません。 Notation の認証オプションの詳細については、「 OCI に準拠したレジストリを使用した認証」を参照してください。

  2. Azure Container Registry タスクを使用して、新しいイメージをビルドしてプッシュします。 タグは変更可能であり、上書きできるため、常にダイジェスト値を使用して署名用のイメージを識別します。

    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
    
  3. 署名キーの ID を取得します。 Key Vault の証明書には、複数のバージョンを含めることができます。 次のコマンドは、最新バージョンのキー ID を取得します。

    KEY_ID=$(az keyvault certificate show -n $CERT_NAME --vault-name $AKV_NAME --query 'kid' -o tsv)
    
  4. 署名キー ID を使用して、 CBOR オブジェクト署名および暗号化 (COSE) 署名形式でコンテナー イメージに署名します。 自己署名証明書で署名するには、プラグイン構成値を self_signed=true設定する必要があります。

    notation sign --signature-format cose --id $KEY_ID --plugin azure-kv --plugin-config self_signed=true $IMAGE
    

    Key Vault で認証するために、既定では、次の資格情報の種類 (有効な場合) が順番に試行されます。

    資格情報の種類を指定する場合は、 credential_typeと呼ばれる追加のプラグイン構成を使用します。 たとえば、次の例に示すように、azure CLI 資格情報を使用するためのcredential_typeazurecliを明示的に設定できます。

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

    次の表に、さまざまな資格情報の種類の credential_type の値を示します。

    資格情報の種類 credential_type の値
    環境資格情報 environment
    ワークロード ID 資格情報 workloadid
    マネージド ID 資格情報 managedid
    Azure CLI の資格情報 azurecli

    Notation v1.2.0 以降、Notation では OCI 参照元タグ スキーマ を使用して、署名が既定でコンテナー レジストリに格納されます。 必要に応じて、フラグ を使用して --force-referrers-tag false を有効にすることもできます。 Container Registry 機能は、カスタマー マネージド キー (CMK) を介して暗号化されたレジストリを除き、OCI Referrers API をサポートします。

  5. 署名されたイメージと関連する署名のグラフを表示します。

    notation ls $IMAGE
    

Notation CLI を使用してコンテナー イメージを確認する

コンテナー イメージを確認するには、リーフ証明書に署名するルート証明書を信頼ストアに追加し、検証用の信頼ポリシーを作成します。 この記事で使用する自己署名証明書の場合、ルート証明書は自己署名証明書自体です。

  1. パブリック証明書をダウンロードします。

    az keyvault certificate download --name $CERT_NAME --vault-name $AKV_NAME --file $CERT_PATH
    
  2. 署名検証のために、ダウンロードしたパブリック証明書を名前付き信頼ストアに追加します。

    STORE_TYPE="ca"
    STORE_NAME="wabbit-networks.io"
    notation cert add --type $STORE_TYPE --store $STORE_NAME $CERT_PATH
    
  3. 確認する証明書を一覧表示します。

    notation cert ls
    
  4. 検証の前に信頼ポリシーを構成します。

    信頼ポリシーを使用すると、ユーザーは微調整された検証ポリシーを指定できます。 次の例では、 wabbit-networks-imagesという名前の信頼ポリシーを構成します。 このポリシーは、$REGISTRY/$REPO内のすべての成果物に適用され、$STORE_NAME型の名前付き信頼ストア $STORE_TYPEを使用します。 また、ユーザーが X.509 サブジェクト $CERT_SUBJECT を使用して、特定の ID を信頼することも前提としています。 詳細については、「 信頼ストアと信頼ポリシーの仕様」を参照してください。

    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
    
  5. notation policyを使用して、前に作成した JSON ファイルから信頼ポリシー構成をインポートします。

    notation policy import ./trustpolicy.json
    notation policy show
    
  6. notation verifyを使用して、ビルド後にコンテナー イメージが変更されていないことを確認します。

    notation verify $IMAGE
    

    信頼ポリシーによるイメージの検証が成功すると、検証済みイメージの SHA256 ダイジェストが正常な出力メッセージで返されます。

タイムスタンプを使用する

Notation v1.2.0 リリース以降、Notation では RFC 3161 準拠のタイムスタンプがサポートされています。 この機能強化により、タイム スタンプ機関 (TSA) を信頼することで、証明書の有効期間内に作成された署名の信頼が拡張されます。 この信頼により、証明書の有効期限が切れた後でも、署名の検証が成功します。

イメージ署名者は、信頼された TSA によって生成されたタイムスタンプを使用してコンテナー イメージに署名する必要があります。 イメージ検証ツールとして、イメージ署名者と関連する TSA の両方を信頼し、信頼ストアと信頼ポリシーを使用して信頼を確立する必要があります。

タイムスタンプを設定すると、証明書の有効期限が切れたためにイメージに定期的に再署名する必要がなくなり、コストが削減されます。 この機能は、有効期間の短い証明書を使用する場合に特に重要です。 タイムスタンプを使用してイメージに署名して検証する方法の詳細については、 Notary Project のタイムスタンプ ガイドを参照してください。

Notation では、Azure Pipelines と GitHub Actions で CI/CD ソリューションが提供されます。

信頼されたコンテナー イメージのみが Azure Kubernetes Service (AKS) にデプロイされるようにするには、