使用 CA 核發的憑證來透過 Notation 和 Azure Key Vault 簽署容器映像
使用受信任的憑證授權單位 (CA) 所核發的憑證來對容器映像進行簽署和驗證是一種有價值的安全性做法。 此安全性措施將幫助您負責任地識別、授權和驗證容器映像發佈者和容器映像本身的身分識別。 GlobalSign、DigiCert 等受信任的憑證授權單位 (CA) 在驗證使用者或組織的身分識別、維護數位憑證的安全性以及在出現任何風險或濫用時立即撤銷憑證方面發揮著至關重要的作用。
以下是一些基本元件,可協助您使用受信任 CA 所核發的憑證來對容器映像進行簽署和驗證:
- 標記法是由 Notary Project 社群開發並由 Microsoft 支援的開放原始碼供應鏈工具,可支援對容器映像和其他成品進行簽署和驗證。
- Azure Key Vault (AKV) 是一項雲端式服務,用於管理密碼編譯金鑰、秘密和憑證,將協助您確保使用簽署金鑰安全地儲存和管理憑證。
- Notation AKV 外掛程式 azure-kv 是 Notation 的延伸模組,它會使用儲存在 Azure Key Vault 中的金鑰來簽署和驗證容器映像和成品的數位簽章。
- Azure Container Registry (ACR) 可讓您將這些簽章附加到已簽署的映像中,並協助您儲存和管理這些容器映像。
當您驗證映像時,會使用簽章來驗證映像的完整性和簽署者的身分識別。 這有助於確保容器映像不會遭到竄改,且是來自受信任的來源。
本文內容:
- 安裝標記法 CLI 和 AKV 外掛程式
- 在 AKV 中建立或匯入 CA 所核發的憑證
- 使用 ACR 工作來建置和推送容器映像
- 使用 Notation CLI 和 AKV 外掛程式來簽署容器映像
- 使用 Notation CLI 來驗證容器映像簽章
- 時間戳記
必要條件
- 建立或使用 Azure Container Registry 來儲存容器映像和簽章
- 建立或使用 Azure Key Vault。
- 安裝及設定最新的 Azure CLI,或在 Azure Cloud Shell 中執行命令
注意
建議您建立新的 Azure Key Vault,以便只儲存憑證。
安裝標記法 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 cli 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。注意
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
設定環境變數
注意
為了方便設定 AKV 和 ACR,本指南會使用環境變數。 請為您的特定資源更新這些環境變數的值。
針對 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"
針對 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
(用於 Codesigning)。
- 主體必須包含一般名稱 (
- 金鑰屬性:
exportable
屬性必須設為false
。- 從 Notary Project 規格中選取受支援的金鑰類型和大小。
重要
為了確保與映像完整性成功整合,憑證的內容類型應設定為 PEM。
注意
本指南使用 AKV 外掛程式 1.0.1 版。 該外掛程式的先前版本有一個限制,需要在憑證鏈中按照特定的順序排列憑證。 該外掛程式的 1.0.1 版沒有這項限制,因此建議您使用 1.0.1 版或更新版本。
建立 CA 所核發的憑證
依照建立憑證簽署要求中的指示,建立憑證簽署要求 (CSR)。
重要
合併 CSR 時,請確保合併從 CA 廠商帶回的整個鏈結。
在 AKV 中匯入憑證
若要匯入憑證:
- 從 CA 廠商取得包含整個憑證鏈的憑證檔。
- 請依照匯入憑證中的指示將憑證匯入 Azure Key Vault。
注意
如果憑證在建立或匯入後未包含憑證鏈,您可以從 CA 廠商取得中繼憑證和根憑證。 您可以要求廠商為您提供包含中繼憑證 (如果有的話) 和根憑證的 PEM 檔案。 然後可以在簽署容器映像的步驟 5 中使用此檔案。
使用 Notation CLI 和 AKV 外掛程式來簽署容器映像
使用 ACR 和 AKV 時,請務必授與適當的權限以確保存取既安全且受控制。 您可以根據您的特定案例授權不同實體的存取權,例如使用者主體、服務主體或受控識別。 在本教學課程中,會將存取權限指派給登入的 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"
組建和推送容器映像至 ACR
使用您的個別 Azure 身分識別來向您的 ACR 進行驗證。
az acr login --name $ACR_NAME
重要
如果您的系統上已安裝 Docker,並使用 az acr login
或 docker login
向您的 ACR 進行驗證,則您的認證已儲存並可供 Notation 使用。 在此情況下,您不需要再次執行 notation login
,即可向 ACR 進行驗證。 若要深入了解 Notation 的驗證選項,請參閱使用符合 OCI 規範的登錄進行驗證。
使用 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 存取權
使用 Azure RBAC (建議)
設定包含 AKV 資源的訂用帳戶
az account set --subscription $AKV_SUB_ID
指派角色
如果憑證包含整個憑證鏈結,則必須使用下列角色來指派主體:
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 中的憑證簽署容器映像
取得憑證的金鑰識別碼。 AKV 中的憑證可以有多個版本,下列命令會取得最新版本的
$CERT_NAME
憑證的金鑰識別碼。KEY_ID=$(az keyvault certificate show -n $CERT_NAME --vault-name $AKV_NAME --query 'kid' -o tsv)
使用金鑰識別碼以 CODE 簽章格式對容器映像進行簽署。
如果憑證包含整個憑證鏈結,請執行下列命令:
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
的附加外掛程式設定。 例如,可以明確地將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
檢視已簽署映像和相關聯簽章的圖。
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 來驗證容器映像
將根憑證新增至具名的信任存放區以進行簽章驗證。 如果您沒有根憑證,您可以從您的 CA 取得該憑證。 下列範例會將根憑證
$ROOT_CERT
新增至$STORE_NAME
信任存放區。STORE_TYPE="ca" STORE_NAME="wabbit-networks.io" notation cert add --type $STORE_TYPE --store $STORE_NAME $ROOT_CERT
列出根憑證以確認已成功新增
$ROOT_CERT
。notation cert ls
在驗證之前設定信任原則。
信任原則可讓使用者指定微調的驗證原則。 使用下列命令來設定信任原則。
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_TYPE
的具名信任存放區$STORE_NAME
包含根憑證。 其也假設使用者信任具有 X.509 主體$CERT_SUBJECT
的特定身分識別。 如需詳細資料,請參閱信任存放區和信任原則規格。使用
notation policy
從trustpolicy.json
匯入信任原則設定。notation policy import ./trustpolicy.json
顯示信任原則設定以確認它成功匯入。
notation policy show
使用
notation verify
來驗證映像的完整性:notation verify $IMAGE
使用信任原則成功驗證映像時,會在成功的輸出訊息中傳回驗證映像的 sha256 摘要。 輸出的範例:
Successfully verified signature for myregistry.azurecr.io/net-monitor@sha256:17cc5dd7dfb8739e19e33e43680e43071f07497ed716814f3ac80bd4aac1b58f
時間戳記
由於 Notation v1.2.0 版本,Notation 支援符合 RFC 3161 規範的時間戳記。 這項增強功能可藉由信任時間戳記授權單位 (Timestamping Authority, TSA) 來延伸憑證有效性期間內所建立之簽章的信任,即使在憑證到期之後,也能成功驗證簽章。 身為映像簽署者,請確定您有使用受信任的 TSA 所產生的時間戳記來簽署容器映像。 身為映像驗證者,若要驗證時間戳記,請確定您信任映像簽署者和相關聯的 TSA,並透過信任存放區和信任原則來建立信任。 時間戳記可減少成本,不需要定期因為憑證到期而重新簽署映像,這在使用短期憑證時特別重要。 如需有關如何使用時間戳記簽署和驗證的詳細指示,請參閱 Notary Project 時間戳記指南。
常見問題集
如果憑證過期,該怎麼辦?
如果您的憑證已過期,您必須從受信任的 CA 廠商取得新的憑證,以及新的私密金鑰。 過期的憑證無法用來簽署容器映像。 對於在憑證過期前簽署的映像,如果其使用了時間戳記來進行簽署,則仍可成功驗證。 若沒有使用時間戳記,則簽章驗證會失敗,您必須使用新的憑證重新簽署這些映像,才能成功通過驗證。
如果憑證被撤銷,該怎麼辦?
如果憑證被撤銷,簽章就會失效。 會導致這個情況發生的原因有幾個,例如私密金鑰遭入侵,或憑證持有者的關係有所變更。 若要解決此問題,請先確定原始程式碼和建置環境是最新且安全的。 然後,從原始程式碼建置容器映像、從受信任的 CA 廠商取得新的憑證以及新的私密金鑰,並遵循本指南使用新的憑證簽署新的容器映像。
下一步
標記法也提供了 Azure Pipeline 和 GitHub Actions 工作流程上的 CI/CD 解決方案:
若要在 AKS 或 Kubernetes 中驗證已簽署的映像部署: