共用方式為


使用 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 Key Vault,以便只儲存憑證。

安裝標記法 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。

    注意

    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.0azure-kv 外掛程式包含在清單中。

    notation plugin ls
    

設定環境變數

注意

為了方便設定 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 (用於 Codesigning)。
  • 金鑰屬性:
    • exportable 屬性必須設為 false
    • Notary Project 規格中選取受支援的金鑰類型和大小。

重要

為了確保與映像完整性成功整合,憑證的內容類型應設定為 PEM。

注意

本指南使用 AKV 外掛程式 1.0.1 版。 該外掛程式的先前版本有一個限制,需要在憑證鏈中按照特定的順序排列憑證。 該外掛程式的 1.0.1 版沒有這項限制,因此建議您使用 1.0.1 版或更新版本。

建立 CA 所核發的憑證

依照建立憑證簽署要求中的指示,建立憑證簽署要求 (CSR)。

重要

合併 CSR 時,請確保合併從 CA 廠商帶回的整個鏈結。

在 AKV 中匯入憑證

若要匯入憑證:

  1. 從 CA 廠商取得包含整個憑證鏈的憑證檔。
  2. 請依照匯入憑證中的指示將憑證匯入 Azure Key Vault。

注意

如果憑證在建立或匯入後未包含憑證鏈,您可以從 CA 廠商取得中繼憑證和根憑證。 您可以要求廠商為您提供包含中繼憑證 (如果有的話) 和根憑證的 PEM 檔案。 然後可以在簽署容器映像的步驟 5 中使用此檔案。

使用 Notation CLI 和 AKV 外掛程式來簽署容器映像

使用 ACR 和 AKV 時,請務必授與適當的權限以確保存取既安全且受控制。 您可以根據您的特定案例授權不同實體的存取權,例如使用者主體、服務主體或受控識別。 在本教學課程中,會將存取權限指派給登入的 Azure 使用者。

撰寫 ACR 存取權

在 ACR 中組建和簽署容器映像需要 AcrPullAcrPush 角色。

  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 身分識別來向您的 ACR 進行驗證。

    az acr login --name $ACR_NAME
    

重要

如果您的系統上已安裝 Docker,並使用 az acr logindocker login 向您的 ACR 進行驗證,則您的認證已儲存並可供 Notation 使用。 在此情況下,您不需要再次執行 notation login,即可向 ACR 進行驗證。 若要深入了解 Notation 的驗證選項,請參閱使用符合 OCI 規範的登錄進行驗證

  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. 取得憑證的金鑰識別碼。 AKV 中的憑證可以有多個版本,下列命令會取得最新版本的 $CERT_NAME 憑證的金鑰識別碼。

    KEY_ID=$(az keyvault certificate show -n $CERT_NAME --vault-name $AKV_NAME --query 'kid' -o tsv) 
    
  2. 使用金鑰識別碼以 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
  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 的信任原則。 此信任原則會套用到儲存在 $REGISTRY/$REPO 存放庫中的所有成品。 類型 $STORE_TYPE 的具名信任存放區 $STORE_NAME 包含根憑證。 其也假設使用者信任具有 X.509 主體 $CERT_SUBJECT 的特定身分識別。 如需詳細資料,請參閱信任存放區和信任原則規格

  4. 使用 notation policytrustpolicy.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 規範的時間戳記。 這項增強功能可藉由信任時間戳記授權單位 (Timestamping Authority, TSA) 來延伸憑證有效性期間內所建立之簽章的信任,即使在憑證到期之後,也能成功驗證簽章。 身為映像簽署者,請確定您有使用受信任的 TSA 所產生的時間戳記來簽署容器映像。 身為映像驗證者,若要驗證時間戳記,請確定您信任映像簽署者和相關聯的 TSA,並透過信任存放區和信任原則來建立信任。 時間戳記可減少成本,不需要定期因為憑證到期而重新簽署映像,這在使用短期憑證時特別重要。 如需有關如何使用時間戳記簽署和驗證的詳細指示,請參閱 Notary Project 時間戳記指南

常見問題集

  • 如果憑證過期,該怎麼辦?

    如果您的憑證已過期,您必須從受信任的 CA 廠商取得新的憑證,以及新的私密金鑰。 過期的憑證無法用來簽署容器映像。 對於在憑證過期前簽署的映像,如果其使用了時間戳記來進行簽署,則仍可成功驗證。 若沒有使用時間戳記,則簽章驗證會失敗,您必須使用新的憑證重新簽署這些映像,才能成功通過驗證。

  • 如果憑證被撤銷,該怎麼辦?

    如果憑證被撤銷,簽章就會失效。 會導致這個情況發生的原因有幾個,例如私密金鑰遭入侵,或憑證持有者的關係有所變更。 若要解決此問題,請先確定原始程式碼和建置環境是最新且安全的。 然後,從原始程式碼建置容器映像、從受信任的 CA 廠商取得新的憑證以及新的私密金鑰,並遵循本指南使用新的憑證簽署新的容器映像。

下一步

標記法也提供了 Azure Pipeline 和 GitHub Actions 工作流程上的 CI/CD 解決方案:

若要在 AKS 或 Kubernetes 中驗證已簽署的映像部署: