Backport Add override_pinned_version support on tune and enable for secret and auth into ce/main (#10644)

* backport: Add override_pinned_version support on tune and enable for secret and auth (#9719)

* fix entWrappedAuthPath() and entWrappedMountsPath() oss stubs

---------

Co-authored-by: Thy Ton <maithytonn@gmail.com>
This commit is contained in:
Vault Automation 2025-11-06 21:55:42 -05:00 committed by GitHub
parent cf476040f4
commit bfa97b551b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 988 additions and 832 deletions

View file

@ -238,6 +238,7 @@ type TuneMountConfigInput struct {
TokenType *string `json:"token_type,omitempty" mapstructure:"token_type"`
AllowedManagedKeys *[]string `json:"allowed_managed_keys,omitempty" mapstructure:"allowed_managed_keys"`
PluginVersion *string `json:"plugin_version,omitempty"`
OverridePinnedVersion *bool `json:"override_pinned_version,omitempty" mapstructure:"override_pinned_version"`
UserLockoutConfig *TuneUserLockoutConfigInput `json:"user_lockout_config,omitempty"`
DelegatedAuthAccessors *[]string `json:"delegated_auth_accessors,omitempty" mapstructure:"delegated_auth_accessors"`
IdentityTokenKey *string `json:"identity_token_key,omitempty" mapstructure:"identity_token_key"`
@ -321,6 +322,8 @@ func (c *Sys) TuneMountWithContext(ctx context.Context, path string, config Moun
tuneConfig.PluginVersion = &config.PluginVersion
}
tuneConfig.OverridePinnedVersion = config.OverridePinnedVersion
if config.UserLockoutConfig != nil {
userLockoutConfig := TuneUserLockoutConfigInput{}
if config.UserLockoutConfig.LockoutDuration != "" {
@ -416,6 +419,7 @@ type MountConfigInput struct {
TokenType string `json:"token_type,omitempty" mapstructure:"token_type"`
AllowedManagedKeys []string `json:"allowed_managed_keys,omitempty" mapstructure:"allowed_managed_keys"`
PluginVersion string `json:"plugin_version,omitempty"`
OverridePinnedVersion *bool `json:"override_pinned_version,omitempty" mapstructure:"override_pinned_version"`
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" mapstructure:"identity_token_key"`
@ -455,6 +459,7 @@ type MountConfigOutput struct {
DelegatedAuthAccessors []string `json:"delegated_auth_accessors,omitempty" mapstructure:"delegated_auth_accessors"`
IdentityTokenKey string `json:"identity_token_key,omitempty" mapstructure:"identity_token_key"`
TrimRequestTrailingSlashes bool `json:"trim_request_trailing_slashes,omitempty" mapstructure:"trim_request_trailing_slashes"`
OverridePinnedVersion bool `json:"override_pinned_version,omitempty" mapstructure:"override_pinned_version"`
// Deprecated: This field will always be blank for newer server responses.
PluginName string `json:"plugin_name,omitempty" mapstructure:"plugin_name"`

3
changelog/_9719.txt Normal file
View file

@ -0,0 +1,3 @@
```release-note:feature
**Plugins (Enterprise)**: Allow overriding pinned version when enabling and tuning auth and secrets backends
```

View file

@ -40,6 +40,7 @@ type AuthEnableCommand struct {
flagTokenType string
flagVersion int
flagPluginVersion string
flagOverridePinnedVersion BoolPtr
flagIdentityTokenKey string
flagTrimRequestTrailingSlashes BoolPtr
}
@ -211,6 +212,12 @@ func (c *AuthEnableCommand) Flags() *FlagSets {
Usage: "Select the semantic version of the plugin to enable.",
})
f.BoolPtrVar(&BoolPtrVar{
Name: flagNameOverridePinnedVersion,
Target: &c.flagOverridePinnedVersion,
Usage: "Enterprise only. Specified plugin-version will override the pinned plugin version.",
})
f.StringVar(&StringVar{
Name: flagNameIdentityTokenKey,
Target: &c.flagIdentityTokenKey,
@ -328,6 +335,11 @@ func (c *AuthEnableCommand) Run(args []string) int {
authOpts.Config.PluginVersion = c.flagPluginVersion
}
if fl.Name == flagNameOverridePinnedVersion && c.flagOverridePinnedVersion.IsSet() {
val := c.flagOverridePinnedVersion.Get()
authOpts.Config.OverridePinnedVersion = &val
}
if fl.Name == flagNameIdentityTokenKey {
authOpts.Config.IdentityTokenKey = c.flagIdentityTokenKey
}

View file

@ -35,6 +35,7 @@ type AuthTuneCommand struct {
flagTokenType string
flagVersion int
flagPluginVersion string
flagOverridePinnedVersion BoolPtr
flagUserLockoutThreshold uint
flagUserLockoutDuration time.Duration
flagUserLockoutCounterResetDuration time.Duration
@ -196,6 +197,13 @@ func (c *AuthTuneCommand) Flags() *FlagSets {
Usage: "Select the semantic version of the plugin to run. The new version must be registered in " +
"the plugin catalog, and will not start running until the plugin is reloaded.",
})
f.BoolPtrVar(&BoolPtrVar{
Name: flagNameOverridePinnedVersion,
Target: &c.flagOverridePinnedVersion,
Usage: "Whether to override the pinned version for this mount",
})
f.BoolPtrVar(&BoolPtrVar{
Name: flagNameTrimRequestTrailingSlashes,
Target: &c.flagTrimRequestTrailingSlashes,
@ -337,6 +345,11 @@ func (c *AuthTuneCommand) Run(args []string) int {
tuneMountInput.PluginVersion = &c.flagPluginVersion
}
if fl.Name == flagNameOverridePinnedVersion && c.flagOverridePinnedVersion.IsSet() {
val := c.flagOverridePinnedVersion.Get()
tuneMountInput.OverridePinnedVersion = &val
}
if fl.Name == flagNameIdentityTokenKey {
tuneMountInput.IdentityTokenKey = &c.flagIdentityTokenKey
}

View file

@ -95,6 +95,8 @@ const (
flagNameAllowedManagedKeys = "allowed-managed-keys"
// flagNamePluginVersion selects what version of a plugin should be used.
flagNamePluginVersion = "plugin-version"
// flagNameOverridePinnedVersion is the flag name used for allowing plugin-version to override the pinned plugin version
flagNameOverridePinnedVersion = "override-pinned-version"
// flagNameIdentityTokenKey selects the key used to sign plugin identity tokens
flagNameIdentityTokenKey = "identity-token-key"
// flagNameTrimRequestTrailingSlashes selects the key used to determine whether to trim trailing slashes

View file

@ -84,3 +84,20 @@ func testPluginCreateAndRegisterVersioned(tb testing.TB, client *api.Client, dir
return pth, sha256Sum, "v1.0.0"
}
func testPluginRegisterWithDownload(tb testing.TB, client *api.Client, name string, pluginType api.PluginType, version string) {
tb.Helper()
resp, err := client.Sys().RegisterPluginDetailed(&api.RegisterPluginInput{
Name: name,
Type: pluginType,
Version: version,
Download: true,
})
if err != nil {
tb.Fatal(err)
}
if len(resp.Warnings) > 0 {
tb.Errorf("expected no warnings, got: %v", resp.Warnings)
}
}

View file

@ -35,6 +35,7 @@ type SecretsEnableCommand struct {
flagForceNoCache bool
flagPluginName string
flagPluginVersion string
flagOverridePinnedVersion BoolPtr
flagOptions map[string]string
flagLocal bool
flagSealWrap bool
@ -179,6 +180,12 @@ func (c *SecretsEnableCommand) Flags() *FlagSets {
"exist in Vault's plugin catalog.",
})
f.BoolPtrVar(&BoolPtrVar{
Name: "override-pinned-version",
Target: &c.flagOverridePinnedVersion,
Usage: "Enterprise only. Specified plugin-version will override the pinned plugin version.",
})
f.StringVar(&StringVar{
Name: flagNamePluginVersion,
Target: &c.flagPluginVersion,
@ -363,6 +370,11 @@ func (c *SecretsEnableCommand) Run(args []string) int {
mountInput.Config.PluginVersion = c.flagPluginVersion
}
if fl.Name == flagNameOverridePinnedVersion && c.flagOverridePinnedVersion.IsSet() {
val := c.flagOverridePinnedVersion.Get()
mountInput.Config.OverridePinnedVersion = &val
}
if fl.Name == flagNameIdentityTokenKey {
mountInput.Config.IdentityTokenKey = c.flagIdentityTokenKey
}

View file

@ -34,6 +34,7 @@ type SecretsTuneCommand struct {
flagOptions map[string]string
flagVersion int
flagPluginVersion string
flagOverridePinnedVersion BoolPtr
flagAllowedManagedKeys []string
flagDelegatedAuthAccessors []string
flagIdentityTokenKey string
@ -161,6 +162,12 @@ func (c *SecretsTuneCommand) Flags() *FlagSets {
"the plugin catalog, and will not start running until the plugin is reloaded.",
})
f.BoolPtrVar(&BoolPtrVar{
Name: flagNameOverridePinnedVersion,
Target: &c.flagOverridePinnedVersion,
Usage: "Enterprise only. Specified plugin-version will override the pinned plugin version.",
})
f.StringSliceVar(&StringSliceVar{
Name: flagNameDelegatedAuthAccessors,
Target: &c.flagDelegatedAuthAccessors,
@ -267,6 +274,11 @@ func (c *SecretsTuneCommand) Run(args []string) int {
mountConfigInput.PluginVersion = c.flagPluginVersion
}
if fl.Name == flagNameOverridePinnedVersion && c.flagOverridePinnedVersion.IsSet() {
val := c.flagOverridePinnedVersion.Get()
mountConfigInput.OverridePinnedVersion = &val
}
if fl.Name == flagNameDelegatedAuthAccessors {
mountConfigInput.DelegatedAuthAccessors = c.flagDelegatedAuthAccessors
}

View file

@ -212,8 +212,8 @@ func NewSystemBackend(core *Core, logger log.Logger, config *logical.BackendConf
b.Backend.Paths = append(b.Backend.Paths, b.pluginsRuntimesCatalogCRUDPath())
b.Backend.Paths = append(b.Backend.Paths, b.pluginsRuntimesCatalogListPaths()...)
b.Backend.Paths = append(b.Backend.Paths, b.auditPaths()...)
b.Backend.Paths = append(b.Backend.Paths, b.mountPaths()...)
b.Backend.Paths = append(b.Backend.Paths, b.authPaths()...)
b.Backend.Paths = append(b.Backend.Paths, entWrappedMountsPath(b)...)
b.Backend.Paths = append(b.Backend.Paths, entWrappedAuthPath(b)...)
b.Backend.Paths = append(b.Backend.Paths, b.lockedUserPaths()...)
b.Backend.Paths = append(b.Backend.Paths, b.leasePaths()...)
b.Backend.Paths = append(b.Backend.Paths, b.policyPaths()...)
@ -514,6 +514,8 @@ func (b *SystemBackend) handlePluginCatalogUntypedList(ctx context.Context, _ *l
}, nil
}
// handlePluginCatalogUpdate handles plugin registration and updates in the plugin catalog.
// Vault Enterprise replaces handlePluginCatalogUpdate with entHandlePluginCatalogUpdate
func (b *SystemBackend) handlePluginCatalogUpdate(ctx context.Context, _ *logical.Request, d *framework.FieldData) (*logical.Response, error) {
pluginName := d.Get("name").(string)
if pluginName == "" {
@ -1383,89 +1385,6 @@ func (b *SystemBackend) handleGenerateRootDecodeTokenUpdate(ctx context.Context,
return resp, nil
}
func (b *SystemBackend) mountInfo(ctx context.Context, entry *MountEntry, legacyTTLFormat bool) map[string]interface{} {
info := map[string]interface{}{
"type": entry.Type,
"description": entry.Description,
"accessor": entry.Accessor,
"local": entry.Local,
"seal_wrap": entry.SealWrap,
"external_entropy_access": entry.ExternalEntropyAccess,
"options": entry.Options,
"uuid": entry.UUID,
"plugin_version": entry.Version,
"running_plugin_version": entry.RunningVersion,
"running_sha256": entry.RunningSha256,
}
coreDefTTL := int64(b.Core.defaultLeaseTTL.Seconds())
coreMaxTTL := int64(b.Core.maxLeaseTTL.Seconds())
entDefTTL := int64(entry.Config.DefaultLeaseTTL.Seconds())
entMaxTTL := int64(entry.Config.MaxLeaseTTL.Seconds())
entryConfig := map[string]interface{}{
"default_lease_ttl": entDefTTL,
"max_lease_ttl": entMaxTTL,
"force_no_cache": entry.Config.ForceNoCache,
}
if !legacyTTLFormat {
if entDefTTL == 0 {
entryConfig["default_lease_ttl"] = coreDefTTL
}
if entMaxTTL == 0 {
entryConfig["max_lease_ttl"] = coreMaxTTL
}
}
if entry.Config.TrimRequestTrailingSlashes {
entryConfig["trim_request_trailing_slashes"] = true
}
if rawVal, ok := entry.synthesizedConfigCache.Load("audit_non_hmac_request_keys"); ok {
entryConfig["audit_non_hmac_request_keys"] = rawVal.([]string)
}
if rawVal, ok := entry.synthesizedConfigCache.Load("audit_non_hmac_response_keys"); ok {
entryConfig["audit_non_hmac_response_keys"] = rawVal.([]string)
}
// Even though empty value is valid for ListingVisibility, we can ignore
// this case during mount since there's nothing to unset/hide.
if len(entry.Config.ListingVisibility) > 0 {
entryConfig["listing_visibility"] = entry.Config.ListingVisibility
}
if rawVal, ok := entry.synthesizedConfigCache.Load("passthrough_request_headers"); ok {
entryConfig["passthrough_request_headers"] = rawVal.([]string)
}
if rawVal, ok := entry.synthesizedConfigCache.Load("allowed_response_headers"); ok {
entryConfig["allowed_response_headers"] = rawVal.([]string)
}
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()
}
if entry.Config.UserLockoutConfig != nil {
userLockoutConfig := map[string]interface{}{
"user_lockout_counter_reset_duration": int64(entry.Config.UserLockoutConfig.LockoutCounterReset.Seconds()),
"user_lockout_threshold": entry.Config.UserLockoutConfig.LockoutThreshold,
"user_lockout_duration": int64(entry.Config.UserLockoutConfig.LockoutDuration.Seconds()),
"user_lockout_disable": entry.Config.UserLockoutConfig.DisableLockout,
}
entryConfig["user_lockout_config"] = userLockoutConfig
}
if rawVal, ok := entry.synthesizedConfigCache.Load("delegated_auth_accessors"); ok {
entryConfig["delegated_auth_accessors"] = rawVal.([]string)
}
// Add deprecation status only if it exists
builtinType := b.Core.builtinTypeFromMountEntry(ctx, entry)
if status, ok := b.Core.builtinRegistry.DeprecationStatus(entry.Type, builtinType); ok {
info["deprecation_status"] = status.String()
}
info["config"] = entryConfig
return info
}
// handleMountTable handles the "mounts" endpoint to provide the mount table
func (b *SystemBackend) handleMountTable(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
ns, err := namespace.FromContext(ctx)
@ -1504,6 +1423,7 @@ func (b *SystemBackend) handleMountTable(ctx context.Context, req *logical.Reque
}
// handleMount is used to mount a new path
// Vault Enterprise replaces handleMount with entHandlerMount
func (b *SystemBackend) handleMount(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
repState := b.Core.ReplicationState()
@ -2069,6 +1989,7 @@ func (b *SystemBackend) moveMount(ns *namespace.Namespace, logger log.Logger, mi
}
// handleAuthTuneRead is used to get config settings on a auth path
// Vault Enterprise replaces handleAuthTuneRead with entHandleAuthTuneRead
func (b *SystemBackend) handleAuthTuneRead(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
path := data.Get("path").(string)
if path == "" {
@ -2108,6 +2029,7 @@ func (b *SystemBackend) handleRemountStatusCheck(ctx context.Context, req *logic
}
// handleMountTuneRead is used to get config settings on a backend
// Vault Enterprise replaces handleMountTuneRead with entHandleMountTuneRead
func (b *SystemBackend) handleMountTuneRead(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
path := data.Get("path").(string)
if path == "" {
@ -2123,6 +2045,7 @@ func (b *SystemBackend) handleMountTuneRead(ctx context.Context, req *logical.Re
}
// handleTuneReadCommon returns the config settings of a path
// Vault Enterprise replaces handleTuneReadCommon with entHandleTuneReadCommon
func (b *SystemBackend) handleTuneReadCommon(ctx context.Context, path string) (*logical.Response, error) {
path = sanitizePath(path)
@ -2221,6 +2144,7 @@ func (b *SystemBackend) handleTuneReadCommon(ctx context.Context, path string) (
}
// handleAuthTuneWrite is used to set config settings on an auth path
// Vault Enterprise replaces handleAuthTuneWrite with entHandleAuthTuneWrite
func (b *SystemBackend) handleAuthTuneWrite(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
path := data.Get("path").(string)
if path == "" {
@ -2231,6 +2155,7 @@ func (b *SystemBackend) handleAuthTuneWrite(ctx context.Context, req *logical.Re
}
// handleMountTuneWrite is used to set config settings on a backend
// Vault Enterprise replaces handleMountTuneWrite with entHandleMountTuneWrite
func (b *SystemBackend) handleMountTuneWrite(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
path := data.Get("path").(string)
if path == "" {
@ -2244,6 +2169,7 @@ func (b *SystemBackend) handleMountTuneWrite(ctx context.Context, req *logical.R
}
// handleTuneWriteCommon is used to set config settings on a path
// Vault Enterprise replaces handleTuneWriteCommon with entHandleTuneWriteCommon
func (b *SystemBackend) handleTuneWriteCommon(ctx context.Context, path string, data *framework.FieldData) (*logical.Response, error) {
repState := b.Core.ReplicationState()
@ -2477,8 +2403,9 @@ func (b *SystemBackend) handleTuneWriteCommon(ctx context.Context, path string,
if err != nil && !errors.Is(err, pluginutil.ErrPinnedVersionNotFound) {
return nil, err
}
if pinnedVersion != nil {
return logical.ErrorResponse(fmt.Sprintf("plugin_version cannot be set for %s plugin %q as a pinned version %s is in effect", pluginType, mountEntry.Type, pinnedVersion.Version)), nil
return logical.ErrorResponse(fmt.Sprintf("plugin_version cannot be set for %s plugin %q as a pinned version %s is in effect.", pluginType, mountEntry.Type, pinnedVersion.Version)), nil
}
version := rawVal.(string)
@ -3205,6 +3132,7 @@ func expandStringValsWithCommas(configMap map[string]interface{}) error {
}
// handleEnableAuth is used to enable a new credential backend
// Vault Enterprise replaces handleEnableAuth with entHandleEnableAuth
func (b *SystemBackend) handleEnableAuth(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
repState := b.Core.ReplicationState()
local := data.Get("local").(bool)

View file

@ -0,0 +1,673 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package vault
import (
"strings"
"github.com/hashicorp/vault/sdk/framework"
)
// authTuneRequestFields returns the request fields for auth tuning endpoints.
// Used in:
// - POST /sys/auth/{path}/tune
// - POST /sys/mounts/auth/{path}/tune
func authTuneRequestFields() map[string]*framework.FieldSchema {
fields := map[string]*framework.FieldSchema{
"allowed_response_headers": {
Type: framework.TypeCommaStringSlice,
Description: strings.TrimSpace(sysHelp["allowed_response_headers"][0]),
},
"audit_non_hmac_request_keys": {
Type: framework.TypeCommaStringSlice,
Description: strings.TrimSpace(sysHelp["tune_audit_non_hmac_request_keys"][0]),
},
"audit_non_hmac_response_keys": {
Type: framework.TypeCommaStringSlice,
Description: strings.TrimSpace(sysHelp["tune_audit_non_hmac_response_keys"][0]),
},
"default_lease_ttl": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["tune_default_lease_ttl"][0]),
},
"description": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["auth_desc"][0]),
},
"identity_token_key": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["identity_token_key"][0]),
Required: false,
},
"listing_visibility": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["listing_visibility"][0]),
},
"max_lease_ttl": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["tune_max_lease_ttl"][0]),
},
"options": {
Type: framework.TypeKVPairs,
Description: strings.TrimSpace(sysHelp["tune_mount_options"][0]),
},
"passthrough_request_headers": {
Type: framework.TypeCommaStringSlice,
Description: strings.TrimSpace(sysHelp["passthrough_request_headers"][0]),
},
"path": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["auth_tune"][0]),
},
"plugin_version": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["plugin-catalog_version"][0]),
},
"token_type": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["token_type"][0]),
},
"trim_request_trailing_slashes": {
Type: framework.TypeBool,
Required: false,
},
"user_lockout_config": {
Type: framework.TypeMap,
Description: strings.TrimSpace(sysHelp["tune_user_lockout_config"][0]),
},
}
entAddAuthTuneRequestFields(fields)
return fields
}
// authTuneResponseFields returns the response fields for auth tuning endpoints.
// Used in:
// - GET /sys/auth/{path}/tune
// - GET /sys/mounts/auth/{path}/tune
func authTuneResponseFields() map[string]*framework.FieldSchema {
fields := map[string]*framework.FieldSchema{
"allowed_managed_keys": {
Type: framework.TypeCommaStringSlice,
Required: false,
},
"allowed_response_headers": {
Type: framework.TypeCommaStringSlice,
Required: false,
},
"audit_non_hmac_request_keys": {
Type: framework.TypeCommaStringSlice,
Required: false,
},
"audit_non_hmac_response_keys": {
Type: framework.TypeCommaStringSlice,
Required: false,
},
"default_lease_ttl": {
Type: framework.TypeInt,
Required: true,
},
"description": {
Type: framework.TypeString,
Required: true,
},
"external_entropy_access": {
Type: framework.TypeBool,
Required: false,
},
"force_no_cache": {
Type: framework.TypeBool,
Required: true,
},
"identity_token_key": {
Type: framework.TypeString,
Required: false,
},
"listing_visibility": {
Type: framework.TypeString,
Required: false,
},
"max_lease_ttl": {
Type: framework.TypeInt,
Required: true,
},
"options": {
Type: framework.TypeMap,
Required: false,
},
"passthrough_request_headers": {
Type: framework.TypeCommaStringSlice,
Required: false,
},
"plugin_version": {
Type: framework.TypeString,
Required: false,
},
"token_type": {
Type: framework.TypeString,
Required: false,
},
"trim_request_trailing_slashes": {
Type: framework.TypeBool,
Required: false,
},
"user_lockout_counter_reset_duration": {
Type: framework.TypeInt64,
Required: false,
},
"user_lockout_disable": {
Type: framework.TypeBool,
Required: false,
},
"user_lockout_duration": {
Type: framework.TypeInt64,
Required: false,
},
"user_lockout_threshold": {
Type: framework.TypeInt64, // uint64
Required: false,
},
}
entAddAuthTuneResponseFields(fields)
return fields
}
// authRequestFields returns the request fields for auth engine mount/unmount operations.
// Used in:
// - POST /sys/auth/{path} (mount auth engine)
// - DELETE /sys/auth/{path} (unmount auth engine)
func authRequestFields() map[string]*framework.FieldSchema {
fields := map[string]*framework.FieldSchema{
"config": {
Type: framework.TypeMap,
Description: strings.TrimSpace(sysHelp["auth_config"][0]),
},
"description": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["auth_desc"][0]),
},
"external_entropy_access": {
Type: framework.TypeBool,
Default: false,
Description: strings.TrimSpace(sysHelp["external_entropy_access"][0]),
},
"local": {
Type: framework.TypeBool,
Default: false,
Description: strings.TrimSpace(sysHelp["mount_local"][0]),
},
"options": {
Type: framework.TypeKVPairs,
Description: strings.TrimSpace(sysHelp["auth_options"][0]),
},
"path": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["auth_path"][0]),
},
"plugin_name": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["auth_plugin"][0]),
},
"plugin_version": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["plugin-catalog_version"][0]),
},
"seal_wrap": {
Type: framework.TypeBool,
Default: false,
Description: strings.TrimSpace(sysHelp["seal_wrap"][0]),
},
"type": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["auth_type"][0]),
},
}
entAddAuthRequestFields(fields)
return fields
}
// authResponseFields returns the response fields for auth engine read operations.
// Used in:
// - GET /sys/auth/{path} (read auth engine configuration)
func authResponseFields() map[string]*framework.FieldSchema {
fields := map[string]*framework.FieldSchema{
"accessor": {
Type: framework.TypeString,
Required: true,
},
"config": {
Type: framework.TypeMap,
Required: true,
},
"deprecation_status": {
Type: framework.TypeString,
Required: false,
},
"description": {
Type: framework.TypeString,
Required: true,
},
"external_entropy_access": {
Type: framework.TypeBool,
Required: true,
},
"local": {
Type: framework.TypeBool,
Required: true,
},
"options": {
Type: framework.TypeMap,
Required: true,
},
"plugin_version": {
Type: framework.TypeString,
Required: true,
},
"running_plugin_version": {
Type: framework.TypeString,
Required: true,
},
"running_sha256": {
Type: framework.TypeString,
Required: true,
},
"seal_wrap": {
Type: framework.TypeBool,
Required: true,
},
"type": {
Type: framework.TypeString,
Required: true,
},
"uuid": {
Type: framework.TypeString,
Required: true,
},
}
entAddAuthResponseFields(fields)
return fields
}
// secretsTuneRequestFields returns the request fields for secrets engine tuning operations.
// Used in:
// - POST /sys/mounts/{path}/tune
func secretsTuneRequestFields() map[string]*framework.FieldSchema {
fields := map[string]*framework.FieldSchema{
"allowed_managed_keys": {
Type: framework.TypeCommaStringSlice,
Description: strings.TrimSpace(sysHelp["tune_allowed_managed_keys"][0]),
},
"allowed_response_headers": {
Type: framework.TypeCommaStringSlice,
Description: strings.TrimSpace(sysHelp["allowed_response_headers"][0]),
},
"audit_non_hmac_request_keys": {
Type: framework.TypeCommaStringSlice,
Description: strings.TrimSpace(sysHelp["tune_audit_non_hmac_request_keys"][0]),
},
"audit_non_hmac_response_keys": {
Type: framework.TypeCommaStringSlice,
Description: strings.TrimSpace(sysHelp["tune_audit_non_hmac_response_keys"][0]),
},
"default_lease_ttl": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["tune_default_lease_ttl"][0]),
},
"delegated_auth_accessors": {
Type: framework.TypeCommaStringSlice,
Description: strings.TrimSpace(sysHelp["allowed_delegated_auth_accessors"][0]),
},
"description": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["auth_desc"][0]),
},
"identity_token_key": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["identity_token_key"][0]),
},
"listing_visibility": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["listing_visibility"][0]),
},
"max_lease_ttl": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["tune_max_lease_ttl"][0]),
},
"options": {
Type: framework.TypeKVPairs,
Description: strings.TrimSpace(sysHelp["tune_mount_options"][0]),
},
"passthrough_request_headers": {
Type: framework.TypeCommaStringSlice,
Description: strings.TrimSpace(sysHelp["passthrough_request_headers"][0]),
},
"path": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["mount_path"][0]),
},
"plugin_version": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["plugin-catalog_version"][0]),
},
"token_type": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["token_type"][0]),
},
"trim_request_trailing_slashes": {
Type: framework.TypeBool,
Description: strings.TrimSpace(sysHelp["trim_request_trailing_slashes"][0]),
},
"user_lockout_config": {
Type: framework.TypeMap,
Description: strings.TrimSpace(sysHelp["tune_user_lockout_config"][0]),
},
}
entAddSecretsTuneRequestFields(fields)
return fields
}
// secretsTuneResponseFields returns the response fields for secrets engine tuning operations.
// Used in:
// - GET /sys/mounts/{path}/tune
func secretsTuneResponseFields() map[string]*framework.FieldSchema {
fields := map[string]*framework.FieldSchema{
"allowed_managed_keys": {
Type: framework.TypeCommaStringSlice,
Description: strings.TrimSpace(sysHelp["tune_allowed_managed_keys"][0]),
Required: false,
},
"allowed_response_headers": {
Type: framework.TypeCommaStringSlice,
Description: strings.TrimSpace(sysHelp["allowed_response_headers"][0]),
Required: false,
},
"audit_non_hmac_request_keys": {
Type: framework.TypeCommaStringSlice,
Required: false,
},
"audit_non_hmac_response_keys": {
Type: framework.TypeCommaStringSlice,
Required: false,
},
"default_lease_ttl": {
Type: framework.TypeInt,
Description: strings.TrimSpace(sysHelp["tune_default_lease_ttl"][0]),
Required: true,
},
"delegated_auth_accessors": {
Type: framework.TypeCommaStringSlice,
Description: strings.TrimSpace(sysHelp["delegated_auth_accessors"][0]),
Required: false,
},
"description": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["auth_desc"][0]),
Required: true,
},
"external_entropy_access": {
Type: framework.TypeBool,
Required: false,
},
"force_no_cache": {
Type: framework.TypeBool,
Required: true,
},
"identity_token_key": {
Type: framework.TypeString,
Required: false,
},
"listing_visibility": {
Type: framework.TypeString,
Required: false,
},
"max_lease_ttl": {
Type: framework.TypeInt,
Description: strings.TrimSpace(sysHelp["tune_max_lease_ttl"][0]),
Required: true,
},
"options": {
Type: framework.TypeKVPairs,
Description: strings.TrimSpace(sysHelp["tune_mount_options"][0]),
Required: false,
},
"passthrough_request_headers": {
Type: framework.TypeCommaStringSlice,
Required: false,
},
"plugin_version": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["plugin-catalog_version"][0]),
Required: false,
},
"token_type": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["token_type"][0]),
Required: false,
},
"trim_request_trailing_slashes": {
Type: framework.TypeBool,
Required: false,
},
"user_lockout_counter_reset_duration": {
Type: framework.TypeInt64,
Required: false,
},
"user_lockout_disable": {
Type: framework.TypeBool,
Required: false,
},
"user_lockout_duration": {
Type: framework.TypeInt64,
Required: false,
},
"user_lockout_threshold": {
Type: framework.TypeInt64, // TODO this is actuall a Uint64 do we need a new type?
Required: false,
},
}
entAddSecretsTuneResponseFields(fields)
return fields
}
// secretsRequestFields returns the request fields for secrets engine mount/unmount operations.
// Used in:
// - POST /sys/mounts/{path} (mount secrets engine)
// - DELETE /sys/mounts/{path} (unmount secrets engine)
func secretsRequestFields() map[string]*framework.FieldSchema {
fields := map[string]*framework.FieldSchema{
"config": {
Type: framework.TypeMap,
Description: strings.TrimSpace(sysHelp["mount_config"][0]),
},
"description": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["mount_desc"][0]),
},
"external_entropy_access": {
Type: framework.TypeBool,
Default: false,
Description: strings.TrimSpace(sysHelp["external_entropy_access"][0]),
},
"local": {
Type: framework.TypeBool,
Default: false,
Description: strings.TrimSpace(sysHelp["mount_local"][0]),
},
"options": {
Type: framework.TypeKVPairs,
Description: strings.TrimSpace(sysHelp["mount_options"][0]),
},
"path": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["mount_path"][0]),
},
"plugin_name": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["mount_plugin_name"][0]),
},
"plugin_version": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["plugin-catalog_version"][0]),
},
"seal_wrap": {
Type: framework.TypeBool,
Default: false,
Description: strings.TrimSpace(sysHelp["seal_wrap"][0]),
},
"type": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["mount_type"][0]),
},
}
entAddSecretsRequestFields(fields)
return fields
}
// secretsResponseFields returns the response fields for secrets engine read operations.
// Used in:
// - GET /sys/mounts/{path} (read secrets engine configuration)
func secretsResponseFields() map[string]*framework.FieldSchema {
fields := map[string]*framework.FieldSchema{
"accessor": {
Type: framework.TypeString,
Required: true,
},
"config": {
Type: framework.TypeMap,
Description: strings.TrimSpace(sysHelp["mount_config"][0]),
Required: true,
},
"deprecation_status": {
Type: framework.TypeString,
Required: false,
},
"description": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["mount_desc"][0]),
Required: true,
},
"external_entropy_access": {
Type: framework.TypeBool,
Required: true,
},
"local": {
Type: framework.TypeBool,
Default: false,
Description: strings.TrimSpace(sysHelp["mount_local"][0]),
Required: true,
},
"options": {
Type: framework.TypeKVPairs,
Description: strings.TrimSpace(sysHelp["mount_options"][0]),
Required: true,
},
"plugin_version": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["plugin-catalog_version"][0]),
Required: true,
},
"running_plugin_version": {
Type: framework.TypeString,
Required: true,
},
"running_sha256": {
Type: framework.TypeString,
Required: true,
},
"seal_wrap": {
Type: framework.TypeBool,
Default: false,
Description: strings.TrimSpace(sysHelp["seal_wrap"][0]),
Required: true,
},
"type": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["mount_type"][0]),
Required: true,
},
"uuid": {
Type: framework.TypeString,
Required: true,
},
}
entAddSecretsResponseFields(fields)
return fields
}
// internalUIMountsPathResponse returns the response fields for the internal UI mounts path.
// Used in:
// - GET /sys/internal/ui/mounts/{path}
func internalUIMountsPathResponseFields() map[string]*framework.FieldSchema {
fields := map[string]*framework.FieldSchema{
"accessor": {
Type: framework.TypeString,
Required: true,
},
"config": {
Type: framework.TypeMap,
Required: true,
},
"description": {
Type: framework.TypeString,
Required: true,
},
"external_entropy_access": {
Type: framework.TypeBool,
Required: true,
},
"local": {
Type: framework.TypeBool,
Required: true,
},
"options": {
Type: framework.TypeMap,
Required: true,
},
"path": {
Type: framework.TypeString,
Required: true,
},
"plugin_version": {
Type: framework.TypeString,
Required: true,
},
"running_plugin_version": {
Type: framework.TypeString,
Required: true,
},
"running_sha256": {
Type: framework.TypeString,
Required: true,
},
"seal_wrap": {
Type: framework.TypeBool,
Required: true,
},
"type": {
Type: framework.TypeString,
Required: true,
},
"uuid": {
Type: framework.TypeString,
Required: true,
},
}
return fields
}

