Skip to content
Merged
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
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- **security**: control-plane admin authentication (`BARBACANE_CONTROL_ADMIN_TOKEN`), CORS allowlist (`BARBACANE_CONTROL_ALLOWED_ORIGINS`).
- **security**: `.bca` Ed25519 signing (`BARBACANE_SIGNING_KEY`) and verify-on-load against a pinned key (`BARBACANE_TRUSTED_PUBKEY`), plus per-plugin/spec/route checksum verification on load.
- **security**: WASM plugin SSRF guard (blocks loopback/link-local/private/metadata egress; `BARBACANE_ALLOW_INTERNAL_EGRESS` to override) and redirect following disabled.
- **security**: WASM plugin capability enforcement — plugins may only import host functions covered by the capabilities declared in `plugin.toml`.
- **security**: `jwt-auth` performs real signature verification via the host `verify_signature` capability (inline JWK).
- **security**: a security testing framework — adversarial integration suite (`crates/barbacane-test/tests/security/`) and `cargo-fuzz` targets (`fuzz/`).
- **docs**: [Configuration & environment variables](reference/configuration.md) reference.

### Changed (breaking, secure-by-default)

- The control plane refuses to start without `BARBACANE_CONTROL_ADMIN_TOKEN`, and all API routes (except `/health` and the data-plane WebSocket) require the bearer token.
- `file://` secret references require `BARBACANE_SECRETS_DIR` and are confined to it.
- MCP requires a valid session for non-`initialize` requests.
- Plugin HTTP egress to internal/metadata addresses is blocked by default.

### Fixed

- **security**: fail-open middleware short-circuit downgrade in the WASM chain.
- **security**: panic on hostile `x-request-id` / `traceparent`; unbounded Prometheus path-label cardinality on unmatched routes.
- **deps**: bump `anyhow` to 1.0.103 (RUSTSEC-2026-0190).

## [0.7.0] - 2026-05-05

Headline: AI gateway extensions land — caller-owned model, glob-based dynamic routing, stateless Responses API, aggregated model catalog, and four new policy middlewares (ADR-0024 + ADR-0030).
Expand Down
7 changes: 5 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ FROM gcr.io/distroless/cc-debian12:nonroot
# OCI labels for GitHub Container Registry
LABEL org.opencontainers.image.source="https://github.com/barbacane-dev/barbacane"
LABEL org.opencontainers.image.description="Barbacane API Gateway - Data Plane"
LABEL org.opencontainers.image.licenses="Apache-2.0"
LABEL org.opencontainers.image.licenses="AGPL-3.0-only"

# Copy the binary from builder
COPY --from=builder /usr/local/bin/barbacane /barbacane
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile.control
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ FROM debian:bookworm-slim
# OCI labels for GitHub Container Registry
LABEL org.opencontainers.image.source="https://github.com/barbacane-dev/barbacane"
LABEL org.opencontainers.image.description="Barbacane API Gateway - Control Plane"
LABEL org.opencontainers.image.licenses="Apache-2.0"
LABEL org.opencontainers.image.licenses="AGPL-3.0-only"

# Install runtime dependencies and nginx for serving UI
RUN apt-get update && apt-get install -y --no-install-recommends \
Expand Down
13 changes: 13 additions & 0 deletions Dockerfile.standalone
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,18 @@ RUN mkdir -p /plugins && \
# ---------------------------------------------------------------------------
FROM debian:bookworm-slim

# OCI labels
LABEL org.opencontainers.image.source="https://github.com/barbacane-dev/barbacane"
LABEL org.opencontainers.image.description="Barbacane API Gateway - Standalone"
LABEL org.opencontainers.image.licenses="AGPL-3.0-only"

RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \
&& rm -rf /var/lib/apt/lists/*

# Create non-root user
RUN groupadd -r barbacane && useradd -r -g barbacane barbacane

# Binary
COPY --from=binary-builder /usr/local/bin/barbacane /usr/local/bin/barbacane

Expand All @@ -90,4 +98,9 @@ COPY --from=plugin-builder /plugins/ /plugins/
COPY docker/plugins.yaml /etc/barbacane/plugins.yaml

WORKDIR /workspace
RUN chown -R barbacane:barbacane /workspace

# Run as non-root (gateway listens on a high port; no privileged bind needed)
USER barbacane

ENTRYPOINT ["barbacane"]
22 changes: 21 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ clean:
# Test & Lint
# -----------------------------------------------------------------------------

.PHONY: test test-verbose test-one check clippy fmt fmt-check
.PHONY: test test-verbose test-one check clippy fmt fmt-check security-test security-test-build fuzz-build

test:
cargo test --workspace
Expand All @@ -89,6 +89,24 @@ test-verbose:
test-one:
cargo test --workspace $(TEST) -- --nocapture

# Adversarial security suite (Layer 1). Tests assert hardened behaviour, so they
# are RED until each finding is fixed. Needs the binaries the harness drives:
# `barbacane` (data plane), `barbacane-control` (control plane, needs Postgres +
# DATABASE_URL), and the WASM plugins (`make plugins`).
# See docs/contributing/security-testing.md.
security-test: plugins
cargo build -p barbacane -p barbacane-control
cargo test -p barbacane-test --test security -- --nocapture

# Compile-only check of the security suite (does not require running services).
security-test-build:
cargo test -p barbacane-test --test security --no-run

# Build (not run) the standalone cargo-fuzz targets on stable, to catch bit-rot.
# Actually fuzzing needs nightly + cargo-fuzz: `cd fuzz && cargo +nightly fuzz run <target>`.
fuzz-build:
cd fuzz && cargo build --bins

check: fmt-check clippy

clippy:
Expand Down Expand Up @@ -189,6 +207,8 @@ help:
@echo " make release Build release"
@echo " make test Run all tests"
@echo " make test-verbose Run tests with output"
@echo " make security-test Run the adversarial security suite (RED until fixed)"
@echo " make fuzz-build Build the cargo-fuzz targets (run with +nightly)"
@echo " make test-one TEST=name"
@echo " make check Run fmt-check + clippy"
@echo " make clippy Run clippy lints"
Expand Down
25 changes: 23 additions & 2 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,22 @@ Forward-looking priorities for Barbacane. See [CHANGELOG.md](CHANGELOG.md) for w

Actively being worked on:

- _(open — pick up from Next)_
### Security hardening (in progress)

A security review drove a hardening pass. Landed on `security/hardening-and-test-framework`:

- [x] **Control-plane authentication** — admin bearer token (`BARBACANE_CONTROL_ADMIN_TOKEN`) required on all routes except `/health` and the data-plane WebSocket; server fails closed without it. CORS tightened to an allowlist (`BARBACANE_CONTROL_ALLOWED_ORIGINS`).
- [x] **Artifact integrity & signing** — `.bca` now carries an Ed25519 signature over its content hash; the data plane recomputes every plugin/spec/route checksum and verifies the signature against a pinned key (`BARBACANE_TRUSTED_PUBKEY`) on load. Sign at compile with `BARBACANE_SIGNING_KEY`.
- [x] **MCP session enforcement** — non-`initialize` requests without a valid session are rejected (no more header-omission bypass).
- [x] **Plugin egress SSRF guard** — the WASM host HTTP client rejects loopback/link-local/private/metadata targets and no longer follows redirects (override with `BARBACANE_ALLOW_INTERNAL_EGRESS`).
- [x] **`jwt-auth` real verification** — signatures verified via the host `verify_signature` capability (inline JWK); the test-only skip flag is ignored in production builds.
- [x] **Secret confinement** — `file://` secret references confined to `BARBACANE_SECRETS_DIR`.
- [x] **Security test framework** — adversarial integration suite (`crates/barbacane-test/tests/security/`) + `cargo-fuzz` targets (`fuzz/`). See `docs/contributing/security-testing.md`.
- [x] **WASM capability enforcement** — all 33 official `plugin.toml`s migrated to the canonical `host_functions` dialect (verified against each plugin's real wasm imports); the data plane runs `validate_imports` on load and rejects any plugin importing a host function outside its declared capabilities. Enforced when the artifact's capabilities are authoritative (`capabilities_enforced`), i.e. compiled from `plugin.toml`.

In flight:

- [ ] **Control-plane capability persistence** — the registry does not yet store plugin capabilities, so control-plane-compiled artifacts are capability-less and load without enforcement. Add a capabilities column + parse `plugin.toml` on plugin upload/seed so control-plane artifacts are enforced too.

---

Expand Down Expand Up @@ -51,7 +66,7 @@ Committed but not yet scheduled. Grouped by concern.
| RBAC | P2 | Role-based access control for control plane API |
| Plugin registry | P2 | Central registry for discovering and versioning plugins |
| Data plane groups | P2 | Deploy to specific subsets of data planes |
| Artifact signing | P2 | GPG/private-key signing + verification on load |
| Artifact signing | | Ed25519 signing + verify-on-load shipped (security hardening); remaining: key distribution/rotation tooling, optional Sigstore/transparency-log |
| Health metrics collection | P2 | Aggregate CPU, memory, request rates from data planes |
| Multi-tenancy | P3 | Organization/team isolation with SNI-based routing |

Expand Down Expand Up @@ -112,6 +127,12 @@ The first three rungs of the trusted spec-to-run pipeline are shipped (artifact
| E1032 validation | P2 | Warn on OpenAPI security scheme without matching auth middleware |
| OPA WASM compilation | P1 | Define OPA version, compilation flags, error handling |
| Auth plugin auditing | P1 | Security review process for auth plugins |
| Ingress timeouts & limits | P1 | Header-read/idle/handshake timeouts, connection cap, streaming body-size limit on the data plane (wire the parsed `--keepalive-timeout`) |
| Per-plugin secret & capability scope | P1 | Scope resolved secrets per plugin; complete the per-plugin default-deny host-function linker + migrate official `plugin.toml` capability dialects |
| Plugin SDK hardening helpers | P2 | Shared SDK helpers: constant-time secret compare, trusted-proxy client-IP extraction, RFC-9457 errors, CRLF-safe headers (removes per-plugin drift) |
| WASM execution budget | P2 | Epoch-interruption wall-clock deadline + host-imposed timeouts/body caps on blocking host calls |
| CI/supply-chain hardening | P2 | SHA-pin third-party Actions, scope job token permissions, `cargo deny check` (licenses/bans/sources) as a gate, SBOM + image signing |
| Control-plane container non-root | P2 | Run `barbacane-control` (nginx) as non-root (high port or capability) |
| Trace volume guidance | P1 | Documentation for managing trace volume at scale |
| Integration tests | P2 | Full control plane API lifecycle tests with PostgreSQL |
| Compile safety CI | P2 | Fitness functions: deterministic build verification, fuzz testing |
Expand Down
1 change: 1 addition & 0 deletions crates/barbacane-compiler/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ categories.workspace = true
chrono = { workspace = true }
hex = { workspace = true }
home = "0.5"
ring = { workspace = true }
reqwest = { workspace = true, features = ["blocking"] }
serde = { workspace = true }
serde_json = { workspace = true }
Expand Down
Loading