In part 2 of the series, we dived into the internals of the provenance document to understand its content and usage. In this part, we will explore the different SLSA levels for generating provenance and go through the different challenges you might face when adopting SLSA provenance. Finally, we will review the challenges in adopting SLSA provenance as an enterprise.
SLSA is a set of incrementally adoptable guidelines for supply chain security, established by industry consensus.
The SLSA framework is designed using different security levels. By breaking down CI/CD pipeline security to incrementally adoptable guidelines, software vendors are able to gradually improve the security posture of their pipelines. Let’s explore the three different levels defined for SLSA provenance generation and how each level improves the security of your pipeline.
To comply with SLSA provenance requirements for the first security level, the build process must generate a provenance document on a best-effort basis:
The build process MUST generate provenance that unambiguously identifies the output package by cryptographic digest and describes how that package was produced.
The goal is to generate the metadata of the build process. Although no security is gained per se, the availability of the provenance documents provides the context for the build process, allowing for better observability of the CI/CD pipeline.
To comply with SLSA provenance requirements for the second security level, consumers must be able to verify the authenticity and integrity of the provenance. In practical terms, the provenance must be signed during the build process.
Signing the provenance within the build process ensures:
Authenticity: Consumers MUST be able to validate the authenticity of the provenance attestation in order to:
Ensure integrity: Verify that the digital signature of the provenance attestation is valid and the provenance was not tampered with after the build.
Define trust: Identify the build platform and other entities that are necessary to trust in order to trust the artifact they produced.
To comply with SLSA provenance requirements for the third security level, it must be strongly resistant to forgery by specific build jobs. In practical terms, the provenance generation procedure and the private key used to sign the provenance must not be accessible to build steps of any jobs.
Generating and signing the provenance on the build platform level ensures the content of the provenance can be trusted regardless of the specific build it describes, i.e., the process is immune to modifications by an insider threat or a compromised developer account.
Note: the term “unforgeable” was introduced in SLSA v1.0 as a replacement for the “non-falsifiable” term.
Accuracy: Provenance MUST be strongly resistant to forgery by tenants.
Any secret material used for authenticating the provenance, (for example the signing key used to generate a digital signature) MUST be stored in a secure management system appropriate for such material and accessible only to the build service account.
Such secret material MUST NOT be accessible to the environment running the user-defined build steps.
Every field in the provenance MUST be generated or verified by the build platform in a trusted control plane.
As described above, SLSA provenance level 3 boils down to:
As of now, the only official open-source solution for provenance level 3 generation is using GitHub Actions. The SLSA project maintains the slsa-github-generator repository, which provides a solution for provenance generation to be used by open source projects.
In the following paragraphs, we will examine that solution and learn why it meets the requirements. To understand it, we first describe the different components that slsa-github-generator relies on to generate the provenance.
GitHub Actions is a continuous integration and continuous delivery (CI/CD) platform that allows you to automate your build, test, and deployment pipeline.
Workflows are defined using yaml files inside repositories. Each workflow defines the build steps that run upon its invocation.
OpenID Connect (OIDC) is an authentication standard that allows apps and websites to verify a user’s identity through their account with a trusted provider using a security token. When a workflow is invoked, GitHub generates an OIDC token that is associated with the workflow and signs it. As a result, the token functions as proof for the invoked workflow, with which it can authorize against external services, such as cloud providers or secret managers.
For example, you might want to limit access to a secret key stored on Google Cloud platform to a specific workflow in your repository. To do that, you first create a role with access to that secret. Then, configure a custom claim to verify the workflow:
job_workflow_ref:ORG_NAME/REPO_NAME/.github/workflows/WORKFLOW_FILE@ref
As a result, the cloud provider enforces that only OIDC tokens generated for this specific workflow will have access to the secret. The following diagram shows a simplified version of the authentication flow with such external services:
Workflows can trigger other workflows using the reusable workflows feature, allowing for modularity and flexibility within the build system. The reusable workflow runs in a separate context but also has access to the contextual information of the calling workflow. When a reusable workflow is invoked, GitHub generates an additional OIDC token associated with the invoked workflow. As a result, a reusable workflow can authorize against external services using its own identity.
Generating a distinct token for reusable workflow enables 3rd-party services, such as a secret manager, to restrict access to the reusable workflow. In addition, 3rd-party services, such as SigStore, can associate the signed document with the reusable workflow rather than the calling workflow.
The SigStore project provides a public endpoint for signing artifacts and attestations, using OIDC as its authorization mechanism. SigStore enables anyone to authorize the use of OIDC and sign their attestations. In addition to signing the attestation, SigStore also uploads the signed attestation to a public transparency log.
The following diagram shows a simplified version of the signing process of an attestation using SigStore and GitHub Actions:
A project generates provenance by invoking the reusable workflow from slsa-github-generator in the project build workflow, providing it with proper permissions and the subjects of the attestation:
Upon invocation, the reusable workflow runs the following steps to generate a trusted provenance:
The result is an unforgeable provenance:
To fully understand this, let’s view the situation from the attacker’s perspective. When a solution only meets the level 2 requirements, an attacker can execute the following attack:
With level 3, on the other hand, the attack flow is blocked on the third step: the repository has no control over the generated provenance and its signature. As a result, the generated provenance would point to the attacker’s branch rather than the main branch. Combined with branch protection, SLSA provenance level 3 prevents the attacker from deploying their malicious code without an approval from a legitimate user.
The set of solutions provided by the SLSA project enables:
But this is just the beginning of the story. Most of the software developed by enterprises is closed source and the requirements for the SDLC in enterprises are therefore different.
SigStore’s security model relies on the public transparency log. While having a transparency log improves the security for open-source projects, it is also a barrier for enterprises. Generating provenance using the standard SLSA tooling discloses private information, namely the provenance content, to the general public. This information may include the names of organizations, repositories, users and emails, as well as tags, commit messages, file names, hosted runners info and more.
A full integration of provenance into the CI/CD pipeline means blocking deployment in case the provenance verification fails. The SigStore verification model assumes that the verifier relies on multiple external entities for the verification of the attestation. By default, the verification process communicates with the public transparency log to verify the attestation. The result is that an enterprise relying on SigStore may not be able to deploy new code upon availability issues with the public SigStore cluster, including:
As a result, you cannot verify provenance documents if you are not online. This adds a bottleneck to your production delivery pipeline – a point of failure managed by an external service. There are plans in SigStore to support provenance “offline” verification, i.e., air-gapped verifying capabilities that do not rely on such external services. At this point, though, these capabilities are very limited and are not available out of the box.
Integrating provenance generation involves manually modifying your CI/CD workflows to trigger the provenance generation, specifying the inputs and adjusting it to the different technologies used in your pipelines.
As an example, let’s examine pushing a Docker container. Here are three examples of options for pushing a docker image, and each requires a different method to pass the resulting image as a provenance input:
In practice, enterprises often have thousands of different pipelines, each requires subtle changes to integrate provenance properly. As a result, fully integrating provenance into your pipeline may result in a huge load of work, involving multiple teams.
Moreover, SLSA currently provides a level 3 solution only for repositories hosted on GitHub that also use GitHub Actions as their CI.
Now that we understand that the public SigStore-based solution does not fit enterprise needs, we need to consider the alternative is setting up a solution from scratch.
The following table examines the alternatives to avoid using the public SigStore cluster:
Idea |
Pros |
Cons |
Set up a private SigStore cluster |
No private information disclosure. No need to rely on the availability of external services. |
Non-trivial setup and maintenance. Does not obviously scale to the enterprise needs. There’s still a fine amount of work managing the underlying PKI, e.g. key rotation, revocation, etc. |
Develop a proprietary security model |
Better fit to enterprise needs. Flexibility and customizability. |
Requires expertise in cryptography and security model design. High developmental and operational costs. |
Even if you decide to go with one of these alternatives, there are still three questions unanswered:
In our next blog post in the SLSA Provenance series we are going to address these questions and more.
Understanding all the challenges that enterprises may face when integrating provenance, Legit developed a novel solution that fits enterprise needs. We will introduce Legit’s Autonomous Provenance Generation service and see how an enterprise can integrate provenance without effort and without conflicting with the needs for information privacy and service independence.
Stay tuned!
Although it’s important to learn about these technologies, adopting them requires some expertise. Today, the SigStore project is a popular way to start integrating attestations and provenance into your CI/CD pipelines. Unfortunately, SigStore operates in an open-source minded approach, uploading your private information to public logs.
Legit Security provides a seamless solution for SLSA provenance generation that meets SLSA level 3 requirements: simply integrate your organization to generate provenance documents for your SCM (GitHub / GitLab / Bitbucket / Azure DevOps) without any extra action.
Contact Legit Security if you’re looking for an alternative that fits enterprise needs (complete data privacy, independency of your production environment on 3rd-party service, and more).