Four new ways to protect your supply chain with Chainguard Enforce

Adam Dawson, Product Manager
  •  
January 30, 2023

Chainguard Enforce is the first developer platform for supply chain security that helps you protect your software throughout its lifecycle by assuring provenance, image integrity, and more. Chainguard Enforce users have been able to ensure that signed supply chain attestations about container images are valid before allowing images to be deployed to production.

Now, Chainguard Enforce provides a richer policy engine that can evaluate a workload's metadata, such as configuration and manifest files, to help you ensure the security of not only the source image, but also its origin and build conditions, as well as context-sensitive details of the container the image is being deployed into.

While you may want to guarantee the provenance of your source container image in every environment from development, testing, and production; you may only have certain restrictions for the runtime environment in specific contexts. For example, the development cluster may allow an image to run as a privileged user for debugging purposes, but the production environment can use the same image with a policy that disallows privilege escalation at runtime.

By including additional metadata in Chainguard Enforce policy definitions, you can validate information about in the image's configuration, such as ENTRYPOINT, USER and build time, as well as the properties of the workload manifest, like metadata, apiVersion, kind, and fields in the resource spec. All of the usage guidelines and specifications for utilizing these features are documented in the Sigstore Policy Controller documentation.

Here are four new features of Chainguard Enforce that help you extend your supply chain security beyond the container image to its configuration and its runtime destination.

1. fetchConfigFile: This feature fetches the OCI Config file that lives alongside the container image itself in the source registry. The specification is defined in the link above. The Config file contains information about how and when the image was built, such as the author, the build time, the history, the source Dockerfile, and more. This file is very useful if you want to verify qualities of the image such as:

  • the image creation time (see how you can use this to author a "build horizon" policy)
  • the specific author
  • whether the image uses COPY or ADD commands in its dockerfile
  • Architecture, ENTRYPOINT, CMD, USER, ENV details in the image
  • The history information from the build tool, including available information about how the image was built

For example, here's the Config file for the busybox image on Dockerhub, which you can view yourself with the crane command line utility.

-- CODE language-bash -- $ crane config busybox | jq { "architecture": "amd64", "config": { "Hostname": "", "Domainname": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "Tty": false, "OpenStdin": false, "StdinOnce": false, "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ], "Cmd": [ "sh" ], "Image": "sha256:e9475e3c9e6925b85a80e5db1014a7feb80c0227827c6422eecbd3af8d10519b", "Volumes": null, "WorkingDir": "", "Entrypoint": null, "OnBuild": null, "Labels": null }, "container": "78be87834474355cd7b8fdd93165ac5c46bb9dd2ff6c213c742e7107e266e56f", "container_config": { "Hostname": "78be87834474", "Domainname": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "Tty": false, "OpenStdin": false, "StdinOnce": false, "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ], "Cmd": [ "/bin/sh", "-c", "#(nop) ", "CMD [\"sh\"]" ], "Image": "sha256:e9475e3c9e6925b85a80e5db1014a7feb80c0227827c6422eecbd3af8d10519b", "Volumes": null, "WorkingDir": "", "Entrypoint": null, "OnBuild": null, "Labels": {} }, "created": "2023-01-04T01:19:41.713369468Z", "docker_version": "20.10.12", "history": [ { "created": "2023-01-04T01:19:41.612792834Z", "created_by": "/bin/sh -c #(nop) ADD file:4bd5aa84616ee938414b5300d3ab0ef716638c37d76109bd2ed0ae6cc08fe88a in / " }, { "created": "2023-01-04T01:19:41.713369468Z", "created_by": "/bin/sh -c #(nop) CMD [\"sh\"]", "empty_layer": true } ], "os": "linux", "rootfs": { "type": "layers", "diff_ids": [ "sha256:b64792c17e4ad443d16b218afb3a8f5d03ca0f4ec49b11c1a7aebe17f6c3c1d2" ] } } },

