共用方式為


使用 Notation 和 Trusted Signing 在 GitHub 工作流程中簽署容器映像

本文是確保容器映像檔和其他 Open Container Initiative (OCI) 構件的完整性和真實性系列的一部分。 如需完整畫面,請從 概述開始,其中解釋了為什麼簽名很重要並概述了各種場景。

在本文中,您將瞭解如何建立 GitHub Actions 工作流程,以:

  • 建置映像,並將它推送至 Azure Container Registry。
  • 使用 Notation 的 GitHub 動作和受信任的簽署來簽署映像。
  • 自動將產生的簽章儲存在 Container Registry 中。

先決條件

  • 設定 信任簽署帳戶和憑證設定檔。 您的信任簽署憑證設定檔必須在其主體中包含下列屬性:

    • 國家/地區 (C
    • 州或省 (STS
    • 組織 (O

    公證專案規格需要這些欄位。

  • 建立或使用 容器登錄

  • 建立或使用 GitHub 存放庫來儲存工作流程檔案和 GitHub 秘密。

備註

目前,信任簽署僅適用於位於美國和加拿大且具有三年或更長時間可驗證歷史記錄的組織。

從 Azure 驗證到 GitHub

根據使用 GitHub Actions 連線到 Azure,您必須在工作流程中先使用 Azure 登入動作以驗證 Azure,然後才能執行 Azure CLI 或 Azure PowerShell 命令。 Azure 登入動作支援多種驗證方法。

在本指南中,您會使用 OpenID Connect (OIDC) 登入、使用使用者分配的受控身分識別,並遵循《透過 OpenID Connect 使用 Azure 登入動作》中的步驟。

  1. 建立使用者指派的受控識別。 如果您有現有的受控識別,請略過此步驟。

    az login
    az identity create -g <identity-resource-group> -n <identity-name>
    

  1. 取得受控身份的用戶端識別碼:

    CLIENT_ID=$(az identity show -g <identity-resource-group> -n <identity-name> --query clientId -o tsv)
    

  1. 將角色指派給受控識別,以存取 Azure Container Registry。

    對於未啟用屬性型存取控制 (ABAC) 的登錄,請指派 AcrPushAcrPull 角色:

    ACR_SCOPE=/subscriptions/<subscription-id>/resourceGroups/<acr-resource-group>
    az role assignment create --assignee $CLIENT_ID --scope $ACR_SCOPE --role "acrpush" --role "acrpull"
    

    對於已啟用 ABAC 的登錄,請指派 Container Registry Repository ReaderContainer Registry Repository Writer 角色:

    ACR_SCOPE=/subscriptions/<subscription-id>/resourceGroups/<acr-resource-group>
    az role assignment create --assignee $CLIENT_ID --scope $ACR_SCOPE --role "Container Registry Repository Reader" --role "Container Registry Repository Writer"
    

  1. Trusted Signing Certificate Profile Signer 角色指派給受控識別以存取信任簽署:

    TS_SCOPE=/subscriptions/<subscription-id>/resourceGroups/<ts-account-resource-group>/providers/Microsoft.CodeSigning/codeSigningAccounts/<ts-account>/certificateProfiles/<ts-cert-profile>
    az role assignment create --assignee $CLIENT_ID --scope $TS_SCOPE --role "Trusted Signing Certificate Profile Signer"
    

  1. 設定 GitHub 以信任您的身分識別。 請遵循 設定使用者指派的受控識別以信任外部身分識別提供者

  2. 遵循為存放庫建立秘密 (英文) 來建立 GitHub 秘密。

    將受控識別值對應至這些秘密:

    GitHub 祕密 管理的身分識別值
    AZURE_CLIENT_ID 用戶端識別碼
    AZURE_SUBSCRIPTION_ID 訂用帳戶識別碼
    AZURE_TENANT_ID 目錄 (租用戶) 識別碼

儲存 TSA 根憑證

時間戳記 (RFC 3161) 將簽章的信任延伸至簽署憑證的有效期間之後。 信任簽署使用短期憑證,因此時間戳記至關重要。 時間戳記授權 (TSA) 的伺服器 URL 位於 http://timestamp.acs.microsoft.com/,此為時間戳記副署中的建議設定。

  1. 下載 TSA 根憑證:

    curl -o msft-tsa-root-certificate-authority-2020.crt "http://www.microsoft.com/pkiops/certs/microsoft%20identity%20verification%20root%20certificate%20authority%202020.crt"
    

  1. 將根憑證儲存在您的儲存庫中;例如, .github/certs/msft-identity-verification-root-cert-authority-2020.crt. 您將在工作流程中使用檔案路徑。

建立 GitHub Actions 工作流程

  1. 在您的存放庫中建立目錄 .github/workflows (如果不存在)。

  2. 建立新的工作流程檔案;例如, .github/workflows/sign-with-trusted-signing.yml.

  3. 將下列簽署工作流程範本複製到您的檔案中。

展開以檢視簽署工作流程範本。
# Build and push an image to Azure Container Registry, set up notation, and sign the image
name: notation-github-actions-sign-with-trusted-signing-template

on:
  push:

env:
  ACR_LOGIN_SERVER: <registry-login-server>             # example: myregistry.azurecr.io
  ACR_REPO_NAME: <repository-name>                      # example: myrepo
  IMAGE_TAG: <image-tag>                                # example: v1
  PLUGIN_NAME: azure-trustedsigning                     # name of Notation Trusted Signing plug-in; do not change
  PLUGIN_DOWNLOAD_URL: <plugin-download-url>            # example: "https://github.com/Azure/trustedsigning-notation-plugin/releases/download/v1.0.0-beta.1/notation-azure-trustedsigning_1.0.0-beta.1_linux_amd64.tar.gz"
  PLUGIN_CHECKSUM: <plugin-package-checksum>            # example: 538b497be0f0b4c6ced99eceb2be16f1c4b8e3d7c451357a52aeeca6751ccb44
  TSA_URL: "http://timestamp.acs.microsoft.com/"        # timestamping server URL
  TSA_ROOT_CERT: <root-cert-file-path>                  # example: .github/certs/msft-identity-verification-root-cert-authority-2020.crt
  TS_ACCOUNT_NAME: <trusted-signing-account-name>       # Trusted Signing account name
  TS_CERT_PROFILE: <trusted-signing-cert-profile-name>  # Trusted Signing certificate profile name 
  TS_ACCOUNT_URI: <trusted-signing-account-uri>         # Trusted Signing account URI; for example, "https://eus.codesigning.azure.net/"

jobs:
  notation-sign:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read
     # packages: write
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: prepare
        id: prepare
        run: |
          echo "target_artifact_reference=${{ env.ACR_LOGIN_SERVER }}/${{ env.ACR_REPO_NAME }}:${{ env.IMAGE_TAG }}" >> "$GITHUB_ENV"
      
      # Log in to Azure with your service principal secret
      # - name: Azure login
      #  uses: Azure/login@v1
      #  with:
      #    creds: ${{ secrets.AZURE_CREDENTIALS }}
      # If you're using OIDC and federated credentials, make sure to replace the preceding step with the following:
      - name: Azure login
        uses: Azure/login@v2
        with:
          client-id: ${{ secrets.AZURE_CLIENT_ID }}
          tenant-id: ${{ secrets.AZURE_TENANT_ID }}
          subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

      # Log in to your container registry
      - name: ACR login
        run: |
            az acr login --name ${{ env.ACR_LOGIN_SERVER }}
      # Build and push an image to the registry
      # Use `Dockerfile` as an example to build an image
      - name: Build and push
        id: push
        uses: docker/build-push-action@v4
        with:
          push: true
          tags: ${{ env.target_artifact_reference }}
          build-args: |
            IMAGE_TAG={{ env.IMAGE_TAG }}
      # Get the manifest digest of the OCI artifact
      - name: Retrieve digest
        run: |
          echo "target_artifact_reference=${{ env.ACR_LOGIN_SERVER }}/${{ env.ACR_REPO_NAME }}@${{ steps.push.outputs.digest }}" >> "$GITHUB_ENV" 
      # Set up the Notation CLI
      - name: setup notation
        uses: notaryproject/notation-action/setup@v1.2.2
      # Sign your container images and OCI artifacts by using a private key stored in Azure Key Vault
      - name: sign OCI artifacts with Trusted Signing
        uses: notaryproject/notation-action/sign@v1
        with:
          timestamp_url: ${{ env.TSA_URL}}
          timestamp_root_cert: ${{env.TSA_ROOT_CERT }}
          plugin_name: ${{ env.PLUGIN_NAME }}
          plugin_url: ${{ env.PLUGIN_DOWNLOAD_URL }}
          plugin_checksum: ${{ env.PLUGIN_CHECKSUM }}
          key_id: ${{ env.TS_CERT_PROFILE }}
          target_artifact_reference: ${{ env.target_artifact_reference }}
          signature_format: cose
          plugin_config: |-
            accountName=${{ env.TS_ACCOUNT_NAME }}
            baseUrl=${{ env.TS_ACCOUNT_URI }}
            certProfile=${{ env.TS_CERT_PROFILE }}
          force_referrers_tag: 'false'

關於環境變數的注意事項:

  • PLUGIN_NAME:一律使用 azure-trustedsigning
  • PLUGIN_DOWNLOAD_URL:從 「信任簽署」外掛程式發行頁面取得 URL。
  • PLUGIN_CHECKSUM:使用發行頁面上的總和檢查碼檔案;例如,notation-azure-trustedsigning_<version>_checksums.txt
  • TS_ACCOUNT_URI:使用特定於其區域的受信任簽署帳戶的端點;例如, https://eus.codesigning.azure.net/.

觸發 GitHub Actions 工作流程

on:push語法會觸發範例工作流程。 提交變更會啟動工作流程。 在您的 GitHub 存放庫名稱下,選取 [動作] 以檢視工作流程記錄。

成功時,工作流程會建置映像、將它推送至 Azure Container Registry,並使用信任簽署來簽署。 您可以檢視工作流程記錄,以確認 azure-trustedsigning 已安裝外掛程式,且映像已成功簽署。

此外,您可以在 Azure 入口網站 中開啟容器登錄。 前往 存放庫,打開您的影像,然後選取 參考者。 確認系統已列出類型為 application/vnd.cncf.notary.signature 的成品 (簽章)。