Condividi tramite


Firmare le immagini del container nei flussi di lavoro di GitHub utilizzando Notation e Trusted Signing

Questo articolo fa parte di una serie su come garantire l'integrità e l'autenticità delle immagini del contenitore e altri artefatti OCI (Open Container Initiative). Per un quadro completo, iniziare con la panoramica, che spiega perché la firma è importante e descrive i vari scenari.

Questo articolo illustra come creare un flusso di lavoro di GitHub Actions per:

  • Creare un'immagine e inviarla ad Azure Container Registry.
  • Firmare l'immagine usando le GitHub Actions di Notation e Trusted Signing.
  • Archiviare automaticamente la firma generata nel Registro Container.

Prerequisiti

Annotazioni

Attualmente, la firma attendibile è disponibile solo per le organizzazioni che si trovano negli Stati Uniti e in Canada che hanno una cronologia verificabile di tre anni o più.

Eseguire l'autenticazione da Azure a GitHub

Secondo Usare GitHub Actions per connettersi ad Azure, è necessario eseguire l'autenticazione con Azure nel flusso di lavoro usando l'azione di accesso di Azure prima di eseguire i comandi di Azure CLI o Azure PowerShell. L'azione Di accesso di Azure supporta più metodi di autenticazione.

In questa guida si accede con OpenID Connect (OIDC), si usa un'identità gestita assegnata dall'utente e si seguono i passaggi descritti in Usare l'azione Di accesso di Azure con OpenID Connect.

  1. Creare un'identità gestita assegnata dall'utente. Ignorare questo passaggio se si dispone di un'identità gestita esistente.

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

  1. Acquisisci l'ID client dell'identità gestita:

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

  1. Assegna ruoli all'identità gestita per l'accesso ad "Azure Container Registry".

    Per i registri non abilitati con il controllo degli accessi basato sugli attributi (ABAC), assegnare i ruoli AcrPush e AcrPull:

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

    Per i registri abilitati per ABAC, assegnare i ruoli Container Registry Repository Reader e Container 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. Assegnare il ruolo Trusted Signing Certificate Profile Signer all'identità gestita per l'accesso a Firma attendibile:

    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. Configurare GitHub per fidarsi della tua identità. Seguire Configurare un'identità gestita assegnata dall'utente per considerare attendibile un provider di identità esterno.

  2. Creare segreti GitHub seguendo la procedura creazione di segreti per un repository.

    Eseguire il mapping dei valori dell'identità gestita a tali segreti:

    Segreto GitHub Valore dell'identità gestita
    AZURE_CLIENT_ID ID cliente
    AZURE_SUBSCRIPTION_ID ID sottoscrizione
    AZURE_TENANT_ID ID della directory (tenant)

Archiviare il certificato radice TSA

Il timestamp (RFC 3161) estende l'attendibilità per le firme oltre il periodo di validità del certificato di firma. La firma attendibile usa certificati di breve durata, quindi il timestamp è fondamentale. L'URL del server per l'autorità di riconoscimento timestamp (TSA) è disponibile in http://timestamp.acs.microsoft.com/, come consigliato nelle controfirme di timestamp.

  1. Scaricare il certificato radice 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. Archiviare il certificato radice nel repository; ad esempio, .github/certs/msft-identity-verification-root-cert-authority-2020.crt. Si userà il percorso del file nel flusso di lavoro.

Creare il flusso di lavoro di GitHub Actions

  1. Creare una directory .github/workflows nel repository, se non è presente.

  2. Creare un nuovo file del flusso di lavoro; ad esempio . .github/workflows/sign-with-trusted-signing.yml

  3. Copiare il modello del flusso di lavoro di firma seguente nel file.

Espandere per visualizzare il modello del flusso di lavoro di firma.
# 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'

Note sulle variabili di ambiente:

  • PLUGIN_NAME: usare sempre azure-trustedsigning.
  • PLUGIN_DOWNLOAD_URL: ottenere l'URL dalla pagina di rilascio del plug-in firma affidabile.
  • PLUGIN_CHECKSUM: usare il file checksum nella pagina di rilascio; ad esempio . notation-azure-trustedsigning_<version>_checksums.txt
  • TS_ACCOUNT_URI: usare l'endpoint per l'account di Firma attendibile, specifico per l'area, ad esempio, https://eus.codesigning.azure.net/.

Attivare il flusso di lavoro di GitHub Actions

La on:push sintassi attiva il flusso di lavoro di esempio. Il commit delle modifiche avvia il flusso di lavoro. Sotto il nome del repository GitHub selezionare Azioni per visualizzare i log del flusso di lavoro.

In caso di esito positivo, il flusso di lavoro compila l'immagine, lo inserisce in Registro Azure Container e lo firma usando firma attendibile. È possibile visualizzare i log del flusso di lavoro per verificare che il azure-trustedsigning plug-in sia stato installato e che l'immagine sia stata firmata correttamente.

È anche possibile aprire il registro contenitori nel portale di Azure. Passare a Repository, passare all'immagine e quindi selezionare Riferimenti. Verificare che gli artefatti (firme) di tipo application/vnd.cncf.notary.signature siano elencati.