mirror of
https://github.com/shankar0123/certctl.git
synced 2026-06-12 08:38:57 +00:00
auth-bundle-1 Phase 0: extract internal/auth/ from middleware package
Bundle 1 / Phase 0: pure refactor splitting auth surface out of internal/api/middleware so Bundle 2 (OIDC + sessions) and the broader RBAC primitive (roles, permissions, scoped grants) have a clean home. Moved to internal/auth/: NamedAPIKey, HashAPIKey, AuthConfig, NewAuthWithNamedKeys, NewAuth, UserKey, AdminKey, GetUser, IsAdmin. Added testfixtures.go (WithActor / WithAdmin / WithActorAdmin) so handler tests don't construct context manually. Stayed in internal/api/middleware/: RequestID, Logging, NewLogging, Recovery, RateLimitConfig, NewRateLimiter (now imports auth.GetUser for per-user keying per audit Category C), CORSConfig, NewCORS, ContentType, CORS, GetRequestID, responseWriter, Chain, audit middleware (now imports auth.GetUser). Updated 22 caller files across cmd/, internal/api/handler/, internal/api/middleware/, internal/mcp/. Existing m008_admin_gate_test.go now scans for auth.IsAdmin( substring; Phase 3 will further evolve to track auth.RequirePermission. Behavior unchanged: all handler / middleware / service / connector / cmd / mcp tests pass with no test-logic edits, only import-path renames. Phase 0 exit criteria: internal/auth/ exists with 6 files; middleware.go went 575 -> 422 lines (auth-related ~150 lines moved out); grep -rE 'middleware\.(GetUser|IsAdmin|UserKey|AdminKey|NamedAPIKey|HashAPIKey|NewAuth)' returns 0 hits; context.WithValue(.*middleware.UserKey/AdminKey) returns 0 hits; go vet ./... clean; go test -short ./... green across all packages tested. Branch: dev/auth-bundle-1. Per cowork/auth-bundle-1-prompt.md, do not merge to master without (1) make verify green, (2) >= 2 external testers confirm, (3) >= 90% coverage on internal/auth/ in .github/coverage-thresholds.yml.
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
// Package auth holds the certctl auth surface: API-key validation, the
|
||||
// authenticated-actor context keys, and the helpers that consumers across
|
||||
// the codebase use to read the actor identity (rate limiter, audit
|
||||
// recorder, handler-level admin gates, GUI affordance hints).
|
||||
//
|
||||
// Bundle 1 / Phase 0 split this code out of internal/api/middleware so
|
||||
// Bundle 2 (OIDC + sessions) and the broader RBAC primitive (roles +
|
||||
// permissions + scoped grants) have a clean home that doesn't bloat the
|
||||
// generic-middleware package. Phase 0 is a pure refactor; behaviour
|
||||
// matches the pre-extract NewAuthWithNamedKeys / NewAuth surface
|
||||
// byte-for-byte.
|
||||
package auth
|
||||
|
||||
import "context"
|
||||
|
||||
// UserKey is the context key for storing the authenticated actor's
|
||||
// canonical name. Populated by Middleware (a.k.a. NewAuthWithNamedKeys)
|
||||
// from the matched NamedAPIKey.Name. Read by GetUser.
|
||||
type UserKey struct{}
|
||||
|
||||
// AdminKey is the context key for storing the admin flag. Populated by
|
||||
// Middleware from the matched NamedAPIKey.Admin. Read by IsAdmin.
|
||||
//
|
||||
// Bundle 1 keeps the boolean shape for backwards compatibility with the
|
||||
// pre-RBAC handler gates. Phase 3 introduces RequirePermission and the
|
||||
// boolean becomes informational only (admin role membership ↔ this flag).
|
||||
type AdminKey struct{}
|
||||
|
||||
// GetUser extracts the authenticated user from context. Returns the name
|
||||
// of the matched API key, or "" if the request was not authenticated
|
||||
// (none mode, missing Bearer, or a misconfigured chain).
|
||||
func GetUser(ctx context.Context) string {
|
||||
user, ok := ctx.Value(UserKey{}).(string)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
return user
|
||||
}
|
||||
|
||||
// IsAdmin extracts the admin flag from context. Returns true only when
|
||||
// the authenticated actor's NamedAPIKey carried Admin=true.
|
||||
//
|
||||
// Bundle 1 maintains the boolean for back-compat. Bundle 1 Phase 3
|
||||
// introduces auth.RequirePermission as the load-bearing authorization
|
||||
// gate; legacy IsAdmin callers (5 admin handlers tracked in M-008)
|
||||
// migrate to RequirePermission in that phase.
|
||||
func IsAdmin(ctx context.Context) bool {
|
||||
admin, ok := ctx.Value(AdminKey{}).(bool)
|
||||
return ok && admin
|
||||
}
|
||||
Reference in New Issue
Block a user