Partilhar via


Assinar imagens de contêiner usando Notation, Azure Key Vault e um certificado autoassinado

Este artigo faz parte de uma série sobre como garantir a integridade e autenticidade de imagens de contêiner e outros artefatos da Open Container Initiative (OCI). Para obter uma visão completa, comece com a visão geral, que explica por que a assinatura é importante e descreve os vários cenários.

A assinatura de imagens de contêiner é um processo que ajuda a garantir sua autenticidade e integridade. Uma assinatura digital adicionada a uma imagem de contêiner é verificada durante a implantação. A assinatura ajuda a verificar se a imagem é de um editor confiável e não foi modificada.

Este artigo descreve as seguintes ferramentas envolvidas no processo de assinatura:

  • Notation é uma ferramenta de segurança da cadeia de suprimentos de código aberto desenvolvida pela comunidade Notary Project e apoiada pela Microsoft. Ele suporta a assinatura e verificação de imagens de contêiner e outros artefatos.

    Se pretender assinar uma imagem de container usando Notation em pipelines de integração contínua e entrega contínua (CI/CD), siga as orientações para Azure Pipelines ou GitHub Actions.

  • O Azure Key Vault é um serviço para armazenar certificados com chaves de assinatura. A notação pode usar essas chaves por meio do plug-in Key Vault (notation-azure-kv) para assinar e verificar imagens de contêiner e outros artefatos.

  • O Registro de Contêiner do Azure é um registro privado que você pode usar para anexar assinaturas a imagens de contêiner e outros artefatos, além de exibir essas assinaturas.

Neste artigo, você aprenderá a:

  • Instale a interface de linha de comando (CLI) Notation e o plug-in Key Vault.
  • Crie um certificado autoassinado no Key Vault (Cofre de Chaves).
  • Crie e envie por push uma imagem de contêiner usando tarefas do Registro de Contêiner.
  • Assine uma imagem de contentor usando o Notation CLI e o plug-in Key Vault.
  • Valide uma imagem de contentor em relação à assinatura utilizando a CLI Notation.
  • Utilize o carimbo de data/hora.

Pré-requisitos

Instale a CLI de Notation e o plug-in do Key Vault

  1. Instale o Notation v1.3.2 em um ambiente Linux AMD64. Para baixar o pacote para outros ambientes, siga o guia de instalação do Notation.

    # Download, extract, and install
    curl -Lo notation.tar.gz https://github.com/notaryproject/notation/releases/download/v1.3.2/notation_1.3.2_linux_amd64.tar.gz
    tar xvzf notation.tar.gz
    
    # Copy the Notation binary to the desired bin directory in $PATH, for example
    cp ./notation /usr/local/bin
    
  2. Instale o plug-in Key Vault (notation-azure-kv) v1.2.1 em um ambiente Linux AMD64.

    Nota

    Você pode encontrar a URL e a soma de verificação SHA256 para o plug-in na página de lançamento do plug-in.

    notation plugin install --url https://github.com/Azure/notation-azure-kv/releases/download/v1.2.1/notation-azure-kv_1.2.1_linux_amd64.tar.gz --sha256sum 67c5ccaaf28dd44d2b6572684d84e344a02c2258af1d65ead3910b3156d3eaf5
    
  3. Liste os plug-ins disponíveis e confirme se o notation-azure-kv plug-in com versão 1.2.1 está incluído na lista:

    notation plugin ls
    

Configurar variáveis de ambiente

Para facilitar a execução de comandos neste artigo, forneça valores para que os recursos do Azure correspondam aos recursos existentes do Registro de Contêiner e do Cofre de Chaves.

  1. Configurar nomes de recursos no Azure Key Vault:

    AKV_SUB_ID=myAkvSubscriptionId
    AKV_RG=myAkvResourceGroup
    # Name of the existing key vault used to store the signing keys
    AKV_NAME=myakv
    # Name of the certificate created in the key vault
    CERT_NAME=wabbit-networks-io
    CERT_SUBJECT="CN=wabbit-networks.io,O=Notation,L=Seattle,ST=WA,C=US"
    CERT_PATH=./${CERT_NAME}.pem
    
  2. Configure o Registro de Contêiner e nomes de recursos de imagem:

    ACR_SUB_ID=myAcrSubscriptionId
    ACR_RG=myAcrResourceGroup
    # Name of the existing registry (example: myregistry.azurecr.io)
    ACR_NAME=myregistry
    # Existing full domain of the container registry
    REGISTRY=$ACR_NAME.azurecr.io
    # Container name inside the container registry where the image will be stored
    REPO=net-monitor
    TAG=v1
    IMAGE=$REGISTRY/${REPO}:$TAG
    # Source code directory that contains the Dockerfile to build
    IMAGE_SOURCE=https://github.com/wabbit-networks/net-monitor.git#main
    

