Skip to content

Commit 19cd844

Browse files
committed
[TT-14494] improve error logging for JWKS URL handling - visor comments
1 parent 9ce9d86 commit 19cd844

3 files changed

Lines changed: 47 additions & 10 deletions

File tree

gateway/log_helpers.go

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ package gateway
33
import (
44
"encoding/json"
55
"errors"
6+
"net"
67
"net/http"
78
"net/url"
89
"strings"
10+
"syscall"
911

1012
"github.com/sirupsen/logrus"
1113

@@ -75,17 +77,43 @@ func (gw *Gateway) logJWKError(logger *logrus.Entry, jwkURL string, err error) {
7577
return
7678
}
7779

78-
// invalid content (JSON errors)
80+
// content/JSON errors
7981
var syntaxErr *json.SyntaxError
8082
var unmarshalErr *json.UnmarshalTypeError
8183
if errors.As(err, &syntaxErr) || errors.As(err, &unmarshalErr) || strings.Contains(err.Error(), "invalid character") {
8284
logger.WithError(err).Errorf("Invalid JWKS retrieved from endpoint: %s", jwkURL)
8385
return
8486
}
8587

86-
// network/URL errors (DNS, TCP, Refused)
88+
// network errors
8789
var urlErr *url.Error
88-
if errors.As(err, &urlErr) || strings.Contains(err.Error(), "dial tcp") || strings.Contains(err.Error(), "no such host") || strings.Contains(err.Error(), "connection refused") {
90+
var netOpErr *net.OpError
91+
var dnsErr *net.DNSError
92+
93+
if errors.As(err, &urlErr) {
94+
logger.WithError(err).Errorf("JWKS endpoint resolution failed: invalid or unreachable host %s", jwkURL)
95+
return
96+
}
97+
98+
// DNS errors
99+
if errors.As(err, &dnsErr) {
100+
logger.WithError(err).Errorf("JWKS endpoint resolution failed: invalid or unreachable host %s", jwkURL)
101+
return
102+
}
103+
104+
// connection refused
105+
if errors.As(err, &netOpErr) {
106+
if errors.Is(netOpErr, syscall.ECONNREFUSED) {
107+
logger.WithError(err).Errorf("JWKS endpoint resolution failed: invalid or unreachable host %s", jwkURL)
108+
return
109+
}
110+
}
111+
112+
// fallback check strings
113+
errStr := err.Error()
114+
if strings.Contains(errStr, "dial tcp") ||
115+
strings.Contains(errStr, "no such host") ||
116+
strings.Contains(errStr, "connection refused") {
89117
logger.WithError(err).Errorf("JWKS endpoint resolution failed: invalid or unreachable host %s", jwkURL)
90118
return
91119
}

gateway/log_helpers_test.go

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ package gateway
33
import (
44
"encoding/json"
55
"errors"
6+
"net"
67
"net/http/httptest"
78
"net/url"
9+
"syscall"
810
"testing"
911

1012
"github.com/sirupsen/logrus"
@@ -142,11 +144,9 @@ func TestGetLogEntryForRequest(t *testing.T) {
142144
}
143145

144146
func TestGatewayLogJWKError(t *testing.T) {
145-
// Setup logrus hook to capture logs
146147
logger, hook := test.NewNullLogger()
147148
entry := logrus.NewEntry(logger)
148149

149-
// We only need a minimal Gateway struct since logJWKError doesn't access Gateway fields
150150
gw := &Gateway{}
151151
testURL := "https://idp.example.com/jwks"
152152

@@ -185,6 +185,18 @@ func TestGatewayLogJWKError(t *testing.T) {
185185
expectedLog: "JWKS endpoint resolution failed: invalid or unreachable host " + testURL,
186186
shouldLog: true,
187187
},
188+
{
189+
name: "Net DNS Error",
190+
err: &net.DNSError{Err: "no such host", Name: "example.com"},
191+
expectedLog: "JWKS endpoint resolution failed: invalid or unreachable host " + testURL,
192+
shouldLog: true,
193+
},
194+
{
195+
name: "Net OpError (Connection Refused)",
196+
err: &net.OpError{Op: "dial", Err: syscall.ECONNREFUSED},
197+
expectedLog: "JWKS endpoint resolution failed: invalid or unreachable host " + testURL,
198+
shouldLog: true,
199+
},
188200
{
189201
name: "String error containing 'dial tcp'",
190202
err: errors.New("dial tcp: lookup failed"),
@@ -222,14 +234,11 @@ func TestGatewayLogJWKError(t *testing.T) {
222234
return
223235
}
224236

225-
// Verify log was written
226237
assert.Len(t, hook.Entries, 1)
227238
assert.Equal(t, logrus.ErrorLevel, hook.LastEntry().Level)
228239

229-
// Verify message matches ticket requirements
230240
assert.Equal(t, tc.expectedLog, hook.LastEntry().Message)
231241

232-
// Verify the original error is attached
233242
assert.Equal(t, tc.err, hook.LastEntry().Data["error"])
234243
})
235244
}

gateway/mw_jwt.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,14 +180,14 @@ func (k *JWTMiddleware) legacyGetSecretFromURL(url, kid, keyType string) (interf
180180
if !found {
181181
resp, err := client.Get(url)
182182
if err != nil {
183-
k.Logger().WithError(err).Errorf("JWKS endpoint resolution failed: invalid or unreachable host %s", url)
183+
k.Gw.logJWKError(k.Logger(), url, err)
184184
return nil, err
185185
}
186186
defer resp.Body.Close()
187187

188188
// Decode it
189189
if err := json.NewDecoder(resp.Body).Decode(&jwkSet); err != nil {
190-
k.Logger().WithError(err).Errorf("Invalid JWKS retrieved from endpoint: %s", url)
190+
k.Gw.logJWKError(k.Logger(), url, err)
191191
return nil, err
192192
}
193193

0 commit comments

Comments
 (0)