From 4289d30357913ae093e6f24e9a7dfcc952f2ac41 Mon Sep 17 00:00:00 2001 From: zhdsmy <434963561@qq.com> Date: Fri, 5 Jun 2026 09:06:38 +0800 Subject: [PATCH] fix(auth): accept hyphenated agent metadata (#1197) --- service/rpc/auth.go | 19 +++++++++++-------- service/rpc/auth_test.go | 20 ++++++++++++++++++++ 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/service/rpc/auth.go b/service/rpc/auth.go index 9f8fae12..cd6fb3c2 100644 --- a/service/rpc/auth.go +++ b/service/rpc/auth.go @@ -39,10 +39,7 @@ func (a *authHandler) check(ctx context.Context) (uint64, error) { return 0, status.Errorf(codes.Unauthenticated, "获取 metaData 失败") } - var clientSecret string - if value, ok := md["client_secret"]; ok { - clientSecret = strings.TrimSpace(value[0]) - } + clientSecret := firstMetadataValue(md, "client-secret", "client_secret") if clientSecret == "" { return 0, status.Error(codes.Unauthenticated, "客户端认证失败") @@ -50,10 +47,7 @@ func (a *authHandler) check(ctx context.Context) (uint64, error) { ip, _ := ctx.Value(model.CtxKeyRealIP{}).(string) - var clientUUID string - if value, ok := md["client_uuid"]; ok { - clientUUID = value[0] - } + clientUUID := firstMetadataValue(md, "client-uuid", "client_uuid") if _, err := uuid.ParseUUID(clientUUID); err != nil { // Keep this counter on the same trigger surface as the @@ -183,6 +177,15 @@ func (a *authHandler) check(ctx context.Context) (uint64, error) { return clientID, nil } +func firstMetadataValue(md metadata.MD, keys ...string) string { + for _, key := range keys { + if value, ok := md[key]; ok && len(value) > 0 { + return strings.TrimSpace(value[0]) + } + } + return "" +} + // authorizeAgentForUUID resolves a client UUID to the dashboard's internal // server ID, ensuring the resolved server is actually owned by the agent // secret's owner. Previously Check returned the resolved server ID without diff --git a/service/rpc/auth_test.go b/service/rpc/auth_test.go index 797da940..2bd7a14c 100644 --- a/service/rpc/auth_test.go +++ b/service/rpc/auth_test.go @@ -25,6 +25,14 @@ func authCheckWithSecret(secret, uuid string) (uint64, error) { return (&authHandler{}).Check(ctx) } +func authCheckWithHyphenatedSecret(secret, uuid string) (uint64, error) { + ctx := metadata.NewIncomingContext(context.Background(), metadata.Pairs( + "client-secret", secret, + "client-uuid", uuid, + )) + return (&authHandler{}).Check(ctx) +} + // authHandshakeUUID is RFC4122-shaped so it survives the uuid.ParseUUID gate // at the top of check(); setupAuthAgentFixture's "uuid-alice" / "uuid-bob" // only work for callers that bypass check() and exercise the inner helpers. @@ -88,6 +96,18 @@ func setupAuthHandshakeFixture(t *testing.T) func() { } } +func TestAuthCheckAcceptsHyphenatedMetadata(t *testing.T) { + defer setupAuthHandshakeFixture(t)() + + cid, err := authCheckWithHyphenatedSecret("alice-global", authHandshakeUUID) + if err != nil { + t.Fatalf("hyphenated metadata must authenticate: %v", err) + } + if cid != 11 { + t.Fatalf("expected server ID 11, got %d", cid) + } +} + // setupAuthAgentFixture seeds an in-memory DB and ServerShared with two // servers belonging to different users so we can assert that a secret bound // to user A cannot resolve a server UUID owned by user B.