次の方法で共有


CA 発行の証明書を使い、Notation と Azure Key Vault を使ってコンテナー イメージに署名する

信頼される証明機関 (CA) が発行した証明書を使ってコンテナー イメージに署名し、確認することは、重要なセキュリティ プラクティスです。 このセキュリティ対策は、コンテナー イメージの発行元とコンテナー イメージ自体の両方の ID を責任を持って識別、認可、検証するのに役立ちます。 GlobalSign、DigiCert などの信頼される証明機関 (CA) は、ユーザーまたは組織の ID を検証し、デジタル証明書のセキュリティを維持し、リスクや悪用があった場合には直ちに証明書を取り消すという重要な役割を担っています。

信頼された CA から発行された証明書を使ってコンテナー イメージに署名し、確認するために不可欠なコンポーネントの一部を次に示します。

  • Notation は、Notary Project コミュニティによって開発され、Microsoft がサポートするオープンソースのサプライ チェーン セキュリティ ツールで、コンテナー イメージとその他の成果物の署名と確認をサポートします。
  • 暗号化キー、シークレット、証明書を管理するためのクラウドベース サービスである Azure Key Vault (AKV) は、署名キーを使ってセキュリティで保護された方法で証明書を保存および管理するために役立ちます。
  • Notation の拡張機能である Notation AKV プラグイン azure-kv は、Azure Key Vault に保存されているキーを使って、コンテナー イメージと成果物のデジタル署名の署名と確認を行います。
  • Azure Container Registry (ACR) を使うと、署名済みイメージにこれらのシグネチャをアタッチできるので、これらのコンテナー イメージの保存と管理に役立ちます。

イメージを確認するときに、イメージの整合性と署名者の身元を検証するためにシグネチャが使われます。 これにより、コンテナー イメージが改ざんされておらず、信頼できる発行元であることを確認できます。

この記事の内容:

  • notation CLI と AKV プラグインをインストールする
  • AKV で CA から発行された証明書を作成する、またはインポートする
  • ACR タスクを使ってコンテナー イメージをビルドおよびプッシュする
  • Notation CLI と AKV プラグインを使用して、コンテナー イメージに署名する
  • Notation CLI を使ってコンテナー イメージのシグネチャを確認する
  • タイムスタンプ

前提条件

Note

証明書のみを保存するために、新しい Azure Key Vault を作成することをお勧めします。

notation CLI と AKV プラグインをインストールする

  1. Linux amd64 環境に Notation v1.2.0 をインストールします。 Notation インストール ガイドに従って、他の環境用のパッケージをダウンロードします。

    # Download, extract and install
    curl -Lo notation.tar.gz https://github.com/notaryproject/notation/releases/download/v1.2.0/notation_1.2.0_linux_amd64.tar.gz
    tar xvzf notation.tar.gz
    
    # Copy the notation cli to the desired bin directory in your PATH, for example
    cp ./notation /usr/local/bin
    
  2. Linux amd64 環境上に、Notation Azure Key Vault プラグイン azure-kv v1.2.0 をインストールします。

    Note

    Notation Azure Key Vault プラグインの URL と SHA256 チェックサムは、プラグインのリリース ページで確認できます。

    notation plugin install --url https://github.com/Azure/notation-azure-kv/releases/download/v1.2.0/notation-azure-kv_1.2.0_linux_amd64.tar.gz --sha256sum 06bb5198af31ce11b08c4557ae4c2cbfb09878dfa6b637b7407ebc2d57b87b34
    
  3. 使用可能なプラグインを一覧表示し、バージョンが 1.2.0 である azure-kv プラグインが一覧に含まれていることを確認します。

    notation plugin ls
    

環境変数を構成する

Note

このガイドでは、AKV と ACR を構成するときに便利な環境変数を使います。 実際のリソースに合わせて、これらの環境変数の値を更新してください。

  1. AKV と証明書の環境変数を構成する

    AKV_SUB_ID=myAkvSubscriptionId
    AKV_RG=myAkvResourceGroup
    AKV_NAME=myakv 
    
    # Name of the certificate created or imported in AKV 
    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 とイメージの環境変数を構成します。

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

Azure CLI を使用してサインインする

az login

Azure CLI とそのサインイン方法について詳しくは、「Azure CLI を使用してサインインする」をご参照ください。

AKV で CA から発行された証明書を作成する、またはインポートする

証明書の要件

