Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 5 additions & 19 deletions how-our-pipeline-maps-to-nist-and-slsa/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
<meta name="robots" content="noindex, nofollow">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>NIST SP 800-204C, 800-204D and SLSA: Our Release Pipeline</title>
<title>How our release pipeline maps to NIST and SLSA (draft)</title>
<meta name="description" content="DRAFT v0.3.0: how the new release pipeline maps to NIST SP 800-204C and 800-204D and SLSA. Not published.">
<meta property="og:title" content="NIST SP 800-204C, 800-204D and SLSA: Our Release Pipeline">
<meta property="og:title" content="How our release pipeline maps to NIST and SLSA (draft)">
<meta property="og:description" content="DRAFT v0.3.0: how the new release pipeline maps to NIST SP 800-204C and 800-204D and SLSA. Not published.">
<meta property="og:url" content="https://fosterstack.com/how-our-pipeline-maps-to-nist-and-slsa/">
<meta property="og:type" content="website">
Expand Down Expand Up @@ -89,11 +89,11 @@
</header>
<main>
<h1>How the v0.3.0 release pipeline maps to NIST and SLSA</h1>
<p>This page puts each stage of the new release pipeline next to the NIST practice it was designed against. It says where a stage only partly implements a practice.</p>
<p>If you have to explain our release pipeline to a security reviewer, start here. This page puts each stage of the new release pipeline next to the NIST practice it was designed against, and says where a stage only partly implements a practice.</p>
<p class="muted-note"><strong>DRAFT for v0.3.0, not published and never merged before v0.3.0 is live.</strong> <code>[TO-VERIFY]</code> marks anything not yet run against a real release.</p>
<p>This is guidance we followed when designing the pipeline. It is not a certification.</p>
<h2>Stage by stage</h2>
<p>"Signs" means the stage records what it did and signs it with a short-lived key, under its own workflow identity, logged in a public transparency log. <code>[TO-VERIFY]</code> against the workflow files at the v0.3.0 tag.</p>
<p>The six stages are described step by step on <a href="/how-we-build/">how we build</a>. "Signs" means the stage records what it did and signs it with a short-lived key, under its own workflow identity, logged in a public transparency log. <code>[TO-VERIFY]</code> against the workflow files at the v0.3.0 tag.</p>
<table>
<thead><tr><th>Stage</th><th>What it does</th><th>NIST practice</th><th>How much</th></tr></thead>
<tbody>
Expand All @@ -105,23 +105,9 @@ <h2>Stage by stage</h2>
<tr><td>Release</td><td><code>[TO-VERIFY]</code> Verifies every stage's signature together, then publishes the same digests.</td><td><code>[TO-VERIFY]</code></td><td><code>[TO-VERIFY]</code></td></tr>
</tbody>
</table>
<p>Our wording: signed at every stage, verified together at release.</p>
<p>Our wording: signed at every stage, verified together at release. <code>[TO-VERIFY: pipeline]</code></p>
<h2>SLSA</h2>
<p><code>[TO-VERIFY]</code> The SLSA Build level we assess v0.3.0 at. We claim Level 3 for the Build stage only after a test shows that a malicious build step cannot produce provenance the release step accepts. Until that test has passed, this page says nothing about Level 3.</p>
<h2>CISA Secure by Design</h2>
<p><code>[TO-VERIFY]</code> This section is a draft and is not published. It lines up the seven goals of CISA's Secure by Design materials with what the product does. CISA does not endorse any company or product, and this page is not a statement by CISA. We do not claim to meet any of these goals until each row below has been checked against the v0.3.0 release.</p>
<table>
<thead><tr><th>Goal</th><th>What the product does</th><th>Status</th></tr></thead>
<tbody>
<tr><td>Multi-factor authentication</td><td><code>[TO-VERIFY]</code> The server has one optional shared HTTP Basic login (plus an optional read-only one). It has no multi-factor sign-in and no single sign-on.</td><td><code>[TO-VERIFY]</code></td></tr>
<tr><td>Default passwords</td><td><code>[TO-VERIFY]</code> No password ships in the product. Logins come only from settings you provide at start, and a half-set pair is refused.</td><td><code>[TO-VERIFY]</code></td></tr>
<tr><td>Classes of vulnerability</td><td><code>[TO-VERIFY]</code> The server is written in Go, with no C imports and cgo off. Request paths are checked twice against directory traversal. There is no SQL.</td><td><code>[TO-VERIFY]</code></td></tr>
<tr><td>Security patches</td><td><code>[TO-VERIFY]</code> A daily rescan for newly disclosed vulnerabilities, and a 48-hour fix target (best effort). The server does not update itself, by design. Whether automatic patch releases are live at v0.3.0: <code>[TO-VERIFY]</code>.</td><td><code>[TO-VERIFY]</code></td></tr>
<tr><td>Vulnerability disclosure policy</td><td><code>[TO-VERIFY]</code> A private reporting channel exists on GitHub. Whether the policy allows testing, promises no legal action, sets a scope and gives a disclosure time: <code>[TO-VERIFY]</code>.</td><td><code>[TO-VERIFY]</code></td></tr>
<tr><td>CVE records</td><td><code>[TO-VERIFY]</code> When we issue a CVE, and the fields it carries.</td><td><code>[TO-VERIFY]</code></td></tr>
<tr><td>Evidence of intrusions</td><td><code>[TO-VERIFY]</code> Structured logs and metrics. The server writes no per-request access log and does not log or count failed logins. Whether that changes at v0.3.0: <code>[TO-VERIFY]</code>.</td><td><code>[TO-VERIFY]</code></td></tr>
</tbody>
</table>
<h2>What this page does not say</h2>
<ul>
<li>No stage here is certified by anyone.</li>
Expand Down
50 changes: 28 additions & 22 deletions how-we-build/index.html
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta name="robots" content="noindex, nofollow">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>How FosterStack Cache is built and signed</title>
<meta name="description" content="How each release is built in CI, checked, scanned, signed and published, what files you get to verify it, and what we do not claim.">
<meta name="description" content="DRAFT v0.3.0, not published: how a FosterStack Cache release is built, signed and checked, and how to verify it yourself.">
<meta property="og:title" content="How FosterStack Cache is built and signed">
<meta property="og:description" content="How each release is built in CI, checked, scanned, signed and published, what files you get to verify it, and what we do not claim.">
<meta property="og:description" content="DRAFT v0.3.0, not published: how a FosterStack Cache release is built, signed and checked, and how to verify it yourself.">
<meta property="og:url" content="https://fosterstack.com/how-we-build/">
<meta property="og:type" content="website">
<meta property="og:site_name" content="FosterStack">
Expand Down Expand Up @@ -90,45 +91,50 @@
</header>
<main>
<h1>How FosterStack Cache is built and signed</h1>
<p class="lede">Every release is built by an automated pipeline, checked, signed, and published with files you can verify yourself. This page says what that means today.</p>
<p class="lede">You are about to run our software inside your build pipeline. How do you know the files you run are the ones we built? Every release is signed and checked at every step, and you can verify it yourself. <code>[TO-VERIFY: pipeline: signed and checked at every stage of the v0.3 chain]</code> This page says how.</p>
<p class="muted-note"><strong>DRAFT for v0.3, private preview, not published and never merged before v0.3.0 is live.</strong> <code>[TO-VERIFY: source]</code> marks a fact that must be checked against the v0.3 release; the source (cache, pipeline or payments) is named in the marker.</p>

