126 lines
4.5 KiB
YAML
126 lines
4.5 KiB
YAML
# =============================================================================
|
|
# dsse-attest-verify-check.yml
|
|
# Sprint: SPRINT_20260219_011 (CIAP-02)
|
|
# Description: Signs SBOM with DSSE, verifies attestation, validates Rekor proof
|
|
# =============================================================================
|
|
#
|
|
# This workflow creates a DSSE attestation for an SBOM, verifies it, and
|
|
# optionally validates the Rekor transparency log inclusion proof.
|
|
#
|
|
# Supports both keyless (Fulcio/OIDC) and keyed (cosign key) signing modes.
|
|
#
|
|
# =============================================================================
|
|
|
|
name: DSSE Attest + Verify + Rekor Check
|
|
|
|
on:
|
|
workflow_call:
|
|
inputs:
|
|
subject_ref:
|
|
description: 'OCI image reference (registry/repo@sha256:...)'
|
|
required: true
|
|
type: string
|
|
predicate_path:
|
|
description: 'Path to the DSSE predicate JSON file'
|
|
required: true
|
|
type: string
|
|
signing_mode:
|
|
description: 'Signing mode: keyless (Fulcio/OIDC) or key (cosign key)'
|
|
required: false
|
|
type: string
|
|
default: 'keyless'
|
|
public_key_path:
|
|
description: 'Path to cosign public key PEM (required for key mode)'
|
|
required: false
|
|
type: string
|
|
predicate_type:
|
|
description: 'Predicate type URI for the attestation'
|
|
required: false
|
|
type: string
|
|
default: 'https://cyclonedx.org/bom'
|
|
skip_rekor:
|
|
description: 'Skip Rekor transparency log (for air-gapped environments)'
|
|
required: false
|
|
type: boolean
|
|
default: false
|
|
|
|
jobs:
|
|
attest-and-verify:
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
contents: read
|
|
packages: write
|
|
id-token: write # For OIDC-based keyless signing
|
|
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Install cosign
|
|
uses: sigstore/cosign-installer@v3
|
|
|
|
- name: Sign attestation
|
|
id: sign
|
|
env:
|
|
COSIGN_EXPERIMENTAL: '1'
|
|
run: |
|
|
SIGN_FLAGS="--predicate ${{ inputs.predicate_path }}"
|
|
SIGN_FLAGS="${SIGN_FLAGS} --type ${{ inputs.predicate_type }}"
|
|
|
|
if [ "${{ inputs.signing_mode }}" = "key" ]; then
|
|
# Keyed signing
|
|
SIGN_FLAGS="${SIGN_FLAGS} --key ${{ inputs.public_key_path }}"
|
|
fi
|
|
|
|
if [ "${{ inputs.skip_rekor }}" = "true" ]; then
|
|
SIGN_FLAGS="${SIGN_FLAGS} --tlog-upload=false"
|
|
fi
|
|
|
|
cosign attest ${SIGN_FLAGS} "${{ inputs.subject_ref }}"
|
|
|
|
echo "### Attestation Signed" >> $GITHUB_STEP_SUMMARY
|
|
echo "- Subject: \`${{ inputs.subject_ref }}\`" >> $GITHUB_STEP_SUMMARY
|
|
echo "- Mode: ${{ inputs.signing_mode }}" >> $GITHUB_STEP_SUMMARY
|
|
echo "- Predicate type: \`${{ inputs.predicate_type }}\`" >> $GITHUB_STEP_SUMMARY
|
|
|
|
- name: Verify attestation
|
|
id: verify
|
|
run: |
|
|
VERIFY_FLAGS="--type ${{ inputs.predicate_type }}"
|
|
|
|
if [ "${{ inputs.signing_mode }}" = "key" ]; then
|
|
VERIFY_FLAGS="${VERIFY_FLAGS} --key ${{ inputs.public_key_path }}"
|
|
else
|
|
# Keyless: verify against Sigstore trust root
|
|
VERIFY_FLAGS="${VERIFY_FLAGS} --certificate-identity-regexp '.*'"
|
|
VERIFY_FLAGS="${VERIFY_FLAGS} --certificate-oidc-issuer-regexp '.*'"
|
|
fi
|
|
|
|
cosign verify-attestation ${VERIFY_FLAGS} "${{ inputs.subject_ref }}"
|
|
|
|
if [ $? -eq 0 ]; then
|
|
echo "Attestation verification: PASS" >> $GITHUB_STEP_SUMMARY
|
|
else
|
|
echo "Attestation verification: FAIL" >> $GITHUB_STEP_SUMMARY
|
|
exit 1
|
|
fi
|
|
|
|
- name: Validate Rekor inclusion proof
|
|
if: inputs.skip_rekor != true
|
|
run: |
|
|
# Fetch the Rekor entry for our attestation
|
|
DIGEST=$(sha256sum "${{ inputs.predicate_path }}" | cut -d' ' -f1)
|
|
|
|
# Use rekor-cli to search and verify
|
|
if command -v rekor-cli &> /dev/null; then
|
|
ENTRY=$(rekor-cli search --sha "sha256:${DIGEST}" 2>/dev/null | head -1)
|
|
if [ -n "${ENTRY}" ]; then
|
|
rekor-cli verify --artifact "${{ inputs.predicate_path }}" --entry "${ENTRY}"
|
|
echo "Rekor inclusion proof: PASS (entry: ${ENTRY})" >> $GITHUB_STEP_SUMMARY
|
|
else
|
|
echo "Rekor entry not found (may be pending)" >> $GITHUB_STEP_SUMMARY
|
|
fi
|
|
else
|
|
echo "rekor-cli not available, skipping Rekor verification" >> $GITHUB_STEP_SUMMARY
|
|
fi
|