Skip to content

Commit 80b546c

Browse files
committed
security: enforce supply chain gates
1 parent f4e6501 commit 80b546c

16 files changed

Lines changed: 3596 additions & 43 deletions

.github/workflows/codeql.yml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name: CodeQL
2+
3+
on:
4+
pull_request:
5+
push:
6+
branches: [main, security]
7+
schedule:
8+
- cron: "17 3 * * 1"
9+
workflow_dispatch:
10+
11+
permissions:
12+
contents: read
13+
security-events: write
14+
15+
jobs:
16+
analyze:
17+
name: Analyze Rust
18+
runs-on: ubuntu-latest
19+
steps:
20+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
21+
- name: Initialize CodeQL
22+
uses: github/codeql-action/init@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4
23+
with:
24+
languages: rust
25+
build-mode: none
26+
- name: Analyze
27+
uses: github/codeql-action/analyze@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4

.github/workflows/fuzz.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ jobs:
3636
with:
3737
toolchain: nightly
3838
- name: Install cargo-fuzz
39-
run: cargo install cargo-fuzz --locked
39+
run: cargo install cargo-fuzz --version 0.13.2 --locked
4040
- name: Run bounded ASan fuzzing
4141
run: |
4242
cargo fuzz run --sanitizer address --target x86_64-unknown-linux-gnu "${{ matrix.target.name }}" -- \

.github/workflows/labels.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ jobs:
1515
sync:
1616
runs-on: ubuntu-latest
1717
steps:
18-
- uses: actions/checkout@v7
19-
- uses: crazy-max/ghaction-github-labeler@v6
18+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
19+
- uses: crazy-max/ghaction-github-labeler@548a7c3603594ec17c819e1239f281a3b801ab4d # v6
2020
with:
2121
yaml-file: .github/labels.yml
2222
# Set to true only after confirming the manifest is complete —

.github/workflows/release-prepare.yml

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,48 @@ jobs:
4141
needs: validate-version
4242
uses: ./.github/workflows/test.yml
4343

44+
sbom:
45+
name: Generate release SBOM
46+
needs: validate-version
47+
runs-on: ubuntu-latest
48+
steps:
49+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
50+
51+
- name: Install Rust
52+
uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4 # stable
53+
54+
- name: Stamp release source and generate CycloneDX SBOM
55+
env:
56+
VERSION: ${{ needs.validate-version.outputs.version }}
57+
run: |
58+
set -euo pipefail
59+
export SOURCE_DATE_EPOCH="$(git log -1 --format=%ct "$GITHUB_SHA")"
60+
bash scripts/ci/stamp_version.sh "$VERSION"
61+
cargo install cargo-cyclonedx --version 0.5.9 --locked
62+
cargo cyclonedx \
63+
--manifest-path nodedb/Cargo.toml \
64+
--format json \
65+
--spec-version 1.5 \
66+
--all-features \
67+
--target all \
68+
--override-filename nodedb-${VERSION}-sbom.cdx
69+
test -f nodedb/nodedb-${VERSION}-sbom.cdx.json
70+
python3 -m json.tool nodedb/nodedb-${VERSION}-sbom.cdx.json > /dev/null
71+
72+
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
73+
with:
74+
name: nodedb-sbom
75+
path: nodedb/nodedb-${{ needs.validate-version.outputs.version }}-sbom.cdx.json
76+
retention-days: 14
77+
4478
build-server:
4579
name: Build server (${{ matrix.label }})
4680
needs: [validate-version, ci]
4781
runs-on: ${{ matrix.runs-on }}
82+
permissions:
83+
contents: read
84+
id-token: write
85+
attestations: write
4886
strategy:
4987
fail-fast: false
5088
matrix:
@@ -56,14 +94,14 @@ jobs:
5694
target: aarch64-unknown-linux-gnu
5795
label: linux-arm64
5896
steps:
59-
- uses: actions/checkout@v7
97+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
6098

