2015-03-02 18:48:53 +00:00
|
|
|
package physical
|
|
|
|
|
2016-04-26 03:10:32 +00:00
|
|
|
import (
|
2017-08-03 17:24:27 +00:00
|
|
|
"strings"
|
2016-07-30 17:17:29 +00:00
|
|
|
"sync"
|
2016-08-19 20:45:17 +00:00
|
|
|
|
|
|
|
log "github.com/mgutz/logxi/v1"
|
2016-04-26 03:10:32 +00:00
|
|
|
)
|
2015-03-05 21:47:10 +00:00
|
|
|
|
2015-11-03 19:48:05 +00:00
|
|
|
const DefaultParallelOperations = 128
|
|
|
|
|
2017-02-17 14:15:35 +00:00
|
|
|
// The operation type
|
|
|
|
type Operation string
|
|
|
|
|
|
|
|
const (
|
|
|
|
DeleteOperation Operation = "delete"
|
|
|
|
GetOperation = "get"
|
|
|
|
ListOperation = "list"
|
|
|
|
PutOperation = "put"
|
|
|
|
)
|
|
|
|
|
2016-04-23 02:55:17 +00:00
|
|
|
// ShutdownSignal
|
|
|
|
type ShutdownChannel chan struct{}
|
|
|
|
|
2015-03-02 18:48:53 +00:00
|
|
|
// Backend is the interface required for a physical
|
|
|
|
// backend. A physical backend is used to durably store
|
2015-04-22 21:59:16 +00:00
|
|
|
// data outside of Vault. As such, it is completely untrusted,
|
2015-03-02 18:48:53 +00:00
|
|
|
// and is only accessed via a security barrier. The backends
|
|
|
|
// must represent keys in a hierarchical manner. All methods
|
|
|
|
// are expected to be thread safe.
|
|
|
|
type Backend interface {
|
|
|
|
// Put is used to insert or update an entry
|
|
|
|
Put(entry *Entry) error
|
|
|
|
|
|
|
|
// Get is used to fetch an entry
|
|
|
|
Get(key string) (*Entry, error)
|
|
|
|
|
|
|
|
// Delete is used to permanently delete an entry
|
|
|
|
Delete(key string) error
|
|
|
|
|
|
|
|
// List is used ot list all the keys under a given
|
|
|
|
// prefix, up to the next prefix.
|
|
|
|
List(prefix string) ([]string, error)
|
|
|
|
}
|
|
|
|
|
2016-05-15 16:58:36 +00:00
|
|
|
// HABackend is an extensions to the standard physical
|
2015-04-14 18:49:46 +00:00
|
|
|
// backend to support high-availability. Vault only expects to
|
|
|
|
// use mutual exclusion to allow multiple instances to act as a
|
|
|
|
// hot standby for a leader that services all requests.
|
|
|
|
type HABackend interface {
|
|
|
|
// LockWith is used for mutual exclusion based on the given key.
|
2015-04-14 23:36:53 +00:00
|
|
|
LockWith(key, value string) (Lock, error)
|
2016-07-18 17:19:58 +00:00
|
|
|
|
|
|
|
// Whether or not HA functionality is enabled
|
|
|
|
HAEnabled() bool
|
2015-04-14 18:49:46 +00:00
|
|
|
}
|
|
|
|
|
2017-01-06 20:42:18 +00:00
|
|
|
// Purgable is an optional interface for backends that support
|
|
|
|
// purging of their caches.
|
|
|
|
type Purgable interface {
|
|
|
|
Purge()
|
|
|
|
}
|
|
|
|
|
2016-08-15 13:42:42 +00:00
|
|
|
// RedirectDetect is an optional interface that an HABackend
|
|
|
|
// can implement. If they do, a redirect address can be automatically
|
2015-05-02 22:34:29 +00:00
|
|
|
// detected.
|
2016-08-15 13:42:42 +00:00
|
|
|
type RedirectDetect interface {
|
2015-05-02 22:34:29 +00:00
|
|
|
// DetectHostAddr is used to detect the host address
|
|
|
|
DetectHostAddr() (string, error)
|
2016-04-23 02:55:17 +00:00
|
|
|
}
|
|
|
|
|
2016-04-28 17:56:41 +00:00
|
|
|
// Callback signatures for RunServiceDiscovery
|
2017-08-03 17:24:27 +00:00
|
|
|
type ActiveFunction func() bool
|
|
|
|
type SealedFunction func() bool
|
2016-04-28 17:56:41 +00:00
|
|
|
|
2016-04-23 02:55:17 +00:00
|
|
|
// ServiceDiscovery is an optional interface that an HABackend can implement.
|
|
|
|
// If they do, the state of a backend is advertised to the service discovery
|
|
|
|
// network.
|
|
|
|
type ServiceDiscovery interface {
|
2016-04-28 17:56:41 +00:00
|
|
|
// NotifyActiveStateChange is used by Core to notify a backend
|
|
|
|
// capable of ServiceDiscovery that this Vault instance has changed
|
|
|
|
// its status to active or standby.
|
|
|
|
NotifyActiveStateChange() error
|
2016-04-23 02:55:17 +00:00
|
|
|
|
2016-04-28 17:56:41 +00:00
|
|
|
// NotifySealedStateChange is used by Core to notify a backend
|
|
|
|
// capable of ServiceDiscovery that Vault has changed its Sealed
|
|
|
|
// status to sealed or unsealed.
|
|
|
|
NotifySealedStateChange() error
|
2016-04-23 02:55:17 +00:00
|
|
|
|
|
|
|
// Run executes any background service discovery tasks until the
|
|
|
|
// shutdown channel is closed.
|
2017-08-03 17:24:27 +00:00
|
|
|
RunServiceDiscovery(waitGroup *sync.WaitGroup, shutdownCh ShutdownChannel, redirectAddr string, activeFunc ActiveFunction, sealedFunc SealedFunction) error
|
2015-05-02 22:34:29 +00:00
|
|
|
}
|
|
|
|
|
2015-04-14 18:49:46 +00:00
|
|
|
type Lock interface {
|
|
|
|
// Lock is used to acquire the given lock
|
|
|
|
// The stopCh is optional and if closed should interrupt the lock
|
|
|
|
// acquisition attempt. The return struct should be closed when
|
|
|
|
// leadership is lost.
|
|
|
|
Lock(stopCh <-chan struct{}) (<-chan struct{}, error)
|
|
|
|
|
|
|
|
// Unlock is used to release the lock
|
|
|
|
Unlock() error
|
2015-04-14 23:36:53 +00:00
|
|
|
|
|
|
|
// Returns the value of the lock and if it is held
|
|
|
|
Value() (bool, string, error)
|
2015-04-14 18:49:46 +00:00
|
|
|
}
|
|
|
|
|
2015-03-02 18:48:53 +00:00
|
|
|
// Entry is used to represent data stored by the physical backend
|
|
|
|
type Entry struct {
|
2017-10-23 20:49:46 +00:00
|
|
|
Key string
|
|
|
|
Value []byte
|
|
|
|
SealWrap bool `json:"seal_wrap,omitempty"`
|
2015-03-02 18:48:53 +00:00
|
|
|
}
|
2015-03-05 21:47:10 +00:00
|
|
|
|
|
|
|
// Factory is the factory function to create a physical backend.
|
2016-08-19 20:45:17 +00:00
|
|
|
type Factory func(config map[string]string, logger log.Logger) (Backend, error)
|
2015-03-05 21:47:10 +00:00
|
|
|
|
2016-11-28 23:34:58 +00:00
|
|
|
// PermitPool is used to limit maximum outstanding requests
|
2015-11-03 16:47:16 +00:00
|
|
|
type PermitPool struct {
|
2015-11-04 17:27:13 +00:00
|
|
|
sem chan int
|
2015-11-03 16:47:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// NewPermitPool returns a new permit pool with the provided
|
|
|
|
// number of permits
|
|
|
|
func NewPermitPool(permits int) *PermitPool {
|
|
|
|
if permits < 1 {
|
2015-11-03 19:48:05 +00:00
|
|
|
permits = DefaultParallelOperations
|
2015-11-03 16:47:16 +00:00
|
|
|
}
|
|
|
|
return &PermitPool{
|
2015-11-04 17:27:13 +00:00
|
|
|
sem: make(chan int, permits),
|
2015-11-03 16:47:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Acquire returns when a permit has been acquired
|
|
|
|
func (c *PermitPool) Acquire() {
|
2015-11-04 17:27:13 +00:00
|
|
|
c.sem <- 1
|
2015-11-03 16:47:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Release returns a permit to the pool
|
|
|
|
func (c *PermitPool) Release() {
|
2015-11-04 17:27:13 +00:00
|
|
|
<-c.sem
|
2015-11-03 16:47:16 +00:00
|
|
|
}
|
2017-08-03 17:24:27 +00:00
|
|
|
|
|
|
|
// Prefixes is a shared helper function returns all parent 'folders' for a
|
|
|
|
// given vault key.
|
|
|
|
// e.g. for 'foo/bar/baz', it returns ['foo', 'foo/bar']
|
|
|
|
func Prefixes(s string) []string {
|
|
|
|
components := strings.Split(s, "/")
|
|
|
|
result := []string{}
|
|
|
|
for i := 1; i < len(components); i++ {
|
|
|
|
result = append(result, strings.Join(components[:i], "/"))
|
|
|
|
}
|
|
|
|
return result
|
|
|
|
}
|