Chainguard open sources new policy catalog for Sigstore policy-controller

Erin Glass, Product Manager and Ville Aikas, Distinguished Engineer
  •  
April 18, 2023

The Sigstore policy-controller was built and designed to help improve the security of the software supply chain when paired with Sigstore’s suite of tooling like cosign, rekor, fulcio and more. As organizations and open source projects look to strengthen the integrity of their software, Sigstore’s policy-controller is a helpful tool which allows users to enforce policies on Kubernetes workloads based on verifiable and trusted supply-chain metadata from cosign.

To help users unlock the security benefits of the Sigstore policy-controller, Chainguard is open sourcing a new policy catalog that can be adopted incrementally to improve the security of your software supply chain. 

Previously only available to Chainguard Enforce customers, the new policy catalog is being open sourced and is available today for existing policy-controller users, organizations and OSS projects. We welcome input from the community on new policies to include in the catalog as the software security landscape evolves and will maintain contributions directly through the open source catalog repo.

Building a secure software supply chain with policy-controller 

The underlying principles upon which the Sigstore ecosystem is built are based on roots of trust: knowing where software came from, whether it is signed, if it came from a trusted source, and having confidence that it hasn’t been tampered with. 

Several admission controllers today allow users to define policies for Kubernetes resources and workloads such as requiring signatures or attestations. The Sigstore policy-controller goes a step further by allowing you to use CUE or Rego languages to customize and create complex  policies to suit your organization’s compliance needs. For example, to meet PCI-DSS, it is required that all vulnerabilities with a CVSS score higher than 4 are addressed. Our policy for failing images that have high or critical CVES (written in Rego to leverage cosign attestation data) can help you meet this need.  

Additionally, Chainguard engineers worked with the Sigstore community to design a fully integrated and native cosign verification API that declares policies using YAML, a format that some users prefer. 

Getting started with the policy catalog 

Let’s look at some of the key policies in the policy catalog that you can get started with today to secure your software supply chain using Sigstore policy-controller: 

Fail on High or Critical CVEs (REGO): Vulnerability attestation with no High or Critical CVEs.

-- CODE language-bash -- ############################################################################################# # To generate an attestation with a scan report and attest it to an image follow these steps: # $ trivy image --format cosign-vuln --output vuln.json # $ cosign attest --key /path/to/cosign.key --type https://cosign.sigstore.dev/attestation/vuln/v1 --predicate vuln.json # # $ cosign verify-attestation --key /path/to/cosign.pub --type https://cosign.sigstore.dev/attestation/vuln/v1 ############################################################################################# apiVersion: policy.sigstore.dev/v1beta1 kind: ClusterImagePolicy metadata: name: vuln-no-high-or-critical-rego annotations: catalog.chainguard.dev/title: Fail on high or critical CVEs catalog.chainguard.dev/description: Vulnerability attestation with no High or Critical CVEs catalog.chainguard.dev/labels: attestation,rego spec: images: - glob: "**" authorities: - name: my-authority key: # REPLACE WITH YOUR PUBLIC KEY! data: | -----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAESWmPfv6b083TNcwY4SlYcZULn7jX /vfUyU7CPr2zssLc3+8SWAv2ZY59pofKnvYBp9dNiNwVTkrxab1bcpocVg== -----END PUBLIC KEY----- attestations: - name: must-not-have-high-critical-cves predicateType: https://cosign.sigstore.dev/attestation/vuln/v1 policy: type: rego data: | package sigstore isCompliant[response] { input.predicateType = "https://cosign.sigstore.dev/attestation/vuln/v1" filteredHighSeverity = [c | c := input.predicate.scanner.result.Results[_].Vulnerabilities[_]; c.Severity == "HIGH"] filteredCriticalSeverity = [c | c := input.predicate.scanner.result.Results[_].Vulnerabilities[_]; c.Severity == "CRITICAL"] result = ((count(filteredHighSeverity) + count(filteredCriticalSeverity)) == 0) errorMsg = sprintf("Found HIGH '%d' and CRITICAL '%d' vulnerabilities", [count(filteredHighSeverity) ,count(filteredCriticalSeverity)]) warnMsg = "" response := { "result" : result, "error" : errorMsg, "warning" : warnMsg } }

