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

A assinatura de imagens de contêiner é um processo que garante autenticidade e integridade. Isso é feito adicionando uma assinatura digital à imagem de contêiner, que pode ser validada durante a implantação. A assinatura ajuda a verificar se a imagem é de um editor confiável e se não foi modificada. O Notation é uma ferramenta de segurança de cadeia de suprimentos de código aberto desenvolvida pela comunidade Notary Project e com apoio da Microsoft, que oferece suporte à assinatura e verificação de imagens de contêiner e outros artefatos. O AKV (Azure Key Vault) é usado para armazenar certificados com chaves de assinatura que podem ser usadas pelo Notation com o plug-in Notation AKV (azure-kv) para assinar e verificar imagens de contêiner e outros artefatos. O ACR (Registro de Contêiner do Azure) permite anexar assinaturas a imagens de contêiner e outros artefatos, bem como exibir essas assinaturas.

Neste tutorial:

  • Instalar a CLI do Notation e o plug-in AKV
  • Criar um certificado autoassinado no AKV
  • Compilar e enviar uma imagem de contêiner com as Tarefas do ACR
  • Assine uma imagem de contêiner com a CLI do Notation e o plug-in AKV
  • Valide uma imagem de contêiner em relação à assinatura com a CLI do Notation
  • Carimbo de data/hora

Pré-requisitos

Instalar a CLI do Notation e o plug-in AKV

  1. Instale o Notation v1.2.0 em um ambiente amd64 do Linux. Siga o guia de instalação do Notação para baixar o pacote para outros ambientes.

    # 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 binary to the desired bin directory in your $PATH, for example
    cp ./notation /usr/local/bin
    
  2. Instale o plug-in Notation Azure Key Vault azure-kv v1.2.0 em um ambiente Linux amd64.

    Observação

    A soma de verificação de URL e SHA256 para o plug-in de Notação do Azure Key Vault, pode ser encontrada na página de lançamento do plug-in.

    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. Liste os plug-ins disponíveis e confirme se o plug-in azure-kv com a versão 1.2.0 está incluída na lista.

    notation plugin ls
    

Configurar variáveis de ambiente

Observação

Para facilitar a execução de comandos no tutorial, forneça valores para que os recursos do Azure correspondam aos recursos existentes do ACR e do AKV.

  1. Configurar nomes de recursos do AKV.

    AKV_SUB_ID=myAkvSubscriptionId
    AKV_RG=myAkvResourceGroup
    # Name of the existing AKV used to store the signing keys
    AKV_NAME=myakv
    # Name of the certificate created in AKV
    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. Configurar nomes de recursos de imagem e 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
    IMAGE=$REGISTRY/${REPO}:$TAG
    # Source code directory containing Dockerfile to build
    IMAGE_SOURCE=https://github.com/wabbit-networks/net-monitor.git#main
    

Entrar com a CLI do Azure

az login

Para saber mais sobre a CLI do Azure e como fazer entrar com ela, confira Entrar com a CLI do Azure.

Proteger permissões de acesso ao ACR e AKV

Ao trabalhar com o ACR e AKV, é essencial conceder as permissões apropriadas para garantir acesso seguro e controlado. Você pode autorizar o acesso de entidades diferentes, como entidades de usuário, entidades de serviço ou identidades gerenciadas, dependendo de seus cenários específicos. Neste tutorial, o acesso está autorizado a um usuário conectado do Azure.

Autorizar o acesso ao ACR

As funções AcrPull e AcrPush são necessárias para assinar imagens de contêiner no ACR.

  1. Definir a assinatura que contém o recurso do ACR

    az account set --subscription $ACR_SUB_ID
    
  2. Atribuir as funções

    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"
    

Autorizar o acesso ao AKV

Nesta seção, vamos explorar duas opções para autorizar o acesso ao AKV.

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

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

Para saber mais sobre o acesso ao Key Vault com o RBAC do Azure, consulte Usar um RBAC do Azure para gerenciar o acesso.

  1. Definir a assinatura que contém o recurso AKV

    az account set --subscription $AKV_SUB_ID
    
  2. Atribuir 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 política de acesso no AKV (herdado)

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

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

Para saber mais sobre a atribuição de política a uma entidade de segurança, confira Atribuir Política de Acesso.

  1. Defina a assinatura que contém o recurso AKV:

    az account set --subscription $AKV_SUB_ID
    
  2. Defina a política de acesso no AKV:

    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

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

Criar um certificado autoassinado no AKV (CLI do Azure)

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

  1. Criar um arquivo de política de certificação.

    Quando o arquivo de política de certificado é executado conforme abaixo, ele cria um certificado válido compatível com os requisitos de certificado do Notary Project no AKV. O valor de ekus é para a assinatura de código, mas não é necessário para a notação para assinar artefatos. A entidade em questão é usada posteriormente como a identidade de confiança na qual o usuário irá confiar 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. Criar o certificado.

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

