Criar atestados

Nesta página, descrevemos as etapas para criar um atestado de autorização binária.

Use atestados para autorizar que imagens de contêiner específicas sejam implantadas em plataformas, como o Google Kubernetes Engine (GKE) e o Cloud Run. Para usar atestados, é necessário exigir atestados na regra apropriada da sua política.

Um único atestado pode autorizar imagens idênticas armazenadas em vários locais ou registros diferentes, como o Artifact Registry, o Container Registry ou um registro de contêiner externo.

No momento da implantação, a autorização binária usa atestadores para verificar atestados.

Para configurar a autorização binária no Cloud Run, no GKE, nos clusters do GKE e no Anthos Service Mesh, consulte Configuração por plataforma e selecione sua plataforma.

Usuários do GKE: para ver um tutorial completo que descreve a aplicação baseada em atestado usando a autorização binária e o Google Kubernetes Engine (GKE), consulte Introdução à ferramenta de linha de comando ou Introdução ao Console do Google Cloud.

Antes de começar

A Visão geral dos atestados apresenta etapas a serem concluídas antes de criar um atestado.

Configure o ambiente

  1. Especifique os IDs do projeto:

    ATTESTOR_PROJECT_ID=ATTESTOR_PROJECT_ID
    ATTESTATION_PROJECT_ID=ATTESTATION_PROJECT_ID
    

    Substitua:

    • ATTESTOR_PROJECT_ID: o nome do projeto em que você está armazenando seus atestadores;
    • ATTESTATION_PROJECT_ID: o nome do projeto em que você está armazenando os atestados.

    Se você quiser que o atestado seja criado no mesmo projeto que os atestadores, use o mesmo ID do projeto para as duas variáveis. Para ver um tutorial completo que demonstra a separação de deveres com projetos diferentes, consulte Configuração de vários projetos.

  2. Especifique o nome do atestador e as informações da imagem:

    ATTESTOR_NAME=ATTESTOR_NAME
    IMAGE_PATH=IMAGE_PATH
    IMAGE_DIGEST=IMAGE_DIGEST
    IMAGE_TO_ATTEST="${IMAGE_PATH}@${IMAGE_DIGEST}"
    

    Substitua:

    • ATTESTOR_NAME: o nome do atestador, por exemplo, build-secure ou prod-qa;
    • IMAGE_PATH: um URI que representa um caminho de imagem. O URI precisa ter um nome de domínio e uma imagem, mas não é necessário se referir a uma imagem real. As imagens não são acessadas durante a criação do atestado. Veja a seguir exemplos de caminhos de imagem:

      • us-docker.pkg.dev/google-samples/containers/gke/hello-app
      • gcr.io/example-project/quickstart-image
      • example.com/hello-app
    • IMAGE_DIGEST: o resumo do manifesto da imagem. Por exemplo, sha256:37e5287945774f27b418ce567cd77f4bbc9ef44a1bcd1a2312369f31f9cce567 é o resumo da imagem associado ao caminho de imagem us-docker.pkg.dev/google-samples/containers/gke/hello-app de exemplo. Para saber como conseguir o resumo de uma imagem no Artifact Registry, consulte Como gerenciar imagens. Para uma imagem no Container Registry, consulte Como listar versões de um imagem.

Conceder papéis de gerenciamento de identidade e acesso

Para criar atestados, é necessário conceder os seguintes papéis de gerenciamento de identidade e acesso (IAM, na sigla em inglês) à identidade que cria o atestador, da seguinte maneira:

  • roles/containeranalysis.notes.attacher no recurso de nota associado ao atestador.
  • roles/containeranalysis.occurrences.editor no recurso de projeto de atestado.

Você criará um atestado com base em um atestador. O atestador está associado a uma nota do Artifact Analysis. Por sua vez, criar um atestado cria uma ocorrência do Artifact Analysis e a anexa à nota.

Saiba mais sobre Como conceder acesso.

Para saber como criar um atestado em um pipeline do Cloud Build, consulte Como criar atestados usando o Kritis Signer.

Criar um atestado

