Skip to content

V1.1 tier c#25

Merged
mikeappsec merged 7 commits into
mainfrom
v1.1-tier-c
May 1, 2026
Merged

V1.1 tier c#25
mikeappsec merged 7 commits into
mainfrom
v1.1-tier-c

Conversation

@mikeappsec

Copy link
Copy Markdown
Owner

No description provided.

mikeappsec added 7 commits May 1, 2026 19:12
Four new cookbook recipes covering the enterprise operational workflows
referenced by Tier C1 (DOC-COOKBOOK-1):

- rotate-jwks: JWKS/IdP signing key rotation (dual-publish → drain → retire)
- policy-shadow-mode: shadow mode, canary evaluation, and decision diffing
- cache-invalidation: manual cache invalidation (Valkey keys, TTL tuning)
- valkey-outage-drill: controlled Valkey outage drill with recovery checklist

Update cookbook/README.md and mkdocs.yml nav with all four entries.
Add internal/admin package with:
- Middleware supporting mTLS and/or admin JWT authentication
- RBAC verb model: read_status, push_config, invalidate_cache,
  revoke_token, read_audit
- Role-to-verb mapping (configurable roles with named verb sets)
- Wildcard verb (*) for break-glass automation
- Context propagation of admin Identity for downstream handlers

Admin endpoint stubs mounted at /v1/admin/:
- GET  /v1/admin/status         (read_status)
- POST /v1/admin/cache/invalidate (invalidate_cache)
- POST /v1/admin/revoke         (revoke_token, stub for E2)
- GET  /v1/admin/audit          (read_audit, stub for D4)

Wired into pkg/lwauthd via Options.Admin; endpoints are mounted on
the existing HTTP listener behind the admin middleware. When
Admin.Enabled is false (default), /v1/admin/* returns 404.

Includes 7 unit tests covering disabled mode, no-credential 401,
mTLS success/forbidden/unmapped, and wildcard/specific verb checks.

Operator docs: docs/operations/admin-auth.md with config reference,
Helm wiring, and endpoint usage examples.
lwauthctl gains three new subcommands for GitOps workflows:

- promote: validate config, stamp spec.version (explicit or auto-
  generated timestamp), compute spec digest, emit canonical JSON
  for Git commit / kubectl apply.
- rollback: rewrite spec.version to a previous value, re-validate,
  emit YAML.
- drift: compare local config (version + SHA-256 digest) against live
  AuthConfig status.appliedVersion / status.appliedDigest via kubectl.
  Exit 1 on drift for CI gating.

Supporting changes:
- config.AuthConfig gains spec.version field (opaque operator tag).
- AuthConfigStatus gains appliedVersion and appliedDigest fields.
- Controller setReady() populates both on successful compile+swap.
- specDigest() computes sha256 of canonical JSON spec encoding.

Operator docs: docs/operations/gitops.md with CI examples, drift
check scheduling, and promote/rollback workflows.
TC1  (High): validate K8s resource names, prepend '--' to kubectl args
TC2  (High): add RequireMTLS config for AND-composition of mTLS+JWT
TC3  (Medium): enforce MaxTokenLifetime (default 15min, exp-iat check)
TC4  (Medium): per-IP rate limiter on admin endpoints (10 rps, burst 20)
TC5  (Medium): reject non-HTTPS JWKS URLs at config time
TC6  (Low): warn on wildcard '*' verb in role config
TC7  (Low): validate cache-invalidation scope against allowlist
TC8  (Low): reject path-traversal ('..') in --out flag
TC9  (Info): return generic 'forbidden' in 403 body
TC10 (Info): canonical sorted-key JSON for deterministic digests
…cket impl

- New pkg/httputil package provides reusable HTTP middleware:
  - KeyedLimiter interface (Allow(key) bool)
  - TokenBucketLimiter: per-key token-bucket with injectable clock
  - RateLimitMiddleware / RateLimitHandler: 429 + Retry-After wrapper
  - IPKeyFunc: common key extractor
- Refactored internal/admin/handler.go to use pkg/httputil instead of
  inline rate-limiter struct, reducing ~45 lines of duplicated logic.
- Full test coverage in pkg/httputil/ratelimit_test.go.
…L4 dynamic Retry-After

- RL1 (High): IPKeyFunc now uses net.SplitHostPort to strip ephemeral
  port, ensuring all connections from the same IP share one bucket.
- RL2 (Medium): Background goroutine evicts idle buckets every 60s
  (threshold = max(burst/rps, 60s)) to bound memory growth.
- RL4 (Info): Retry-After computed from 1/rps instead of hardcoded 1.
- Added TestIPKeyFunc_StripsPort covering IPv4 and IPv6.
@mikeappsec
mikeappsec merged commit af9866b into main May 1, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant