2015-03-09 23:33:27 +00:00
package vault
import (
2017-12-01 22:08:38 +00:00
"context"
2016-08-15 13:42:42 +00:00
"crypto/ecdsa"
2019-10-17 17:33:00 +00:00
"crypto/rand"
2017-02-17 01:13:19 +00:00
"crypto/subtle"
2019-10-28 16:51:45 +00:00
"crypto/tls"
2016-08-15 13:42:42 +00:00
"crypto/x509"
2015-03-10 00:45:34 +00:00
"errors"
2015-03-09 23:33:27 +00:00
"fmt"
2019-10-17 17:33:00 +00:00
"io"
2016-08-15 13:42:42 +00:00
"net"
"net/http"
2015-05-02 20:28:33 +00:00
"net/url"
2017-04-04 00:52:29 +00:00
"path/filepath"
2015-03-10 00:45:34 +00:00
"sync"
2017-10-23 20:06:27 +00:00
"sync/atomic"
2015-04-08 23:43:17 +00:00
"time"
2015-03-09 23:33:27 +00:00
2020-01-14 01:02:16 +00:00
"github.com/armon/go-metrics"
2015-11-02 16:01:00 +00:00
"github.com/hashicorp/errwrap"
2019-10-08 17:57:15 +00:00
log "github.com/hashicorp/go-hclog"
2020-01-11 01:39:52 +00:00
wrapping "github.com/hashicorp/go-kms-wrapping"
aeadwrapper "github.com/hashicorp/go-kms-wrapping/wrappers/aead"
2020-02-13 21:27:31 +00:00
"github.com/hashicorp/go-multierror"
"github.com/hashicorp/go-uuid"
2019-10-08 17:57:15 +00:00
"github.com/hashicorp/vault/api"
2015-03-27 20:45:13 +00:00
"github.com/hashicorp/vault/audit"
2019-10-08 17:57:15 +00:00
"github.com/hashicorp/vault/command/server"
"github.com/hashicorp/vault/helper/metricsutil"
2019-04-13 07:44:06 +00:00
"github.com/hashicorp/vault/helper/namespace"
2020-02-15 19:58:05 +00:00
"github.com/hashicorp/vault/internalshared/reloadutil"
2019-10-08 17:57:15 +00:00
"github.com/hashicorp/vault/physical/raft"
2019-04-12 21:54:35 +00:00
"github.com/hashicorp/vault/sdk/helper/certutil"
"github.com/hashicorp/vault/sdk/helper/consts"
"github.com/hashicorp/vault/sdk/helper/jsonutil"
"github.com/hashicorp/vault/sdk/helper/logging"
"github.com/hashicorp/vault/sdk/helper/mlock"
2019-06-20 19:14:58 +00:00
"github.com/hashicorp/vault/sdk/helper/strutil"
2019-04-12 22:26:54 +00:00
"github.com/hashicorp/vault/sdk/helper/tlsutil"
2019-04-12 21:54:35 +00:00
"github.com/hashicorp/vault/sdk/logical"
"github.com/hashicorp/vault/sdk/physical"
2019-12-06 14:46:39 +00:00
sr "github.com/hashicorp/vault/serviceregistration"
2015-03-11 18:34:08 +00:00
"github.com/hashicorp/vault/shamir"
2019-04-17 20:50:31 +00:00
"github.com/hashicorp/vault/vault/cluster"
2020-01-11 01:39:52 +00:00
vaultseal "github.com/hashicorp/vault/vault/seal"
2020-02-13 21:27:31 +00:00
"github.com/patrickmn/go-cache"
2019-10-08 17:57:15 +00:00
"google.golang.org/grpc"
2015-03-09 23:33:27 +00:00
)
2015-03-10 00:45:34 +00:00
const (
2018-10-12 16:29:15 +00:00
// CoreLockPath is the path used to acquire a coordinating lock
2015-04-14 21:06:15 +00:00
// for a highly-available deploy.
2018-10-12 16:29:15 +00:00
CoreLockPath = "core/lock"
2015-04-14 21:06:15 +00:00
2017-03-03 20:00:46 +00:00
// The poison pill is used as a check during certain scenarios to indicate
// to standby nodes that they should seal
poisonPillPath = "core/poison-pill"
2015-04-14 23:44:48 +00:00
// coreLeaderPrefix is the prefix used for the UUID that contains
// the currently elected leader.
coreLeaderPrefix = "core/leader/"
2017-10-23 20:03:36 +00:00
// knownPrimaryAddrsPrefix is used to store last-known cluster address
// information for primaries
knownPrimaryAddrsPrefix = "core/primary-addrs/"
2017-02-17 01:13:19 +00:00
// coreKeyringCanaryPath is used as a canary to indicate to replicated
// clusters that they need to perform a rekey operation synchronously; this
// isn't keyring-canary to avoid ignoring it when ignoring core/keyring
coreKeyringCanaryPath = "core/canary-keyring"
2015-03-10 00:45:34 +00:00
)
var (
// ErrAlreadyInit is returned if the core is already
// initialized. This prevents a re-initialization.
ErrAlreadyInit = errors . New ( "Vault is already initialized" )
// ErrNotInit is returned if a non-initialized barrier
// is attempted to be unsealed.
ErrNotInit = errors . New ( "Vault is not initialized" )
2015-03-16 22:28:50 +00:00
// ErrInternalError is returned when we don't want to leak
// any information about an internal error
ErrInternalError = errors . New ( "internal error" )
2015-04-14 23:53:40 +00:00
// ErrHANotEnabled is returned if the operation only makes sense
// in an HA setting
ErrHANotEnabled = errors . New ( "Vault is not configured for highly-available mode" )
2016-08-15 13:42:42 +00:00
// manualStepDownSleepPeriod is how long to sleep after a user-initiated
// step down of the active node, to prevent instantly regrabbing the lock.
// It's var not const so that tests can manipulate it.
manualStepDownSleepPeriod = 10 * time . Second
2017-02-17 01:13:19 +00:00
// Functions only in the Enterprise version
2019-10-27 20:30:38 +00:00
enterprisePostUnseal = enterprisePostUnsealImpl
enterprisePreSeal = enterprisePreSealImpl
enterpriseSetupFilteredPaths = enterpriseSetupFilteredPathsImpl
startReplication = startReplicationImpl
stopReplication = stopReplicationImpl
LastWAL = lastWALImpl
LastPerformanceWAL = lastPerformanceWALImpl
PerformanceMerkleRoot = merkleRootImpl
DRMerkleRoot = merkleRootImpl
LastRemoteWAL = lastRemoteWALImpl
WaitUntilWALShipped = waitUntilWALShippedImpl
2015-03-10 00:45:34 +00:00
)
2016-04-04 14:44:22 +00:00
// NonFatalError is an error that can be returned during NewCore that should be
// displayed but not cause a program exit
type NonFatalError struct {
Err error
2015-03-09 23:33:27 +00:00
}
2016-04-04 14:44:22 +00:00
func ( e * NonFatalError ) WrappedErrors ( ) [ ] error {
return [ ] error { e . Err }
2015-03-10 00:45:34 +00:00
}
2016-04-04 14:44:22 +00:00
func ( e * NonFatalError ) Error ( ) string {
return e . Err . Error ( )
2015-03-10 00:45:34 +00:00
}
2019-01-23 21:34:34 +00:00
// NewNonFatalError returns a new non-fatal error.
func NewNonFatalError ( err error ) * NonFatalError {
return & NonFatalError { Err : err }
}
2019-06-27 10:50:47 +00:00
// IsFatalError returns true if the given error is a fatal error.
2019-01-23 21:34:34 +00:00
func IsFatalError ( err error ) bool {
return ! errwrap . ContainsType ( err , new ( NonFatalError ) )
}
2016-08-24 18:15:25 +00:00
// ErrInvalidKey is returned if there is a user-based error with a provided
// unseal key. This will be shown to the user, so should not contain
// information that is sensitive.
2015-03-12 18:20:27 +00:00
type ErrInvalidKey struct {
Reason string
}
func ( e * ErrInvalidKey ) Error ( ) string {
return fmt . Sprintf ( "invalid key: %v" , e . Reason )
}
2018-09-18 03:03:00 +00:00
type RegisterAuthFunc func ( context . Context , time . Duration , string , * logical . Auth ) error
2016-08-15 13:42:42 +00:00
type activeAdvertisement struct {
2019-02-15 02:14:56 +00:00
RedirectAddr string ` json:"redirect_addr" `
ClusterAddr string ` json:"cluster_addr,omitempty" `
ClusterCert [ ] byte ` json:"cluster_cert,omitempty" `
ClusterKeyParams * certutil . ClusterKeyParams ` json:"cluster_key_params,omitempty" `
2016-08-15 13:42:42 +00:00
}
2017-01-17 16:47:06 +00:00
type unlockInformation struct {
Parts [ ] [ ] byte
Nonce string
}
2019-10-11 18:56:59 +00:00
type raftInformation struct {
2020-01-11 01:39:52 +00:00
challenge * wrapping . EncryptedBlobInfo
2019-10-11 18:56:59 +00:00
leaderClient * api . Client
leaderBarrierConfig * SealConfig
nonVoter bool
2020-01-14 01:02:16 +00:00
joinInProgress bool
2019-10-11 18:56:59 +00:00
}
2020-02-13 21:27:31 +00:00
type migrationInformation struct {
// seal to use during a migration operation. It is the
// seal we're migrating *from*.
seal Seal
masterKey [ ] byte
recoveryKey [ ] byte
// shamirCombinedKey is the key that is used to store master key when shamir
// seal is in use. This will be set as the recovery key when a migration happens
// from shamir to auto-seal.
shamirCombinedKey [ ] byte
}
2015-03-09 23:33:27 +00:00
// Core is used as the central manager of Vault activity. It is the primary point of
// interface for API handlers and is responsible for managing the logical and physical
// backends, router, security barrier, and audit trails.
type Core struct {
2018-09-18 03:03:00 +00:00
entCore
2018-11-07 01:21:24 +00:00
// The registry of builtin plugins is passed in here as an interface because
// if it's used directly, it results in import cycles.
builtinRegistry BuiltinRegistry
2017-02-17 01:13:19 +00:00
// N.B.: This is used to populate a dev token down replication, as
// otherwise, after replication is started, a dev would have to go through
// the generate-root process simply to talk to the new follower cluster.
devToken string
2015-04-14 21:06:15 +00:00
// HABackend may be available depending on the physical backend
ha physical . HABackend
2019-09-18 19:07:18 +00:00
// storageType is the the storage type set in the storage configuration
storageType string
2016-08-15 13:42:42 +00:00
// redirectAddr is the address we advertise as leader if held
redirectAddr string
// clusterAddr is the address we use for clustering
2019-06-27 17:00:03 +00:00
clusterAddr * atomic . Value
2015-04-14 23:44:48 +00:00
2015-03-09 23:33:27 +00:00
// physical backend is the un-trusted backend with durable data
physical physical . Backend
2019-12-06 14:46:39 +00:00
// serviceRegistration is the ServiceRegistration network
serviceRegistration sr . ServiceRegistration
2019-06-20 19:14:58 +00:00
// underlyingPhysical will always point to the underlying backend
// implementation. This is an un-trusted backend with durable data
underlyingPhysical physical . Backend
2018-10-23 06:34:02 +00:00
// seal is our seal, for seal configuration information
2016-04-04 14:44:22 +00:00
seal Seal
2020-01-14 01:02:16 +00:00
// raftJoinDoneCh is used by the raft retry join routine to inform unseal process
// that the join is complete
raftJoinDoneCh chan struct { }
// postUnsealStarted informs the raft retry join routine that unseal key
// validation is completed and post unseal has started so that it can complete
// the join process when Shamir seal is in use
postUnsealStarted * uint32
2019-10-11 18:56:59 +00:00
// raftInfo will contain information required for this node to join as a
// peer to an existing raft cluster
raftInfo * raftInformation
2019-06-20 19:14:58 +00:00
2020-02-13 21:27:31 +00:00
// migrationInfo is used during a seal migration. This contains information
// about the seal we are migrating *from*.
migrationInfo * migrationInformation
2019-10-16 16:52:37 +00:00
sealMigrated * uint32
2018-10-23 06:34:02 +00:00
2019-03-04 22:11:56 +00:00
// unwrapSeal is the seal to use on Enterprise to unwrap values wrapped
// with the previous seal.
unwrapSeal Seal
2015-03-09 23:33:27 +00:00
// barrier is the security barrier wrapping the physical backend
barrier SecurityBarrier
// router is responsible for managing the mount points for logical backends.
router * Router
2015-03-10 00:45:34 +00:00
2015-03-18 22:21:41 +00:00
// logicalBackends is the mapping of backends to use for this core
logicalBackends map [ string ] logical . Factory
// credentialBackends is the mapping of backends to use for this core
2015-03-31 01:07:05 +00:00
credentialBackends map [ string ] logical . Factory
2015-03-15 23:25:38 +00:00
2015-03-27 20:45:13 +00:00
// auditBackends is the mapping of backends to use for this core
auditBackends map [ string ] audit . Factory
2015-03-10 00:45:34 +00:00
// stateLock protects mutable state
2020-03-10 20:01:20 +00:00
stateLock DeadlockRWMutex
2018-07-24 20:57:25 +00:00
sealed * uint32
2015-03-10 00:45:34 +00:00
2018-03-07 02:35:58 +00:00
standby bool
2018-08-27 17:01:07 +00:00
perfStandby bool
2018-03-07 02:35:58 +00:00
standbyDoneCh chan struct { }
standbyStopCh chan struct { }
manualStepDownCh chan struct { }
2018-06-09 19:35:22 +00:00
keepHALockOnStepDown * uint32
2018-03-07 02:35:58 +00:00
heldHALock physical . Lock
2015-04-14 21:06:15 +00:00
2020-02-15 02:07:31 +00:00
// shutdownDoneCh is used to notify when Shutdown() completes
shutdownDoneCh chan struct { }
2017-01-17 16:47:06 +00:00
// unlockInfo has the keys provided to Unseal until the threshold number of parts is available, as well as the operation nonce
unlockInfo * unlockInformation
2015-03-10 00:45:34 +00:00
2016-01-15 15:55:35 +00:00
// generateRootProgress holds the shares until we reach enough
2016-01-09 02:21:02 +00:00
// to verify the master key
2016-01-15 15:55:35 +00:00
generateRootConfig * GenerateRootConfig
generateRootProgress [ ] [ ] byte
generateRootLock sync . Mutex
2016-01-09 02:21:02 +00:00
2016-04-04 14:44:22 +00:00
// These variables holds the config and shares we have until we reach
// enough to verify the appropriate master key. Note that the same lock is
// used; this isn't time-critical so this shouldn't be a problem.
2018-05-21 21:46:32 +00:00
barrierRekeyConfig * SealConfig
recoveryRekeyConfig * SealConfig
rekeyLock sync . RWMutex
2015-05-28 18:40:01 +00:00
2015-03-11 22:19:41 +00:00
// mounts is loaded after unseal since it is a protected
// configuration
2015-03-17 22:28:01 +00:00
mounts * MountTable
2015-03-11 22:19:41 +00:00
2015-11-11 16:44:07 +00:00
// mountsLock is used to ensure that the mounts table does not
// change underneath a calling function
mountsLock sync . RWMutex
2015-03-18 22:46:07 +00:00
// auth is loaded after unseal since it is a protected
// configuration
2015-03-19 16:54:57 +00:00
auth * MountTable
2015-03-18 22:46:07 +00:00
2015-11-11 16:44:07 +00:00
// authLock is used to ensure that the auth table does not
// change underneath a calling function
authLock sync . RWMutex
2015-03-27 20:45:13 +00:00
// audit is loaded after unseal since it is a protected
// configuration
audit * MountTable
2015-11-11 16:44:07 +00:00
// auditLock is used to ensure that the audit table does not
// change underneath a calling function
auditLock sync . RWMutex
2015-03-31 20:22:40 +00:00
// auditBroker is used to ingest the audit events and fan
// out into the configured audit backends
auditBroker * AuditBroker
2017-02-02 19:49:20 +00:00
// auditedHeaders is used to configure which http headers
// can be output in the audit logs
auditedHeaders * AuditedHeadersConfig
2017-10-11 17:21:20 +00:00
// systemBackend is the backend which is used to manage internal operations
systemBackend * SystemBackend
2018-09-18 03:03:00 +00:00
// cubbyholeBackend is the backend which manages the per-token storage
cubbyholeBackend * CubbyholeBackend
2015-09-04 20:58:12 +00:00
// systemBarrierView is the barrier view for the system backend
systemBarrierView * BarrierView
2015-03-12 19:41:12 +00:00
2015-04-08 20:35:32 +00:00
// expiration manager is used for managing LeaseIDs,
2015-03-12 19:44:22 +00:00
// renewal, expiration and revocation
expiration * ExpirationManager
2015-03-17 23:23:58 +00:00
// rollback manager is used to run rollbacks periodically
rollback * RollbackManager
2015-03-18 21:00:42 +00:00
// policy store is used to manage named ACL policies
2015-11-06 16:52:26 +00:00
policyStore * PolicyStore
2015-03-18 21:00:42 +00:00
2015-03-23 20:41:05 +00:00
// token store is used to manage authentication tokens
tokenStore * TokenStore
2017-10-11 17:21:20 +00:00
// identityStore is used to manage client entities
identityStore * IdentityStore
2015-04-08 23:43:17 +00:00
// metricsCh is used to stop the metrics streaming
metricsCh chan struct { }
2015-10-12 20:33:54 +00:00
// metricsMutex is used to prevent a race condition between
// metrics emission and sealing leading to a nil pointer
metricsMutex sync . Mutex
2015-08-27 14:50:16 +00:00
defaultLeaseTTL time . Duration
maxLeaseTTL time . Duration
2015-07-30 13:42:49 +00:00
2018-08-23 19:04:18 +00:00
// baseLogger is used to avoid ResetNamed as it strips useful prefixes in
// e.g. testing
baseLogger log . Logger
logger log . Logger
2016-04-21 13:52:42 +00:00
2016-04-21 20:32:06 +00:00
// cachingDisabled indicates whether caches are disabled
cachingDisabled bool
2018-01-26 03:21:51 +00:00
// Cache stores the actual cache; we always have this but may bypass it if
// disabled
physicalCache physical . ToggleablePurgemonster
2016-07-26 06:25:33 +00:00
2016-09-30 04:06:40 +00:00
// reloadFuncs is a map containing reload functions
2020-02-15 19:58:05 +00:00
reloadFuncs map [ string ] [ ] reloadutil . ReloadFunc
2016-09-30 04:06:40 +00:00
2017-07-03 18:54:01 +00:00
// reloadFuncsLock controls access to the funcs
2016-09-30 04:06:40 +00:00
reloadFuncsLock sync . RWMutex
2017-01-04 21:44:03 +00:00
// wrappingJWTKey is the key used for generating JWTs containing response
// wrapping information
wrappingJWTKey * ecdsa . PrivateKey
2016-08-15 13:42:42 +00:00
//
// Cluster information
//
// Name
2016-07-26 14:01:35 +00:00
clusterName string
2017-08-30 20:28:23 +00:00
// Specific cipher suites to use for clustering, if any
clusterCipherSuites [ ] uint16
2017-02-17 01:13:19 +00:00
// Used to modify cluster parameters
2016-08-15 13:42:42 +00:00
clusterParamsLock sync . RWMutex
// The private key stored in the barrier used for establishing
// mutually-authenticated connections between Vault cluster members
2018-02-23 19:47:07 +00:00
localClusterPrivateKey * atomic . Value
2016-08-15 13:42:42 +00:00
// The local cluster cert
2018-02-23 19:47:07 +00:00
localClusterCert * atomic . Value
2017-03-02 15:03:49 +00:00
// The parsed form of the local cluster cert
2018-02-23 19:47:07 +00:00
localClusterParsedCert * atomic . Value
2016-08-19 15:03:53 +00:00
// The TCP addresses we should use for clustering
clusterListenerAddrs [ ] * net . TCPAddr
2017-05-24 14:38:48 +00:00
// The handler to use for request forwarding
clusterHandler http . Handler
2016-08-15 13:42:42 +00:00
// Write lock used to ensure that we don't have multiple connections adjust
// this value at the same time
requestForwardingConnectionLock sync . RWMutex
2019-02-06 02:01:18 +00:00
// Lock for the leader values, ensuring we don't run the parts of Leader()
// that change things concurrently
leaderParamsLock sync . RWMutex
// Current cluster leader values
clusterLeaderParams * atomic . Value
2017-05-25 00:51:53 +00:00
// Info on cluster members
2017-05-25 01:10:32 +00:00
clusterPeerClusterAddrsCache * cache . Cache
2017-05-24 19:06:56 +00:00
// The context for the client
rpcClientConnContext context . Context
2016-08-19 15:03:53 +00:00
// The function for canceling the client connection
rpcClientConnCancelFunc context . CancelFunc
// The grpc ClientConn for RPC calls
rpcClientConn * grpc . ClientConn
// The grpc forwarding client
2017-05-24 19:06:56 +00:00
rpcForwardingClient * forwardingClient
2019-06-20 19:14:58 +00:00
// The UUID used to hold the leader lock. Only set on active node
leaderUUID string
2017-01-13 19:51:10 +00:00
2017-06-17 04:04:55 +00:00
// CORS Information
corsConfig * CORSConfig
2017-10-23 20:03:36 +00:00
// The active set of upstream cluster addresses; stored via the Echo
// mechanism, loaded by the balancer
atomicPrimaryClusterAddrs * atomic . Value
atomicPrimaryFailoverAddrs * atomic . Value
2018-09-18 03:03:00 +00:00
2017-01-13 19:51:10 +00:00
// replicationState keeps the current replication state cached for quick
2018-01-20 00:24:04 +00:00
// lookup; activeNodeReplicationState stores the active value on standbys
replicationState * uint32
activeNodeReplicationState * uint32
2017-02-24 15:45:29 +00:00
2018-03-27 20:23:33 +00:00
// uiConfig contains UI configuration
uiConfig * UIConfig
2017-04-04 00:52:29 +00:00
2017-09-15 04:21:35 +00:00
// rawEnabled indicates whether the Raw endpoint is enabled
rawEnabled bool
2017-04-11 00:12:52 +00:00
// pluginDirectory is the location vault will look for plugin binaries
2017-04-04 00:52:29 +00:00
pluginDirectory string
// pluginCatalog is used to manage plugin configurations
pluginCatalog * PluginCatalog
2017-04-11 00:12:52 +00:00
2017-04-24 19:21:49 +00:00
enableMlock bool
2017-08-04 20:42:51 +00:00
// This can be used to trigger operations to stop running when Vault is
// going to be shut down, stepped down, or sealed
2018-01-19 06:44:44 +00:00
activeContext context . Context
2018-08-01 19:07:37 +00:00
activeContextCancelFunc * atomic . Value
2018-02-09 21:37:40 +00:00
// Stores the sealunwrapper for downgrade needs
sealUnwrapper physical . Backend
2018-04-19 17:29:43 +00:00
2019-01-23 21:34:34 +00:00
// unsealwithStoredKeysLock is a mutex that prevents multiple processes from
// unsealing with stored keys are the same time.
unsealWithStoredKeysLock sync . Mutex
2018-04-19 17:29:43 +00:00
// Stores any funcs that should be run on successful postUnseal
postUnsealFuncs [ ] func ( )
2018-09-05 19:52:54 +00:00
2019-10-15 04:55:31 +00:00
// Stores any funcs that should be run on successful barrier unseal in
// recovery mode
postRecoveryUnsealFuncs [ ] func ( ) error
2018-09-18 03:03:00 +00:00
// replicationFailure is used to mark when replication has entered an
// unrecoverable failure.
replicationFailure * uint32
// disablePerfStanby is used to tell a standby not to attempt to become a
// perf standby
disablePerfStandby bool
licensingStopCh chan struct { }
2018-09-05 19:52:54 +00:00
// Stores loggers so we can reset the level
allLoggers [ ] log . Logger
allLoggersLock sync . RWMutex
2019-02-06 02:01:18 +00:00
// Can be toggled atomically to cause the core to never try to become
// active, or give up active as soon as it gets it
neverBecomeActive * uint32
2019-02-08 21:32:06 +00:00
// loadCaseSensitiveIdentityStore enforces the loading of identity store
// artifacts in a case sensitive manner. To be used only in testing.
2019-02-15 02:14:56 +00:00
loadCaseSensitiveIdentityStore bool
// clusterListener starts up and manages connections on the cluster ports
2019-09-03 15:59:56 +00:00
clusterListener * atomic . Value
2019-02-20 20:12:21 +00:00
2019-02-14 20:46:59 +00:00
// Telemetry objects
2019-02-20 20:12:21 +00:00
metricsHelper * metricsutil . MetricsHelper
2019-03-05 19:55:07 +00:00
// Stores request counters
counters counters
2019-06-10 18:07:16 +00:00
2019-06-20 19:14:58 +00:00
// Stores the raft applied index for standby nodes
raftFollowerStates * raftFollowerStates
// Stop channel for raft TLS rotations
raftTLSRotationStopCh chan struct { }
2019-07-03 20:56:30 +00:00
// Stores the pending peers we are waiting to give answers
pendingRaftPeers map [ string ] [ ] byte
2019-06-20 19:14:58 +00:00
2019-10-08 17:57:15 +00:00
// rawConfig stores the config as-is from the provided server configuration.
2020-04-16 23:34:46 +00:00
rawConfig * atomic . Value
2019-10-08 17:57:15 +00:00
2019-06-10 18:07:16 +00:00
coreNumber int
2019-10-15 04:55:31 +00:00
2019-10-17 17:33:00 +00:00
// secureRandomReader is the reader used for CSP operations
secureRandomReader io . Reader
2019-10-15 04:55:31 +00:00
recoveryMode bool
2020-01-17 07:03:02 +00:00
clusterNetworkLayer cluster . NetworkLayer
2020-01-21 17:24:33 +00:00
2020-01-17 07:03:02 +00:00
// PR1103disabled is used to test upgrade workflows: when set to true,
// the correct behaviour for namespaced cubbyholes is disabled, so we
// can test an upgrade to a version that includes the fixes from
// https://github.com/hashicorp/vault-enterprise/pull/1103
PR1103disabled bool
2015-03-09 23:33:27 +00:00
}
2015-03-11 18:52:01 +00:00
// CoreConfig is used to parameterize a core
type CoreConfig struct {
2020-02-15 00:39:13 +00:00
entCoreConfig
2019-12-06 14:46:39 +00:00
DevToken string
2017-02-17 01:13:19 +00:00
2019-12-06 14:46:39 +00:00
BuiltinRegistry BuiltinRegistry
2018-11-07 01:21:24 +00:00
2019-12-06 14:46:39 +00:00
LogicalBackends map [ string ] logical . Factory
2016-07-26 06:25:33 +00:00
2019-12-06 14:46:39 +00:00
CredentialBackends map [ string ] logical . Factory
2016-07-26 06:25:33 +00:00
2019-12-06 14:46:39 +00:00
AuditBackends map [ string ] audit . Factory
2016-07-26 06:25:33 +00:00
2019-12-06 14:46:39 +00:00
Physical physical . Backend
2016-07-26 06:25:33 +00:00
2019-12-06 14:46:39 +00:00
StorageType string
2019-09-18 19:07:18 +00:00
2016-07-26 06:25:33 +00:00
// May be nil, which disables HA operations
2019-12-06 14:46:39 +00:00
HAPhysical physical . HABackend
ServiceRegistration sr . ServiceRegistration
2016-07-26 06:25:33 +00:00
2019-12-06 14:46:39 +00:00
Seal Seal
2016-07-26 06:25:33 +00:00
2019-12-06 14:46:39 +00:00
SecureRandomReader io . Reader
2019-10-17 17:33:00 +00:00
2019-12-06 14:46:39 +00:00
Logger log . Logger
2016-07-26 06:25:33 +00:00
// Disables the LRU cache on the physical backend
2019-12-06 14:46:39 +00:00
DisableCache bool
2016-07-26 06:25:33 +00:00
// Disables mlock syscall
2019-12-06 14:46:39 +00:00
DisableMlock bool
2016-07-26 06:25:33 +00:00
2016-08-26 14:27:06 +00:00
// Custom cache size for the LRU cache on the physical backend, or zero for default
2019-12-06 14:46:39 +00:00
CacheSize int
2016-07-26 06:25:33 +00:00
// Set as the leader address for HA
2019-12-06 14:46:39 +00:00
RedirectAddr string
2016-08-15 13:42:42 +00:00
// Set as the cluster address for HA
2019-12-06 14:46:39 +00:00
ClusterAddr string
2016-07-26 06:25:33 +00:00
2019-12-06 14:46:39 +00:00
DefaultLeaseTTL time . Duration
2016-07-26 06:25:33 +00:00
2019-12-06 14:46:39 +00:00
MaxLeaseTTL time . Duration
2016-07-26 06:25:33 +00:00
2019-12-06 14:46:39 +00:00
ClusterName string
2016-09-30 04:06:40 +00:00
2019-12-06 14:46:39 +00:00
ClusterCipherSuites string
2017-08-30 20:28:23 +00:00
2019-12-06 14:46:39 +00:00
EnableUI bool
2017-02-24 15:45:29 +00:00
2017-09-15 04:21:35 +00:00
// Enable the raw endpoint
2019-12-06 14:46:39 +00:00
EnableRaw bool
2017-09-15 04:21:35 +00:00
2019-12-06 14:46:39 +00:00
PluginDirectory string
2017-04-04 00:52:29 +00:00
2019-12-06 14:46:39 +00:00
DisableSealWrap bool
2018-09-18 03:03:00 +00:00
2019-10-08 17:57:15 +00:00
RawConfig * server . Config
2020-02-15 19:58:05 +00:00
ReloadFuncs * map [ string ] [ ] reloadutil . ReloadFunc
2016-09-30 04:06:40 +00:00
ReloadFuncsLock * sync . RWMutex
2018-09-05 19:52:54 +00:00
2018-09-18 03:03:00 +00:00
// Licensing
LicensingConfig * LicensingConfig
// Don't set this unless in dev mode, ideally only when using inmem
DevLicenseDuration time . Duration
DisablePerformanceStandby bool
2018-10-23 19:03:17 +00:00
DisableIndexing bool
2018-11-19 21:13:16 +00:00
DisableKeyEncodingChecks bool
2018-09-18 03:03:00 +00:00
2018-09-05 19:52:54 +00:00
AllLoggers [ ] log . Logger
2019-02-14 20:46:59 +00:00
// Telemetry objects
MetricsHelper * metricsutil . MetricsHelper
2019-03-05 19:55:07 +00:00
CounterSyncInterval time . Duration
2019-10-15 04:55:31 +00:00
RecoveryMode bool
2020-01-17 07:03:02 +00:00
ClusterNetworkLayer cluster . NetworkLayer
2015-03-11 18:52:01 +00:00
}
2018-10-23 06:34:02 +00:00
func ( c * CoreConfig ) Clone ( ) * CoreConfig {
return & CoreConfig {
DevToken : c . DevToken ,
LogicalBackends : c . LogicalBackends ,
CredentialBackends : c . CredentialBackends ,
AuditBackends : c . AuditBackends ,
Physical : c . Physical ,
HAPhysical : c . HAPhysical ,
2019-12-06 14:46:39 +00:00
ServiceRegistration : c . ServiceRegistration ,
2018-10-23 06:34:02 +00:00
Seal : c . Seal ,
Logger : c . Logger ,
DisableCache : c . DisableCache ,
DisableMlock : c . DisableMlock ,
CacheSize : c . CacheSize ,
2019-09-18 19:07:18 +00:00
StorageType : c . StorageType ,
2018-10-23 06:34:02 +00:00
RedirectAddr : c . RedirectAddr ,
ClusterAddr : c . ClusterAddr ,
DefaultLeaseTTL : c . DefaultLeaseTTL ,
MaxLeaseTTL : c . MaxLeaseTTL ,
ClusterName : c . ClusterName ,
ClusterCipherSuites : c . ClusterCipherSuites ,
EnableUI : c . EnableUI ,
EnableRaw : c . EnableRaw ,
PluginDirectory : c . PluginDirectory ,
DisableSealWrap : c . DisableSealWrap ,
ReloadFuncs : c . ReloadFuncs ,
ReloadFuncsLock : c . ReloadFuncsLock ,
LicensingConfig : c . LicensingConfig ,
DevLicenseDuration : c . DevLicenseDuration ,
DisablePerformanceStandby : c . DisablePerformanceStandby ,
2018-10-23 19:03:17 +00:00
DisableIndexing : c . DisableIndexing ,
2018-10-23 06:34:02 +00:00
AllLoggers : c . AllLoggers ,
2019-03-05 19:55:07 +00:00
CounterSyncInterval : c . CounterSyncInterval ,
2020-01-17 07:03:02 +00:00
ClusterNetworkLayer : c . ClusterNetworkLayer ,
2020-02-15 00:39:13 +00:00
entCoreConfig : c . entCoreConfig . Clone ( ) ,
2018-10-23 06:34:02 +00:00
}
}
2019-12-06 14:46:39 +00:00
// GetServiceRegistration returns the config's ServiceRegistration, or nil if it does
// not exist.
func ( c * CoreConfig ) GetServiceRegistration ( ) sr . ServiceRegistration {
// Check whether there is a ServiceRegistration explictly configured
if c . ServiceRegistration != nil {
return c . ServiceRegistration
}
// Check if HAPhysical is configured and implements ServiceRegistration
if c . HAPhysical != nil && c . HAPhysical . HAEnabled ( ) {
if disc , ok := c . HAPhysical . ( sr . ServiceRegistration ) ; ok {
return disc
}
}
// No service discovery is available.
return nil
}
2015-07-30 13:42:49 +00:00
// NewCore is used to construct a new core
2015-03-11 18:52:01 +00:00
func NewCore ( conf * CoreConfig ) ( * Core , error ) {
2016-08-15 13:42:42 +00:00
if conf . HAPhysical != nil && conf . HAPhysical . HAEnabled ( ) {
if conf . RedirectAddr == "" {
2018-01-04 15:45:40 +00:00
return nil , fmt . Errorf ( "missing API address, please set in configuration or via environment" )
2016-08-15 13:42:42 +00:00
}
2015-04-14 23:44:48 +00:00
}
2015-04-14 21:06:15 +00:00
2015-08-27 14:50:16 +00:00
if conf . DefaultLeaseTTL == 0 {
conf . DefaultLeaseTTL = defaultLeaseTTL
2015-07-30 13:42:49 +00:00
}
2015-08-27 14:50:16 +00:00
if conf . MaxLeaseTTL == 0 {
conf . MaxLeaseTTL = maxLeaseTTL
2015-07-30 13:42:49 +00:00
}
2015-08-27 14:50:16 +00:00
if conf . DefaultLeaseTTL > conf . MaxLeaseTTL {
return nil , fmt . Errorf ( "cannot have DefaultLeaseTTL larger than MaxLeaseTTL" )
2015-07-30 13:42:49 +00:00
}
2015-08-20 17:14:13 +00:00
2015-05-02 20:28:33 +00:00
// Validate the advertise addr if its given to us
2016-08-15 13:42:42 +00:00
if conf . RedirectAddr != "" {
u , err := url . Parse ( conf . RedirectAddr )
2015-05-02 20:28:33 +00:00
if err != nil {
2018-04-05 15:49:21 +00:00
return nil , errwrap . Wrapf ( "redirect address is not valid url: {{err}}" , err )
2015-05-02 20:28:33 +00:00
}
if u . Scheme == "" {
2016-08-19 14:52:14 +00:00
return nil , fmt . Errorf ( "redirect address must include scheme (ex. 'http')" )
2015-05-02 20:28:33 +00:00
}
}
2016-08-26 14:27:06 +00:00
// Make a default logger if not provided
if conf . Logger == nil {
2018-04-03 00:46:59 +00:00
conf . Logger = logging . NewVaultLogger ( log . Trace )
2016-08-26 14:27:06 +00:00
}
2019-10-08 17:57:15 +00:00
// Instantiate a non-nil raw config if none is provided
if conf . RawConfig == nil {
conf . RawConfig = new ( server . Config )
}
2019-03-05 19:55:07 +00:00
syncInterval := conf . CounterSyncInterval
if syncInterval . Nanoseconds ( ) == 0 {
syncInterval = 30 * time . Second
}
2019-10-17 17:33:00 +00:00
// secureRandomReader cannot be nil
if conf . SecureRandomReader == nil {
conf . SecureRandomReader = rand . Reader
}
2015-03-09 23:33:27 +00:00
// Setup the core
c := & Core {
2019-02-15 02:14:56 +00:00
entCore : entCore { } ,
devToken : conf . DevToken ,
physical : conf . Physical ,
2019-12-06 14:46:39 +00:00
serviceRegistration : conf . GetServiceRegistration ( ) ,
2019-06-20 19:14:58 +00:00
underlyingPhysical : conf . Physical ,
2019-09-18 19:07:18 +00:00
storageType : conf . StorageType ,
2019-02-15 02:14:56 +00:00
redirectAddr : conf . RedirectAddr ,
2019-06-27 17:00:03 +00:00
clusterAddr : new ( atomic . Value ) ,
2019-09-03 15:59:56 +00:00
clusterListener : new ( atomic . Value ) ,
2019-02-15 02:14:56 +00:00
seal : conf . Seal ,
router : NewRouter ( ) ,
sealed : new ( uint32 ) ,
2019-10-16 16:52:37 +00:00
sealMigrated : new ( uint32 ) ,
2019-02-15 02:14:56 +00:00
standby : true ,
baseLogger : conf . Logger ,
logger : conf . Logger . Named ( "core" ) ,
defaultLeaseTTL : conf . DefaultLeaseTTL ,
maxLeaseTTL : conf . MaxLeaseTTL ,
cachingDisabled : conf . DisableCache ,
clusterName : conf . ClusterName ,
2020-01-17 07:03:02 +00:00
clusterNetworkLayer : conf . ClusterNetworkLayer ,
2019-04-17 20:50:31 +00:00
clusterPeerClusterAddrsCache : cache . New ( 3 * cluster . HeartbeatInterval , time . Second ) ,
2019-02-15 02:14:56 +00:00
enableMlock : ! conf . DisableMlock ,
rawEnabled : conf . EnableRaw ,
2020-02-15 02:07:31 +00:00
shutdownDoneCh : make ( chan struct { } ) ,
2019-02-15 02:14:56 +00:00
replicationState : new ( uint32 ) ,
atomicPrimaryClusterAddrs : new ( atomic . Value ) ,
atomicPrimaryFailoverAddrs : new ( atomic . Value ) ,
localClusterPrivateKey : new ( atomic . Value ) ,
localClusterCert : new ( atomic . Value ) ,
localClusterParsedCert : new ( atomic . Value ) ,
activeNodeReplicationState : new ( uint32 ) ,
keepHALockOnStepDown : new ( uint32 ) ,
replicationFailure : new ( uint32 ) ,
disablePerfStandby : true ,
activeContextCancelFunc : new ( atomic . Value ) ,
allLoggers : conf . AllLoggers ,
builtinRegistry : conf . BuiltinRegistry ,
neverBecomeActive : new ( uint32 ) ,
clusterLeaderParams : new ( atomic . Value ) ,
2019-02-20 20:12:21 +00:00
metricsHelper : conf . MetricsHelper ,
2019-10-17 17:33:00 +00:00
secureRandomReader : conf . SecureRandomReader ,
2020-04-16 23:34:46 +00:00
rawConfig : new ( atomic . Value ) ,
2019-03-05 19:55:07 +00:00
counters : counters {
requests : new ( uint64 ) ,
syncInterval : syncInterval ,
} ,
2020-01-14 01:02:16 +00:00
recoveryMode : conf . RecoveryMode ,
postUnsealStarted : new ( uint32 ) ,
raftJoinDoneCh : make ( chan struct { } ) ,
2015-03-09 23:33:27 +00:00
}
2015-03-15 23:25:38 +00:00
2020-04-16 23:34:46 +00:00
c . rawConfig . Store ( conf . RawConfig )
2018-07-24 20:57:25 +00:00
atomic . StoreUint32 ( c . sealed , 1 )
2018-09-05 19:52:54 +00:00
c . allLoggers = append ( c . allLoggers , c . logger )
2018-07-24 20:57:25 +00:00
2019-07-03 02:16:43 +00:00
c . router . logger = c . logger . Named ( "router" )
c . allLoggers = append ( c . allLoggers , c . router . logger )
2018-01-23 02:44:38 +00:00
atomic . StoreUint32 ( c . replicationState , uint32 ( consts . ReplicationDRDisabled | consts . ReplicationPerformanceDisabled ) )
2018-02-23 19:47:07 +00:00
c . localClusterCert . Store ( ( [ ] byte ) ( nil ) )
c . localClusterParsedCert . Store ( ( * x509 . Certificate ) ( nil ) )
c . localClusterPrivateKey . Store ( ( * ecdsa . PrivateKey ) ( nil ) )
2018-01-23 02:44:38 +00:00
2019-02-06 02:01:18 +00:00
c . clusterLeaderParams . Store ( ( * ClusterLeaderParams ) ( nil ) )
2019-06-27 17:00:03 +00:00
c . clusterAddr . Store ( conf . ClusterAddr )
2018-08-01 19:07:37 +00:00
c . activeContextCancelFunc . Store ( ( context . CancelFunc ) ( nil ) )
2019-10-28 16:51:45 +00:00
switch conf . ClusterCipherSuites {
2019-11-19 04:04:49 +00:00
case "tls13" , "tls12" :
2019-10-28 16:51:45 +00:00
// Do nothing, let Go use the default
case "" :
// Add in forward compatible TLS 1.3 suites, followed by handpicked 1.2 suites
c . clusterCipherSuites = [ ] uint16 {
// 1.3
tls . TLS_AES_128_GCM_SHA256 ,
tls . TLS_AES_256_GCM_SHA384 ,
tls . TLS_CHACHA20_POLY1305_SHA256 ,
// 1.2
tls . TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 ,
tls . TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 ,
tls . TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 ,
}
default :
2017-08-30 20:28:23 +00:00
suites , err := tlsutil . ParseCiphers ( conf . ClusterCipherSuites )
if err != nil {
return nil , errwrap . Wrapf ( "error parsing cluster cipher suites: {{err}}" , err )
}
c . clusterCipherSuites = suites
}
2017-08-07 14:03:30 +00:00
// Load CORS config and provide a value for the core field.
2018-06-09 20:57:57 +00:00
c . corsConfig = & CORSConfig {
core : c ,
Enabled : new ( uint32 ) ,
}
2017-06-17 05:26:25 +00:00
2017-10-23 20:03:36 +00:00
if c . seal == nil {
2020-01-11 01:39:52 +00:00
c . seal = NewDefaultSeal ( & vaultseal . Access {
Wrapper : aeadwrapper . NewWrapper ( & wrapping . WrapperOptions {
Logger : c . logger . Named ( "shamir" ) ,
} ) ,
} )
2017-10-23 20:03:36 +00:00
}
c . seal . SetCore ( c )
2018-09-18 03:03:00 +00:00
if err := coreInit ( c , conf ) ; err != nil {
return nil , err
2017-01-06 20:42:18 +00:00
}
2017-02-17 01:13:19 +00:00
if ! conf . DisableMlock {
// Ensure our memory usage is locked into physical RAM
if err := mlock . LockMemory ( ) ; err != nil {
return nil , fmt . Errorf (
"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." ,
err )
}
}
var err error
2018-09-18 03:03:00 +00:00
2017-04-04 00:52:29 +00:00
// Construct a new AES-GCM barrier
2017-02-17 01:13:19 +00:00
c . barrier , err = NewAESGCMBarrier ( c . physical )
if err != nil {
2018-04-05 15:49:21 +00:00
return nil , errwrap . Wrapf ( "barrier setup failed: {{err}}" , err )
2017-02-17 01:13:19 +00:00
}
2016-09-30 04:06:40 +00:00
// We create the funcs here, then populate the given config with it so that
// the caller can share state
conf . ReloadFuncsLock = & c . reloadFuncsLock
c . reloadFuncsLock . Lock ( )
2020-02-15 19:58:05 +00:00
c . reloadFuncs = make ( map [ string ] [ ] reloadutil . ReloadFunc )
2016-09-30 04:06:40 +00:00
c . reloadFuncsLock . Unlock ( )
conf . ReloadFuncs = & c . reloadFuncs
2019-10-15 04:55:31 +00:00
// All the things happening below this are not required in
// recovery mode
if c . recoveryMode {
return c , nil
}
if conf . PluginDirectory != "" {
c . pluginDirectory , err = filepath . Abs ( conf . PluginDirectory )
if err != nil {
return nil , errwrap . Wrapf ( "core setup failed, could not verify plugin directory: {{err}}" , err )
}
}
createSecondaries ( c , conf )
if conf . HAPhysical != nil && conf . HAPhysical . HAEnabled ( ) {
c . ha = conf . HAPhysical
}
2015-03-18 22:21:41 +00:00
logicalBackends := make ( map [ string ] logical . Factory )
for k , f := range conf . LogicalBackends {
logicalBackends [ k ] = f
2015-03-15 23:25:38 +00:00
}
2018-11-07 01:21:24 +00:00
_ , ok := logicalBackends [ "kv" ]
2015-09-19 22:24:53 +00:00
if ! ok {
2017-09-15 13:02:29 +00:00
logicalBackends [ "kv" ] = PassthroughBackendFactory
2015-09-19 22:24:53 +00:00
}
2018-11-07 01:21:24 +00:00
2015-09-10 01:58:09 +00:00
logicalBackends [ "cubbyhole" ] = CubbyholeBackendFactory
2018-09-18 03:03:00 +00:00
logicalBackends [ systemMountType ] = func ( ctx context . Context , config * logical . BackendConfig ) ( logical . Backend , error ) {
2018-09-05 19:52:54 +00:00
sysBackendLogger := conf . Logger . Named ( "system" )
c . AddLogger ( sysBackendLogger )
b := NewSystemBackend ( c , sysBackendLogger )
2018-01-19 06:44:44 +00:00
if err := b . Setup ( ctx , config ) ; err != nil {
Backend plugin system (#2874)
* Add backend plugin changes
* Fix totp backend plugin tests
* Fix logical/plugin InvalidateKey test
* Fix plugin catalog CRUD test, fix NoopBackend
* Clean up commented code block
* Fix system backend mount test
* Set plugin_name to omitempty, fix handleMountTable config parsing
* Clean up comments, keep shim connections alive until cleanup
* Include pluginClient, disallow LookupPlugin call from within a plugin
* Add wrapper around backendPluginClient for proper cleanup
* Add logger shim tests
* Add logger, storage, and system shim tests
* Use pointer receivers for system view shim
* Use plugin name if no path is provided on mount
* Enable plugins for auth backends
* Add backend type attribute, move builtin/plugin/package
* Fix merge conflict
* Fix missing plugin name in mount config
* Add integration tests on enabling auth backend plugins
* Remove dependency cycle on mock-plugin
* Add passthrough backend plugin, use logical.BackendType to determine lease generation
* Remove vault package dependency on passthrough package
* Add basic impl test for passthrough plugin
* Incorporate feedback; set b.backend after shims creation on backendPluginServer
* Fix totp plugin test
* Add plugin backends docs
* Fix tests
* Fix builtin/plugin tests
* Remove flatten from PluginRunner fields
* Move mock plugin to logical/plugin, remove totp and passthrough plugins
* Move pluginMap into newPluginClient
* Do not create storage RPC connection on HandleRequest and HandleExistenceCheck
* Change shim logger's Fatal to no-op
* Change BackendType to uint32, match UX backend types
* Change framework.Backend Setup signature
* Add Setup func to logical.Backend interface
* Move OptionallyEnableMlock call into plugin.Serve, update docs and comments
* Remove commented var in plugin package
* RegisterLicense on logical.Backend interface (#3017)
* Add RegisterLicense to logical.Backend interface
* Update RegisterLicense to use callback func on framework.Backend
* Refactor framework.Backend.RegisterLicense
* plugin: Prevent plugin.SystemViewClient.ResponseWrapData from getting JWTs
* plugin: Revert BackendType to remove TypePassthrough and related references
* Fix typo in plugin backends docs
2017-07-20 17:28:40 +00:00
return nil , err
}
return b , nil
2015-03-15 23:25:38 +00:00
}
2018-01-19 06:44:44 +00:00
logicalBackends [ "identity" ] = func ( ctx context . Context , config * logical . BackendConfig ) ( logical . Backend , error ) {
2018-09-05 19:52:54 +00:00
identityLogger := conf . Logger . Named ( "identity" )
c . AddLogger ( identityLogger )
return NewIdentityStore ( ctx , c , config , identityLogger )
2017-10-11 17:21:20 +00:00
}
2018-09-18 03:03:00 +00:00
addExtraLogicalBackends ( c , logicalBackends )
2015-03-18 22:21:41 +00:00
c . logicalBackends = logicalBackends
2015-03-15 23:25:38 +00:00
2015-03-31 01:07:05 +00:00
credentialBackends := make ( map [ string ] logical . Factory )
2015-03-18 22:21:41 +00:00
for k , f := range conf . CredentialBackends {
credentialBackends [ k ] = f
}
2018-01-19 06:44:44 +00:00
credentialBackends [ "token" ] = func ( ctx context . Context , config * logical . BackendConfig ) ( logical . Backend , error ) {
2018-09-05 19:52:54 +00:00
tsLogger := conf . Logger . Named ( "token" )
c . AddLogger ( tsLogger )
return NewTokenStore ( ctx , tsLogger , c , config )
2015-03-19 02:11:52 +00:00
}
2018-09-18 03:03:00 +00:00
addExtraCredentialBackends ( c , credentialBackends )
2015-03-18 22:21:41 +00:00
c . credentialBackends = credentialBackends
2015-03-27 20:45:13 +00:00
auditBackends := make ( map [ string ] audit . Factory )
for k , f := range conf . AuditBackends {
auditBackends [ k ] = f
}
c . auditBackends = auditBackends
2016-04-04 14:44:22 +00:00
2018-03-27 20:23:33 +00:00
uiStoragePrefix := systemBarrierPrefix + "ui"
c . uiConfig = NewUIConfig ( conf . EnableUI , physical . NewView ( c . physical , uiStoragePrefix ) , NewBarrierView ( c . barrier , uiStoragePrefix ) )
2019-09-03 15:59:56 +00:00
c . clusterListener . Store ( ( * cluster . Listener ) ( nil ) )
2017-10-23 20:03:36 +00:00
return c , nil
2015-03-09 23:33:27 +00:00
}
2015-06-18 01:23:59 +00:00
// Shutdown is invoked when the Vault instance is about to be terminated. It
// should not be accessible as part of an API call as it will cause an availability
// problem. It is only used to gracefully quit in the case of HA so that failover
// happens as quickly as possible.
func ( c * Core ) Shutdown ( ) error {
2018-04-03 00:46:59 +00:00
c . logger . Debug ( "shutdown called" )
2020-02-15 02:07:31 +00:00
err := c . sealInternal ( )
c . stateLock . Lock ( )
defer c . stateLock . Unlock ( )
if c . shutdownDoneCh != nil {
close ( c . shutdownDoneCh )
c . shutdownDoneCh = nil
}
return err
}
// ShutdownDone returns a channel that will be closed after Shutdown completes
func ( c * Core ) ShutdownDone ( ) <- chan struct { } {
return c . shutdownDoneCh
2015-06-18 01:23:59 +00:00
}
2017-06-17 04:04:55 +00:00
// CORSConfig returns the current CORS configuration
func ( c * Core ) CORSConfig ( ) * CORSConfig {
return c . corsConfig
}
2018-01-19 06:44:44 +00:00
func ( c * Core ) GetContext ( ) ( context . Context , context . CancelFunc ) {
c . stateLock . RLock ( )
defer c . stateLock . RUnlock ( )
2018-09-18 03:03:00 +00:00
return context . WithCancel ( namespace . RootContext ( c . activeContext ) )
2018-01-19 06:44:44 +00:00
}
2015-03-09 23:33:27 +00:00
// Sealed checks if the Vault is current sealed
2018-07-24 20:57:25 +00:00
func ( c * Core ) Sealed ( ) bool {
return atomic . LoadUint32 ( c . sealed ) == 1
2015-03-09 23:33:27 +00:00
}
2015-03-11 18:52:01 +00:00
// SecretProgress returns the number of keys provided so far
2017-01-17 16:47:06 +00:00
func ( c * Core ) SecretProgress ( ) ( int , string ) {
2015-03-11 18:52:01 +00:00
c . stateLock . RLock ( )
defer c . stateLock . RUnlock ( )
2017-01-17 16:47:06 +00:00
switch c . unlockInfo {
case nil :
return 0 , ""
default :
return len ( c . unlockInfo . Parts ) , c . unlockInfo . Nonce
}
2015-03-11 18:52:01 +00:00
}
2015-10-28 19:59:39 +00:00
// ResetUnsealProcess removes the current unlock parts from memory, to reset
// the unsealing process
func ( c * Core ) ResetUnsealProcess ( ) {
c . stateLock . Lock ( )
defer c . stateLock . Unlock ( )
2017-01-17 16:47:06 +00:00
c . unlockInfo = nil
2015-10-28 19:59:39 +00:00
}
2015-03-15 00:47:11 +00:00
// Unseal is used to provide one of the key parts to unseal the Vault.
2015-03-15 01:25:36 +00:00
//
// They key given as a parameter will automatically be zerod after
// this method is done with it. If you want to keep the key around, a copy
// should be made.
func ( c * Core ) Unseal ( key [ ] byte ) ( bool , error ) {
2018-10-23 06:34:02 +00:00
return c . unseal ( key , false )
}
func ( c * Core ) UnsealWithRecoveryKeys ( key [ ] byte ) ( bool , error ) {
return c . unseal ( key , true )
}
func ( c * Core ) unseal ( key [ ] byte , useRecoveryKeys bool ) ( bool , error ) {
2015-04-08 23:43:17 +00:00
defer metrics . MeasureSince ( [ ] string { "core" , "unseal" } , time . Now ( ) )
2017-11-07 20:15:39 +00:00
c . stateLock . Lock ( )
defer c . stateLock . Unlock ( )
2019-06-21 01:32:00 +00:00
c . logger . Debug ( "unseal key supplied" )
2018-01-19 06:44:44 +00:00
ctx := context . Background ( )
2017-11-07 20:15:39 +00:00
// Explicitly check for init status. This also checks if the seal
// configuration is valid (i.e. non-nil).
2018-01-19 06:44:44 +00:00
init , err := c . Initialized ( ctx )
2017-11-07 20:15:39 +00:00
if err != nil {
return false , err
}
2019-06-20 19:14:58 +00:00
if ! init && ! c . isRaftUnseal ( ) {
2017-11-07 20:15:39 +00:00
return false , ErrNotInit
}
2015-03-12 18:20:27 +00:00
// Verify the key length
min , max := c . barrier . KeyLength ( )
max += shamir . ShareOverhead
if len ( key ) < min {
return false , & ErrInvalidKey { fmt . Sprintf ( "key is shorter than minimum %d bytes" , min ) }
}
if len ( key ) > max {
return false , & ErrInvalidKey { fmt . Sprintf ( "key is longer than maximum %d bytes" , max ) }
}
2017-11-07 20:15:39 +00:00
// Check if already unsealed
2018-07-24 20:57:25 +00:00
if ! c . Sealed ( ) {
2017-11-07 20:15:39 +00:00
return true , nil
}
2018-10-23 06:34:02 +00:00
sealToUse := c . seal
2020-02-13 21:27:31 +00:00
if c . migrationInfo != nil {
2019-10-18 18:46:00 +00:00
c . logger . Info ( "unsealing using migration seal" )
2020-02-13 21:27:31 +00:00
sealToUse = c . migrationInfo . seal
2017-11-07 20:15:39 +00:00
}
2019-10-18 18:46:00 +00:00
// unsealPart returns either a master key (legacy shamir) or an unseal
// key (new-style shamir).
2018-10-23 06:34:02 +00:00
masterKey , err := c . unsealPart ( ctx , sealToUse , key , useRecoveryKeys )
2017-02-17 01:13:19 +00:00
if err != nil {
return false , err
}
2019-06-20 19:14:58 +00:00
2017-02-17 01:13:19 +00:00
if masterKey != nil {
2020-02-13 21:27:31 +00:00
if sealToUse . BarrierType ( ) == wrapping . Shamir && c . migrationInfo == nil {
2019-10-18 18:46:00 +00:00
// If this is a legacy shamir seal this serves no purpose but it
// doesn't hurt.
2020-02-13 21:27:31 +00:00
err = sealToUse . GetAccess ( ) . Wrapper . ( * aeadwrapper . Wrapper ) . SetAESGCMKeyBytes ( masterKey )
2019-06-20 19:14:58 +00:00
if err != nil {
return false , err
}
}
if ! c . isRaftUnseal ( ) {
2020-02-13 21:27:31 +00:00
if sealToUse . BarrierType ( ) == wrapping . Shamir {
cfg , err := sealToUse . BarrierConfig ( ctx )
2019-10-18 18:46:00 +00:00
if err != nil {
return false , err
}
// If there is a stored key, retrieve it.
if cfg . StoredShares > 0 {
// Here's where we actually test that the provided unseal
// key is valid: can it decrypt the stored master key?
2020-02-13 21:27:31 +00:00
storedKeys , err := sealToUse . GetStoredKeys ( ctx )
2019-10-18 18:46:00 +00:00
if err != nil {
return false , err
}
if len ( storedKeys ) == 0 {
return false , fmt . Errorf ( "shamir seal with stored keys configured but no stored keys found" )
}
masterKey = storedKeys [ 0 ]
}
}
2019-06-20 19:14:58 +00:00
return c . unsealInternal ( ctx , masterKey )
}
2020-01-14 01:02:16 +00:00
switch c . raftInfo . joinInProgress {
case true :
// JoinRaftCluster is already trying to perform a join based on retry_join configuration.
// Inform that routine that unseal key validation is complete so that it can continue to
// try and join possible leader nodes, and wait for it to complete.
atomic . StoreUint32 ( c . postUnsealStarted , 1 )
c . logger . Info ( "waiting for raft retry join process to complete" )
<- c . raftJoinDoneCh
default :
// This is the case for manual raft join. Send the answer to the leader node and
// wait for data to start streaming in.
2020-02-13 21:27:31 +00:00
if err := c . joinRaftSendAnswer ( ctx , sealToUse . GetAccess ( ) , c . raftInfo ) ; err != nil {
2020-01-14 01:02:16 +00:00
return false , err
}
// Reset the state
c . raftInfo = nil
2019-06-20 19:14:58 +00:00
}
go func ( ) {
keyringFound := false
2020-02-13 21:27:31 +00:00
haveMasterKey := sealToUse . StoredKeysSupported ( ) != vaultseal . StoredKeysSupportedShamirMaster
2019-06-20 19:14:58 +00:00
defer func ( ) {
2019-10-18 18:46:00 +00:00
if keyringFound && haveMasterKey {
2019-06-20 19:14:58 +00:00
_ , err := c . unsealInternal ( ctx , masterKey )
if err != nil {
c . logger . Error ( "failed to unseal" , "error" , err )
}
}
} ( )
// Wait until we at least have the keyring before we attempt to
// unseal the node.
for {
2019-10-18 18:46:00 +00:00
if ! keyringFound {
keys , err := c . underlyingPhysical . List ( ctx , keyringPrefix )
if err != nil {
c . logger . Error ( "failed to list physical keys" , "error" , err )
return
}
if strutil . StrListContains ( keys , "keyring" ) {
keyringFound = true
}
2019-06-20 19:14:58 +00:00
}
2019-10-18 18:46:00 +00:00
if ! haveMasterKey {
2020-02-13 21:27:31 +00:00
keys , err := sealToUse . GetStoredKeys ( ctx )
2019-10-18 18:46:00 +00:00
if err != nil {
c . logger . Error ( "failed to read master key" , "error" , err )
return
}
if len ( keys ) > 0 {
haveMasterKey = true
masterKey = keys [ 0 ]
}
2019-06-20 19:14:58 +00:00
}
2019-10-18 18:46:00 +00:00
if keyringFound && haveMasterKey {
return
2019-06-20 19:14:58 +00:00
}
2019-10-18 18:46:00 +00:00
time . Sleep ( 1 * time . Second )
2019-06-20 19:14:58 +00:00
}
} ( )
// Return Vault as sealed since unsealing happens in background
// which gets delayed until the data from the leader is streamed to
// the follower.
return true , nil
2017-02-17 01:13:19 +00:00
}
return false , nil
}
2017-11-07 20:15:39 +00:00
// unsealPart takes in a key share, and returns the master key if the threshold
// is met. If recovery keys are supported, recovery key shares may be provided.
2018-10-23 06:34:02 +00:00
func ( c * Core ) unsealPart ( ctx context . Context , seal Seal , key [ ] byte , useRecoveryKeys bool ) ( [ ] byte , error ) {
2015-03-11 18:43:36 +00:00
// Check if we already have this piece
2017-01-17 16:47:06 +00:00
if c . unlockInfo != nil {
for _ , existing := range c . unlockInfo . Parts {
2017-02-17 01:13:19 +00:00
if subtle . ConstantTimeCompare ( existing , key ) == 1 {
return nil , nil
2017-01-17 16:47:06 +00:00
}
}
} else {
uuid , err := uuid . GenerateUUID ( )
if err != nil {
2017-02-17 01:13:19 +00:00
return nil , err
2017-01-17 16:47:06 +00:00
}
c . unlockInfo = & unlockInformation {
Nonce : uuid ,
2015-03-11 18:43:36 +00:00
}
}
// Store this key
2017-01-17 16:47:06 +00:00
c . unlockInfo . Parts = append ( c . unlockInfo . Parts , key )
2015-03-11 18:43:36 +00:00
2018-10-23 06:34:02 +00:00
var config * SealConfig
var err error
2019-06-20 19:14:58 +00:00
switch {
2020-02-13 21:27:31 +00:00
case seal . RecoveryKeySupported ( ) && ( useRecoveryKeys || c . migrationInfo != nil ) :
2018-10-23 06:34:02 +00:00
config , err = seal . RecoveryConfig ( ctx )
2019-06-20 19:14:58 +00:00
case c . isRaftUnseal ( ) :
// Ignore follower's seal config and refer to leader's barrier
// configuration.
2019-10-11 18:56:59 +00:00
config = c . raftInfo . leaderBarrierConfig
2019-06-20 19:14:58 +00:00
default :
2018-10-23 06:34:02 +00:00
config , err = seal . BarrierConfig ( ctx )
}
if err != nil {
return nil , err
}
2017-11-07 20:15:39 +00:00
// Check if we don't have enough keys to unlock, proceed through the rest of
// the call only if we have met the threshold
2017-01-17 16:47:06 +00:00
if len ( c . unlockInfo . Parts ) < config . SecretThreshold {
2016-08-19 20:45:17 +00:00
if c . logger . IsDebug ( ) {
2018-04-03 00:46:59 +00:00
c . logger . Debug ( "cannot unseal, not enough keys" , "keys" , len ( c . unlockInfo . Parts ) , "threshold" , config . SecretThreshold , "nonce" , c . unlockInfo . Nonce )
2016-08-19 20:45:17 +00:00
}
2017-02-17 01:13:19 +00:00
return nil , nil
2015-03-11 18:43:36 +00:00
}
2017-02-17 01:13:19 +00:00
// Best-effort memzero of unlock parts once we're done with them
defer func ( ) {
2017-11-07 20:15:39 +00:00
for i := range c . unlockInfo . Parts {
2017-02-17 01:13:19 +00:00
memzero ( c . unlockInfo . Parts [ i ] )
}
c . unlockInfo = nil
} ( )
2017-11-07 20:15:39 +00:00
// Recover the split key. recoveredKey is the shamir combined
// key, or the single provided key if the threshold is 1.
var recoveredKey [ ] byte
2018-10-23 06:34:02 +00:00
var masterKey [ ] byte
var recoveryKey [ ] byte
2015-03-11 18:43:36 +00:00
if config . SecretThreshold == 1 {
2017-11-07 20:15:39 +00:00
recoveredKey = make ( [ ] byte , len ( c . unlockInfo . Parts [ 0 ] ) )
copy ( recoveredKey , c . unlockInfo . Parts [ 0 ] )
2015-03-11 18:43:36 +00:00
} else {
2017-11-07 20:15:39 +00:00
recoveredKey , err = shamir . Combine ( c . unlockInfo . Parts )
2015-03-11 18:43:36 +00:00
if err != nil {
2018-04-05 15:49:21 +00:00
return nil , errwrap . Wrapf ( "failed to compute master key: {{err}}" , err )
2015-03-11 18:43:36 +00:00
}
}
2020-02-13 21:27:31 +00:00
if seal . RecoveryKeySupported ( ) && ( useRecoveryKeys || c . migrationInfo != nil ) {
2019-10-18 18:46:00 +00:00
// Verify recovery key.
2018-10-23 06:34:02 +00:00
if err := seal . VerifyRecoveryKey ( ctx , recoveredKey ) ; err != nil {
2017-11-07 20:15:39 +00:00
return nil , err
}
2018-10-23 06:34:02 +00:00
recoveryKey = recoveredKey
2017-11-07 20:15:39 +00:00
// Get stored keys and shamir combine into single master key. Unsealing with
// recovery keys currently does not support: 1) mixed stored and non-stored
// keys setup, nor 2) seals that support recovery keys but not stored keys.
2018-03-20 18:54:10 +00:00
// If insufficient shares are provided, shamir.Combine will error, and if
2017-11-07 20:15:39 +00:00
// no stored keys are found it will return masterKey as nil.
2020-01-11 01:39:52 +00:00
if seal . StoredKeysSupported ( ) == vaultseal . StoredKeysSupportedGeneric {
2018-10-23 06:34:02 +00:00
masterKeyShares , err := seal . GetStoredKeys ( ctx )
2017-11-07 20:15:39 +00:00
if err != nil {
2018-04-05 15:49:21 +00:00
return nil , errwrap . Wrapf ( "unable to retrieve stored keys: {{err}}" , err )
2017-11-07 20:15:39 +00:00
}
2019-03-04 22:11:56 +00:00
switch len ( masterKeyShares ) {
case 0 :
return nil , errors . New ( "seal returned no master key shares" )
case 1 :
2018-10-23 06:34:02 +00:00
masterKey = masterKeyShares [ 0 ]
2019-03-04 22:11:56 +00:00
default :
2018-10-23 06:34:02 +00:00
masterKey , err = shamir . Combine ( masterKeyShares )
if err != nil {
return nil , errwrap . Wrapf ( "failed to compute master key: {{err}}" , err )
}
2017-11-07 20:15:39 +00:00
}
2018-10-23 06:34:02 +00:00
}
} else {
masterKey = recoveredKey
}
2020-02-13 21:27:31 +00:00
switch {
case c . migrationInfo != nil :
// Make copies of fields that gets passed on to migration via migrationInfo to
// avoid accidental reference changes
c . migrationInfo . shamirCombinedKey = make ( [ ] byte , len ( recoveredKey ) )
copy ( c . migrationInfo . shamirCombinedKey , recoveredKey )
2020-01-11 01:39:52 +00:00
if seal . StoredKeysSupported ( ) == vaultseal . StoredKeysSupportedShamirMaster {
2020-02-13 21:27:31 +00:00
err = seal . GetAccess ( ) . Wrapper . ( * aeadwrapper . Wrapper ) . SetAESGCMKeyBytes ( recoveredKey )
2019-10-18 18:46:00 +00:00
if err != nil {
return nil , errwrap . Wrapf ( "failed to set master key in seal: {{err}}" , err )
}
storedKeys , err := seal . GetStoredKeys ( ctx )
if err != nil {
return nil , errwrap . Wrapf ( "unable to retrieve stored keys: {{err}}" , err )
}
masterKey = storedKeys [ 0 ]
}
2020-02-13 21:27:31 +00:00
c . migrationInfo . masterKey = make ( [ ] byte , len ( masterKey ) )
copy ( c . migrationInfo . masterKey , masterKey )
c . migrationInfo . recoveryKey = make ( [ ] byte , len ( recoveryKey ) )
copy ( c . migrationInfo . recoveryKey , recoveryKey )
}
2019-03-04 22:11:56 +00:00
2020-02-13 21:27:31 +00:00
return masterKey , nil
}
2019-03-04 22:11:56 +00:00
2020-02-13 21:27:31 +00:00
func ( c * Core ) migrateSeal ( ctx context . Context ) error {
if c . migrationInfo == nil {
return nil
}
2019-03-04 22:11:56 +00:00
2020-02-13 21:27:31 +00:00
existBarrierSealConfig , _ , err := c . PhysicalSealConfigs ( ctx )
if err != nil {
return fmt . Errorf ( "failed to read existing seal configuration during migration: %v" , err )
}
if existBarrierSealConfig . Type != c . migrationInfo . seal . BarrierType ( ) {
// If the existing barrier type is not the same as the type of seal we are
// migrating from, it can be concluded that migration has already been performed
c . logger . Info ( "migration is already performed since existing seal type and source seal types are different" )
c . migrationInfo = nil
atomic . StoreUint32 ( c . sealMigrated , 1 )
return nil
}
2019-03-04 22:11:56 +00:00
2020-02-13 21:27:31 +00:00
c . logger . Info ( "seal migration initiated" )
2019-03-04 22:11:56 +00:00
2020-02-13 21:27:31 +00:00
switch {
case c . migrationInfo . seal . RecoveryKeySupported ( ) && c . seal . RecoveryKeySupported ( ) :
c . logger . Info ( "migrating from one auto-unseal to another" , "from" , c . migrationInfo . seal . BarrierType ( ) , "to" , c . seal . BarrierType ( ) )
2019-03-04 22:11:56 +00:00
2020-02-13 21:27:31 +00:00
// Set the recovery and barrier keys to be the same.
recoveryKey , err := c . migrationInfo . seal . RecoveryKey ( ctx )
if err != nil {
return errwrap . Wrapf ( "error getting recovery key to set on new seal: {{err}}" , err )
}
2019-03-04 22:11:56 +00:00
2020-02-13 21:27:31 +00:00
if err := c . seal . SetRecoveryKey ( ctx , recoveryKey ) ; err != nil {
return errwrap . Wrapf ( "error setting new recovery key information during migrate: {{err}}" , err )
}
2019-03-04 22:11:56 +00:00
2020-02-13 21:27:31 +00:00
barrierKeys , err := c . migrationInfo . seal . GetStoredKeys ( ctx )
if err != nil {
return errwrap . Wrapf ( "error getting stored keys to set on new seal: {{err}}" , err )
}
2018-10-23 06:34:02 +00:00
2020-02-13 21:27:31 +00:00
if err := c . seal . SetStoredKeys ( ctx , barrierKeys ) ; err != nil {
return errwrap . Wrapf ( "error setting new barrier key information during migrate: {{err}}" , err )
}
2018-10-23 06:34:02 +00:00
2020-02-13 21:27:31 +00:00
case c . migrationInfo . seal . RecoveryKeySupported ( ) :
c . logger . Info ( "migrating from one auto-unseal to shamir" , "from" , c . migrationInfo . seal . BarrierType ( ) )
// Auto to Shamir, since recovery key isn't supported on new seal
2018-10-23 06:34:02 +00:00
2020-02-13 21:27:31 +00:00
// In this case we have to ensure that the recovery information was
// set properly.
if c . migrationInfo . recoveryKey == nil {
return errors . New ( "did not get expected recovery information to set new seal during migration" )
}
2018-10-23 06:34:02 +00:00
2020-02-13 21:27:31 +00:00
// We have recovery keys; we're going to use them as the new
// shamir KeK.
err := c . seal . GetAccess ( ) . Wrapper . ( * aeadwrapper . Wrapper ) . SetAESGCMKeyBytes ( c . migrationInfo . recoveryKey )
if err != nil {
return errwrap . Wrapf ( "failed to set master key in seal: {{err}}" , err )
}
2018-10-23 06:34:02 +00:00
2020-02-13 21:27:31 +00:00
if err := c . seal . SetStoredKeys ( ctx , [ ] [ ] byte { c . migrationInfo . masterKey } ) ; err != nil {
return errwrap . Wrapf ( "error setting new barrier key information during migrate: {{err}}" , err )
2018-10-23 06:34:02 +00:00
}
2020-02-13 21:27:31 +00:00
case c . seal . RecoveryKeySupported ( ) :
c . logger . Info ( "migrating from shamir to auto-unseal" , "to" , c . seal . BarrierType ( ) )
// Migration is happening from shamir -> auto. In this case use the shamir
// combined key that was used to store the master key as the new recovery key.
if err := c . seal . SetRecoveryKey ( ctx , c . migrationInfo . shamirCombinedKey ) ; err != nil {
return errwrap . Wrapf ( "error setting new recovery key information: {{err}}" , err )
}
2018-10-23 06:34:02 +00:00
2020-02-13 21:27:31 +00:00
// Generate a new master key
newMasterKey , err := c . barrier . GenerateKey ( c . secureRandomReader )
2018-10-23 06:34:02 +00:00
if err != nil {
2020-02-13 21:27:31 +00:00
return errwrap . Wrapf ( "error generating new master key: {{err}}" , err )
2018-10-23 06:34:02 +00:00
}
2020-02-13 21:27:31 +00:00
// Rekey the barrier
if err := c . barrier . Rekey ( ctx , newMasterKey ) ; err != nil {
return errwrap . Wrapf ( "error rekeying barrier during migration: {{err}}" , err )
2018-10-23 06:34:02 +00:00
}
2017-11-07 20:15:39 +00:00
2020-02-13 21:27:31 +00:00
// Store the new master key
if err := c . seal . SetStoredKeys ( ctx , [ ] [ ] byte { newMasterKey } ) ; err != nil {
return errwrap . Wrapf ( "error storing new master key: {{err}}" , err )
2017-11-07 20:15:39 +00:00
}
2020-02-13 21:27:31 +00:00
default :
return errors . New ( "unhandled migration case (shamir to shamir)" )
2017-11-07 20:15:39 +00:00
}
2020-02-13 21:27:31 +00:00
// At this point we've swapped things around and need to ensure we
// don't migrate again
c . migrationInfo = nil
atomic . StoreUint32 ( c . sealMigrated , 1 )
// Ensure we populate the new values
bc , err := c . seal . BarrierConfig ( ctx )
if err != nil {
return errwrap . Wrapf ( "error fetching barrier config after migration: {{err}}" , err )
}
if err := c . seal . SetBarrierConfig ( ctx , bc ) ; err != nil {
return errwrap . Wrapf ( "error storing barrier config after migration: {{err}}" , err )
}
if c . seal . RecoveryKeySupported ( ) {
rc , err := c . seal . RecoveryConfig ( ctx )
if err != nil {
return errwrap . Wrapf ( "error fetching recovery config after migration: {{err}}" , err )
}
if err := c . seal . SetRecoveryConfig ( ctx , rc ) ; err != nil {
return errwrap . Wrapf ( "error storing recovery config after migration: {{err}}" , err )
}
} else if err := c . physical . Delete ( ctx , recoverySealConfigPlaintextPath ) ; err != nil {
return errwrap . Wrapf ( "failed to delete old recovery seal configuration during migration: {{err}}" , err )
}
c . logger . Info ( "seal migration complete" )
return nil
2017-01-06 21:30:43 +00:00
}
2017-11-07 20:15:39 +00:00
// unsealInternal takes in the master key and attempts to unseal the barrier.
// N.B.: This must be called with the state write lock held.
2018-01-19 06:44:44 +00:00
func ( c * Core ) unsealInternal ( ctx context . Context , masterKey [ ] byte ) ( bool , error ) {
2017-02-17 01:13:19 +00:00
defer memzero ( masterKey )
2015-03-11 18:43:36 +00:00
// Attempt to unlock
2018-01-19 06:44:44 +00:00
if err := c . barrier . Unseal ( ctx , masterKey ) ; err != nil {
2015-03-11 18:43:36 +00:00
return false , err
}
2018-09-18 03:03:00 +00:00
if err := preUnsealInternal ( ctx , c ) ; err != nil {
return false , err
}
2019-02-15 02:14:56 +00:00
if err := c . startClusterListener ( ctx ) ; err != nil {
return false , err
}
2019-06-20 19:14:58 +00:00
if err := c . startRaftStorage ( ctx ) ; err != nil {
return false , err
}
2020-02-15 00:39:13 +00:00
if err := c . setupReplicationResolverHandler ( ) ; err != nil {
c . logger . Warn ( "failed to start replication resolver server" , "error" , err )
}
2015-04-14 21:06:15 +00:00
// Do post-unseal setup if HA is not enabled
if c . ha == nil {
2016-08-15 13:42:42 +00:00
// We still need to set up cluster info even if it's not part of a
2017-01-04 21:44:03 +00:00
// cluster right now. This also populates the cached cluster object.
2018-01-19 06:44:44 +00:00
if err := c . setupCluster ( ctx ) ; err != nil {
2018-04-03 00:46:59 +00:00
c . logger . Error ( "cluster setup failed" , "error" , err )
2016-08-15 13:42:42 +00:00
c . barrier . Seal ( )
2018-04-03 00:46:59 +00:00
c . logger . Warn ( "vault is sealed" )
2016-08-15 13:42:42 +00:00
return false , err
}
2017-02-17 01:13:19 +00:00
2020-02-13 21:27:31 +00:00
if err := c . migrateSeal ( ctx ) ; err != nil {
c . logger . Error ( "seal migration error" , "error" , err )
c . barrier . Seal ( )
c . logger . Warn ( "vault is sealed" )
return false , err
}
2018-09-18 03:03:00 +00:00
ctx , ctxCancel := context . WithCancel ( namespace . RootContext ( nil ) )
if err := c . postUnseal ( ctx , ctxCancel , standardUnsealStrategy { } ) ; err != nil {
2018-04-03 00:46:59 +00:00
c . logger . Error ( "post-unseal setup failed" , "error" , err )
2015-04-14 21:06:15 +00:00
c . barrier . Seal ( )
2018-04-03 00:46:59 +00:00
c . logger . Warn ( "vault is sealed" )
2015-04-14 21:06:15 +00:00
return false , err
}
2017-02-17 01:13:19 +00:00
2020-02-13 21:27:31 +00:00
// Force a cache bust here, which will also run migration code
if c . seal . RecoveryKeySupported ( ) {
c . seal . SetRecoveryConfig ( ctx , nil )
}
2015-12-17 18:48:08 +00:00
c . standby = false
2015-04-14 21:06:15 +00:00
} else {
// Go to standby mode, wait until we are active to unseal
c . standbyDoneCh = make ( chan struct { } )
2016-02-29 02:35:32 +00:00
c . manualStepDownCh = make ( chan struct { } )
2018-03-07 02:35:58 +00:00
c . standbyStopCh = make ( chan struct { } )
go c . runStandby ( c . standbyDoneCh , c . manualStepDownCh , c . standbyStopCh )
2015-03-11 22:19:41 +00:00
}
2018-07-24 20:57:25 +00:00
// Success!
atomic . StoreUint32 ( c . sealed , 0 )
2019-06-20 19:14:58 +00:00
if c . logger . IsInfo ( ) {
c . logger . Info ( "vault is unsealed" )
}
2019-12-06 14:46:39 +00:00
if c . serviceRegistration != nil {
2020-01-24 17:42:03 +00:00
if err := c . serviceRegistration . NotifySealedStateChange ( false ) ; err != nil {
2019-12-06 14:46:39 +00:00
if c . logger . IsWarn ( ) {
c . logger . Warn ( "failed to notify unsealed status" , "error" , err )
2016-04-28 17:56:41 +00:00
}
2016-04-23 02:55:17 +00:00
}
}
2015-03-11 18:43:36 +00:00
return true , nil
2015-03-09 23:33:27 +00:00
}
2015-03-10 00:45:34 +00:00
2016-05-20 17:03:54 +00:00
// SealWithRequest takes in a logical.Request, acquires the lock, and passes
// through to sealInternal
2018-07-24 21:50:49 +00:00
func ( c * Core ) SealWithRequest ( httpCtx context . Context , req * logical . Request ) error {
2016-05-20 17:03:54 +00:00
defer metrics . MeasureSince ( [ ] string { "core" , "seal-with-request" } , time . Now ( ) )
2018-07-24 20:57:25 +00:00
if c . Sealed ( ) {
2016-05-20 17:03:54 +00:00
return nil
}
2018-07-24 20:57:25 +00:00
c . stateLock . RLock ( )
2017-08-04 20:42:51 +00:00
// This will unlock the read lock
2018-01-19 06:44:44 +00:00
// We use background context since we may not be active
2018-09-18 03:03:00 +00:00
ctx , cancel := context . WithCancel ( namespace . RootContext ( nil ) )
2018-07-24 21:50:49 +00:00
defer cancel ( )
go func ( ) {
select {
case <- ctx . Done ( ) :
case <- httpCtx . Done ( ) :
cancel ( )
}
} ( )
// This will unlock the read lock
return c . sealInitCommon ( ctx , req )
2016-05-20 17:03:54 +00:00
}
// Seal takes in a token and creates a logical.Request, acquires the lock, and
// passes through to sealInternal
func ( c * Core ) Seal ( token string ) error {
2015-04-08 23:43:17 +00:00
defer metrics . MeasureSince ( [ ] string { "core" , "seal" } , time . Now ( ) )
2016-02-27 00:43:55 +00:00
2018-07-24 20:57:25 +00:00
if c . Sealed ( ) {
2016-05-20 17:03:54 +00:00
return nil
2015-03-10 00:45:34 +00:00
}
2015-03-31 16:59:02 +00:00
2018-07-24 20:57:25 +00:00
c . stateLock . RLock ( )
2016-01-07 20:10:05 +00:00
req := & logical . Request {
Operation : logical . UpdateOperation ,
Path : "sys/seal" ,
ClientToken : token ,
}
2017-08-04 20:42:51 +00:00
// This will unlock the read lock
2018-01-19 06:44:44 +00:00
// We use background context since we may not be active
2018-09-18 03:03:00 +00:00
return c . sealInitCommon ( namespace . RootContext ( nil ) , req )
2016-05-20 17:03:54 +00:00
}
// sealInitCommon is common logic for Seal and SealWithRequest and is used to
// re-seal the Vault. This requires the Vault to be unsealed again to perform
2017-08-04 20:42:51 +00:00
// any further operations. Note: this function will read-unlock the state lock.
2018-01-19 06:44:44 +00:00
func ( c * Core ) sealInitCommon ( ctx context . Context , req * logical . Request ) ( retErr error ) {
2016-05-20 17:03:54 +00:00
defer metrics . MeasureSince ( [ ] string { "core" , "seal-internal" } , time . Now ( ) )
2019-06-19 13:40:57 +00:00
var unlocked bool
defer func ( ) {
if ! unlocked {
c . stateLock . RUnlock ( )
}
} ( )
2016-05-20 17:03:54 +00:00
if req == nil {
retErr = multierror . Append ( retErr , errors . New ( "nil request to seal" ) )
return retErr
}
2018-04-14 01:49:40 +00:00
// Since there is no token store in standby nodes, sealing cannot be done.
// Ideally, the request has to be forwarded to leader node for validation
// and the operation should be performed. But for now, just returning with
// an error and recommending a vault restart, which essentially does the
// same thing.
if c . standby {
c . logger . Error ( "vault cannot seal when in standby mode; please restart instead" )
retErr = multierror . Append ( retErr , errors . New ( "vault cannot seal when in standby mode; please restart instead" ) )
return retErr
}
2018-09-18 03:03:00 +00:00
acl , te , entity , identityPolicies , err := c . fetchACLTokenEntryAndEntity ( ctx , req )
2015-03-31 16:59:02 +00:00
if err != nil {
2016-05-16 20:11:33 +00:00
retErr = multierror . Append ( retErr , err )
return retErr
2015-03-31 16:59:02 +00:00
}
2016-05-20 17:03:54 +00:00
// Audit-log the request before going any further
auth := & logical . Auth {
2018-09-18 03:03:00 +00:00
ClientToken : req . ClientToken ,
2018-10-15 16:56:24 +00:00
Accessor : req . ClientTokenAccessor ,
2018-04-14 01:49:40 +00:00
}
if te != nil {
2018-09-18 03:03:00 +00:00
auth . IdentityPolicies = identityPolicies [ te . NamespaceID ]
delete ( identityPolicies , te . NamespaceID )
auth . ExternalNamespacePolicies = identityPolicies
2018-06-14 13:49:33 +00:00
auth . TokenPolicies = te . Policies
2018-09-18 03:03:00 +00:00
auth . Policies = append ( te . Policies , identityPolicies [ te . NamespaceID ] ... )
2018-04-14 01:49:40 +00:00
auth . Metadata = te . Meta
auth . DisplayName = te . DisplayName
auth . EntityID = te . EntityID
2018-10-15 16:56:24 +00:00
auth . TokenType = te . Type
2016-05-20 17:03:54 +00:00
}
2019-05-22 22:52:53 +00:00
logInput := & logical . LogInput {
2018-03-02 17:18:39 +00:00
Auth : auth ,
Request : req ,
}
if err := c . auditBroker . LogRequest ( ctx , logInput , c . auditedHeaders ) ; err != nil {
2018-04-03 00:46:59 +00:00
c . logger . Error ( "failed to audit request" , "request_path" , req . Path , "error" , err )
2016-05-20 17:03:54 +00:00
retErr = multierror . Append ( retErr , errors . New ( "failed to audit request, cannot continue" ) )
return retErr
}
2018-04-14 01:49:40 +00:00
if entity != nil && entity . Disabled {
2018-06-19 16:57:19 +00:00
c . logger . Warn ( "permission denied as the entity on the token is disabled" )
retErr = multierror . Append ( retErr , logical . ErrPermissionDenied )
return retErr
}
if te != nil && te . EntityID != "" && entity == nil {
c . logger . Warn ( "permission denied as the entity on the token is invalid" )
2018-04-23 20:50:04 +00:00
retErr = multierror . Append ( retErr , logical . ErrPermissionDenied )
2018-04-14 01:49:40 +00:00
return retErr
}
2016-02-29 02:35:32 +00:00
// Attempt to use the token (decrement num_uses)
2016-05-02 07:11:14 +00:00
// On error bail out; if the token has been revoked, bail out too
2016-02-29 02:35:32 +00:00
if te != nil {
2018-01-19 06:44:44 +00:00
te , err = c . tokenStore . UseToken ( ctx , te )
2016-05-02 07:11:14 +00:00
if err != nil {
2018-04-03 00:46:59 +00:00
c . logger . Error ( "failed to use token" , "error" , err )
2016-05-16 20:11:33 +00:00
retErr = multierror . Append ( retErr , ErrInternalError )
return retErr
2016-05-02 07:11:14 +00:00
}
if te == nil {
// Token is no longer valid
2016-05-16 20:11:33 +00:00
retErr = multierror . Append ( retErr , logical . ErrPermissionDenied )
return retErr
2016-05-02 07:11:14 +00:00
}
2016-02-29 02:35:32 +00:00
}
2015-03-31 16:59:02 +00:00
2016-01-07 20:10:05 +00:00
// Verify that this operation is allowed
2018-01-19 07:43:36 +00:00
authResults := c . performPolicyChecks ( ctx , acl , te , req , entity , & PolicyCheckOpts {
2017-10-23 20:03:36 +00:00
RootPrivsRequired : true ,
} )
if ! authResults . Allowed {
2018-08-11 02:32:10 +00:00
retErr = multierror . Append ( retErr , authResults . Error )
2018-08-11 01:05:10 +00:00
if authResults . Error . ErrorOrNil ( ) == nil || authResults . DeniedError {
2018-08-11 02:32:10 +00:00
retErr = multierror . Append ( retErr , logical . ErrPermissionDenied )
2018-08-11 01:05:10 +00:00
}
2018-08-11 02:32:10 +00:00
return retErr
2016-01-07 20:10:05 +00:00
}
2018-05-10 19:50:02 +00:00
if te != nil && te . NumUses == tokenRevocationPending {
2017-11-02 13:47:02 +00:00
// Token needs to be revoked. We do this immediately here because
// we won't have a token store after sealing.
2018-08-02 01:39:39 +00:00
leaseID , err := c . expiration . CreateOrFetchRevocationLeaseByToken ( c . activeContext , te )
2018-05-10 19:50:02 +00:00
if err == nil {
2018-08-02 01:39:39 +00:00
err = c . expiration . Revoke ( c . activeContext , leaseID )
2018-05-10 19:50:02 +00:00
}
2017-11-02 13:47:02 +00:00
if err != nil {
2018-04-03 00:46:59 +00:00
c . logger . Error ( "token needed revocation before seal but failed to revoke" , "error" , err )
2017-11-02 13:47:02 +00:00
retErr = multierror . Append ( retErr , ErrInternalError )
}
}
2018-07-24 20:57:25 +00:00
// Unlock; sealing will grab the lock when needed
2019-06-19 13:40:57 +00:00
unlocked = true
2017-08-04 20:42:51 +00:00
c . stateLock . RUnlock ( )
2018-07-25 03:26:28 +00:00
sealErr := c . sealInternal ( )
2017-08-04 20:42:51 +00:00
2018-03-06 23:06:09 +00:00
if sealErr != nil {
retErr = multierror . Append ( retErr , sealErr )
2015-08-20 17:37:42 +00:00
}
2018-03-06 23:06:09 +00:00
return
2015-06-18 01:23:59 +00:00
}
2018-03-27 20:23:33 +00:00
// UIEnabled returns if the UI is enabled
func ( c * Core ) UIEnabled ( ) bool {
return c . uiConfig . Enabled ( )
}
// UIHeaders returns configured UI headers
func ( c * Core ) UIHeaders ( ) ( http . Header , error ) {
return c . uiConfig . Headers ( context . Background ( ) )
}
2016-02-27 00:43:55 +00:00
// sealInternal is an internal method used to seal the vault. It does not do
2018-07-24 20:57:25 +00:00
// any authorization checking.
2018-07-25 03:26:28 +00:00
func ( c * Core ) sealInternal ( ) error {
2019-06-21 00:55:10 +00:00
return c . sealInternalWithOptions ( true , false , true )
2018-07-25 03:26:28 +00:00
}
2019-06-21 00:55:10 +00:00
func ( c * Core ) sealInternalWithOptions ( grabStateLock , keepHALock , shutdownRaft bool ) error {
2018-07-24 20:57:25 +00:00
// Mark sealed, and if already marked return
if swapped := atomic . CompareAndSwapUint32 ( c . sealed , 0 , 1 ) ; ! swapped {
2017-08-04 20:42:51 +00:00
return nil
}
2018-09-04 17:53:40 +00:00
c . logger . Info ( "marked as sealed" )
2017-02-28 23:17:19 +00:00
2017-03-01 23:16:47 +00:00
// Clear forwarding clients
c . requestForwardingConnectionLock . Lock ( )
c . clearForwardingClients ( )
c . requestForwardingConnectionLock . Unlock ( )
2018-08-01 19:07:37 +00:00
activeCtxCancel := c . activeContextCancelFunc . Load ( ) . ( context . CancelFunc )
cancelCtxAndLock := func ( ) {
doneCh := make ( chan struct { } )
go func ( ) {
select {
case <- doneCh :
// Attempt to drain any inflight requests
case <- time . After ( DefaultMaxRequestDuration ) :
if activeCtxCancel != nil {
activeCtxCancel ( )
}
}
} ( )
c . stateLock . Lock ( )
close ( doneCh )
// Stop requests from processing
if activeCtxCancel != nil {
activeCtxCancel ( )
}
}
2015-04-14 21:06:15 +00:00
// Do pre-seal teardown if HA is not enabled
if c . ha == nil {
2018-07-30 18:54:54 +00:00
if grabStateLock {
2018-08-01 19:07:37 +00:00
cancelCtxAndLock ( )
2018-07-30 18:54:54 +00:00
defer c . stateLock . Unlock ( )
}
2017-01-11 16:13:09 +00:00
// Even in a non-HA context we key off of this for some things
c . standby = true
2018-07-24 20:57:25 +00:00
// Stop requests from processing
2018-08-01 19:07:37 +00:00
if activeCtxCancel != nil {
activeCtxCancel ( )
2018-07-24 20:57:25 +00:00
}
2015-04-14 21:06:15 +00:00
if err := c . preSeal ( ) ; err != nil {
2018-04-03 00:46:59 +00:00
c . logger . Error ( "pre-seal teardown failed" , "error" , err )
2015-04-14 21:06:15 +00:00
return fmt . Errorf ( "internal error" )
}
} else {
2018-07-24 20:57:25 +00:00
// If we are keeping the lock we already have the state write lock
// held. Otherwise grab it here so that when stopCh is triggered we are
// locked.
2018-07-25 03:26:28 +00:00
if keepHALock {
2018-06-09 19:35:22 +00:00
atomic . StoreUint32 ( c . keepHALockOnStepDown , 1 )
2018-07-25 03:26:28 +00:00
}
if grabStateLock {
2018-08-01 19:07:37 +00:00
cancelCtxAndLock ( )
2018-07-24 20:57:25 +00:00
defer c . stateLock . Unlock ( )
2018-03-07 02:35:58 +00:00
}
2018-08-01 19:07:37 +00:00
2018-03-06 23:06:09 +00:00
// If we are trying to acquire the lock, force it to return with nil so
// runStandby will exit
// If we are active, signal the standby goroutine to shut down and wait
// for completion. We have the state lock here so nothing else should
// be toggling standby status.
2018-03-07 02:35:58 +00:00
close ( c . standbyStopCh )
2018-04-03 00:46:59 +00:00
c . logger . Debug ( "finished triggering standbyStopCh for runStandby" )
2018-03-06 23:06:09 +00:00
2018-03-07 02:35:58 +00:00
// Wait for runStandby to stop
<- c . standbyDoneCh
2018-06-09 19:35:22 +00:00
atomic . StoreUint32 ( c . keepHALockOnStepDown , 0 )
2018-04-03 00:46:59 +00:00
c . logger . Debug ( "runStandby done" )
2015-03-13 18:16:24 +00:00
}
2020-02-15 00:39:13 +00:00
c . teardownReplicationResolverHandler ( )
2019-06-20 19:14:58 +00:00
// If the storage backend needs to be sealed
2019-06-21 00:55:10 +00:00
if shutdownRaft {
if raftStorage , ok := c . underlyingPhysical . ( * raft . RaftBackend ) ; ok {
2019-09-03 15:59:56 +00:00
if err := raftStorage . TeardownCluster ( c . getClusterListener ( ) ) ; err != nil {
2019-06-21 00:55:10 +00:00
c . logger . Error ( "error stopping storage cluster" , "error" , err )
return err
}
2019-06-20 19:14:58 +00:00
}
2019-06-21 00:55:10 +00:00
// Stop the cluster listener
c . stopClusterListener ( )
}
2019-02-15 02:14:56 +00:00
2018-04-03 00:46:59 +00:00
c . logger . Debug ( "sealing barrier" )
2015-03-13 18:34:40 +00:00
if err := c . barrier . Seal ( ) ; err != nil {
2018-04-03 00:46:59 +00:00
c . logger . Error ( "error sealing barrier" , "error" , err )
2015-03-13 18:34:40 +00:00
return err
}
2016-02-27 00:43:55 +00:00
2019-12-06 14:46:39 +00:00
if c . serviceRegistration != nil {
2020-01-24 17:42:03 +00:00
if err := c . serviceRegistration . NotifySealedStateChange ( true ) ; err != nil {
2019-12-06 14:46:39 +00:00
if c . logger . IsWarn ( ) {
c . logger . Warn ( "failed to notify sealed status" , "error" , err )
2016-04-28 17:56:41 +00:00
}
2016-04-23 02:55:17 +00:00
}
}
2018-09-18 03:03:00 +00:00
postSealInternal ( c )
2018-04-03 00:46:59 +00:00
c . logger . Info ( "vault is sealed" )
2017-02-28 23:17:19 +00:00
2015-03-13 18:34:40 +00:00
return nil
2015-03-10 00:45:34 +00:00
}
2015-03-11 22:19:41 +00:00
2018-09-18 03:03:00 +00:00
type UnsealStrategy interface {
unseal ( context . Context , log . Logger , * Core ) error
}
2018-04-19 17:29:43 +00:00
2018-09-18 03:03:00 +00:00
type standardUnsealStrategy struct { }
2017-01-06 20:42:18 +00:00
2018-09-18 03:03:00 +00:00
func ( s standardUnsealStrategy ) unseal ( ctx context . Context , logger log . Logger , c * Core ) error {
2017-03-01 23:16:47 +00:00
// Clear forwarding clients; we're active
c . requestForwardingConnectionLock . Lock ( )
c . clearForwardingClients ( )
c . requestForwardingConnectionLock . Unlock ( )
2018-09-18 03:03:00 +00:00
if err := postUnsealPhysical ( c ) ; err != nil {
return err
2017-02-28 23:36:28 +00:00
}
2017-02-17 01:13:19 +00:00
if err := enterprisePostUnseal ( c ) ; err != nil {
return err
}
2020-02-19 23:06:53 +00:00
if ! c . ReplicationState ( ) . HasState ( consts . ReplicationPerformanceSecondary | consts . ReplicationDRPrimary | consts . ReplicationDRSecondary ) {
// Only perf primarys should write feature flags, but we do it by
// excluding other states so that we don't have to change it when
// a non-replicated cluster becomes a primary.
if err := c . persistFeatureFlags ( ctx ) ; err != nil {
return err
}
}
2018-09-18 03:03:00 +00:00
if ! c . IsDRSecondary ( ) {
if err := c . ensureWrappingKey ( ctx ) ; err != nil {
return err
}
2017-01-04 21:44:03 +00:00
}
2018-11-07 01:21:24 +00:00
if err := c . setupPluginCatalog ( ctx ) ; err != nil {
2017-08-16 02:10:32 +00:00
return err
}
2018-08-01 19:07:37 +00:00
if err := c . loadMounts ( ctx ) ; err != nil {
2015-03-11 22:19:41 +00:00
return err
}
2019-10-27 20:30:38 +00:00
if err := enterpriseSetupFilteredPaths ( c ) ; err != nil {
return err
}
2018-08-01 19:07:37 +00:00
if err := c . setupMounts ( ctx ) ; err != nil {
2015-03-11 22:50:27 +00:00
return err
}
2018-08-01 19:07:37 +00:00
if err := c . setupPolicyStore ( ctx ) ; err != nil {
2015-11-02 16:01:00 +00:00
return err
2015-03-18 21:00:42 +00:00
}
2018-08-01 19:07:37 +00:00
if err := c . loadCORSConfig ( ctx ) ; err != nil {
2017-06-17 04:04:55 +00:00
return err
}
2019-03-05 19:55:07 +00:00
if err := c . loadCurrentRequestCounters ( ctx , time . Now ( ) ) ; err != nil {
return err
}
2018-08-01 19:07:37 +00:00
if err := c . loadCredentials ( ctx ) ; err != nil {
2015-11-02 16:01:00 +00:00
return err
2015-03-18 22:46:07 +00:00
}
2019-10-27 20:30:38 +00:00
if err := enterpriseSetupFilteredPaths ( c ) ; err != nil {
return err
}
2018-08-01 19:07:37 +00:00
if err := c . setupCredentials ( ctx ) ; err != nil {
2015-11-02 16:01:00 +00:00
return err
2015-03-18 22:30:31 +00:00
}
2018-09-18 03:03:00 +00:00
if ! c . IsDRSecondary ( ) {
if err := c . startRollback ( ) ; err != nil {
return err
}
if err := c . setupExpiration ( expireLeaseStrategyRevoke ) ; err != nil {
return err
}
if err := c . loadAudits ( ctx ) ; err != nil {
return err
}
if err := c . setupAudits ( ctx ) ; err != nil {
return err
}
if err := c . loadIdentityStoreArtifacts ( ctx ) ; err != nil {
return err
}
if err := loadMFAConfigs ( ctx , c ) ; err != nil {
return err
}
if err := c . setupAuditedHeadersConfig ( ctx ) ; err != nil {
return err
}
} else {
c . auditBroker = NewAuditBroker ( c . logger )
2017-09-01 05:02:03 +00:00
}
2018-09-18 03:03:00 +00:00
2019-09-03 15:59:56 +00:00
if c . getClusterListener ( ) != nil && ( c . ha != nil || shouldStartClusterListener ( c ) ) {
2019-07-03 20:56:30 +00:00
if err := c . setupRaftActiveNode ( ctx ) ; err != nil {
return err
}
2019-06-27 17:00:03 +00:00
2019-02-15 02:14:56 +00:00
if err := c . startForwarding ( ctx ) ; err != nil {
2018-09-18 03:03:00 +00:00
return err
}
2019-06-20 19:14:58 +00:00
2015-03-24 01:00:14 +00:00
}
2018-09-18 03:03:00 +00:00
c . clusterParamsLock . Lock ( )
defer c . clusterParamsLock . Unlock ( )
if err := startReplication ( c ) ; err != nil {
2015-03-27 21:00:38 +00:00
return err
}
2018-09-18 03:03:00 +00:00
return nil
}
2019-10-03 20:40:18 +00:00
// postUnseal is invoked on the active node after the barrier is unsealed, but before
2018-09-18 03:03:00 +00:00
// allowing any user operations. This allows us to setup any state that
// requires the Vault to be unsealed such as mount tables, logical backends,
// credential stores, etc.
func ( c * Core ) postUnseal ( ctx context . Context , ctxCancelFunc context . CancelFunc , unsealer UnsealStrategy ) ( retErr error ) {
defer metrics . MeasureSince ( [ ] string { "core" , "post_unseal" } , time . Now ( ) )
// Clear any out
c . postUnsealFuncs = nil
// Create a new request context
c . activeContext = ctx
c . activeContextCancelFunc . Store ( ctxCancelFunc )
defer func ( ) {
if retErr != nil {
ctxCancelFunc ( )
c . preSeal ( )
}
} ( )
c . logger . Info ( "post-unseal setup starting" )
// Enable the cache
c . physicalCache . Purge ( ctx )
if ! c . cachingDisabled {
c . physicalCache . SetEnabled ( true )
2015-03-27 21:00:38 +00:00
}
2018-09-18 03:03:00 +00:00
// Purge these for safety in case of a rekey
c . seal . SetBarrierConfig ( ctx , nil )
if c . seal . RecoveryKeySupported ( ) {
c . seal . SetRecoveryConfig ( ctx , nil )
2017-10-23 20:03:36 +00:00
}
2018-09-18 03:03:00 +00:00
if err := unsealer . unseal ( ctx , c . logger , c ) ; err != nil {
2017-02-02 19:49:20 +00:00
return err
}
2017-04-04 00:52:29 +00:00
2019-10-03 20:40:18 +00:00
// Automatically re-encrypt the keys used for auto unsealing when the
// seal's encryption key changes. The regular rotation of cryptographic
// keys is a NIST recommendation. Access to prior keys for decryption
// is normally supported for a configurable time period. Re-encrypting
// the keys used for auto unsealing ensures Vault and its data will
// continue to be accessible even after prior seal keys are destroyed.
if seal , ok := c . seal . ( * autoSeal ) ; ok {
if err := seal . UpgradeKeys ( c . activeContext ) ; err != nil {
c . logger . Warn ( "post-unseal upgrade seal keys failed" , "error" , err )
}
}
2015-04-08 23:43:17 +00:00
c . metricsCh = make ( chan struct { } )
go c . emitMetrics ( c . metricsCh )
2018-04-19 17:29:43 +00:00
// This is intentionally the last block in this function. We want to allow
// writes just before allowing client requests, to ensure everything has
// been set up properly before any writes can have happened.
for _ , v := range c . postUnsealFuncs {
v ( )
}
2019-10-16 16:52:37 +00:00
if atomic . LoadUint32 ( c . sealMigrated ) == 1 {
defer func ( ) { atomic . StoreUint32 ( c . sealMigrated , 0 ) } ( )
2019-10-16 18:00:00 +00:00
if err := c . postSealMigration ( ctx ) ; err != nil {
c . logger . Warn ( "post-unseal post seal migration failed" , "error" , err )
}
2019-10-16 16:52:37 +00:00
}
2018-04-03 00:46:59 +00:00
c . logger . Info ( "post-unseal setup complete" )
2015-03-11 22:19:41 +00:00
return nil
}
2015-03-13 18:16:24 +00:00
// preSeal is invoked before the barrier is sealed, allowing
// for any state teardown required.
2015-11-02 18:29:18 +00:00
func ( c * Core ) preSeal ( ) error {
2015-04-08 23:43:17 +00:00
defer metrics . MeasureSince ( [ ] string { "core" , "pre_seal" } , time . Now ( ) )
2018-04-03 00:46:59 +00:00
c . logger . Info ( "pre-seal teardown starting" )
2015-05-28 19:07:52 +00:00
2018-04-19 17:29:43 +00:00
// Clear any pending funcs
c . postUnsealFuncs = nil
2015-05-28 19:07:52 +00:00
// Clear any rekey progress
2016-04-04 14:44:22 +00:00
c . barrierRekeyConfig = nil
c . recoveryRekeyConfig = nil
2015-05-28 19:07:52 +00:00
2015-04-08 23:43:17 +00:00
if c . metricsCh != nil {
close ( c . metricsCh )
c . metricsCh = nil
}
2015-11-02 18:29:18 +00:00
var result error
2017-02-17 01:13:19 +00:00
2019-06-21 00:55:10 +00:00
c . stopForwarding ( )
2019-07-03 20:56:30 +00:00
c . stopRaftActiveNode ( )
2019-06-27 17:00:03 +00:00
2018-09-18 03:03:00 +00:00
c . clusterParamsLock . Lock ( )
if err := stopReplication ( c ) ; err != nil {
result = multierror . Append ( result , errwrap . Wrapf ( "error stopping replication: {{err}}" , err ) )
}
c . clusterParamsLock . Unlock ( )
2015-03-27 21:00:38 +00:00
if err := c . teardownAudits ( ) ; err != nil {
2016-08-19 20:45:17 +00:00
result = multierror . Append ( result , errwrap . Wrapf ( "error tearing down audits: {{err}}" , err ) )
2015-03-27 21:00:38 +00:00
}
2015-03-24 01:00:14 +00:00
if err := c . stopExpiration ( ) ; err != nil {
2016-08-19 20:45:17 +00:00
result = multierror . Append ( result , errwrap . Wrapf ( "error stopping expiration: {{err}}" , err ) )
2015-03-24 01:00:14 +00:00
}
2018-08-01 19:07:37 +00:00
if err := c . teardownCredentials ( context . Background ( ) ) ; err != nil {
2016-08-19 20:45:17 +00:00
result = multierror . Append ( result , errwrap . Wrapf ( "error tearing down credentials: {{err}}" , err ) )
2015-03-18 22:30:31 +00:00
}
2015-03-18 21:00:42 +00:00
if err := c . teardownPolicyStore ( ) ; err != nil {
2016-08-19 20:45:17 +00:00
result = multierror . Append ( result , errwrap . Wrapf ( "error tearing down policy store: {{err}}" , err ) )
2015-03-18 21:00:42 +00:00
}
2015-03-17 23:23:58 +00:00
if err := c . stopRollback ( ) ; err != nil {
2016-08-19 20:45:17 +00:00
result = multierror . Append ( result , errwrap . Wrapf ( "error stopping rollback: {{err}}" , err ) )
2015-03-17 23:23:58 +00:00
}
2018-08-01 19:07:37 +00:00
if err := c . unloadMounts ( context . Background ( ) ) ; err != nil {
2016-08-19 20:45:17 +00:00
result = multierror . Append ( result , errwrap . Wrapf ( "error unloading mounts: {{err}}" , err ) )
2015-03-13 18:16:24 +00:00
}
2017-02-17 01:13:19 +00:00
if err := enterprisePreSeal ( c ) ; err != nil {
result = multierror . Append ( result , err )
}
2018-09-18 03:03:00 +00:00
preSealPhysical ( c )
2018-01-26 03:21:51 +00:00
2018-04-03 00:46:59 +00:00
c . logger . Info ( "pre-seal teardown complete" )
2015-11-02 18:29:18 +00:00
return result
2015-03-13 18:16:24 +00:00
}
2015-04-08 23:43:17 +00:00
2017-02-17 01:13:19 +00:00
func enterprisePostUnsealImpl ( c * Core ) error {
return nil
}
func enterprisePreSealImpl ( c * Core ) error {
return nil
}
2019-10-27 20:30:38 +00:00
func enterpriseSetupFilteredPathsImpl ( c * Core ) error {
return nil
}
2017-02-17 01:13:19 +00:00
func startReplicationImpl ( c * Core ) error {
return nil
}
func stopReplicationImpl ( c * Core ) error {
return nil
}
2018-03-20 18:54:10 +00:00
// emitMetrics is used to periodically expose metrics while running
2015-04-08 23:43:17 +00:00
func ( c * Core ) emitMetrics ( stopCh chan struct { } ) {
2019-03-05 19:55:07 +00:00
emitTimer := time . Tick ( time . Second )
writeTimer := time . Tick ( c . counters . syncInterval )
2015-04-08 23:43:17 +00:00
for {
select {
2019-03-05 19:55:07 +00:00
case <- emitTimer :
2015-10-12 20:33:54 +00:00
c . metricsMutex . Lock ( )
if c . expiration != nil {
c . expiration . emitMetrics ( )
}
c . metricsMutex . Unlock ( )
2019-03-05 19:55:07 +00:00
case <- writeTimer :
2019-06-05 16:26:29 +00:00
if stopped := grabLockOrStop ( c . stateLock . RLock , c . stateLock . RUnlock , stopCh ) ; stopped {
// Go through the loop again, this time the stop channel case
// should trigger
continue
}
2019-03-05 19:55:07 +00:00
if c . perfStandby {
syncCounter ( c )
} else {
err := c . saveCurrentRequestCounters ( context . Background ( ) , time . Now ( ) )
if err != nil {
c . logger . Error ( "writing request counters to barrier" , "err" , err )
}
}
2019-06-05 16:26:29 +00:00
c . stateLock . RUnlock ( )
2019-03-05 19:55:07 +00:00
2015-04-08 23:43:17 +00:00
case <- stopCh :
return
}
}
}
2016-04-04 14:44:22 +00:00
2017-02-16 20:15:02 +00:00
func ( c * Core ) ReplicationState ( ) consts . ReplicationState {
2018-01-16 18:51:55 +00:00
return consts . ReplicationState ( atomic . LoadUint32 ( c . replicationState ) )
2017-02-16 20:15:02 +00:00
}
2018-01-20 00:24:04 +00:00
func ( c * Core ) ActiveNodeReplicationState ( ) consts . ReplicationState {
return consts . ReplicationState ( atomic . LoadUint32 ( c . activeNodeReplicationState ) )
}
2016-04-04 14:44:22 +00:00
func ( c * Core ) SealAccess ( ) * SealAccess {
2017-10-23 20:03:36 +00:00
return NewSealAccess ( c . seal )
2016-04-04 14:44:22 +00:00
}
2016-08-15 13:42:42 +00:00
2019-09-18 19:07:18 +00:00
// StorageType returns a string equal to the storage configuration's type.
func ( c * Core ) StorageType ( ) string {
return c . storageType
}
2016-08-19 20:45:17 +00:00
func ( c * Core ) Logger ( ) log . Logger {
2016-08-15 13:42:42 +00:00
return c . logger
}
2016-08-15 20:01:15 +00:00
func ( c * Core ) BarrierKeyLength ( ) ( min , max int ) {
min , max = c . barrier . KeyLength ( )
max += shamir . ShareOverhead
return
}
2017-02-02 19:49:20 +00:00
func ( c * Core ) AuditedHeadersConfig ( ) * AuditedHeadersConfig {
return c . auditedHeaders
}
2017-03-01 17:39:42 +00:00
2018-09-18 03:03:00 +00:00
func waitUntilWALShippedImpl ( ctx context . Context , c * Core , index uint64 ) bool {
return true
}
2019-07-22 17:11:00 +00:00
func merkleRootImpl ( c * Core ) string {
return ""
}
2018-10-16 13:38:44 +00:00
func lastWALImpl ( c * Core ) uint64 {
return 0
}
2019-07-22 17:11:00 +00:00
func lastPerformanceWALImpl ( c * Core ) uint64 {
return 0
}
2017-03-01 17:42:10 +00:00
func lastRemoteWALImpl ( c * Core ) uint64 {
2017-03-01 17:39:42 +00:00
return 0
}
2017-10-23 20:03:36 +00:00
2018-10-23 06:34:02 +00:00
func ( c * Core ) PhysicalSealConfigs ( ctx context . Context ) ( * SealConfig , * SealConfig , error ) {
pe , err := c . physical . Get ( ctx , barrierSealConfigPath )
if err != nil {
return nil , nil , errwrap . Wrapf ( "failed to fetch barrier seal configuration at migration check time: {{err}}" , err )
}
if pe == nil {
return nil , nil , nil
}
barrierConf := new ( SealConfig )
if err := jsonutil . DecodeJSON ( pe . Value , barrierConf ) ; err != nil {
return nil , nil , errwrap . Wrapf ( "failed to decode barrier seal configuration at migration check time: {{err}}" , err )
}
2018-12-14 00:44:56 +00:00
err = barrierConf . Validate ( )
if err != nil {
return nil , nil , errwrap . Wrapf ( "failed to validate barrier seal configuration at migration check time: {{err}}" , err )
}
// In older versions of vault the default seal would not store a type. This
2019-03-19 13:32:45 +00:00
// is here to offer backwards compatibility for older seal configs.
2018-12-14 00:44:56 +00:00
if barrierConf . Type == "" {
2020-01-11 01:39:52 +00:00
barrierConf . Type = wrapping . Shamir
2018-12-14 00:44:56 +00:00
}
2018-10-23 06:34:02 +00:00
var recoveryConf * SealConfig
pe , err = c . physical . Get ( ctx , recoverySealConfigPlaintextPath )
if err != nil {
return nil , nil , errwrap . Wrapf ( "failed to fetch seal configuration at migration check time: {{err}}" , err )
}
if pe != nil {
recoveryConf = & SealConfig { }
if err := jsonutil . DecodeJSON ( pe . Value , recoveryConf ) ; err != nil {
return nil , nil , errwrap . Wrapf ( "failed to decode seal configuration at migration check time: {{err}}" , err )
}
2018-12-14 00:44:56 +00:00
err = recoveryConf . Validate ( )
if err != nil {
return nil , nil , errwrap . Wrapf ( "failed to validate seal configuration at migration check time: {{err}}" , err )
}
// In older versions of vault the default seal would not store a type. This
2019-03-19 13:32:45 +00:00
// is here to offer backwards compatibility for older seal configs.
2018-12-14 00:44:56 +00:00
if recoveryConf . Type == "" {
2020-01-11 01:39:52 +00:00
recoveryConf . Type = wrapping . Shamir
2018-12-14 00:44:56 +00:00
}
2018-10-23 06:34:02 +00:00
}
return barrierConf , recoveryConf , nil
}
2019-03-04 22:11:56 +00:00
func ( c * Core ) SetSealsForMigration ( migrationSeal , newSeal , unwrapSeal Seal ) {
2018-10-23 06:34:02 +00:00
c . stateLock . Lock ( )
defer c . stateLock . Unlock ( )
2019-03-04 22:11:56 +00:00
c . unwrapSeal = unwrapSeal
if c . unwrapSeal != nil {
c . unwrapSeal . SetCore ( c )
}
if newSeal != nil && migrationSeal != nil {
2020-02-13 21:27:31 +00:00
c . migrationInfo = & migrationInformation {
seal : migrationSeal ,
}
c . migrationInfo . seal . SetCore ( c )
2019-03-04 22:11:56 +00:00
c . seal = newSeal
c . seal . SetCore ( c )
2020-02-13 21:27:31 +00:00
c . logger . Warn ( "entering seal migration mode; Vault will not automatically unseal even if using an autoseal" , "from_barrier_type" , c . migrationInfo . seal . BarrierType ( ) , "to_barrier_type" , c . seal . BarrierType ( ) )
2019-10-15 19:48:23 +00:00
c . initSealsForMigration ( )
2019-03-04 22:11:56 +00:00
}
2018-10-23 06:34:02 +00:00
}
2019-10-23 16:52:28 +00:00
// unsealKeyToMasterKey takes a key provided by the user, either a recovery key
// if using an autoseal or an unseal key with Shamir. It returns a nil error
// if the key is valid and an error otherwise. It also returns the master key
// that can be used to unseal the barrier.
func ( c * Core ) unsealKeyToMasterKey ( ctx context . Context , combinedKey [ ] byte ) ( [ ] byte , error ) {
switch c . seal . StoredKeysSupported ( ) {
2020-01-11 01:39:52 +00:00
case vaultseal . StoredKeysSupportedGeneric :
2019-10-23 16:52:28 +00:00
if err := c . seal . VerifyRecoveryKey ( ctx , combinedKey ) ; err != nil {
return nil , errwrap . Wrapf ( "recovery key verification failed: {{err}}" , err )
}
storedKeys , err := c . seal . GetStoredKeys ( ctx )
if err == nil && len ( storedKeys ) != 1 {
err = fmt . Errorf ( "expected exactly one stored key, got %d" , len ( storedKeys ) )
}
if err != nil {
return nil , errwrap . Wrapf ( "unable to retrieve stored keys" , err )
}
return storedKeys [ 0 ] , nil
2020-01-11 01:39:52 +00:00
case vaultseal . StoredKeysSupportedShamirMaster :
testseal := NewDefaultSeal ( & vaultseal . Access {
Wrapper : aeadwrapper . NewWrapper ( & wrapping . WrapperOptions {
Logger : c . logger . Named ( "testseal" ) ,
} ) ,
} )
2019-10-23 16:52:28 +00:00
testseal . SetCore ( c )
cfg , err := c . seal . BarrierConfig ( ctx )
if err != nil {
return nil , errwrap . Wrapf ( "failed to setup test barrier config: {{err}}" , err )
}
testseal . SetCachedBarrierConfig ( cfg )
2020-01-11 01:39:52 +00:00
err = testseal . GetAccess ( ) . Wrapper . ( * aeadwrapper . Wrapper ) . SetAESGCMKeyBytes ( combinedKey )
2019-10-23 16:52:28 +00:00
if err != nil {
return nil , errwrap . Wrapf ( "failed to setup unseal key: {{err}}" , err )
}
storedKeys , err := testseal . GetStoredKeys ( ctx )
if err == nil && len ( storedKeys ) != 1 {
err = fmt . Errorf ( "expected exactly one stored key, got %d" , len ( storedKeys ) )
}
if err != nil {
return nil , errwrap . Wrapf ( "unable to retrieve stored keys" , err )
}
return storedKeys [ 0 ] , nil
2020-01-11 01:39:52 +00:00
case vaultseal . StoredKeysNotSupported :
2019-10-23 16:52:28 +00:00
return combinedKey , nil
}
return nil , fmt . Errorf ( "invalid seal" )
}
2018-10-23 06:34:02 +00:00
func ( c * Core ) IsInSealMigration ( ) bool {
c . stateLock . RLock ( )
defer c . stateLock . RUnlock ( )
2020-02-13 21:27:31 +00:00
return c . migrationInfo != nil
2018-10-23 06:34:02 +00:00
}
2017-10-23 20:03:36 +00:00
func ( c * Core ) BarrierEncryptorAccess ( ) * BarrierEncryptorAccess {
return NewBarrierEncryptorAccess ( c . barrier )
}
func ( c * Core ) PhysicalAccess ( ) * physical . PhysicalAccess {
return physical . NewPhysicalAccess ( c . physical )
}
func ( c * Core ) RouterAccess ( ) * RouterAccess {
return NewRouterAccess ( c )
}
2018-01-03 20:07:13 +00:00
// IsDRSecondary returns if the current cluster state is a DR secondary.
func ( c * Core ) IsDRSecondary ( ) bool {
return c . ReplicationState ( ) . HasState ( consts . ReplicationDRSecondary )
}
2018-09-05 19:52:54 +00:00
func ( c * Core ) AddLogger ( logger log . Logger ) {
c . allLoggersLock . Lock ( )
defer c . allLoggersLock . Unlock ( )
c . allLoggers = append ( c . allLoggers , logger )
}
func ( c * Core ) SetLogLevel ( level log . Level ) {
c . allLoggersLock . RLock ( )
defer c . allLoggersLock . RUnlock ( )
for _ , logger := range c . allLoggers {
logger . SetLevel ( level )
}
}
2018-11-07 01:21:24 +00:00
2019-10-08 17:57:15 +00:00
// SetConfig sets core's config object to the newly provided config.
func ( c * Core ) SetConfig ( conf * server . Config ) {
2020-04-16 23:34:46 +00:00
c . rawConfig . Store ( conf )
2019-10-08 17:57:15 +00:00
}
// SanitizedConfig returns a sanitized version of the current config.
// See server.Config.Sanitized for specific values omitted.
func ( c * Core ) SanitizedConfig ( ) map [ string ] interface { } {
2020-04-16 23:34:46 +00:00
conf := c . rawConfig . Load ( )
if conf == nil {
return nil
}
return conf . ( * server . Config ) . Sanitized ( )
2019-10-08 17:57:15 +00:00
}
2019-10-04 07:29:51 +00:00
// MetricsHelper returns the global metrics helper which allows external
// packages to access Vault's internal metrics.
func ( c * Core ) MetricsHelper ( ) * metricsutil . MetricsHelper {
return c . metricsHelper
}
2018-11-07 01:21:24 +00:00
// BuiltinRegistry is an interface that allows the "vault" package to use
// the registry of builtin plugins without getting an import cycle. It
// also allows for mocking the registry easily.
type BuiltinRegistry interface {
Contains ( name string , pluginType consts . PluginType ) bool
Get ( name string , pluginType consts . PluginType ) ( func ( ) ( interface { } , error ) , bool )
Keys ( pluginType consts . PluginType ) [ ] string
}
2020-02-06 16:56:37 +00:00
func ( c * Core ) AuditLogger ( ) AuditLogger {
return & basicAuditor { c : c }
}
2020-02-19 23:06:53 +00:00
type FeatureFlags struct {
NamespacesCubbyholesLocal bool ` json:"namespace_cubbyholes_local" `
}
func ( c * Core ) persistFeatureFlags ( ctx context . Context ) error {
c . logger . Debug ( "persisting feature flags" )
json , err := jsonutil . EncodeJSON ( & FeatureFlags { NamespacesCubbyholesLocal : ! c . PR1103disabled } )
if err != nil {
return err
}
return c . barrier . Put ( ctx , & logical . StorageEntry {
Key : consts . CoreFeatureFlagPath ,
Value : json ,
} )
}
func ( c * Core ) readFeatureFlags ( ctx context . Context ) ( * FeatureFlags , error ) {
entry , err := c . barrier . Get ( ctx , consts . CoreFeatureFlagPath )
if err != nil {
return nil , err
}
var flags FeatureFlags
if entry != nil {
err = jsonutil . DecodeJSON ( entry . Value , & flags )
if err != nil {
return nil , err
}
}
return & flags , nil
}