View file

@ -0,0 +1,48 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
//go:build !enterprise
package vault
import "github.com/hashicorp/vault/sdk/framework"
// entAddAuthTuneRequestFields is a stub implementation for CE
func entAddAuthTuneRequestFields(fields map[string]*framework.FieldSchema) {
// No additional fields in CE
}
// entAddAuthTuneResponseFields is a stub implementation for CE
func entAddAuthTuneResponseFields(fields map[string]*framework.FieldSchema) {
// No additional fields in CE
}
// entAddAuthRequestFields is a stub implementation for CE
func entAddAuthRequestFields(fields map[string]*framework.FieldSchema) {
// No additional fields in CE
}
// entAddAuthResponseFields is a stub implementation for CE
func entAddAuthResponseFields(fields map[string]*framework.FieldSchema) {
// No additional fields in CE
}
// entAddSecretsTuneRequestFields is a stub implementation for CE
func entAddSecretsTuneRequestFields(fields map[string]*framework.FieldSchema) {
// No additional fields in CE
}
// entAddSecretsTuneResponseFields is a stub implementation for CE
func entAddSecretsTuneResponseFields(fields map[string]*framework.FieldSchema) {
// No additional fields in CE
}
// entAddSecretsRequestFields is a stub implementation for CE
func entAddSecretsRequestFields(fields map[string]*framework.FieldSchema) {
// No additional fields in CE
}
// entAddSecretsResponseFields is a stub implementation for CE
func entAddSecretsResponseFields(fields map[string]*framework.FieldSchema) {
// No additional fields in CE
}

