fix(oidc): test seam for jwksProbeClient — closes the B5 R6 httptest regression

CI break diagnosed from go-build-and-test on 47da13e+596e675:
TestTestDiscovery_HappyPath_AgainstMockIdP + TestTestDiscovery_JWKSFetchFails
fail with "refusing to dial reserved address 127.0.0.1" because my
Bundle 5 R6 closure wrapped jwksReachable in
validation.SafeHTTPDialContext — which is exactly what the production
guard is supposed to refuse for httptest.NewServer's 127.0.0.1 bind.

Same shape as the Slack/Teams test-seam fix in 596e675: factor the
http.Client construction into a package-level var (`jwksProbeClient`),
default to the SSRF-safe transport in production, override to
http.DefaultTransport in test-only `setup_test.go::init()`. Production
code never reassigns the var. The audit R6 closure stands — the
production jwksReachable still uses validation.SafeHTTPDialContext.

Verification (sandbox, Go 1.25.10):
  go test -short -count=1
    -run 'TestTestDiscovery_HappyPath|TestTestDiscovery_JWKSFetchFails'
    ./internal/auth/oidc                                # PASS (1.1s)
  go test -short -count=1 ./internal/auth/oidc          # PASS (21.8s)
  gofmt -l                                              # clean
  go vet ./internal/auth/oidc                           # clean
This commit is contained in:
shankar0123
2026-05-13 01:30:47 +00:00
parent 264015059d
commit 4e8fb16fc2
2 changed files with 51 additions and 11 deletions
+19 -11
View File
@@ -157,22 +157,30 @@ func (s *Service) TestDiscovery(ctx context.Context, issuerURL string) (*TestDis
// 10-second timeout matches the package-wide oidcOutboundTimeout
// budget so token endpoint + JWKS + userinfo probes share the same
// wall-clock horizon.
// jwksProbeClient is the *http.Client used by jwksReachable. Package-
// level var so the test suite can swap it for an SSRF-guard-bypassed
// client when exercising jwksReachable against httptest.NewServer
// (which binds to 127.0.0.1 and would otherwise be refused by
// validation.SafeHTTPDialContext). Mirrors the
// internal/connector/notifier/webhook + slack + teams test-seam
// pattern. Production code never reassigns this var.
var jwksProbeClient = &http.Client{
Timeout: oidcOutboundTimeout,
Transport: &http.Transport{
DialContext: validation.SafeHTTPDialContext(oidcOutboundTimeout),
MaxIdleConns: 10,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
},
}
var jwksReachable = func(ctx context.Context, jwksURI string) (bool, error) {
req, err := http.NewRequestWithContext(ctx, http.MethodGet, jwksURI, nil)
if err != nil {
return false, err
}
client := &http.Client{
Timeout: oidcOutboundTimeout,
Transport: &http.Transport{
DialContext: validation.SafeHTTPDialContext(oidcOutboundTimeout),
MaxIdleConns: 10,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
},
}
resp, err := client.Do(req)
resp, err := jwksProbeClient.Do(req)
if err != nil {
return false, err
}