Entrar usando a CLI do Azure

az login

Para obter mais informações, consulte Autenticar no Azure usando a CLI do Azure.

Conceder permissões de acesso ao Registro de Contêiner e ao Cofre de Chaves

Quando você estiver trabalhando com o Registro de Contêiner e o Cofre de Chaves, é essencial conceder as permissões apropriadas para ajudar a garantir acesso seguro e controlado. Você pode autorizar o acesso para várias entidades, como entidades de usuário, entidades de serviço ou identidades gerenciadas, dependendo de seus cenários específicos. Neste artigo, o acesso é autorizado para um usuário conectado do Azure.

Autorizar o acesso ao Registro de Contêiner

Para registos habilitados para o controlo de acesso baseado em atributos (ABAC) do Microsoft Entra, são necessárias as funções Container Registry Repository Reader e Container Registry Repository Writer para criar e assinar imagens de contêiner no Registo de Contêiner.

Para registos não habilitados para ABAC, os papéis AcrPull e AcrPush são necessários.

Para obter mais informações sobre o ABAC, consulte Controle de acesso baseado em atributos do Microsoft Entra para permissões de repositório.

  1. Defina a assinatura que contém o recurso Registro de Contêiner:

    az account set --subscription $ACR_SUB_ID
    
  2. Atribua as funções. A função correta a ser usada na atribuição de função depende se o registro está habilitado para ABAC ou não.

    USER_ID=$(az ad signed-in-user show --query id -o tsv)
    ROLE1="Container Registry Repository Reader" # For ABAC-enabled registries. Otherwise, use "AcrPull" for non-ABAC-enabled registries.
    ROLE2="Container Registry Repository Writer" # For ABAC-enabled registries. Otherwise, use "AcrPush" for non-ABAC-enabled registries.
    az role assignment create --role "$ROLE1" --role "$ROLE2" --assignee $USER_ID --scope "/subscriptions/$ACR_SUB_ID/resourceGroups/$ACR_RG/providers/Microsoft.ContainerRegistry/registries/$ACR_NAME"
    

Autorizar o acesso ao Cofre de Chaves

Esta seção explora duas opções para autorizar o acesso ao Cofre da Chave.

As seguintes funções são necessárias para assinar usando certificados autoassinados:

  • Key Vault Certificates Officer para criar e ler certificados
  • Key Vault Certificates User para leitura de certificados existentes
  • Key Vault Crypto User para operações de assinatura

Para saber mais sobre o acesso ao Cofre da Chave com o RBAC (controle de acesso baseado em função) do Azure, consulte Fornecer acesso a chaves, certificados e segredos do Cofre da Chave usando o controle de acesso baseado em função do Azure.

  1. Defina a assinatura que contém o recurso do Key Vault.

    az account set --subscription $AKV_SUB_ID
    
  2. Atribua as funções:

    USER_ID=$(az ad signed-in-user show --query id -o tsv)
    az role assignment create --role "Key Vault Certificates Officer" --role "Key Vault Crypto User" --assignee $USER_ID --scope "/subscriptions/$AKV_SUB_ID/resourceGroups/$AKV_RG/providers/Microsoft.KeyVault/vaults/$AKV_NAME"
    

Atribuir uma política de acesso no Cofre da Chave (legado)

As seguintes permissões são necessárias para uma identidade:

  • Create Permissões para criar um certificado
  • Get Permissões para ler certificados existentes
  • Sign Permissões para operações de assinatura

