次の方法で共有


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

コンテナー イメージに署名することは、その信頼性と整合性を保証するプロセスです。 これは、デジタル署名をコンテナー イメージに追加することによって実現され、デプロイ中に検証できます。 この署名は、このイメージが信頼された発行元からのものであり、変更されていないことを確認するのに役立ちます。 Notation は、Notary Project コミュニティによって開発され、Microsoft がサポートするオープンソースのサプライ チェーン セキュリティ ツールで、コンテナー イメージとその他の成果物の署名と確認をサポートします。 Azure Key Vault (AKV) は、署名キーを含む証明書を格納するために使用されます。その証明書は、Notation により Notation AKV プラグイン (azure-kv) とともに使用され、コンテナー イメージとその他の成果物を署名および確認することができます。 Azure Container Registry (ACR) を使用すると、コンテナー イメージとその他の成果物に署名を添付する、およびそれらの署名を表示することができます。

このチュートリアルでは、次の作業を行います。

  • Notation CLI と AKV プラグインをインストールする
  • AKV 内で自己署名証明書を作成する
  • ACR タスクを使用して、コンテナー イメージをビルドおよびプッシュする
  • Notation CLI と AKV プラグインを使用して、コンテナー イメージに署名する
  • Notation CLI を使用して、署名に対してコンテナー イメージを検証する
  • タイムスタンプ

前提条件

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 binary 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

チュートリアルでコマンドを簡単に実行するには、既存の ACR リソースと AKV リソースに一致する Azure リソースの値を指定してください。

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

    AKV_SUB_ID=myAkvSubscriptionId
    AKV_RG=myAkvResourceGroup
    # Name of the existing AKV used to store the signing keys
    AKV_NAME=myakv
    # Name of the certificate created in AKV
    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 とイメージ リソース名を構成します。

    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
    IMAGE=$REGISTRY/${REPO}:$TAG
    # 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 を使用してサインインする」をご参照ください。

ACR と 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"
    

AKV へのアクセスを承認する

このセクションでは、AKV へのアクセスを承認するための 2 つの選択肢を確認します。

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

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

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

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

    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"
    

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

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

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

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

  1. 以下のように AKV リソースを含むサブスクリプションを設定する

    az account set --subscription $AKV_SUB_ID
    
  2. 以下のように AKV 内でアクセス ポリシーを設定する

    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
    

重要

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

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

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

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

    この証明書ポリシー ファイルを以下のように実行すると、AKV 内に Notary Project Certificate Requirement と互換性のある、有効な証明書が作成されます。 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 と AKV プラグインを使用して、コンテナー イメージに署名する

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

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

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

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

    資格情報の種類を指定する場合は、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
  4. 署名されたイメージと関連する署名のグラフを表示します。

    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_TYPE 型の名前付き信頼ストア $STORE_NAME を使用します。 また、ユーザーが X.509 サブジェクト $CERT_SUBJECT を使用して、特定の ID を信頼することも前提としています。 詳しくは、「Trust Store and Trust Policy Specification」をご参照ください。

    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 Pipeline と GitHub Actions ワークフロー上の CI/CD ソリューションも用意されています。

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