Compartir a través de


Firmar las imágenes de contenedores utilizando la herramienta Notation, Azure Key Vault y un certificado autofirmado

Este artículo forma parte de una serie sobre cómo garantizar la integridad y la autenticidad de las imágenes de contenedor y otros artefactos de Open Container Initiative (OCI). Para obtener la imagen completa, comience con la información general, que explica por qué la firma es importante y describe los distintos escenarios.

Firmar imágenes de contenedor es un proceso que ayuda a garantizar su autenticidad e integridad. Durante la implementación se comprueba una firma digital que se agrega a una imagen de contenedor. La firma ayuda a comprobar que la imagen procede de un publicador de confianza y no se modifica.

En este artículo se describen las siguientes herramientas implicadas en el proceso de firma:

  • Notación es una herramienta de seguridad de cadena de suministro de código abierto desarrollada por la comunidad de Notary Project y respaldada por Microsoft. Admite la firma y comprobación de imágenes de contenedor y otros artefactos.

    Si desea firmar una imagen de contenedor mediante Notation en canalizaciones de integración continua y entrega continua (CI/CD), siga las guías para Azure Pipelines o Acciones de GitHub.

  • Azure Key Vault es un servicio para almacenar certificados con claves de firma. La herramienta de notación puede usar estas claves mediante el complemento Key Vault (notation-azure-kv) para firmar y verificar imágenes de contenedor y otros artefactos.

  • Azure Container Registry es un registro privado que puede usar para adjuntar firmas a imágenes de contenedor y otros artefactos, junto con la visualización de esas firmas.

En este artículo aprenderá a:

  • Instale la interfaz de la línea de comandos (CLI) de Notation y el complemento key Vault.
  • Cree un certificado autofirmado en Key Vault.
  • Compile e inserte una imagen de contenedor mediante tareas de Container Registry.
  • Firme una imagen de contenedor mediante la CLI de Notación y el complemento Key Vault.
  • Valida una imagen de contenedor contra la firma utilizando la CLI de Notation.
  • Use la marca de tiempo.

Requisitos previos

Instala la CLI de Notation y el complemento de Key Vault

  1. Instale Notation v1.3.2 en un entorno linux AMD64. Para descargar el paquete para otros entornos, siga la guía de instalación de notación.

    # 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 el complemento Key Vault (notation-azure-kv) v1.2.1 en un entorno linux AMD64.

    Nota:

    Puede encontrar la dirección URL y la suma de comprobación SHA256 del complemento en la página de versión del complemento.

    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. Enumere los complementos disponibles y confirme que el notation-azure-kv complemento con la versión 1.2.1 está incluido en la lista:

    notation plugin ls
    

Configuración de las variables de entorno

Para facilitar la ejecución de comandos en este artículo, proporcione valores para que los recursos de Azure coincidan con los recursos existentes de Container Registry y Key Vault.

  1. Configuración de nombres de recursos de 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. Configuración de Container Registry y nombres de recursos de imagen:

    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
    

Inicio de sesión mediante la CLI de Azure

az login

Para más información, consulte Autenticación en Azure mediante la CLI de Azure.

Concesión de permisos de acceso a Container Registry y Key Vault

Cuando trabaja con Container Registry y Key Vault, es esencial conceder los permisos adecuados para ayudar a garantizar el acceso seguro y controlado. Puede autorizar el acceso a varias entidades, como principales de usuario, principales de servicio o identidades administradas, según tus escenarios específicos. En este artículo, el acceso está autorizado para un usuario de Azure que ha iniciado sesión.

Autorización del acceso a Container Registry

Para los registros habilitados para el control de acceso basado en atributos (ABAC) de Microsoft Entra, Container Registry Repository Reader y Container Registry Repository Writer roles son necesarios para construir y firmar imágenes de contenedor en el Container Registry.

En el caso de los registros no habilitados para ABAC, se requieren los roles AcrPull y AcrPush.