Para saber mais sobre como atribuir uma política a uma entidade de segurança, consulte Atribuir uma política de acesso ao Cofre da Chave (legado).

  1. Defina a assinatura que contém o recurso do Key Vault.

    az account set --subscription $AKV_SUB_ID
    
  2. Defina a Política de Acesso no Key Vault:

    USER_ID=$(az ad signed-in-user show --query id -o tsv)
    az keyvault set-policy -n $AKV_NAME --certificate-permissions create get --key-permissions sign --object-id $USER_ID
    

Importante

Este exemplo mostra as permissões mínimas necessárias para criar um certificado e assinar uma imagem de contêiner. Dependendo dos seus requisitos, talvez seja necessário conceder mais permissões.

Criar um certificado autoassinado no Cofre da Chave (CLI do Azure)

As etapas a seguir mostram como criar um certificado autoassinado para fins de teste:

  1. Crie um arquivo de política de certificado.

    Após a execução do ficheiro de política de certificado através do código abaixo, será criado um certificado válido que é compatível com os requisitos de certificado do Projeto Notarial no Azure Key Vault. O valor de ekus é para a assinatura de código, mas não é necessário que Notation assine artefatos. O sujeito é utilizado mais tarde como uma identidade confiável durante a verificação.

    cat <<EOF > ./my_policy.json
    {
        "issuerParameters": {
        "certificateTransparency": null,
        "name": "Self"
        },
        "keyProperties": {
          "exportable": false,
          "keySize": 2048,
          "keyType": "RSA",
          "reuseKey": true
        },
        "secretProperties": {
          "contentType": "application/x-pem-file"
        },
        "x509CertificateProperties": {
        "ekus": [
            "1.3.6.1.5.5.7.3.3"
        ],
        "keyUsage": [
            "digitalSignature"
        ],
        "subject": "$CERT_SUBJECT",
        "validityInMonths": 12
        }
    }
    EOF
    
  2. Crie o certificado:

    az keyvault certificate create -n $CERT_NAME --vault-name $AKV_NAME -p @my_policy.json
    

Assinar uma imagem de contêiner usando o plug-in Notation CLI e Key Vault

  1. Autentique-se em seu registro de contêiner usando sua identidade individual do Azure:

    az acr login --name $ACR_NAME
    

    Importante

    Se você tiver o Docker instalado em seu sistema e tiver usado az acr login ou docker login para autenticar no registro do contêiner, suas credenciais já estarão armazenadas e disponíveis para Notation. Nesse caso, você não precisa executar notation login novamente para autenticar no registro do contêiner. Para saber mais sobre as opções de autenticação para Notação, consulte Autenticar com registros compatíveis com OCI.

  2. Crie e envie por push uma nova imagem usando tarefas do Registro de Contêiner do Azure. Use sempre o valor digest para identificar a imagem para assinatura, porque as tags são mutáveis e podem ser substituídas.

    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
    

    Neste artigo, se a imagem já estiver compilada e armazenada no Registro, a tag servirá como um identificador para essa imagem por conveniência:

    IMAGE=$REGISTRY/${REPO}:$TAG
    
  3. Obtenha a ID da chave de assinatura. Um certificado no Azure Key Vault pode ter várias versões. O comando a seguir obtém o ID de chave da versão mais recente:

    KEY_ID=$(az keyvault certificate show -n $CERT_NAME --vault-name $AKV_NAME --query 'kid' -o tsv)
    
  4. Assine a imagem do contêiner com o formato de assinatura COSE (CBOR Object Signing and Encryption), usando o ID da chave de assinatura. Para assinar com um certificado autoassinado, é necessário definir o valor self_signed=true da configuração do plug-in.

    notation sign --signature-format cose --id $KEY_ID --plugin azure-kv --plugin-config self_signed=true $IMAGE
    

    Para autenticar com o Azure Key Vault, normalmente, por predefinição, os seguintes tipos de credenciais (se habilitados) são utilizados na ordem:

    Se desejar especificar um tipo de credencial, use uma configuração de plug-in adicional chamada credential_type. Por exemplo, você pode definir credential_type explicitamente como azurecli para usar uma credencial da CLI do Azure, conforme demonstrado neste exemplo:

    notation sign --signature-format cose --id $KEY_ID --plugin azure-kv --plugin-config self_signed=true --plugin-config credential_type=azurecli $IMAGE
    

    A tabela a seguir mostra os valores de credential_type para vários tipos de credenciais.

    Tipo de credencial Valor para credential_type
    Credencial de ambiente environment
    Credencial de identidade de carga de trabalho workloadid
    Credencial de identidade gerenciada managedid
    Credencial da CLI do Azure azurecli

    Nota

    Desde a Notação v1.2.0, a Notação usa o esquema de marca de referenciadores OCI para armazenar a assinatura no Registro de Contêiner por padrão. Você também pode habilitar a API de referências OCI usando o sinalizador --force-referrers-tag false, se necessário. Os recursos do Registo de contentores suportam a API de Referências OCI, exceto para o registo encriptado por meio de chaves geridas pelo cliente (CMKs).

  5. Veja o gráfico de imagens assinadas e assinaturas associadas:

    notation ls $IMAGE
    