Criar um atestado usando uma chave armazenada localmente

Para criar um atestado assinado com uma chave local, faça o seguinte:

  1. Crie um arquivo de payload de assinatura:

    gcloud

    Para criar o arquivo de payload de assinatura, digite este comando:

    gcloud container binauthz create-signature-payload \
        --artifact-url="${IMAGE_TO_ATTEST}" > /tmp/generated_payload.json
    

    O arquivo de payload no formato JSON é semelhante a:

    {
      "critical": {
        "identity": {
          "docker-reference": "us-docker.pkg.dev/google-samples/containers/gke/hello-app"
        },
        "image": {
          "docker-manifest-digest": "sha256:37e5287945774f27b418ce567cd77f4bbc9ef44a1bcd1a2312369f31f9cce567"
        },
        "type": "Google cloud binauthz container signature"
      }
    }
    

    API REST

    Crie um arquivo de payload chamado /tmp/generated_payload.json usando as variáveis de ambiente definidas anteriormente neste documento:

    cat > /tmp/generated_payload.json << EOM
    {
      "critical": {
        "identity": {
          "docker-reference": "${IMAGE_PATH}"
        },
        "image": {
          "docker-manifest-digest": "${IMAGE_DIGEST}"
        },
        "type": "Google cloud binauthz container signature"
      }
    }
    EOM
    
  2. Assine o payload com a chave privada para gerar um arquivo de assinatura.

    Este guia usa o algoritmo recomendado de algoritmo de assinatura digital de curva elíptica (ECDSA, na sigla em inglês) para assinatura. Também é possível usar o algoritmo RSA. Para mais informações sobre algoritmos de assinatura, consulte Finalidades de chave e algoritmos. Este guia também usa o formato de assinatura de Infraestrutura de chave pública (X.509) (PKIX, na sigla em inglês). Também é possível usar o PGP.

    PRIVATE_KEY_FILE=PRIVATE_KEY_FILE
    openssl dgst -sha256 -sign ${PRIVATE_KEY_FILE} /tmp/generated_payload.json > /tmp/ec_signature
    

    Substitua PRIVATE_KEY_FILE pelo caminho para a chave privada que você gerou quando criou o atestador.

  3. Encontre o ID da chave pública.

    É possível recuperar o código da chave pública no atestador inserindo o seguinte comando:

    PUBLIC_KEY_ID=$(gcloud container binauthz attestors describe ${ATTESTOR_NAME} \
      --format='value(userOwnedGrafeasNote.publicKeys[0].id)')
    
  4. Crie o atestado:

    gcloud

    Para criar e validar o atestado, insira o seguinte:

    gcloud container binauthz attestations create \
        --project="${ATTESTATION_PROJECT_ID}" \
        --artifact-url="${IMAGE_TO_ATTEST}" \
        --attestor="projects/${ATTESTOR_PROJECT_ID}/attestors/${ATTESTOR_NAME}" \
        --signature-file=/tmp/ec_signature \
        --public-key-id="${PUBLIC_KEY_ID}" \
        --validate
    

    A sinalização validate verifica se o atestado pode ser verificado pelo atestador que você configurou na política.

    Observação: o código da chave pode ser qualquer string.

    API REST

    Para criar o atestado:

    1. Recupere o atestador associado ao atestado e extraia o ID da chave pública armazenada:

      curl \
          -H "Authorization: Bearer $(gcloud auth print-access-token)"  \
          -H "x-goog-user-project: ${ATTESTOR_PROJECT_ID}" \
          "https://binaryauthorization.googleapis.com/v1/projects/${ATTESTOR_PROJECT_ID}/attestors/"
      

      A autorização binária retorna um objeto JSON semelhante ao seguinte:

      {
        "name": "projects/example-project/attestors/test-attestor",
        "userOwnedGrafeasNote": {
          "noteReference": "projects/example-project/notes/test-attestor",
          "publicKeys": [
            {
              "id": "ni:///sha-256;EwVxs8fNUAHq9FI2AMfh8WNIXVBuuTMeGtPH72U-I70",
              "pkixPublicKey": {
                "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEXnpuYEfvLl1kj4fjxViFRwY1a+zC\n5qzlf9LJIK+rnjq42tiKGyyXMbnZKJiYPPdMDGyltnkrABnztg2jJ48aYQ==\n-----END PUBLIC KEY-----\n",
                "signatureAlgorithm": "ECDSA_P256_SHA256"
              }
            }
          ],
          "delegationServiceAccountEmail": "service-363451293945@gcp-sa-binaryauthorization.iam.gserviceaccount.com"
        },
        "updateTime": "2019-06-26T16:58:33.977438Z"
      }
      

      A chave pública pode ser encontrada no campo id.

    2. Crie um arquivo JSON em /tmp/attestation.json que descreva o atestado:

      cat > /tmp/attestation.json << EOM
      {
        "resourceUri": "${IMAGE_TO_ATTEST}",
        "note_name": "${NOTE_URI}",
        "attestation": {
           "serialized_payload": "$(base64 --wrap=0 /tmp/generated_payload.json)",
           "signatures": [
              {
               "public_key_id": "${PUBLIC_KEY_ID}",
               "signature": "$(base64 --wrap=0 /tmp/ec_signature)"
              }
           ]
        }
       }
      EOM
      
    3. Crie o atestado:

      curl -X POST \
          -H "Content-Type: application/json" \
          -H "X-Goog-User-Project: ${ATTESTATION_PROJECT_ID}" \
          -H "Authorization: Bearer $(gcloud auth print-access-token)" \
          --data-binary @/tmp/attestation.json \
          "https://containeranalysis.googleapis.com/v1/projects/${ATTESTATION_PROJECT_ID}/occurrences/"
      

