Generar y validar la procedencia de la compilación

En esta página se explica cómo generar la procedencia de la compilación, ver el resultado y validarlo.

La procedencia de compilación es un conjunto de datos verificables sobre una compilación. Los metadatos de procedencia incluyen detalles como los resúmenes de las imágenes compiladas, las ubicaciones de la fuente de entrada, los argumentos de compilación y la duración de la compilación. Puedes usar esta información para asegurarte de que los artefactos compilados que utilizas son precisos y fiables, y de que los han creado fuentes y compiladores de confianza.

Cloud Build admite la generación de procedencia de compilación que cumple el nivel 3 de garantía de Supply-chain Levels for Software Artifacts (SLSA) según las especificaciones de las versiones 0.1 y 1.0 de SLSA.

Como parte de la compatibilidad con la especificación SLSA v1.0, Cloud Build proporciona detalles de buildType en la procedencia de la compilación. Puede usar el esquema buildType para comprender la plantilla parametrizada que se usa en el proceso de compilación, incluidos los valores que registra Cloud Build y el origen de esos valores. Para obtener más información, consulta buildType v1 de Cloud Build.

Limitaciones

Antes de empezar

  1. Enable the Cloud Build, Container Analysis, and Artifact Registry APIs.

    Enable the APIs

  2. Para usar los ejemplos de línea de comandos de esta guía, instala y configura el SDK de Google Cloud.

  3. Ten a mano el código fuente.

  4. Tener un repositorio en Artifact Registry.

Generar procedencia de compilación

En las siguientes instrucciones se explica cómo generar la procedencia de compilación de las imágenes de contenedor que almacena en Artifact Registry:

  1. En el archivo de configuración de compilación, añade el campo images para configurar Cloud Build de forma que almacene las imágenes compiladas en Artifact Registry una vez que se haya completado la compilación.

    Cloud Build no puede generar procedencia si insertas tu imagen en Artifact Registry mediante un paso docker push explícito.

    En el siguiente fragmento de código se muestra una configuración de compilación para crear una imagen de contenedor y almacenarla en un repositorio de Docker en Artifact Registry:

    YAML

      steps:
      - name: 'gcr.io/cloud-builders/docker'
        args: [ 'build', '-t', 'LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE', '.' ]
      images: ['LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE']
    

    Donde:

    • LOCATION: la ubicación regional o multirregional de tu repositorio.
    • PROJECT_ID: tu ID de proyecto Google Cloud .
    • REPOSITORY: el nombre de tu repositorio de Artifact Registry.
    • IMAGE: el nombre de la imagen de tu contenedor.

    JSON

      {
      "steps": [
          {
              "name": "gcr.io/cloud-builders/docker",
              "args": [
                  "build",
                  "-t",
                  "LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE",
                  "."
              ]
          }
      ],
      "images": [
          "LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE"
      ]
      }
    

    Donde:

    • LOCATION: la ubicación regional o multirregional de tu repositorio.
    • PROJECT_ID: tu ID de proyecto Google Cloud .
    • REPOSITORY: el nombre de tu repositorio de Artifact Registry.
    • IMAGE: el nombre de la imagen de tu contenedor.
  2. En la sección options de la configuración de compilación, añade la opción requestedVerifyOption y asigna el valor VERIFIED.

    Este ajuste habilita la generación de procedencia y configura Cloud Build para verificar que los metadatos de procedencia estén presentes. Las compilaciones solo se marcarán como correctas si se genera la procedencia.

    YAML

    options:
      requestedVerifyOption: VERIFIED
    

    JSON

    {
        "options": {
            "requestedVerifyOption": "VERIFIED"
        }
    }
    
  3. Empieza a crear tu versión.

Ver la procedencia de la compilación

En esta sección se explica cómo ver los metadatos de procedencia de compilación creados por Cloud Build. Puedes obtener esta información con fines de auditoría.

