Skip to content
Merged
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
6 changes: 2 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,8 @@
- (Documentation) ManualUpgrade Docs
- (Documentation) Add Required & Skip in Docs
- (Feature) (Platform) ECS Storage
- (Bugfix) (Platform) Prevent NPE in case of missing Helm Release
- (Feature) Unify Errors
- (Documentation) Update Service Values Doc Type
- (Feature) (Platform) Improve Registry Performance
- (Bugfix) (Platform) Prevent NPE in case of missing Helm Release
- (Bugfix) Align JWT Discovery

## [1.2.50](https://github.com/arangodb/kube-arangodb/tree/1.2.50) (2025-07-04)
- (Feature) (Platform) MetaV1 Integration Service
Expand Down
19 changes: 15 additions & 4 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 @@ -401,20 +401,31 @@ func createClient(endpoints []string, certCA *x509.CertPool, auth connection.Aut
}

// getJWTTokenFromSecrets returns token from the secret.
func getJWTTokenFromSecrets(ctx context.Context, secrets generic.ReadClient[*core.Secret], name string) (connection.Authentication, error) {
func getJWTTokenFromSecrets(ctx context.Context, secrets generic.ReadClient[*core.Secret], name string, paths ...string) (connection.Authentication, error) {
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")
claims := token.NewClaims().With(
token.WithDefaultClaims(),
token.WithServerID("kube-arangodb"),
)

if len(paths) > 0 {
claims = claims.With(token.WithAllowedPaths(paths...))
}

authz, err := claims.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
18 changes: 6 additions & 12 deletions integrations/authentication/v1/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,13 @@ import (
"time"

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

const MaxSize = 128

type tokens struct {
signingToken []byte

validationTokens [][]byte
}

func newCache(cfg Configuration) func(ctx context.Context) (*tokens, time.Duration, error) {
return func(ctx context.Context) (*tokens, time.Duration, error) {
func newCache(cfg Configuration) func(ctx context.Context) (token.Secret, time.Duration, error) {
return func(ctx context.Context) (token.Secret, time.Duration, error) {
files, err := os.ReadDir(cfg.Path)
if err != nil {
return nil, 0, err
Expand Down Expand Up @@ -87,9 +82,8 @@ func newCache(cfg Configuration) func(ctx context.Context) (*tokens, time.Durati
data[id] = ts[keys[id]]
}

return &tokens{
signingToken: ts[keys[0]],
validationTokens: data,
}, cfg.TTL, nil
return token.NewSecretSet(token.NewSecret(ts[keys[0]]), util.FormatList(data, func(a []byte) token.Secret {
return token.NewSecret(a)
})...), cfg.TTL, nil
}
}
31 changes: 14 additions & 17 deletions integrations/authentication/v1/implementation.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ type implementation struct {
cfg Configuration

userClient cache.Object[arangodb.Requests]
cache cache.Object[*tokens]
cache cache.Object[token.Secret]
}

func (i *implementation) Name() string {
Expand Down Expand Up @@ -190,16 +190,12 @@ func (i *implementation) CreateToken(ctx context.Context, request *pbAuthenticat
duration = v
}

// 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()...)),
)
signedToken, err := token.NewClaims().With(
token.WithDefaultClaims(),
token.WithCurrentIAT(),
token.WithDuration(duration),
token.WithUsername(user),
token.WithRoles(request.GetRoles()...)).Sign(cache)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -344,24 +340,25 @@ func (i *implementation) Logout(ctx context.Context, req *pbAuthenticationV1.Log
return &pbSharedV1.Empty{}, nil
}

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

p, err := token.ParseWithAny(t, cache.validationTokens...)
p, err := cache.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 @@ -372,7 +369,7 @@ func (i *implementation) extractTokenDetails(cache *tokens, 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.

26 changes: 13 additions & 13 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
Loading