The first step is to set the default Google Cloud project used by the gcloud
command:
PROJECT_ID=PROJECT_ID gcloud config set project ${PROJECT_ID}
where PROJECT_ID is the name of your project.
Enable required APIsEnable APIs for:
Artifact Registrygcloud --project=${PROJECT_ID} \ services enable\ container.googleapis.com\ artifactregistry.googleapis.com\ binaryauthorization.googleapis.comCreate a cluster with Binary Authorization enabled Create the cluster
Create a GKE cluster with Binary Authorization enabled. This is the cluster where you want your deployed container images to run. When you create the cluster, you pass the --binauthz-evaluation-mode=PROJECT_SINGLETON_POLICY_ENFORCE
flag to the gcloud container clusters create
command.
To create the cluster, follow these steps:
gcloud container clusters create \ --binauthz-evaluation-mode=PROJECT_SINGLETON_POLICY_ENFORCE \ --zone us-central1-a \ test-cluster
Here, you create a cluster named test-cluster
in the GKE zone us-central1-a
.
kubectl
You must also update the local kubeconfig
file for your kubectl
installation. This provides the credentials and endpoint information required to access the cluster in GKE.
To update the local kubeconfig
file:
gcloud container clusters get-credentials \ --zone us-central1-a \ test-clusterView the default policy
A policy in Binary Authorization is a set of rules that govern the deployment of container images. You can have one policy per project. By default, the policy is configured to allow all container images to be deployed.
Binary Authorization allows you to export and import a policy file in YAML format. This format reflects the structure of a policy as it is stored by the service. When you configure a policy using gcloud
commands, you edit this file.
To view the default policy, export the policy YAML file:
gcloud container binauthz policy export
By default, the file has the following contents:
defaultAdmissionRule: enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG evaluationMode: ALWAYS_ALLOW globalPolicyEvaluationMode: ENABLE name: projects/PROJECT_ID/policy
The default rule is defined in the defaultAdmissionRule
node. evaluationMode
specifies that the policy allows all attempts at image deployment. In this tutorial, you update the default rule to require attestations.
globalPolicyEvaluationMode
exempts Google-managed system images from Binary Authorization enforcement.
To add an exempt image to the allowlist, add the following to the policy file:
admissionWhitelistPatterns: - namePattern: EXEMPT_IMAGE_PATH
Replace EXEMPT_IMAGE_PATH
with the path to am image to exempt. To exempt additional images, add additional - namePattern
entries. Learn more about admissionWhitelistPatterns
.
For more information on the structure of a policy, see the Policy YAML reference.
Create an attestorAn attestor is the verification authority that the Binary Authorization enforcer uses at deploy time to decide whether to allow GKE to deploy the corresponding signed container image. The attestor contains the public key and is typically managed by personnel in your organization who are responsible for software supply chain security.
Creating an attestor requires you to:
For this tutorial, you have one attestor named test-attestor
and a Container Analysis note named test-attestor-note
. In a real-world scenario, you can have any number of attestors, each one representing a party that participates in the authorization process for a container image.
Set variables that store the name of your attestor and Artifact Analysis note:
ATTESTOR_NAME=test-attestor NOTE_ID=test-attestor-note
Replace:
Create a JSON file in /tmp/note_payload.json
that describes the Container Analysis note:
cat > /tmp/note_payload.json << EOM { "name": "projects/${PROJECT_ID}/notes/${NOTE_ID}", "attestation": { "hint": { "human_readable_name": "Attestor Note" } } } EOM
Create the note by sending an HTTP request to the Artifact Analysis REST API:
curl -X POST \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $(gcloud auth print-access-token)" \ --data-binary @/tmp/note_payload.json \ "https://containeranalysis.googleapis.com/v1/projects/${PROJECT_ID}/notes/?noteId=${NOTE_ID}"Caution: Binary Authorization doesn't support Artifact Analysis regional storage or regional endpoints. We recommend that you use the Artifact Analysis global API endpoint (
https://containeranalysis.googleapis.com/
).Verify that the note was created:
curl \ -H "Authorization: Bearer $(gcloud auth print-access-token)" \ "https://containeranalysis.googleapis.com/v1/projects/${PROJECT_ID}/notes/${NOTE_ID}"
Now, you can create the attestor:
Create the attestor in Binary Authorization:
gcloud container binauthz attestors create ${ATTESTOR_NAME} \ --attestation-authority-note=${NOTE_ID} \ --attestation-authority-note-project=${PROJECT_ID}
Verify that the attestor was created:
gcloud container binauthz attestors list
The attestor you created is not yet usable without an associated key pair, which you create later in this guide.
For a multi-project configuration, you must set permissions on the Container Analysis note as described in Multi-Project Setup. This is not required in a single-project scenario, because the project has the requiredroles/containeranalysis.notes.occurrences.viewer
by default. Generate a key pair
Binary Authorization uses cryptographic keys to securely verify the identity of signers. This ensures that only authorized container images can be deployed. The key pair consists of a private key and a public key. The signer uses the private key to sign the container image digest, producing a signature that is then stored in an attestation. The public key is stored in the attestor. At deploy time, the Binary Authorization enforcer uses the attestor's public key to verify the signature in the attestation before allowing the container to deploy.
In this tutorial, you use Public-Key Infrastructure (X.509) (PKIX) format for cryptographic keys. This tutorial uses the recommended Elliptic Curve Digital Signature Algorithm (ECDSA) to generate a PKIX key pair. You can also use RSA or PGP keys for signing images.
For more information on signing algorithms, see Key purposes and algorithms.
The keys generated and stored by Cloud Key Management Service (Cloud KMS) are PKIX-compliant. See Creating attestors using the gcloud CLI for more information on using PKIX keys and Cloud KMS.
PKIX (Cloud KMS)To create the key pair in Cloud KMS, do the following:
Set up environment variables needed to create the key pair.
KMS_KEY_PROJECT_ID=${PROJECT_ID}
KMS_KEYRING_NAME=my-binauthz-keyring
KMS_KEY_NAME=my-binauthz-kms-key-name
KMS_KEY_LOCATION=global
KMS_KEY_PURPOSE=asymmetric-signing
KMS_KEY_ALGORITHM=ec-sign-p256-sha256
KMS_PROTECTION_LEVEL=software
KMS_KEY_VERSION=1
To create the keyring, run the following command:
gcloud kms keyrings create ${KMS_KEYRING_NAME} \
--location ${KMS_KEY_LOCATION}
To create the key, run the following command:
gcloud 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}
To add the public key to the attestor, run the following command:
gcloud --project="${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}"
Get the public key ID from the attestor as follows:
You can view your public key ID at any time using the command: gcloud container binauthz attestors describe <var>ATTESTOR_NAME</var>
.
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)' --project ${PROJECT_ID})
To generate a PKIX key pair, follow these steps:
Create the private key:
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:
PUBLIC_KEY_FILE="/tmp/ec_public.pem" openssl ec -in ${PRIVATE_KEY_FILE} -pubout -out ${PUBLIC_KEY_FILE}
Add the public key to the 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="${PROJECT_ID}" \ beta container binauthz attestors public-keys add \ --attestor="${ATTESTOR_NAME}" \ --pkix-public-key-file=${PUBLIC_KEY_FILE} \ --pkix-public-key-algorithm=ecdsa-p256-sha256Note: This command outputs the PUBLIC_KEY_ID you use when creating an attestation. It is in the
id
field of the output and looks likeni:///sha-256;ybf_gINTzsBKLCaRIeQnExNhKFkGONXXXlr63QeZY-Q
.Save the public key ID.
To save the public key ID, you can copy it from the output of public-keys add
above. To view your attestor's public key ID after adding it to the attestor, use gcloud container binauthz attestors describe ${ATTESTOR_NAME}
:
PUBLIC_KEY_ID=$(gcloud container binauthz attestors describe ${ATTESTOR_NAME} \
--format='value(userOwnedGrafeasNote.publicKeys[0].id)')
Now, you can configure your policy. In this step, you export the policy YAML file to your local system and modify the default rule so that it requires an attestation by the attestor you defined above.
To configure the policy, follow these steps:
Create a new policy file that allows Google-maintained system images, sets the evaluationMode
to REQUIRE_ATTESTATION
, and adds a node named requireAttestationsBy
that references the attestor you created:
cat > /tmp/policy.yaml << EOM globalPolicyEvaluationMode: ENABLE defaultAdmissionRule: evaluationMode: REQUIRE_ATTESTATION enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG requireAttestationsBy: - projects/${PROJECT_ID}/attestors/${ATTESTOR_NAME} name: projects/${PROJECT_ID}/policy EOM
Import the policy YAML file into Binary Authorization:
gcloud container binauthz policy import /tmp/policy.yaml
For more information on configuring a policy, see Configure a policy using the gcloud CLI.
Test the policyYou can test the policy you configured above by trying to deploy a sample container image to the cluster. The policy will block deployment because the required attestation has not been made.
For this tutorial, you can use sample images from Artifact Registry. The image from Artifact Registry is located at the path us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0
. The path contains a public image created by Google that contains a "Hello, World!" sample application.
First, try to deploy the image:
kubectl run hello-server --image us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0 --port 8080
Now, verify that the deployment was blocked by Binary Authorization:
kubectl get pods
The command prints the following message, which indicates that the image was not deployed:
No resources found.
You can get further details about the deployment:
kubectl get event --template \ '{{range.items}}{{"\033[0;36m"}}{{.reason}}:{{"\033[0m"}}\{{.message}}{{"\n"}}{{end}}'
You see a response that resembles the following:
FailedCreate: Error creating: pods POD_NAME is forbidden: admission webhook "imagepolicywebhook.image-policy.k8s.io" denied the request: Image IMAGE_NAME denied by Binary Authorization default admission rule. Image IMAGE_NAME denied by attestor ATTESTOR_NAME: No attestations found
In this output:
Make sure to delete the deployment so you can continue to the next step:
kubectl delete deployment hello-serverCreate an attestation
An attestation is a digital document created by a signer that certifies that GKE is allowed to deploy the associated container image. The process of creating an attestation is sometimes called "signing an image." A signer can be a person or, more often, an automated process that runs when a container image is built. The signature is created using the private key from a key pair. At deploy time, the Binary Authorization enforcer uses the attestor's public key to verify the signature in the attestation.
In this tutorial, your attestation simply states that you authorize the image for deployment.
To create an attestation, follow these steps:
Set variables that store the registry path and digest of the image:
Artifact RegistryIMAGE_PATH="us-docker.pkg.dev/google-samples/containers/gke/hello-app" IMAGE_DIGEST="sha256:37e5287945774f27b418ce567cd77f4bbc9ef44a1bcd1a2312369f31f9cce567" IMAGE_TO_ATTEST=${IMAGE_PATH}@${IMAGE_DIGEST}
To create the attestation, do the following:
PKIX Cloud KMSTo create the attestation using the Cloud KMS key, run the following command:
gcloud beta container binauthz attestations sign-and-create \
--project="${PROJECT_ID}" \
--artifact-url="${IMAGE_TO_ATTEST}" \
--attestor="${ATTESTOR_NAME}" \
--attestor-project="${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}"
PKIX (local key)
To create the attestation using the local key, do the following:
Generate the attestation payload:
Note: In the following command, while an${IMAGE_PATH}
is required to create the signature payload for the attestation, only the ${IMAGE_DIGEST}
is used at deploy time. This means you can deploy an identical container image from multiple locations with the same attestation.
gcloud container binauthz create-signature-payload \ --artifact-url=${IMAGE_TO_ATTEST} > /tmp/generated_payload.json
The payload JSON file has the following contents:
{ "critical": { "identity": { "docker-reference": "us-docker.pkg.dev/google-samples/containers/gke/hello-app" }, "image": { "docker-manifest-digest": "sha256:c62ead5b8c15c231f9e786250b07909daf6c266d0fcddd93fea 882eb722c3be4" }, "type": "Google cloud binauthz container signature" } }
To sign the payload with your PKIX private key and generate a signature file, run the following command:
openssl dgst -sha256 -sign ${PRIVATE_KEY_FILE} /tmp/generated_payload.json > /tmp/ec_signature
The signature file is the signed version of the payload JSON file you created earlier in this guide.
Create and validate the attestation:
gcloud container binauthz attestations create \ --project="${PROJECT_ID}" \ --artifact-url="${IMAGE_TO_ATTEST}" \ --attestor="projects/${PROJECT_ID}/attestors/${ATTESTOR_NAME}" \ --signature-file=/tmp/ec_signature \ --public-key-id="${PUBLIC_KEY_ID}" \ --validate
Replace PUBLIC_KEY_ID
with the public key id that you found in Generate a PKIX key pair above.
The validate
flag checks that the attestation can be verified by the attestor you configured in your policy.
Verify that the attestation was created:
gcloud container binauthz attestations list \ --attestor=$ATTESTOR_NAME --attestor-project=$PROJECT_ID
For more information on creating attestations, see Creating Attestations.
Retest the policyAgain, test the policy by deploying a sample container image to the cluster. This time, you must deploy the image using the digest rather than a tag like 1.0
or latest
, as Binary Authorization will use the digest to look up attestations. Here, Binary Authorization allows the image to be deployed because the required attestation has been made.
To deploy the image, follow these steps:
kubectl run hello-server --image ${IMAGE_TO_ATTEST} --port 8080
To verify that the image was deployed:
kubectl get pods
The command prints a message similar to the following, which indicates that deployment was successful:
NAME READY STATUS RESTARTS AGE hello-server-579859fb5b-h2k8s 1/1 Running 0 1m
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4