<h2>We do it to our own pipeline first</h2>
<p>We started with a build cache, and we secure our own release pipeline the same way before we ask you to run it. <code>[TO-VERIFY: pipeline: the v0.3 chain, secured before the product ships]</code></p>

<h2>Releases are built only in CI</h2>
<p>No release file is ever made on a person's laptop, ours included. A release starts when a signed tag is pushed, and there is no manual release path. That is what makes the signatures mean something: nobody can forge a release that GitHub's own build machines never built.</p>
<p>No release file is ever made on a person's laptop, ours included. A release starts when a signed tag is pushed, and there is no manual release path. That is what lets the signatures mean something: a release that our CI workflow did not build does not carry its signature. <code>[TO-VERIFY: pipeline: the signing identity is pinned to the release workflow and tag; no manual release path in v0.3]</code></p>

<h2>The steps a release goes through</h2>
<p>Signed at every stage, verified together at release. Each stage signs its own statement about the exact files, and the Release stage verifies them all together. A signature shows who signed these exact files; it does not show the software has no bugs. <code>[TO-VERIFY: pipeline: each v0.3 stage signs its own statement; the Release stage verifies all together]</code></p>
<ol class="steps">
<li><strong>Source check.</strong> The tag and the commit must be signed by an allowed signer, sit on the main branch, and have every required check green.</li>
<li><strong>Build.</strong> The binaries are built, with checksums and a software bill of materials for each archive.</li>
<li><strong>Container images.</strong> Each image is assembled once, from the unmodified distroless base plus one binary.</li>
<li><strong>Reproducibility check.</strong> The image is assembled a second time on a separate machine. The results must be identical, or the release fails.</li>
<li><strong>Scans and tests.</strong> Every scanner on our list runs against the exact images. A finding blocks the release unless a published VEX statement explains why it does not apply. The Gradle and Maven acceptance tests run against the same images.</li>
<li><strong>Authorization.</strong> One step checks that every earlier step produced signed proof for these exact files. Anything missing stops the release.</li>
<li><strong>Publish.</strong> The published images are the same digests that were scanned and tested, promoted without a rebuild, and checked again the way a customer would check them.</li>
<li><strong>Source check.</strong> The tag and the commit must be signed by an allowed signer, sit on the main branch, and have every required check green. <code>[TO-VERIFY: pipeline: v0.3 source admission unchanged from v0.2.2]</code></li>
<li><strong>Build.</strong> The binaries and the image's packages are built once. The image is assembled from those signed packages, with no base image. <code>[TO-VERIFY: cache: melange packages, apko image, no base image]</code></li>
<li><strong>Sign.</strong> A separate stage, with its own identity, records the build and signs it. <code>[TO-VERIFY: pipeline: the Sign boundary stage; a distinct certificate subject for each stage, visible in the cosign output]</code></li>
<li><strong>Rebuild.</strong> The image is assembled again, independently, on a separate machine. The digests must be identical, or the release fails. <code>[TO-VERIFY: pipeline: the Rebuild stage runs on a separate runner and identity, sharing no cache or inputs with Build]</code></li>
<li><strong>Check.</strong> The scanners we list (the list is in the repository) run against the exact images, and each signs its verdict for those digests. A finding blocks the release unless a published VEX statement explains why it does not apply. The Gradle and Maven acceptance tests run against the same images. <code>[TO-VERIFY: pipeline: scanner list and acceptance suites at v0.3]</code></li>
<li><strong>Release.</strong> One step verifies every earlier signature together. Anything missing stops the release. Then the same digests are published, promoted without a rebuild, and checked again the way a customer would check them. <code>[TO-VERIFY: pipeline: the Release job runs the same commands as the verify page]</code></li>
</ol>
<p class="muted-note">The full description, as the pipeline actually runs, is in <a href="https://github.com/fosterstack/cache/blob/main/RELEASING.md">RELEASING.md</a>.</p>
<p class="muted-note">The full description, as the pipeline actually runs, is in <a href="https://github.com/fosterstack/cache/blob/main/RELEASING.md">RELEASING.md</a>. <code>[TO-VERIFY: pipeline: RELEASING.md matches the v0.3 chain]</code></p>

