chore: prepare verifier v3.14.0 #196
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| jobs: | |
| verify: | |
| runs-on: ubuntu-latest | |
| defaults: | |
| run: | |
| working-directory: keel-verifier | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| python-version: ["3.10", "3.11", "3.12", "3.13"] | |
| env: | |
| KEEL_TSA_REQUIRE_OPENSSL3: "1" | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| path: keel-verifier | |
| - uses: actions/checkout@v6 | |
| with: | |
| repository: keelapi/keel-permit | |
| path: keel-permit | |
| # TODO: re-enable KEEL_REQUIRE_GOLDEN_CORPUS once cat-09 lands on | |
| # keel-permit main; origin/main currently publishes cat-01/02/08 only. | |
| - uses: actions/setup-python@v6 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| cache: pip | |
| cache-dependency-path: keel-verifier/requirements.txt | |
| - name: Require OpenSSL 3 for TSA trust tests | |
| run: | | |
| set -euo pipefail | |
| OPENSSL_BIN="$(command -v openssl)" | |
| VERSION="$("${OPENSSL_BIN}" version)" | |
| echo "${VERSION}" | |
| case "${VERSION}" in | |
| OpenSSL\ 3.*) ;; | |
| *) | |
| echo "OpenSSL 3.x is required for TSA trust regression coverage." >&2 | |
| exit 1 | |
| ;; | |
| esac | |
| echo "KEEL_OPENSSL_BIN=${OPENSSL_BIN}" >> "${GITHUB_ENV}" | |
| - name: Install dependencies | |
| run: | | |
| pip install -r requirements.txt | |
| pip install -e ".[dev]" | |
| - name: Run Ruff | |
| run: ruff check . | |
| - name: Run historical compatibility release gate | |
| run: python scripts/check_historical_compatibility_corpus.py --run | |
| - name: Run canonical drift lock | |
| run: pytest -q tests/test_jcs_drift_lock.py | |
| - name: Check TSA trust bundle freshness | |
| run: python scripts/check_tsa_trust_bundle_freshness.py --min-valid-days 7 | |
| - name: Run TSA trust real-crypto tests | |
| run: >- | |
| pytest -q tests/test_tsa_trust.py | |
| -k "real_cert_negative | |
| or revocation_real_crl_boundaries | |
| or release_pinned_public_ca_receipts_validate_offline | |
| or release_pinned_public_ca_receipt_tamper_rejects_imprint" | |
| -rs | |
| - name: Run pytest | |
| run: pytest -q | |
| - name: Bundled trust root matches live api.keelapi.com endpoint | |
| # Catches a silent swap of keel_verifier/data/trust_root.json, | |
| # or an unsynced key rotation that would render real Keel trust artifacts | |
| # unverifiable by the default trust root. | |
| run: python tools/check_bundled_key.py | |
| - name: Default trust root rejects sample (must fail, exit 1) | |
| # The sample is signed by a deterministic test key shipped in tools/ | |
| # make_sample.py. The default trust root is the real Keel production | |
| # key from the bundled file. A mismatch is the correct outcome and | |
| # proves the default behavior actually anchors against an external | |
| # trust root rather than the artifact's own embedded key. | |
| run: | | |
| set +e | |
| python -m keel_verifier sample/export.json | |
| rc=$? | |
| set -e | |
| if [ "$rc" -ne 1 ]; then | |
| echo "ERROR: default mode should reject sample (test key vs prod trust root), got exit $rc." >&2 | |
| exit 1 | |
| fi | |
| - name: --self-attested verifies sample (must pass, exit 0) | |
| run: python -m keel_verifier sample/export.json --self-attested | |
| - name: --offline alias still works (back-compat with v0.1) | |
| run: python -m keel_verifier sample/export.json --offline --self-attested | |
| - name: --json output is parseable on success | |
| run: | | |
| python -m keel_verifier sample/export.json --self-attested --json | \ | |
| python -c "import json, sys; d = json.load(sys.stdin); assert d['ok'] is True, d; assert d['self_attested'] is True, d; print('json output ok')" | |
| - name: --json output is parseable on failure | |
| run: | | |
| set +e | |
| python -m keel_verifier sample/export.json --json > /tmp/result.json | |
| rc=$? | |
| set -e | |
| if [ "$rc" -ne 1 ]; then | |
| echo "ERROR: expected exit 1 on default-mode sample, got $rc." >&2 | |
| exit 1 | |
| fi | |
| python -c "import json; d = json.load(open('/tmp/result.json')); assert d['ok'] is False, d; assert d['error'], d; print('json output ok')" | |
| - name: Tampered chain (must fail, exit 1) | |
| run: | | |
| set +e | |
| python -m keel_verifier sample/tampered.json --self-attested | |
| rc=$? | |
| set -e | |
| if [ "$rc" -ne 1 ]; then | |
| echo "ERROR: expected exit 1 on tampered.json, got $rc." >&2 | |
| exit 1 | |
| fi | |
| - name: Tampered TSA receipt (must fail, exit 1) | |
| run: | | |
| set +e | |
| python -m keel_verifier sample/tsa_tampered.json --self-attested | |
| rc=$? | |
| set -e | |
| if [ "$rc" -ne 1 ]; then | |
| echo "ERROR: expected exit 1 on tsa_tampered.json, got $rc." >&2 | |
| exit 1 | |
| fi | |
| - name: Tampered TSA passes with --no-tsa (must pass, exit 0) | |
| run: python -m keel_verifier sample/tsa_tampered.json --self-attested --no-tsa | |
| - name: --public-key-url against live endpoint rejects sample (must fail, exit 1) | |
| run: | | |
| set +e | |
| python -m keel_verifier sample/export.json \ | |
| --public-key-url https://api.keelapi.com/v1/integrity/checkpoint-public-key | |
| rc=$? | |
| set -e | |
| if [ "$rc" -ne 1 ]; then | |
| echo "ERROR: live --public-key-url should reject sample (test key vs prod), got $rc." >&2 | |
| exit 1 | |
| fi | |
| - name: Mutually-exclusive trust-root flags rejected | |
| run: | | |
| set +e | |
| python -m keel_verifier sample/export.json --self-attested --public-key ed25519:dummy | |
| rc=$? | |
| set -e | |
| if [ "$rc" -ne 2 ]; then | |
| echo "ERROR: expected usage error (exit 2), got $rc." >&2 | |
| exit 1 | |
| fi |