Edit

Share via


Sign container images by using Notation and Artifact Signing

This article is part of a series on ensuring the integrity and authenticity of container images and other Open Container Initiative (OCI) artifacts. For the complete picture, start with the overview, which explains why signing matters and outlines the various scenarios.

This article focuses on signing by using Notary Project tooling, Notation, and Artifact Signing:

  • What you'll learn here: How to use the Notation command-line interface (CLI) to sign artifacts by using Artifact Signing.
  • Where it fits: Artifact Signing is an alternative to Azure Key Vault. Although Key Vault gives organizations full control of certificate lifecycle management, Artifact Signing provides streamlined signing experience with zero-touch certificate lifecycle management and short-lived certificates.
  • Why it matters: Artifact Signing simplifies the developer experience while providing strong identity assurance. It helps teams reduce operational complexity without compromising security.

Prerequisites

Before you can sign and verify container images by using Notation and Artifact Signing, you need to set up the required Azure resources and install the necessary tools. This section walks you through preparing Azure Container Registry, configuring Artifact Signing, and setting up the Azure CLI as your development environment.

Prepare container images in Azure Container Registry

  1. Create or use a container registry to store container images, OCI artifacts, and signatures.
  2. Push or use a container image in your container registry.

Set up Artifact Signing

Set up an Artifact Signing account and certificate profile in your Azure subscription.

Your certificate profile must include country/region (C), state or province (ST or S), and organization (O) in the certificate subject. The Notary Project specification requires these fields.

Set up the Azure CLI

Install the Azure CLI, or use Azure Cloud Shell.

Install the Notation CLI and Artifact Signing plug-in

This guide runs commands on Linux AMD64 and Windows as examples.

  1. Install Notation CLI v1.3.2:

    curl -Lo notation.tar.gz https://github.com/notaryproject/notation/releases/download/v1.3.2/notation_1.3.2_linux_amd64.tar.gz
    # Validate the checksum
    EXPECTED_SHA256SUM="e1a0f060308086bf8020b2d31defb7c5348f133ca0dba6a1a7820ef3cbb6dfe5"
    echo "$EXPECTED_SHA256SUM  notation.tar.gz" | sha256sum -c -
    # Continue if sha256sum matches
    tar xvzf notation.tar.gz
    cp ./notation /usr/local/bin
    

    For other platforms, see the Notation installation guide.

  2. Install the Artifact Signing plug-in:

    notation plugin install --url "https://github.com/Azure/artifact-signing-notation-plugin/releases/download/v1.0.0/notation-azure-artifactsigning_1.0.0_linux_amd64.tar.gz" --sha256sum 2f45891a14aa9c88c9bee3d11a887c1adbe9d2d24e50de4bc4b4fa3fe595292f
    

    Find the latest plug-in URL and checksum on the release page.

  3. Verify plug-in installation:

    notation plugin ls
    

    Example output:

    NAME                    DESCRIPTION                                             VERSION   CAPABILITIES                ERROR
    azure-artifactsigning   Sign OCI artifacts using the Artifact Signing Service   1.0.0     [SIGNATURE_GENERATOR.RAW]   <nil>
    

Configure environment variables

Set the following environment variables for use in subsequent commands. Replace placeholders with your actual values.

You can find the required values in the Azure portal:

  • For Artifact Signing account information, go to your account, and then select Overview.
  • For certificate profile information, go to your account, and then select Objects > Certificate Profiles.
# Artifact Signing environment variables
AS_SUB_ID="<subscription-id>"
AS_ACCT_RG=<ts-account-resource-group>
AS_ACCT_NAME=<ts-account-name>
AS_ACCT_URL=<ts-account-url>
AS_CERT_PROFILE=<ts-cert-profile>
AS_CERT_SUBJECT=<ts-cert-subject>
AS_SIGNING_ROOT_CERT="https://www.microsoft.com/pkiops/certs/Microsoft%20Enterprise%20Identity%20Verification%20Root%20Certificate%20Authority%202020.crt"
AS_TSA_URL="http://timestamp.acs.microsoft.com/"
AS_TSA_ROOT_CERT="http://www.microsoft.com/pkiops/certs/microsoft%20identity%20verification%20root%20certificate%20authority%202020.crt"

# Azure Container Registry and image environment variables
ACR_SUB_ID="<acr-subscription-id>"
ACR_RG=<acr-resource-group>
ACR_NAME=<registry-name>
ACR_LOGIN_SERVER=$ACR_NAME.azurecr.io
REPOSITORY=<repository>
TAG=<tag>
IMAGE=$ACR_LOGIN_SERVER/${REPOSITORY}:$TAG

Sign in to Azure

