Skip to content

feat: add JWT authentication for gRPC clients - #1987

Open
CooooolFrog wants to merge 1 commit into
dragonflyoss:mainfrom
CooooolFrog:feat/grpc-jwt-auth
Open

feat: add JWT authentication for gRPC clients#1987
CooooolFrog wants to merge 1 commit into
dragonflyoss:mainfrom
CooooolFrog:feat/grpc-jwt-auth

Conversation

@CooooolFrog

Copy link
Copy Markdown

Description

Add JWT authentication support for inter-component gRPC communication in the Dragonfly Rust Client.

This change introduces:

  • A new dragonfly-client-auth crate.
  • JWT generation and verification compatible with the protocol implemented in dragonflyoss/dragonfly.
  • Shared HMAC keys loaded from Base64-encoded secret files.
  • Support for disabled, permissive, and required modes.
  • Unary and streaming gRPC interceptors.
  • JWT credentials for calls to Manager and Scheduler.
  • JWT credentials for peer and dfdaemon Upload calls.
  • JWT credentials for dfctl task preheat.
  • Authentication for the dfdaemon Upload gRPC server.
  • Component-specific JWT audiences.
  • Token caching and refresh before expiration.
  • Support for multiple trusted keys and kid-based key rotation.
  • Authentication metrics.
  • Shared Go/Rust interoperability test vectors.

Authentication remains disabled by default. Existing configuration files that do not contain grpcAuth continue to load with the default disabled configuration.

Existing public tracing interceptor types remain compatible. JWT authentication is enabled through the new authenticated constructors without changing the existing public client field types.

Validation performed:

  • cargo check --workspace --all-targets.
  • cargo test --workspace --all-targets.
  • cargo clippy --workspace --all-targets -- -D warnings.
  • cargo fmt --check.
  • Authentication, configuration, request, and client tests.
  • Shared Go/Rust JWT interoperability tests.

Related Issue

Related to dragonflyoss/dragonfly#4417

Motivation and Context

Manager and Scheduler authentication alone is insufficient because dfdaemon, Seed Client, peers, and command-line clients also participate in internal gRPC communication.

This PR implements the Rust side of the shared JWT protocol so Go and Rust components can authenticate each other without introducing a new protobuf API or an external token-issuing service.

The three authentication modes support a simple rolling-upgrade process:

  • disabled preserves the existing behavior.
  • permissive sends JWTs while allowing requests from older callers that have not yet been upgraded.
  • required enforces authentication after all callers have been upgraded.

Old servers ignore the additional authorization metadata sent by upgraded clients. New permissive servers continue to accept old callers without credentials. This allows old and new components to coexist
during the first authenticated rollout.

Screenshots (if appropriate)

N/A

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation Update (if none of the other choices apply)

Checklist

  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.

@codecov

codecov Bot commented Aug 13, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 61.72070% with 307 lines in your changes missing coverage. Please review.
✅ Project coverage is 52.03%. Comparing base (1bdea4a) to head (ef1b110).

Files with missing lines Patch % Lines
dragonfly-client-auth/src/lib.rs 71.05% 189 Missing ⚠️
dragonfly-client/src/bin/dfctl/task.rs 0.00% 33 Missing ⚠️
dragonfly-client/src/grpc/scheduler.rs 0.00% 24 Missing ⚠️
dragonfly-client/src/grpc/interceptor.rs 9.09% 20 Missing ⚠️
dragonfly-client/src/grpc/dfdaemon_upload.rs 0.00% 15 Missing ⚠️
dragonfly-client/src/dynconfig/mod.rs 0.00% 9 Missing ⚠️
dragonfly-client-metric/src/lib.rs 0.00% 8 Missing ⚠️
dragonfly-client/src/grpc/manager.rs 64.28% 5 Missing ⚠️
dragonfly-client-request/src/lib.rs 78.94% 4 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #1987      +/-   ##
==========================================
+ Coverage   51.71%   52.03%   +0.31%     
==========================================
  Files         100      101       +1     
  Lines       27222    27986     +764     
==========================================
+ Hits        14078    14562     +484     
- Misses      13144    13424     +280     
Files with missing lines Coverage Δ
dragonfly-client-config/src/dfdaemon.rs 91.81% <ø> (ø)
dragonfly-client-request/src/selector.rs 95.21% <100.00%> (+0.06%) ⬆️
dragonfly-client-request/src/lib.rs 61.06% <78.94%> (+0.39%) ⬆️
dragonfly-client/src/grpc/manager.rs 29.06% <64.28%> (+6.09%) ⬆️
dragonfly-client-metric/src/lib.rs 76.28% <0.00%> (-0.54%) ⬇️
dragonfly-client/src/dynconfig/mod.rs 0.00% <0.00%> (ø)
dragonfly-client/src/grpc/dfdaemon_upload.rs 0.00% <0.00%> (ø)
dragonfly-client/src/grpc/interceptor.rs 14.81% <9.09%> (-6.40%) ⬇️
dragonfly-client/src/grpc/scheduler.rs 0.00% <0.00%> (ø)
dragonfly-client/src/bin/dfctl/task.rs 0.00% <0.00%> (ø)
... and 1 more

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@CooooolFrog CooooolFrog added the enhancement New feature or request label Aug 13, 2026
Signed-off-by: CooooolFrog <zuliangwanghust@gmail.com>
@CooooolFrog CooooolFrog changed the title feat(auth): add JWT authentication for gRPC clients feat: add JWT authentication for gRPC clients Aug 13, 2026

@gaius-qi gaius-qi left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should not build our own token issuance and key rotation. With HS256 the secret must be shared with every verifier, including dfdaemon on every node, so any compromised node can forge
Manager tokens, and we take on key distribution/rotation forever.

Use Kubernetes-issued tokens instead:

Client: projected service account token with our audience (e.g. urn:dragonfly:grpc:manager) + grpc-go's built-in credentials/jwt.NewTokenFileCallCredentials. Rotation is handled by
kubelet.
Server: keep this PR's interceptor and permissive mode, but verify against the cluster JWKS (/openid/v1/jwks) instead of an HMAC keyring.
This gives asymmetric signing, per-workload identity (sub), pod-bound revocation, zero secret management — and deletes roughly half of this PR.

Prior art: Istio (proxies auth to istiod with projected tokens — closest to our case), Teleport (TokenReview or static JWKS for out-of-cluster verifiers), Vault, SPIRE, AWS IRSA. Bare-metal
support can follow Teleport's static-JWKS approach later.

Also: the design doc should go to dragonflyoss/design (kebab-case dir under systems-analysis/), not docs/design/ here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Assignees

Couldn't load assignees.