mirror of
https://github.com/lukaszraczylo/traefikoidc.git
synced 2026-10-15 04:18:03 +00:00
Audit review (rounds 1-31): fix confirmed issues, remove dead code, harden tests
Security/correctness fixes: - fail-open token validation preserved with lenient-audience; access token that fails verification and has no ID token to corroborate now fails closed - token_manager blacklist-expiry: fix impossible tautology (x>24h && x<24h) - constant-time OAuth state compare; clear state/nonce/code_verifier on callback token-exchange failure to prevent replay of half-failed flows - StopAllTasks gated on last-instance close - background-task panic recovery; remove task-registry counter leak - circuit breaker half-open: release probe slot; CB + per-session outcome recorded once per refresh operation, not once per waiter - Redis connection pool: handle nil receive when pool closed concurrently - FileStore: atomic temp-write + rename - errors_recovery health-check data race -> atomic Test-isolation / hardening: - reset helpers for Once-pinned global cache manager and transport pool - coverage: utils 70->93% (redirect URL security contract); fuzz targets for bearer parsers; concurrent ServeHTTP race tests for the shared request path Dead-code removal (verified orphaned, build+suite green): internal/providers (30 files, 0 importers), internal/compat, internal/features, input_validation. Verified: govulncheck, go mod tidy, yaegi-validate, cross-compile (darwin+ linux), golangci-lint (new-from-rev clean), 3x full race+shuffle green.
This commit is contained in:
+28
-12
@@ -60,21 +60,37 @@ var (
|
||||
|
||||
// GetTransportPool returns the global transport pool instance
|
||||
func GetTransportPool() *TransportPool {
|
||||
transportPoolOnce.Do(func() {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
globalTransportPool = &TransportPool{
|
||||
transports: make(map[string]*sharedTransport),
|
||||
maxConns: 20,
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
clientCount: 0,
|
||||
maxClients: 5,
|
||||
}
|
||||
go globalTransportPool.cleanupRoutine(ctx)
|
||||
})
|
||||
if globalTransportPool == nil {
|
||||
transportPoolOnce.Do(func() {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
globalTransportPool = &TransportPool{
|
||||
transports: make(map[string]*sharedTransport),
|
||||
maxConns: 20,
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
clientCount: 0,
|
||||
maxClients: 5,
|
||||
}
|
||||
go globalTransportPool.cleanupRoutine(ctx)
|
||||
})
|
||||
}
|
||||
return globalTransportPool
|
||||
}
|
||||
|
||||
// resetGlobalTransportPoolForTest clears the process-global transport pool so the
|
||||
// next call to GetTransportPool returns a fresh instance, and cancels the
|
||||
// current pool's cleanup goroutine. Required for order-independent tests that
|
||||
// replace the global pool: the singleton is sync.Once-guarded, so without a
|
||||
// reset a consumed Once leaves GetTransportPool returning nil and later callers
|
||||
// panic on a nil receiver (see TestCreateHTTPClient_Fallback).
|
||||
func resetGlobalTransportPoolForTest() {
|
||||
if globalTransportPool != nil && globalTransportPool.cancel != nil {
|
||||
globalTransportPool.cancel()
|
||||
}
|
||||
transportPoolOnce = sync.Once{}
|
||||
globalTransportPool = nil
|
||||
}
|
||||
|
||||
// DefaultTransportConfig returns a secure default configuration
|
||||
func DefaultTransportConfig() TransportConfig {
|
||||
return TransportConfig{
|
||||
|
||||
@@ -476,11 +476,13 @@ func TestCreateHTTPClient(t *testing.T) {
|
||||
|
||||
// TestCreateHTTPClient_Fallback tests fallback when pool is exhausted
|
||||
func TestCreateHTTPClient_Fallback(t *testing.T) {
|
||||
// Override global pool with limited one
|
||||
originalPool := globalTransportPool
|
||||
defer func() {
|
||||
globalTransportPool = originalPool
|
||||
}()
|
||||
// Replace the global pool with a full one. resetGlobalTransportPoolForTest
|
||||
// is required: the global is sync.Once-guarded, so overriding the var
|
||||
// alone would be clobbered by GetTransportPool's once-body, and restoring
|
||||
// a nil original after the Once was consumed would leave later callers
|
||||
// panicking on a nil receiver.
|
||||
resetGlobalTransportPoolForTest()
|
||||
defer resetGlobalTransportPoolForTest()
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
@@ -504,9 +506,17 @@ func TestCreateHTTPClient_Fallback(t *testing.T) {
|
||||
return
|
||||
}
|
||||
|
||||
// When the pool is exhausted, GetTransport returns nil and CreateHTTPClient
|
||||
// falls back to a basic client: timeout set, no transport, no redirect policy.
|
||||
if client.Timeout != timeout {
|
||||
t.Errorf("Client timeout should be %v, got %v", timeout, client.Timeout)
|
||||
}
|
||||
if client.Transport != nil {
|
||||
t.Error("Fallback client should have no transport")
|
||||
}
|
||||
if client.CheckRedirect != nil {
|
||||
t.Error("Fallback client should have no redirect policy")
|
||||
}
|
||||
}
|
||||
|
||||
// TestTransportPool_ConcurrentAccess tests concurrent access to transport pool
|
||||
|
||||
Reference in New Issue
Block a user