Para obtener más información sobre ABAC, consulte Control de acceso basado en atributos de Microsoft Entra para permisos de repositorio.

  1. Establezca la suscripción que contiene el recurso de Container Registry:

    az account set --subscription $ACR_SUB_ID
    
  2. Asigne los roles. El rol correcto para usar en la asignación de roles depende de si el registro está habilitado para ABAC o no.

    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"
    

Autorización del acceso a Key Vault

En esta sección se exploran dos opciones para autorizar el acceso a Key Vault.

Los siguientes roles son necesarios para firmar mediante certificados autofirmados:

  • Key Vault Certificates Officer para crear y leer certificados
  • Key Vault Certificates User para leer certificados existentes
  • Key Vault Crypto User para las operaciones de firma

Para más información sobre el acceso a Key Vault con el control de acceso basado en rol (RBAC) de Azure, consulte Proporcionar acceso a claves, certificados y secretos de Key Vault mediante el control de acceso basado en rol de Azure.

  1. Establezca la suscripción que contiene el recurso de Key Vault:

    az account set --subscription $AKV_SUB_ID
    
  2. Asigne los roles:

    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"
    

Asignar una directiva de acceso en Key Vault (heredado)

Los permisos siguientes son necesarios para una identidad:

  • Create permisos para crear un certificado
  • Get permisos para leer certificados existentes
  • Sign permisos para las operaciones de firma

Para obtener más información sobre cómo asignar una directiva a un principal, consulte Asignar una política de acceso de Key Vault (heredada).

  1. Establezca la suscripción que contiene el recurso de Key Vault:

    az account set --subscription $AKV_SUB_ID
    
  2. Establezca la directiva de acceso en 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

En este ejemplo se muestran los permisos mínimos que necesita para crear un certificado y firmar una imagen de contenedor. En función de sus requisitos, es posible que tenga que conceder más permisos.

Creación de un certificado autofirmado en Key Vault (CLI de Azure)

En los pasos siguientes se muestra cómo crear un certificado autofirmado con fines de prueba:

  1. Cree un archivo de directiva de certificados.

    Después de ejecutar el archivo de directiva de certificado mediante el código siguiente, crea un certificado válido compatible con los requisitos de certificado de Notary Project en Key Vault. El valor de es para ekus la firma de código, pero no es necesario para que Notación firme artefactos. El asunto se usa más adelante como una identidad de confianza durante la comprobación.

    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. Cree el certificado:

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

Firmar una imagen de contenedor utilizando la CLI de Notation y el complemento Key Vault

  1. Autentíquese en el registro de contenedor mediante la identidad de Azure individual:

    az acr login --name $ACR_NAME
    

    Importante

    Si tiene Docker instalado en el sistema y ha usado az acr login o docker login para autenticarse en el registro de contenedor, las credenciales ya están almacenadas y disponibles para notación. En este caso, no es necesario volver a ejecutar notation login para autenticarse en el registro de contenedor. Para más información sobre las opciones de autenticación para notación, consulte Autenticación con registros compatibles con OCI.

  2. Compile e inserte una nueva imagen mediante tareas de Azure Container Registry. Use siempre el valor de resumen para identificar la imagen para firmar, ya que las etiquetas son mutables y se pueden sobrescribir.

    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
    

    En este artículo, si la imagen ya está compilada y se almacena en el Registro, la etiqueta actúa como identificador para esa imagen para mayor comodidad:

    IMAGE=$REGISTRY/${REPO}:$TAG
    
  3. Obtenga el identificador de la clave de firma. Un certificado de Key Vault puede tener varias versiones. El comando siguiente obtiene el identificador de clave de la versión más reciente:

    KEY_ID=$(az keyvault certificate show -n $CERT_NAME --vault-name $AKV_NAME --query 'kid' -o tsv)
    
  4. Firme la imagen del contenedor con el formato de firma y cifrado de objetos CBOR (COSE), utilizando el identificador de la clave de firma. Para firmar con un certificado autofirmado, debe establecer el valor de configuración del complemento self_signed=true.

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

    Para autenticarse con Key Vault, de forma predeterminada, se intentan los siguientes tipos de credenciales (si están habilitados):

    Si desea especificar un tipo de credencial, use una configuración adicional de complemento denominada credential_type. Por ejemplo, puede establecer credential_type explícitamente en azurecli para usar una credencial de la CLI de Azure, como se muestra en este ejemplo:

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

    En la siguiente tabla se muestran los valores de credential_type para varios tipos de credenciales.

    Tipo de credencial Valor para credential_type
    Credenciales de entorno environment
    Credencial de identidad de carga de trabajo workloadid
    Credenciales de identidad administrada managedid
    Credencial de la CLI de Azure azurecli

    Nota:

    Desde Notation v1.2.0, Notation usa el esquema de etiquetas de referencia de OCI para almacenar la firma en el Registro de Contenedores de forma predeterminada. También puede habilitar la API de referencias de OCI mediante la marca --force-referrers-tag false, si es necesario. Las características de Container Registry admiten la API de referencias de OCI, excepto el registro cifrado mediante claves administradas por el cliente (CMK).

  5. Vea el gráfico de imágenes firmadas y firmas asociadas:

    notation ls $IMAGE
    