6199
- name: Install Rust
62-
uses: dtolnay/rust-toolchain@stable
100+
uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4 # stable
63101
with:
64102
targets: ${{ matrix.target }}
65103

66-
- uses: Swatinem/rust-cache@v2
104+
- uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
67105
with:
68106
prefix-key: server-${{ matrix.target }}
69107

@@ -87,23 +125,30 @@ jobs:
87125
tar czf nodedb-${{ needs.validate-version.outputs.version }}-${{ matrix.label }}.tar.gz nodedb
88126
ls -lh nodedb-*.tar.gz
89127
128+
- name: Attest build provenance
129+
uses: actions/attest-build-provenance@977bb373ede98d70efdf65b84cb5f73e068dcc2a # v3
130+
with:
131+
subject-path: |
132+
target/${{ matrix.target }}/release/nodedb
133+
target/${{ matrix.target }}/release/nodedb-${{ needs.validate-version.outputs.version }}-${{ matrix.label }}.tar.gz
134+
90135
# Two artifacts per arch: the tarball ships in the GitHub Release, the
91136
# bare binary is the Docker build context. Same bytes, different shape.
92-
- uses: actions/upload-artifact@v7
137+
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
93138
with:
94139
name: server-${{ matrix.label }}
95140
path: target/${{ matrix.target }}/release/nodedb-*.tar.gz
96141
retention-days: 14
97142

98-
- uses: actions/upload-artifact@v7
143+
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
99144
with:
100145
name: binary-${{ matrix.label }}
101146
path: target/${{ matrix.target }}/release/nodedb
102147
retention-days: 14
103148

104149
summary:
105150
name: Release instructions
106-
needs: [validate-version, build-server]
151+
needs: [validate-version, build-server, sbom]
107152
runs-on: ubuntu-latest
108153
steps:
109154
- name: Write summary

.github/workflows/release-validate.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,12 @@ jobs:
3030
version: ${{ steps.version.outputs.version }}
3131
is_full_release: ${{ steps.version.outputs.is_full_release }}
3232
steps:
33-
- uses: actions/checkout@v7
33+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
3434
with:
3535
ref: ${{ inputs.ref }}
3636

3737
- name: Install Rust
38-
uses: dtolnay/rust-toolchain@stable
38+
uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4 # stable
3939

4040
- name: Validate tag against Cargo.toml
4141
id: version

.github/workflows/release.yml

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -84,12 +84,12 @@ jobs:
8484
runs-on: ubuntu-latest
8585
environment: crates.io
8686
steps:
87-
- uses: actions/checkout@v7
87+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
8888
with:
8989
ref: ${{ inputs.tag }}
9090

9191
- name: Install Rust
92-
uses: dtolnay/rust-toolchain@stable
92+
uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4 # stable
9393

9494
- name: Install system deps
9595
run: |
@@ -204,12 +204,12 @@ jobs:
204204
label: arm64
205205
binary: binary-linux-arm64
206206
steps:
207-
- uses: actions/checkout@v7
207+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
208208
with:
209209
ref: ${{ inputs.ref || inputs.tag }}
210210

211211
- name: Download prebuilt binary
212-
uses: actions/download-artifact@v8
212+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
213213
with:
214214
name: ${{ matrix.binary }}
215215
run-id: ${{ inputs.prepare_run_id }}
@@ -220,16 +220,16 @@ jobs:
220220
run: chmod +x ./binctx/nodedb
221221

222222
- name: Set up Docker Buildx
223-
uses: docker/setup-buildx-action@v4
223+
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4
224224

225225
- name: Log in to Docker Hub
226-
uses: docker/login-action@v4
226+
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4
227227
with:
228228
username: ${{ secrets.DOCKERHUB_USERNAME }}
229229
password: ${{ secrets.DOCKERHUB_TOKEN }}
230230