You can validate any of the fields in this file with the fetchConfigFile: feature. In the example above, the image referenced was built on January 04, 2023. Perhaps you want to ensure that this image is no more than 30 days old before allowing it to be deployed to your production environment. You can use a build horizon policy to confirm this detail.

2. includeSpec: This feature enables Chainguard Enforce to include the workload resource "spec" file in validation. The spec file is the yaml used to define how the container should be launched. A trivial PodSpec might look like this:

-- CODE language-bash -- apiVersion: v1 kind: Pod metadata: name: nginx spec: containers: - name: nginx image: nginx:1.14.2 ports: - containerPort: 80

You can now apply policies to verify anything in the spec: section of this document, such as the image name, tags, versions, replica settings, ports, and other details. The spec can also include configuration to achieve PodSecurity standards that you may require in your organization. 

includeSpec: is a very powerful feature that adds a lot of metadata about the deployment request to the information about the source images to make a more comprehensive admission decision.

3. includeObjectMeta: This feature enriches the policy engine with the workload's metadata: in the deployment request. The ObjectMeta spec is defined here, and includes fields like the resource's name, namespace, labels, and annotations. You might use this content to verify that a certain Pod request contains approved labels or is being deployed to the proper namespace. In one example, the AppArmor PodSecurity standard restricts annotations in the metadata:

You can use the ObjectMeta: information to validate information like this, or other required labels or annotations.

4. includeTypeMeta: Including this metadata allows you to verify the "kind" and "apiVersion" in the Kubernetes resource request before allowing deployment. For example, you may have a policy that requires you to use v1 or greater API versions instead of alpha or beta versions. You can write Enforce policies that check this before allowing resources to be deployed.

Note: you may also meet requirements about the type of resource metadata using the matchResource: label selector.

How to use these features

By adding context-sensitive information from the image configuration and the workload metadata to your policies, you can enhance the supply chain security of your clusters beyond the static software itself, to verify the integrity of the container and environment it will be deployed into. 

There are several policies in the Enforce Policy Catalog that already take advantage of these features, which you can deploy out-of-the-box or customize for your use. 

If you are authoring your own Chainguard Enforce policies, you need to add the appropriate details to the ClusterImagePolicy definition:

The power of Chainguard Enforce is combining policies regarding signatures and attestations with details about the workload configuration. However, if your policy is limited to only check metadata about the workload, the signature authority check will need to be set to pass: 

-- CODE language-bash -- authorities: - static: action: pass

Then, add one or more of the desired parameters to the policy: section:

-- CODE language-bash -- policy: fetchConfigFile: true includeSpec: true includeObjectMeta: true includeTypeMeta: true

Further, the information you are including the policy evaluation is presented to Chainguard Enforce as a JSON document, so you will need to use either CUE or Rego to define the traversal of the JSON document to check the proper keys and values for the required content. To do this, you set the policy type: to cue: or rego: and define the policy in a data: block as follows in the example below:

-- CODE language-bash -- type: rego data: | package sigstore default isCompliant = false isCompliant { input.spec.hostIPC == "false" input.spec.hostPID == "false" input.spec.hostNetwork == "false" }

Requirements for structuring rego-style policies are listed in this blog and some examples of Cue-based policies are in the Policy Catalog. More information is available in the Chainguard Enforce documentation and many sample policies are available in the pre-written policy catalog.

It is important to verify the integrity of container images you are deploying, but it is equally important to ensure that the source information about the image meets your expectations, and the container the image will be running in also meets your security requirements. By combining image provenance validation and the workload metadata described above, you can enforce a comprehensive supply chain security policy in your clusters that meet compliance benchmarks, PodSecurity standards, and a complete list of your best practices for deploying software across your environments. There are dozens of policies in the Enforce Policy Catalog that you can use out-of-the-box to meet these requirements or customize according to your needs.

To get a demo of Chainguard Enforce or get started with a free trial, contact us today.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique. Duis cursus, mi quis viverra ornare, eros dolor interdum nulla, ut commodo diam libero vitae erat. Aenean faucibus nibh et justo cursus id rutrum lorem imperdiet. Nunc ut sem vitae risus tristique posuere.

