Skip to content

Latest commit

 

History

History
359 lines (269 loc) · 14 KB

SLSA.md

File metadata and controls

359 lines (269 loc) · 14 KB

SLSA

SLSA is a framework to guide developers and help them secure their software supply chain.

In this document we are describing how we incrementally reach SLSA level 4, and explain why we meet each criteria.

SLSA 1

SLSA level 1 does not do much, but helps us get on track to build a resilient system. We only have 2 requirements to satisfy.

All build steps were fully defined in some sort of “build script”. The only manual command, if any, was to invoke the build script.

We use a GitHub Workflow to execute all the CI steps.

The provenance is available to the consumer in a format that the consumer accepts. The format SHOULD be in-toto SLSA Provenance, but another format MAY be used if both producer and consumer agree and it meets all the other requirements.

We provide provenance using the SLSA github-actions-demo and attach it to the GitHub Release.

Things to notice

  • The attestation will not be uploaded to crates.io, but will live in GitHub release. This is not ideal and will complexify the process to verify it. Ideally all should be managed by cargo.
  • The attestation does not mention which commit was used to build the crate.
  • Following cosign's convention, we named the attestation trauma.${{ github.sha }}.att

SLSA 2

We keep adding to the security here, by requiring automated CI systems and introducing signing.

Every change to the source is tracked in a version control system that meets the following requirements:

  • [Change history] There exists a record of the history of changes that went into the revision. Each change must contain: the identities of the uploader and reviewers (if any), timestamps of the reviews (if any) and submission, the change description/justification, the content of the change, and the parent revisions.
  • [Immutable reference] There exists a way to indefinitely reference this particular, immutable revision. In git, this is the {repo URL + branch/tag/ref + commit ID}.

We are using git as our VCS, which meets these requirements, so we're good here ✅.

All build steps ran using some build service, not on a developer’s workstation.

We use GitHub Actions as the automated build system.

The provenance’s authenticity and integrity can be verified by the consumer. This SHOULD be through a digital signature from a private key accessible only to the service generating the provenance.

For this requirement, we are using cosign to sign the provenance attestation. The attestation signature will be attached to the GitHub release, next to the attestation itself.

Here is the trauma public key trauma.pub:

-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE9REilH9skU+RaK9Pcs3PhAKOSsjH
hSt+Gu73ChvvFNZd5u9LDU7BpdJUG5vKBVMaHnOlPY1Az/dC2DxqQa5iRQ==
-----END PUBLIC KEY-----

The signature could be verified using cosign as well:

$ cosign verify-blob --key trauma.pub --signature trauma.sig trauma.att
Verified OK

And we're good here.

The data in the provenance MUST be obtained from the build service (either because the generator is the build service or because the provenance generator reads the data directly from the build service).

Regular users of the service MUST NOT be able to inject or alter the contents, except as noted below.

The following provenance fields MAY be generated by the user-controlled build steps:

  • The output artifact hash from Identifies Artifact. Reasoning: This only allows a “bad” build to falsely claim that it produced a “good” artifact. This is not a > security problem because the consumer MUST accept only “good” builds and reject “bad” builds.
  • The “reproducible” boolean and justification from Reproducible.

We are generating the provenance through a custom action as a step in our GitHub Workflow. It is not a service offered by GitHub Actions itself. Therefore we do not meet the criteria.

Things to notice

  • It is best practice to add a password to the signing key, but it was not required to be SLSA 2 compliant.
  • Could probably further improve the verification workflow by using rekor/fulcio.
  • Using the GitHub OIDC provider would also be a nice addition, but this feature is still marked as experimental at the time of writing. See the openid signing reference for more information.

SLSA 3

Now we are getting serious!

Every change in the revision’s history has at least one strongly authenticated actor identity (author, uploader, reviewer, etc.) and timestamp. It must be clear which identities were verified, and those identities must use two-step verification or similar. (Exceptions noted below.)

Here are the elements allowing us to match this requirement:

  • We are using GitHub.
  • We can identify the author of a pull-request.
  • A GitHub account is required to submit a pull-request.
  • This repository is not in an organization, BUT 2FA is enabled.
  • This repository requires pull-request to add changes and the main branch has been protected.

So we should be in compliance here.

Source - Retained indefinitely (18 months for SLSA 3)

The revision and its change history are preserved indefinitely and cannot be deleted, except when subject to an established and transparent policy for obliteration, such as a legal or policy requirement.