Para acceder a los metadatos de procedencia de compilación de los contenedores, puedes usar el panel lateral Información valiosa de seguridad de la consola Google Cloud o la CLI de gcloud.

consola

El panel lateral Información de seguridad ofrece un resumen general de la información de seguridad de los artefactos almacenados en Artifact Registry.

Para ver el panel Estadísticas de seguridad, sigue estos pasos:

  1. Abre la página Historial de compilaciones en la Google Cloud consola:

    Abre la página Historial de compilaciones.

  2. En la tabla de compilaciones, busca la fila de la compilación de la que quieras ver las estadísticas de seguridad.

  3. En la columna Información valiosa de seguridad, haga clic en Ver.

    Se muestra el panel Información de seguridad del artefacto seleccionado.

    La tarjeta Compilación muestra los detalles de procedencia y un enlace. Para ver el fragmento de procedencia, haz clic en el icono de enlace.

Para obtener más información sobre el panel lateral y cómo puedes usar Cloud Build para proteger tu cadena de suministro de software, consulta Ver información valiosa sobre la seguridad de las compilaciones.

CLI de gcloud

Para ver los metadatos de procedencia de las imágenes de contenedor, ejecuta el siguiente comando:

  gcloud artifacts docker images describe \
  LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE@sha256:HASH \
  --show-provenance --format=FORMAT

Haz los cambios siguientes:

  • LOCATION: la ubicación regional o multirregional de tu repositorio.
  • PROJECT_ID: tu ID de proyecto Google Cloud .
  • REPOSITORY: el nombre de tu repositorio de Artifact Registry.
  • IMAGE: el nombre de la imagen de tu contenedor.
  • HASH: el valor de hash sha256 de la imagen. Puedes encontrarlo en la salida de tu compilación.
  • FORMAT: un ajuste opcional en el que puede especificar un formato de salida.

Ejemplo

