VAULT-20476: vault.NewCore refactor. (#23644) (#23659)

* NewCore tech debt refactoring

* addExtraCredentialBackends

* singletonMounts => mountTypeToken instead of 'token'

* NewCore tests support ent backend addition

* PR feedback

* reorder method calls

* mounthPath___ standardization

* Try to be more explicit about the min number of backends

* Include cluster listener

* explicit declaration of events before assignment

* Removed nil checking

* resolve conflicts

Co-authored-by: Peter Wilson <peter.wilson@hashicorp.com>
This commit is contained in:
hc-github-team-secure-vault-core 2023-10-16 07:38:11 -04:00 committed by GitHub
parent cfdc96981f
commit 325e822e8a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 507 additions and 132 deletions

View File

@ -116,7 +116,7 @@ func (c *Core) enableCredentialInternal(ctx context.Context, entry *MountEntry,
} }
// Ensure the token backend is a singleton // Ensure the token backend is a singleton
if entry.Type == "token" { if entry.Type == mountTypeToken {
return fmt.Errorf("token credential backend cannot be instantiated") return fmt.Errorf("token credential backend cannot be instantiated")
} }
@ -883,7 +883,7 @@ func (c *Core) setupCredentials(ctx context.Context) error {
} }
// Check if this is the token store // Check if this is the token store
if entry.Type == "token" { if entry.Type == mountTypeToken {
c.tokenStore = backend.(*TokenStore) c.tokenStore = backend.(*TokenStore)
// At some point when this isn't beta we may persist this but for // At some point when this isn't beta we may persist this but for
@ -893,7 +893,7 @@ func (c *Core) setupCredentials(ctx context.Context) error {
// this is loaded *after* the normal mounts, including cubbyhole // this is loaded *after* the normal mounts, including cubbyhole
c.router.tokenStoreSaltFunc = c.tokenStore.Salt c.router.tokenStoreSaltFunc = c.tokenStore.Salt
if !c.IsDRSecondary() { if !c.IsDRSecondary() {
c.tokenStore.cubbyholeBackend = c.router.MatchingBackend(ctx, cubbyholeMountPath).(*CubbyholeBackend) c.tokenStore.cubbyholeBackend = c.router.MatchingBackend(ctx, mountPathCubbyhole).(*CubbyholeBackend)
} }
} }
@ -1048,7 +1048,7 @@ func (c *Core) defaultAuthTable() *MountTable {
tokenAuth := &MountEntry{ tokenAuth := &MountEntry{
Table: credentialTableType, Table: credentialTableType,
Path: "token/", Path: "token/",
Type: "token", Type: mountTypeToken,
Description: "token based credentials", Description: "token based credentials",
UUID: tokenUUID, UUID: tokenUUID,
Accessor: tokenAccessor, Accessor: tokenAccessor,

View File

@ -125,6 +125,15 @@ const (
// undoLogsAreSafeStoragePath is a storage path that we write once we know undo logs are // undoLogsAreSafeStoragePath is a storage path that we write once we know undo logs are
// safe, so we don't have to keep checking all the time. // safe, so we don't have to keep checking all the time.
undoLogsAreSafeStoragePath = "core/raft/undo_logs_are_safe" undoLogsAreSafeStoragePath = "core/raft/undo_logs_are_safe"
ErrMlockFailedTemplate = "Failed to lock memory: %v\n\n" +
"This usually means that the mlock syscall is not available.\n" +
"Vault uses mlock to prevent memory from being swapped to\n" +
"disk. This requires root privileges as well as a machine\n" +
"that supports mlock. Please enable mlock on your system or\n" +
"disable Vault from using it. To disable Vault from using it,\n" +
"set the `disable_mlock` configuration option in your configuration\n" +
"file."
) )
var ( var (
@ -1126,30 +1135,27 @@ func CreateCore(conf *CoreConfig) (*Core, error) {
return c, nil return c, nil
} }
// NewCore is used to construct a new core // NewCore creates, initializes and configures a Vault node (core).
func NewCore(conf *CoreConfig) (*Core, error) { func NewCore(conf *CoreConfig) (*Core, error) {
var err error // NOTE: The order of configuration of the core has some importance, as we can
// make use of an early return if we are running this new core in recovery mode.
c, err := CreateCore(conf) c, err := CreateCore(conf)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if err = coreInit(c, conf); err != nil {
err = coreInit(c, conf)
if err != nil {
return nil, err return nil, err
} }
if !conf.DisableMlock { switch {
// Ensure our memory usage is locked into physical RAM case conf.DisableMlock:
if err := mlock.LockMemory(); err != nil { // User configured that memory lock should be disabled on unix systems.
return nil, fmt.Errorf( default:
"Failed to lock memory: %v\n\n"+ err = mlock.LockMemory()
"This usually means that the mlock syscall is not available.\n"+ if err != nil {
"Vault uses mlock to prevent memory from being swapped to\n"+ return nil, fmt.Errorf(ErrMlockFailedTemplate, err)
"disk. This requires root privileges as well as a machine\n"+
"that supports mlock. Please enable mlock on your system or\n"+
"disable Vault from using it. To disable Vault from using it,\n"+
"set the `disable_mlock` configuration option in your configuration\n"+
"file.",
err)
} }
} }
@ -1159,9 +1165,11 @@ func NewCore(conf *CoreConfig) (*Core, error) {
return nil, fmt.Errorf("barrier setup failed: %w", err) return nil, fmt.Errorf("barrier setup failed: %w", err)
} }
if err := storedLicenseCheck(c, conf); err != nil { err = storedLicenseCheck(c, conf)
if err != nil {
return nil, err return nil, err
} }
// We create the funcs here, then populate the given config with it so that // We create the funcs here, then populate the given config with it so that
// the caller can share state // the caller can share state
conf.ReloadFuncsLock = &c.reloadFuncsLock conf.ReloadFuncsLock = &c.reloadFuncsLock
@ -1171,12 +1179,12 @@ func NewCore(conf *CoreConfig) (*Core, error) {
conf.ReloadFuncs = &c.reloadFuncs conf.ReloadFuncs = &c.reloadFuncs
c.rollbackPeriod = conf.RollbackPeriod c.rollbackPeriod = conf.RollbackPeriod
if conf.RollbackPeriod == 0 { if c.rollbackPeriod == 0 {
c.rollbackPeriod = time.Minute // Default to 1 minute
c.rollbackPeriod = 1 * time.Minute
} }
// All the things happening below this are not required in // For recovery mode we've now configured enough to return early.
// recovery mode
if c.recoveryMode { if c.recoveryMode {
return c, nil return c, nil
} }
@ -1195,81 +1203,39 @@ func NewCore(conf *CoreConfig) (*Core, error) {
c.pluginFilePermissions = conf.PluginFilePermissions c.pluginFilePermissions = conf.PluginFilePermissions
} }
createSecondaries(c, conf) // Create secondaries (this will only impact Enterprise versions of Vault)
c.createSecondaries(conf.Logger)
if conf.HAPhysical != nil && conf.HAPhysical.HAEnabled() { if conf.HAPhysical != nil && conf.HAPhysical.HAEnabled() {
c.ha = conf.HAPhysical c.ha = conf.HAPhysical
} }
// MFA method
c.loginMFABackend = NewLoginMFABackend(c, conf.Logger) c.loginMFABackend = NewLoginMFABackend(c, conf.Logger)
logicalBackends := make(map[string]logical.Factory) // Logical backends
for k, f := range conf.LogicalBackends { c.configureLogicalBackends(conf.LogicalBackends, conf.Logger, conf.AdministrativeNamespacePath)
logicalBackends[k] = f
}
_, ok := logicalBackends["kv"]
if !ok {
logicalBackends["kv"] = PassthroughBackendFactory
}
logicalBackends["cubbyhole"] = CubbyholeBackendFactory // Credentials backends
logicalBackends[systemMountType] = func(ctx context.Context, config *logical.BackendConfig) (logical.Backend, error) { c.configureCredentialsBackends(conf.CredentialBackends, conf.Logger)
sysBackendLogger := conf.Logger.Named("system")
b := NewSystemBackend(c, sysBackendLogger)
if err := b.Setup(ctx, config); err != nil {
return nil, err
}
return b, nil
}
logicalBackends["identity"] = func(ctx context.Context, config *logical.BackendConfig) (logical.Backend, error) {
identityLogger := conf.Logger.Named("identity")
return NewIdentityStore(ctx, c, config, identityLogger)
}
addExtraLogicalBackends(c, logicalBackends, conf.AdministrativeNamespacePath)
c.logicalBackends = logicalBackends
credentialBackends := make(map[string]logical.Factory) // Audit backends
for k, f := range conf.CredentialBackends { c.configureAuditBackends(conf.AuditBackends)
credentialBackends[k] = f
}
credentialBackends["token"] = func(ctx context.Context, config *logical.BackendConfig) (logical.Backend, error) {
tsLogger := conf.Logger.Named("token")
return NewTokenStore(ctx, tsLogger, c, config)
}
addExtraCredentialBackends(c, credentialBackends)
c.credentialBackends = credentialBackends
auditBackends := make(map[string]audit.Factory)
for k, f := range conf.AuditBackends {
auditBackends[k] = f
}
c.auditBackends = auditBackends
// UI
uiStoragePrefix := systemBarrierPrefix + "ui" uiStoragePrefix := systemBarrierPrefix + "ui"
c.uiConfig = NewUIConfig(conf.EnableUI, physical.NewView(c.physical, uiStoragePrefix), NewBarrierView(c.barrier, uiStoragePrefix)) c.uiConfig = NewUIConfig(conf.EnableUI, physical.NewView(c.physical, uiStoragePrefix), NewBarrierView(c.barrier, uiStoragePrefix))
c.clusterListener.Store((*cluster.Listener)(nil)) // Listeners
err = c.configureListeners(conf)
// for listeners with custom response headers, configuring customListenerHeader
if conf.RawConfig.Listeners != nil {
uiHeaders, err := c.UIHeaders()
if err != nil { if err != nil {
return nil, err return nil, err
} }
c.customListenerHeader.Store(NewListenerCustomHeader(conf.RawConfig.Listeners, c.logger, uiHeaders))
} else {
c.customListenerHeader.Store(([]*ListenerCustomHeaders)(nil))
}
logRequestsLevel := conf.RawConfig.LogRequestsLevel // Log level
c.logRequestsLevel = uberAtomic.NewInt32(0) c.configureLogRequestLevel(conf.RawConfig.LogLevel)
switch {
case log.LevelFromString(logRequestsLevel) > log.NoLevel && log.LevelFromString(logRequestsLevel) < log.Off:
c.logRequestsLevel.Store(int32(log.LevelFromString(logRequestsLevel)))
case logRequestsLevel != "":
c.logger.Warn("invalid log_requests_level", "level", conf.RawConfig.LogRequestsLevel)
}
// Quotas
quotasLogger := conf.Logger.Named("quotas") quotasLogger := conf.Logger.Named("quotas")
c.quotaManager, err = quotas.NewManager(quotasLogger, c.quotaLeaseWalker, c.metricSink) c.quotaManager, err = quotas.NewManager(quotasLogger, c.quotaLeaseWalker, c.metricSink)
if err != nil { if err != nil {
@ -1281,14 +1247,14 @@ func NewCore(conf *CoreConfig) (*Core, error) {
return nil, err return nil, err
} }
// Version history
if c.versionHistory == nil { if c.versionHistory == nil {
c.logger.Info("Initializing version history cache for core") c.logger.Info("Initializing version history cache for core")
c.versionHistory = make(map[string]VaultVersion) c.versionHistory = make(map[string]VaultVersion)
} }
// start the event system // Events
eventsLogger := conf.Logger.Named("events") events, err := eventbus.NewEventBus(conf.Logger.Named("events"))
events, err := eventbus.NewEventBus(eventsLogger)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -1301,9 +1267,110 @@ func NewCore(conf *CoreConfig) (*Core, error) {
// yet registered core to the server command's SubloggerAdder, so any new // yet registered core to the server command's SubloggerAdder, so any new
// subloggers will be in conf.AllLoggers. // subloggers will be in conf.AllLoggers.
c.allLoggers = conf.AllLoggers c.allLoggers = conf.AllLoggers
return c, nil return c, nil
} }
// configureListeners configures the Core with the listeners from the CoreConfig.
func (c *Core) configureListeners(conf *CoreConfig) error {
c.clusterListener.Store((*cluster.Listener)(nil))
if conf.RawConfig.Listeners == nil {
c.customListenerHeader.Store(([]*ListenerCustomHeaders)(nil))
return nil
}
uiHeaders, err := c.UIHeaders()
if err != nil {
return err
}
c.customListenerHeader.Store(NewListenerCustomHeader(conf.RawConfig.Listeners, c.logger, uiHeaders))
return nil
}
// configureLogRequestLevel configures the Core with the supplied log level.
func (c *Core) configureLogRequestLevel(level string) {
c.logRequestsLevel = uberAtomic.NewInt32(0)
lvl := log.LevelFromString(level)
switch {
case lvl > log.NoLevel && lvl < log.Off:
c.logRequestsLevel.Store(int32(lvl))
case level != "":
c.logger.Warn("invalid log_requests_level", "level", level)
}
}
// configureAuditBackends configures the Core with the ability to create audit
// backends for various types.
func (c *Core) configureAuditBackends(backends map[string]audit.Factory) {
auditBackends := make(map[string]audit.Factory, len(backends))
for k, f := range backends {
auditBackends[k] = f
}
c.auditBackends = auditBackends
}
// configureCredentialsBackends configures the Core with the ability to create
// credential backends for various types.
func (c *Core) configureCredentialsBackends(backends map[string]logical.Factory, logger log.Logger) {
credentialBackends := make(map[string]logical.Factory, len(backends))
for k, f := range backends {
credentialBackends[k] = f
}
credentialBackends[mountTypeToken] = func(ctx context.Context, config *logical.BackendConfig) (logical.Backend, error) {
return NewTokenStore(ctx, logger.Named("token"), c, config)
}
c.credentialBackends = credentialBackends
c.addExtraCredentialBackends()
}
// configureLogicalBackends configures the Core with the ability to create
// logical backends for various types.
func (c *Core) configureLogicalBackends(backends map[string]logical.Factory, logger log.Logger, adminNamespacePath string) {
logicalBackends := make(map[string]logical.Factory, len(backends))
for k, f := range backends {
logicalBackends[k] = f
}
// KV
_, ok := logicalBackends[mountTypeKV]
if !ok {
logicalBackends[mountTypeKV] = PassthroughBackendFactory
}
// Cubbyhole
logicalBackends[mountTypeCubbyhole] = CubbyholeBackendFactory
// System
logicalBackends[mountTypeSystem] = func(ctx context.Context, config *logical.BackendConfig) (logical.Backend, error) {
b := NewSystemBackend(c, logger.Named("system"))
if err := b.Setup(ctx, config); err != nil {
return nil, err
}
return b, nil
}
// Identity
logicalBackends[mountTypeIdentity] = func(ctx context.Context, config *logical.BackendConfig) (logical.Backend, error) {
return NewIdentityStore(ctx, c, config, logger.Named("identity"))
}
c.logicalBackends = logicalBackends
c.addExtraLogicalBackends(adminNamespacePath)
}
// handleVersionTimeStamps stores the current version at the current time to // handleVersionTimeStamps stores the current version at the current time to
// storage, and then loads all versions and upgrade timestamps out from storage. // storage, and then loads all versions and upgrade timestamps out from storage.
func (c *Core) handleVersionTimeStamps(ctx context.Context) error { func (c *Core) handleVersionTimeStamps(ctx context.Context) error {

View File

@ -13,6 +13,19 @@ import (
"testing" "testing"
"time" "time"
"github.com/hashicorp/vault/command/server"
logicalKv "github.com/hashicorp/vault-plugin-secrets-kv"
logicalDb "github.com/hashicorp/vault/builtin/logical/database"
"github.com/hashicorp/vault/builtin/plugin"
"github.com/hashicorp/vault/builtin/audit/syslog"
"github.com/hashicorp/vault/builtin/audit/file"
"github.com/hashicorp/vault/builtin/audit/socket"
"github.com/stretchr/testify/require"
"github.com/go-test/deep" "github.com/go-test/deep"
"github.com/hashicorp/errwrap" "github.com/hashicorp/errwrap"
log "github.com/hashicorp/go-hclog" log "github.com/hashicorp/go-hclog"
@ -35,6 +48,297 @@ import (
// invalidKey is used to test Unseal // invalidKey is used to test Unseal
var invalidKey = []byte("abcdefghijklmnopqrstuvwxyz")[:17] var invalidKey = []byte("abcdefghijklmnopqrstuvwxyz")[:17]
// TestNewCore_configureAuditBackends ensures that we are able to configure the
// supplied audit backends when getting a NewCore.
func TestNewCore_configureAuditBackends(t *testing.T) {
t.Parallel()
tests := map[string]struct {
backends map[string]audit.Factory
}{
"none": {
backends: nil,
},
"file": {
backends: map[string]audit.Factory{
"file": file.Factory,
},
},
"socket": {
backends: map[string]audit.Factory{
"socket": socket.Factory,
},
},
"syslog": {
backends: map[string]audit.Factory{
"syslog": syslog.Factory,
},
},
"all": {
backends: map[string]audit.Factory{
"file": file.Factory,
"socket": socket.Factory,
"syslog": syslog.Factory,
},
},
}
for name, tc := range tests {
name := name
tc := tc
t.Run(name, func(t *testing.T) {
t.Parallel()
core := &Core{}
require.Len(t, core.auditBackends, 0)
core.configureAuditBackends(tc.backends)
require.Len(t, core.auditBackends, len(tc.backends))
for k := range tc.backends {
require.Contains(t, core.auditBackends, k)
}
})
}
}
// TestNewCore_configureCredentialsBackends ensures that we are able to configure the
// supplied credential backends, in addition to defaults, when getting a NewCore.
func TestNewCore_configureCredentialsBackends(t *testing.T) {
t.Parallel()
tests := map[string]struct {
backends map[string]logical.Factory
}{
"none": {
backends: nil,
},
"plugin": {
backends: map[string]logical.Factory{
"plugin": plugin.Factory,
},
},
}
for name, tc := range tests {
name := name
tc := tc
t.Run(name, func(t *testing.T) {
t.Parallel()
core := &Core{}
require.Len(t, core.credentialBackends, 0)
core.configureCredentialsBackends(tc.backends, corehelpers.NewTestLogger(t))
require.GreaterOrEqual(t, len(core.credentialBackends), len(tc.backends)+1) // token + ent
for k := range tc.backends {
require.Contains(t, core.credentialBackends, k)
}
})
}
}
// TestNewCore_configureLogicalBackends ensures that we are able to configure the
// supplied logical backends, in addition to defaults, when getting a NewCore.
func TestNewCore_configureLogicalBackends(t *testing.T) {
t.Parallel()
// configureLogicalBackends will add some default backends for us:
// cubbyhole
// identity
// kv
// system
// In addition Enterprise versions of Vault may add additional engines.
tests := map[string]struct {
backends map[string]logical.Factory
adminNamespacePath string
expectedNonEntBackends int
}{
"none": {
backends: nil,
expectedNonEntBackends: 0,
},
"database": {
backends: map[string]logical.Factory{
"database": logicalDb.Factory,
},
adminNamespacePath: "foo",
expectedNonEntBackends: 5, // database + defaults
},
"kv": {
backends: map[string]logical.Factory{
"kv": logicalKv.Factory,
},
adminNamespacePath: "foo",
expectedNonEntBackends: 4, // kv + defaults (kv is a default)
},
"plugin": {
backends: map[string]logical.Factory{
"plugin": plugin.Factory,
},
adminNamespacePath: "foo",
expectedNonEntBackends: 5, // plugin + defaults
},
"all": {
backends: map[string]logical.Factory{
"database": logicalDb.Factory,
"kv": logicalKv.Factory,
"plugin": plugin.Factory,
},
adminNamespacePath: "foo",
expectedNonEntBackends: 6, // database, plugin + defaults
},
}
for name, tc := range tests {
name := name
tc := tc
t.Run(name, func(t *testing.T) {
t.Parallel()
core := &Core{}
require.Len(t, core.logicalBackends, 0)
core.configureLogicalBackends(tc.backends, corehelpers.NewTestLogger(t), tc.adminNamespacePath)
require.GreaterOrEqual(t, len(core.logicalBackends), tc.expectedNonEntBackends)
require.Contains(t, core.logicalBackends, mountTypeKV)
require.Contains(t, core.logicalBackends, mountTypeCubbyhole)
require.Contains(t, core.logicalBackends, mountTypeSystem)
require.Contains(t, core.logicalBackends, mountTypeIdentity)
for k := range tc.backends {
require.Contains(t, core.logicalBackends, k)
}
})
}
}
// TestNewCore_configureLogRequestLevel ensures that we are able to configure the
// supplied logging level when getting a NewCore.
func TestNewCore_configureLogRequestLevel(t *testing.T) {
t.Parallel()
tests := map[string]struct {
level string
expectedLevel log.Level
}{
"none": {
level: "",
expectedLevel: log.NoLevel,
},
"trace": {
level: "trace",
expectedLevel: log.Trace,
},
"debug": {
level: "debug",
expectedLevel: log.Debug,
},
"info": {
level: "info",
expectedLevel: log.Info,
},
"warn": {
level: "warn",
expectedLevel: log.Warn,
},
"error": {
level: "error",
expectedLevel: log.Error,
},
"bad": {
level: "foo",
expectedLevel: log.NoLevel,
},
}
for name, tc := range tests {
name := name
tc := tc
t.Run(name, func(t *testing.T) {
t.Parallel()
// We need to supply a logger, as configureLogRequestLevel emits
// warnings to the logs in certain circumstances.
core := &Core{
logger: corehelpers.NewTestLogger(t),
}
core.configureLogRequestLevel(tc.level)
require.Equal(t, tc.expectedLevel, log.Level(core.logRequestsLevel.Load()))
})
}
}
// TestNewCore_configureListeners tests that we are able to configure listeners
// on a NewCore via config.
func TestNewCore_configureListeners(t *testing.T) {
// We would usually expect CoreConfig to come from server.NewConfig().
// However, we want to fiddle to give us some granular control over the config.
tests := map[string]struct {
config *CoreConfig
expectedListeners []*ListenerCustomHeaders
}{
"nil-listeners": {
config: &CoreConfig{
RawConfig: &server.Config{
SharedConfig: &configutil.SharedConfig{},
},
},
expectedListeners: nil,
},
"listeners-empty": {
config: &CoreConfig{
RawConfig: &server.Config{
SharedConfig: &configutil.SharedConfig{
Listeners: []*configutil.Listener{},
},
},
},
expectedListeners: nil,
},
"listeners-some": {
config: &CoreConfig{
RawConfig: &server.Config{
SharedConfig: &configutil.SharedConfig{
Listeners: []*configutil.Listener{
{Address: "foo"},
},
},
},
},
expectedListeners: []*ListenerCustomHeaders{
{Address: "foo"},
},
},
}
for name, tc := range tests {
name := name
tc := tc
t.Run(name, func(t *testing.T) {
t.Parallel()
// We need to init some values ourselves, usually CreateCore does this for us.
logger := corehelpers.NewTestLogger(t)
backend, err := inmem.NewInmem(nil, logger)
require.NoError(t, err)
storage := &logical.InmemStorage{}
core := &Core{
clusterListener: new(atomic.Value),
customListenerHeader: new(atomic.Value),
uiConfig: NewUIConfig(false, backend, storage),
}
err = core.configureListeners(tc.config)
require.NoError(t, err)
switch tc.expectedListeners {
case nil:
require.Nil(t, core.customListenerHeader.Load())
default:
for i, v := range core.customListenerHeader.Load().([]*ListenerCustomHeaders) {
require.Equal(t, v.Address, tc.config.RawConfig.Listeners[i].Address)
}
}
})
}
}
func TestNewCore_badRedirectAddr(t *testing.T) { func TestNewCore_badRedirectAddr(t *testing.T) {
logger = logging.NewVaultLogger(log.Trace) logger = logging.NewVaultLogger(log.Trace)

View File

@ -78,11 +78,11 @@ func (c *Core) EnableUndoLogs() {}
func (c *Core) PersistUndoLogs() error { return nil } func (c *Core) PersistUndoLogs() error { return nil }
func (c *Core) teardownReplicationResolverHandler() {} func (c *Core) teardownReplicationResolverHandler() {}
func createSecondaries(*Core, *CoreConfig) {} func (c *Core) createSecondaries(_ hclog.Logger) {}
func addExtraLogicalBackends(*Core, map[string]logical.Factory, string) {} func (c *Core) addExtraLogicalBackends(_ string) {}
func addExtraCredentialBackends(*Core, map[string]logical.Factory) {} func (c *Core) addExtraCredentialBackends() {}
func preUnsealInternal(context.Context, *Core) error { return nil } func preUnsealInternal(context.Context, *Core) error { return nil }

View File

@ -2032,7 +2032,7 @@ func (b *SystemBackend) handleTuneWriteCommon(ctx context.Context, path string,
if !strings.HasPrefix(path, "auth/") { if !strings.HasPrefix(path, "auth/") {
return logical.ErrorResponse(fmt.Sprintf("'token_type' can only be modified on auth mounts")), logical.ErrInvalidRequest return logical.ErrorResponse(fmt.Sprintf("'token_type' can only be modified on auth mounts")), logical.ErrInvalidRequest
} }
if mountEntry.Type == "token" || mountEntry.Type == "ns_token" { if mountEntry.Type == mountTypeToken || mountEntry.Type == mountTypeNSToken {
return logical.ErrorResponse(fmt.Sprintf("'token_type' cannot be set for 'token' or 'ns_token' auth mounts")), logical.ErrInvalidRequest return logical.ErrorResponse(fmt.Sprintf("'token_type' cannot be set for 'token' or 'ns_token' auth mounts")), logical.ErrInvalidRequest
} }

View File

@ -62,15 +62,19 @@ const (
// ListingVisibilityUnauth is the unauth type for listing visibility // ListingVisibilityUnauth is the unauth type for listing visibility
ListingVisibilityUnauth ListingVisibilityType = "unauth" ListingVisibilityUnauth ListingVisibilityType = "unauth"
systemMountPath = "sys/" mountPathSystem = "sys/"
identityMountPath = "identity/" mountPathIdentity = "identity/"
cubbyholeMountPath = "cubbyhole/" mountPathCubbyhole = "cubbyhole/"
systemMountType = "system" mountTypeSystem = "system"
identityMountType = "identity" mountTypeNSSystem = "ns_system"
cubbyholeMountType = "cubbyhole" mountTypeIdentity = "identity"
pluginMountType = "plugin" mountTypeCubbyhole = "cubbyhole"
mountTypePlugin = "plugin"
mountTypeKV = "kv"
mountTypeNSCubbyhole = "ns_cubbyhole" mountTypeNSCubbyhole = "ns_cubbyhole"
mountTypeToken = "token"
mountTypeNSToken = "ns_token"
MountTableUpdateStorage = true MountTableUpdateStorage = true
MountTableNoUpdateStorage = false MountTableNoUpdateStorage = false
@ -91,25 +95,25 @@ var (
protectedMounts = []string{ protectedMounts = []string{
"audit/", "audit/",
"auth/", "auth/",
systemMountPath, mountPathSystem,
cubbyholeMountPath, mountPathCubbyhole,
identityMountPath, mountPathIdentity,
} }
untunableMounts = []string{ untunableMounts = []string{
cubbyholeMountPath, mountPathCubbyhole,
systemMountPath, mountPathSystem,
"audit/", "audit/",
identityMountPath, mountPathIdentity,
} }
// singletonMounts can only exist in one location and are // singletonMounts can only exist in one location and are
// loaded by default. These are types, not paths. // loaded by default. These are types, not paths.
singletonMounts = []string{ singletonMounts = []string{
cubbyholeMountType, mountTypeCubbyhole,
systemMountType, mountTypeSystem,
"token", mountTypeToken,
identityMountType, mountTypeIdentity,
} }
// mountAliases maps old backend names to new backend names, allowing us // mountAliases maps old backend names to new backend names, allowing us
@ -430,7 +434,7 @@ func (e *MountEntry) IsExternalPlugin() bool {
// MountClass returns the mount class based on Accessor and Path // MountClass returns the mount class based on Accessor and Path
func (e *MountEntry) MountClass() string { func (e *MountEntry) MountClass() string {
if e.Accessor == "" || strings.HasPrefix(e.Path, fmt.Sprintf("%s/", systemMountPath)) { if e.Accessor == "" || strings.HasPrefix(e.Path, fmt.Sprintf("%s/", mountPathSystem)) {
return "" return ""
} }
@ -694,7 +698,7 @@ func (c *Core) mountInternal(ctx context.Context, entry *MountEntry, updateStora
// Check for the correct backend type // Check for the correct backend type
backendType := backend.Type() backendType := backend.Type()
if backendType != logical.TypeLogical { if backendType != logical.TypeLogical {
if entry.Type != "kv" && entry.Type != "system" && entry.Type != "cubbyhole" { if entry.Type != mountTypeKV && entry.Type != mountTypeSystem && entry.Type != mountTypeCubbyhole {
return fmt.Errorf(`unknown backend type: "%s"`, entry.Type) return fmt.Errorf(`unknown backend type: "%s"`, entry.Type)
} }
} }
@ -1336,7 +1340,7 @@ func (c *Core) runMountUpdates(ctx context.Context, needPersist bool) error {
entry.Local = true entry.Local = true
needPersist = true needPersist = true
} }
if entry.Type == cubbyholeMountType && !entry.Local { if entry.Type == mountTypeCubbyhole && !entry.Local {
entry.Local = true entry.Local = true
needPersist = true needPersist = true
} }
@ -1563,7 +1567,7 @@ func (c *Core) setupMounts(ctx context.Context) error {
backendType := backend.Type() backendType := backend.Type()
if backendType != logical.TypeLogical { if backendType != logical.TypeLogical {
if entry.Type != "kv" && entry.Type != "system" && entry.Type != "cubbyhole" { if entry.Type != mountTypeKV && entry.Type != mountTypeSystem && entry.Type != mountTypeCubbyhole {
return fmt.Errorf(`unknown backend type: "%s"`, entry.Type) return fmt.Errorf(`unknown backend type: "%s"`, entry.Type)
} }
} }
@ -1692,7 +1696,7 @@ func (c *Core) newLogicalBackend(ctx context.Context, entry *MountEntry, sysView
} }
switch { switch {
case entry.Type == "plugin": case entry.Type == mountTypePlugin:
conf["plugin_name"] = entry.Config.PluginName conf["plugin_name"] = entry.Config.PluginName
default: default:
conf["plugin_name"] = t conf["plugin_name"] = t
@ -1750,7 +1754,7 @@ func (c *Core) defaultMountTable() *MountTable {
if err != nil { if err != nil {
panic(fmt.Sprintf("could not create default secret mount UUID: %v", err)) panic(fmt.Sprintf("could not create default secret mount UUID: %v", err))
} }
mountAccessor, err := c.generateMountAccessor("kv") mountAccessor, err := c.generateMountAccessor(mountTypeKV)
if err != nil { if err != nil {
panic(fmt.Sprintf("could not generate default secret mount accessor: %v", err)) panic(fmt.Sprintf("could not generate default secret mount accessor: %v", err))
} }
@ -1762,7 +1766,7 @@ func (c *Core) defaultMountTable() *MountTable {
kvMount := &MountEntry{ kvMount := &MountEntry{
Table: mountTableType, Table: mountTableType,
Path: "secret/", Path: "secret/",
Type: "kv", Type: mountTypeKV,
Description: "key/value secret storage", Description: "key/value secret storage",
UUID: mountUUID, UUID: mountUUID,
Accessor: mountAccessor, Accessor: mountAccessor,
@ -1798,8 +1802,8 @@ func (c *Core) requiredMountTable() *MountTable {
} }
cubbyholeMount := &MountEntry{ cubbyholeMount := &MountEntry{
Table: mountTableType, Table: mountTableType,
Path: cubbyholeMountPath, Path: mountPathCubbyhole,
Type: cubbyholeMountType, Type: mountTypeCubbyhole,
Description: "per-token private secret storage", Description: "per-token private secret storage",
UUID: cubbyholeUUID, UUID: cubbyholeUUID,
Accessor: cubbyholeAccessor, Accessor: cubbyholeAccessor,
@ -1823,7 +1827,7 @@ func (c *Core) requiredMountTable() *MountTable {
sysMount := &MountEntry{ sysMount := &MountEntry{
Table: mountTableType, Table: mountTableType,
Path: "sys/", Path: "sys/",
Type: systemMountType, Type: mountTypeSystem,
Description: "system endpoints used for control, policy and debugging", Description: "system endpoints used for control, policy and debugging",
UUID: sysUUID, UUID: sysUUID,
Accessor: sysAccessor, Accessor: sysAccessor,
@ -1899,15 +1903,15 @@ func (c *Core) singletonMountTables() (mounts, auth *MountTable) {
func (c *Core) setCoreBackend(entry *MountEntry, backend logical.Backend, view *BarrierView) { func (c *Core) setCoreBackend(entry *MountEntry, backend logical.Backend, view *BarrierView) {
switch entry.Type { switch entry.Type {
case systemMountType: case mountTypeSystem:
c.systemBackend = backend.(*SystemBackend) c.systemBackend = backend.(*SystemBackend)
c.systemBarrierView = view c.systemBarrierView = view
case cubbyholeMountType: case mountTypeCubbyhole:
ch := backend.(*CubbyholeBackend) ch := backend.(*CubbyholeBackend)
ch.saltUUID = entry.UUID ch.saltUUID = entry.UUID
ch.storageView = view ch.storageView = view
c.cubbyholeBackend = ch c.cubbyholeBackend = ch
case identityMountType: case mountTypeIdentity:
c.identityStore = backend.(*IdentityStore) c.identityStore = backend.(*IdentityStore)
} }
} }

View File

@ -33,7 +33,7 @@ func runFilteredPathsEvaluation(context.Context, *Core, bool) error {
// ViewPath returns storage prefix for the view // ViewPath returns storage prefix for the view
func (e *MountEntry) ViewPath() string { func (e *MountEntry) ViewPath() string {
switch e.Type { switch e.Type {
case systemMountType: case mountTypeSystem:
return systemBarrierPrefix return systemBarrierPrefix
case "token": case "token":
return path.Join(systemBarrierPrefix, tokenSubPath) + "/" return path.Join(systemBarrierPrefix, tokenSubPath) + "/"

View File

@ -41,9 +41,9 @@ func (c *Core) reloadMatchingPluginMounts(ctx context.Context, mounts []string)
// - auth/foo // - auth/foo
if strings.HasPrefix(mount, credentialRoutePrefix) { if strings.HasPrefix(mount, credentialRoutePrefix) {
isAuth = true isAuth = true
} else if strings.HasPrefix(mount, systemMountPath+credentialRoutePrefix) { } else if strings.HasPrefix(mount, mountPathSystem+credentialRoutePrefix) {
isAuth = true isAuth = true
mount = strings.TrimPrefix(mount, systemMountPath) mount = strings.TrimPrefix(mount, mountPathSystem)
} }
if !strings.HasSuffix(mount, "/") { if !strings.HasSuffix(mount, "/") {
mount += "/" mount += "/"

View File

@ -637,9 +637,9 @@ func (r *Router) routeCommon(ctx context.Context, req *logical.Request, existenc
clientToken := req.ClientToken clientToken := req.ClientToken
switch { switch {
case strings.HasPrefix(originalPath, "auth/token/"): case strings.HasPrefix(originalPath, "auth/token/"):
case strings.HasPrefix(originalPath, "sys/"): case strings.HasPrefix(originalPath, mountPathSystem):
case strings.HasPrefix(originalPath, "identity/"): case strings.HasPrefix(originalPath, mountPathIdentity):
case strings.HasPrefix(originalPath, cubbyholeMountPath): case strings.HasPrefix(originalPath, mountPathCubbyhole):
if req.Operation == logical.RollbackOperation { if req.Operation == logical.RollbackOperation {
// Backend doesn't support this and it can't properly look up a // Backend doesn't support this and it can't properly look up a
// cubbyhole ID so just return here // cubbyhole ID so just return here
@ -809,7 +809,7 @@ func (r *Router) routeCommon(ctx context.Context, req *logical.Request, existenc
} }
switch re.mountEntry.Type { switch re.mountEntry.Type {
case "token", "ns_token": case mountTypeToken, mountTypeNSToken:
// Nothing; we respect what the token store is telling us and // Nothing; we respect what the token store is telling us and
// we don't allow tuning // we don't allow tuning
default: default:

View File

@ -113,7 +113,7 @@ var (
return errors.New("nil token entry") return errors.New("nil token entry")
} }
storage := ts.core.router.MatchingStorageByAPIPath(ctx, cubbyholeMountPath) storage := ts.core.router.MatchingStorageByAPIPath(ctx, mountPathCubbyhole)
if storage == nil { if storage == nil {
return fmt.Errorf("no cubby mount entry") return fmt.Errorf("no cubby mount entry")
} }
@ -2201,7 +2201,7 @@ func (ts *TokenStore) handleTidy(ctx context.Context, req *logical.Request, data
} }
// List all the cubbyhole storage keys // List all the cubbyhole storage keys
view := ts.core.router.MatchingStorageByAPIPath(ctx, cubbyholeMountPath) view := ts.core.router.MatchingStorageByAPIPath(ctx, mountPathCubbyhole)
if view == nil { if view == nil {
return fmt.Errorf("no cubby mount entry") return fmt.Errorf("no cubby mount entry")
} }

View File

@ -135,8 +135,8 @@ func TestTokenStore_CubbyholeTidy(t *testing.T) {
func testTokenStore_CubbyholeTidy(t *testing.T, c *Core, root string, nsCtx context.Context) { func testTokenStore_CubbyholeTidy(t *testing.T, c *Core, root string, nsCtx context.Context) {
ts := c.tokenStore ts := c.tokenStore
backend := c.router.MatchingBackend(nsCtx, cubbyholeMountPath) backend := c.router.MatchingBackend(nsCtx, mountPathCubbyhole)
view := c.router.MatchingStorageByAPIPath(nsCtx, cubbyholeMountPath) view := c.router.MatchingStorageByAPIPath(nsCtx, mountPathCubbyhole)
for i := 1; i <= 20; i++ { for i := 1; i <= 20; i++ {
// Create 20 tokens // Create 20 tokens