fix: harden provider and promotion evidence

This commit is contained in:
DongHyeonka
2026-08-02 16:28:24 +09:00
parent 42ffb79997
commit 30ceac23c1
29 changed files with 3961 additions and 1076 deletions
+38 -16
View File
@@ -156,6 +156,7 @@ jobs:
artifacts/release/sbom.cdx.json \
artifacts/security/dependency-diff.json \
artifacts/security/license-report.json \
artifacts/security/local-evidence-assessment.json \
artifacts/security/scan.sarif \
artifacts/security/supply-chain-coherence.json \
artifacts/security/supply-chain-verification.json \
@@ -174,11 +175,16 @@ jobs:
needs: immutable_build
runs-on: ubuntu-latest
timeout-minutes: 45
outputs:
invocation_nonce: ${{ steps.supervise_vulnerability.outputs.invocation_nonce }}
env:
CANDIDATE_ARCHIVE_SHA256: "${{ needs.immutable_build.outputs.archive_sha256 }}"
CANDIDATE_ARCHIVE_PATH: ".release/vulnerability-candidate/release-candidate-${{ gitea.run_id }}-${{ gitea.run_attempt }}.tar.gz"
CANDIDATE_DIST_SHA256: "${{ needs.immutable_build.outputs.dist_sha256 }}"
CANDIDATE_LOCKFILE_PATH: .release/verified-vulnerability/pnpm-lock.yaml
CI_RUN_ID: "${{ gitea.run_id }}"
CI_RUN_ATTEMPT: "${{ gitea.run_attempt }}"
EXPECTED_SOURCE_REVISION: "${{ gitea.sha }}"
VULNERABILITY_PUBLIC_KEY_PATH: "${{ vars.VULNERABILITY_PUBLIC_KEY_PATH }}"
VULNERABILITY_KEY_ID: "${{ vars.VULNERABILITY_KEY_ID }}"
VULNERABILITY_PROVIDER_COMMAND: "${{ vars.VULNERABILITY_PROVIDER_COMMAND }}"
VULNERABILITY_REPORT_PATH: provider-evidence/untrusted/vulnerability-report.json
VALIDATED_PROVIDER_REPORT_PATH: provider-evidence/vulnerability-report.json
@@ -198,9 +204,8 @@ jobs:
with:
name: "release-candidate-${{ gitea.run_id }}-${{ gitea.run_attempt }}"
path: .release/vulnerability-candidate
- name: Verify and extract the candidate through one inode-bound operation
run: node scripts/verify-ci-candidate-archive.ts --archive ".release/vulnerability-candidate/release-candidate-${{ gitea.run_id }}-${{ gitea.run_attempt }}.tar.gz" --extract-to ".release/verified-vulnerability"
- name: Run and validate external vulnerability provider in one trusted supervisor
id: supervise_vulnerability
run: node scripts/run-and-validate-provider.ts --kind vulnerability
- name: Confirm sealed vulnerability provider evidence
run: test -s "$VALIDATED_PROVIDER_REPORT_PATH"
@@ -216,11 +221,16 @@ jobs:
needs: immutable_build
runs-on: ubuntu-latest
timeout-minutes: 45
outputs:
invocation_nonce: ${{ steps.supervise_provenance.outputs.invocation_nonce }}
env:
CANDIDATE_ARCHIVE_SHA256: "${{ needs.immutable_build.outputs.archive_sha256 }}"
CANDIDATE_ARCHIVE_PATH: ".release/provenance-candidate/release-candidate-${{ gitea.run_id }}-${{ gitea.run_attempt }}.tar.gz"
CANDIDATE_DIST_SHA256: "${{ needs.immutable_build.outputs.dist_sha256 }}"
CANDIDATE_LOCKFILE_PATH: .release/verified-provenance/pnpm-lock.yaml
CI_RUN_ID: "${{ gitea.run_id }}"
CI_RUN_ATTEMPT: "${{ gitea.run_attempt }}"
EXPECTED_SOURCE_REVISION: "${{ gitea.sha }}"
PROVENANCE_PUBLIC_KEY_PATH: "${{ vars.PROVENANCE_PUBLIC_KEY_PATH }}"
PROVENANCE_KEY_ID: "${{ vars.PROVENANCE_KEY_ID }}"
PROVENANCE_PROVIDER_COMMAND: "${{ vars.PROVENANCE_PROVIDER_COMMAND }}"
PROVENANCE_ATTESTATION_PATH: provider-evidence/untrusted/provenance-attestation.json
VALIDATED_PROVIDER_REPORT_PATH: provider-evidence/provenance-attestation.json
@@ -240,9 +250,8 @@ jobs:
with:
name: "release-candidate-${{ gitea.run_id }}-${{ gitea.run_attempt }}"
path: .release/provenance-candidate
- name: Verify and extract the candidate through one inode-bound operation
run: node scripts/verify-ci-candidate-archive.ts --archive ".release/provenance-candidate/release-candidate-${{ gitea.run_id }}-${{ gitea.run_attempt }}.tar.gz" --extract-to ".release/verified-provenance"
- name: Run and validate external provenance provider in one trusted supervisor
id: supervise_provenance
run: node scripts/run-and-validate-provider.ts --kind provenance
- name: Confirm sealed provenance provider evidence
run: test -s "$VALIDATED_PROVIDER_REPORT_PATH"
@@ -261,13 +270,16 @@ jobs:
env:
CANDIDATE_ARCHIVE_SHA256: "${{ needs.immutable_build.outputs.archive_sha256 }}"
CANDIDATE_ARCHIVE_PATH: ".release/candidate/release-candidate-${{ gitea.run_id }}-${{ gitea.run_attempt }}.tar.gz"
CANDIDATE_ROOT: "${{ gitea.workspace }}/.release/verified-candidate"
CI_RUN_ID: "${{ gitea.run_id }}"
CI_RUN_ATTEMPT: "${{ gitea.run_attempt }}"
VULNERABILITY_REPORT_PATH: "${{ gitea.workspace }}/.release/vulnerability/vulnerability-report.json"
PROVENANCE_ATTESTATION_PATH: "${{ gitea.workspace }}/.release/provenance/provenance-attestation.json"
VULNERABILITY_PUBLIC_KEY_PATH: "${{ vars.VULNERABILITY_PUBLIC_KEY_PATH }}"
VULNERABILITY_KEY_ID: "${{ vars.VULNERABILITY_KEY_ID }}"
PROVENANCE_PUBLIC_KEY_PATH: "${{ vars.PROVENANCE_PUBLIC_KEY_PATH }}"
PROVENANCE_KEY_ID: "${{ vars.PROVENANCE_KEY_ID }}"
VULNERABILITY_INVOCATION_NONCE: "${{ needs.vulnerability_provider.outputs.invocation_nonce }}"
PROVENANCE_INVOCATION_NONCE: "${{ needs.provenance_provider.outputs.invocation_nonce }}"
steps:
- uses: https://github.com/actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
with:
@@ -294,21 +306,31 @@ jobs:
with:
name: "provenance-provider-${{ gitea.run_id }}-${{ gitea.run_attempt }}"
path: .release/provenance
- name: Verify and extract the candidate through one inode-bound operation
run: node scripts/verify-ci-candidate-archive.ts --archive ".release/candidate/release-candidate-${{ gitea.run_id }}-${{ gitea.run_attempt }}.tar.gz" --extract-to ".release/verified-candidate"
- name: Finalize verified promotion from inode-bound captured inputs
id: finalize
run: node scripts/stage-verified-promotion.ts
- name: Upload promoted release
uses: https://github.com/ChristopherHX/gitea-upload-artifact@81f940d004763f986ba3582c007fd842dd5cb0d7
with:
name: "promoted-release-${{ gitea.run_id }}-${{ gitea.run_attempt }}"
path: |
.release/promoted-staging/release-candidate.tar.gz
.release/promoted-staging/vulnerability-report.json
.release/promoted-staging/provenance-attestation.json
.release/promoted-staging/provider-verification.json
.release/promoted-staging/promotion-verification.json
${{ steps.finalize.outputs.staging_root }}/release-candidate.tar.gz
${{ steps.finalize.outputs.staging_root }}/vulnerability-report.json
${{ steps.finalize.outputs.staging_root }}/provenance-attestation.json
${{ steps.finalize.outputs.staging_root }}/provider-verification.json
${{ steps.finalize.outputs.staging_root }}/promotion-verification.json
if-no-files-found: error
- name: Always remove private promotion staging
if: always()
env:
PROMOTION_STAGING_ROOT: ${{ steps.finalize.outputs.staging_root }}
PROMOTION_CLEANUP_TOKEN: ${{ steps.finalize.outputs.cleanup_token }}
PROMOTION_RUNNER_TEMP_DEV: ${{ steps.finalize.outputs.runner_temp_dev }}
PROMOTION_RUNNER_TEMP_INO: ${{ steps.finalize.outputs.runner_temp_ino }}
run: |
if [ -n "$PROMOTION_STAGING_ROOT" ] && [ -n "$PROMOTION_CLEANUP_TOKEN" ]; then
node scripts/cleanup-verified-promotion.ts
fi
production_gate:
name: "${{ matrix.gate }} / ${{ matrix.name }}"