View file

@ -11,6 +11,34 @@ import (
"github.com/hashicorp/vault/sdk/logical"
)
const (
// Auth paths patterns
patternAuth = "auth$"
patternAuthTune = "auth/(?P<path>.+?)/tune$"
patternAuthPath = "auth/(?P<path>.+)"
// Mount paths patterns
patternMountsTune = "mounts/(?P<path>.+?)/tune$"
patternMountsAuthTune = "mounts/auth/(?P<path>.+?)/tune$"
patternMountsPath = "mounts/(?P<path>.+?)"
patternMounts = "mounts$"
)
var passwordPolicySchema = map[string]*framework.FieldSchema{
"name": {
Type: framework.TypeString,
Description: "The name of the password policy.",
},
"policy": {
Type: framework.TypeString,
Description: "The password policy",
},
"entropy_source": {
Type: framework.TypeString,
Description: "The entropy source for generation",
},
}
func (b *SystemBackend) configPaths() []*framework.Path {
return []*framework.Path{
{
@ -2742,60 +2770,7 @@ func (b *SystemBackend) internalPaths() []*framework.Path {
Responses: map[int][]framework.Response{
http.StatusOK: {{
Description: "OK",
Fields: map[string]*framework.FieldSchema{
"type": {
Type: framework.TypeString,
Required: true,
},
"description": {
Type: framework.TypeString,
Required: true,
},
"accessor": {
Type: framework.TypeString,
Required: true,
},
"local": {
Type: framework.TypeBool,
Required: true,
},
"seal_wrap": {
Type: framework.TypeBool,
Required: true,
},
"external_entropy_access": {
Type: framework.TypeBool,
Required: true,
},
"options": {
Type: framework.TypeMap,
Required: true,
},
"uuid": {
Type: framework.TypeString,
Required: true,
},
"plugin_version": {
Type: framework.TypeString,
Required: true,
},
"running_plugin_version": {
Type: framework.TypeString,
Required: true,
},
"running_sha256": {
Type: framework.TypeString,
Required: true,
},
"path": {
Type: framework.TypeString,
Required: true,
},
"config": {
Type: framework.TypeMap,
Required: true,
},
},
Fields: internalUIMountsPathResponseFields(),
}},
},
},
@ -3719,7 +3694,7 @@ func (b *SystemBackend) hostInfoPath() *framework.Path {
func (b *SystemBackend) authPaths() []*framework.Path {
return []*framework.Path{
{
Pattern: "auth$",
Pattern: patternAuth,
DisplayAttrs: &framework.DisplayAttributes{
OperationPrefix: "auth",
@ -3743,75 +3718,13 @@ func (b *SystemBackend) authPaths() []*framework.Path {
HelpDescription: strings.TrimSpace(sysHelp["auth-table"][1]),
},
{
Pattern: "auth/(?P<path>.+?)/tune$",
Pattern: patternAuthTune,
DisplayAttrs: &framework.DisplayAttributes{
OperationPrefix: "auth",
},
Fields: map[string]*framework.FieldSchema{
"path": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["auth_tune"][0]),
},
"default_lease_ttl": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["tune_default_lease_ttl"][0]),
},
"max_lease_ttl": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["tune_max_lease_ttl"][0]),
},
"description": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["auth_desc"][0]),
},
"audit_non_hmac_request_keys": {
Type: framework.TypeCommaStringSlice,
Description: strings.TrimSpace(sysHelp["tune_audit_non_hmac_request_keys"][0]),
},
"audit_non_hmac_response_keys": {
Type: framework.TypeCommaStringSlice,
Description: strings.TrimSpace(sysHelp["tune_audit_non_hmac_response_keys"][0]),
},
"options": {
Type: framework.TypeKVPairs,
Description: strings.TrimSpace(sysHelp["tune_mount_options"][0]),
},
"listing_visibility": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["listing_visibility"][0]),
},
"passthrough_request_headers": {
Type: framework.TypeCommaStringSlice,
Description: strings.TrimSpace(sysHelp["passthrough_request_headers"][0]),
},
"allowed_response_headers": {
Type: framework.TypeCommaStringSlice,
Description: strings.TrimSpace(sysHelp["allowed_response_headers"][0]),
},
"token_type": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["token_type"][0]),
},
"user_lockout_config": {
Type: framework.TypeMap,
Description: strings.TrimSpace(sysHelp["tune_user_lockout_config"][0]),
},
"plugin_version": {
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,
},
"trim_request_trailing_slashes": {
Type: framework.TypeBool,
Required: false,
},
},
Fields: authTuneRequestFields(),
Operations: map[logical.Operation]framework.OperationHandler{
logical.ReadOperation: &framework.PathOperation{
Callback: b.handleAuthTuneRead,
@ -3824,88 +3737,7 @@ func (b *SystemBackend) authPaths() []*framework.Path {
Responses: map[int][]framework.Response{
http.StatusOK: {{
Description: "OK",
Fields: map[string]*framework.FieldSchema{
"description": {
Type: framework.TypeString,
Required: true,
},
"default_lease_ttl": {
Type: framework.TypeInt,
Required: true,
},
"max_lease_ttl": {
Type: framework.TypeInt,
Required: true,
},
"force_no_cache": {
Type: framework.TypeBool,
Required: true,
},
"external_entropy_access": {
Type: framework.TypeBool,
Required: false,
},
"token_type": {
Type: framework.TypeString,
Required: false,
},
"audit_non_hmac_request_keys": {
Type: framework.TypeCommaStringSlice,
Required: false,
},
"audit_non_hmac_response_keys": {
Type: framework.TypeCommaStringSlice,
Required: false,
},
"listing_visibility": {
Type: framework.TypeString,
Required: false,
},
"passthrough_request_headers": {
Type: framework.TypeCommaStringSlice,
Required: false,
},
"allowed_response_headers": {
Type: framework.TypeCommaStringSlice,
Required: false,
},
"allowed_managed_keys": {
Type: framework.TypeCommaStringSlice,
Required: false,
},
"user_lockout_counter_reset_duration": {
Type: framework.TypeInt64,
Required: false,
},
"user_lockout_threshold": {
Type: framework.TypeInt64, // uint64
Required: false,
},
"user_lockout_duration": {
Type: framework.TypeInt64,
Required: false,
},
"user_lockout_disable": {
Type: framework.TypeBool,
Required: false,
},
"options": {
Type: framework.TypeMap,
Required: false,
},
"plugin_version": {
Type: framework.TypeString,
Required: false,
},
"identity_token_key": {
Type: framework.TypeString,
Required: false,
},
"trim_request_trailing_slashes": {
Type: framework.TypeBool,
Required: false,
},
},
Fields: authTuneResponseFields(),
}},
},
},
@ -3928,57 +3760,13 @@ func (b *SystemBackend) authPaths() []*framework.Path {
HelpDescription: strings.TrimSpace(sysHelp["auth_tune"][1]),
},
{
Pattern: "auth/(?P<path>.+)",
Pattern: patternAuthPath,
DisplayAttrs: &framework.DisplayAttributes{
OperationPrefix: "auth",
},
Fields: map[string]*framework.FieldSchema{
"path": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["auth_path"][0]),
},
"type": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["auth_type"][0]),
},
"description": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["auth_desc"][0]),
},
"config": {
Type: framework.TypeMap,
Description: strings.TrimSpace(sysHelp["auth_config"][0]),
},
"local": {
Type: framework.TypeBool,
Default: false,
Description: strings.TrimSpace(sysHelp["mount_local"][0]),
},
"seal_wrap": {
Type: framework.TypeBool,
Default: false,
Description: strings.TrimSpace(sysHelp["seal_wrap"][0]),
},
"external_entropy_access": {
Type: framework.TypeBool,
Default: false,
Description: strings.TrimSpace(sysHelp["external_entropy_access"][0]),
},
"plugin_name": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["auth_plugin"][0]),
},
"options": {
Type: framework.TypeKVPairs,
Description: strings.TrimSpace(sysHelp["auth_options"][0]),
},
"plugin_version": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["plugin-catalog_version"][0]),
},
},
Fields: authRequestFields(),
Operations: map[logical.Operation]framework.OperationHandler{
logical.ReadOperation: &framework.PathOperation{
Callback: b.handleReadAuth,
@ -3990,60 +3778,7 @@ func (b *SystemBackend) authPaths() []*framework.Path {
Responses: map[int][]framework.Response{
http.StatusOK: {{
Description: "OK",
Fields: map[string]*framework.FieldSchema{
"type": {
Type: framework.TypeString,
Required: true,
},
"description": {
Type: framework.TypeString,
Required: true,
},
"accessor": {
Type: framework.TypeString,
Required: true,
},
"local": {
Type: framework.TypeBool,
Required: true,
},
"seal_wrap": {
Type: framework.TypeBool,
Required: true,
},
"external_entropy_access": {
Type: framework.TypeBool,
Required: true,
},
"options": {
Type: framework.TypeMap,
Required: true,
},
"uuid": {
Type: framework.TypeString,
Required: true,
},
"plugin_version": {
Type: framework.TypeString,
Required: true,
},
"running_plugin_version": {
Type: framework.TypeString,
Required: true,
},
"running_sha256": {
Type: framework.TypeString,
Required: true,
},
"deprecation_status": {
Type: framework.TypeString,
Required: false,
},
"config": {
Type: framework.TypeMap,
Required: true,
},
},
Fields: authResponseFields(),
}},
},
},
@ -4601,85 +4336,16 @@ func (b *SystemBackend) wrappingPaths() []*framework.Path {
}
}
func (b *SystemBackend) mountPaths() []*framework.Path {
func (b *SystemBackend) mountsPaths() []*framework.Path {
return []*framework.Path{
{
Pattern: "mounts/(?P<path>.+?)/tune$",
Pattern: patternMountsTune,
DisplayAttrs: &framework.DisplayAttributes{
OperationPrefix: "mounts",
},
Fields: map[string]*framework.FieldSchema{
"path": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["mount_path"][0]),
},
"default_lease_ttl": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["tune_default_lease_ttl"][0]),
},
"max_lease_ttl": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["tune_max_lease_ttl"][0]),
},
"description": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["auth_desc"][0]),
},
"audit_non_hmac_request_keys": {
Type: framework.TypeCommaStringSlice,
Description: strings.TrimSpace(sysHelp["tune_audit_non_hmac_request_keys"][0]),
},
"audit_non_hmac_response_keys": {
Type: framework.TypeCommaStringSlice,
Description: strings.TrimSpace(sysHelp["tune_audit_non_hmac_response_keys"][0]),
},
"options": {
Type: framework.TypeKVPairs,
Description: strings.TrimSpace(sysHelp["tune_mount_options"][0]),
},
"listing_visibility": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["listing_visibility"][0]),
},
"passthrough_request_headers": {
Type: framework.TypeCommaStringSlice,
Description: strings.TrimSpace(sysHelp["passthrough_request_headers"][0]),
},
"allowed_response_headers": {
Type: framework.TypeCommaStringSlice,
Description: strings.TrimSpace(sysHelp["allowed_response_headers"][0]),
},
"token_type": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["token_type"][0]),
},
"allowed_managed_keys": {
Type: framework.TypeCommaStringSlice,
Description: strings.TrimSpace(sysHelp["tune_allowed_managed_keys"][0]),
},
"delegated_auth_accessors": {
Type: framework.TypeCommaStringSlice,
Description: strings.TrimSpace(sysHelp["allowed_delegated_auth_accessors"][0]),
},
"plugin_version": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["plugin-catalog_version"][0]),
},
"user_lockout_config": {
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]),
},
"trim_request_trailing_slashes": {
Type: framework.TypeBool,
Description: strings.TrimSpace(sysHelp["trim_request_trailing_slashes"][0]),
},
},
Fields: secretsTuneRequestFields(),
Operations: map[logical.Operation]framework.OperationHandler{
logical.ReadOperation: &framework.PathOperation{
@ -4691,101 +4357,7 @@ func (b *SystemBackend) mountPaths() []*framework.Path {
Responses: map[int][]framework.Response{
http.StatusOK: {{
Description: "OK",
Fields: map[string]*framework.FieldSchema{
"max_lease_ttl": {
Type: framework.TypeInt,
Description: strings.TrimSpace(sysHelp["tune_max_lease_ttl"][0]),
Required: true,
},
"description": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["auth_desc"][0]),
Required: true,
},
"default_lease_ttl": {
Type: framework.TypeInt,
Description: strings.TrimSpace(sysHelp["tune_default_lease_ttl"][0]),
Required: true,
},
"force_no_cache": {
Type: framework.TypeBool,
Required: true,
},
"token_type": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["token_type"][0]),
Required: false,
},
"allowed_managed_keys": {
Type: framework.TypeCommaStringSlice,
Description: strings.TrimSpace(sysHelp["tune_allowed_managed_keys"][0]),
Required: false,
},
"delegated_auth_accessors": {
Type: framework.TypeCommaStringSlice,
Description: strings.TrimSpace(sysHelp["delegated_auth_accessors"][0]),
Required: false,
},
"allowed_response_headers": {
Type: framework.TypeCommaStringSlice,
Description: strings.TrimSpace(sysHelp["allowed_response_headers"][0]),
Required: false,
},
"options": {
Type: framework.TypeKVPairs,
Description: strings.TrimSpace(sysHelp["tune_mount_options"][0]),
Required: false,
},
"plugin_version": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["plugin-catalog_version"][0]),
Required: false,
},
"external_entropy_access": {
Type: framework.TypeBool,
Required: false,
},
"audit_non_hmac_request_keys": {
Type: framework.TypeCommaStringSlice,
Required: false,
},
"audit_non_hmac_response_keys": {
Type: framework.TypeCommaStringSlice,
Required: false,
},
"listing_visibility": {
Type: framework.TypeString,
Required: false,
},
"passthrough_request_headers": {
Type: framework.TypeCommaStringSlice,
Required: false,
},
"user_lockout_counter_reset_duration": {
Type: framework.TypeInt64,
Required: false,
},
"user_lockout_threshold": {
Type: framework.TypeInt64, // TODO this is actuall a Uint64 do we need a new type?
Required: false,
},
"user_lockout_duration": {
Type: framework.TypeInt64,
Required: false,
},
"user_lockout_disable": {
Type: framework.TypeBool,
Required: false,
},
"identity_token_key": {
Type: framework.TypeString,
Required: false,
},
"trim_request_trailing_slashes": {
Type: framework.TypeBool,
Required: false,
},
},
Fields: secretsTuneResponseFields(),
}},
},
},
@ -4808,75 +4380,13 @@ func (b *SystemBackend) mountPaths() []*framework.Path {
},
{
Pattern: "mounts/auth/(?P<path>.+?)/tune$",
Pattern: patternMountsAuthTune,
DisplayAttrs: &framework.DisplayAttributes{
OperationPrefix: "mounts-auth",
},
Fields: map[string]*framework.FieldSchema{
"path": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["auth_tune"][0]),
},
"default_lease_ttl": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["tune_default_lease_ttl"][0]),
},
"max_lease_ttl": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["tune_max_lease_ttl"][0]),
},
"description": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["auth_desc"][0]),
},
"audit_non_hmac_request_keys": {
Type: framework.TypeCommaStringSlice,
Description: strings.TrimSpace(sysHelp["tune_audit_non_hmac_request_keys"][0]),
},
"audit_non_hmac_response_keys": {
Type: framework.TypeCommaStringSlice,
Description: strings.TrimSpace(sysHelp["tune_audit_non_hmac_response_keys"][0]),
},
"options": {
Type: framework.TypeKVPairs,
Description: strings.TrimSpace(sysHelp["tune_mount_options"][0]),
},
"listing_visibility": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["listing_visibility"][0]),
},
"passthrough_request_headers": {
Type: framework.TypeCommaStringSlice,
Description: strings.TrimSpace(sysHelp["passthrough_request_headers"][0]),
},
"allowed_response_headers": {
Type: framework.TypeCommaStringSlice,
Description: strings.TrimSpace(sysHelp["allowed_response_headers"][0]),
},
"token_type": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["token_type"][0]),
},
"user_lockout_config": {
Type: framework.TypeMap,
Description: strings.TrimSpace(sysHelp["tune_user_lockout_config"][0]),
},
"plugin_version": {
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,
},
"trim_request_trailing_slashes": {
Type: framework.TypeBool,
Required: false,
},
},
Fields: authTuneRequestFields(),
Operations: map[logical.Operation]framework.OperationHandler{
logical.ReadOperation: &framework.PathOperation{
Callback: b.handleAuthTuneRead,
@ -4889,88 +4399,7 @@ func (b *SystemBackend) mountPaths() []*framework.Path {
Responses: map[int][]framework.Response{
http.StatusOK: {{
Description: "OK",
Fields: map[string]*framework.FieldSchema{
"description": {
Type: framework.TypeString,
Required: true,
},
"default_lease_ttl": {
Type: framework.TypeInt,
Required: true,
},
"max_lease_ttl": {
Type: framework.TypeInt,
Required: true,
},
"force_no_cache": {
Type: framework.TypeBool,
Required: true,
},
"external_entropy_access": {
Type: framework.TypeBool,
Required: false,
},
"token_type": {
Type: framework.TypeString,
Required: false,
},
"audit_non_hmac_request_keys": {
Type: framework.TypeCommaStringSlice,
Required: false,
},
"audit_non_hmac_response_keys": {
Type: framework.TypeCommaStringSlice,
Required: false,
},
"listing_visibility": {
Type: framework.TypeString,
Required: false,
},
"passthrough_request_headers": {
Type: framework.TypeCommaStringSlice,
Required: false,
},
"allowed_response_headers": {
Type: framework.TypeCommaStringSlice,
Required: false,
},
"allowed_managed_keys": {
Type: framework.TypeCommaStringSlice,
Required: false,
},
"user_lockout_counter_reset_duration": {
Type: framework.TypeInt64,
Required: false,
},
"user_lockout_threshold": {
Type: framework.TypeInt64, // uint64
Required: false,
},
"user_lockout_duration": {
Type: framework.TypeInt64,
Required: false,
},
"user_lockout_disable": {
Type: framework.TypeBool,
Required: false,
},
"options": {
Type: framework.TypeMap,
Required: false,
},
"plugin_version": {
Type: framework.TypeString,
Required: false,
},
"identity_token_key": {
Type: framework.TypeString,
Required: false,
},
"trim_request_trailing_slashes": {
Type: framework.TypeBool,
Required: false,
},
},
Fields: authTuneResponseFields(),
}},
},
},
@ -4994,57 +4423,13 @@ func (b *SystemBackend) mountPaths() []*framework.Path {
},
{
Pattern: "mounts/(?P<path>.+?)",
Pattern: patternMountsPath,
DisplayAttrs: &framework.DisplayAttributes{
OperationPrefix: "mounts",
},
Fields: map[string]*framework.FieldSchema{
"path": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["mount_path"][0]),
},
"type": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["mount_type"][0]),
},
"description": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["mount_desc"][0]),
},
"config": {
Type: framework.TypeMap,
Description: strings.TrimSpace(sysHelp["mount_config"][0]),
},
"local": {
Type: framework.TypeBool,
Default: false,
Description: strings.TrimSpace(sysHelp["mount_local"][0]),
},
"seal_wrap": {
Type: framework.TypeBool,
Default: false,
Description: strings.TrimSpace(sysHelp["seal_wrap"][0]),
},
"external_entropy_access": {
Type: framework.TypeBool,
Default: false,
Description: strings.TrimSpace(sysHelp["external_entropy_access"][0]),
},
"plugin_name": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["mount_plugin_name"][0]),
},
"options": {
Type: framework.TypeKVPairs,
Description: strings.TrimSpace(sysHelp["mount_options"][0]),
},
"plugin_version": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["plugin-catalog_version"][0]),
},
},
Fields: secretsRequestFields(),
Operations: map[logical.Operation]framework.OperationHandler{
logical.ReadOperation: &framework.PathOperation{
@ -5056,69 +4441,7 @@ func (b *SystemBackend) mountPaths() []*framework.Path {
Responses: map[int][]framework.Response{
http.StatusOK: {{
Description: "OK",
Fields: map[string]*framework.FieldSchema{
"type": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["mount_type"][0]),
Required: true,
},
"description": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["mount_desc"][0]),
Required: true,
},
"accessor": {
Type: framework.TypeString,
Required: true,
},
"local": {
Type: framework.TypeBool,
Default: false,
Description: strings.TrimSpace(sysHelp["mount_local"][0]),
Required: true,
},
"seal_wrap": {
Type: framework.TypeBool,
Default: false,
Description: strings.TrimSpace(sysHelp["seal_wrap"][0]),
Required: true,
},
"external_entropy_access": {
Type: framework.TypeBool,
Required: true,
},
"options": {
Type: framework.TypeKVPairs,
Description: strings.TrimSpace(sysHelp["mount_options"][0]),
Required: true,
},
"plugin_version": {
Type: framework.TypeString,
Description: strings.TrimSpace(sysHelp["plugin-catalog_version"][0]),
Required: true,
},
"uuid": {
Type: framework.TypeString,
Required: true,
},
"running_plugin_version": {
Type: framework.TypeString,
Required: true,
},
"running_sha256": {
Type: framework.TypeString,
Required: true,
},
"config": {
Type: framework.TypeMap,
Description: strings.TrimSpace(sysHelp["mount_config"][0]),
Required: true,
},
"deprecation_status": {
Type: framework.TypeString,
Required: false,
},
},
Fields: secretsResponseFields(),
}},
},
Summary: "Read the configuration of the secret engine at the given path.",
@ -5155,7 +4478,7 @@ func (b *SystemBackend) mountPaths() []*framework.Path {
},
{
Pattern: "mounts$",
Pattern: patternMounts,
DisplayAttrs: &framework.DisplayAttributes{
OperationPrefix: "mounts",

View file

@ -0,0 +1,20 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
//go:build !enterprise
package vault
import "github.com/hashicorp/vault/sdk/framework"
func entWrappedPluginsCRUDPath(b *SystemBackend) []*framework.Path {
return []*framework.Path{b.pluginsCatalogCRUDPath()}
}
func entWrappedAuthPath(b *SystemBackend) []*framework.Path {
return b.authPaths()
}
func entWrappedMountsPath(b *SystemBackend) []*framework.Path {
return b.mountsPaths()
}

View file

@ -32,6 +32,87 @@ func (s *SystemBackend) makeSnapshotSource(ctx context.Context, _ *framework.Fie
return snapshots.NewManualSnapshotSource(body), nil
}
func entWrappedPluginsCRUDPath(b *SystemBackend) []*framework.Path {
return []*framework.Path{b.pluginsCatalogCRUDPath()}
// mountInfo returns a map of information about the given mount entry
// Enterprise-specific fields are added in the enterprise version of this method.
func (b *SystemBackend) mountInfo(ctx context.Context, entry *MountEntry, legacyTTLFormat bool) map[string]interface{} {
info := map[string]interface{}{
"type": entry.Type,
"description": entry.Description,
"accessor": entry.Accessor,
"local": entry.Local,
"seal_wrap": entry.SealWrap,
"external_entropy_access": entry.ExternalEntropyAccess,
"options": entry.Options,
"uuid": entry.UUID,
"plugin_version": entry.Version,
"running_plugin_version": entry.RunningVersion,
"running_sha256": entry.RunningSha256,
}
coreDefTTL := int64(b.Core.defaultLeaseTTL.Seconds())
coreMaxTTL := int64(b.Core.maxLeaseTTL.Seconds())
entDefTTL := int64(entry.Config.DefaultLeaseTTL.Seconds())
entMaxTTL := int64(entry.Config.MaxLeaseTTL.Seconds())
entryConfig := map[string]interface{}{
"default_lease_ttl": entDefTTL,
"max_lease_ttl": entMaxTTL,
"force_no_cache": entry.Config.ForceNoCache,
}
if !legacyTTLFormat {
if entDefTTL == 0 {
entryConfig["default_lease_ttl"] = coreDefTTL
}
if entMaxTTL == 0 {
entryConfig["max_lease_ttl"] = coreMaxTTL
}
}
if entry.Config.TrimRequestTrailingSlashes {
entryConfig["trim_request_trailing_slashes"] = true
}
if rawVal, ok := entry.synthesizedConfigCache.Load("audit_non_hmac_request_keys"); ok {
entryConfig["audit_non_hmac_request_keys"] = rawVal.([]string)
}
if rawVal, ok := entry.synthesizedConfigCache.Load("audit_non_hmac_response_keys"); ok {
entryConfig["audit_non_hmac_response_keys"] = rawVal.([]string)
}
// Even though empty value is valid for ListingVisibility, we can ignore
// this case during mount since there's nothing to unset/hide.
if len(entry.Config.ListingVisibility) > 0 {
entryConfig["listing_visibility"] = entry.Config.ListingVisibility
}
if rawVal, ok := entry.synthesizedConfigCache.Load("passthrough_request_headers"); ok {
entryConfig["passthrough_request_headers"] = rawVal.([]string)
}
if rawVal, ok := entry.synthesizedConfigCache.Load("allowed_response_headers"); ok {
entryConfig["allowed_response_headers"] = rawVal.([]string)
}
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()
}
if entry.Config.UserLockoutConfig != nil {
userLockoutConfig := map[string]interface{}{
"user_lockout_counter_reset_duration": int64(entry.Config.UserLockoutConfig.LockoutCounterReset.Seconds()),
"user_lockout_threshold": entry.Config.UserLockoutConfig.LockoutThreshold,
"user_lockout_duration": int64(entry.Config.UserLockoutConfig.LockoutDuration.Seconds()),
"user_lockout_disable": entry.Config.UserLockoutConfig.DisableLockout,
}
entryConfig["user_lockout_config"] = userLockoutConfig
}
if rawVal, ok := entry.synthesizedConfigCache.Load("delegated_auth_accessors"); ok {
entryConfig["delegated_auth_accessors"] = rawVal.([]string)
}
// Add deprecation status only if it exists
builtinType := b.Core.builtinTypeFromMountEntry(ctx, entry)
if status, ok := b.Core.builtinRegistry.DeprecationStatus(entry.Type, builtinType); ok {
info["deprecation_status"] = status.String()
}
info["config"] = entryConfig
return info
}

View file

@ -24,7 +24,6 @@ import (
"github.com/hashicorp/vault/helper/versions"
"github.com/hashicorp/vault/sdk/helper/consts"
"github.com/hashicorp/vault/sdk/helper/jsonutil"
"github.com/hashicorp/vault/sdk/helper/pluginutil"
"github.com/hashicorp/vault/sdk/logical"
"github.com/hashicorp/vault/vault/observations"
"github.com/hashicorp/vault/vault/plugincatalog"
@ -353,6 +352,7 @@ type MountEntry struct {
// MountConfig is used to hold settable options
type MountConfig struct {
EntMountConfig `mapstructure:",squash"`
DefaultLeaseTTL time.Duration `json:"default_lease_ttl,omitempty" structs:"default_lease_ttl" mapstructure:"default_lease_ttl"` // Override for global default
MaxLeaseTTL time.Duration `json:"max_lease_ttl,omitempty" structs:"max_lease_ttl" mapstructure:"max_lease_ttl"` // Override for global default
ForceNoCache bool `json:"force_no_cache,omitempty" structs:"force_no_cache" mapstructure:"force_no_cache"` // Override for global default
@ -394,6 +394,7 @@ type APIUserLockoutConfig struct {
// APIMountConfig is an embedded struct of api.MountConfigInput
type APIMountConfig struct {
EntAPIMountConfig `mapstructure:",squash"`
DefaultLeaseTTL string `json:"default_lease_ttl" structs:"default_lease_ttl" mapstructure:"default_lease_ttl"`
MaxLeaseTTL string `json:"max_lease_ttl" structs:"max_lease_ttl" mapstructure:"max_lease_ttl"`
ForceNoCache bool `json:"force_no_cache" structs:"force_no_cache" mapstructure:"force_no_cache"`
@ -1842,23 +1843,6 @@ func (c *Core) newLogicalBackend(ctx context.Context, entry *MountEntry, sysView
return backend, nil
}
// resolveMountEntryVersion allows entry.Version to be overridden if there is a
// corresponding pinned version.
func (c *Core) resolveMountEntryVersion(ctx context.Context, pluginType consts.PluginType, entry *MountEntry) (string, error) {
pluginName := entry.Type
if alias, ok := mountAliases[pluginName]; ok {
pluginName = alias
}
pinnedVersion, err := c.pluginCatalog.GetPinnedVersion(ctx, pluginType, pluginName)
if err != nil && !errors.Is(err, pluginutil.ErrPinnedVersionNotFound) {
return "", err
}
if pinnedVersion != nil {
return pinnedVersion.Version, nil
}
return entry.Version, nil
}
// defaultMountTable creates a default mount table
func (c *Core) defaultMountTable() *MountTable {
table := &MountTable{
@ -2015,7 +1999,7 @@ func (c *Core) singletonMountTables() (mounts, auth *MountTable) {
}
c.authLock.RUnlock()
return
return mounts, auth
}
func (c *Core) setCoreBackend(entry *MountEntry, backend logical.Backend, view *BarrierView) {

View file

@ -1,17 +1,40 @@
// Copyright IBM Corp. 2016, 2025
// SPDX-License-Identifier: MPL-2.0
// go:build !enterprise
//go:build !enterprise
package vault
import (
"context"
"errors"
"github.com/hashicorp/vault/sdk/helper/consts"
"github.com/hashicorp/vault/sdk/helper/pluginutil"
)
type EntMountConfig struct{}
type EntAPIMountConfig struct{}
func entExtractVerifyPlugin(context.Context, *pluginutil.PluginRunner) error {
// Do nothing in OSS
return nil
}
// resolveMountEntryVersion allows entry.Version to be overridden if there is a
// corresponding pinned version.
func (c *Core) resolveMountEntryVersion(ctx context.Context, pluginType consts.PluginType, entry *MountEntry) (string, error) {
pluginName := entry.Type
if alias, ok := mountAliases[pluginName]; ok {
pluginName = alias
}
pinnedVersion, err := c.pluginCatalog.GetPinnedVersion(ctx, pluginType, pluginName)
if err != nil && !errors.Is(err, pluginutil.ErrPinnedVersionNotFound) {
return "", err
}
if pinnedVersion != nil {
return pinnedVersion.Version, nil
}
return entry.Version, nil
}