Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 7 additions & 64 deletions .github/workflows/reusable-iac-security.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,30 +38,6 @@ on:
required: false
type: boolean
default: true
zizmor_advisory:
description: |
When true, zizmor still runs and uploads SARIF, but never fails
the job. Useful for consumers transitioning toward contract
conformance whose existing bespoke workflows have known findings.
Default is false (strict — block on error-level findings).
required: false
type: boolean
default: false
trivy_advisory:
description: |
When true, Trivy still runs and uploads SARIF, but never fails the
job. Same transition story as zizmor_advisory.
required: false
type: boolean
default: false
gitleaks_advisory:
description: |
When true, Gitleaks still runs and reports findings, but never
fails the job. Same transition story as zizmor_advisory.
required: false
type: boolean
default: false

permissions: {}

jobs:
Expand Down Expand Up @@ -98,7 +74,7 @@ jobs:
format: "table"
severity: ${{ inputs.trivy_severity }}
scanners: "misconfig,secret"
exit-code: ${{ inputs.trivy_advisory && '0' || '1' }}
exit-code: "1"

- name: Upload Trivy SARIF to GitHub Security
# SARIF upload requires GitHub Advanced Security on private repos.
Expand Down Expand Up @@ -132,7 +108,6 @@ jobs:
# lets findings flow into the consumer's GitHub Security tab
# alongside CodeQL, Trivy, zizmor, and Scorecard results.
uses: docker://ghcr.io/gitleaks/gitleaks:v8.30.1@sha256:c00b6bd0aeb3071cbcb79009cb16a60dd9e0a7c60e2be9ab65d25e6bc8abbb7f
continue-on-error: ${{ inputs.gitleaks_advisory }}
with:
args: detect --source . --redact --verbose --no-banner --report-format sarif --report-path gitleaks.sarif --exit-code 1

Expand All @@ -146,11 +121,6 @@ jobs:
with:
sarif_file: gitleaks.sarif

- name: Surface Gitleaks advisory result
if: ${{ inputs.gitleaks_advisory && steps.gitleaks_run.outcome == 'failure' }}
run: |
echo "::warning::Gitleaks reported findings (advisory mode — not blocking)."

zizmor:
name: zizmor (Actions security)
if: ${{ inputs.enable_zizmor }}
Expand All @@ -171,46 +141,19 @@ jobs:

- name: Install zizmor
# renovate: datasource=pypi depName=zizmor
run: python -m pip install --no-cache-dir zizmor==1.24.1
run: python -m pip install --no-cache-dir zizmor==1.25.2

- name: Run zizmor
# Emit SARIF for the GitHub Security tab; --persona regular catches
# findings most projects care about (omit auditor-only false positives).
env:
ZIZMOR_ADVISORY: ${{ inputs.zizmor_advisory }}
# Emit SARIF for the GitHub Security tab and run the same pedantic
# gate required by the fleet audit.
run: |
set -o pipefail
zizmor --format sarif --persona regular .github/workflows/ \
zizmor --format sarif --persona pedantic .github/workflows/ \
> zizmor.sarif || rc=$?
echo "zizmor exit code: ${rc:-0}"
# Re-run for human-readable output in the log.
zizmor --persona regular .github/workflows/ || true
if [ "${ZIZMOR_ADVISORY}" = "true" ]; then
echo "zizmor in advisory mode — findings are visible in the run "
echo "log and on the Security tab but do not fail the job."
exit 0
fi
# Strict mode (default): block on error-level findings.
python <<'PY'
import json, sys
with open("zizmor.sarif", encoding="utf-8") as fh:
sarif = json.load(fh)
blocking = []
for run in sarif.get("runs", []):
for result in run.get("results", []):
level = result.get("level", "warning")
if level == "error":
msg = result.get("message", {}).get("text", "")
loc = result.get("locations", [{}])[0]
uri = loc.get("physicalLocation", {}).get("artifactLocation", {}).get("uri", "?")
blocking.append(f"{uri}: {msg}")
if blocking:
print("zizmor blocking findings:")
for b in blocking:
print(f" - {b}")
sys.exit(1)
print("no blocking zizmor findings")
PY
zizmor --persona pedantic .github/workflows/ || true
exit "${rc:-0}"

- name: Upload zizmor SARIF
if: always()
Expand Down
11 changes: 9 additions & 2 deletions .github/workflows/reusable-repo-hygiene.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,15 @@ jobs:
bin="opa_linux_amd64_static"
base="https://github.com/open-policy-agent/opa/releases/download/v${OPA_VERSION}"
workdir="$(mktemp -d)"
curl --fail --silent --show-error --location -o "${workdir}/${bin}" "${base}/${bin}"
curl --fail --silent --show-error --location -o "${workdir}/${bin}.sha256" "${base}/${bin}.sha256"
fetch_url() {
local output="$1"
local url="$2"
curl --fail --silent --show-error --location \
--retry 5 --retry-all-errors --retry-delay 2 --connect-timeout 20 \
-o "${output}" "${url}"
}
fetch_url "${workdir}/${bin}" "${base}/${bin}"
fetch_url "${workdir}/${bin}.sha256" "${base}/${bin}.sha256"
expected="$(awk '{print $1}' "${workdir}/${bin}.sha256")"
actual="$(sha256sum "${workdir}/${bin}" | awk '{print $1}')"
if [ "$expected" != "$actual" ]; then
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/reusable-scorecard.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ jobs:

- name: Run Scorecard analysis
# renovate: datasource=github-releases depName=ossf/scorecard-action
uses: ossf/scorecard-action@99c09fe975337306107572b4fdf4db224cf8e2f2 # v2.4.3
uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
# continue-on-error keeps the job green on private repos where
# scorecard's GraphQL queries fail with "Resource not accessible
# by integration." Private repos can't fully use Scorecard without
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@
!/docs/explanation/repo-type-taxonomy-and-ci-focus.md
!/docs/diagrams/
!/docs/diagrams/.gitkeep
!/docs/diagrams/example-flow.mmd
!/docs/diagrams/reusable-workflow-call-graph.mmd
!/docs/runbooks/
!/docs/runbooks/.gitkeep
Expand Down Expand Up @@ -142,3 +143,4 @@
!/docs/decision-records/0007-centralize-universal-ci-reusables-within-each-namespace.md
!/docs/decision-records/0008-enforce-repo-hygiene-by-repo-type.md
!/docs/decision-records/0009-classify-baseline-manifest-byte-identity.md
!/docs/decision-records/0011-adopt-two-organization-portfolio-structure.md
8 changes: 8 additions & 0 deletions baseline-manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@
"source": "docs/decision-records/0009-classify-baseline-manifest-byte-identity.md",
"target": "docs/decision-records/org/0009-classify-baseline-manifest-byte-identity.md"
},
{
"source": "docs/decision-records/0011-adopt-two-organization-portfolio-structure.md",
"target": "docs/decision-records/org/0011-adopt-two-organization-portfolio-structure.md"
},
{
"source": "docs/decision-records/org/.gitkeep",
"target": "docs/decision-records/org/.gitkeep"
Expand Down Expand Up @@ -113,6 +117,10 @@
"source": "docs/diagrams/.gitkeep",
"target": "docs/diagrams/.gitkeep"
},
{
"source": "docs/diagrams/example-flow.mmd",
"target": "docs/diagrams/example-flow.mmd"
},
{
"source": "docs/runbooks/.gitkeep",
"target": "docs/runbooks/.gitkeep"
Expand Down
Loading