Criar um atestado usando o Cloud KMS

Para criar um atestado usando o Cloud Key Management Service:

  1. Crie variáveis de ambiente:

    KMS_KEY_PROJECT_ID=KMS_KEY_PROJECT_ID
    KMS_KEY_LOCATION=KMS_KEY_LOCATION
    KMS_KEYRING_NAME=KMS_KEYRING_NAME
    KMS_KEY_NAME=KMS_KEY_NAME
    KMS_KEY_VERSION=KMS_KEY_VERSION
    

    Substitua:

    • KMS_KEY_PROJECT_ID: o ID do projeto em que as chaves do Cloud Key Management Service estão armazenadas;
    • KMS_KEY_LOCATION: o local da chave (global é o padrão);
    • KMS_KEYRING_NAME: o nome do keyring;
    • KMS_KEY_NAME: o nome da chave;
    • KMS_KEY_VERSION: a versão da chave.
  2. Assine e crie o atestado:

    gcloud

    Digite este comando:

    gcloud beta container binauthz attestations sign-and-create \
        --project="${ATTESTATION_PROJECT_ID}" \
        --artifact-url="${IMAGE_TO_ATTEST}" \
        --attestor="${ATTESTOR_NAME}" \
        --attestor-project="${ATTESTOR_PROJECT_ID}" \
        --keyversion-project="${KMS_KEY_PROJECT_ID}" \
        --keyversion-location="${KMS_KEY_LOCATION}" \
        --keyversion-keyring="${KMS_KEYRING_NAME}" \
        --keyversion-key="${KMS_KEY_NAME}" \
        --keyversion="${KMS_KEY_VERSION}"
    

    API REST

    1. Crie um arquivo de payload chamado /tmp/generated_payload.json usando as variáveis de ambiente definidas acima:

      cat > /tmp/generated_payload.json << EOM
      {
        "critical": {
          "identity": {
            "docker-reference": "${IMAGE_PATH}"
          },
          "image": {
            "docker-manifest-digest": "${IMAGE_DIGEST}"
          },
          "type": "Google cloud binauthz container signature"
        }
      }
      EOM
      
    2. Assine o arquivo de payload:

      curl \
        --header "Content-Type: application/json" \
        --header "Authorization: Bearer $(gcloud auth print-access-token)" \
        --header "x-goog-user-project: ${ATTESTOR_PROJECT_ID}" \
        --data '{"digest":  {"DIGEST_ALGORITHM": "'$(openssl dgst -sha256 -binary /tmp/generated_payload.json | openssl base64)'" }}' \
      https://cloudkms.googleapis.com/v1/projects/${KMS_KEY_PROJECT_ID}/locations/${KMS_KEY_LOCATION}/keyRings/${KMS_KEYRING_NAME}/cryptoKeys/${KMS_KEY_NAME}/cryptoKeyVersions/${KMS_KEY_VERSION}:asymmetricSign?alt=json
      

      Substitua DIGEST_ALGORITHM pelo algoritmo para resumir a entrada. Os exemplos neste guia usam um resumo sha256. É possível usar sha256, sha384 ou sha512.

      Neste exemplo, a saída é semelhante a esta:

      {
        "signature": "<var>SIGNATURE</var>": "996305066",
        "name": "projects/<var>KMS_KEY_PROJECT_ID</var>/locations/<var>KMS_KEY_LOCATION</var>/keyRings/<var>KMS_KEYRING_NAME</var>/cryptoKeys/<var>KMS_KEY_NAME</var>/cryptoKeyVersions/<var>KMS_KEY_VERSION</var>"
      }
      

      Nesta saída, SIGNATURE é a assinatura codificada em base64 do arquivo de payload.

    3. Armazene a assinatura em uma variável de ambiente:

      PAYLOAD_SIGNATURE=PAYLOAD_SIGNATURE
      
    4. Recupere o atestador em nome de quem você está assinando o atestado e extraia o ID da chave pública armazenada e o ID da nota:

      curl \
          -H "Authorization: Bearer $(gcloud auth print-access-token)"  \
          -H "x-goog-user-project: ${ATTESTOR_PROJECT_ID}" \
          "https://binaryauthorization.googleapis.com/v1/projects/${ATTESTOR_PROJECT_ID}/attestors/"
      

      A autorização binária retorna um objeto JSON semelhante ao seguinte:

      {
        "name": "projects/example-project/attestors/test-attestor",
        "userOwnedGrafeasNote": {
          "noteReference": "projects/example-project/notes/test-attestor",
          "publicKeys": [
            {
              "id": "ni:///sha-256;EwVxs8fNUAHq9FI2AMfh8WNIXVBuuTMeGtPH72U-I70",
              "pkixPublicKey": {
                "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEXnpuYEfvLl1kj4fjxViFRwY1a+zC\n5qzlf9LJIK+rnjq42tiKGyyXMbnZKJiYPPdMDGyltnkrABnztg2jJ48aYQ==\n-----END PUBLIC KEY-----\n",
                "signatureAlgorithm": "ECDSA_P256_SHA256"
              }
            }
          ],
          "delegationServiceAccountEmail": "service-363451293945@gcp-sa-binaryauthorization.iam.gserviceaccount.com"
        },
        "updateTime": "2019-06-26T16:58:33.977438Z"
      }
      

      É possível encontrar o ID da chave pública no campo id e o ID da nota no campo noteReference.

    5. Armazene o código da chave pública em uma variável de ambiente:

      PUBLIC_KEY_ID="PUBLIC_KEY_ID"
      NOTE_URI="NOTE_URI"
      

      Substitua:

      • PUBLIC_KEY_ID: o ID da chave pública do atestador.
      • NOTE_URI: o URI da nota do Artifact Analysis associado ao atestador.
    6. Crie um arquivo JSON em /tmp/attestation.json que descreva o atestado:

      cat > /tmp/attestation.json << EOM
      {
        "resourceUri": "${IMAGE_TO_ATTEST}",
        "note_name": "${NOTE_URI}",
        "attestation": {
           "serialized_payload": "$(base64 --wrap=0 /tmp/generated_payload.json)",
           "signatures": [
               {
                   "public_key_id": "${PUBLIC_KEY_ID}",
                   "signature": "${PAYLOAD_SIGNATURE}"
               }
           ]
        }
      }
      EOM
      
    7. Crie o atestado:

      curl -X POST \
          -H "Content-Type: application/json" \
          -H "X-Goog-User-Project: ${ATTESTATION_PROJECT_ID}" \
          -H "Authorization: Bearer $(gcloud auth print-access-token)" \
          --data-binary @/tmp/attestation.json \
      "https://containeranalysis.googleapis.com/v1/projects/${ATTESTATION_PROJECT_ID}/occurrences/"
      

