Skip to content

[Bugfix] Fix JWT Secret Tail characters #1867

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- (Feature) Ensure Group Service Type
- (Maintenance) Fix Helm & JWT CVE's
- (Feature) (Platform) Improve CLI Values
- (Bugfix) Align JWT Discovery

## [1.2.48](https://github.com/arangodb/kube-arangodb/tree/1.2.48) (2025-05-08)
- (Maintenance) Extend Documentation
Expand Down
12 changes: 9 additions & 3 deletions cmd/admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ import (
meta "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/arangodb-helper/go-certificates"
"github.com/arangodb/go-driver/jwt"
"github.com/arangodb/go-driver/v2/connection"

api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
Expand All @@ -51,6 +50,7 @@ import (
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector/generic"
"github.com/arangodb/kube-arangodb/pkg/util/kclient"
"github.com/arangodb/kube-arangodb/pkg/util/token"
)

const (
Expand Down Expand Up @@ -405,16 +405,22 @@ func getJWTTokenFromSecrets(ctx context.Context, secrets generic.ReadClient[*cor
ctxChild, cancel := globals.GetGlobalTimeouts().Kubernetes().WithTimeout(ctx)
defer cancel()

token, err := k8sutil.GetTokenSecret(ctxChild, secrets, name)
secret, err := k8sutil.GetTokenSecret(ctxChild, secrets, name)
if err != nil {
return nil, errors.WithMessage(err, fmt.Sprintf("failed to get secret \"%s\"", name))
}

bearerToken, err := jwt.CreateArangodJwtAuthorizationHeader(token, "kube-arangodb")
authz, err := token.NewClaims().With(
token.WithDefaultClaims(),
token.WithServerID("kube-arangodb"),
token.WithAllowedPaths("/_api/version"),
).Sign(secret)
if err != nil {
return nil, errors.WithMessage(err, fmt.Sprintf("failed to create bearer token from secret \"%s\"", name))
}

bearerToken := fmt.Sprintf("bearer %s", authz)

return JWTAuthentication{key: "Authorization", value: bearerToken}, nil
}

Expand Down
16 changes: 8 additions & 8 deletions integrations/authentication/v1/cache.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//
// DISCLAIMER
//
// Copyright 2024 ArangoDB GmbH, Cologne, Germany
// Copyright 2024-2025 ArangoDB GmbH, Cologne, Germany
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -29,6 +29,7 @@ import (

"github.com/arangodb/kube-arangodb/pkg/util"
"github.com/arangodb/kube-arangodb/pkg/util/errors"
"github.com/arangodb/kube-arangodb/pkg/util/token"
)

const MaxSize = 128
Expand All @@ -38,9 +39,7 @@ type cache struct {

eol time.Time

signingToken []byte

validationTokens [][]byte
token token.Secret
}

func (i *implementation) newCache(cfg Configuration) (*cache, error) {
Expand Down Expand Up @@ -91,10 +90,11 @@ func (i *implementation) newCache(cfg Configuration) (*cache, error) {
}

cache := cache{
parent: i,
eol: time.Now().Add(i.cfg.TTL),
signingToken: tokens[keys[0]],
validationTokens: data,
parent: i,
eol: time.Now().Add(i.cfg.TTL),
token: token.NewSecretSet(token.NewSecret(tokens[keys[0]]), util.FormatList(data, func(a []byte) token.Secret {
return token.NewSecret(a)
})...),
}

return &cache, nil
Expand Down
29 changes: 16 additions & 13 deletions integrations/authentication/v1/implementation.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,15 +169,14 @@ func (i *implementation) CreateToken(ctx context.Context, request *pbAuthenticat
}

// Token is validated, we can continue with creation
secret := cache.signingToken

signedToken, err := token.New(secret,
token.NewClaims().With(token.WithDefaultClaims(),
token.WithCurrentIAT(),
token.WithDuration(duration),
token.WithUsername(user),
token.WithRoles(request.GetRoles()...)),
)
secret := cache.token

signedToken, err := token.NewClaims().With(
token.WithDefaultClaims(),
token.WithCurrentIAT(),
token.WithDuration(duration),
token.WithUsername(user),
token.WithRoles(request.GetRoles()...)).Sign(secret)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -242,22 +241,26 @@ func (i *implementation) Identity(ctx context.Context, _ *pbSharedV1.Empty) (*pb

func (i *implementation) extractTokenDetails(cache *cache, t string) (string, []string, time.Duration, error) {
// Let's check if token is signed properly
secret := cache.token

p, err := token.ParseWithAny(t, cache.validationTokens...)
// Let's check if token is signed properly
p, err := secret.Validate(t)
if err != nil {
return "", nil, 0, err
}

user := DefaultAdminUser
if v, ok := p[token.ClaimPreferredUsername]; ok {
if v, ok := p.Claims()[token.ClaimPreferredUsername]; ok {
if s, ok := v.(string); ok {
user = s
}
}

duration := DefaultTokenMaxTTL

if v, ok := p[token.ClaimEXP]; ok {
claims := p.Claims()

if v, ok := claims[token.ClaimEXP]; ok {
switch o := v.(type) {
case int64:
duration = time.Until(time.Unix(o, 0))
Expand All @@ -268,7 +271,7 @@ func (i *implementation) extractTokenDetails(cache *cache, t string) (string, []

var roles []string

if v, ok := p[token.ClaimRoles]; ok {
if v, ok := claims[token.ClaimRoles]; ok {
switch o := v.(type) {
case []string:
roles = o
Expand Down
2 changes: 1 addition & 1 deletion pkg/api/api.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions pkg/api/auth.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 12 additions & 12 deletions pkg/api/jwt.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pkg/deployment/context_impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ func (d *Deployment) getJWTToken() (string, bool) {
func (d *Deployment) GetSyncServerClient(ctx context.Context, group api.ServerGroup, id string) (client.API, error) {
// Fetch monitoring token
secretName := d.GetSpec().Sync.Monitoring.GetTokenSecretName()
monitoringToken, err := k8sutil.GetTokenSecret(ctx, d.GetCachedStatus().Secret().V1().Read(), secretName)
monitoringToken, err := k8sutil.GetTokenSecretString(ctx, d.GetCachedStatus().Secret().V1().Read(), secretName)
if err != nil {
d.log.Err(err).Str("secret-name", secretName).Debug("Failed to get sync monitoring secret")
return nil, errors.WithStack(err)
Expand Down
26 changes: 13 additions & 13 deletions pkg/deployment/deployment_pod_sync_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//
// DISCLAIMER
//
// Copyright 2016-2024 ArangoDB GmbH, Cologne, Germany
// Copyright 2016-2025 ArangoDB GmbH, Cologne, Germany
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -227,7 +227,7 @@ func TestEnsurePod_Sync_Master(t *testing.T) {
testCase.createTestPodData(deployment, api.ServerGroupSyncMasters, firstSyncMaster)

name := testCase.ArangoDeployment.Spec.Sync.Monitoring.GetTokenSecretName()
auth, err := k8sutil.GetTokenSecret(context.Background(), deployment.GetCachedStatus().Secret().V1().Read(), name)
auth, err := k8sutil.GetTokenSecretString(context.Background(), deployment.GetCachedStatus().Secret().V1().Read(), name)
require.NoError(t, err)

testCase.ExpectedPod.Spec.Containers[0].LivenessProbe = createTestLivenessProbe("", true, "bearer "+auth, shared.ServerPortName)
Expand Down Expand Up @@ -316,7 +316,7 @@ func TestEnsurePod_Sync_Master(t *testing.T) {

testCase.createTestPodData(deployment, api.ServerGroupSyncMasters, firstSyncMaster)
name := testCase.ArangoDeployment.Spec.Sync.Monitoring.GetTokenSecretName()
auth, err := k8sutil.GetTokenSecret(context.Background(), deployment.GetCachedStatus().Secret().V1().Read(), name)
auth, err := k8sutil.GetTokenSecretString(context.Background(), deployment.GetCachedStatus().Secret().V1().Read(), name)
require.NoError(t, err)

testCase.ExpectedPod.Spec.Containers[0].LivenessProbe = createTestLivenessProbe("", true, "bearer "+auth, shared.ServerPortName)
Expand Down Expand Up @@ -420,7 +420,7 @@ func TestEnsurePod_Sync_Master(t *testing.T) {

testCase.createTestPodData(deployment, api.ServerGroupSyncMasters, firstSyncMaster)
name := testCase.ArangoDeployment.Spec.Sync.Monitoring.GetTokenSecretName()
auth, err := k8sutil.GetTokenSecret(context.Background(), deployment.GetCachedStatus().Secret().V1().Read(), name)
auth, err := k8sutil.GetTokenSecretString(context.Background(), deployment.GetCachedStatus().Secret().V1().Read(), name)
require.NoError(t, err)

testCase.ExpectedPod.Spec.Containers[0].LivenessProbe = createTestLivenessProbe("", true, "bearer "+auth, shared.ServerPortName)
Expand Down Expand Up @@ -521,7 +521,7 @@ func TestEnsurePod_Sync_Master(t *testing.T) {

testCase.createTestPodData(deployment, api.ServerGroupSyncMasters, firstSyncMaster)
name := testCase.ArangoDeployment.Spec.Sync.Monitoring.GetTokenSecretName()
auth, err := k8sutil.GetTokenSecret(context.Background(), deployment.GetCachedStatus().Secret().V1().Read(), name)
auth, err := k8sutil.GetTokenSecretString(context.Background(), deployment.GetCachedStatus().Secret().V1().Read(), name)
require.NoError(t, err)

testCase.ExpectedPod.Spec.Containers[0].LivenessProbe = createTestLivenessProbe("", true, "bearer "+auth, shared.ServerPortName)
Expand Down Expand Up @@ -622,7 +622,7 @@ func TestEnsurePod_Sync_Master(t *testing.T) {

testCase.createTestPodData(deployment, api.ServerGroupSyncMasters, firstSyncMaster)
name := testCase.ArangoDeployment.Spec.Sync.Monitoring.GetTokenSecretName()
auth, err := k8sutil.GetTokenSecret(context.Background(), deployment.GetCachedStatus().Secret().V1().Read(), name)
auth, err := k8sutil.GetTokenSecretString(context.Background(), deployment.GetCachedStatus().Secret().V1().Read(), name)
require.NoError(t, err)

testCase.ExpectedPod.Spec.Containers[0].LivenessProbe = createTestLivenessProbe("", true, "bearer "+auth, shared.ServerPortName)
Expand Down Expand Up @@ -726,7 +726,7 @@ func TestEnsurePod_Sync_Master(t *testing.T) {

testCase.createTestPodData(deployment, api.ServerGroupSyncMasters, firstSyncMaster)
name := testCase.ArangoDeployment.Spec.Sync.Monitoring.GetTokenSecretName()
auth, err := k8sutil.GetTokenSecret(context.Background(), deployment.GetCachedStatus().Secret().V1().Read(), name)
auth, err := k8sutil.GetTokenSecretString(context.Background(), deployment.GetCachedStatus().Secret().V1().Read(), name)
require.NoError(t, err)

testCase.ExpectedPod.Spec.Containers[0].LivenessProbe = createTestLivenessProbe("", true, "bearer "+auth, shared.ServerPortName)
Expand Down Expand Up @@ -825,7 +825,7 @@ func TestEnsurePod_Sync_Master(t *testing.T) {

testCase.createTestPodData(deployment, api.ServerGroupSyncMasters, firstSyncMaster)
name := testCase.ArangoDeployment.Spec.Sync.Monitoring.GetTokenSecretName()
auth, err := k8sutil.GetTokenSecret(context.Background(), deployment.GetCachedStatus().Secret().V1().Read(), name)
auth, err := k8sutil.GetTokenSecretString(context.Background(), deployment.GetCachedStatus().Secret().V1().Read(), name)
require.NoError(t, err)

testCase.ExpectedPod.Spec.Containers[0].LivenessProbe = createTestLivenessProbe("", true, "bearer "+auth, shared.ServerPortName)
Expand Down Expand Up @@ -931,7 +931,7 @@ func TestEnsurePod_Sync_Master(t *testing.T) {

testCase.createTestPodData(deployment, api.ServerGroupSyncMasters, firstSyncMaster)
name := testCase.ArangoDeployment.Spec.Sync.Monitoring.GetTokenSecretName()
auth, err := k8sutil.GetTokenSecret(context.Background(), deployment.GetCachedStatus().Secret().V1().Read(), name)
auth, err := k8sutil.GetTokenSecretString(context.Background(), deployment.GetCachedStatus().Secret().V1().Read(), name)
require.NoError(t, err)

testCase.ExpectedPod.Spec.Containers[0].LivenessProbe = createTestLivenessProbe("", true, "bearer "+auth, shared.ServerPortName)
Expand Down Expand Up @@ -1047,7 +1047,7 @@ func TestEnsurePod_Sync_Master(t *testing.T) {

testCase.createTestPodData(deployment, api.ServerGroupSyncMasters, firstSyncMaster)
name := testCase.ArangoDeployment.Spec.Sync.Monitoring.GetTokenSecretName()
auth, err := k8sutil.GetTokenSecret(context.Background(), deployment.GetCachedStatus().Secret().V1().Read(), name)
auth, err := k8sutil.GetTokenSecretString(context.Background(), deployment.GetCachedStatus().Secret().V1().Read(), name)
require.NoError(t, err)

testCase.ExpectedPod.Spec.Containers[0].LivenessProbe = createTestLivenessProbe("", true, "bearer "+auth, shared.ServerPortName)
Expand Down Expand Up @@ -1161,7 +1161,7 @@ func TestEnsurePod_Sync_Master(t *testing.T) {

testCase.createTestPodData(deployment, api.ServerGroupSyncMasters, firstSyncMaster)
name := testCase.ArangoDeployment.Spec.Sync.Monitoring.GetTokenSecretName()
auth, err := k8sutil.GetTokenSecret(context.Background(), deployment.GetCachedStatus().Secret().V1().Read(), name)
auth, err := k8sutil.GetTokenSecretString(context.Background(), deployment.GetCachedStatus().Secret().V1().Read(), name)
require.NoError(t, err)

testCase.ExpectedPod.Spec.Containers[0].LivenessProbe = createTestLivenessProbe("", true, "bearer "+auth, shared.ServerPortName)
Expand Down Expand Up @@ -1272,7 +1272,7 @@ func TestEnsurePod_Sync_Worker(t *testing.T) {
testCase.createTestPodData(deployment, api.ServerGroupSyncWorkers, firstSyncWorker)

name := testCase.ArangoDeployment.Spec.Sync.Monitoring.GetTokenSecretName()
auth, err := k8sutil.GetTokenSecret(context.Background(), deployment.GetCachedStatus().Secret().V1().Read(), name)
auth, err := k8sutil.GetTokenSecretString(context.Background(), deployment.GetCachedStatus().Secret().V1().Read(), name)
require.NoError(t, err)

testCase.ExpectedPod.Spec.Containers[0].LivenessProbe = createTestLivenessProbe("", true, "bearer "+auth, shared.ServerPortName)
Expand Down Expand Up @@ -1367,7 +1367,7 @@ func TestEnsurePod_Sync_Worker(t *testing.T) {
testCase.createTestPodData(deployment, api.ServerGroupSyncWorkers, firstSyncWorker)

name := testCase.ArangoDeployment.Spec.Sync.Monitoring.GetTokenSecretName()
auth, err := k8sutil.GetTokenSecret(context.Background(), deployment.GetCachedStatus().Secret().V1().Read(), name)
auth, err := k8sutil.GetTokenSecretString(context.Background(), deployment.GetCachedStatus().Secret().V1().Read(), name)
require.NoError(t, err)

testCase.ExpectedPod.Spec.Containers[0].LivenessProbe = createTestLivenessProbe("", true, "bearer "+auth, shared.ServerPortName)
Expand Down
Loading