ledgerprove/sign-sbom

GitHub: ledgerprove/sign-sbom

Stars: 0 | Forks: 0

# LedgerProve — sign-sbom GitHub Action [![GitHub Marketplace](https://img.shields.io/badge/Marketplace-LedgerProve-blue?logo=github)](https://github.com/marketplace/actions/ledgerprove-sign-sbom) [![Release](https://img.shields.io/github/v/release/ledgerprove/sign-sbom?display_name=tag&sort=semver)](https://github.com/ledgerprove/sign-sbom/releases) [![License](https://img.shields.io/badge/license-MIT-green)](LICENSE) Cryptographically sign your SBOM, append it to a tamper-evident hash chain, and get a public verification URL — all in one CI step. ## Quick start (auto-generates the SBOM for you) - name: Sign SBOM with LedgerProve uses: ledgerprove/sign-sbom@v1 with: api-key: ${{ secrets.LEDGERPROVE_API_KEY }} That's the whole workflow step. The Action installs Syft, generates a CycloneDX SBOM of your repo, signs it with ECDSA-P521 (hardware-backed, non-exportable signing key), and prints a public verify URL. ## Bring-your-own SBOM (full control) If you already generate an SBOM in a previous step (cyclonedx-cli, custom tooling, etc.), pass it explicitly: - name: Sign SBOM with LedgerProve uses: ledgerprove/sign-sbom@v1 with: api-key: ${{ secrets.LEDGERPROVE_API_KEY }} sbom-file: ./my-sbom.json ## What it does Anyone can verify the signed SBOM at the verification URL with a single OpenSSL command. No account required. ## Inputs | Input | Required | Default | Description | |-------|----------|---------|-------------| | `api-key` | ✅ | — | Your LedgerProve API key (`lp_live_…`). Generate at https://ledgerprove.com/dashboard. Store as a repo or org secret. | | `sbom-file` | ✅ | — | Path to the SBOM JSON file. Generate it in an earlier step with `syft`, `cyclonedx-cli`, or your tool of choice. | | `repo-id` | — | `${{ github.repository }}` | Repository identifier under which to record this build. | | `commit-hash` | — | `${{ github.sha }}` | The commit SHA to record. | | `build-status` | — | `PASS` | `PASS`, `FAIL`, or `WARN`. Use `FAIL` to record a failed build (e.g. tests failed, vulns found). | | `cve-count` | — | `0` | Optional. CVE count to bake into the signed chain payload. Most users leave this at `0` — LedgerProve runs its own CVE scan against OSV.dev after every signed build and exposes the real findings on your dashboard. This field exists for callers who want to record a count from their own scanner inside the signature. | | `api-url` | — | `https://api.ledgerprove.com` | Override the LedgerProve API URL. Only set this for self-hosted/staging. | ## Outputs | Output | Description | |--------|-------------| | `verification-id` | Public verification ID (24-char hex) | | `verification-url` | Public URL anyone can use to verify the SBOM | | `signature-algorithm` | Always `ECDSA-P521-SHA512` | | `chain-index` | Position of this record in your organisation's chain | | `record-hash` | SHA-512 of the signed record | | `timestamped` | `true` if an RFC 3161 timestamp was attached | ## Full example — sign every build, post the verify URL on PRs name: Build & Sign SBOM on: [push, pull_request] jobs: build-sign: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 # 1. Generate an SBOM with Syft (works for any language / lockfile) - name: Generate SBOM uses: anchore/sbom-action@v0 with: format: cyclonedx-json output-file: sbom.json # 2. Sign and chain it with LedgerProve - name: Sign with LedgerProve id: ledgerprove uses: ledgerprove/sign-sbom@v1 with: api-key: ${{ secrets.LEDGERPROVE_API_KEY }} sbom-file: ./sbom.json # 3. Comment the verification URL on the PR - name: Comment verify URL on PR if: github.event_name == 'pull_request' uses: actions/github-script@v7 with: script: | github.rest.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, body: '🛡 SBOM signed: ${{ steps.ledgerprove.outputs.verification-url }}' }) ## Setting up the API key 1. Sign in at https://ledgerprove.com/login (GitHub or Google). 2. Click **Generate API key** in your dashboard. 3. Copy the `lp_live_…` value (shown once). 4. In your GitHub repo (or org): **Settings → Secrets and variables → Actions → New repository secret** - Name: `LEDGERPROVE_API_KEY` - Value: paste your key 5. Use `${{ secrets.LEDGERPROVE_API_KEY }}` in your workflow. ## Free plan limits - **1 repository** with unlimited builds. - ECDSA-P521 signing on every build. - Public verification links forever. For more repos, CVE alerts, SBOM diff and team accounts, see https://ledgerprove.com/pricing. ## Verifying a signed SBOM yourself Anyone can verify a record without a LedgerProve account: # 1. Fetch the public record curl -s https://api.ledgerprove.com/verify/ # 2. Download our public key curl -sO https://api.ledgerprove.com/.well-known/public-key.pem # 3. (Optional) Verify the RFC 3161 timestamp with OpenSSL openssl ts -reply -in token.tsr -text ## FAQ ### How is this different from sigstore / cosign? Sigstore uses keyless signing through a transparency log and a public Certificate Authority (Fulcio). It's a great fit if you want zero key management and are happy depending on a CA. LedgerProve doesn't use a CA. Each organisation has a long-lived ECDSA-P521 key held inside a hardware-backed KMS, and records are appended to a per-org hash chain. The trade-off: - **Sigstore wins** if you want true keyless signing with a public transparency log - **LedgerProve wins** if you want signing without a CA dependency, with FIPS-aligned crypto, and a single-step CI integration Both produce verifiable artifacts; the trust models differ. ### Why ECDSA-P521 instead of Ed25519? P521 is FIPS-186-5 approved (matters for some customers' compliance reviews) and AWS KMS supports it for signing today; Ed25519 in KMS is still not GA. We'd switch when Ed25519 lands. ### Why a hash chain instead of a Merkle tree / transparency log? A per-org hash chain is simpler operationally and gives the same tamper-evidence properties for a single organisation's history. A global Merkle log (like Rekor) gives cross-org public auditability — useful if you're publishing widely-consumed artifacts, less useful for internal SBOMs. We chose the simpler model for the MVP. ### Does the action send my SBOM contents to your servers? No. The action computes a SHA-256 of the SBOM locally and sends only the hash + metadata. The SBOM body never leaves your runner. The signed record references the hash, not the file. (Trade-off: you need to keep the SBOM retrievable yourself if you want full reproducibility later — sigstore goes the other way with attestation bundles.) ### What happens if your service goes down? Already-signed records remain verifiable forever using the public key at `https://api.ledgerprove.com/.well-known/public-key.pem`. If you cache the public key locally, you can verify signatures with OpenSSL even if our API is unreachable. New signings would obviously fail until we're back up. ### Is there a free plan? Yes — 1 repository, unlimited builds, no credit card. The open-source action and the public verify endpoint are free on every plan. See https://ledgerprove.com/pricing for paid tiers (more repos, longer history retention, SBOM diff, CVE email alerts). ### Why is `dist/` checked in? GitHub Actions runs the compiled JavaScript directly — there's no install step at action runtime. The compiled output has to be in the repo. We rebuild `dist/` on every change in `src/`. ## License [MIT](LICENSE). Source: https://github.com/ledgerprove/sign-sbom ## Security For security disclosures, see [SECURITY.md](SECURITY.md) — do not report security issues via public GitHub Issues. ## Issues / questions - General: https://github.com/ledgerprove/sign-sbom/issues - Discussions: https://github.com/ledgerprove/sign-sbom/discussions - Email: hello@ledgerprove.com
标签:自动化攻击