From ccf5dc34e9061b416989d76a2c1a5345430c18ed Mon Sep 17 00:00:00 2001 From: Chris Lu Date: Thu, 30 Jul 2026 12:23:12 -0700 Subject: [PATCH] test: stop comparing two JWTs minted a second apart (#10495) TestProxyReadDropsCallerJwtQueryParam mints a read token up front and requires the token the volume server would evaluate to equal it byte for byte. The expiry claim has one-second resolution -- GenJwtForVolumeServer sets it from jwt.NewNumericDate(time.Now().Add(...)) -- so two mints on either side of a tick produce different strings for the same authority and the same file, and the assertion fails for a reason the test is not about. It surfaces on the 32-bit job, where the runner is slow enough that the HEAD subtest (the second one, after a full proxy round trip) lands in a later second than the mint at the top of the test. Confirmed directly: minting the same file id with the same key either side of a boundary yields different tokens. Assert what the test is actually about instead -- that the credential decodes against the read key and authorizes this file id -- which holds whatever second it is minted in, and is a closer statement of the property than string equality. --- .../filer_server_handlers_proxy_test.go | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/weed/server/filer_server_handlers_proxy_test.go b/weed/server/filer_server_handlers_proxy_test.go index 46c6fe18f..d6babddad 100644 --- a/weed/server/filer_server_handlers_proxy_test.go +++ b/weed/server/filer_server_handlers_proxy_test.go @@ -79,12 +79,6 @@ func (v *proxyTestVolume) requireReached(t *testing.T) { // header, so a caller-supplied one would outrank the token the filer attaches // on a read -- the credential the volume server evaluates has to be the filer's. func TestProxyReadDropsCallerJwtQueryParam(t *testing.T) { - minted := &FilerServer{volumeGuard: security.NewGuard([]string{}, proxyTestWriteKey, 10, proxyTestReadKey, 10)} - want := minted.maybeGetVolumeReadJwtAuthorizationToken(proxyTestFileId) - if want == "" { - t.Fatal("no read token minted despite a configured read key") - } - for _, method := range []string{http.MethodGet, http.MethodHead} { t.Run(method, func(t *testing.T) { volume := newProxyTestVolume(t) @@ -98,8 +92,19 @@ func TestProxyReadDropsCallerJwtQueryParam(t *testing.T) { if got := volume.seenEffectiveJwt(); got == "caller-supplied" { t.Fatal("caller's jwt query param outranked the filer-minted token") } - if got := volume.seenEffectiveJwt(); got != want { - t.Fatalf("volume server would evaluate %q, want the minted token %q", got, want) + // The credential has to be a filer-minted read token for THIS file. + // Comparing it against a separately minted token would also say that, + // but only within the second that minted both: the expiry claim has + // one-second resolution, so two mints either side of a tick differ in + // the encoded string while carrying the same authority and file id. + claims := &security.SeaweedFileIdClaims{} + if _, err := security.DecodeJwt(security.SigningKey(proxyTestReadKey), + security.EncodedJwt(volume.seenEffectiveJwt()), claims); err != nil { + t.Fatalf("volume server would evaluate %q, which does not validate against the read key: %v", + volume.seenEffectiveJwt(), err) + } + if claims.Fid != proxyTestFileId { + t.Fatalf("token authorizes file %q, want %q", claims.Fid, proxyTestFileId) } if q := volume.seenRawQuery(); strings.Contains(q, "jwt=") { t.Fatalf("jwt survived in the forwarded query: %q", q)