Home
Unchained
Open Source Blog

Chainguard open sources new policy catalog for Sigstore policy-controller

Erin Glass, Product Manager and Ville Aikas, Distinguished Engineer

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.


#############################################################################################
# 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.


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.

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.


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.

“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 (

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.

Share

Ready to Lock Down Your Supply Chain?

Talk to our customer obsessed, community-driven team.

Get Started