Verifique una imagen de contenedor utilizando la CLI de Notation

Para verificar la imagen del contenedor, agregue el certificado raíz que firma el certificado intermedio al almacén de certificados de confianza y establezca políticas de confianza para la verificación. Para el certificado autofirmado que usa este artículo, el certificado raíz es el propio certificado autofirmado.

  1. Descargue un certificado público:

    az keyvault certificate download --name $CERT_NAME --vault-name $AKV_NAME --file $CERT_PATH
    
  2. Agregue el certificado público descargado al almacén de confianza con nombre para la comprobación de firmas:

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

    notation cert ls
    
  4. Configure una directiva de confianza antes de la comprobación.

    Las directivas de confianza permiten a los usuarios especificar directivas de comprobación optimizadas. En el ejemplo siguiente se configura una directiva de confianza denominada wabbit-networks-images. Esta política se aplica a todos los artefactos en $REGISTRY/$REPO y utiliza el almacén de confianza llamado $STORE_NAME del tipo $STORE_TYPE. También supone que el usuario confía en una identidad específica con el asunto X.509 $CERT_SUBJECT. Para obtener más información, consulte la especificación del almacén de confianza y la directiva de confianza.

    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 la configuración de la directiva de confianza desde el archivo JSON que creó anteriormente:

    notation policy import ./trustpolicy.json
    notation policy show
    
  6. Use notation verify para comprobar que la imagen de contenedor no se modificó después del tiempo de compilación:

    notation verify $IMAGE
    

    Tras la comprobación correcta de la imagen a través de la directiva de confianza, el resumen SHA256 de la imagen verificada se devuelve en un mensaje de salida correcto.

Use la marca de tiempo

Desde la versión Notation v1.2.0, Notation admite la marca de tiempo compatible con RFC 3161. Esta mejora amplía la confianza de las firmas creadas dentro del período de validez del certificado mediante la confianza en una autoridad de sello de tiempo (TSA). Esta confianza permite la comprobación correcta de firmas incluso después de que expiren los certificados.

Como firmante de imágenes, debe asegurarse de que las imágenes de contenedores se firmen con marcas de tiempo generadas por una TSA de confianza. Como verificador de imágenes, debe asegurarse de que confía tanto en el firmante de imágenes como en el TSA asociado, y establecer la confianza a través de almacenes de confianza y políticas de confianza.

La marca de tiempo reduce los costos eliminando la necesidad de volver a firmar periódicamente las imágenes debido a la expiración del certificado. Esta capacidad es especialmente crítica cuando se usan certificados de corta duración. Para obtener instrucciones detalladas sobre cómo firmar y comprobar imágenes mediante la marca de tiempo, consulte la guía de marcas de tiempo del proyecto notario.

Notación proporciona soluciones de CI/CD en Azure Pipelines y Acciones de GitHub:

Para garantizar que solo se despliegan imágenes de contenedor de confianza en Azure Kubernetes Service (AKS):