自己署名証明書を使用し、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 を使用して、署名に対してコンテナー イメージを検証する
- タイムスタンプ
前提条件
- コンテナー イメージと署名を格納するために Azure Container Registry を作成または使用する
- 証明書を管理するために Azure Key Vault を作成または使用する
- 最新の Azure CLI をインストールして構成するか、Azure Cloud Shell 内でコマンドを実行する
Notation CLI と AKV プラグインをインストールする
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
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
使用可能なプラグインを一覧表示し、バージョンが
1.2.0
であるazure-kv
プラグインが一覧に含まれていることを確認します。notation plugin ls
環境変数を構成する
Note
チュートリアルでコマンドを簡単に実行するには、既存の ACR リソースと AKV リソースに一致する Azure リソースの値を指定してください。
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
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
ロールが必要です。
ACR リソースを含むサブスクリプションを設定する
az account set --subscription $ACR_SUB_ID
ロールを割り当てる
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 つの選択肢を確認します。
Azure RBAC を使用する (推奨)
自己署名証明書を使用した署名には、以下のロールが必要です。
- 証明書の作成と読み取り用の
Key Vault Certificates Officer
- 既存の証明書の読み取り用の
Key Vault Certificates User
- 署名操作用の
Key Vault Crypto User
Azure RBAC を使用した Key Vault アクセスの詳細については、「Azure RBAC を使用したアクセスの管理」を参照してください。
AKV リソースを含むサブスクリプションを設定する
az account set --subscription $AKV_SUB_ID
ロールを割り当てる
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
アクセス許可
プリンシパルへのポリシーの割り当てについて詳しくは、アクセス ポリシーを割り当てるをご参照ください。
以下のように AKV リソースを含むサブスクリプションを設定する
az account set --subscription $AKV_SUB_ID
以下のように 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)
次の手順では、テスト目的用の自己署名証明書を作成する方法を示します。
証明書のポリシー ファイルを作成します。
この証明書ポリシー ファイルを以下のように実行すると、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
証明書を作成します。
az keyvault certificate create -n $CERT_NAME --vault-name $AKV_NAME -p @my_policy.json
Notation CLI と AKV プラグインを使用して、コンテナー イメージに署名する
ご自身の個人 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」をご参照ください。
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
署名キーのキー ID を取得します。 AKV 内の証明書には複数のバージョンを含めることができます。次のコマンドは、最新バージョンのキー ID を取得します。
KEY_ID=$(az keyvault certificate show -n $CERT_NAME --vault-name $AKV_NAME --query 'kid' -o tsv)
この署名キー 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_type
をazurecli
に明示的に設定できます: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 ls $IMAGE
Notation CLI を使用してコンテナー イメージを確認する
このコンテナー イメージを確認するには、リーフ証明書に署名するルート証明書を信頼ストアに追加し、確認用の信頼ポリシーを作成します。 このチュートリアルで使用する自己署名証明書の場合、このルート証明書はこの自己署名証明書そのものです。
パブリック証明書をダウンロードします。
az keyvault certificate download --name $CERT_NAME --vault-name $AKV_NAME --file $CERT_PATH
署名検証のためにダウンロードしたパブリック証明書を名前付き信頼ストアに追加します。
STORE_TYPE="ca" STORE_NAME="wabbit-networks.io" notation cert add --type $STORE_TYPE --store $STORE_NAME $CERT_PATH
証明書を表示して確認します。
notation cert ls
検証前に信頼ポリシーを構成します。
信頼ポリシーを使用すると、ユーザーは微調整された確認ポリシーを指定できます。 次の例では
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
notation policy
を使用して、先ほど作成した JSON ファイルから信頼ポリシー構成をインポートします。notation policy import ./trustpolicy.json notation policy show
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 ソリューションも用意されています。
- Azure Pipeline で Notation を使用してコンテナー イメージに署名して検証する
- GitHub Actions ワークフローで Notation を使用してコンテナー イメージに署名して検証する
AKS または Kubernetes で署名されたイメージのデプロイを検証するには: