This is a self-evaluation of the SLSA v1.0 build level for Docker Official Images (DOI) GitHub Actions (GHA) Workflow trusted builder.
Builder ID | https://github.com/docker-library/meta/.github/workflows/build.yml@refs/heads/main |
---|
A subset of DOI builds run on the meta GHA workflow.
Applicable builds are limited to the following image platforms:
linux/amd64
linux/386
The list of all applicable images can be found in subset.txt.
The DOI build platform can be trusted to produce Build Level 3 artifacts on images that are built by the meta
GHA workflow due to the strengthened unforgeability and isolation controls for provenance generation as detailed in the following sections.
DOI GHA workflow builder is modeled around the GHA workflow build type.
The DOI build platform in its entirety extends beyond the GHA workflow, but we choose to limit the trusted boundary for this analysis to the DOI GHA workflow. In this model, the GHA workflow itself is the trusted control plane and all other platform automation outside it are considered untrusted external parameters and dependencies that are "to be verified" according to a set of expectations that we define as the source of truth for DOI builds.
Build platform components are defined according to the SLSA v1.0 spec terminology below.
The control plane for the DOI GHA workflow builder is the meta GHA workflow file.
This GHA workflow orchestrates each build stage and is operated by administrators that have privilege to modify the control plane. The workflow is made available to the public for transparency and is version controlled in git with branch protection controls requiring two person review by maintainers of the DOI build platform.
Provenance generation and signing is sufficiently isolated from the build environment through the use of separate GitHub-hosted runner VMs via jobs.
Access to signing operations is provided by OIDC authentication of the control plane (GHA workflow) to KMS managed keys that store key material in a Hardware Security Module (HSM). Only trusted jobs in the GHA workflow are provided access to the ID Token to obtain tokens for KMS signing. Specifically, the job that handles the build environment is NOT granted permission to request ID Tokens on behalf of the workflow. This provides sufficient security controls to ensure unforgeable provenance generation.
Use of the KMS is audited and alerts are in place for unauthorized access by entities outside of the DOI GHA workflow identity.
Build artifacts are passed between jobs in the workflow using a combination of workflow artifacts and job outputs.
Job outputs are treated as a trusted channel to distribute the cryptographic digest of artifacts so that each job can verify the integrity of build artifacts cached outside of the trusted builder boundary in workflow artifact storage.
In addition to what is defined by the GHA build type, all workflow inputs are considered external parameters for this build model.
These inputs are verified according to a set of expectations about them for authentic DOI builds. See #verifying-expectations-for-doi-builds.
The build environment is a job
within the DOI GHA workflow that is named build
.
The build job is isolated from the control plane and other jobs within the workflow with the use of GitHub-hosted runner virtual machines.
The build environment cannot influence provenance generation because provenance is generated by the control plane in a separate job.
Access to key material and signing operations is not permitted for the build environment through the use of job permissions.
The build
job is not granted id-token
permissions, therefore it cannot generate a workload identity token to authenticate with the signing KMS.
The minimum required resolved dependency for a DOI GHA workflow is the resolved git commit URI for the workflow run on the meta repository.
The official-images and meta-scripts repositories are dependencies for DOI builds and are git submodules in the meta repository. Therefore, the commit references for those repositories are obtained by the URI for the meta repository git commit.
Artifacts are output from the build system as OCI images. Images are stored in an OCI registry as build "outputs" that are later collected by a separate process that deploys them to the image architecture and library namespaces.
The provenance attestation generated by the trusted builder captures the cryptographic digest of the image as a subject of the predicate, such that if the image was modified after being output, the verification of the provenance attestation would fail.
To verify that the provenance of a DOI build is authentic, expectations for a DOI build must be defined and checked.
Expectations for provenance verification are defined by source.
The source of truth for DOI builds is defined by the official-images library manifest files. Library manifest files are managed by image maintainers and approved by platform administrators. Contents of the manifest file define a set of inputs for each Official Image build (e.g. source repository, explicit full git commit hash, Dockerfile path, etc.).
The combination of expectations from library manifest files and GHA workflow context can be used to verify an image's provenance to determine if the artifact is genuine.
💡 Tip: These generic steps are enumerated for informational purposes, see #verification-summary-attestations on how to verify a precomputed summary of provenance verification
-
Check SLSA build level
- Verify the signature of the provenance attestation DSSE envelope using the trust store published in Docker's TUF root
- Verify the SLSA build level that maps to the
builder.id
and public key used to verify the envelope signature is at leastSLSA_BUILD_LEVEL_3
in the trust store - Verify the statement's
subject
matches the digest and PURL of the target image - Verify the
predicateType
ishttps://slsa.dev/provenance/v1
-
Check expectations
- Verify the statement's
subject
platform is one of the applicable image platforms for thebuilder.id
- Verify that the
buildType
ishttps://github.com/actions/buildtypes/tree/main/workflow/v1
- Verify the external parameters
📝 Note: We can ignore all workflow inputs except for the
buildId
input (this is the metadata used to invoke the build)- Using the meta repository resolved dependency commit ref
- download the build metadata (
builds.json
) at the repository root - filter metadata for specific
buildId
- extract the
source.entry
data for verification
- download the build metadata (
- Lookup the official-images submodule commit ref from the meta repository resolved dependency
- Map the statement
subject
package name (e.g.pkg:docker/hello-world
) to the library manifest file (e.g. docker-library/official-images/library/hello-world) - Compare the contents of the library manifest file (source of truth) to the contents of the build metadata (obtained from
builds.json
)- Verify that
GitRepo
,GitCommit
,GitFetch
,Directory
, andFile
for the build match what is expected from the library manifest file⚠️ Warning: These values are often unique to the specific platform and tag of the image build and must be appropriately parsed and selected from the manifest - If
GitCommit
fails, calculate the reproducibleGitChecksum and verify it against the value in the build metadata📝 Note:
reproducibleGitChecksum
represents the build context by cryptographic digest of the source repository's Dockerfile path contents. In this case, the build is considered valid because the build context is the same for differentGitCommit
values. - Verify all tags for subject references in the statement match expected tags for the artifact as defined in the library manifest file
- Verify that
- Map the statement
- Using the meta repository resolved dependency commit ref
- Verify the statement's
The source repository build context for each build can be identified by a digest of the git archive contents at the specified GitRepo
, GitCommit
, GitFetch
, and Directory
for a DOI build. This value is known as the reproducibleGitChecksum
.
To calculate the value of reproducibleGitChecksum
:
Prerequisites:
git
version >= 2.40.0- tar scrubber to strip
uname
andgname
headers (e.g. tar-scrubber.go)
Steps:
- Clone the source repository at
GitRepo
from the library manifest file - Run
git archive
and scrub the tar output, usingGitCommit
andDirectory
from the library manifest filegit archive --format=tar --mtime='1970-01-01 00:00:00Z' <GitCommit>:<Directory> | go run tar-scrubber.go | sha256sum
Example:
git clone https://github.com/docker-library/hello-world.git
git archive --format=tar --mtime='1970-01-01 00:00:00Z' 3fb6ebca4163bf5b9cc496ac3e8f11cb1e754aee:amd64/hello-world | go run tar-scrubber.go | sha256sum
22266b0a36deee72428cffd00859ce991f1db101260999c40904ace7d634b788
Note that the output digest 22266b0a36deee72428cffd00859ce991f1db101260999c40904ace7d634b788
matches the value in builds.json
The DOI build process generates Verification Summary Attestations (VSA) to communicate that the image has been verified at the build level obtained by the builder that generated the artifact.
The VSA generation process verifies expectations for DOI build provenance as outlined in #steps-to-verify-doi-provenance by use of attestation verification tooling and Rego policy stored in Docker's TUF root.
Consumers of DOI need not implement the extensive verification process for provenance and instead can verify the VSA as a minimal summary of the verification process as performed by Docker.
The table below describes how Docker Official Images (DOI) meet the SLSA Build L3 (v1.0) (Supply-chain Levels for Software Artifacts Build Level 3 spec version 1.0) requirements.
Level | Requirement | Implementation |
---|---|---|
Build L1: Provenance exists | Software producer follows a consistent build process so that others can form expectations about what a “correct” build looks like. | The whole DOI build process is open, and there are strict rules that must be followed to be considered part of DOI. For example, dependencies should be pinned and digests checked when package managers are not used. For more details, see the docs on creating a new DOI |
Provenance exists describing how the artifact was built, including the build platform, build process, and top-level inputs. | DOI GHA workflow builds generate a provenance attestation by the trusted control plane in accordance with the official GitHub Actions buildType | |
Software producer distributes provenance to consumers, preferably using a convention determined by the package ecosystem. | Provenance attestations are distributed as standard OCI artifacts, and conform to open In-Toto and SLSA specifications | |
Build L2: Hosted build platform | Build platform runs on dedicated infrastructure, not an individual’s workstation, and the provenance is tied to that infrastructure through a digital signature. | GitHub Actions runs the build workloads, and workload identity is used to sign provenance. Build triggering (which does not affect the build output) is a process that runs on Jenkins |
Downstream verification of provenance includes validating the authenticity of the provenance. | A Verification Summary Attestation (VSA) is created from a version controlled and securely distributed policy that validates the authenticity of the build-time attestations | |
Build L3: Hardened builds | Build platform implements strong controls to prevent runs from influencing one another, even within the same project. | Each build is performed on a clean node isolated from all other workloads. Where caching is used, it is verified e2e using a trusted channel to transmit cryptographic digests. |
Build platform implements strong controls to prevent secret material used to sign the provenance from being accessible to the user-defined build steps. | Secret key material is held in Cloud KMS within HSMs and cannot be read by any process. Workload identity is used to authenticate with the KMS for the signing of attestations and is limited to trusted processes initiated by the control plane and isolated from the build environment. |