La procedencia de la compilación es similar a la siguiente:

      image_summary:
      digest: sha256:7e9b6e7ba2842c91cf49f3e214d04a7a496f8214356f41d81a6e6dcad11f11e3
      fully_qualified_digest: us-central1-docker.pkg.dev/my-project/my-repo/my-image@sha256:7e9b6e7ba2842c91cf49f3e214d04a7a496f8214356f41d81a6e6dcad11f11e3
      registry: us-central1-docker.pkg.dev
      repository: my-repo
      slsa_build_level: 0
    provenance_summary:
      provenance:
      - build:
          inTotoSlsaProvenanceV1:
            _type: https://in-toto.io/Statement/v1
            predicate:
              buildDefinition:
                buildType: https://cloud.google.com/build/gcb-buildtypes/google-worker/v1
                externalParameters:
                  buildConfigSource:
                    path: cloudbuild.yaml
                    ref: refs/heads/main
                    repository: git+https://github.com/my-username/my-git-repo
                  substitutions: {}
                internalParameters:
                  systemSubstitutions:
                    BRANCH_NAME: main
                    BUILD_ID: e73ca1d4-ec4a-4ea6-acdd-ac8bb16dcc79
                    COMMIT_SHA: 525c52c501739e6df0609ed1f944c1bfd83224e7
                    LOCATION: us-west1
                    PROJECT_NUMBER: '265426041527'
                    REF_NAME: main
                    REPO_FULL_NAME: my-username/my-git-repo
                    REPO_NAME: my-git-repo
                    REVISION_ID: 525c52c501739e6df0609ed1f944c1bfd83224e7
                    SHORT_SHA: 525c52c
                    TRIGGER_BUILD_CONFIG_PATH: cloudbuild.yaml
                    TRIGGER_NAME: github-trigger-staging
                  triggerUri: projects/265426041527/locations/us-west1/triggers/a0d239a4-635e-4bd3-982b-d8b72d0b4bab
                resolvedDependencies:
                - digest:
                    gitCommit: 525c52c501739e6df0609ed1f944c1bfd83224e7
                  uri: git+https://github.com/my-username/my-git-repo@refs/heads/main
                - digest:
                    sha256: 154fcd4d2d65c6a35b06b98053a0829c581e223d530be5719326f5d85d680e8d
                  uri: gcr.io/cloud-builders/docker@sha256:154fcd4d2d65c6a35b06b98053a0829c581e223d530be5719326f5d85d680e8d
              runDetails:
                builder:
                  id: https://cloudbuild.googleapis.com/GoogleHostedWorker
                byproducts:
                - {}
                metadata:
                  finishedOn: '2023-08-01T19:57:10.734471Z'
                  invocationId: https://cloudbuild.googleapis.com/v1/projects/my-project/locations/us-west1/builds/e73ca1d4-ec4a-4ea6-acdd-ac8bb16dcc79
                  startedOn: '2023-08-01T19:56:57.451553160Z'
            predicateType: https://slsa.dev/provenance/v1
            subject:
            - digest:
                sha256: 7e9b6e7ba2842c91cf49f3e214d04a7a496f8214356f41d81a6e6dcad11f11e3
              name: https://us-central1-docker.pkg.dev/my-project/my-repo/my-image
            - digest:
                sha256: 7e9b6e7ba2842c91cf49f3e214d04a7a496f8214356f41d81a6e6dcad11f11e3
              name: https://us-central1-docker.pkg.dev/my-project/my-repo/my-image:latest
        createTime: '2023-08-01T19:57:14.810489Z'
        envelope:
          payload:
          eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdMWQ0LWVjNGEtNGVhNi1hY2RkLWFjOGJiMTZkY2M3OSIsICJzdGFydGVkT24iOiIyMDIzLTA4LTAxVDE5OjU2OjU3LjQ1MTU1MzE2MFoiLCAiZmluaXNoZWRPbiI6IjIwMjMtMDgtMDFUMTk6NTc6MTAuNzM0NDcxWiJ9LCAiYnlwcm9kdWN0cyI6W3t9XX19fQ==...
          payloadType: application/vnd.in-toto+json
          signatures:
          - keyid: projects/verified-builder/locations/global/keyRings/attestor/cryptoKeys/google-hosted-worker/cryptoKeyVersions/1
            sig: MEUCIQCss8UlQL2feFePRJuKTE8VA73f85iqj4OJ9SvVPqTNwAIgYyuyuIrl1PxQC5B109thO24Y6NA4bTa0PJY34EHRSVE=
        kind: BUILD
        name: projects/my-project/occurrences/71787589-c6a6-4d6a-a030-9fd041e40468
        noteName: projects/argo-qa/notes/intoto_slsa_v1_e73ca1d4-ec4a-4ea6-acdd-ac8bb16dcc79
        resourceUri: https://us-central1-docker.pkg.dev/my-project/my-repo/my-image@sha256:7e9b6e7ba2842c91cf49f3e214d04a7a496f8214356f41d81a6e6dcad11f11e3
        updateTime: '2023-08-01T19:57:14.810489Z'
    

En este ejemplo, hay varios aspectos importantes que debes tener en cuenta:

  • Fuente: la compilación se ha activado desde un repositorio de GitHub.

  • Referencia de objeto: los campos digest y fileHash hacen referencia al mismo objeto. El campo digest incluido en el ejemplo de salida está codificado en base 16 (codificación hexadecimal). Si usas la procedencia de la versión 0.1 de SLSA, tu salida usa el campo fileHash codificado en base 64.

  • Firmas: si usas la procedencia de la versión 0.1 de SLSA, tu salida contiene dos firmas en el campo envelope. La primera firma, que tiene el nombre de clave provenanceSigner, usa una firma conforme a DSSE (con el formato de codificación previa a la autenticación [PAE]), que se puede verificar en las políticas de Autorización binaria. Te recomendamos que utilices esta firma en los nuevos usos de esta procedencia. La segunda firma, que tiene el nombre de clave builtByGCB, se proporciona para usos antiguos.

  • Cuentas de servicio: las firmas que se incluyen automáticamente en la procedencia de Cloud Build te ayudan a verificar el servicio de compilación que ha ejecutado una compilación. También puedes configurar Cloud Build para que registre metadatos verificables sobre la cuenta de servicio utilizada para iniciar una compilación. Para obtener más información, consulta Firmar imágenes de contenedor con Cosign.

  • Carga útil: la procedencia de ejemplo que se muestra en esta página se ha acortado para que sea más fácil de leer. La salida real será más larga, ya que la carga útil es una versión codificada en base64 de todos los metadatos de procedencia.

  • Dependencias: las dependencias que especifiques en el archivo de compilación se incluyen en la procedencia, en el campo resolvedDependencies.

Ver la procedencia de los artefactos sin contenedor

Cloud Build genera metadatos de procedencia SLSA para aplicaciones independientes de Go, Java (Maven), Python y Node.js (npm) cuando subes los artefactos de compilación a Artifact Registry. Puedes recuperar los metadatos de procedencia haciendo una llamada directa a la API.

  1. Para generar los metadatos de procedencia de tus artefactos, ejecuta una compilación con Cloud Build. Usa una de las siguientes guías:

    Cuando se complete la compilación, anota el BuildID.

  2. Para recuperar los metadatos de procedencia, ejecuta la siguiente llamada a la API en tu terminal, donde PROJECT_ID es el ID asociado a tu proyecto Google Cloud :

    alias gcurl='curl -H"Authorization: Bearer $(gcloud auth print-access-token)"'
        gcurl 'https://containeranalysis.googleapis.com/v1/projects/PROJECT_ID/occurrences'
    

    Debes usar una llamada a la API para acceder a los metadatos de procedencia de este tipo de artefacto. Los metadatos de procedencia de los artefactos que no son contenedores no se muestran en la Google Cloud consola ni se puede acceder a ellos mediante la CLI de gcloud.

  3. En las ocurrencias de tu proyecto, busca por BuildID para encontrar la información de procedencia asociada a un artefacto de compilación.

Validar la procedencia

En esta sección se explica cómo validar la procedencia de la compilación de imágenes de contenedor.

Validar la procedencia de la compilación te ayuda a:

  • confirmar que los artefactos de compilación se generan a partir de fuentes y compiladores de confianza
  • Asegúrate de que los metadatos de procedencia que describen tu proceso de compilación estén completos y sean auténticos.

Para obtener más información, consulta Protección de compilaciones.

Validar la procedencia con el verificador de SLSA

El verificador de SLSA es una herramienta de línea de comandos de código abierto que permite validar la integridad de las compilaciones según las especificaciones de SLSA.

Si el verificador detecta problemas, devuelve mensajes de error detallados para ayudarte a actualizar el proceso de compilación y mitigar los riesgos.

Para usar el verificador de SLSA, haz lo siguiente:

  1. Instala la versión 2.1 o una posterior del repositorio slsa-verifier.

    go install github.com/slsa-framework/slsa-verifier/v2/cli/slsa-verifier@VERSION
    
  2. En tu CLI, define una variable para el identificador de tu imagen:

    export IMAGE=LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE@sha256:HASH
    

    Donde:

    • LOCATION: ubicación regional o multirregional.
    • PROJECT_ID: Google Cloud ID de proyecto.
    • REPOSITORY: nombre del repositorio.
    • IMAGE: nombre de la imagen.
    • HASH: el valor de hash sha256 de la imagen. Puedes encontrarlo en el resultado de tu compilación.
  3. Autoriza la CLI de gcloud para que el verificador de SLSA pueda acceder a tus datos de procedencia:

    gcloud auth configure-docker LOCATION-docker.pkg.dev
    
  4. Recupera la procedencia de tu imagen y guárdala como JSON:

    gcloud artifacts docker images describe $IMAGE --format json --show-provenance > provenance.json
    
  5. Verifica la procedencia:

    slsa-verifier verify-image "$IMAGE" \
    --provenance-path provenance.json \
    --source-uri SOURCE \
    --builder-id=BUILDER_ID
    

    Donde:

    • SOURCE es el URI del repositorio de origen de tu imagen, por ejemplo, github.com/my-repo/my-application.
    • BUILDER_ID ID único del creador, por ejemplo, https://cloudbuild.googleapis.com/GoogleHostedWorker

    Si quieres imprimir la procedencia validada para usarla en un motor de políticas, usa el comando anterior con la marca --print-provenance.

    La salida es similar a la siguiente: PASSED: Verified SLSA provenance o FAILED: SLSA verification failed: <error details>.