Don’t break the chain – secure your supply chain today!

Product

Four new ways to protect your supply chain with Chainguard Enforce

Adam Dawson, Product Manager
January 30, 2023
copied

Chainguard Enforce is the first developer platform for supply chain security that helps you protect your software throughout its lifecycle by assuring provenance, image integrity, and more. Chainguard Enforce users have been able to ensure that signed supply chain attestations about container images are valid before allowing images to be deployed to production.

Now, Chainguard Enforce provides a richer policy engine that can evaluate a workload's metadata, such as configuration and manifest files, to help you ensure the security of not only the source image, but also its origin and build conditions, as well as context-sensitive details of the container the image is being deployed into.

While you may want to guarantee the provenance of your source container image in every environment from development, testing, and production; you may only have certain restrictions for the runtime environment in specific contexts. For example, the development cluster may allow an image to run as a privileged user for debugging purposes, but the production environment can use the same image with a policy that disallows privilege escalation at runtime.

By including additional metadata in Chainguard Enforce policy definitions, you can validate information about in the image's configuration, such as ENTRYPOINT, USER and build time, as well as the properties of the workload manifest, like metadata, apiVersion, kind, and fields in the resource spec. All of the usage guidelines and specifications for utilizing these features are documented in the Sigstore Policy Controller documentation.

Here are four new features of Chainguard Enforce that help you extend your supply chain security beyond the container image to its configuration and its runtime destination.

1. fetchConfigFile: This feature fetches the OCI Config file that lives alongside the container image itself in the source registry. The specification is defined in the link above. The Config file contains information about how and when the image was built, such as the author, the build time, the history, the source Dockerfile, and more. This file is very useful if you want to verify qualities of the image such as:

  • the image creation time (see how you can use this to author a "build horizon" policy)
  • the specific author
  • whether the image uses COPY or ADD commands in its dockerfile
  • Architecture, ENTRYPOINT, CMD, USER, ENV details in the image
  • The history information from the build tool, including available information about how the image was built

For example, here's the Config file for the busybox image on Dockerhub, which you can view yourself with the crane command line utility.

-- CODE language-bash -- $ crane config busybox | jq { "architecture": "amd64", "config": { "Hostname": "", "Domainname": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "Tty": false, "OpenStdin": false, "StdinOnce": false, "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ], "Cmd": [ "sh" ], "Image": "sha256:e9475e3c9e6925b85a80e5db1014a7feb80c0227827c6422eecbd3af8d10519b", "Volumes": null, "WorkingDir": "", "Entrypoint": null, "OnBuild": null, "Labels": null }, "container": "78be87834474355cd7b8fdd93165ac5c46bb9dd2ff6c213c742e7107e266e56f", "container_config": { "Hostname": "78be87834474", "Domainname": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "Tty": false, "OpenStdin": false, "StdinOnce": false, "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ], "Cmd": [ "/bin/sh", "-c", "#(nop) ", "CMD [\"sh\"]" ], "Image": "sha256:e9475e3c9e6925b85a80e5db1014a7feb80c0227827c6422eecbd3af8d10519b", "Volumes": null, "WorkingDir": "", "Entrypoint": null, "OnBuild": null, "Labels": {} }, "created": "2023-01-04T01:19:41.713369468Z", "docker_version": "20.10.12", "history": [ { "created": "2023-01-04T01:19:41.612792834Z", "created_by": "/bin/sh -c #(nop) ADD file:4bd5aa84616ee938414b5300d3ab0ef716638c37d76109bd2ed0ae6cc08fe88a in / " }, { "created": "2023-01-04T01:19:41.713369468Z", "created_by": "/bin/sh -c #(nop) CMD [\"sh\"]", "empty_layer": true } ], "os": "linux", "rootfs": { "type": "layers", "diff_ids": [ "sha256:b64792c17e4ad443d16b218afb3a8f5d03ca0f4ec49b11c1a7aebe17f6c3c1d2" ] } } },

