mirror of
https://git.quad4.io/RNS-Things/MeshChatX.git
synced 2026-04-02 03:35:53 +00:00
feat(ci): add scripts for cosign setup, release asset attestation, and verification
This commit is contained in:
4
cosign.pub
Normal file
4
cosign.pub
Normal file
@@ -0,0 +1,4 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEyWx2eajLfc+pflz3cq2XcmopUoO9
|
||||
9oGHYfmtd+zSod22RkU4YJtIcEBesql7Wb+wjkqBxjpXgdrTB9Tu3dPVZQ==
|
||||
-----END PUBLIC KEY-----
|
||||
36
scripts/ci/attest-release-assets.sh
Executable file
36
scripts/ci/attest-release-assets.sh
Executable file
@@ -0,0 +1,36 @@
|
||||
#!/bin/sh
|
||||
# Create SLSA v1 cosign bundle attestations next to each release binary under DIR.
|
||||
# Requires: cosign on PATH; COSIGN_KEY_PATH to cosign private key PEM; COSIGN_PASSWORD
|
||||
# if the key is encrypted. Run from repository root so scripts/ci/slsa-predicate.py resolves.
|
||||
#
|
||||
# Usage: attest-release-assets.sh <directory>
|
||||
set -eu
|
||||
|
||||
DIR="${1:?directory}"
|
||||
KEY="${COSIGN_KEY_PATH:?set COSIGN_KEY_PATH}"
|
||||
|
||||
if [ ! -f "$KEY" ]; then
|
||||
echo "attest-release-assets.sh: missing key file $KEY" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
PRED="$(mktemp "${TMPDIR:-/tmp}/slsa-pred.XXXXXX")"
|
||||
trap 'rm -f "$PRED"' EXIT INT
|
||||
|
||||
python3 scripts/ci/slsa-predicate.py > "$PRED"
|
||||
|
||||
find "$DIR" -type f ! -name '*.sha256' ! -name '*.cosign.bundle' | while IFS= read -r f; do
|
||||
case "$f" in
|
||||
*/.git/*) continue ;;
|
||||
esac
|
||||
echo "attest: $f"
|
||||
cosign attest-blob --yes \
|
||||
--key "$KEY" \
|
||||
--predicate "$PRED" \
|
||||
--type slsaprovenance1 \
|
||||
--bundle "${f}.cosign.bundle" \
|
||||
--tlog-upload=true \
|
||||
"$f" >/dev/null
|
||||
done
|
||||
|
||||
echo "attest-release-assets.sh: done"
|
||||
32
scripts/ci/setup-cosign.sh
Executable file
32
scripts/ci/setup-cosign.sh
Executable file
@@ -0,0 +1,32 @@
|
||||
#!/bin/sh
|
||||
# Install cosign from GitHub releases with SHA256 verification.
|
||||
# Usage: setup-cosign.sh [version]
|
||||
set -eu
|
||||
|
||||
COSIGN_VERSION="${1:-3.0.5}"
|
||||
|
||||
ARCH="$(uname -m)"
|
||||
case "$ARCH" in
|
||||
x86_64) ARCH="amd64" ;;
|
||||
aarch64) ARCH="arm64" ;;
|
||||
*) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;;
|
||||
esac
|
||||
|
||||
BASE_URL="https://github.com/sigstore/cosign/releases/download/v${COSIGN_VERSION}"
|
||||
BINARY="cosign-linux-${ARCH}"
|
||||
CHECKSUMS_URL="${BASE_URL}/cosign_checksums.txt"
|
||||
|
||||
curl -fsSL "$CHECKSUMS_URL" -o /tmp/cosign-checksums.txt
|
||||
curl -fsSL "${BASE_URL}/${BINARY}" -o /tmp/cosign
|
||||
|
||||
EXPECTED="$(grep " ${BINARY}\$" /tmp/cosign-checksums.txt | awk '{print $1}')"
|
||||
ACTUAL="$(sha256sum /tmp/cosign | awk '{print $1}')"
|
||||
if [ -z "$EXPECTED" ] || [ "$EXPECTED" != "$ACTUAL" ]; then
|
||||
echo "SHA256 verification failed for ${BINARY}" >&2
|
||||
rm -f /tmp/cosign /tmp/cosign-checksums.txt
|
||||
exit 1
|
||||
fi
|
||||
|
||||
sudo install -m 0755 /tmp/cosign /usr/local/bin/cosign
|
||||
rm -f /tmp/cosign /tmp/cosign-checksums.txt
|
||||
cosign version
|
||||
76
scripts/ci/slsa-predicate.py
Normal file
76
scripts/ci/slsa-predicate.py
Normal file
@@ -0,0 +1,76 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Emit a SLSA v1 provenance predicate JSON on stdout (stdin unused)."""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
from datetime import datetime, timezone
|
||||
|
||||
|
||||
def _source_uri() -> str:
|
||||
server = (os.environ.get("GITHUB_SERVER_URL") or os.environ.get("GITEA_SERVER_URL") or "").rstrip("/")
|
||||
repo = os.environ.get("GITHUB_REPOSITORY") or os.environ.get("GITEA_REPOSITORY") or ""
|
||||
if not server or not repo:
|
||||
return ""
|
||||
if server.startswith("https://") or server.startswith("http://"):
|
||||
return f"git+{server}/{repo}.git"
|
||||
return f"git+https://{server}/{repo}.git"
|
||||
|
||||
|
||||
def _build_type() -> str:
|
||||
custom = os.environ.get("PROVENANCE_BUILD_TYPE")
|
||||
if custom:
|
||||
return custom
|
||||
server = (os.environ.get("GITHUB_SERVER_URL") or os.environ.get("GITEA_SERVER_URL") or "").rstrip("/")
|
||||
repo = os.environ.get("GITHUB_REPOSITORY") or os.environ.get("GITEA_REPOSITORY") or ""
|
||||
if server and repo:
|
||||
return f"{server}/{repo}/.gitea/workflows/build.yml"
|
||||
return "https://slsa.dev/provenance/v1"
|
||||
|
||||
|
||||
def _builder_id() -> str:
|
||||
custom = os.environ.get("PROVENANCE_BUILDER_ID")
|
||||
if custom:
|
||||
return custom
|
||||
server = (os.environ.get("GITHUB_SERVER_URL") or os.environ.get("GITEA_SERVER_URL") or "").rstrip("/")
|
||||
if server:
|
||||
return f"{server}/actions"
|
||||
return "https://gitea.io/actions/runner"
|
||||
|
||||
|
||||
def main() -> None:
|
||||
ref = os.environ.get("GITHUB_REF", "")
|
||||
sha = os.environ.get("GITHUB_SHA", "")
|
||||
run_id = os.environ.get("GITHUB_RUN_ID", "")
|
||||
attempt = os.environ.get("GITHUB_RUN_ATTEMPT", "1")
|
||||
workflow = os.environ.get("GITHUB_WORKFLOW", "")
|
||||
started = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
|
||||
|
||||
internal = {}
|
||||
if workflow:
|
||||
internal["workflow"] = workflow
|
||||
|
||||
predicate = {
|
||||
"buildDefinition": {
|
||||
"buildType": _build_type(),
|
||||
"externalParameters": {
|
||||
"source": _source_uri(),
|
||||
"ref": ref,
|
||||
"revision": sha,
|
||||
},
|
||||
"internalParameters": internal,
|
||||
"resolvedDependencies": [],
|
||||
},
|
||||
"runDetails": {
|
||||
"builder": {"id": _builder_id()},
|
||||
"metadata": {
|
||||
"invocationId": f"{run_id}-{attempt}",
|
||||
"startedOn": started,
|
||||
},
|
||||
},
|
||||
}
|
||||
print(json.dumps(predicate, separators=(",", ":")))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
21
scripts/ci/verify-release-attestation.sh
Executable file
21
scripts/ci/verify-release-attestation.sh
Executable file
@@ -0,0 +1,21 @@
|
||||
#!/bin/sh
|
||||
# Verify a cosign SLSA bundle for a release binary using the repository public key.
|
||||
# Checks Sigstore Rekor (public log) unless COSIGN_REKOR_URL points elsewhere.
|
||||
# Usage: verify-release-attestation.sh <blob-file> <bundle-file>
|
||||
# Env: COSIGN_PUBLIC_KEY (default cosign.pub)
|
||||
set -eu
|
||||
|
||||
BLOB="${1:?blob path}"
|
||||
BUNDLE="${2:?bundle path}"
|
||||
PUB="${COSIGN_PUBLIC_KEY:-cosign.pub}"
|
||||
|
||||
if [ ! -f "$PUB" ]; then
|
||||
echo "Missing $PUB (generate a key pair with cosign and commit the .pub file)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exec cosign verify-blob-attestation \
|
||||
--key "$PUB" \
|
||||
--bundle "$BUNDLE" \
|
||||
--type slsaprovenance1 \
|
||||
"$BLOB"
|
||||
Reference in New Issue
Block a user