Você criou o atestado.

Verificar se o atestado foi criado

Para verificar se o atestado foi criado, liste os atestados associados à imagem.

gcloud

Para recuperar uma lista de atestados, digite o seguinte comando:

gcloud container binauthz attestations list\
    --project="${ATTESTATION_PROJECT_ID}"\
    --attestor="projects/${ATTESTOR_PROJECT_ID}/attestors/${ATTESTOR_NAME}"\
    --artifact-url="${IMAGE_TO_ATTEST}"

API REST

Para solicitar uma lista de atestados, digite o seguinte comando:

curl -X GET \
    -H "Content-Type: application/json" \
    -H "X-Goog-User-Project: ${ATTESTOR_PROJECT_ID}" \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
https://containeranalysis.googleapis.com/v1/projects/${ATTESTOR_PROJECT_ID}/notes/${NOTE_ID}/occurrences?filter=resourceUrl%3D%22https%3A%2F%2F$(jq -rn --arg x ${IMAGE_TO_ATTEST} '$x|@uri')%22

Se houver muitos atestados, a resposta poderá conter um valor nextPageToken. Nesse caso, é possível recuperar a próxima página de resultados repetindo a solicitação, adicionando um parâmetro de consulta pageToken, da seguinte maneira:

NEXT_PAGE_TOKEN=NEXT_PAGE_TOKEN
curl -X GET \
    -H "Content-Type: application/json" \
    -H "X-Goog-User-Project: ${ATTESTOR_PROJECT_ID}" \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