署名と検証用に証明書を作成する場合、証明書は Notary Project の証明書要件を満たしている必要があります。

ルート証明書と中間証明書の要件は次のとおりです。

  • basicConstraints 拡張機能が存在し、クリティカルとマークされている必要があります。 CA フィールドは true に設定する必要があります。
  • keyUsage 拡張機能が存在し、critical とマークされている必要があります。 keyCertSign のビット位置は "必ず" 設定します。

CA から発行される証明書の要件は次のとおりです。

  • X.509 証明書のプロパティ:
    • サブジェクトには、共通名 (CN)、国 (C)、州または都道府県 (ST)、組織 (O) を含める必要があります。 このチュートリアルでは、サブジェクトとして $CERT_SUBJECT を使います。
    • X.509 キー使用フラグは DigitalSignature のみにする必要があります。
    • 拡張キー使用法 (EKU) は空または 1.3.6.1.5.5.7.3.3 (コード署名の場合) にする必要があります。
  • キーのプロパティ:
    • exportable プロパティは false に設定する必要があります。
    • Notary Project の仕様からサポートされているキーの種類とサイズを選びます。

重要

Image Integrity と正常に統合するには、証明書のコンテンツ タイプを PEM に設定する必要があります。

Note

このガイドでは、バージョン 1.0.1 の AKV プラグインを使います。 以前のバージョンのプラグインには、証明書チェーン内の証明書を特定の順序で指定する必要があるという制限がありました。 バージョン 1.0.1 のプラグインにはこの制限がないため、バージョン 1.0.1 以降を使うことをお勧めします。

CA から発行された証明書を作成する

証明書署名要求の作成の手順に従って、証明書署名要求 (CSR) を作成します。

重要

CSR をマージするときは、必ず CA ベンダーから返送されたチェーン全体をマージしてください。

AKV に証明書をインポートする

証明書をインポートするには:

  1. 証明書チェーン全体を使って CA ベンダーから証明書ファイルを取得します。
  2. 証明書のインポートの手順に従って、証明書を Azure Key Vault にインポートします。

Note

作成またはインポート後に証明書に証明書チェーンが含まれていない場合は、CA ベンダーから中間証明書とルート証明書を取得できます。 中間証明書 (存在する場合) とルート証明書を含む PEM ファイルを提供するようベンダーに依頼できます。 このファイルは、コンテナー イメージの署名の手順 5 で使用できます。

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

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

ACR へのオーサリング アクセス

ACR でコンテナー イメージをビルドして署名するには、AcrPull および AcrPush ロールが必要です。

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

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

    USER_ID=$(az ad signed-in-user show --query id -o tsv)
    az role assignment create --role "AcrPull" --role "AcrPush" --assignee $USER_ID --scope "/subscriptions/$ACR_SUB_ID/resourceGroups/$ACR_RG/providers/Microsoft.ContainerRegistry/registries/$ACR_NAME"
    

コンテナー イメージをビルドし、ACR にプッシュする

  1. ご自身の個人 Azure ID を使用して、お使いの ACR に対する認証を行います。

    az acr login --name $ACR_NAME
    

重要

お使いのシステム上に Docker がインストールされており、az acr login または docker login を使用してお使いの ACR に対する認証を行う場合、ご自身の資格情報は既に格納されており、Notation に使用できます。 この場合、お使いの ACR に対して notation login をもう一度実行して認証する必要はありません。 Notation の認証オプションについて詳しくは、「Authenticate with OCI-compliant registries」をご参照ください。

  1. ACR タスクを使用して新しいイメージをビルドし、プッシュします。 タグは変更可能であり、上書き可能なので、常に 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

AKV へのオーサリング アクセス

  1. AKV リソースを含むサブスクリプションを設定する

    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"
    

Azure RBAC を使用した Key Vault へのアクセスの詳細については、「アクセスの管理に Azure RBAC を使用する」を参照してください。

アクセス ポリシーを使用する (レガシ)

AKV リソースを含むサブスクリプションを設定するには、次のコマンドを実行します。

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

プリンシパルへのポリシーの割り当てについて詳しくは、アクセス ポリシーを割り当てるをご参照ください。