You can validate any of the fields in this file with the fetchConfigFile: feature. In the example above, the image referenced was built on January 04, 2023. Perhaps you want to ensure that this image is no more than 30 days old before allowing it to be deployed to your production environment. You can use a build horizon policy to confirm this detail.

2. includeSpec: This feature enables Chainguard Enforce to include the workload resource "spec" file in validation. The spec file is the yaml used to define how the container should be launched. A trivial PodSpec might look like this:

-- CODE language-bash -- apiVersion: v1 kind: Pod metadata: name: nginx spec: containers: - name: nginx image: nginx:1.14.2 ports: - containerPort: 80

You can now apply policies to verify anything in the spec: section of this document, such as the image name, tags, versions, replica settings, ports, and other details. The spec can also include configuration to achieve PodSecurity standards that you may require in your organization. 

includeSpec: is a very powerful feature that adds a lot of metadata about the deployment request to the information about the source images to make a more comprehensive admission decision.

3. includeObjectMeta: This feature enriches the policy engine with the workload's metadata: in the deployment request. The ObjectMeta spec is defined here, and includes fields like the resource's name, namespace, labels, and annotations. You might use this content to verify that a certain Pod request contains approved labels or is being deployed to the proper namespace. In one example, the AppArmor PodSecurity standard restricts annotations in the metadata:

You can use the ObjectMeta: information to validate information like this, or other required labels or annotations.

4. includeTypeMeta: Including this metadata allows you to verify the "kind" and "apiVersion" in the Kubernetes resource request before allowing deployment. For example, you may have a policy that requires you to use v1 or greater API versions instead of alpha or beta versions. You can write Enforce policies that check this before allowing resources to be deployed.

Note: you may also meet requirements about the type of resource metadata using the matchResource: label selector.

How to use these features

By adding context-sensitive information from the image configuration and the workload metadata to your policies, you can enhance the supply chain security of your clusters beyond the static software itself, to verify the integrity of the container and environment it will be deployed into. 

There are several policies in the Enforce Policy Catalog that already take advantage of these features, which you can deploy out-of-the-box or customize for your use. 

If you are authoring your own Chainguard Enforce policies, you need to add the appropriate details to the ClusterImagePolicy definition:

The power of Chainguard Enforce is combining policies regarding signatures and attestations with details about the workload configuration. However, if your policy is limited to only check metadata about the workload, the signature authority check will need to be set to pass: 

-- CODE language-bash -- authorities: - static: action: pass

Then, add one or more of the desired parameters to the policy: section:

-- CODE language-bash -- policy: fetchConfigFile: true includeSpec: true includeObjectMeta: true includeTypeMeta: true

Further, the information you are including the policy evaluation is presented to Chainguard Enforce as a JSON document, so you will need to use either CUE or Rego to define the traversal of the JSON document to check the proper keys and values for the required content. To do this, you set the policy type: to cue: or rego: and define the policy in a data: block as follows in the example below:

-- CODE language-bash -- type: rego data: | package sigstore default isCompliant = false isCompliant { input.spec.hostIPC == "false" input.spec.hostPID == "false" input.spec.hostNetwork == "false" }

Requirements for structuring rego-style policies are listed in this blog and some examples of Cue-based policies are in the Policy Catalog. More information is available in the Chainguard Enforce documentation and many sample policies are available in the pre-written policy catalog.

It is important to verify the integrity of container images you are deploying, but it is equally important to ensure that the source information about the image meets your expectations, and the container the image will be running in also meets your security requirements. By combining image provenance validation and the workload metadata described above, you can enforce a comprehensive supply chain security policy in your clusters that meet compliance benchmarks, PodSecurity standards, and a complete list of your best practices for deploying software across your environments. There are dozens of policies in the Enforce Policy Catalog that you can use out-of-the-box to meet these requirements or customize according to your needs.

To get a demo of Chainguard Enforce or get started with a free trial, contact us today.

Related articles