mirror of
https://github.com/shankar0123/certctl.git
synced 2026-06-07 14:11:31 +00:00
docs: v2.1.0 release polish — strip internal bundle/phase tags, update status for OIDC ship
README:
- Rewrite Status block: drop the stale 'federated identity not yet
shipped' line; flag v2.1.0 OIDC + sessions + back-channel logout
+ break-glass as early-access; encourage GitHub issues for IdP
rough edges. (A1 framing — keep early-access umbrella, no
SAML/WebAuthn/JIT roadmap teaser.)
- Add OIDC SSO bullet to 'What it does' covering per-IdP runbooks,
group-claim → role mapping, AES-256-GCM client_secret encryption,
JWKS auto-refresh, PKCE-S256, RFC 9700 §4.7.1 pre-login binding,
RFC 9207 iss check, __Host- cookies, CSRF rotation, idle+absolute
expiry, BCL, break-glass admin.
- Update Security paragraph: three auth paths (API keys / OIDC /
break-glass), HMAC-signed sessions, CSRF rotation, RFC OIDC BCL.
- Correct CI coverage thresholds against
.github/coverage-thresholds.yml (service 70%, handler 75%,
crypto 88%, auth packages 85-95%); 'static analysis' replaces
the inflated '11 linters' claim (actual count is 4 active).
Docs B3 sweep — strip operator-facing 'Bundle N' / 'Phase N' tags:
- docs/operator/auth-threat-model.md — rewrite intro; rename 5 H2
sections (API-key + RBAC defenses / OIDC + sessions + break-glass
defenses / OIDC + sessions threat catalogue / Closed federated-
identity threats / Future-work threats); clean ~12 H3/prose hits.
- docs/operator/rbac.md — strip Bundle 1 framing from intro,
scope_id deferral note, MCP tools section, day-0 bootstrap, and
'Where to look next'.
- docs/operator/auth-benchmarks.md — drop 'Phase 14' framing from
title intro, hardware floor caption, result table caption,
methodology, and pre-merge audit section.
- docs/operator/security.md — already cleaned earlier this session
(RBAC / day-0 / approval-bypass / OIDC federation / sessions /
OIDC first-admin / break-glass H3s).
- docs/operator/oidc-runbooks/{index,keycloak,authentik,okta,
azure-ad}.md — strip Auth Bundle 2 framing + Phase 10/3/4
references; replace with feature-name prose.
- docs/operator/legacy-clients-tls-1.2.md — drop Bundle F / M-023
audit-reference framing; keep CWE-326.
- docs/operator/database-tls.md — drop Bundle B / M-018 framing
from intro + Helm section.
- docs/operator/runbooks/disaster-recovery.md — drop 'Production
hardening II Phase 10' status callout.
- docs/migration/oidc-enable.md — retitle 'Enable OIDC SSO';
strip Bundle 1/2 framing from prereqs, troubleshooting, related
docs; update __Host- cookie callout from 'audit MED-14' to
v2.1.0-BREAKING.
- docs/migration/api-keys-to-rbac.md — strip Bundle 1 framing from
intro, migration table, IsAdmin section, and cross-references.
- docs/migration/acme-from-cert-manager.md — strip residual
'Phase 5' tags from cert-manager integration test references.
- docs/reference/configuration.md — retitle Auth section.
- docs/reference/profiles.md — strip Bundle 1 Phase 9 framing
from RequiresApproval section + Related list.
- docs/reference/auth-standards-implemented.md — rewrite intro
(API-key + RBAC + OIDC + sessions + back-channel logout +
break-glass); rename 'Bundle 1 (RBAC) standards covered
separately' H2; clean per-row Phase references.
- docs/README.md — rewrite nav-table entries to drop Bundle 1/2
parentheticals; retitle 'Enable OIDC SSO' migration entry.
No code or test changes; pure operator-facing prose polish for
the v2.1.0 tag.
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
> Last reviewed: 2026-05-10
|
||||
|
||||
This document is an honest informational reference for operators, external testers, and acquirers who want to know which RFCs and standards Auth Bundle 1 (RBAC) and Auth Bundle 2 (OIDC + sessions + back-channel logout + break-glass) implement, and which CWE weakness classes the implementation closes. Every row points at a real file or migration in this repository.
|
||||
This document is an honest informational reference for operators, external testers, and acquirers who want to know which RFCs and standards certctl's authentication surface (API keys + RBAC + OIDC + sessions + back-channel logout + break-glass admin) implements, and which CWE weakness classes the implementation closes. Every row points at a real file or migration in this repository.
|
||||
|
||||
This document is intentionally NOT a compliance-mapping doc. The operator retired the framework-mapping subtree (`docs/compliance/{index,soc2,pci-dss,nist-sp-800-57}.md`) on 2026-05-05; framework-name-drops (SOC 2 / PCI-DSS / HIPAA / NIST SSDF / FedRAMP) are also swept from prose mentions across `README.md` and `docs/` per that decision. RFC and CWE references stay because they are precise technical pointers; framework labels were marketing-flavored and prone to overclaim. If you are an auditor mapping certctl's controls to a framework, treat the rows below as evidence and do the framework mapping yourself against the framework you are auditing against.
|
||||
|
||||
@@ -17,15 +17,15 @@ Each row carries at least one negative test (a test that asserts the fail-closed
|
||||
| RFC 6749 (OAuth 2.0) | Authorization-code grant via OIDC; confidential-client credentials only | `internal/auth/oidc/service.go` (HandleAuthRequest, HandleCallback) | `internal/auth/oidc/service_test.go` (21+ negatives covering wrong aud / wrong iss / expired / etc.) |
|
||||
| RFC 7636 (PKCE) | S256 challenge mandatory; `plain` rejected at the service-layer sentinel; verifier persisted in pre-login row, single-use | `internal/auth/oidc/service.go` (oauth2.S256ChallengeOption hard-coded), `internal/auth/oidc/prelogin.go` | `TestService_PKCEPlainRejectedSentinel`, `TestService_StateReplayDeniedByConsumeOnce` |
|
||||
| RFC 7519 (JWT) | ID-token validation via go-oidc; service-layer alg allow-list (RS256/RS512/ES256/ES384/EdDSA); HS-family + `none` rejected | `internal/auth/oidc/service.go` (disallowedAlgs map, isDisallowedAlg) | `TestService_HandleCallback_RejectsHSAlgsConfusion`, `TestService_IdPDowngradeDefense_RejectsHSAdvertised` |
|
||||
| RFC 7517 (JWK) | JWKS fetch + cache + rotation handled transparently by coreos/go-oidc; operator-triggered RefreshKeys + auto-refresh on TTL expiry | `internal/auth/oidc/service.go` (RefreshKeys; cfg.JWKSCacheTTLSeconds default 3600) | `TestService_RefreshKeys_CatchesPostLoadDowngrade`, `TestKeycloakIntegration_JWKSRotation_RefreshKeysPicksUpNewKey` (Phase 10 integration) |
|
||||
| OIDC Core 1.0 §3.1.3.7 | `iss` exact match, `aud` membership, `azp` for multi-aud, `at_hash` REQUIRED-when-access_token-present (Phase 3 tightening of the spec MAY → MUST), `nonce` constant-time-compare | `internal/auth/oidc/service.go` (HandleCallback steps 5-9) | `TestService_HandleCallback_RejectsWrongAudience`, `TestService_HandleCallback_AZPRequiredOnMultiAud`, `TestService_HandleCallback_ATHashRequiredWhenAccessTokenPresent`, `TestService_HandleCallback_RejectsNonceMismatch` |
|
||||
| RFC 7517 (JWK) | JWKS fetch + cache + rotation handled transparently by coreos/go-oidc; operator-triggered RefreshKeys + auto-refresh on TTL expiry | `internal/auth/oidc/service.go` (RefreshKeys; cfg.JWKSCacheTTLSeconds default 3600) | `TestService_RefreshKeys_CatchesPostLoadDowngrade`, `TestKeycloakIntegration_JWKSRotation_RefreshKeysPicksUpNewKey` (Keycloak integration) |
|
||||
| OIDC Core 1.0 §3.1.3.7 | `iss` exact match, `aud` membership, `azp` for multi-aud, `at_hash` REQUIRED-when-access_token-present (certctl tightens the spec MAY → MUST), `nonce` constant-time-compare | `internal/auth/oidc/service.go` (HandleCallback steps 5-9) | `TestService_HandleCallback_RejectsWrongAudience`, `TestService_HandleCallback_AZPRequiredOnMultiAud`, `TestService_HandleCallback_ATHashRequiredWhenAccessTokenPresent`, `TestService_HandleCallback_RejectsNonceMismatch` |
|
||||
| OIDC Core 1.0 §5.3.2 (UserInfo endpoint) | Optional fallback when ID-token groups claim is empty; bounded by configured FetchUserinfo bool | `internal/auth/oidc/service.go` (fetchUserinfoGroups) | 4-case userinfo-fallback matrix in `service_test.go` (happy + endpoint-missing + endpoint-failing + userinfo-also-empty) |
|
||||
| OpenID Connect Back-Channel Logout 1.0 | `events` claim + `sid`/`sub` revocation; `nonce` MUST be absent; `jti`-based replay defense | `internal/api/handler/auth_session_oidc.go` (BackChannelLogout, DefaultBCLVerifier) | 6 negatives in `auth_session_oidc_test.go`: BCL missing events, BCL nonce-present, BCL unknown-key-sig, etc. |
|
||||
| RFC 6265 (HTTP State Management) | Session cookie attributes: `Secure` + `HttpOnly` + `SameSite=Lax` (default; configurable to Strict via `CERTCTL_SESSION_SAMESITE`); `Path=/`; host-only | `internal/auth/session/service.go` (cookie minting), `internal/api/handler/auth_session_oidc.go` (Set-Cookie wiring) | Phase 6 middleware-chain test matrix (7 cases) in `internal/auth/session/middleware_test.go` |
|
||||
| RFC 6265 (HTTP State Management) | Session cookie attributes: `Secure` + `HttpOnly` + `SameSite=Lax` (default; configurable to Strict via `CERTCTL_SESSION_SAMESITE`); `Path=/`; host-only | `internal/auth/session/service.go` (cookie minting), `internal/api/handler/auth_session_oidc.go` (Set-Cookie wiring) | 7-case middleware-chain test matrix in `internal/auth/session/middleware_test.go` |
|
||||
| RFC 9700 (OAuth 2.0 Security Best Current Practice) | PKCE mandatory; no implicit flow; strict redirect_uri (registered + exact-match per OIDCProvider.RedirectURI); state non-guessable (32-byte random); single-use | `internal/auth/oidc/service.go`; `OIDCProvider.Validate()` enforces redirect_uri shape | `TestOIDCProvider_Validate_RejectsHTTPRedirectInProd`, state-replay test |
|
||||
| RFC 8414 (OAuth 2.0 Authorization Server Metadata) | Discovery doc fetched via go-oidc at provider creation + RefreshKeys; `id_token_signing_alg_values_supported` consulted for IdP-downgrade-attack defense | `internal/auth/oidc/service.go` (getOrLoad, guardAdvertisedAlgs) | `TestService_IdPDowngradeDefense_RejectsHSAdvertised` and `RejectsNoneAdvertised` |
|
||||
| RFC 7633 (X.509 TLS Feature Extension; Must-Staple) | Per-profile certctl issuance flag; out-of-scope for Bundle 2 but cited here because RFC 7633 OID `id-pe-tlsfeature` is in the same crypto-stack umbrella | `internal/connector/issuer/local/local.go` | Bundle 9 SCEP master-bundle Phase 5.6 tests; not Bundle-2 territory |
|
||||
| RFC 8555 §7 (ACME directory metadata) | certctl-side ACME server tier; out-of-scope for Bundle 2 but cited because it shares the alg-pinning + nonce-handling discipline that Bundle 2 carries forward | `internal/api/handler/acme/*` | per-route handler tests in `internal/api/handler/acme/` |
|
||||
| RFC 7633 (X.509 TLS Feature Extension; Must-Staple) | Per-profile certctl issuance flag; out-of-scope for the auth surface but cited here because RFC 7633 OID `id-pe-tlsfeature` is in the same crypto-stack umbrella | `internal/connector/issuer/local/local.go` | SCEP master-bundle must-staple tests; not auth-surface territory |
|
||||
| RFC 8555 §7 (ACME directory metadata) | certctl-side ACME server tier; out-of-scope for the auth surface but cited because it shares the alg-pinning + nonce-handling discipline the auth surface carries forward | `internal/api/handler/acme/*` | per-route handler tests in `internal/api/handler/acme/` |
|
||||
| RFC 7515 (JWS) | JWS verification delegated to go-oidc/v3 + go-jose/v4; alg pin enforced at `gooidc.NewIDTokenVerifier` config + service-layer re-check | `internal/auth/oidc/service.go` (oauthConfig + verifier wiring) | `TestService_HandleCallback_RejectsExpired` and `TestService_HandleCallback_RejectsIATInFuture` |
|
||||
|
||||
## Table 2: CWE / weakness classes the implementation closes
|
||||
@@ -34,28 +34,28 @@ Each row points at the file(s) that implement the defense and the test file(s) t
|
||||
|
||||
| CWE | Description | Where defended | Where pinned |
|
||||
|---|---|---|---|
|
||||
| CWE-287 (Improper Authentication) | Session-cookie HMAC verification (length-prefixed input defeats concat-collision) + alg-pinned ID-token verify | `internal/auth/session/service.go` (computeHMAC, parseCookie, Validate); `internal/auth/oidc/service.go` (HandleCallback) | `TestComputeHMAC_LengthPrefixDefeatsConcatCollision`; `TestService_Validate_ConcatenationCollisionDefeatedByLengthPrefix`; full Phase 3 21+ negatives matrix |
|
||||
| CWE-352 (Cross-Site Request Forgery) | Double-submit cookie + `SameSite=Lax`/`Strict` + hashed CSRF token on session row; constant-time compare in CSRFMiddleware | `internal/auth/session/middleware.go` (CSRFMiddleware) | Phase 6 7-case middleware-chain matrix (`internal/auth/session/middleware_test.go`); `TestSessionMiddleware_CSRFRequiredOnStateChangingMethods` |
|
||||
| CWE-287 (Improper Authentication) | Session-cookie HMAC verification (length-prefixed input defeats concat-collision) + alg-pinned ID-token verify | `internal/auth/session/service.go` (computeHMAC, parseCookie, Validate); `internal/auth/oidc/service.go` (HandleCallback) | `TestComputeHMAC_LengthPrefixDefeatsConcatCollision`; `TestService_Validate_ConcatenationCollisionDefeatedByLengthPrefix`; full 21+ OIDC negatives matrix |
|
||||
| CWE-352 (Cross-Site Request Forgery) | Double-submit cookie + `SameSite=Lax`/`Strict` + hashed CSRF token on session row; constant-time compare in CSRFMiddleware | `internal/auth/session/middleware.go` (CSRFMiddleware) | 7-case middleware-chain matrix (`internal/auth/session/middleware_test.go`); `TestSessionMiddleware_CSRFRequiredOnStateChangingMethods` |
|
||||
| CWE-384 (Session Fixation) | Session ID is opaque random `ses-<base64url>` (32 bytes entropy) generated server-side at login; cookie value rotates on every login (no inheritance from pre-login); CSRF token rotates alongside | `internal/auth/session/service.go` (Create, RotateCSRFToken) | `TestService_Create_AssignsFreshSessionID`; CSRF rotation pinned via `TestService_RotateCSRFToken_AfterLogin` |
|
||||
| CWE-294 (Authentication Bypass by Capture-Replay) | Single-use state, single-use nonce (both stored in pre-login row, atomic `DELETE...RETURNING` on consume); single-use authorization code (Keycloak/IdP-side); `jti`-based BCL replay defense | `internal/auth/oidc/prelogin.go` (LookupAndConsume); `internal/api/handler/auth_session_oidc.go` (BCL handler) | `TestService_StateReplayDeniedByConsumeOnce`; `TestService_HandleCallback_RejectsForgedPreLoginCookie`; BCL replay negative in handler tests |
|
||||
| CWE-916 / CWE-329 (Use of Password Hash With Insufficient Computational Effort / Use of a Key Past its Expiration Date) | Argon2id with OWASP 2024 params (m=64 MiB, t=3, p=4, 16-byte salt, 32-byte output) for break-glass passwords; per-credential random salt; PHC-format hash | `internal/auth/breakglass/service.go` (HashPassword, VerifyPassword); v3 ciphertext blob format with PBKDF2-SHA256 600,000 rounds for config-at-rest encryption | `TestPhase7_5_HashPasswordOWASP2024Params`; `TestPhase7_5_HashFormatPHC`; `internal/crypto/encryption_test.go` for v3 PBKDF2 floor |
|
||||
| CWE-307 (Improper Restriction of Excessive Authentication Attempts) | Failure count + lockout window on break-glass credential; threshold default 5, reset window default 1h, lockout duration default 30s; atomic single-statement IncrementFailure defeats concurrent racing attempts | `internal/auth/breakglass/service.go` (Login, IncrementFailure); `internal/repository/postgres/breakglass.go` | `TestPhase7_5_LockoutAfterThresholdFailures`; `TestPhase7_5_FailureCountResetsAfterWindow` |
|
||||
| CWE-345 (Insufficient Verification of Data Authenticity) | OIDC `at_hash` REQUIRED-when-access_token-present ties access token to ID token (Phase 3 tightening of OIDC core MAY → MUST); OIDC `iss` + `aud` + `azp` checks ensure token came from the configured IdP for the configured client | `internal/auth/oidc/service.go` (HandleCallback steps 5-9, atHashMatches) | `TestService_HandleCallback_ATHashRequiredWhenAccessTokenPresent`; `TestService_HandleCallback_RejectsATHashMismatch` |
|
||||
| CWE-200 (Information Exposure) | Token-leak hygiene tests on every secret-bearing path: ID tokens, access tokens, refresh tokens, authorization codes, PKCE verifiers, state, nonce, signing keys, break-glass passwords NEVER appear in any log line at any level | `internal/auth/oidc/service.go`, `internal/auth/session/service.go`, `internal/auth/breakglass/service.go` (all log calls audited); `internal/service/audit_redact.go` (Bundle 6 redactor) | `internal/auth/oidc/logging_test.go` (4 grep-asserts); `internal/auth/breakglass/service_test.go` (token-leak hygiene + json.Marshal probe); `internal/auth/bootstrap/service_test.go` (Bundle 1 pattern) |
|
||||
| CWE-345 (Insufficient Verification of Data Authenticity) | OIDC `at_hash` REQUIRED-when-access_token-present ties access token to ID token (certctl tightens OIDC core MAY → MUST); OIDC `iss` + `aud` + `azp` checks ensure token came from the configured IdP for the configured client | `internal/auth/oidc/service.go` (HandleCallback steps 5-9, atHashMatches) | `TestService_HandleCallback_ATHashRequiredWhenAccessTokenPresent`; `TestService_HandleCallback_RejectsATHashMismatch` |
|
||||
| CWE-200 (Information Exposure) | Token-leak hygiene tests on every secret-bearing path: ID tokens, access tokens, refresh tokens, authorization codes, PKCE verifiers, state, nonce, signing keys, break-glass passwords NEVER appear in any log line at any level | `internal/auth/oidc/service.go`, `internal/auth/session/service.go`, `internal/auth/breakglass/service.go` (all log calls audited); `internal/service/audit_redact.go` (audit redactor) | `internal/auth/oidc/logging_test.go` (4 grep-asserts); `internal/auth/breakglass/service_test.go` (token-leak hygiene + json.Marshal probe); `internal/auth/bootstrap/service_test.go` (canonical pattern) |
|
||||
| CWE-770 (Allocation of Resources Without Limits or Throttling) | Per-IP rate limit on `/auth/breakglass/login` via the global middleware.NewRateLimiter (default RPS / burst from `CERTCTL_RATE_LIMIT_*` env vars) wrapped around the entire mux; the breakglass login endpoint inherits this protection. Per-route override available via `middleware.NewRateLimiter` per-bucket configuration if the operator wants stricter caps | `cmd/server/main.go` (rateLimiter wiring at the root middleware stack); `internal/api/middleware/middleware.go` (NewRateLimiter) | `internal/api/middleware/ratelimit_test.go`; `internal/api/middleware/ratelimit_keyed_test.go` |
|
||||
| CWE-330 (Use of Insufficiently Random Values) | `crypto/rand` for state, nonce, PKCE verifier (via `oauth2.GenerateVerifier`), session signing keys (32 random bytes), session IDs (`ses-<base64url-no-pad>` from 32 random bytes), pre-login IDs (`pl-<base64url-no-pad>` from 16 random bytes), CSRF tokens (32 random bytes), break-glass salts (16 random bytes via `crypto/rand`) | `internal/auth/oidc/service.go` (randomB64URL); `internal/auth/session/service.go` (newOpaqueID, newCSRFToken); `internal/auth/oidc/prelogin.go` (newID); `internal/auth/breakglass/service.go` (HashPassword salt) | `TestPreLoginAdapter_CreatePreLogin_RNGFailure` (entropy-source error path); RNG failure pinned for every callsite |
|
||||
| CWE-311 (Missing Encryption of Sensitive Data) | OIDC `client_secret` AES-256-GCM encrypted at rest (v3 blob format: magic 0x03 + salt(16) + nonce(12) + ciphertext+tag); session signing keys same scheme; empty `CERTCTL_CONFIG_ENCRYPTION_KEY` returns `ErrEncryptionKeyRequired` (fail-closed) | `internal/crypto/encryption.go` (EncryptIfKeySet, DecryptIfKeySet); `internal/api/handler/auth_session_oidc.go` (encryptClientSecret); `internal/auth/session/service.go` (KeyMaterialEncrypted) | `internal/repository/postgres/oidc_encryption_invariant_test.go` (Phase 13 invariant test: ciphertext != plaintext, v2/v3 blob shape, round-trip + wrong-passphrase fails) |
|
||||
| CWE-326 (Inadequate Encryption Strength) | TLS 1.3 only on the certctl control plane (post-v2.2 milestone); HSTS-equivalent posture via HTTPS-only listener; AES-256-GCM for at-rest config encryption; PBKDF2-SHA256 600,000 rounds for v3 blob key derivation (OWASP 2024 floor) | `cmd/server/main.go` (TLS 1.3 listener config); `internal/crypto/encryption.go` (v3 PBKDF2 iteration count) | `TestServerTLSConfig_RejectsTLS12` (Bundle 5); `TestEncryption_V3IterationCount_PinnedAtOWASP2024Floor` |
|
||||
| CWE-311 (Missing Encryption of Sensitive Data) | OIDC `client_secret` AES-256-GCM encrypted at rest (v3 blob format: magic 0x03 + salt(16) + nonce(12) + ciphertext+tag); session signing keys same scheme; empty `CERTCTL_CONFIG_ENCRYPTION_KEY` returns `ErrEncryptionKeyRequired` (fail-closed) | `internal/crypto/encryption.go` (EncryptIfKeySet, DecryptIfKeySet); `internal/api/handler/auth_session_oidc.go` (encryptClientSecret); `internal/auth/session/service.go` (KeyMaterialEncrypted) | `internal/repository/postgres/oidc_encryption_invariant_test.go` (invariant test: ciphertext != plaintext, v2/v3 blob shape, round-trip + wrong-passphrase fails) |
|
||||
| CWE-326 (Inadequate Encryption Strength) | TLS 1.3 only on the certctl control plane (post-v2.2 milestone); HSTS-equivalent posture via HTTPS-only listener; AES-256-GCM for at-rest config encryption; PBKDF2-SHA256 600,000 rounds for v3 blob key derivation (OWASP 2024 floor) | `cmd/server/main.go` (TLS 1.3 listener config); `internal/crypto/encryption.go` (v3 PBKDF2 iteration count) | `TestServerTLSConfig_RejectsTLS12`; `TestEncryption_V3IterationCount_PinnedAtOWASP2024Floor` |
|
||||
| CWE-1004 (Sensitive Cookie Without HttpOnly) | Session cookie set with `HttpOnly=true`; CSRF cookie intentionally `HttpOnly=false` so the GUI can read it for the `X-CSRF-Token` header (the read is by-design per the double-submit-cookie pattern) | `internal/auth/session/service.go` (cookie attrs); `internal/api/handler/auth_session_oidc.go` (Set-Cookie wiring) | Cookie-attribute pinning in handler tests; documented in [auth-threat-model.md](../operator/auth-threat-model.md) "Session minting + cookies" subsection |
|
||||
| CWE-614 (Sensitive Cookie in HTTPS Session Without 'Secure' Attribute) | Session + CSRF cookies set with `Secure=true`; rejected at cookie-write time on `http://` listeners (HTTPS-only control plane post-v2.2) | `internal/auth/session/service.go`; `cmd/server/main.go` HTTPS-only listener | TLS-listener tests in `cmd/server/`; cookie attrs pinned in handler tests |
|
||||
| CWE-1275 (Sensitive Cookie with Improper SameSite Attribute) | Session cookie `SameSite=Lax` default (configurable to Strict via `CERTCTL_SESSION_SAMESITE`); CSRF defense via the double-submit pattern means `Lax` is sufficient even if the operator does not flip to Strict | `internal/auth/session/service.go` (cookie attrs); `internal/config/config.go` (SAMESITE env var) | Cookie-attribute pinning; SameSite enforcement is per-cookie |
|
||||
|
||||
## Bundle 1 (RBAC) standards covered separately
|
||||
## API-key + RBAC standards covered separately
|
||||
|
||||
The above tables focus on Bundle 2's OIDC + sessions + back-channel logout + break-glass surface. Bundle 1's RBAC primitive carries its own implementation pointers; the Bundle 1 [`auth-threat-model.md`](../operator/auth-threat-model.md) section "Defenses Bundle 1 ships" enumerates the full RBAC + bootstrap + auditor + approval-workflow surface. CWE-pointers that apply to Bundle 1's surface:
|
||||
The above tables focus on the OIDC + sessions + back-channel logout + break-glass surface. The RBAC primitive carries its own implementation pointers; the [`auth-threat-model.md`](../operator/auth-threat-model.md) section "API-key + RBAC defenses" enumerates the full RBAC + bootstrap + auditor + approval-workflow surface. CWE-pointers that apply to the RBAC surface:
|
||||
|
||||
- CWE-285 (Improper Authorization) — defended by the Phase 3 RequirePermission middleware + Authorizer.CheckPermission service-layer call. Pinned by 90+ tests across `internal/auth/` and `internal/service/auth/`.
|
||||
- CWE-862 (Missing Authorization) — pinned by Phase 12's `phase12_protocol_allowlist_test.go` (asserts protocol endpoints are explicitly allowlisted, NOT silently bypassing the gate).
|
||||
- CWE-285 (Improper Authorization) — defended by the RequirePermission middleware + Authorizer.CheckPermission service-layer call. Pinned by 90+ tests across `internal/auth/` and `internal/service/auth/`.
|
||||
- CWE-862 (Missing Authorization) — pinned by `phase12_protocol_allowlist_test.go` (asserts protocol endpoints are explicitly allowlisted, NOT silently bypassing the gate).
|
||||
- CWE-863 (Incorrect Authorization) — pinned by the auditor-split invariant in `internal/domain/auth/auditor_test.go` (auditor role holds exactly `audit.read` + `audit.export` ONLY).
|
||||
- CWE-732 (Incorrect Permission Assignment for Critical Resource) — five admin-only fine-grained perms (`cert.bulk_revoke`, `crl.admin`, `scep.admin`, `est.admin`, `ca.hierarchy.manage`) seeded into `r-admin` only; pinned by migration 000030 + `r-admin`-only seed test.
|
||||
|
||||
@@ -74,10 +74,10 @@ If you are an external tester, an operator's auditor, or an acquirer doing techn
|
||||
- [`auth-threat-model.md`](../operator/auth-threat-model.md) — threat model behind these defenses.
|
||||
- [`security.md`](../operator/security.md) — overall security posture.
|
||||
- [`oidc-runbooks/index.md`](../operator/oidc-runbooks/index.md) — per-IdP operator setup guides.
|
||||
- [`auth-benchmarks.md`](../operator/auth-benchmarks.md) — Phase 14 perf baselines for the validation paths cited above.
|
||||
- [`auth-benchmarks.md`](../operator/auth-benchmarks.md) — performance baselines for the validation paths cited above.
|
||||
- `internal/auth/oidc/` — OIDC service + groupclaim resolver + pre-login adapter + bootstrap hook.
|
||||
- `internal/auth/session/` — Session service + middleware + CSRF + signing-key rotation.
|
||||
- `internal/auth/breakglass/` — break-glass admin (Argon2id + lockout + constant-time + surface-invisibility).
|
||||
- `internal/crypto/encryption.go` — AES-256-GCM v3 blob format for at-rest encryption.
|
||||
- `migrations/000029` through `000038` — schema for RBAC, OIDC providers, sessions, signing keys, users, group mappings, pre-login, break-glass.
|
||||
- `scripts/ci-guards/multi-tenant-query-coverage.sh` — Phase 13 forward-compat multi-tenant query coverage.
|
||||
- `scripts/ci-guards/multi-tenant-query-coverage.sh` — forward-compat multi-tenant query coverage guard.
|
||||
|
||||
Reference in New Issue
Block a user