Skip to content

Commit

Permalink
sys: adds identity_token_key to mounts/auth for enable/tune (#24962)
Browse files Browse the repository at this point in the history
* sys: adds identity_token_key to mounts/auth for enable/tune

* adds changelog

* adds godoc on new tests

* adds function for identityStoreKeyExists

* use read lock, remove helper func

* tune test in logical_system_test, remove router access method

* fix key existence check in namespaces
  • Loading branch information
austingebauer authored Jan 22, 2024
1 parent 677d98a commit 76a62d5
Show file tree
Hide file tree
Showing 7 changed files with 365 additions and 1 deletion.
3 changes: 3 additions & 0 deletions api/sys_mounts.go
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,8 @@ type MountConfigInput struct {
PluginVersion string `json:"plugin_version,omitempty"`
UserLockoutConfig *UserLockoutConfigInput `json:"user_lockout_config,omitempty"`
DelegatedAuthAccessors []string `json:"delegated_auth_accessors,omitempty" mapstructure:"delegated_auth_accessors"`
IdentityTokenKey string `json:"identity_token_key,omitempty"`

// Deprecated: This field will always be blank for newer server responses.
PluginName string `json:"plugin_name,omitempty" mapstructure:"plugin_name"`
}
Expand Down Expand Up @@ -305,6 +307,7 @@ type MountConfigOutput struct {
AllowedManagedKeys []string `json:"allowed_managed_keys,omitempty" mapstructure:"allowed_managed_keys"`
UserLockoutConfig *UserLockoutConfigOutput `json:"user_lockout_config,omitempty"`
DelegatedAuthAccessors []string `json:"delegated_auth_accessors,omitempty" mapstructure:"delegated_auth_accessors"`
IdentityTokenKey string `json:"identity_token_key,omitempty"`

// Deprecated: This field will always be blank for newer server responses.
PluginName string `json:"plugin_name,omitempty" mapstructure:"plugin_name"`
Expand Down
3 changes: 3 additions & 0 deletions changelog/24962.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:improvement
sys: adds configuration of the key used to sign plugin identity tokens during mount enable and tune
```
2 changes: 1 addition & 1 deletion vault/identity_store_oidc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1288,7 +1288,7 @@ func TestOIDC_pathOIDCKeyExistenceCheck(t *testing.T) {
t.Fatalf("Expected existence check to return false but instead returned: %t", exists)
}

// Populte storage with a namedKey
// Populate storage with a namedKey
namedKey := &namedKey{}
entry, _ := logical.StorageEntryJSON(namedKeyConfigPath+keyName, namedKey)
if err := storage.Put(ctx, entry); err != nil {
Expand Down
95 changes: 95 additions & 0 deletions vault/logical_system.go
Original file line number Diff line number Diff line change
Expand Up @@ -1277,6 +1277,9 @@ func (b *SystemBackend) mountInfo(ctx context.Context, entry *MountEntry) map[st
if rawVal, ok := entry.synthesizedConfigCache.Load("allowed_managed_keys"); ok {
entryConfig["allowed_managed_keys"] = rawVal.([]string)
}
if rawVal, ok := entry.synthesizedConfigCache.Load("identity_token_key"); ok {
entryConfig["identity_token_key"] = rawVal.(string)
}
if entry.Table == credentialTableType {
entryConfig["token_type"] = entry.Config.TokenType.String()
}
Expand Down Expand Up @@ -1498,6 +1501,26 @@ func (b *SystemBackend) handleMount(ctx context.Context, req *logical.Request, d
config.DelegatedAuthAccessors = apiConfig.DelegatedAuthAccessors
}

if apiConfig.IdentityTokenKey != "" {
storage := b.Core.router.MatchingStorageByAPIPath(ctx, mountPathIdentity)
if storage == nil {
return nil, errors.New("failed to find identity storage")
}

identityStore := b.Core.IdentityStore()
identityStore.oidcLock.RLock()
defer identityStore.oidcLock.RUnlock()
k, err := identityStore.getNamedKey(ctx, storage, apiConfig.IdentityTokenKey)
if err != nil {
return nil, fmt.Errorf("failed getting key %q: %w", apiConfig.IdentityTokenKey, err)
}
if k == nil {
return logical.ErrorResponse("key %q does not exist", apiConfig.IdentityTokenKey), nil
}

config.IdentityTokenKey = apiConfig.IdentityTokenKey
}

// Create the mount entry
me := &MountEntry{
Table: mountTableType,
Expand Down Expand Up @@ -1954,6 +1977,10 @@ func (b *SystemBackend) handleTuneReadCommon(ctx context.Context, path string) (
resp.Data["allowed_managed_keys"] = rawVal.([]string)
}

if rawVal, ok := mountEntry.synthesizedConfigCache.Load("identity_token_key"); ok {
resp.Data["identity_token_key"] = rawVal.(string)
}

if mountEntry.Config.UserLockoutConfig != nil {
resp.Data["user_lockout_counter_reset_duration"] = int64(mountEntry.Config.UserLockoutConfig.LockoutCounterReset.Seconds())
resp.Data["user_lockout_threshold"] = mountEntry.Config.UserLockoutConfig.LockoutThreshold
Expand Down Expand Up @@ -2245,6 +2272,50 @@ func (b *SystemBackend) handleTuneWriteCommon(ctx context.Context, path string,
}
}

if rawVal, ok := data.GetOk("identity_token_key"); ok {
identityTokenKey := rawVal.(string)

if identityTokenKey != "" {
storage := b.Core.router.MatchingStorageByAPIPath(ctx, mountPathIdentity)
if storage == nil {
return nil, errors.New("failed to find identity storage")
}

identityStore := b.Core.IdentityStore()
identityStore.oidcLock.RLock()
defer identityStore.oidcLock.RUnlock()
k, err := identityStore.getNamedKey(ctx, storage, identityTokenKey)
if err != nil {
return nil, fmt.Errorf("failed getting key %q: %w", identityTokenKey, err)
}
if k == nil {
return logical.ErrorResponse("key %q does not exist", identityTokenKey), nil
}
}

oldVal := mountEntry.Config.IdentityTokenKey
mountEntry.Config.IdentityTokenKey = identityTokenKey

// Update the mount table
var err error
switch {
case strings.HasPrefix(path, "auth/"):
err = b.Core.persistAuth(ctx, b.Core.auth, &mountEntry.Local)
default:
err = b.Core.persistMounts(ctx, b.Core.mounts, &mountEntry.Local)
}
if err != nil {
mountEntry.Config.IdentityTokenKey = oldVal
return handleError(err)
}

mountEntry.SyncCache()

if b.Core.logger.IsInfo() {
b.Core.logger.Info("mount tuning of identity_token_key successful", "path", path)
}
}

if rawVal, ok := data.GetOk("audit_non_hmac_request_keys"); ok {
auditNonHMACRequestKeys := rawVal.([]string)

Expand Down Expand Up @@ -3000,6 +3071,26 @@ func (b *SystemBackend) handleEnableAuth(ctx context.Context, req *logical.Reque
config.AllowedManagedKeys = apiConfig.AllowedManagedKeys
}

if apiConfig.IdentityTokenKey != "" {
storage := b.Core.router.MatchingStorageByAPIPath(ctx, mountPathIdentity)
if storage == nil {
return nil, errors.New("failed to find identity storage")
}

identityStore := b.Core.IdentityStore()
identityStore.oidcLock.RLock()
defer identityStore.oidcLock.RUnlock()
k, err := identityStore.getNamedKey(ctx, storage, apiConfig.IdentityTokenKey)
if err != nil {
return nil, fmt.Errorf("failed getting key %q: %w", apiConfig.IdentityTokenKey, err)
}
if k == nil {
return logical.ErrorResponse("key %q does not exist", apiConfig.IdentityTokenKey), nil
}

config.IdentityTokenKey = apiConfig.IdentityTokenKey
}

// Create the mount entry
me := &MountEntry{
Table: credentialTableType,
Expand Down Expand Up @@ -6445,6 +6536,10 @@ This path responds to the following HTTP methods.
"Whether the container runtime is run as a non-privileged (non-root) user.",
"",
},
"identity_token_key": {
"The name of the key used to sign plugin identity tokens. Defaults to the default key.",
"",
},
"leases": {
`View or list lease metadata.`,
`
Expand Down
17 changes: 17 additions & 0 deletions vault/logical_system_paths.go
Original file line number Diff line number Diff line change
Expand Up @@ -3721,6 +3721,11 @@ func (b *SystemBackend) authPaths() []*framework.Path {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["plugin-catalog_version"][0]),
},
"identity_token_key": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["identity_token_key"][0]),
Required: false,
},
},
Operations: map[logical.Operation]framework.OperationHandler{
logical.ReadOperation: &framework.PathOperation{
Expand Down Expand Up @@ -3807,6 +3812,10 @@ func (b *SystemBackend) authPaths() []*framework.Path {
Type: framework.TypeString,
Required: false,
},
"identity_token_key": {
Type: framework.TypeString,
Required: false,
},
},
}},
},
Expand Down Expand Up @@ -4573,6 +4582,10 @@ func (b *SystemBackend) mountPaths() []*framework.Path {
Type: framework.TypeMap,
Description: strings.TrimSpace(sysHelp["tune_user_lockout_config"][0]),
},
"identity_token_key": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["identity_token_key"][0]),
},
},

Operations: map[logical.Operation]framework.OperationHandler{
Expand Down Expand Up @@ -4671,6 +4684,10 @@ func (b *SystemBackend) mountPaths() []*framework.Path {
Type: framework.TypeBool,
Required: false,
},
"identity_token_key": {
Type: framework.TypeString,
Required: false,
},
},
}},
},
Expand Down
Loading

0 comments on commit 76a62d5

Please sign in to comment.