This page explains how to create an attestor in Binary Authorization by using the Google Cloud CLI. As an alternative, you can also perform these steps by using the Google Cloud console or the REST API. This task is part of setting up Binary Authorization.
An attestor is a Google Cloud resource that Binary Authorization uses to verify an attestation. To learn more about attestations, see the Binary Authorization overview.
Creating an attestor requires you to do the following:
- Create a note in Container Analysis to store trusted metadata used in the attestation process.
- Set up a PKIX key pair that can be used to verify the identity of the attestor. (Asymmetric key pairs generated by Cloud Key Management Service (Cloud KMS) are in PKIX-compatible format.)
- Create the attestor itself in Binary Authorization, and associate the note and public key you created.
In a single-project setup, you create your attestor in the same Google Cloud project where you configure your Binary Authorization policy. In a multi-project setup, you most likely have a deployer project where your policy is configured and a separate attestor project where your attestors are stored.
Set up the environment
Set up environment variables to store your project names and numbers:
DEPLOYER_PROJECT_ID=DEPLOYER_PROJECT_ID= DEPLOYER_PROJECT_NUMBER="$( gcloud projects describe "${DEPLOYER_PROJECT_ID}" \ --format="value(projectNumber)" )" ATTESTOR_PROJECT_ID=ATTESTOR_PROJECT_ID ATTESTOR_PROJECT_NUMBER="$( gcloud projects describe "${ATTESTOR_PROJECT_ID}" \ --format="value(projectNumber)" )"
If your attestor and deployer projects are the same project, use the same project ID for both variables. For an end-to-end tutorial that describes separation of duties using multiple projects, see Multi project setup.
You must also get the service account names for the projects:
DEPLOYER_SERVICE_ACCOUNT="service-${DEPLOYER_PROJECT_NUMBER}@gcp-sa-binaryauthorization.iam.gserviceaccount.com" ATTESTOR_SERVICE_ACCOUNT="service-${ATTESTOR_PROJECT_NUMBER}@gcp-sa-binaryauthorization.iam.gserviceaccount.com"
Create a Container Analysis note
Binary Authorization uses Container Analysis to store trusted metadata used in the authorization process. For each attestor you create, you must create one Container Analysis note. Each attestation is stored as an occurrence of this note.
To create a Container Analysis note, follow these steps:
Set up environment variables to store the note ID and a human-readable description:
NOTE_ID=NOTE_ID NOTE_URI="projects/${ATTESTOR_PROJECT_ID}/notes/${NOTE_ID}" DESCRIPTION=DESCRIPTION
Replace the following:
- NOTE_ID is the internal name of the note in alphanumeric
characters with no spaces (for example,
test-attestor-note
) - NOTE_URI is the fully-qualified path to the note resource
- DESCRIPTION is a human-readable display name for the note
(for example,
Test Attestor Note
)
- NOTE_ID is the internal name of the note in alphanumeric
characters with no spaces (for example,
In a text editor, create a JSON file in
/tmp/note_payload.json
that describes the Container Analysis note:cat > /tmp/note_payload.json << EOM { "name": "${NOTE_URI}", "attestation": { "hint": { "human_readable_name": "${DESCRIPTION}" } } } EOM
Create the note by sending an HTTP request to the Container Analysis REST API:
curl -X POST \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $(gcloud auth print-access-token)" \ -H "x-goog-user-project: ${ATTESTOR_PROJECT_ID}" \ --data-binary @/tmp/note_payload.json \ "https://containeranalysis.googleapis.com/v1/projects/${ATTESTOR_PROJECT_ID}/notes/?noteId=${NOTE_ID}"
To verify that the note was created successfully:
curl \ -H "Authorization: Bearer $(gcloud auth print-access-token)" \ -H "x-goog-user-project: ${ATTESTOR_PROJECT_ID}" \ "https://containeranalysis.googleapis.com/v1/projects/${ATTESTOR_PROJECT_ID}/notes/"
Set Identity and Access Management permissions on the note
You must grant an Identity and Access Management (IAM) role to
the attestor project service account on the Container Analysis note
resource. You do this by adding the attestor project service account to the containeranalysis.notes.occurrences.viewer
role in the note's
IAM policy.
To add the role:
Generate a JSON file that contains the information needed to set the IAM role on your note:
cat > /tmp/iam_request.json << EOM { "resource": "${NOTE_URI}", "policy": { "bindings": [ { "role": "roles/containeranalysis.notes.occurrences.viewer", "members": [ "serviceAccount:${ATTESTOR_SERVICE_ACCOUNT}" ] } ] } } EOM
Add the service account and requested access roles to the IAM policy for the note you created:
curl -X POST \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $(gcloud auth print-access-token)" \ -H "x-goog-user-project: ${ATTESTOR_PROJECT_ID}" \ --data-binary @/tmp/iam_request.json \ "https://containeranalysis.googleapis.com/v1/projects/${ATTESTOR_PROJECT_ID}/notes/${NOTE_ID}:setIamPolicy"
Multi-project usage
If you store the attestor in one project and you deploy in a separate project,
you must grant the roles/binaryauthorization.attestorsVerifier
role to the
service account associated with the deployer project on the attestor.
Set up cryptographic keys
Binary Authorization allows you to use PKIX keys to securely verify the identity of signer that created an attestation. This ensures that only verified parties can authorize a container image. As an alternative to PKIX, you can also use PGP keys.
Generate a key pair
In this guide, the recommended Elliptic Curve Digital Signing Algorithm (ECDSA) is used to generate a PKIX key pair. You can also use RSA or PGP keys for signing. See Key purposes and algorithms for more information on signing algorithms.
A PKIX key pair consists of a private key, which the signer uses to digitally sign attestations, and a public key, which you add to the attestor. At deploy time, Binary Authorization uses this public key to verify the attestation signed by the private key.
To generate a new local asymmetric PKIX key pair and store it in a file:
Generate the private key:
PRIVATE_KEY_FILE is the name of the file containing the private key used for signing the attestation payload.
PRIVATE_KEY_FILE="/tmp/ec_private.pem" openssl ecparam -genkey -name prime256v1 -noout -out ${PRIVATE_KEY_FILE}
Extract the public key from the private key and store it in a file:
PUBLIC_KEY_FILE is the name of the file containing the public key that will be stored in the attestor.
PUBLIC_KEY_FILE="/tmp/ec_public.pem" openssl ec -in ${PRIVATE_KEY_FILE} -pubout -out ${PUBLIC_KEY_FILE}
The asymmetric key pairs generated and stored in Cloud KMS are compliant with the PKIX format. To create a Cloud KMS key for use with Binary Authorization, see Creating Asymmetric Keys. Make sure that you choose Asymmetric Sign as the key purpose when you create the key.
Create the attestor
The next step is to create the attestor itself in Binary Authorization with the associated Container Analysis note. You must also add the cryptographic public key.
To create the attestor, follow these steps:
Set up an environment variable to store the name of the attestor as defined in Binary Authorization:
ATTESTOR_NAME=ATTESTOR_NAME
where ATTESTOR_NAME is the name of the attestor you want to create (for example,
build-secure
orprod-qa
).Create the attestor resource in Binary Authorization:
gcloud --project="${ATTESTOR_PROJECT_ID}" \ container binauthz attestors create "${ATTESTOR_NAME}" \ --attestation-authority-note="${NOTE_ID}" \ --attestation-authority-note-project="${ATTESTOR_PROJECT_ID}"
Add an IAM role binding for the deployer project to the attestor. This is used by Binary Authorization when it evaluates a policy to determine whether the project has permissions to access any associated attestations.
gcloud container binauthz attestors add-iam-policy-binding \ "projects/${ATTESTOR_PROJECT_ID}/attestors/${ATTESTOR_NAME}" \ --member="serviceAccount:${DEPLOYER_SERVICE_ACCOUNT}" \ --role=roles/binaryauthorization.attestorsVerifier
Add the public key to the attestor:
PKIX (local key)
Add a locally stored PKIX public key to an attestor:
Now, add the public key you exported to the attestor so that it can be used by Binary Authorization for identity verification:
gcloud --project="${ATTESTOR_PROJECT_ID}" \ container binauthz attestors public-keys add \ --attestor="${ATTESTOR_NAME}" \ --pkix-public-key-file=${PUBLIC_KEY_FILE} \ --pkix-public-key-algorithm=ecdsa-p256-sha256
Note: If you add a public key to an attestor and don't specify a key ID (which can be any string), it will automatically be given one in the RFC 6920 format:
ni:///sha-256;...
, where...
is an encoded hash of the public key. This value is returned in theid
field of the command output. The returned ID can be saved in PUBLIC_KEY_ID and used to create an attestation.Save the public key ID.
When creating an attestation, you will need the public key ID. To save the public key ID, you can save it from the output of the
binauthz attestors public-keys add
command, above.Alternatively, you can view your attestor's public key ID at any time using the command:
gcloud container binauthz attestors describe ${ATTESTOR}
.To save your public key ID in an environment variable, enter this command:
PUBLIC_KEY_ID=$(gcloud container binauthz attestors describe ${ATTESTOR_NAME} \ --format='value(userOwnedGrafeasNote.publicKeys[0].id)')
PKIX (Cloud KMS)
Set up environment variables to store information about the key pair as managed by Cloud KMS:
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 KMS_KEY_PURPOSE=asymmetric-signing KMS_KEY_ALGORITHM=KMS_KEY_ALGORITHM KMS_PROTECTION_LEVEL=KMS_PROTECTION_LEVEL
Replace the following:
- KMS_KEY_PROJECT_ID: the ID of the project where the keys are stored.
- KMS_KEY_LOCATION: the location of the key.
- KMS_KEYRING_NAME: the name of the key ring.
- KMS_KEY_NAME: the name of the key.
- KMS_KEY_VERSION: the key version.
- KMS_KEY_ALGORITHM: the algorithm. We recommend
ec-sign-p256-sha256
. - KMS_PROTECTION_LEVEL: the protection level, for
example
software
.
Create a Cloud KMS key ring:
gcloud --project ${KMS_KEY_PROJECT_ID} kms keyrings create \ ${KMS_KEYRING_NAME} \ --location ${KMS_KEY_LOCATION}
Create the key:
gcloud --project ${KMS_KEY_PROJECT_ID} kms keys create \ ${KMS_KEY_NAME} \ --location ${KMS_KEY_LOCATION} \ --keyring ${KMS_KEYRING_NAME} \ --purpose ${KMS_KEY_PURPOSE} \ --default-algorithm ${KMS_KEY_ALGORITHM} \ --protection-level ${KMS_PROTECTION_LEVEL}
For more information on creating KMS keys, see Create an asymmetric key.
Add the public key to the attestor:
gcloud --project="${ATTESTOR_PROJECT_ID}" \ container binauthz attestors public-keys add \ --attestor="${ATTESTOR_NAME}" \ --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}"
Verify that the attestor was created
To verify that the attestor was created, run the following command:
gcloud --project="${ATTESTOR_PROJECT_ID}" \ container binauthz attestors list
What's next
- Configure a policy using the command-line tool
- Configure a policy using the Google Cloud console
- Create an attestation