diff --git a/api/sys_mounts.go b/api/sys_mounts.go index e10ad12575..39d37ac57f 100644 --- a/api/sys_mounts.go +++ b/api/sys_mounts.go @@ -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"` diff --git a/changelog/_9719.txt b/changelog/_9719.txt new file mode 100644 index 0000000000..cb18ce601b --- /dev/null +++ b/changelog/_9719.txt @@ -0,0 +1,3 @@ +```release-note:feature +**Plugins (Enterprise)**: Allow overriding pinned version when enabling and tuning auth and secrets backends +``` \ No newline at end of file diff --git a/command/auth_enable.go b/command/auth_enable.go index 57edf73363..964d512299 100644 --- a/command/auth_enable.go +++ b/command/auth_enable.go @@ -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 } diff --git a/command/auth_tune.go b/command/auth_tune.go index 77a32f493b..63f834034b 100644 --- a/command/auth_tune.go +++ b/command/auth_tune.go @@ -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 } diff --git a/command/commands.go b/command/commands.go index 75c8170f0f..8a8c6ac446 100644 --- a/command/commands.go +++ b/command/commands.go @@ -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 diff --git a/command/plugin_test.go b/command/plugin_test.go index 97eeea8325..6f4ff8ba78 100644 --- a/command/plugin_test.go +++ b/command/plugin_test.go @@ -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) + } +} diff --git a/command/secrets_enable.go b/command/secrets_enable.go index 55eb63dd4a..f44fbe95b1 100644 --- a/command/secrets_enable.go +++ b/command/secrets_enable.go @@ -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 } diff --git a/command/secrets_tune.go b/command/secrets_tune.go index bcce9338da..f5bf18d645 100644 --- a/command/secrets_tune.go +++ b/command/secrets_tune.go @@ -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 } diff --git a/vault/logical_system.go b/vault/logical_system.go index ba83f9e9be..2707c83120 100644 --- a/vault/logical_system.go +++ b/vault/logical_system.go @@ -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) diff --git a/vault/logical_system_fields.go b/vault/logical_system_fields.go new file mode 100644 index 0000000000..1dfd2855d0 --- /dev/null +++ b/vault/logical_system_fields.go @@ -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 +} diff --git a/vault/logical_system_fields_stubs_oss.go b/vault/logical_system_fields_stubs_oss.go new file mode 100644 index 0000000000..ec3cd9f10f --- /dev/null +++ b/vault/logical_system_fields_stubs_oss.go @@ -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 +} diff --git a/vault/logical_system_paths.go b/vault/logical_system_paths.go index 5c26af9fa2..592ce7c0b5 100644 --- a/vault/logical_system_paths.go +++ b/vault/logical_system_paths.go @@ -11,6 +11,34 @@ import ( "github.com/hashicorp/vault/sdk/logical" ) +const ( + // Auth paths patterns + patternAuth = "auth$" + patternAuthTune = "auth/(?P.+?)/tune$" + patternAuthPath = "auth/(?P.+)" + + // Mount paths patterns + patternMountsTune = "mounts/(?P.+?)/tune$" + patternMountsAuthTune = "mounts/auth/(?P.+?)/tune$" + patternMountsPath = "mounts/(?P.+?)" + 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.+?)/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.+)", + 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.+?)/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.+?)/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.+?)", + 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", diff --git a/vault/logical_system_paths_stubs_oss.go b/vault/logical_system_paths_stubs_oss.go new file mode 100644 index 0000000000..20b4169f56 --- /dev/null +++ b/vault/logical_system_paths_stubs_oss.go @@ -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() +} diff --git a/vault/logical_system_stubs_oss.go b/vault/logical_system_stubs_oss.go index c130c8b755..e840449d33 100644 --- a/vault/logical_system_stubs_oss.go +++ b/vault/logical_system_stubs_oss.go @@ -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 } diff --git a/vault/mount.go b/vault/mount.go index b7ac1fd8af..87292546bc 100644 --- a/vault/mount.go +++ b/vault/mount.go @@ -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) { diff --git a/vault/mount_stubs_oss.go b/vault/mount_stubs_oss.go index 7b1ca0b147..7d987bb382 100644 --- a/vault/mount_stubs_oss.go +++ b/vault/mount_stubs_oss.go @@ -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 +}