[Immutable history] It must not be possible for persons to delete or modify the history, even with multi-party approval, except by trusted platform admins with two-party approval following the obliterate policy.

Since we are using GitHub we think we are in compliance with this item. Besides git does not allow to modify a commit without altering the child commits.

The build definition and configuration is defined in text files, stored in a version control system, and is executed by the build service.

Our build operations are defined in the our GitHub workflow ci-rust.yml.

The build service ensured that the build steps ran in an ephemeral environment, such as a container or VM, provisioned solely for this build, and not reused from a prior build.

github hosted runners are ephemeral VMs. Therefore each job will be run in a different VM, but not each step. So if we follow the definition strictly, we are not in compliance here. But since our jobs are isolated from each others, we may still be good.

The build service ensured that the build steps ran in an isolated environment free of influence from other build instances, whether prior or concurrent.

  • It MUST NOT be possible for a build to access any secrets of the build service, such as the provenance signing key.
  • It MUST NOT be possible for two builds that overlap in time to influence one another.
  • It MUST NOT be possible for one build to persist or influence the build environment of a subsequent build.
  • Build caches, if used, MUST be purely content-addressable to prevent tampering.

We think we are in compliance here, but the secrets are usable to each step of the workflow, even though the contant cannot be viewed direclty.

GitHub actions lets admin share secrets either at the organization level, either at the repository level. This part will require more digging to see if the way GitHub Actions is implemented is compliant or not.

Provenance cannot be falsified by the build service’s users.

NOTE: This requirement is a stricter version of Service Generated.

  • The provenance signing key MUST be stored in a secure key management system accessible only to the build service account.
  • The provenance signing key 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 service in a trusted control plane.
  • The user-controlled build steps MUST NOT be able to inject or alter the contents, except as noted below.

We clearly don't meet this criteria since our signing key is stored as a git secret, therefore accessible anywhere throughout the workflow.

Things to notice

  • Although we can identify the authors of a pull-request, commit signing is not required.

  • Some definitions could use some clarification.

  • There is no standard naming and each CI system uses different words to mean the same thing, or the same words to mean different things.

    GitHub Tekton
    Workflow Pipeline
    Job Task
    Step Step

SLSA 4

Since we believe we are SLSA 3 compliant, let's continue this excercise and see if we can reach level 4.

Every change in the revision’s history was agreed to by two trusted persons prior to submission, and both of these trusted persons were strongly authenticated.

We are failing this requirement since the repository only has 1 maintainer.

The build output cannot be affected by user parameters other than the build entry point and the top-level source location. In other words, the build is fully defined through the build script and nothing else.

We are using Github Actions in this manner. The only parameters are information coming from the source to build itself (commit sha, repository name, etc.)

All transitive build steps, sources, and dependencies were fully declared up front with immutable references, and the build steps ran with no network access.

All the dependencies are strongly specified in the Cargo.lock file.

However the dependencies are being fetched from crates.io every time the build runs (even though we are using caching), so we may be failing this requirement.

A way to satisfy this requirement would be to use cargo vendor to vendor all dependencies locally.

Build - Reproducible (best effort)

Re-running the build steps with identical input artifacts results in bit-for-bit identical output. Builds that cannot meet this MUST provide a justification why the build cannot be made reproducible.

We think we are doing good on this one, mainly dur to the use of the lock file, but this item would require deeper investigation.

Provenance records all build dependencies that were available while running the build steps. This includes the initial state of the machine, VM, or container of the build worker.

We may provide an SBOM, but that does not seem to be enough to satisfy this criteria.

The system meets some TBD baseline security standard to prevent compromise. (Patching, vulnerability scanning, user isolation, transport security, secure boot, machine identity, etc. Perhaps NIST 800-53 or a subset thereof.)

This criteria seems to only apply does services which are deployed somewhere, therefore not apply here.

All physical and remote access must be rare, logged, and gated behind multi-party approval.

This criteria seems to only apply does services which are deployed somewhere, therefore not apply here.

Only a small number of platform admins may override the guarantees listed here. Doing so MUST require approval of a second platform admin.

Since we have one admin, we're also failing this criteria. But they are talking about a platform admin, so it may no apply here.

Things to notice

  • A lot of projects/tools/libraries only have one maintainer. Therefore it rules them out from being SLSA 4 compliant right away.
  • Such a high level of details in the provenance seems ideal, but it looks like such a tool does not exist yet.
  • The criteria in the "Common" category seem to only applied to deployed services.