Assine uma imagem de contêiner com a CLI do Notation e o plug-in AKV

  1. Faça a autenticação no ACR usando sua identidade individual do Azure.

    az acr login --name $ACR_NAME
    

Importante

Se você tiver o Docker instalado no sistema e usou az acr login ou docker login para se autenticar no ACR, suas credenciais já estarão armazenadas e disponíveis para notação. Nesse caso, você não precisa executar notation login novamente para se autenticar no ACR. Para saber mais sobre as opções de autenticação para notação, confira Autenticar com registros compatíveis com OCI.

  1. Compilar e enviar por push uma nova imagem com Tarefas do ACR. Sempre use o valor de resumo da mensagem para identificar a imagem para assinatura, pois as marcas 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 tutorial, se a imagem já foi criada e armazenada no registro, a marca servirá como um identificador para essa imagem por conveniência.

    IMAGE=$REGISTRY/${REPO}:$TAG
    
  2. Obtenha a ID de Chave da chave de assinatura. Um certificado no AKV pode ter várias versões; o comando a seguir obtém a 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)
    
  3. Assine a imagem de contêiner com o formato de assinatura COSE usando a ID da chave de assinatura. Para assinar com um certificado autoassinado, você precisa definir o valor de 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 AKV, por padrão, os seguintes tipos de credencial se habilitados serão testados na ordem:

    Se você quiser 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 a credencial da CLI do Azure, conforme demonstrado abaixo:

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

    Consulte a tabela abaixo para obter os valores de credential_type para vários tipos de credencial.

    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
  4. Veja o grafo de imagens assinadas e assinaturas associadas.

    notation ls $IMAGE
    

Verificar uma imagem de contêiner com a CLI do Notation

Para verificar a imagem de contêiner, adicione o certificado raiz que assina o certificado folha ao armazenamento confiável e crie políticas de confiança para verificação. No caso do certificado autoassinado usado neste tutorial, o certificado raiz é o próprio certificado autoassinado.

  1. Baixar 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 repositório confiável nomeado para a verificação da assinatura.

    STORE_TYPE="ca"
    STORE_NAME="wabbit-networks.io"
    notation cert add --type $STORE_TYPE --store $STORE_NAME $CERT_PATH
    
  3. Liste o certificado a ser confirmado.

    notation cert ls
    
  4. Configure a 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 com ajuste fino. O exemplo a seguir configura uma política de confiança chamada wabbit-networks-images, que se aplica a todos os artefatos em $REGISTRY/$REPO e usa o repositório confiável $STORE_NAME nomeado do tipo $STORE_TYPE. Ele também pressupõe que o usuário confia em uma identidade específica com o assunto X.509 $CERT_SUBJECT. Para obter mais detalhes, confira Especificação do repositório confiável e da 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 a notation policy para importar a configuração de política de confiança de um arquivo JSON que criamos anteriormente.

    notation policy import ./trustpolicy.json
    notation policy show
    
  6. Use notation verify para verificar se a imagem de contêiner não foi alterada desde o momento da compilação.

    notation verify $IMAGE
    

    Após a verificação bem-sucedida da imagem usando a política de confiança, o código hash sha256 da imagem verificada será retornado em uma mensagem de saída bem-sucedida.

Carimbo de data/hora

Desde o lançamento do Notation v1.2.0, o Notation oferece suporte a carimbos de data/hora compatíveis com RFC 3161. Esse aprimoramento estende a confiança das assinaturas criadas no período de validade do certificado confiando em uma Autoridade de Carimbo de Data/Hora (TSA), permitindo a verificação de assinatura bem-sucedida mesmo após os certificados expirarem. Como signatário de imagem, você deve garantir a assinatura de imagens de contêineres com carimbos de data/hora gerados por um TSA confiável. Como verificador de imagens, para verificar carimbos de data/hora, você deve garantir que confia no signatário da imagem e no TSA associado e estabelecer a confiança usando armazenamentos e políticas de confiança. O registro de data e hora reduz custos ao eliminar a necessidade de assinar novamente imagens periodicamente devido à expiração do certificado, o que é especialmente crítico ao usar certificados de curta duração. Para obter instruções detalhadas sobre como assinar e verificar usando carimbo de data/hora, consulte o Guia de carimbo de data/hora do Notary Project.

Próximas etapas

A notação também fornece soluções de CI/CD no fluxo de trabalho do Azure Pipeline e do GitHub Actions:

Para validar a implantação de imagem assinada no AKS ou Kubernetes: