Cómo generar y validar la procedencia de las compilaciones

En esta página, se proporcionan instrucciones para generar la procedencia de la compilación, ver el resultado y validarlo.

La procedencia de la compilación es una colección 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 las fuentes 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 usas sean precisos y confiables, y que se creen mediante fuentes y compiladores confiables.

Cloud Build admite la generación de procedencia de la compilación que cumple con la garantía de nivel 3 de los Niveles de cadena de suministro para artefactos de software (SLSA) según las especificaciones de las versiones 0.1 y 1.0 de SLSA.

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

Limitaciones

  • Cloud Build solo genera la procedencia de la compilación para los artefactos almacenados en Artifact Registry.
  • Para obtener la procedencia de SLSA v1.0 y v0.1, debes compilar con activadores. Si inicias una compilación de forma manual con la CLI de gcloud, Cloud Build solo proporciona la procedencia de SLSA v0.1.

Antes de comenzar

  1. Habilita las API de Cloud Build, Container Analysis, and Artifact Registry.

    Habilita las API

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

  3. Ten tu código fuente a mano.

  4. Tener un repositorio en Artifact Registry

Genera la procedencia de la compilación

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

  1. En el archivo de configuración de compilación, agrega el campo images para configurar Cloud Build de forma que almacene las imágenes compiladas en Artifact Registry después de que se complete la compilación.

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

    En el siguiente fragmento, se muestra una configuración de compilación para compilar 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']
    

    Aquí:

    • LOCATION: Es la ubicación regional o multirregional de tu repositorio.
    • PROJECT_ID: tu ID del proyecto de Google Cloud.
    • REPOSITORY: Es el nombre de tu repositorio de Artifact Registry.
    • IMAGE: Es el nombre de tu imagen de 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"
      ]
      }
    

    Aquí:

    • LOCATION: Es la ubicación regional o multirregional de tu repositorio.
    • PROJECT_ID: tu ID del proyecto de Google Cloud.
    • REPOSITORY: Es el nombre de tu repositorio de Artifact Registry.
    • IMAGE: Es el nombre de tu imagen de contenedor.
  2. En la sección options de tu configuración de compilación, agrega la opción requestedVerifyOption y establécela en el valor VERIFIED.

    Esta configuración 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 exitosas si se genera la procedencia.

    YAML

    options:
      requestedVerifyOption: VERIFIED
    

    JSON

    {
        "options": {
            "requestedVerifyOption": "VERIFIED"
        }
    }
    
  3. Comienza tu compilación.

Ver procedencia de la compilación

En esta sección, se explica cómo ver los metadatos de procedencia de la compilación que crea Cloud Build. Puedes recuperar esta información para realizar auditorías.

Puedes acceder a los metadatos de procedencia compilados para los contenedores mediante el panel lateral Estadísticas de seguridad en la consola de Google Cloud o con gcloud CLI.

Console

El panel lateral Estadísticas de seguridad proporciona una descripción general de alto nivel de la información de seguridad para 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 consola de Google Cloud:

    Abrir la página Historial de compilación

  2. Selecciona tu proyecto y haz clic en Open.

  3. En el menú desplegable Región, selecciona la región en la que ejecutaste tu compilación.

  4. En la tabla con las compilaciones, ubica la fila con la compilación para la que deseas ver las estadísticas de seguridad.

  5. En la columna Estadísticas de seguridad, haz clic en Ver.

    Se mostrará el panel Estadísticas de seguridad del artefacto seleccionado.

    La tarjeta Compilación muestra los detalles de origen y un vínculo. Para ver el fragmento de procedencia, haz clic en el ícono de vínculo.

Si deseas obtener más información sobre el panel lateral y cómo puedes usar Cloud Build para proteger la cadena de suministro de software, consulta Consulta estadísticas de seguridad de compilación.

gcloud CLI

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

Reemplaza lo siguiente:

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

Ejemplo de resultado

La procedencia de la compilación se parece 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'
    

A continuación, se indican algunos aspectos importantes que debes tener en cuenta en este ejemplo:

  • Fuente: La compilación se activó desde un repositorio de GitHub.

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

  • Firmas: Si usas la fuente de SLSA versión 0.1, el resultado contiene dos firmas en el campo envelope. La primera firma, que tiene el nombre de clave provenanceSigner, usa una firma que cumple con DSSE (con formato con codificación previa a la autenticación (PAE)), que se puede verificar en las políticas de autorización binaria. Te recomendamos que uses esta firma en los usos nuevos de esta procedencia. La segunda firma, que tiene el nombre de clave builtByGCB, se proporciona para el uso heredado.

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

  • Carga útil: La procedencia de ejemplo que se muestra en esta página se abrevia para facilitar la lectura. El resultado real será más largo, ya que la carga útil es una versión codificada en Base64 de todos los metadatos de origen.

Visualiza la procedencia de los artefactos que no son contenedores

Cloud Build genera metadatos de procedencia SLSA para aplicaciones independientes de Java (Maven), Python y Node.js (npm) cuando subes los artefactos de compilación a Artifact Registry.

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

    Cuando se complete la compilación, toma nota del BuildID.

  2. Ejecuta la siguiente llamada a la API en tu terminal, en la que PROJECT_ID es el ID asociado con el proyecto de Google Cloud:

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

    En los casos de tu proyecto, busca por BuildID para encontrar la información de procedencia asociada con cada artefacto de compilación.

Valida la procedencia

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

La validación de la procedencia de la compilación te ayuda a hacer lo siguiente:

  • 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 el proceso de compilación estén completos y sean auténticos

Para obtener más información, consulta Cómo proteger compilaciones.

Valida la procedencia con el verificador SLSA

El verificador de SLSA es una herramienta de CLI de código abierto para validar la integridad de la compilación según las especificaciones de SLSA.

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

Para usar el verificador de SLSA, sigue estos pasos:

  1. Instala la versión 2.1 o una posterior desde el repositorio de slsa-verifier:

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

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

    Reemplaza los valores de marcador de posición en el comando por los siguientes:

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

    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
    

    Aquí:

    • SOURCE es el URI del repositorio de código fuente de tu imagen, por ejemplo, github.com/my-repo/my-application.
    • BUILDER_ID es el ID único para el compilador, por ejemplo, https://cloudbuild.googleapis.com/GoogleHostedWorker.

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

    El resultado es similar al siguiente: PASSED: Verified SLSA provenance o FAILED: SLSA verification failed: <error details>.

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

Valida los metadatos de origen con gcloud CLI

Si deseas verificar que no se hayan alterado los metadatos de procedencia de la compilación, puedes validarlos mediante los siguientes pasos:

  1. Crea un directorio nuevo y ve a ese directorio.

    mkdir provenance && cd provenance
    
  2. Con la información del campo keyid, obtén 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. payload contiene la representación JSON de la procedencia, codificada en base64url. Decodifica los datos y almacénalos 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
    

    Los tipos de procedencia de las versiones 0.1 y 1.0 de SLSA se almacenan cuando están disponibles. Si deseas filtrar según la versión 1.0, cambia predicateType para usar 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 almacénalos en un archivo.

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

    Si deseas filtrar según la versión 1.0, cambia predicateType para usar 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 se firma con la clave provenanceSigner. La carga útil está firmada en un sobre con formato PPA. Para verificarlo, ejecuta este comando y transforma la procedencia en el 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
    

    Después de una validación correcta, el resultado es Verified OK.

¿Qué sigue?