diff --git a/.github/workflows/generate-and-scan-sbom.yml b/.github/workflows/generate-and-scan-sbom.yml index dcaa15d..025a0ec 100644 --- a/.github/workflows/generate-and-scan-sbom.yml +++ b/.github/workflows/generate-and-scan-sbom.yml @@ -1,227 +1,35 @@ -name: SBOM Generation, Signing, & Vulnerability Scanning +name: SBOM Generation, Signing, and Vulnerability Scanning on: workflow_dispatch: push: - branches: [ main ] + branches: + - main -jobs: - setup: - name: Determin Project Names - runs-on: ubuntu-latest - outputs: - interlynk_environment: ${{ steps.setvar.outputs.interlynk_environment }} - sanitized_branch_name: ${{ steps.setbranch.outputs.sanitized_branch_name }} - - steps: - - name: Set Interlynk Project Name - id: setvar - run: | - if [[ "${GITHUB_REF}" == refs/tags/v* ]]; then - echo "setting interlynk_environment to: Production" - echo "interlynk_environment=Production" >> $GITHUB_OUTPUT - else - echo "setting interlynk_environment to: Development" - echo "interlynk_environment=Development" >> $GITHUB_OUTPUT - fi - - echo "Final interlynk_environment value:" - cat "$GITHUB_OUTPUT" - - - name: Set Santized Branch Name - id: setbranch - run: | - echo "DEBUG INFO" - echo "GITHUB_REF=${GITHUB_REF}" - echo "GITHUB_REF_NAME=${GITHUB_REF_NAME}" - - if [[ "${GITHUB_REF}" == refs/tags/v* ]] || [[ "${GITHUB_REF_NAME}" == "main" ]]; then - echo "Matched release or main branch condition" - echo "sanitized_branch_name=${GITHUB_REF_NAME}" >> "$GITHUB_OUTPUT" - else - CLEAN_NAME="${GITHUB_REF_NAME//\//-}" - echo "Using sanitized branch name: ${CLEAN_NAME}" - echo "sanitized_branch_name=${CLEAN_NAME}" >> "$GITHUB_OUTPUT" - fi - - echo "Final sanitized_branch_name value:" - cat "$GITHUB_OUTPUT" - - generate_sbom: - name: 🔏 Generate & Sign SBOM - needs: setup - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - - - name: Set up Go - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 - with: - go-version-file: 'go.mod' - cache: true - - - name: Generate SBOM (CycloneDX) - uses: CycloneDX/gh-gomod-generate-sbom@efc74245d6802c8cefd925620515442756c70d8f # v2.0.0 - with: - version: v1 - args: mod -licenses -json -output-version 1.6 -output sbom-validator.${{ needs.setup.outputs.sanitized_branch_name }}.cdx.json - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Upload SBOM Artifacts - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: unsigned-sbom - path: sbom-validator.${{ needs.setup.outputs.sanitized_branch_name }}.cdx.json - retention-days: 7 +permissions: + actions: read + contents: read - - name: Add Job Summary - run: | - echo "### 🔏 SBOM Lifecycle Completed" >> $GITHUB_STEP_SUMMARY - echo "- ✅ SBOM generated" >> $GITHUB_STEP_SUMMARY - echo "- 📄 Artifacts uploaded for transparency" >> $GITHUB_STEP_SUMMARY - - sign-sbom: - name: Sign SBOM via SecureSBOM - needs: [setup, generate_sbom] - runs-on: ubuntu-latest - - steps: - - name: Download Signed SBOM - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - with: - name: unsigned-sbom - path: . - - - name: Sign SBOM via SecureSBOM - uses: shiftleftcyber/secure-sbom-action@542dffaadd81bc0614947d749720558a399e6454 # v2.4.0 - with: - sbom_file: sbom-validator.${{ needs.setup.outputs.sanitized_branch_name }}.cdx.json - secure_sbom_action: sign_sbom - secure_sbom_api_key: ${{ secrets.SECURE_SBOM_API_KEY }} - secure_sbom_signing_key_id: ${{ vars.SECURE_SBOM_SIGNING_KEY_ID }} - - - name: Verify SBOM via SecureSBOM - uses: shiftleftcyber/secure-sbom-action@542dffaadd81bc0614947d749720558a399e6454 # v2.4.0 - with: - sbom_file: sbom-validator.${{ needs.setup.outputs.sanitized_branch_name }}.cdx.signed.json - secure_sbom_action: verify_sbom - secure_sbom_api_key: ${{ secrets.SECURE_SBOM_API_KEY }} - secure_sbom_signing_key_id: ${{ vars.SECURE_SBOM_SIGNING_KEY_ID }} - - - name: Upload Signed SBOM - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: signed-sbom - path: sbom-validator.${{ needs.setup.outputs.sanitized_branch_name }}.cdx.signed.json - retention-days: 7 - - osv-scan: - name: 🔎 OSV Scan - needs: [setup, sign-sbom] - runs-on: ubuntu-latest - permissions: - security-events: write - contents: read - actions: read - - steps: - - name: Download Signed SBOM - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - with: - name: signed-sbom - path: . - - - name: Run OSV Scanner - run: | - SAFE_REF="${{ needs.setup.outputs.sanitized_branch_name }}" - SAFE_REF="${SAFE_REF//\//-}" - # osv-scanner does not like when an sbom is named with "signed" - change filename into something - # it can understand - cp sbom-validator.${SAFE_REF}.cdx.signed.json bom.json - docker run --rm -v ${{ github.workspace }}:/opt --workdir /opt ghcr.io/google/osv-scanner:latest \ - scan --lockfile bom.json \ - --format json --output osv-scan-report.json || true - - - name: Upload OSV Report - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: osv-scan-report - path: osv-scan-report.json - - - name: Enforce Security Gate - id: enforce-gate - run: | - echo "🔍 Evaluating OSV scan results..." - COUNT=$(jq '[.results[] | select(.severity == "HIGH" or .severity == "CRITICAL")] | length' osv-scan-report.json) - if [ "$COUNT" -gt 0 ]; then - echo "❌ Blocking release - $COUNT high/critical vulnerabilities detected!" - jq '.results[] | select(.severity == "HIGH" or .severity == "CRITICAL") | {package: .package.name, severity: .severity, summary: .summary}' osv-scan-report.json - echo "blocked=true" >> $GITHUB_OUTPUT - exit 1 - else - echo "✅ No blocking vulnerabilities found." - echo "blocked=false" >> $GITHUB_OUTPUT - fi - - - name: Add Job Summary - if: always() - run: | - echo "### 🔒 OSV Vulnerability Scan Summary" >> $GITHUB_STEP_SUMMARY - echo "- **Scan file:** \`osv-scan-report.json\`" >> $GITHUB_STEP_SUMMARY - if [[ '${{ steps.enforce-gate.outputs.blocked }}' == 'true' ]]; then - echo "- ❌ **High/Critical vulnerabilities found — release blocked**" >> $GITHUB_STEP_SUMMARY - else - echo "- ✅ **No blocking vulnerabilities detected — safe to proceed**" >> $GITHUB_STEP_SUMMARY - fi - echo "" >> $GITHUB_STEP_SUMMARY - echo "For full report, download the [osv-scan-report artifact](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})" >> $GITHUB_STEP_SUMMARY - - upload-sbom: - name: Upload SBOM to Interlynk - needs: [setup, sign-sbom] - runs-on: ubuntu-latest - steps: - - name: Download Signed SBOM - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - with: - name: signed-sbom - path: . - - - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 - with: - python-version: '3.11' - - - name: Clone Interlynk pylynk - run: git clone --depth=1 https://github.com/interlynk-io/pylynk.git - - - name: Install pylynk dependencies - env: - INTERLYNK_COMMIT_HASH: '3aa99e85b5f241e107335b57a9263c5d46134fb5' #v1.2.4 - run: | - cd pylynk - git checkout ${{ env.INTERLYNK_COMMIT_HASH }} - pip install -r requirements.txt - - - name: Upload SBOM to Interlynk - env: - INTERLYNK_SECURITY_TOKEN: ${{ secrets.INTERLYNK_TOKEN }} - INTERLYNK_ENVIRONMENT: ${{ needs.setup.outputs.interlynk_environment }} - SANITIZED_BRANCH_NAME: ${{ needs.setup.outputs.sanitized_branch_name }} - run: | - cd pylynk - echo "🚀 Uploading SBOM to Interlynk project: secure-sbom-api - environment: ${INTERLYNK_ENVIRONMENT}" - python3 pylynk.py upload \ - --prod "sbom-validator" \ - --env "${INTERLYNK_ENVIRONMENT}" \ - --sbom "../sbom-validator.${SANITIZED_BRANCH_NAME}.cdx.signed.json" - - - name: Add Job Summary - if: always() - run: | - echo "### 📤 SBOM Upload to Interlynk" >> $GITHUB_STEP_SUMMARY - echo "- ✅ SBOM uploaded successfully to Interlynk" >> $GITHUB_STEP_SUMMARY - echo "- 🔗 Project: \`sbom-validator-main\`" >> $GITHUB_STEP_SUMMARY - echo "- File: \`sbom-validator.${{ needs.setup.outputs.sanitized_branch_name }}.cdx.json\`" >> $GITHUB_STEP_SUMMARY +jobs: + source-sbom: + uses: shiftleftcyber/supply-chain-workflows/.github/workflows/source-sbom-go.yml@f945c3d57f3129a0124baa29fc77a9706e4e4131 + with: + artifact-name: signed-source-sbom + fail-on-vulnerabilities: true + file-prefix: sbom-validator-${{ github.run_id }} + go-version-file: go.mod + secure-sbom-signing-key-id: ${{ vars.SECURE_SBOM_SIGNING_KEY_ID }} + source-directory: . + secrets: + secure-sbom-api-key: ${{ secrets.SECURE_SBOM_API_KEY }} + + publish-interlynk: + needs: source-sbom + uses: shiftleftcyber/supply-chain-workflows/.github/workflows/publish-sbom-interlynk.yml@f945c3d57f3129a0124baa29fc77a9706e4e4131 + with: + artifact-name: ${{ needs.source-sbom.outputs.artifact-name }} + environment: Development + product: sbom-validator + sbom-file: ${{ needs.source-sbom.outputs.signed-sbom-file }} + secrets: + interlynk-security-token: ${{ secrets.INTERLYNK_TOKEN }} diff --git a/.github/workflows/rearm.yml b/.github/workflows/rearm.yml index bdd785e..c1d1cd5 100644 --- a/.github/workflows/rearm.yml +++ b/.github/workflows/rearm.yml @@ -3,123 +3,63 @@ name: ReARM Workflow on: workflow_dispatch: push: - branches: [ main ] + branches: + - main tags: - - 'v*' + - "v*" + +permissions: + contents: read jobs: - setup: - name: Determine Project Version + version: + name: Determine project version runs-on: ubuntu-latest + timeout-minutes: 5 outputs: - sanitized_project_version: ${{ steps.setversion.outputs.sanitized_project_version }} - - steps: - - name: Checkout (with tags) - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - with: - fetch-depth: 0 - fetch-tags: true - - - name: Set Project Version - id: setversion - shell: bash - run: | - echo "GITHUB_REF=${GITHUB_REF}" - echo "GITHUB_REF_NAME=${GITHUB_REF_NAME}" - - LATEST_TAG=$(git tag --list 'v*' --sort=-v:refname | head -n 1) - - if [[ -z "$LATEST_TAG" ]]; then - echo "No version tags found (vX.Y.Z required)" - exit 1 - fi - - BASE_VERSION="${LATEST_TAG#v}" - - if [[ "${GITHUB_REF}" == refs/tags/v* ]]; then - VERSION="${GITHUB_REF_NAME#v}" - elif [[ "${GITHUB_REF_NAME}" == "main" ]]; then - VERSION="${BASE_VERSION}-main-${GITHUB_RUN_NUMBER}" - else - VERSION="${BASE_VERSION}-dev-${GITHUB_RUN_NUMBER}" - fi - - echo "Resolved project version: ${VERSION}" - echo "sanitized_project_version=${VERSION}" >> "$GITHUB_OUTPUT" - - echo "Final output:" - cat "$GITHUB_OUTPUT" - - sign-with-rearm: - name: ReARM - Generate, Sign & Send - needs: setup - runs-on: ubuntu-latest + project-version: ${{ steps.version.outputs.project-version }} steps: - - name: Checkout Repo - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + - name: Check out tags + uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 with: fetch-depth: 0 + fetch-tags: true + persist-credentials: false - - id: setup-rearm - name: setup-rearm - uses: relizaio/rearm-actions/setup-cli@40bd23d8f2b442c1781a32cdcd5891318a69a1ae # v1.5.0 - - - name: Display rearm version - shell: bash - run: rearm version - - - id: init - name: Initialize ReARM Flow - uses: relizaio/rearm-actions/initialize@40bd23d8f2b442c1781a32cdcd5891318a69a1ae # v1.5.0 - with: - rearm_api_id: ${{ secrets.REARM_COMPONENT_API_ID }} - rearm_api_key: ${{ secrets.REARM_COMPONENT_API_KEY }} - rearm_api_url: ${{ vars.REARM_API_URL }} - component: ${{ vars.REARM_COMPONENT_ID }} - version: ${{ needs.setup.outputs.sanitized_project_version }} - allow_rebuild: true - - - name: Generate and sign SBOMs - id: sbom - uses: relizaio/rearm-actions/sbom-sign-scan@40bd23d8f2b442c1781a32cdcd5891318a69a1ae # v1.5.0 - with: - enable_sbom: true - deliverable_type: FILE - source_code_sbom_type: custom - enable_securesbom: true - securesbom_host: ${{ vars.SECURE_SBOM_API_URL }} - securesbom_pub_key_id: ${{ vars.SECURE_SBOM_SIGNING_KEY_ID }} - securesbom_api_key: ${{ secrets.SECURE_SBOM_API_KEY }} - rearm_short_version: ${{ needs.setup.outputs.sanitized_project_version }} - rearm_full_version: ${{ needs.setup.outputs.sanitized_project_version }} - - - name: TEMP - add REARM_BUILD_LIFECYCLE + - name: Resolve project version + id: version shell: bash run: | - echo "REARM_BUILD_LIFECYCLE=ASSEMBLED" >> $GITHUB_ENV + set -euo pipefail + mapfile -t release_tags < <(git tag --list 'v*' --sort=-v:refname) + latest_tag="${release_tags[0]:-}" + if [[ ! "${latest_tag}" =~ ^v[0-9]+[.][0-9]+[.][0-9]+([-+][0-9A-Za-z.-]+)?$ ]]; then + echo "No valid vX.Y.Z release tag was found." + exit 1 + fi - - name: Submit metadata to ReARM and Finalize - uses: relizaio/rearm-actions/finalize@40bd23d8f2b442c1781a32cdcd5891318a69a1ae # v1.5.0 - with: - rearm_api_id: ${{ secrets.REARM_COMPONENT_API_ID }} - rearm_api_key: ${{ secrets.REARM_COMPONENT_API_KEY }} - rearm_api_url: ${{ vars.REARM_API_URL }} - component: ${{ vars.REARM_COMPONENT_ID }} - rearm_build_start: ${{ steps.init.outputs.build_start }} - rearm_build_lifecycle: 'ASSEMBLED' - deliverable_type: 'FILE' - commit_list: ${{ steps.init.outputs.commit_list }} - sce_commit: ${{ steps.init.outputs.sce_commit }} - sce_commit_message: ${{ steps.init.outputs.sce_commit_message }} - sce_commit_date: ${{ steps.init.outputs.sce_commit_date }} - sce_vcs_uri: ${{ steps.init.outputs.sce_vcs_uri }} - scearts: ${{ steps.sbom.outputs.scearts }} - rearm_short_version: ${{ needs.setup.outputs.sanitized_project_version }} - rearm_full_version: ${{ needs.setup.outputs.sanitized_project_version }} - - - name: Add Job Summary - if: always() - run: | - echo "### 📤 SBOM Upload to ReARM" >> $GITHUB_STEP_SUMMARY - echo "- ✅ SBOM uploaded successfully to ReARM" >> $GITHUB_STEP_SUMMARY + base_version="${latest_tag#v}" + if [[ "${GITHUB_REF}" == refs/tags/v* ]]; then + project_version="${GITHUB_REF_NAME#v}" + elif [[ "${GITHUB_REF}" == "refs/heads/main" ]]; then + project_version="${base_version}-main-${GITHUB_RUN_NUMBER}" + else + project_version="${base_version}-dev-${GITHUB_RUN_NUMBER}" + fi + echo "project-version=${project_version}" >> "${GITHUB_OUTPUT}" + + evidence: + needs: version + uses: shiftleftcyber/supply-chain-workflows/.github/workflows/rearm.yml@f945c3d57f3129a0124baa29fc77a9706e4e4131 + with: + artifact-name: rearm-signed-sbom + component-id: ${{ vars.REARM_COMPONENT_ID }} + deliverable-name: sbom-validator + project-version: ${{ needs.version.outputs.project-version }} + rearm-api-url: ${{ vars.REARM_API_URL }} + secure-sbom-api-url: ${{ vars.SECURE_SBOM_API_URL }} + secure-sbom-signing-key-id: ${{ vars.SECURE_SBOM_SIGNING_KEY_ID }} + secrets: + rearm-api-id: ${{ secrets.REARM_COMPONENT_API_ID }} + rearm-api-key: ${{ secrets.REARM_COMPONENT_API_KEY }} + secure-sbom-api-key: ${{ secrets.SECURE_SBOM_API_KEY }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8a81537..79993a9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -3,254 +3,45 @@ name: Release Workflow on: push: tags: - - 'v*' + - "v*.*.*" permissions: actions: read - security-events: write + attestations: write contents: write + id-token: write jobs: - release: - name: 🚀 Perform GitHub Release - runs-on: ubuntu-latest - needs: [osv-scan] - - steps: - - name: Checkout Repository - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - with: - fetch-depth: 0 - - - name: Setup Go - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 - with: - go-version-file: 'go.mod' - check-latest: true - - - name: Run GoReleaser - uses: goreleaser/goreleaser-action@5daf1e915a5f0af01ddbcd89a43b8061ff4f1a89 # v7.2.2 - with: - version: latest - args: release --clean - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Add Job Summary - run: | - echo "### 🚀 Release Completed" >> $GITHUB_STEP_SUMMARY - echo "- ✅ GoReleaser successfully published binaries and SBOM" >> $GITHUB_STEP_SUMMARY - - generate_sbom: - name: 🔏 Generate SBOM - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - - - name: Setup Go - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 - with: - go-version-file: 'go.mod' - check-latest: true - - - name: Generate SBOM (CycloneDX) - uses: CycloneDX/gh-gomod-generate-sbom@efc74245d6802c8cefd925620515442756c70d8f # v2.0.0 - with: - version: v1 - args: mod -licenses -json -output-version 1.6 -output sbom-validator.${{ github.ref_name }}.cdx.json - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Upload SBOM Artifacts - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: unsigned-sbom - path: sbom-validator.${{ github.ref_name }}.cdx.json - retention-days: 7 - - - name: Add Job Summary - run: | - echo "### 🔏 SBOM Generated & Signed" >> $GITHUB_STEP_SUMMARY - echo "- ✅ CycloneDX SBOM created" >> $GITHUB_STEP_SUMMARY - echo "- 🔐 Signed with SecureSBOM API" >> $GITHUB_STEP_SUMMARY - echo "- 📦 Uploaded as release asset" >> $GITHUB_STEP_SUMMARY - - sign-sbom: - name: Sign SBOM via SecureSBOM - needs: generate_sbom - runs-on: ubuntu-latest - - steps: - - name: Download Signed SBOM - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - with: - name: unsigned-sbom - path: . - - - name: Sign SBOM via SecureSBOM - uses: shiftleftcyber/secure-sbom-action@542dffaadd81bc0614947d749720558a399e6454 # v2.4.0 - with: - sbom_file: sbom-validator.${{ github.ref_name }}.cdx.json - secure_sbom_action: sign_sbom - secure_sbom_api_key: ${{ secrets.SECURE_SBOM_API_KEY }} - secure_sbom_signing_key_id: ${{ vars.SECURE_SBOM_SIGNING_KEY_ID }} - - - name: Verify SBOM via SecureSBOM - uses: shiftleftcyber/secure-sbom-action@542dffaadd81bc0614947d749720558a399e6454 # v2.4.0 - with: - sbom_file: sbom-validator.${{ github.ref_name }}.cdx.signed.json - secure_sbom_action: verify - secure_sbom_api_key: ${{ secrets.SECURE_SBOM_API_KEY }} - secure_sbom_signing_key_id: ${{ vars.SECURE_SBOM_SIGNING_KEY_ID }} + source-sbom: + uses: shiftleftcyber/supply-chain-workflows/.github/workflows/source-sbom-go.yml@f945c3d57f3129a0124baa29fc77a9706e4e4131 + with: + artifact-name: signed-release-sbom + fail-on-vulnerabilities: true + file-prefix: sbom-validator-${{ github.ref_name }} + go-version-file: go.mod + secure-sbom-signing-key-id: ${{ vars.SECURE_SBOM_SIGNING_KEY_ID }} + source-directory: . + secrets: + secure-sbom-api-key: ${{ secrets.SECURE_SBOM_API_KEY }} - - name: Upload Signed SBOM - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: signed-sbom - path: sbom-validator.${{ github.ref_name }}.cdx.signed.json - retention-days: 7 - - - name: Upload Signed SBOM to Release - uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.2 - with: - files: sbom-validator.${{ github.ref_name }}.cdx.signed.json - - osv-scan: - name: 🔎 OSV Scan - needs: sign-sbom - runs-on: ubuntu-latest - permissions: - security-events: write - contents: read - actions: read - - steps: - - name: Download Signed SBOM - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - with: - name: signed-sbom - path: . - - - name: Run OSV Scanner - run: | - cp sbom-validator.${{ github.ref_name }}.cdx.signed.json bom.json - docker run --rm -v ${{ github.workspace }}:/opt --workdir /opt ghcr.io/google/osv-scanner:latest \ - scan --lockfile bom.json \ - --format json --output osv-scan-report.json || true - - - name: Upload OSV Report - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: osv-scan-report - path: osv-scan-report.json - - - name: Enforce Security Gate - id: enforce-gate - run: | - echo "🔍 Evaluating OSV scan results..." - COUNT=$(jq '[.results[] | select(.severity == "HIGH" or .severity == "CRITICAL")] | length' osv-scan-report.json) - if [ "$COUNT" -gt 0 ]; then - echo "❌ Blocking release - $COUNT high/critical vulnerabilities detected!" - jq '.results[] | select(.severity == "HIGH" or .severity == "CRITICAL") | {package: .package.name, severity: .severity, summary: .summary}' osv-scan-report.json - echo "blocked=true" >> $GITHUB_OUTPUT - exit 1 - else - echo "✅ No blocking vulnerabilities found." - echo "blocked=false" >> $GITHUB_OUTPUT - fi - - - name: Add Job Summary - if: always() - run: | - echo "### 🔒 OSV Vulnerability Scan Summary" >> $GITHUB_STEP_SUMMARY - echo "- **Scan file:** \`osv-scan-report.json\`" >> $GITHUB_STEP_SUMMARY - if [[ '${{ steps.enforce-gate.outputs.blocked }}' == 'true' ]]; then - echo "- ❌ **High/Critical vulnerabilities found — release blocked**" >> $GITHUB_STEP_SUMMARY - else - echo "- ✅ **No blocking vulnerabilities detected — safe to proceed**" >> $GITHUB_STEP_SUMMARY - fi - echo "" >> $GITHUB_STEP_SUMMARY - echo "For full report, download the [osv-scan-report artifact](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})" >> $GITHUB_STEP_SUMMARY - - upload-sbom: - name: Upload SBOM to Interlynk - needs: sign-sbom - runs-on: ubuntu-latest - steps: - - name: Download Signed SBOM - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - with: - name: signed-sbom - path: . - - - name: Set up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 - with: - python-version: '3.11' - - - name: Clone Interlynk pylynk - run: git clone --depth=1 https://github.com/interlynk-io/pylynk.git - - - name: Install pylynk dependencies - env: - INTERLYNK_COMMIT_HASH: '4db3f363aa08a2bd922c98456088705662afff30' #v1.2.3 - run: | - cd pylynk - git checkout ${{ env.INTERLYNK_COMMIT_HASH }} - pip install -r requirements.txt - - - name: Upload SBOM to Interlynk - env: - INTERLYNK_SECURITY_TOKEN: ${{ secrets.INTERLYNK_TOKEN }} - run: | - cd pylynk - python3 pylynk.py upload --prod 'sbom-validator' --env "Production" --sbom ../sbom-validator.${{ github.ref_name }}.cdx.signed.json - - - name: Add Job Summary - if: always() - run: | - echo "### 📤 SBOM Upload to Interlynk" >> $GITHUB_STEP_SUMMARY - echo "- ✅ SBOM uploaded successfully to Interlynk" >> $GITHUB_STEP_SUMMARY - echo "- 🔗 Project: \`sbom-validator-main\`" >> $GITHUB_STEP_SUMMARY - echo "- File: \`sbom-validator.${{ github.ref_name }}.cdx.json\`" >> $GITHUB_STEP_SUMMARY - - update-major-tag: - name: Update Major Tag Alias - needs: [release] - runs-on: ubuntu-latest - - steps: - - name: Checkout Repository - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - with: - fetch-depth: 0 - - - name: Update moving major tag - env: - RELEASE_TAG: ${{ github.ref_name }} - run: | - case "$RELEASE_TAG" in - v[0-9]*.[0-9]*.[0-9]*) - MAJOR_TAG="$(echo "$RELEASE_TAG" | cut -d. -f1)" - ;; - *) - echo "Tag $RELEASE_TAG is not a semver release tag; skipping major tag update." - exit 0 - ;; - esac - - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - - git tag -fa "$MAJOR_TAG" -m "Update $MAJOR_TAG to $RELEASE_TAG" "$GITHUB_SHA" - git push origin "refs/tags/$MAJOR_TAG" --force - - - name: Add Job Summary - env: - RELEASE_TAG: ${{ github.ref_name }} - run: | - MAJOR_TAG="$(echo "$RELEASE_TAG" | cut -d. -f1)" - echo "### 🏷️ Major Tag Alias Updated" >> $GITHUB_STEP_SUMMARY - echo "- Release tag: \`$RELEASE_TAG\`" >> $GITHUB_STEP_SUMMARY - echo "- Moving major tag: \`$MAJOR_TAG\`" >> $GITHUB_STEP_SUMMARY + release: + needs: source-sbom + uses: shiftleftcyber/supply-chain-workflows/.github/workflows/release-go.yml@f945c3d57f3129a0124baa29fc77a9706e4e4131 + with: + config: .goreleaser.yml + evidence-artifact-name: ${{ needs.source-sbom.outputs.artifact-name }} + evidence-file: ${{ needs.source-sbom.outputs.signed-sbom-file }} + go-version-file: go.mod + update-major-tag: true + working-directory: . + + publish-interlynk: + needs: source-sbom + uses: shiftleftcyber/supply-chain-workflows/.github/workflows/publish-sbom-interlynk.yml@f945c3d57f3129a0124baa29fc77a9706e4e4131 + with: + artifact-name: ${{ needs.source-sbom.outputs.artifact-name }} + environment: Production + product: sbom-validator + sbom-file: ${{ needs.source-sbom.outputs.signed-sbom-file }} + secrets: + interlynk-security-token: ${{ secrets.INTERLYNK_TOKEN }}