Verificar uma imagem de contentor usando a linha de comandos Notation

Para verificar a imagem do contêiner, adicione o certificado raiz que assina o certificado intermediário ao repositório de confiança e crie políticas de confiança para a verificação. Para o certificado autoassinado usado neste artigo, o certificado raiz é o próprio certificado autoassinado.

  1. Faça o download de um certificado público:

    az keyvault certificate download --name $CERT_NAME --vault-name $AKV_NAME --file $CERT_PATH
    
  2. Adicione o certificado público baixado ao armazenamento confiável nomeado para verificação de assinatura:

    STORE_TYPE="ca"
    STORE_NAME="wabbit-networks.io"
    notation cert add --type $STORE_TYPE --store $STORE_NAME $CERT_PATH
    
  3. Liste o certificado para confirmar:

    notation cert ls
    
  4. Configure uma política de confiança antes da verificação.

    As políticas de confiança permitem que os usuários especifiquem políticas de verificação ajustadas. O exemplo a seguir configura uma política de confiança chamada wabbit-networks-images. Esta política aplica-se a todos os artefatos em $REGISTRY/$REPO e usa o armazenamento confiável nomeado $STORE_NAME do tipo $STORE_TYPE. Ele também assume que o usuário confia em uma identidade específica com o assunto $CERT_SUBJECTX.509. Para obter mais informações, consulte Armazenamento confiável e especificação de política de confiança.

    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
    
  5. Use notation policy para importar a configuração da política de confiança do arquivo JSON que você criou anteriormente:

    notation policy import ./trustpolicy.json
    notation policy show
    
  6. Use notation verify para verificar se a imagem do contêiner não foi alterada após o tempo de compilação:

    notation verify $IMAGE
    

    Após a verificação bem-sucedida da imagem por meio da política de confiança, o resumo SHA256 da imagem verificada é retornado em uma mensagem de saída bem-sucedida.

Utilizar marcação temporal

Desde o lançamento do Notation v1.2.0, o Notation suporta carimbo de data/hora compatível com RFC 3161. Esta melhoria amplia a confiança das assinaturas criadas dentro do período de validade do certificado confiando numa autoridade de marca temporal (TSA). Essa confiança permite uma verificação de assinatura bem-sucedida mesmo após a expiração dos certificados.

Como signatário de imagem, você deve garantir que assina imagens de contêiner com carimbos de data/hora gerados por um TSA confiável. Como verificador de imagem, você deve garantir que confia no signatário da imagem e no TSA associado e estabelecer confiança por meio de armazenamentos de confiança e políticas de confiança.

A autenticação temporal reduz os custos, eliminando a necessidade de se reassinarem imagens periodicamente devido à expiração do certificado. Essa capacidade é especialmente crítica quando você usa certificados de curta duração. Para obter instruções detalhadas sobre como assinar e verificar imagens usando o carimbo de data/hora, consulte o guia de carimbo de data/hora do Projeto Notarial.

Notation fornece soluções de CI/CD em Azure Pipelines e GitHub Actions.

Para garantir que apenas imagens de contêiner confiáveis sejam implantadas no Serviço Kubernetes do Azure (AKS):