Signature Policy: this enforces that all images are signed before they are allowed to be pushed to production.

-- CODE language-bash -- apiVersion: policy.sigstore.dev/v1beta1 kind: ClusterImagePolicy metadata: name: keyless-signature annotations: catalog.chainguard.dev/title: Signature policy catalog.chainguard.dev/description: Enforce images are signed catalog.chainguard.dev/labels: popular, oidc spec: images: - glob: gcr.io/your-image-here/* authorities: - keyless: identities: # <<<-- REPLACE the following with your OIDC provider & subject --> # - issuer: https://accounts.google.com subject: foo@example.com url: https://fulcio.sigstore.dev ctlog: url: https://rekor.sigstore.dev

Maximum Image Age (REGO): This checks that the maximum age an image is allowed to have is 30 days old. This is measured using the container image's configuration, which has a "created" field. Some build tools may fail this check because they build reproducibly, and use a fixed date (e.g. the Unix epoch) as their creation time, but many of these tools support specifying SOURCE_DATE_EPOCH, which aligns the creation time with the date of the source commit.

-- CODE language-bash -- apiVersion: policy.sigstore.dev/v1beta1 kind: ClusterImagePolicy metadata: name: maximum-image-age-rego annotations: catalog.chainguard.dev/title: Maximum image age catalog.chainguard.dev/description: | This checks that the maximum age an image is allowed to have is 30 days old. This is measured using the container image's configuration, which has a "created" field. Some build tools may fail this check because they build reproducibly, and use a fixed date (e.g. the Unix epoch) as their creation time, but many of these tools support specifying SOURCE_DATE_EPOCH, which aligns the creation time with the date of the source commit. catalog.chainguard.dev/labels: rego spec: images: [{ glob: "**" }] authorities: [{ static: { action: pass } }] mode: warn policy: fetchConfigFile: true type: "rego" data: | package sigstore nanosecs_per_second = 1000 * 1000 * 1000 nanosecs_per_day = 24 * 60 * 60 * nanosecs_per_second # Change this to the maximum number of days to allow. maximum_age = 30 * nanosecs_per_day isCompliant[response] { created := time.parse_rfc3339_ns(input.config[_].created) response := { "result" : time.now_ns() < created + maximum_age, "error" : "Image exceeds maximum allowed age." } }

Log4Shell  (CUE): Ensure that Log4shell is not running in your environment. A recent report found that 29% of vulnerable assets saw the reintroduction of Log4Shell even after full remediation was achieved. This policy will prevent reintroduction from being possible.

-- CODE language-bash -- ApiVersion: policy.sigstore.dev/v1beta1 kind: ClusterImagePolicy metadata: name: log4shell-cue annotations: catalog.chainguard.dev/title: Log4Shell catalog.chainguard.dev/description: Ensure Log4Shell is not running catalog.chainguard.dev/labels: cue spec: images: - glob: "**" # Your image here authorities: - name: keyatt keyless: url: "https://fulcio.sigstore.dev" identities: # Check the identity you expect to be signing SBOMs here! - issuerRegExp: ".*" subjectRegExp: ".*" attestations: - predicateType: https://cyclonedx.org/bom name: log4shellcyclonedx policy: type: cue data: | import ( "list" "strings" ) let log4shell_names = [ "log4j-api", "log4j-core" ] let log4shell_versions = [ "2.0-beta9", "2.0-rc1", "2.0-rc2", "2.0", "2.0.1", "2.0.2", "2.1", "2.2", "2.3", "2.4", "2.4.1", "2.5", "2.6", "2.6.1", "2.6.2", "2.7", "2.8", "2.8.1", "2.8.2", "2.9.0", "2.9.1","2.10.0", "2.11.0", "2.11.1", "2.11.2", "2.12.0", "2.12.1", "2.13.0", "2.13.1", "2.13.2", "2.13.3", "2.14.0", "2.14.1", "2.15.0" ] predicate: { Data: { components: [...{ name: name version: version if list.Contains(log4shell_names, name) && list.Contains(log4shell_versions, version) { err: strings.Join([ "Error: CycloneDX SBOM contains package", name, "version", version, "which is", "vulnerable to Log4Shell (CVE-2021-44228)" ], " ") name: err } }] } } - predicateType: https://spdx.dev/Document name: log4shellspdxjson policy: type: cue data: | import ( "list" "strings" ) let log4shell_names = [ "log4j-api", "log4j-core" ] let log4shell_versions = [ "2.0-beta9", "2.0-rc1", "2.0-rc2", "2.0", "2.0.1", "2.0.2", "2.1", "2.2", "2.3", "2.4", "2.4.1", "2.5", "2.6", "2.6.1", "2.6.2", "2.7", "2.8", "2.8.1", "2.8.2", "2.9.0", "2.9.1","2.10.0", "2.11.0", "2.11.1", "2.11.2", "2.12.0", "2.12.1", "2.13.0", "2.13.1", "2.13.2", "2.13.3", "2.14.0", "2.14.1", "2.15.0" ] predicate: { Data: { packages: [...{ name: name versionInfo: versionInfo if list.Contains(log4shell_names, name) && list.Contains(log4shell_versions, versionInfo) { err: strings.Join([ "Error: SPDX SBOM contains package", name, "version", versionInfo, "which is", "vulnerable to Log4Shell (CVE-2021-44228)" ], " ") name: err } }] } }

Building trust and integrity in the software artifacts that underpin the technologies we depend on requires an open approach. That is why the policy catalog is being released and maintained openly to advance adoption of admission controller tooling with supply chain security principles built in. Here are some key insights from the Sigstore community, maintainers and end users that highlight these benefits and more of the Sigstore policy-controller.

"This is not the year 2020 anymore. We have the data and the means to trace the integrity of our software supply chain and, now, with the policy controller and its catalog, we can have agency to enforce our security requirements. This is beyond a catalog, but rather the language to speak about software supply chains.”Santiago Torres-Arias, Director of the Trustworthy Software Ecosystems Lab @ Purdue University
“The Sigstore policy-controller is an incredible tool that helps developers and maintainers everywhere enable stronger software supply chain security policies like enforcing software signatures and attestations, and preventing critical or high CVEs. The availability of the new open source policy catalog is an exciting opportunity for the Sigstore community and beyond to start unlocking these benefits with a clear path to the enforcement of software supply chain security policies.” Priya Wadhwa, Software Engineer at Chainguard and member of the Sigstore Technical Steering Committee 
“When I recently learned about Cosign, Sigstore policy-controller was a natural fit to make sure that my container images are signed before actually being deployed in my Kubernetes clusters. It was easy to get started with, and yet powerful. I was able to leverage an advanced setup on Google Kubernetes Engine (GKE) with Workload Identity to securely connect Sigstore policy-controller to Google Artifact Registry and Cloud KMS (see associated blog post). Last but not least, the Sigstore community and contributors are very active on Slack and GitHub, they were eager to answer my questions to help me in my learning journey.” – Mathieu Benoit, CNCF Ambassador

Learn more 

If you are just starting to explore Sigstore and the policy-controller, check out these resources in Chainguard Academy and Unchained:

To get started with the policy catalog, visit the public repo here or watch this demo video that explores available policies:

If you are a Chainguard Enforce customer, you can use the policy catalog to set and enforce policies compatible with Sigstore policy-controller directly through the platform. Want to learn more about Chainguard Enforce and its rich policy enforcement and admission controller capabilities? Reach out to our team for a demo or start your 30-day free trial

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!

Open Source

Chainguard open sources new policy catalog for Sigstore policy-controller

Erin Glass, Product Manager and Ville Aikas, Distinguished Engineer
April 18, 2023
copied

The Sigstore policy-controller was built and designed to help improve the security of the software supply chain when paired with Sigstore’s suite of tooling like cosign, rekor, fulcio and more. As organizations and open source projects look to strengthen the integrity of their software, Sigstore’s policy-controller is a helpful tool which allows users to enforce policies on Kubernetes workloads based on verifiable and trusted supply-chain metadata from cosign.

To help users unlock the security benefits of the Sigstore policy-controller, Chainguard is open sourcing a new policy catalog that can be adopted incrementally to improve the security of your software supply chain. 

Previously only available to Chainguard Enforce customers, the new policy catalog is being open sourced and is available today for existing policy-controller users, organizations and OSS projects. We welcome input from the community on new policies to include in the catalog as the software security landscape evolves and will maintain contributions directly through the open source catalog repo.

Building a secure software supply chain with policy-controller 

The underlying principles upon which the Sigstore ecosystem is built are based on roots of trust: knowing where software came from, whether it is signed, if it came from a trusted source, and having confidence that it hasn’t been tampered with. 

Several admission controllers today allow users to define policies for Kubernetes resources and workloads such as requiring signatures or attestations. The Sigstore policy-controller goes a step further by allowing you to use CUE or Rego languages to customize and create complex  policies to suit your organization’s compliance needs. For example, to meet PCI-DSS, it is required that all vulnerabilities with a CVSS score higher than 4 are addressed. Our policy for failing images that have high or critical CVES (written in Rego to leverage cosign attestation data) can help you meet this need.  

Additionally, Chainguard engineers worked with the Sigstore community to design a fully integrated and native cosign verification API that declares policies using YAML, a format that some users prefer. 

Getting started with the policy catalog 

Let’s look at some of the key policies in the policy catalog that you can get started with today to secure your software supply chain using Sigstore policy-controller: 

Fail on High or Critical CVEs (REGO): Vulnerability attestation with no High or Critical CVEs.

-- CODE language-bash -- ############################################################################################# # To generate an attestation with a scan report and attest it to an image follow these steps: # $ trivy image --format cosign-vuln --output vuln.json # $ cosign attest --key /path/to/cosign.key --type https://cosign.sigstore.dev/attestation/vuln/v1 --predicate vuln.json # # $ cosign verify-attestation --key /path/to/cosign.pub --type https://cosign.sigstore.dev/attestation/vuln/v1 ############################################################################################# apiVersion: policy.sigstore.dev/v1beta1 kind: ClusterImagePolicy metadata: name: vuln-no-high-or-critical-rego annotations: catalog.chainguard.dev/title: Fail on high or critical CVEs catalog.chainguard.dev/description: Vulnerability attestation with no High or Critical CVEs catalog.chainguard.dev/labels: attestation,rego spec: images: - glob: "**" authorities: - name: my-authority key: # REPLACE WITH YOUR PUBLIC KEY! data: | -----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAESWmPfv6b083TNcwY4SlYcZULn7jX /vfUyU7CPr2zssLc3+8SWAv2ZY59pofKnvYBp9dNiNwVTkrxab1bcpocVg== -----END PUBLIC KEY----- attestations: - name: must-not-have-high-critical-cves predicateType: https://cosign.sigstore.dev/attestation/vuln/v1 policy: type: rego data: | package sigstore isCompliant[response] { input.predicateType = "https://cosign.sigstore.dev/attestation/vuln/v1" filteredHighSeverity = [c | c := input.predicate.scanner.result.Results[_].Vulnerabilities[_]; c.Severity == "HIGH"] filteredCriticalSeverity = [c | c := input.predicate.scanner.result.Results[_].Vulnerabilities[_]; c.Severity == "CRITICAL"] result = ((count(filteredHighSeverity) + count(filteredCriticalSeverity)) == 0) errorMsg = sprintf("Found HIGH '%d' and CRITICAL '%d' vulnerabilities", [count(filteredHighSeverity) ,count(filteredCriticalSeverity)]) warnMsg = "" response := { "result" : result, "error" : errorMsg, "warning" : warnMsg } }

Signature Policy: this enforces that all images are signed before they are allowed to be pushed to production.

-- CODE language-bash -- apiVersion: policy.sigstore.dev/v1beta1 kind: ClusterImagePolicy metadata: name: keyless-signature annotations: catalog.chainguard.dev/title: Signature policy catalog.chainguard.dev/description: Enforce images are signed catalog.chainguard.dev/labels: popular, oidc spec: images: - glob: gcr.io/your-image-here/* authorities: - keyless: identities: # <<<-- REPLACE the following with your OIDC provider & subject --> # - issuer: https://accounts.google.com subject: foo@example.com url: https://fulcio.sigstore.dev ctlog: url: https://rekor.sigstore.dev

Maximum Image Age (REGO): This checks that the maximum age an image is allowed to have is 30 days old. This is measured using the container image's configuration, which has a "created" field. Some build tools may fail this check because they build reproducibly, and use a fixed date (e.g. the Unix epoch) as their creation time, but many of these tools support specifying SOURCE_DATE_EPOCH, which aligns the creation time with the date of the source commit.

-- CODE language-bash -- apiVersion: policy.sigstore.dev/v1beta1 kind: ClusterImagePolicy metadata: name: maximum-image-age-rego annotations: catalog.chainguard.dev/title: Maximum image age catalog.chainguard.dev/description: | This checks that the maximum age an image is allowed to have is 30 days old. This is measured using the container image's configuration, which has a "created" field. Some build tools may fail this check because they build reproducibly, and use a fixed date (e.g. the Unix epoch) as their creation time, but many of these tools support specifying SOURCE_DATE_EPOCH, which aligns the creation time with the date of the source commit. catalog.chainguard.dev/labels: rego spec: images: [{ glob: "**" }] authorities: [{ static: { action: pass } }] mode: warn policy: fetchConfigFile: true type: "rego" data: | package sigstore nanosecs_per_second = 1000 * 1000 * 1000 nanosecs_per_day = 24 * 60 * 60 * nanosecs_per_second # Change this to the maximum number of days to allow. maximum_age = 30 * nanosecs_per_day isCompliant[response] { created := time.parse_rfc3339_ns(input.config[_].created) response := { "result" : time.now_ns() < created + maximum_age, "error" : "Image exceeds maximum allowed age." } }

Log4Shell  (CUE): Ensure that Log4shell is not running in your environment. A recent report found that 29% of vulnerable assets saw the reintroduction of Log4Shell even after full remediation was achieved. This policy will prevent reintroduction from being possible.

-- CODE language-bash -- ApiVersion: policy.sigstore.dev/v1beta1 kind: ClusterImagePolicy metadata: name: log4shell-cue annotations: catalog.chainguard.dev/title: Log4Shell catalog.chainguard.dev/description: Ensure Log4Shell is not running catalog.chainguard.dev/labels: cue spec: images: - glob: "**" # Your image here authorities: - name: keyatt keyless: url: "https://fulcio.sigstore.dev" identities: # Check the identity you expect to be signing SBOMs here! - issuerRegExp: ".*" subjectRegExp: ".*" attestations: - predicateType: https://cyclonedx.org/bom name: log4shellcyclonedx policy: type: cue data: | import ( "list" "strings" ) let log4shell_names = [ "log4j-api", "log4j-core" ] let log4shell_versions = [ "2.0-beta9", "2.0-rc1", "2.0-rc2", "2.0", "2.0.1", "2.0.2", "2.1", "2.2", "2.3", "2.4", "2.4.1", "2.5", "2.6", "2.6.1", "2.6.2", "2.7", "2.8", "2.8.1", "2.8.2", "2.9.0", "2.9.1","2.10.0", "2.11.0", "2.11.1", "2.11.2", "2.12.0", "2.12.1", "2.13.0", "2.13.1", "2.13.2", "2.13.3", "2.14.0", "2.14.1", "2.15.0" ] predicate: { Data: { components: [...{ name: name version: version if list.Contains(log4shell_names, name) && list.Contains(log4shell_versions, version) { err: strings.Join([ "Error: CycloneDX SBOM contains package", name, "version", version, "which is", "vulnerable to Log4Shell (CVE-2021-44228)" ], " ") name: err } }] } } - predicateType: https://spdx.dev/Document name: log4shellspdxjson policy: type: cue data: | import ( "list" "strings" ) let log4shell_names = [ "log4j-api", "log4j-core" ] let log4shell_versions = [ "2.0-beta9", "2.0-rc1", "2.0-rc2", "2.0", "2.0.1", "2.0.2", "2.1", "2.2", "2.3", "2.4", "2.4.1", "2.5", "2.6", "2.6.1", "2.6.2", "2.7", "2.8", "2.8.1", "2.8.2", "2.9.0", "2.9.1","2.10.0", "2.11.0", "2.11.1", "2.11.2", "2.12.0", "2.12.1", "2.13.0", "2.13.1", "2.13.2", "2.13.3", "2.14.0", "2.14.1", "2.15.0" ] predicate: { Data: { packages: [...{ name: name versionInfo: versionInfo if list.Contains(log4shell_names, name) && list.Contains(log4shell_versions, versionInfo) { err: strings.Join([ "Error: SPDX SBOM contains package", name, "version", versionInfo, "which is", "vulnerable to Log4Shell (CVE-2021-44228)" ], " ") name: err } }] } }

Building trust and integrity in the software artifacts that underpin the technologies we depend on requires an open approach. That is why the policy catalog is being released and maintained openly to advance adoption of admission controller tooling with supply chain security principles built in. Here are some key insights from the Sigstore community, maintainers and end users that highlight these benefits and more of the Sigstore policy-controller.

"This is not the year 2020 anymore. We have the data and the means to trace the integrity of our software supply chain and, now, with the policy controller and its catalog, we can have agency to enforce our security requirements. This is beyond a catalog, but rather the language to speak about software supply chains.”Santiago Torres-Arias, Director of the Trustworthy Software Ecosystems Lab @ Purdue University
“The Sigstore policy-controller is an incredible tool that helps developers and maintainers everywhere enable stronger software supply chain security policies like enforcing software signatures and attestations, and preventing critical or high CVEs. The availability of the new open source policy catalog is an exciting opportunity for the Sigstore community and beyond to start unlocking these benefits with a clear path to the enforcement of software supply chain security policies.” Priya Wadhwa, Software Engineer at Chainguard and member of the Sigstore Technical Steering Committee 
“When I recently learned about Cosign, Sigstore policy-controller was a natural fit to make sure that my container images are signed before actually being deployed in my Kubernetes clusters. It was easy to get started with, and yet powerful. I was able to leverage an advanced setup on Google Kubernetes Engine (GKE) with Workload Identity to securely connect Sigstore policy-controller to Google Artifact Registry and Cloud KMS (see associated blog post). Last but not least, the Sigstore community and contributors are very active on Slack and GitHub, they were eager to answer my questions to help me in my learning journey.” – Mathieu Benoit, CNCF Ambassador

Learn more 

If you are just starting to explore Sigstore and the policy-controller, check out these resources in Chainguard Academy and Unchained:

To get started with the policy catalog, visit the public repo here or watch this demo video that explores available policies:

If you are a Chainguard Enforce customer, you can use the policy catalog to set and enforce policies compatible with Sigstore policy-controller directly through the platform. Want to learn more about Chainguard Enforce and its rich policy enforcement and admission controller capabilities? Reach out to our team for a demo or start your 30-day free trial

Related articles