Security best practices in GKE — Part 3

Yasirhashmi
Google Cloud - Community
6 min readFeb 15, 2023

--

Google Kubernetes Engine (GKE) is a fully-managed, highly-scalable, and secure container orchestration service in Google Cloud. However, as with any system, there are certain security best practices that we should follow to ensure that our GKE deployments are as secure as possible.

This article is part of a multi-part series covering below best practices around securing GKE workloads:

  1. Enable Network Policies in GKE
  2. Role based access control (RBAC) in GKE
  3. Workload Identity
  4. Binary Authorization
  5. PodSecurity — Hardening GKE clusters

In the first part and second part of this series, we covered network policies, RBAC and Workload Identity.

In this article, we will delve deep into Binary Authorization.

Binary Authorization is a security feature in GKE that helps to ensure the authenticity and trustworthiness of container images deployed in a cluster. The main idea behind Binary Authorization is to ensure that only authorized and trusted images are deployed in a cluster. The feature acts as a gatekeeper, requiring images to meet certain criteria before they are allowed to be deployed in the cluster. This helps to prevent any unauthorized or potentially malicious images from being deployed, thereby reducing the risk of security threats and unauthorized access to sensitive data.

The concept of Binary Authorization revolves around the concepts of attestors, attestations, signers, and signed images.

An Attestor is a Google Cloud’s resource that verifies the authenticity of a container image. The Attestor performs an attestation on the image, which is a verification process that ensures the image meets the criteria specified in the Binary Authorization policies.

The Signer is the entity that signs the container image, providing a digital signature that proves the image’s authenticity and creates the attestation. A signed image is an image that has been verified and signed by the Signer.

Container Analysis note

When the signer creates an attestation, that attestation is stored in the container analysis metadata as a container analysis note. During deployment, Binary authorization checks for the occurrence of the note in container analysis storage.

Flow of Binary Authorization:

  1. Container images are built and pushed to container registry
  2. The images in the container registry are signed and attestations are created
  3. Attestations are stored in container analysis API metadata
  4. Once the attestations are stored centrally, all the requests to create a pod or update a pod are validated against the binary authorization policies set
  5. The Binary Authorization API is triggered by sending a WebHook for policy evaluation. The API will then consult the Binary Authorization policy, and if necessary, it will also obtain the required attestation occurrences from the Container Analysis API. If the container image is compliant with the policy, it will be granted permission to run. If the image fails to adhere to the policy, an error message will be displayed to the API client, indicating the reason for denial.

Steps to configure binary authorization with Attestation

  1. Creating and Enforcing attestation

The first step towards creating and configuring Binary Authorization with Attestation is to create and enforce attestation.

The first step towards creating an attestation is to create an attestation note and define a cryptographic key. Binary Authorization uses cryptographic keys to digitally sign the container image and verify the authenticity of the signer. The signature generated is then stored in the attestation.

This key pair consists of a private key and a public key. Binary Authorization uses the private key to digitally sign the image and create the attestation and public key is used to verify the signature stored in the attestation before letting the container to deploy.

In this example, we will perform a manual attestation of a container image

Setting up the necessary variables

  1. Attestor’s email address

ATTESTOR_EMAIL=”$(gcloud config get-value core/account)”

The gcloud config get-value core/account command would list the email ID of the account.

Once these variables are set, the next step is to create the attestation note and register it with the container analysis metadata.

Creating the attestation note

Under advanced settings, verify the Automatically create a Container Analysis note is checked.

Creating a PGP Signing Key

As we will be using a PGP signing key to perform the cryptographic signing of the container image, we will create a new PGP key and export the public key.

  1. Set the public key variable

PUB_PGP_KEY=”pub-key.pgp”

  1. Create the PGP key

sudo apt-get install rng-tools

sudo rngd -r /dev/urandom

gpg — quick-generate-key — yes ${ATTESTOR_EMAIL}

  1. Extract the public key

gpg — armor — export “${ATTESTOR_EMAIL}” > ${PUB_PGP_KEY}

  1. Once the public key is generated, upload the public key or copy/paste the content in the attestor and create the attestor

Signing a Container Image

Uptil now, we have created an attestor and attached a public key to it. This is a one step process and needs to be done only once. For every image we want to deploy in the GKE cluster, we will have to sign it with the private key for the binary authorization to approve and deploy it.

For this example, we will use a sample image from the container registry gcr.io/google-samples/hello-app:1.0

  1. Set a few shell variables:

GENERATED_PAYLOAD=”generated_payload.json”

GENERATED_SIGNATURE=”generated_signature.pgp”

2. Get the PGP fingerprint:

PGP_FINGERPRINT=”$(gpg — list-keys ${ATTESTOR_EMAIL} | head -2 | tail -1 | awk ‘{print $1}’)”

3. Obtain the SHA256 Digest of the container image:

IMAGE_PATH=”gcr.io/google-samples/hello-app:1.0”
IMAGE_DIGEST=”$(gcloud container images list-tags — format=’get(digest)’ $IMAGE_PATH | head -1)”

4. Create a JSON-formatted signature payload:

gcloud container binauthz create-signature-payload \
— artifact-url=”${IMAGE_PATH}@${IMAGE_DIGEST}” > ${GENERATED_PAYLOAD}

5. View the generated signature payload:

cat “${GENERATED_PAYLOAD}”

6. Sign the payload with the PGP key and output the signature file

gpg — local-user “${ATTESTOR_EMAIL}” \
— armor \
— output ${GENERATED_SIGNATURE} \
— sign ${GENERATED_PAYLOAD}

7. Create the attestation:

gcloud container binauthz attestations create \
— artifact-url=”${IMAGE_PATH}@${IMAGE_DIGEST}” \
— attestor=”projects/${PROJECT_ID}/attestors/${ATTESTOR}” \
— signature-file=${GENERATED_SIGNATURE} \
— public-key-id=”${PGP_FINGERPRINT}”

8. Verify the attestation created:

gcloud container binauthz attestations list \
— attestor=”projects/${PROJECT_ID}/attestors/${ATTESTOR}”

Running an Image with Attestation enabled

In order for Attestation to work, we will have to edit the default policy to Require attestations. Next, we will have to add the created attestor created during the create attestor process.

Once the attestor is added, we are ready to deploy our sample app

kubectl run hello-server — image gcr.io/google-samples/hello-app:1.0 — port 8080

pod/hello-server created

As expected, the pod is created.

Let’s try to create another pod with another image

Kubectl run hello-world — image=nginx — port 8080

Error from server (VIOLATES_POLICY): admission webhook “imagepolicywebhook.image-policy.k8s.io” denied the request: Image nginx denied by Binary Authorization cluster admission rule for us-central1-a.my-gke-cluster Image nginx denied by attestor projects//attestors/$PROJECT_ID/dev-attestor: Expected digest with sha256 scheme, but gottag or malformed digest

This results in error as there is no attestation available for the image.

Conclusion

In conclusion, binary authorization is an essential security mechanism that can provide protection against a variety of security threats in a production environment. By ensuring that only cryptographically signed and verified code is allowed to run, binary authorization can help prevent malicious attacks, unauthorized code modifications, and software vulnerabilities. However, it is not a standalone solution and must be implemented in conjunction with other security best practices. Ultimately, by taking a comprehensive approach to security and implementing binary authorization as part of a larger strategy, organizations can better protect their systems and ensure the integrity and safety of their data and applications.

--

--