AKV の証明書を使用してコンテナー イメージに署名する

  1. 証明書のキー ID を取得します。 AKV 内の証明書には複数のバージョンを含めることができます。次のコマンドを使って、最新バージョン $CERT_NAME 証明書のキー ID を取得します。

    KEY_ID=$(az keyvault certificate show -n $CERT_NAME --vault-name $AKV_NAME --query 'kid' -o tsv) 
    
  2. このキー ID を使って、COSE シグネチャ形式でこのコンテナー イメージに署名します。

    証明書に証明書チェーン全体が含まれている場合は、次のコマンドを実行します。

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

    証明書にチェーンが含まれていない場合は、--plugin-config ca_certs=<ca_bundle_file> パラメーターを使って PEM ファイル内の CA 証明書を AKV プラグインに渡し、次のコマンドを実行します。

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

    AKV で認証を実施する場合、既定では、次の資格情報の種類が有効になっていれば順番に試行されます。

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

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

    さまざまな資格情報の種類の credential_type 値については、次の表を参照してください。

    資格情報の種類 credential_type の値
    環境資格情報 environment
    ワークロード ID 資格情報 workloadid
    マネージド ID 資格情報 managedid
    Azure CLI の資格情報 azurecli
  3. 署名されたイメージと関連する署名のグラフを表示します。

    notation ls $IMAGE
    

    次の出力例では、ダイジェスト sha256:d7258166ca820f5ab7190247663464f2dcb149df4d1b6c4943dcaac59157de8e によって識別される型 application/vnd.cncf.notary.signature のシグネチャが $IMAGE に関連付けられています。

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

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

  1. シグネチャ検証のためにルート証明書を名前付き信頼ストアに追加します。 ルート証明書がない場合は、CA から取得できます。 次の例では、ルート証明書 $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 という 1 つの信頼ポリシーが定義されています。 この信頼ポリシーは、$REGISTRY/$REPO リポジトリに保存されているすべての成果物に適用されます。 型 $STORE_TYPE の名前付き信頼ストア $STORE_NAME にはルート証明書が含まれています。 また、ユーザーが X.509 サブジェクト $CERT_SUBJECT を使用して、特定の ID を信頼することも前提としています。 詳しくは、「Trust Store and Trust Policy Specification」をご参照ください。

  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

タイムスタンプ

Notation v1.2.0 リリース以降、Notation では RFC 3161 準拠のタイムスタンプがサポートされています。 この機能強化により、タイムスタンプ機関 (TSA) を信頼することで、証明書の有効期間内に作成された署名の信頼が延長され、証明書の有効期限が切れた後でも署名の検証が成功します。 イメージ署名者は、信頼された TSA によって生成されたタイムスタンプを使用してコンテナー イメージに署名する必要があります。 イメージ検証者は、タイムスタンプを検証するために、イメージ署名者と関連付けられている TSA の両方を信頼し、信頼ストアと信頼ポリシーを使用して信頼を確立する必要があります。 タイムスタンプにより、証明書の有効期限切れによるイメージの再署名を定期的に行う必要がなくなるため、コストを削減できます。これは、有効期間の短い証明書を使用する場合に特に重要です。 タイムスタンプを使用した署名および検証方法の詳細については、Notary Project のタイムスタンプ ガイドを参照してください。

よく寄せられる質問

  • 証明書の有効期限が切れている場合はどうすればよいですか?

    証明書の有効期限が切れている場合は、信頼された CA ベンダーから新しい証明書と新しい秘密キーを取得する必要があります。 期限切れの証明書を使用してコンテナー イメージに署名することはできません。 証明書の有効期限が切れる前に署名されたイメージの場合、タイムスタンプで署名された場合でも検証に成功する可能性があります。 タイムスタンプがない場合、署名の検証は失敗します。検証に成功するには、新しい証明書を使用してそれらのイメージにもう一度署名する必要があります。

  • 証明書が失効している場合はどうすればよいですか?

    証明書が取り消されると、署名は無効になります。 これは、秘密キーの侵害や証明書所有者の所属の変更など、いくつかの理由で発生する可能性があります。 この問題を解決するには、まず、ソース コードとビルド環境が最新で安全であることを確認する必要があります。 次に、ソース コードからコンテナー イメージをビルドし、信頼された CA ベンダーから新しい証明書と新しい秘密キーを取得し、このガイドに従って新しい証明書で新しいコンテナー イメージに署名します。

次のステップ

Notation には、Azure Pipeline と GitHub Actions ワークフロー上の CI/CD ソリューションも用意されています。

AKS または Kubernetes で署名されたイメージのデプロイを検証するには: