Skip to content

Commit c154c3e

Browse files
committed
[apiserver/tunnelnode] Consolidate Token deps
1 parent 44f9a3d commit c154c3e

File tree

4 files changed

+50
-32
lines changed

4 files changed

+50
-32
lines changed

pkg/apiserver/controllers/tunnelnode.go

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -30,30 +30,28 @@ type TunnelNodeReconciler struct {
3030

3131
jwksHost string
3232
jwksPort int
33-
jwtPrivateKeyPEM []byte
34-
jwtPublicKeyPEM []byte
3533
tokenRefreshThreshold time.Duration
3634
ipamv6, ipamv4 tunnet.IPAM
3735

38-
validator *token.InMemoryValidator
36+
validator token.Validator
3937
issuer token.TokenIssuer
4038
}
4139

4240
func NewTunnelNodeReconciler(
4341
c client.Client,
42+
validator token.Validator,
43+
issuer token.TokenIssuer,
4444
jwksHost string,
4545
jwksPort int,
46-
jwtPrivateKey []byte,
47-
jwtPublicKey []byte,
4846
tokenRefreshThreshold time.Duration,
4947
ipamv6, ipamv4 tunnet.IPAM,
5048
) *TunnelNodeReconciler {
5149
return &TunnelNodeReconciler{
5250
Client: c,
51+
validator: validator,
52+
issuer: issuer,
5353
jwksHost: jwksHost,
5454
jwksPort: jwksPort,
55-
jwtPrivateKeyPEM: jwtPrivateKey,
56-
jwtPublicKeyPEM: jwtPublicKey,
5755
tokenRefreshThreshold: tokenRefreshThreshold,
5856
ipamv6: ipamv6,
5957
ipamv4: ipamv4,
@@ -222,25 +220,15 @@ func (r *TunnelNodeReconciler) Reconcile(ctx context.Context, req reconcile.Requ
222220
return ctrl.Result{}, nil
223221
}
224222

225-
func (r *TunnelNodeReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manager) error {
226-
var err error
227-
r.validator, err = token.NewInMemoryValidator(r.jwtPublicKeyPEM)
228-
if err != nil {
229-
return fmt.Errorf("failed to create token validator: %w", err)
230-
}
231-
r.issuer, err = token.NewIssuer(r.jwtPrivateKeyPEM)
232-
if err != nil {
233-
return fmt.Errorf("failed to create token issuer: %w", err)
234-
}
235-
223+
func (r *TunnelNodeReconciler) SetupWithManager(mgr ctrl.Manager) error {
236224
return ctrl.NewControllerManagedBy(mgr).
237225
For(&corev1alpha.TunnelNode{}).
238226
Complete(r)
239227
}
240228

241229
// ServeJWKS starts an HTTP server to serve JWK sets
242230
func (r *TunnelNodeReconciler) ServeJWKS(ctx context.Context) error {
243-
jwksHandler, err := token.NewJWKSHandler(r.jwtPublicKeyPEM)
231+
jwksHandler, err := token.NewJWKSHandler(r.validator.PublicKeyPEM())
244232
if err != nil {
245233
return fmt.Errorf("failed to create JWKS handler: %w", err)
246234
}

pkg/apiserver/controllers/tunnelnode_test.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,27 +42,27 @@ func TestTunnelNodeReconciler(t *testing.T) {
4242
privKey, pubKey, err := cryptoutils.GenerateEllipticKeyPair()
4343
require.NoError(t, err)
4444

45+
validator, err := token.NewInMemoryValidator(pubKey)
46+
require.NoError(t, err)
47+
issuer, err := token.NewIssuer(privKey)
48+
require.NoError(t, err)
49+
4550
systemULA := tunnet.NewULA(context.Background(), net.SystemNetworkID)
4651
// Agent prefixes are /96 subnets that can embed IPv4 suffixes.
4752
ipamv6, err := systemULA.IPAM(context.Background(), 96)
4853
require.NoError(t, err)
4954

5055
r := NewTunnelNodeReconciler(
5156
k8sClient,
57+
validator,
58+
issuer,
5259
"localhost",
5360
9444,
54-
privKey,
55-
pubKey,
5661
time.Minute,
5762
ipamv6,
5863
net.NewIPAMv4(context.Background()),
5964
)
6065

61-
r.validator, err = token.NewInMemoryValidator(r.jwtPublicKeyPEM)
62-
require.NoError(t, err)
63-
r.issuer, err = token.NewIssuer(r.jwtPrivateKeyPEM)
64-
require.NoError(t, err)
65-
6666
_, err = r.Reconcile(context.TODO(), reconcile.Request{
6767
NamespacedName: types.NamespacedName{
6868
Name: "test-tunnelnode",

pkg/apiserver/manager.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ import (
4949
"github.com/apoxy-dev/apoxy/pkg/log"
5050
apoxynet "github.com/apoxy-dev/apoxy/pkg/tunnel/net"
5151
tunnet "github.com/apoxy-dev/apoxy/pkg/tunnel/net"
52+
"github.com/apoxy-dev/apoxy/pkg/tunnel/token"
5253
"github.com/apoxy-dev/apoxy/pkg/tunnel/vni"
5354

5455
corev1alpha "github.com/apoxy-dev/apoxy/api/core/v1alpha"
@@ -512,17 +513,25 @@ func (m *Manager) Start(
512513

513514
// Legacy v1alpha1 TunnelNode controller
514515
log.Infof("Registering TunnelNode controller")
516+
tunnelNodeValidator, err := token.NewInMemoryValidator(dOpts.jwtPublicKey)
517+
if err != nil {
518+
return fmt.Errorf("failed to create tunnel node validator: %v", err)
519+
}
520+
tunnelNodeIssuer, err := token.NewIssuer(dOpts.jwtPrivateKey)
521+
if err != nil {
522+
return fmt.Errorf("failed to create tunnel node issuer: %v", err)
523+
}
515524
tunnelNodeReconciler := controllers.NewTunnelNodeReconciler(
516525
m.manager.GetClient(),
526+
tunnelNodeValidator,
527+
tunnelNodeIssuer,
517528
dOpts.jwksHost,
518529
dOpts.jwksPort,
519-
dOpts.jwtPrivateKey,
520-
dOpts.jwtPublicKey,
521530
dOpts.jwtRefreshThreshold,
522531
dOpts.agentIPAM,
523532
apoxynet.NewIPAMv4(context.Background()),
524533
)
525-
if err := tunnelNodeReconciler.SetupWithManager(ctx, m.manager); err != nil {
534+
if err := tunnelNodeReconciler.SetupWithManager(m.manager); err != nil {
526535
return fmt.Errorf("failed to set up TunnelNode controller: %v", err)
527536
}
528537
g.Go(func() error {

pkg/tunnel/token/validator.go

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,21 @@ import (
1515
"github.com/apoxy-dev/apoxy/pkg/cryptoutils"
1616
)
1717

18+
// JWTValidator validates JWT tokens.
1819
type JWTValidator interface {
20+
// Validate validates the token and returns its claims.
1921
Validate(tokenStr string) (jwt.Claims, error)
2022
}
2123

24+
// Validator extends JWTValidator with the ability to retrieve the public key.
25+
// Use this interface when you need to serve JWKS endpoints locally.
26+
// For remote validation (e.g., RemoteValidator), use JWTValidator instead.
27+
type Validator interface {
28+
JWTValidator
29+
// PublicKeyPEM returns the PEM-encoded public key used for validation.
30+
PublicKeyPEM() []byte
31+
}
32+
2233
func validate(keyFunc jwt.Keyfunc, tokenStr string) (jwt.Claims, error) {
2334
token, err := jwt.Parse(
2435
tokenStr,
@@ -42,9 +53,11 @@ func validate(keyFunc jwt.Keyfunc, tokenStr string) (jwt.Claims, error) {
4253
return tokenClaims, nil
4354
}
4455

45-
// InMemoryValidator validates JWT tokens signed with an ECDSA public key
56+
// InMemoryValidator validates JWT tokens signed with an ECDSA public key.
57+
// It implements the Validator interface.
4658
type InMemoryValidator struct {
47-
publicKey *ecdsa.PublicKey
59+
publicKey *ecdsa.PublicKey
60+
publicKeyPEM []byte
4861
}
4962

5063
// NewInMemoryValidator creates a new Validator with the public key.
@@ -54,7 +67,10 @@ func NewInMemoryValidator(publicKeyPEM []byte) (*InMemoryValidator, error) {
5467
return nil, fmt.Errorf("failed to parse ECDSA public key: %w", err)
5568
}
5669

57-
return &InMemoryValidator{publicKey: publicKey}, nil
70+
return &InMemoryValidator{
71+
publicKey: publicKey,
72+
publicKeyPEM: publicKeyPEM,
73+
}, nil
5874
}
5975

6076
// Validate validates the token is valid.
@@ -64,6 +80,11 @@ func (v *InMemoryValidator) Validate(tokenStr string) (jwt.Claims, error) {
6480
}, tokenStr)
6581
}
6682

83+
// PublicKeyPEM returns the PEM-encoded public key used for validation.
84+
func (v *InMemoryValidator) PublicKeyPEM() []byte {
85+
return v.publicKeyPEM
86+
}
87+
6788
type RemoteValidator struct {
6889
rkf keyfunc.Keyfunc
6990
}

0 commit comments

Comments
 (0)