Use the Azure CLI to sign in with your user identity:

az login
USER_ID=$(az ad signed-in-user show --query id -o tsv)

Note

This guide demonstrates signing in with a user account. For other identity options, including a managed identity, see Authenticate to Azure by using the Azure CLI.

Assign permissions for Azure Container Registry and Artifact Signing

Grant your identity the necessary roles to access Container Registry:

  • For registries enabled with attribute-based access control (ABAC), assign:
    • Container Registry Repository Reader
    • Container Registry Repository Writer
  • For non-ABAC registries, assign:
    • AcrPull
    • AcrPush
az role assignment create --role "Container Registry Repository Reader" --assignee $USER_ID --scope "/subscriptions/$ACR_SUB_ID/resourceGroups/$ACR_RG/providers/Microsoft.ContainerRegistry/registries/$ACR_NAME"
az role assignment create --role "Container Registry Repository Writer" --assignee $USER_ID --scope "/subscriptions/$ACR_SUB_ID/resourceGroups/$ACR_RG/providers/Microsoft.ContainerRegistry/registries/$ACR_NAME"

Assign the role Artifact Signing Certificate Profile Signer to your identity so that you can sign by using Artifact Signing:

az role assignment create --assignee $USER_ID --role "Artifact Signing Certificate Profile Signer" --scope "/subscriptions/$AS_SUB_ID/resourceGroups/$AS_ACCT_RG/providers/Microsoft.CodeSigning/codeSigningAccounts/$AS_ACCT_NAME/certificateProfiles/$AS_CERT_PROFILE"

Sign a container image

# Authenticate to Azure Container Registry
az acr login --name $ACR_NAME

# Download the timestamping root certificate
curl -o msft-tsa-root-certificate-authority-2020.crt $AS_TSA_ROOT_CERT

# Sign the image
notation sign --signature-format cose --timestamp-url $AS_TSA_URL --timestamp-root-cert "msft-tsa-root-certificate-authority-2020.crt" --id $AS_CERT_PROFILE --plugin azure-artifactsigning --plugin-config accountName=$AS_ACCT_NAME --plugin-config baseUrl=$AS_ACCT_URL --plugin-config certProfile=$AS_CERT_PROFILE $IMAGE

Key flags explained:

  • --signature-format cose: Uses CBOR Object Signing and Encryption (COSE) format for signatures.
  • --timestamp-url: Uses the timestamping server that Artifact Signing supports.
  • --plugin-config: Passes configuration to the Artifact Signing plug-in.

List signed images and signatures:

notation ls $IMAGE

Example output:

myregistry.azurecr.io/myrepo@sha256:5d0bf1e8f5a0c74a4c22d8c0f962a7cfa06a4f9d8423b196e482df8af23b5d55
└── application/vnd.cncf.notary.signature
    └── sha256:d3a4c9fbc17e27b19a0b28e7b6a33f2c0f541dbdf8d2e5e8d0d79a835e8a76f2a

Verify a container image

  1. Download and add root certificates:

    curl -o msft-root-certificate-authority-2020.crt $AS_SIGNING_ROOT_CERT
    SIGNING_TRUST_STORE="myRootCerts"
    notation cert add --type ca --store $SIGNING_TRUST_STORE msft-root-certificate-authority-2020.crt
    
    curl -o msft-tsa-root-certificate-authority-2020.crt $AS_TSA_ROOT_CERT
    TSA_TRUST_STORE="myTsaRootCerts"
    notation cert add -t tsa -s $TSA_TRUST_STORE msft-tsa-root-certificate-authority-2020.crt
    notation cert ls
    

  1. Create a trust policy JSON file:

    cat <<EOF > trustpolicy.json
    {
        "version": "1.0",
        "trustPolicies": [
            {
                "name": "myPolicy",
                "registryScopes": [ "$ACR_LOGIN_SERVER/$REPOSITORY" ],
                "signatureVerification": {
                    "level" : "strict"
                },
                "trustStores": [ "ca:$SIGNING_TRUST_STORE", "tsa:$TSA_TRUST_STORE" ],
                "trustedIdentities": [
                    "x509.subject: $AS_CERT_SUBJECT"
                ]
            }
        ]
    }
    EOF
    

    Import and check the policy:

    notation policy import trustpolicy.json
    notation policy show
    

  1. Verify the image:

    notation verify $IMAGE
    

    Example output:

    Successfully verified signature for myregistry.azurecr.io/myrepo@sha256:5d0bf1e8f5a0c74a4c22d8c0f962a7cfa06a4f9d8423b196e482df8af23b5d55
    

    If verification fails, ensure that your trust policy and certificates are configured correctly.