Para obtener más información sobre las marcas opcionales, consulta las opciones.

Validar los metadatos de procedencia con la herramienta de línea de comandos gcloud

Si quieres verificar que los metadatos de procedencia de la compilación no se han manipulado, puedes validar la procedencia siguiendo estos pasos:

  1. Crea un directorio y ve a él.

    mkdir provenance && cd provenance
    
  2. Usa la información del campo keyid para obtener la clave pública.

    gcloud kms keys versions get-public-key 1 --location global --keyring attestor \
      --key builtByGCB --project verified-builder --output-file my-key.pub
    
  3. El payload contiene la representación JSON de la procedencia, codificada en base64url. Decodifica los datos y guárdalos en un archivo.

    gcloud artifacts docker images describe \
    LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE@sha256:HASH --show-provenance \
      --format=json | jq -r '.provenance_summary.provenance[] | select(.build.intotoStatement.predicateType == "https://slsa.dev/provenance/v0.1") | .envelope.payload' | tr '\-_' '+/' | base64 -d > provenance.json
    

    Se almacenan los tipos de procedencia de las versiones 0.1 y 1.0 de SLSA cuando están disponibles. Si quieres filtrar por la versión 1.0, cambia predicateType por https://slsa.dev/provenance/v1. Por ejemplo:

    gcloud artifacts docker images describe \
    LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE@sha256:HASH --show-provenance \
      --format=json | jq -r '.provenance_summary.provenance[] | select(.build.intotoStatement.predicateType == "https://slsa.dev/provenance/v1") | .envelope.payload' | tr '\-_' '+/' | base64 -d > provenance.json
    
  4. El sobre también contiene la firma sobre la procedencia. Decodifica los datos y guárdalos en un archivo.

      gcloud artifacts docker images describe LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE@sha256:HASH --show-provenance \
      --format=json | jq -r '.provenance_summary.provenance[] | select(.build.intotoStatement.predicateType == "https://slsa.dev/provenance/v0.1") | .envelope.signatures[0].sig' | tr '\-_' '+/' | base64 -d > signature.bin
    

    Si quieres filtrar por la versión 1.0, cambia predicateType por https://slsa.dev/provenance/v1. Por ejemplo:

    gcloud artifacts docker images describe LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE@sha256:HASH --show-provenance \
    --format=json | jq -r '.provenance_summary.provenance[] | select(.build.intotoStatement.predicateType == "https://slsa.dev/provenance/v1") | .envelope.signatures[0].sig' | tr '\-_' '+/' | base64 -d > signature.bin
    
  5. El comando anterior hace referencia a la primera firma de procedencia (.provenance_summary.provenance[0].envelope.signatures[0]), que está firmada por la clave provenanceSigner. La carga útil se firma en el sobre con formato PAE. Para verificarlo, ejecuta este comando para transformar la procedencia al formato PAE esperado de "DSSEv1" + SP + LEN(type) + SP + type + SP + LEN(body) + SP + body.

    echo -n "DSSEv1 28 application/vnd.in-toto+json $(cat provenance.json | wc -c) $(cat provenance.json)" > provenance.json
    
  6. Valida la firma.

    openssl dgst -sha256 -verify my-key.pub -signature signature.bin provenance.json
    

    Si la validación se realiza correctamente, la salida es Verified OK.

Siguientes pasos