fix: use double quotes for environment variable assignments in workflows
- Updated environment variable assignments in multiple workflow files to use double quotes for consistency and to prevent potential issues with variable expansion. - Refactored echo commands to group multiple lines into a single block for improved readability in the following workflows: - release-goreleaser.yml - renovate_prune.yml - security-pr.yml - security-weekly-rebuild.yml - supply-chain-pr.yml - supply-chain-verify.yml - update-geolite2.yml - waf-integration.yml - weekly-nightly-promotion.yml
This commit is contained in:
117
.github/workflows/supply-chain-verify.yml
vendored
117
.github/workflows/supply-chain-verify.yml
vendored
@@ -4,6 +4,15 @@ on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '0 0 * * 1' # Mondays 00:00 UTC
|
||||
workflow_run:
|
||||
workflows:
|
||||
- Docker Build, Publish & Test
|
||||
types:
|
||||
- completed
|
||||
release:
|
||||
types:
|
||||
- published
|
||||
- prereleased
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -17,6 +26,8 @@ jobs:
|
||||
verify-sbom:
|
||||
name: Verify SBOM
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
image_exists: ${{ steps.image-check.outputs.exists }}
|
||||
# Only run on scheduled scans for main branch, or if workflow_run completed successfully
|
||||
# Critical Fix #5: Exclude PR builds to prevent duplicate verification (now handled inline in docker-build.yml)
|
||||
if: |
|
||||
@@ -61,7 +72,7 @@ jobs:
|
||||
TAG="pr-${PR_NUMBER}"
|
||||
else
|
||||
# Fallback to SHA-based tag if PR number not available
|
||||
TAG="sha-$(echo ${{ github.event.workflow_run.head_sha }} | cut -c1-7)"
|
||||
TAG="sha-$(echo "${{ github.event.workflow_run.head_sha }}" | cut -c1-7)"
|
||||
fi
|
||||
else
|
||||
# For feature branches and other pushes, sanitize branch name for Docker tag
|
||||
@@ -71,7 +82,7 @@ jobs:
|
||||
else
|
||||
TAG="latest"
|
||||
fi
|
||||
echo "tag=${TAG}" >> $GITHUB_OUTPUT
|
||||
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
|
||||
echo "Determined image tag: ${TAG}"
|
||||
|
||||
- name: Check Image Availability
|
||||
@@ -83,15 +94,15 @@ jobs:
|
||||
echo "Checking if image exists: ${IMAGE}"
|
||||
|
||||
# Authenticate with GHCR using GitHub token
|
||||
echo "${GH_TOKEN}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
|
||||
echo "${GH_TOKEN}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin
|
||||
|
||||
if docker manifest inspect ${IMAGE} >/dev/null 2>&1; then
|
||||
if docker manifest inspect "${IMAGE}" >/dev/null 2>&1; then
|
||||
echo "✅ Image exists and is accessible"
|
||||
echo "exists=true" >> $GITHUB_OUTPUT
|
||||
echo "exists=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "⚠️ Image not found - likely not built yet"
|
||||
echo "This is normal for PR workflows before docker-build completes"
|
||||
echo "exists=false" >> $GITHUB_OUTPUT
|
||||
echo "exists=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
# Generate SBOM using official Anchore action (auto-updated by Renovate)
|
||||
@@ -138,21 +149,21 @@ jobs:
|
||||
# Check jq availability
|
||||
if ! command -v jq &> /dev/null; then
|
||||
echo "❌ jq is not available"
|
||||
echo "valid=false" >> $GITHUB_OUTPUT
|
||||
echo "valid=false" >> "$GITHUB_OUTPUT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check file exists
|
||||
if [[ ! -f sbom-verify.cyclonedx.json ]]; then
|
||||
echo "❌ SBOM file does not exist"
|
||||
echo "valid=false" >> $GITHUB_OUTPUT
|
||||
echo "valid=false" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Check file is non-empty
|
||||
if [[ ! -s sbom-verify.cyclonedx.json ]]; then
|
||||
echo "❌ SBOM file is empty"
|
||||
echo "valid=false" >> $GITHUB_OUTPUT
|
||||
echo "valid=false" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
@@ -161,7 +172,7 @@ jobs:
|
||||
echo "❌ SBOM file contains invalid JSON"
|
||||
echo "SBOM content:"
|
||||
cat sbom-verify.cyclonedx.json
|
||||
echo "valid=false" >> $GITHUB_OUTPUT
|
||||
echo "valid=false" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
@@ -177,16 +188,16 @@ jobs:
|
||||
|
||||
if [[ "${BOMFORMAT}" != "CycloneDX" ]]; then
|
||||
echo "❌ Invalid bomFormat: expected 'CycloneDX', got '${BOMFORMAT}'"
|
||||
echo "valid=false" >> $GITHUB_OUTPUT
|
||||
echo "valid=false" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${COMPONENTS}" == "0" ]]; then
|
||||
echo "⚠️ SBOM has no components - may indicate incomplete scan"
|
||||
echo "valid=partial" >> $GITHUB_OUTPUT
|
||||
echo "valid=partial" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "✅ SBOM is valid with ${COMPONENTS} components"
|
||||
echo "valid=true" >> $GITHUB_OUTPUT
|
||||
echo "valid=true" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
echo "SBOM Format: ${BOMFORMAT}"
|
||||
@@ -196,16 +207,16 @@ jobs:
|
||||
|
||||
if [[ "${BOMFORMAT}" != "CycloneDX" ]]; then
|
||||
echo "❌ Invalid bomFormat: expected 'CycloneDX', got '${BOMFORMAT}'"
|
||||
echo "valid=false" >> $GITHUB_OUTPUT
|
||||
echo "valid=false" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${COMPONENTS}" == "0" ]]; then
|
||||
echo "⚠️ SBOM has no components - may indicate incomplete scan"
|
||||
echo "valid=partial" >> $GITHUB_OUTPUT
|
||||
echo "valid=partial" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "✅ SBOM is valid with ${COMPONENTS} components"
|
||||
echo "valid=true" >> $GITHUB_OUTPUT
|
||||
echo "valid=true" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
# Scan for vulnerabilities using official Anchore action (auto-updated by Renovate)
|
||||
@@ -251,10 +262,12 @@ jobs:
|
||||
fi
|
||||
|
||||
# Store for PR comment
|
||||
echo "CRITICAL_VULNS=${CRITICAL}" >> $GITHUB_ENV
|
||||
echo "HIGH_VULNS=${HIGH}" >> $GITHUB_ENV
|
||||
echo "MEDIUM_VULNS=${MEDIUM}" >> $GITHUB_ENV
|
||||
echo "LOW_VULNS=${LOW}" >> $GITHUB_ENV
|
||||
{
|
||||
echo "CRITICAL_VULNS=${CRITICAL}"
|
||||
echo "HIGH_VULNS=${HIGH}"
|
||||
echo "MEDIUM_VULNS=${MEDIUM}"
|
||||
echo "LOW_VULNS=${LOW}"
|
||||
} >> "$GITHUB_ENV"
|
||||
|
||||
- name: Parse Vulnerability Details
|
||||
if: steps.validate-sbom.outputs.valid == 'true'
|
||||
@@ -314,22 +327,24 @@ jobs:
|
||||
- name: Report Skipped Scan
|
||||
if: steps.image-check.outputs.exists != 'true' || steps.validate-sbom.outputs.valid != 'true'
|
||||
run: |
|
||||
echo "## ⚠️ Vulnerability Scan Skipped" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
{
|
||||
echo "## ⚠️ Vulnerability Scan Skipped"
|
||||
echo ""
|
||||
|
||||
if [[ "${{ steps.image-check.outputs.exists }}" != "true" ]]; then
|
||||
echo "**Reason**: Docker image not available yet" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "This is expected for PR workflows. The image will be scanned" >> $GITHUB_STEP_SUMMARY
|
||||
echo "after it's built by the docker-build workflow." >> $GITHUB_STEP_SUMMARY
|
||||
elif [[ "${{ steps.validate-sbom.outputs.valid }}" != "true" ]]; then
|
||||
echo "**Reason**: SBOM validation failed" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "Check the 'Validate SBOM File' step for details." >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
if [[ "${{ steps.image-check.outputs.exists }}" != "true" ]]; then
|
||||
echo "**Reason**: Docker image not available yet"
|
||||
echo ""
|
||||
echo "This is expected for PR workflows. The image will be scanned"
|
||||
echo "after it's built by the docker-build workflow."
|
||||
elif [[ "${{ steps.validate-sbom.outputs.valid }}" != "true" ]]; then
|
||||
echo "**Reason**: SBOM validation failed"
|
||||
echo ""
|
||||
echo "Check the 'Validate SBOM File' step for details."
|
||||
fi
|
||||
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "✅ Workflow completed successfully (scan skipped)" >> $GITHUB_STEP_SUMMARY
|
||||
echo ""
|
||||
echo "✅ Workflow completed successfully (scan skipped)"
|
||||
} >> "$GITHUB_STEP_SUMMARY"
|
||||
|
||||
- name: Determine PR Number
|
||||
id: pr-number
|
||||
@@ -453,8 +468,6 @@ jobs:
|
||||
"
|
||||
|
||||
if [[ -f critical-vulns.txt && -s critical-vulns.txt ]]; then
|
||||
# Count lines in the file
|
||||
CRIT_COUNT=$(wc -l < critical-vulns.txt)
|
||||
COMMENT_BODY+="$(cat critical-vulns.txt)"
|
||||
|
||||
# If more than 20, add truncation message
|
||||
@@ -585,6 +598,15 @@ jobs:
|
||||
echo "Generated comment body:"
|
||||
cat /tmp/comment-body.txt
|
||||
|
||||
- name: Find Existing PR Comment
|
||||
id: find-comment
|
||||
if: steps.pr-number.outputs.result != ''
|
||||
uses: peter-evans/find-comment@v3.2.0
|
||||
with:
|
||||
issue-number: ${{ steps.pr-number.outputs.result }}
|
||||
comment-author: 'github-actions[bot]'
|
||||
body-includes: '<!-- supply-chain-security-comment -->'
|
||||
|
||||
- name: Update or Create PR Comment
|
||||
if: steps.pr-number.outputs.result != ''
|
||||
uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5.0.0
|
||||
@@ -592,8 +614,7 @@ jobs:
|
||||
issue-number: ${{ steps.pr-number.outputs.result }}
|
||||
body-path: /tmp/comment-body.txt
|
||||
edit-mode: replace
|
||||
comment-author: 'github-actions[bot]'
|
||||
body-includes: '<!-- supply-chain-security-comment -->'
|
||||
comment-id: ${{ steps.find-comment.outputs.comment-id }}
|
||||
|
||||
verify-docker-image:
|
||||
name: Verify Docker Image Supply Chain
|
||||
@@ -623,7 +644,7 @@ jobs:
|
||||
id: tag
|
||||
run: |
|
||||
TAG="${{ github.event.release.tag_name }}"
|
||||
echo "tag=${TAG}" >> $GITHUB_OUTPUT
|
||||
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Verify Cosign Signature with Rekor Fallback
|
||||
env:
|
||||
@@ -632,7 +653,7 @@ jobs:
|
||||
echo "Verifying Cosign signature for ${IMAGE}..."
|
||||
|
||||
# Try with Rekor
|
||||
if cosign verify ${IMAGE} \
|
||||
if cosign verify "${IMAGE}" \
|
||||
--certificate-identity-regexp="https://github.com/${{ github.repository }}" \
|
||||
--certificate-oidc-issuer="https://token.actions.githubusercontent.com" 2>&1; then
|
||||
echo "✅ Cosign signature verified (with Rekor)"
|
||||
@@ -640,7 +661,7 @@ jobs:
|
||||
echo "⚠️ Rekor verification failed, trying offline verification..."
|
||||
|
||||
# Fallback: verify without Rekor
|
||||
if cosign verify ${IMAGE} \
|
||||
if cosign verify "${IMAGE}" \
|
||||
--certificate-identity-regexp="https://github.com/${{ github.repository }}" \
|
||||
--certificate-oidc-issuer="https://token.actions.githubusercontent.com" \
|
||||
--insecure-ignore-tlog 2>&1; then
|
||||
@@ -653,11 +674,11 @@ jobs:
|
||||
fi
|
||||
|
||||
- name: Verify Docker Hub Image Signature
|
||||
if: steps.image-check.outputs.exists == 'true'
|
||||
if: needs.verify-sbom.outputs.image_exists == 'true'
|
||||
continue-on-error: true
|
||||
run: |
|
||||
echo "Verifying Docker Hub image signature..."
|
||||
cosign verify docker.io/wikid82/charon:${{ steps.tag.outputs.tag }} \
|
||||
cosign verify "docker.io/wikid82/charon:${{ steps.tag.outputs.tag }}" \
|
||||
--certificate-identity-regexp="https://github.com/Wikid82/Charon" \
|
||||
--certificate-oidc-issuer="https://token.actions.githubusercontent.com" && \
|
||||
echo "✅ Docker Hub signature verified" || \
|
||||
@@ -702,7 +723,7 @@ jobs:
|
||||
6. Re-run build if signatures/provenance are missing
|
||||
EOF
|
||||
|
||||
cat verification-report.md >> $GITHUB_STEP_SUMMARY
|
||||
cat verification-report.md >> "$GITHUB_STEP_SUMMARY"
|
||||
|
||||
verify-release-artifacts:
|
||||
name: Verify Release Artifacts
|
||||
@@ -723,9 +744,9 @@ jobs:
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
TAG=${{ github.event.release.tag_name }}
|
||||
TAG="${{ github.event.release.tag_name }}"
|
||||
mkdir -p ./release-assets
|
||||
gh release download ${TAG} --dir ./release-assets || {
|
||||
gh release download "${TAG}" --dir ./release-assets || {
|
||||
echo "⚠️ No release assets found or download failed"
|
||||
exit 0
|
||||
}
|
||||
@@ -750,11 +771,11 @@ jobs:
|
||||
fi
|
||||
|
||||
if [[ -f "$artifact" ]]; then
|
||||
echo "Verifying: $(basename $artifact)"
|
||||
echo "Verifying: $(basename "$artifact")"
|
||||
|
||||
# Check if signature files exist
|
||||
if [[ ! -f "${artifact}.sig" ]] || [[ ! -f "${artifact}.pem" ]]; then
|
||||
echo "⚠️ No signature files found for $(basename $artifact)"
|
||||
echo "⚠️ No signature files found for $(basename "$artifact")"
|
||||
FAILED_COUNT=$((FAILED_COUNT + 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user