Commit Graph

4 Commits

Author SHA1 Message Date
Jon Chery 5013209e31 feat(P3): nft SNAT+DNAT + orca init ingress bootstrap (REQ-173)
nft emitter (internal/emitter/nft.go):
- Add DNATTarget field (C-51: validated via net.ParseIP; injection
  guard). Default 127.0.0.1; proxmox native uses LXC bridge IP.
- Add EnableSNAT field (default true for zero-value config).
- Add postrouting masquerade chain (research Topic 1):
  ip saddr 127.0.0.0/8 oifname != lo masquerade
- Shift input/forward priority from filter (=0) to -10 (research
  Topic 2: pve-firewall coexistence — avoids same-priority undefined
  evaluation order).

internal/ingress/bootstrap.go (new):
- BootstrapLocalIngress: mkdir dirs, push step-ca root CA (C-60:
  certpaths.CACertPath not CAPath), render+write traefik static
  config (C-58: preserves traefik-on-public-ip opt-out), render+
  write+apply nft ruleset, pre-create table (C-55: avoids first-
  apply flush-table error), ensure podman container. All non-fatal.

init.go: Step 4d now calls ingress.BootstrapLocalIngress (R-024).
doctor_nft.go: assert postrouting masquerade + priority -10.

Tests: nft_test.go — DNATTarget substitution, invalid DNATTarget
rejection (C-51), EnableSNAT=false omits postrouting, priority -10.

---ci---
project: orca
phase: 3
milestone: v0.14
status: execute
---/ci---
2026-08-10 20:09:26 +00:00
Jon Chery 4b70e31cf4 fix(P02): input validation + injection hardening — 11 vectors (REQ-150)
Critical fixes:
- logs --job: validate ^[A-Za-z0-9_-]+$ + shellQuote (was %q backtick RCE)
- pprof: isLoopback treats empty host as bind-all (was :6060 bypass)
- backup restore: filepath.Rel containment check (was tar-slip via a/../..)
- WebAuthn reg auth deferred to P04 (requires session infra)

High fixes:
- txn rollback/show/apply: validate ^T-[0-9a-f]{16}$ + shellQuote
- nft diff --against: validate txn ID before filepath.Join
- drain stopAlloc: validate allocID ^[A-Za-z0-9_-]+$
- cluster_compat: shellQuote peer dir name
- podman image: shellQuote (was %q backtick injection)
- nft TrustedProbes: net.ParseIP/CIDR validation + split v4/v6 sets
- sudoers: validate --proxmox-user/--proxmox-role ^[a-zA-Z_][a-zA-Z0-9_-]{0,31}$
  fixed path /etc/sudoers.d/orca; shellQuote pveum/useradd; validateSudoers
  checks actual file
- nft country block: validate ^[A-Z]{2}$ (was len==2 only)

New file: internal/cli/validate.go (shared validators + shellQuote)
All 38 Go test packages pass. go vet + gofmt clean.

---ci---
project: orca
phase: 2
milestone: v0.13
status: complete
requirements:
  covered: [150]
---/ci---
2026-08-07 19:28:01 +00:00
Jon Chery a6bd1385ab fix(P18): nftables ruleset hardening (REQ-133, F21)
---ci---
project: orca
phase: 18
milestone: v0.12
status: execute
---/ci---

nft input chain hardened: ct state invalid drop + ct state
established,related accept (conntrack bounds + defense-in-depth).
Tests pass. Build green.
2026-08-07 11:27:33 +00:00
Jon Chery 8d1cdceb5c feat(P15.5): threat model (C-19) + ingress hybrid (R-017, REQ-099..102) + doctor mTLS (REQ-118)
Sub-wave 1: internal/emitter/nft.go (nftables emitter, DNAT :443→127.0.0.1:8443, rate-limit, SYN-flood filter); Traefik static config 127.0.0.1:8443 binding (D-220); orca doctor nft; orca nft CLI (show/diff/doctor/country-block/rate-limit).
Sub-wave 2: docs/threat-model.md (R-017 trust boundary, R-020 deadlock, D-234 secret exclusion, orca user blast radius, step-ca SPOF); orca doctor mTLS (chain verification + live handshake probe, C5).

---ci---
project: orca
phase: 15.5
milestone: v0.11
status: execute
---/ci---
2026-08-07 08:35:06 +00:00