<h2>What you get with each release</h2>
<ul class="trust">
<li>Container images on GitHub's registry, signed without a stored key (Sigstore), with build provenance.</li>
<li>Plain binaries and a <code>checksums.txt</code> with its own signature file.</li>
<li>A software bill of materials (SBOM) for each binary archive.</li>
<li>A VEX file saying which known vulnerabilities do and do not affect the release.</li>
<li>A <code>release-manifest.json</code> listing every file and its digest.</li>
<li>Container images on GitHub's registry, signed without a stored key (Sigstore), with build provenance. <code>[TO-VERIFY: pipeline/cache: v0.3 image signing and provenance]</code></li>
<li>Plain binaries and a <code>checksums.txt</code> with its own signature file. <code>[TO-VERIFY: cache fix A #276: which files the signed checksums list covers]</code></li>
<li>A software bill of materials (SBOM) for each binary archive. <code>[TO-VERIFY: cache: v0.3 release assets]</code></li>
<li>A VEX file saying which known vulnerabilities do and do not affect the release. <code>[TO-VERIFY: cache: v0.3 release assets]</code></li>
<li>A <code>release-manifest.json</code> listing every file and its digest. <code>[TO-VERIFY: cache: manifest layout at v0.3]</code></li>
</ul>
<p>All of it is public. You do not need an account or a purchase to check any of it. The commands are under "Verifying a release" in <a href="https://github.com/fosterstack/cache/blob/main/RELEASING.md">RELEASING.md</a>.</p>
<p>All of it is public. You do not need an account or a purchase to check any of it. The commands are on <a href="/verify-a-release/">verify a release yourself</a>.</p>

<h2>Kept patched</h2>
<p>The current release's images are scanned again every day, so a vulnerability disclosed against something we already shipped raises an issue without anyone having to remember to look.</p>
<p>The current release's images are scanned again every day, so a vulnerability disclosed against something we already shipped raises an issue without anyone having to remember to look. We keep it patched. <code>[TO-VERIFY: cache/ops: the daily rescan; "kept patched" only after the first automatic patch release has been cut; the brief also says "new or abandoned upstream": that needs a written scope before a page can say it]</code></p>

<h2>What we do not claim</h2>
<ul class="trust">
<li>Vulnerable dependencies fixed fast — our target is 48 hours from disclosure (<a href="https://github.com/fosterstack/cache/blob/main/SECURITY.md">the scope is in SECURITY.md</a>).</li>
<li>Vulnerable dependencies fixed fast: our target is 48 hours from disclosure (<a href="https://github.com/fosterstack/cache/blob/main/SECURITY.md">the scope is in SECURITY.md</a>).</li>
<li>A signature shows who signed these exact files. It does not show the software has no bugs, and it is not a certification by anyone.</li>
<li>The paid tiers are not built. Everything here is the free MIT core.</li>
</ul>

<div class="cta-row">
<a class="btn" href="https://github.com/fosterstack/cache">FosterStack Cache on GitHub</a>
<a class="btn btn-secondary" href="/">FosterStack home</a>
<a class="btn" href="/verify-a-release/">Verify a release yourself</a>
<a class="btn btn-secondary" href="/how-our-pipeline-maps-to-nist-and-slsa/">How each stage maps to NIST and SLSA</a>
</div>
</main>
<footer>
Expand Down
6 changes: 3 additions & 3 deletions verify-a-release/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@
</header>
<main>
<h1>Verify a FosterStack Cache release yourself</h1>
<p>Each stage of a release is signed on its own, and the signatures are verified together at release. These commands check that yourself, using only <code>cosign</code>, <code>gh</code> and <code>jq</code>.</p>
<p>You should not have to take our word for what you run. Each stage of a release is signed on its own, and the signatures are verified together at release. <code>[TO-VERIFY: pipeline]</code> These commands check the final signature, how the image was built, its parts list and what it was assembled from, using only <code>cosign</code>, <code>gh</code> and <code>jq</code>.</p>
<p class="muted-note"><strong>DRAFT for v0.3.0, not published and never merged before v0.3.0 is live.</strong> <code>[TO-VERIFY]</code> marks anything not yet run against a real release.</p>
<p>Use the image by digest for <code>&lt;IMAGE_REF&gt;</code>. There are two images; run every step for each. <code>[TO-VERIFY]</code> which two variants.</p>
<h2 id="verify-container-image-signature-cosign">1. The signature and who signed it</h2>
Expand All @@ -100,7 +100,7 @@ <h2>2. The digest is the one in the release</h2>
<pre tabindex="0"><code># [TO-VERIFY] file name and layout
gh release download &lt;TAG&gt; --repo fosterstack/cache -p release-manifest.json
jq -r '.images[] | "\(.variant) \(.digest)"' release-manifest.json</code></pre>
<p>Every statement names the image by digest, never by tag. The digest you verified should match this list.</p>
<p>Every statement names the image by digest, never by tag. <code>[TO-VERIFY: pipeline]</code> The digest you verified should match this list.</p>
<h2>3. How it was built</h2>
<pre tabindex="0"><code># [TO-VERIFY] signer workflow
gh attestation verify oci://&lt;IMAGE_REF&gt; --repo fosterstack/cache \
Expand All @@ -117,7 +117,7 @@ <h2>5. What the image was assembled from</h2>
cosign verify-attestation &lt;IMAGE_REF&gt; --type '&lt;INPUTS_TYPE&gt;' ... | jq '&lt;FILTER&gt;'</code></pre>
<h2>What this proves</h2>
<ul>
<li>A valid signature proves who signed these exact bytes.</li>
<li>A valid signature proves who signed these exact files.</li>
<li>Provenance proves which workflow and run produced them.</li>
<li>It does not prove the software has no bugs.</li>
</ul>
Expand Down
Loading