https://containeranalysis.googleapis.com/v1/projects/${ATTESTOR_PROJECT_ID}/notes/${NOTE_ID}/occurrences?filter=resourceUrl%3D%22https%3A%2F%2F$(jq -rn --arg x ${IMAGE_TO_ATTEST} '$x|@uri')%22&pageToken=${NEXT_PAGE_TOKEN}

Substitua NEXT_PAGE_TOKEN pelo valor nextPageToken na resposta da solicitação anterior.

Quando nextPageToken está vazio, isso significa que não há mais resultados.

Excluir o atestado

Antes de excluir o atestado, faça o seguinte:

  1. Entenda as consequências de excluí-los. A exclusão de um atestado acaba bloqueando a implantação de imagens de contêiner associadas ao atestado.

  2. Interrompa todos os contêineres em execução associados aos atestados que você pretende excluir.

  3. Exclua todas as cópias dos atestados onde quer que estejam, por exemplo, atestados dos repositórios do Artifact Registry e do Artifact Analysis.

  4. Verifique se as imagens afetadas estão realmente bloqueadas para a implantação tentando reimplantá-las.

Para excluir um atestado, execute os seguintes comandos:

  1. Liste atestados:

    gcloud container binauthz attestations list \
      --attestor-project=${ATTESTOR_PROJECT_ID} \
      --attestor=${ATTESTOR_NAME}
    

    O atestado contém um ID de ocorrência. A resposta será semelhante a:

    projects/ATTESTOR_PROJECT_ID/occurrences/OCCURRENCE_ID
    
  2. Salve o ID da ocorrência.

    Salve o ID da ocorrência do atestado que você quer excluir.

    OCCURRENCE_ID=OCCURRENCE_ID
    
  3. Exclua o atestado:

    curl -H "Authorization: Bearer $(gcloud auth print-access-token)" -X DELETE \
      https://containeranalysis.googleapis.com/v1beta1/projects/${ATTESTATION_PROJECT_ID}/occurrences/${OCCURRENCE_ID}
    

    Para verificar se os atestados foram excluídos, liste os atestados novamente.

A seguir