-
Notifications
You must be signed in to change notification settings - Fork 0
feat(store): optimistic concurrency on postgres snapshots #105
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
seonghobae
merged 19 commits into
feat/issue-86-in-path-coraza
from
feat/issue-80-optimistic-concurrency
Aug 26, 2026
Merged
Changes from all commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
eb2a99d
feat(security): fail-closed destination policy for outbound HTTP
seonghobae cf8adf1
docs: record PR #96 in the product-technical gap baseline
seonghobae 5aca11d
feat(security): harden destination policy per-IP CIDR and readiness o…
seonghobae 7cacaf1
feat(security): pin outbound HTTP to evaluated destination addresses
seonghobae 4b13313
feat(waf): evaluate live gateway transactions with in-process libcoraza
seonghobae d22ad23
docs: record PR #97 in the product-technical gap baseline
seonghobae ea62198
feat(store): require PostgreSQL as the production control plane
seonghobae 3a19ed9
feat(store): transactional outbox and leased workers
seonghobae 02ca9b9
feat(store): rustls for production PostgreSQL sslmode=require (#100)
seonghobae f3ea6ba
feat(store): optimistic concurrency on postgres snapshots
seonghobae 0812630
docs: record PR #105 in the product-technical gap baseline
seonghobae f84ece0
fix(store): keep postgres snapshot_version aligned after startup save
seonghobae 5516d38
feat(store): outbox consumers for TAXII, Clearfolio, and orchestrator
seonghobae 18fd115
docs: record PR #106 in the product-technical gap baseline
seonghobae 6831fbc
Merge pull request #106 from ContextualWisdomLab/feat/issue-81-outbox…
seonghobae 6a31ef0
feat(release): tagged GitHub Release with SHA-256 and immutable GHCR …
seonghobae 41e7047
Merge updated PR #95 base into optimistic concurrency stack
seonghobae f92f3aa
fix(control-plane): close OCC and credential race gaps
seonghobae 935b971
fix(release): capture pushed image digest
seonghobae File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,132 @@ | ||
| name: Release | ||
|
|
||
| on: | ||
| push: | ||
| tags: | ||
| - "v*.*.*" | ||
|
|
||
| permissions: | ||
| contents: write | ||
| packages: write | ||
| id-token: write | ||
| attestations: write | ||
|
|
||
| jobs: | ||
| release: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 | ||
| with: | ||
| fetch-depth: 0 | ||
| - name: Admit annotated vX.Y.Z tag only | ||
| run: scripts/admit-release-tag.sh "$GITHUB_REF_NAME" | ||
| - uses: dtolnay/rust-toolchain@4be7066ada62dd38de10e7b70166bc74ed198c30 # stable | ||
| with: | ||
| toolchain: stable | ||
| - uses: sigstore/cosign-installer@d7543c93d881b35a8faa02e8e3605f69b7a1ce62 # v3.10.0 | ||
| - uses: anchore/sbom-action/download-syft@a930d0ac434e3182448fe678398ba5713717112a # v0.21.0 | ||
| - name: Build release binary | ||
| run: cargo build --locked --release | ||
| - name: Stage binary and binary SBOM | ||
| run: | | ||
| mkdir -p dist | ||
| cp target/release/waf-ids-ai-soc dist/waf-ids-ai-soc-linux-x86_64 | ||
| scripts/release-sbom.sh --output dist/sbom.spdx.json dist/waf-ids-ai-soc-linux-x86_64 | ||
| - name: Publish GHCR image by digest | ||
| id: image | ||
| env: | ||
| GH_TOKEN: ${{ github.token }} | ||
| run: | | ||
| set -euo pipefail | ||
| echo "$GH_TOKEN" | docker login ghcr.io -u "$GITHUB_ACTOR" --password-stdin | ||
| image="ghcr.io/contextualwisdomlab/waf-ids-ai-soc" | ||
| tag="${GITHUB_REF_NAME}" | ||
| docker build -t "${image}:${tag}" . | ||
| push_out="$(docker push "${image}:${tag}")" | ||
| digest="$(printf '%s\n' "$push_out" | awk '{for (i=1;i<=NF;i++) if ($i ~ /^sha256:/) d=$i} END{print d}')" | ||
| test -n "$digest" | ||
| ref="${image}@${digest}" | ||
| printf '%s\n' "$ref" > dist/IMAGE-DIGEST.txt | ||
| scripts/release-sbom.sh --output dist/image.sbom.spdx.json "$ref" | ||
| echo "ref=${ref}" >> "$GITHUB_OUTPUT" | ||
| echo "digest=${digest}" >> "$GITHUB_OUTPUT" | ||
| echo "image=${image}" >> "$GITHUB_OUTPUT" | ||
| - name: Checksums and keyless blob signatures | ||
| run: | | ||
| set -euo pipefail | ||
| (cd dist && ../scripts/release-checksums.sh \ | ||
| waf-ids-ai-soc-linux-x86_64 \ | ||
| sbom.spdx.json \ | ||
| image.sbom.spdx.json \ | ||
| IMAGE-DIGEST.txt > SHA256SUMS) | ||
| cat dist/SHA256SUMS | ||
| cosign sign-blob --yes \ | ||
| --bundle dist/waf-ids-ai-soc-linux-x86_64.sigstore.json \ | ||
| dist/waf-ids-ai-soc-linux-x86_64 | ||
| cosign sign-blob --yes \ | ||
| --bundle dist/SHA256SUMS.sigstore.json \ | ||
| dist/SHA256SUMS | ||
| cosign sign-blob --yes \ | ||
| --bundle dist/sbom.spdx.json.sigstore.json \ | ||
| dist/sbom.spdx.json | ||
| cosign sign-blob --yes \ | ||
| --bundle dist/image.sbom.spdx.json.sigstore.json \ | ||
| dist/image.sbom.spdx.json | ||
| cosign sign-blob --yes \ | ||
| --bundle dist/IMAGE-DIGEST.txt.sigstore.json \ | ||
| dist/IMAGE-DIGEST.txt | ||
| - name: Sign image and attest image SBOM (keyless) | ||
| run: | | ||
| set -euo pipefail | ||
| ref="${{ steps.image.outputs.ref }}" | ||
| cosign sign --yes "$ref" | ||
| cosign attest --yes --predicate dist/image.sbom.spdx.json --type spdxjson "$ref" | ||
| - name: SLSA provenance for binary | ||
| uses: actions/attest-build-provenance@977bb373ede98d70efdf65b84cb5f73e068dcc2a # v3.0.0 | ||
| with: | ||
| subject-path: dist/waf-ids-ai-soc-linux-x86_64 | ||
| - name: SLSA provenance for image | ||
| uses: actions/attest-build-provenance@977bb373ede98d70efdf65b84cb5f73e068dcc2a # v3.0.0 | ||
| with: | ||
| subject-name: ghcr.io/contextualwisdomlab/waf-ids-ai-soc | ||
| subject-digest: ${{ steps.image.outputs.digest }} | ||
| push-to-registry: true | ||
| - name: Attest binary SBOM | ||
| uses: actions/attest-sbom@115c3be05ff3974bcbd596578934b3f9ce39bf68 # v2.2.0 | ||
| with: | ||
| subject-path: dist/waf-ids-ai-soc-linux-x86_64 | ||
| sbom-path: dist/sbom.spdx.json | ||
| - name: Attest image SBOM | ||
| uses: actions/attest-sbom@115c3be05ff3974bcbd596578934b3f9ce39bf68 # v2.2.0 | ||
| with: | ||
| subject-name: ghcr.io/contextualwisdomlab/waf-ids-ai-soc | ||
| subject-digest: ${{ steps.image.outputs.digest }} | ||
| sbom-path: dist/image.sbom.spdx.json | ||
| push-to-registry: true | ||
| - name: GitHub Release | ||
| env: | ||
| GH_TOKEN: ${{ github.token }} | ||
| run: | | ||
| set -euo pipefail | ||
| notes="$(mktemp)" | ||
| { | ||
| echo "Promotion authority is the image digest and Sigstore signatures, not the tag." | ||
| echo | ||
| echo "Image: \`${{ steps.image.outputs.ref }}\`" | ||
| echo "Tag alias: \`ghcr.io/contextualwisdomlab/waf-ids-ai-soc:${GITHUB_REF_NAME}\`" | ||
| echo | ||
| echo "Verify: \`docs/runbooks/release.md\`" | ||
| } > "$notes" | ||
| gh release create "$GITHUB_REF_NAME" \ | ||
| dist/waf-ids-ai-soc-linux-x86_64 \ | ||
| dist/SHA256SUMS \ | ||
| dist/sbom.spdx.json \ | ||
| dist/image.sbom.spdx.json \ | ||
| dist/IMAGE-DIGEST.txt \ | ||
| dist/waf-ids-ai-soc-linux-x86_64.sigstore.json \ | ||
| dist/SHA256SUMS.sigstore.json \ | ||
| dist/sbom.spdx.json.sigstore.json \ | ||
| dist/image.sbom.spdx.json.sigstore.json \ | ||
| dist/IMAGE-DIGEST.txt.sigstore.json \ | ||
| --notes-file "$notes" \ | ||
| --verify-tag |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| # Doctoring — CI attack-evidence battery (issue #11) | ||
|
|
||
| This note grounds the issue #11 slice: the compiled gateway binary is started | ||
| in CI with a hermetic libcoraza engine, a deterministic OWASP CRS attack | ||
| battery is fired over real HTTP, and every attempt must be blocked with the | ||
| cited CRS rule id and recorded as a security event that keeps the forwarded | ||
| client IP unmasked. | ||
|
|
||
| ## What is proven (and what is not) | ||
|
|
||
| Proven end to end on the real binary: operator-supplied `CORAZA_LIB_PATH` | ||
| loading, rules-file admission, per-transaction evaluation of method/URI/body, | ||
| block responses citing `coraza/crs: rule <id>`, benign traffic still | ||
| forwarding, and unmasked client attribution in `/api/events`. | ||
|
|
||
| Not proven: detection *quality* against arbitrary live traffic. The CI engine | ||
| is the build-script ABI stub (`src/coraza_abi_stub.rs`), a fixture that | ||
| mirrors the libcoraza C ABI, not Coraza itself. Quality evidence stays with an | ||
| operator deployment using a real libcoraza plus the OWASP Core Rule Set; this | ||
| slice only removes "the path was never exercised in CI" from the gap list. | ||
|
|
||
| ## Adopted standards and literature | ||
|
|
||
| OWASP Foundation. (n.d.). *OWASP Core Rule Set documentation*. | ||
| https://coreruleset.org/docs/ | ||
|
|
||
| - **Design impact:** Battery entries map to canonical CRS rule families — | ||
| 942100 SQLi (libinjection), 941100 XSS (libinjection), 930100 path | ||
| traversal, 932100 Unix command injection, 944120 Log4j JNDI. Rule ids in | ||
| block reasons and events stay CRS ids so operator dashboards read the same | ||
| vocabulary in CI evidence and production. | ||
|
|
||
| Scarfone, K., & Mell, P. (2007). *Guide to intrusion detection and prevention | ||
| systems (IDPS)* (NIST Special Publication 800-94). National Institute of | ||
| Standards and Technology. https://doi.org/NIST.SP.800-94 | ||
|
|
||
| - **Design impact:** IDPS evaluation distinguishes the detection *path* from | ||
| detection *efficacy*. SP 800-94's testing guidance motivates keeping the two | ||
| claims separate: CI asserts the prevention path (signature → interrupt → | ||
| block → record), while efficacy against evasive payloads requires curated | ||
| corpora and is explicitly out of scope for this fixture. | ||
|
|
||
| Saltzer, J. H., & Schroeder, M. D. (1975). The protection of information in | ||
| computer systems. *Proceedings of the IEEE*, *63*(9), 1278–1308. | ||
| https://doi.org/10.1109/PROC.1975.9939 | ||
|
|
||
| - **Design impact:** Complete mediation and fail-safe defaults. The battery | ||
| runs through the same route pipeline (`mode: block`) as production traffic, | ||
| so no test-only bypass exists; an engine that fails to load refuses startup | ||
| before bind instead of degrading silently. | ||
|
|
||
| MITRE. (n.d.). *CWE-20: Improper input validation*. MITRE Corporation. | ||
| https://cwe.mitre.org/data/definitions/20.html | ||
|
|
||
| - **Design impact:** The battery covers encoded variants (`%3Cscript`, | ||
| `%24%7BJNDI`, `..%2F`) because input-validation defects classically live at | ||
| decoding boundaries; the gateway evaluates the raw request line exactly as | ||
| received, so fixtures pin that behavior rather than a decoded copy. | ||
|
|
||
| ## Verification posture | ||
|
|
||
| - `tests/binary.rs::live_gateway_detects_owasp_attack_battery_end_to_end` | ||
| spawns the binary, creates the block route over the admin API, fires nine | ||
| battery cases (GET query attacks across five rule families plus a POST-body | ||
| XSS), asserts HTTP 403 + `engine=coraza` + cited rule id per case, asserts a | ||
| benign request forwards, and asserts `/api/events` records one event per | ||
| attempt with `X-Forwarded-For` preserved verbatim. | ||
| - `src/coraza_inprocess.rs::stub_engine_battery_matches_each_owasp_family` | ||
| pins the fixture contract itself, including first-match ordering so the | ||
| overlapping `; cat /etc/passwd` payload attributes to RCE (932100), not | ||
| traversal. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.