Skip to content

Commit

Permalink
fix: validate JWT token on alias look ahead (#114)
Browse files Browse the repository at this point in the history
- in order to ensure proper validation for alias look ahead the provided
 JWT token must match the role's configuration.
  • Loading branch information
benashz committed Sep 29, 2021
1 parent e5af6cc commit 1b7f46f
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 9 deletions.
12 changes: 12 additions & 0 deletions backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package kubeauth
import (
"context"
"encoding/json"
"errors"
"fmt"
"strings"
"sync"
Expand Down Expand Up @@ -106,6 +107,17 @@ func (b *kubeAuthBackend) config(ctx context.Context, s logical.Storage) (*kubeC
return conf, nil
}

func (b *kubeAuthBackend) loadConfig(ctx context.Context, s logical.Storage) (*kubeConfig, error) {
config, err := b.config(ctx, s)
if err != nil {
return nil, err
}
if config == nil {
return nil, errors.New("could not load backend configuration")
}
return config, nil
}

// role takes a storage backend and the name and returns the role's storage
// entry
func (b *kubeAuthBackend) role(ctx context.Context, s logical.Storage, name string) (*roleStorageEntry, error) {
Expand Down
15 changes: 6 additions & 9 deletions path_login.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,10 @@ func (b *kubeAuthBackend) pathLogin(ctx context.Context, req *logical.Request, d
}
}

config, err := b.config(ctx, req.Storage)
config, err := b.loadConfig(ctx, req.Storage)
if err != nil {
return nil, err
}
if config == nil {
return nil, errors.New("could not load backend configuration")
}

serviceAccount, err := b.parseAndValidateJWT(jwtStr, role, config)
if err != nil {
Expand Down Expand Up @@ -171,6 +168,7 @@ func (b *kubeAuthBackend) getAliasName(role *roleStorageEntry, serviceAccount *s

// aliasLookahead returns the alias object with the SA UID from the JWT
// Claims.
// Only JWTs matching the specified role's configuration will be accepted as valid.
func (b *kubeAuthBackend) aliasLookahead(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
roleName, resp := b.getFieldValueStr(data, "role")
if resp != nil {
Expand All @@ -190,15 +188,14 @@ func (b *kubeAuthBackend) aliasLookahead(ctx context.Context, req *logical.Reque
return logical.ErrorResponse(fmt.Sprintf("invalid role name %q", roleName)), nil
}

// Parse into JWT
parsedJWT, err := jws.ParseJWT([]byte(jwtStr))
config, err := b.loadConfig(ctx, req.Storage)
if err != nil {
return nil, err
}

// Decode claims into a service account object
sa := &serviceAccount{}
err = mapstructure.Decode(parsedJWT.Claims(), sa)
// validation of the JWT against the provided role ensures alias look ahead requests
// are authentic.
sa, err := b.parseAndValidateJWT(jwtStr, role, config)
if err != nil {
return nil, err
}
Expand Down
6 changes: 6 additions & 0 deletions path_login_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,12 @@ func TestAliasLookAhead(t *testing.T) {
config: defaultTestBackendConfig(),
wantErr: errors.New("missing jwt"),
},
"invalid_jwt": {
role: "plugin-test",
config: defaultTestBackendConfig(),
jwt: jwtBadServiceAccount,
wantErr: errors.New("service account name not authorized"),
},
"serviceaccount_uid": {
role: "plugin-test",
jwt: jwtData,
Expand Down

0 comments on commit 1b7f46f

Please sign in to comment.