231231
- name: Build and push platform image
232-
uses: docker/build-push-action@v7
232+
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7
233233
with:
234234
context: .
235235
build-contexts: binary=./binctx
@@ -256,7 +256,7 @@ jobs:
256256
runs-on: ubuntu-latest
257257
steps:
258258
- name: Log in to Docker Hub
259-
uses: docker/login-action@v4
259+
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4
260260
with:
261261
username: ${{ secrets.DOCKERHUB_USERNAME }}
262262
password: ${{ secrets.DOCKERHUB_TOKEN }}
@@ -283,21 +283,29 @@ jobs:
283283
contents: write
284284
actions: read
285285
steps:
286-
- uses: actions/checkout@v7
286+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
287287
with:
288288
ref: ${{ inputs.tag }}
289289

290290
- name: Download binary artifacts
291-
uses: actions/download-artifact@v8
291+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
292292
with:
293293
pattern: "server-*"
294294
run-id: ${{ inputs.prepare_run_id }}
295295
github-token: ${{ github.token }}
296296
path: ./artifacts
297297
merge-multiple: true
298298

299+
- name: Download SBOM artifact
300+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
301+
with:
302+
name: nodedb-sbom
303+
run-id: ${{ inputs.prepare_run_id }}
304+
github-token: ${{ github.token }}
305+
path: ./artifacts
306+
299307
- name: Create GitHub Release
300-
uses: softprops/action-gh-release@v3
308+
uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3
301309
with:
302310
tag_name: ${{ inputs.tag }}
303311
name: NodeDB ${{ needs.validate-version.outputs.version }}
@@ -325,7 +333,7 @@ jobs:
325333
# guarded only by the `notify` input: leave `notify: false` when re-dispatching
326334
# already-announced releases, or you will double-post.
327335
steps:
328-
- uses: actions/checkout@v7
336+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
329337
with:
330338
ref: ${{ inputs.tag }}
331339
fetch-depth: 0

.github/workflows/secrets.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
name: Secret scan
2+
3+
on:
4+
pull_request:
5+
push:
6+
branches: [main, security]
7+
schedule:
8+
- cron: "29 3 * * 1"
9+
workflow_dispatch:
10+
11+
permissions:
12+
contents: read
13+
14+
jobs:
15+
gitleaks:
16+
name: Gitleaks history scan
17+
runs-on: ubuntu-latest
18+
steps:
19+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
20+
with:
21+
fetch-depth: 0
22+
- name: Install Gitleaks
23+
run: go install github.com/gitleaks/gitleaks/v8@v8.30.0
24+
- name: Scan Git history
25+
run: gitleaks git --redact --verbose

.github/workflows/supply-chain.yml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
name: Supply Chain
2+
3+
on:
4+
pull_request:
5+
branches: [main, security]
6+
paths:
7+
- "**/Cargo.toml"
8+
- "**/Cargo.lock"
9+
- supply-chain/**
10+
- deny.toml
11+
- scripts/ci/check_advisory_ignores.py
12+
- .github/workflows/supply-chain.yml
13+
push:
14+
branches: [main, security]
15+
paths:
16+
- "**/Cargo.toml"
17+
- "**/Cargo.lock"
18+
- supply-chain/**
19+
- deny.toml
20+
- scripts/ci/check_advisory_ignores.py
21+
- .github/workflows/supply-chain.yml
22+
schedule:
23+
- cron: "17 3 * * 1"
24+
workflow_dispatch:
25+
26+
permissions:
27+
contents: read
28+
29+
jobs:
30+
cargo-vet:
31+
name: cargo vet
32+
runs-on: ubuntu-latest
33+
steps:
34+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
35+
36+
- name: Verify advisory-ignore policy
37+
run: |
38+
python3 scripts/ci/check_advisory_ignores.py --self-test
39+
python3 scripts/ci/check_advisory_ignores.py
40+
41+
- name: Install stable Rust
42+
uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4 # stable
43+
44+
- name: Install cargo-vet
45+
run: cargo install cargo-vet --version 0.10.2 --locked
46+
47+
- name: Verify dependency audits
48+
run: cargo vet --locked

0 commit comments

Comments
 (0)