Zion Boggan zionboggan.com ↗

pipeline and soc-integration docs

4ab2d75   Zion Boggan committed on Apr 21, 2026 (2 months ago)
docs/pipeline.md +46 -0
@@ -0,0 +1,46 @@
+# Pipeline detail
+
+## Triggers
+
+The workflow runs on push and pull request to `main`, plus `workflow_dispatch` so I
+can kick it manually when I'm testing a change to the pipeline itself.
+
+## Permissions
+
+The workflow requests `contents: read` and `security-events: write`. The second is
+what lets the SARIF upload write to the Security tab. Nothing in the pipeline needs
+write access to the repo contents, so it doesn't ask for it.
+
+## Job graph
+
+`lint` is the fail-fast. If ruff fails there's no point spending runner minutes on
+the heavier scans, so everything depends on it.
+
+`sast`, `secrets`, and `dependencies` have no dependency on each other and run in
+parallel. Each one is independently informative: a Semgrep finding, a leaked secret,
+and a vulnerable dependency are three different problems with three different fixes.
+
+`test` waits on all three security jobs. Tests passing on code that has a known
+secret leak in it isn't a green pipeline, so the gates come first.
+
+`notify-soc` uses `if: always()` and depends on `test`, so it reports the outcome
+whether the pipeline passed or failed.
+
+## Why these tools
+
+- **ruff** replaces flake8 + isort + a chunk of bandit's lint-level checks in one
+ fast binary. The `S` rule selection pulls in the security subset.
+- **Semgrep** does the real static analysis. Custom rules live in the repo so they
+ are reviewed like any other code.
+- **gitleaks** scans full history on pull requests (`fetch-depth: 0`) so a secret
+ that was committed and then "removed" in a later commit is still caught.
+- **pip-audit** checks the pinned dependencies against the advisory database. `--strict`
+ makes an unfixable advisory fail the job rather than warn.
+
+## Tuning the noise
+
+Semgrep on `p/default` is broad. The `.gitleaks.toml` allowlist covers the
+documented placeholders (`replace-with-...`, `changeme-...`) and the test fixtures so
+the secret scan doesn't flag the examples in this repo. Real allowlisting should be
+narrow - path- and rule-scoped - which is why the allowlist here is explicit instead
+of a blanket ignore.
docs/soc-integration.md +44 -0
@@ -0,0 +1,44 @@
+# Wiring the pipeline into the SOC lab
+
+This pipeline doesn't stop at a green check. The `notify-soc` job posts the run
+outcome to the same Shuffle instance that runs the SOC automation lab, so CI
+security events land next to endpoint alerts.
+
+## Why send CI events to a SOC
+
+A failed secret scan or a newly vulnerable dependency is a security event. Treating
+it like one - routing it to the same place analysts already watch - means a leaked
+credential in a commit gets the same case-and-notify treatment as a Wazuh alert,
+instead of sitting in a CI log nobody reads.
+
+## What gets sent
+
+`scripts/notify_soc.py` posts a small JSON document:
+
+```json
+{
+ "source": "github-actions",
+ "pipeline": "security-pipeline",
+ "status": "failure",
+ "outcome": "failure",
+ "repository": "owner/secure-cicd-pipeline",
+ "commit": "9f2c...",
+ "actor": "username",
+ "run_url": "https://github.com/owner/secure-cicd-pipeline/actions/runs/123"
+}
+```
+
+## Shuffle side
+
+In Shuffle, point a webhook trigger at a small workflow that branches on `outcome`:
+
+1. On `failure`, open a TheHive case tagged `ci`, `pipeline`, severity Medium, with
+ the run URL in the description so the analyst can jump straight to the failing job.
+2. On `success`, drop a low-priority message in the CI channel and do nothing else.
+
+## Setup
+
+Add a repository secret named `SHUFFLE_WEBHOOK_URL` with the webhook from the
+Shuffle workflow. If the secret is absent the job logs that it's skipping and exits
+zero, so forks and clones don't fail the pipeline trying to reach a webhook they
+don't have.