2015-03-15 23:39:49 +00:00
|
|
|
package framework
|
2015-03-14 04:11:19 +00:00
|
|
|
|
|
|
|
import (
|
2018-01-08 18:31:38 +00:00
|
|
|
"context"
|
2019-10-17 17:33:00 +00:00
|
|
|
"crypto/rand"
|
2015-03-19 18:41:41 +00:00
|
|
|
"fmt"
|
2019-10-17 17:33:00 +00:00
|
|
|
"io"
|
2015-04-04 18:39:58 +00:00
|
|
|
"io/ioutil"
|
2018-08-13 18:02:44 +00:00
|
|
|
"net/http"
|
2015-03-14 06:17:25 +00:00
|
|
|
"regexp"
|
2015-04-04 04:00:23 +00:00
|
|
|
"sort"
|
2015-04-04 04:10:54 +00:00
|
|
|
"strings"
|
2015-03-14 06:17:25 +00:00
|
|
|
"sync"
|
2015-03-18 00:58:05 +00:00
|
|
|
"time"
|
2015-03-14 06:17:25 +00:00
|
|
|
|
2018-04-05 15:49:21 +00:00
|
|
|
"github.com/hashicorp/errwrap"
|
2018-04-03 00:46:59 +00:00
|
|
|
log "github.com/hashicorp/go-hclog"
|
2020-01-11 01:39:52 +00:00
|
|
|
"github.com/hashicorp/go-kms-wrapping/entropy"
|
2020-01-07 22:04:08 +00:00
|
|
|
"github.com/hashicorp/go-multierror"
|
|
|
|
"github.com/hashicorp/vault/sdk/helper/consts"
|
2019-04-12 21:54:35 +00:00
|
|
|
"github.com/hashicorp/vault/sdk/helper/errutil"
|
|
|
|
"github.com/hashicorp/vault/sdk/helper/license"
|
|
|
|
"github.com/hashicorp/vault/sdk/helper/logging"
|
|
|
|
"github.com/hashicorp/vault/sdk/helper/parseutil"
|
|
|
|
"github.com/hashicorp/vault/sdk/logical"
|
2015-03-14 04:11:19 +00:00
|
|
|
)
|
|
|
|
|
2015-03-15 21:57:19 +00:00
|
|
|
// Backend is an implementation of logical.Backend that allows
|
2015-03-14 04:11:19 +00:00
|
|
|
// the implementer to code a backend using a much more programmer-friendly
|
|
|
|
// framework that handles a lot of the routing and validation for you.
|
|
|
|
//
|
2015-03-15 21:57:19 +00:00
|
|
|
// This is recommended over implementing logical.Backend directly.
|
2015-03-14 04:11:19 +00:00
|
|
|
type Backend struct {
|
2015-04-04 03:36:47 +00:00
|
|
|
// Help is the help text that is shown when a help request is made
|
|
|
|
// on the root of this resource. The root help is special since we
|
|
|
|
// show all the paths that can be requested.
|
|
|
|
Help string
|
|
|
|
|
2015-03-14 06:17:25 +00:00
|
|
|
// Paths are the various routes that the backend responds to.
|
|
|
|
// This cannot be modified after construction (i.e. dynamically changing
|
|
|
|
// paths, including adding or removing, is not allowed once the
|
|
|
|
// backend is in use).
|
2015-03-19 13:39:25 +00:00
|
|
|
//
|
2015-03-31 00:46:18 +00:00
|
|
|
// PathsSpecial is the list of path patterns that denote the
|
|
|
|
// paths above that require special privileges. These can't be
|
2015-03-16 00:35:59 +00:00
|
|
|
// regular expressions, it is either exact match or prefix match.
|
|
|
|
// For prefix match, append '*' as a suffix.
|
2015-03-31 00:46:18 +00:00
|
|
|
Paths []*Path
|
|
|
|
PathsSpecial *logical.Paths
|
2015-03-16 00:35:59 +00:00
|
|
|
|
2015-03-19 14:07:45 +00:00
|
|
|
// Secrets is the list of secret types that this backend can
|
|
|
|
// return. It is used to automatically generate proper responses,
|
|
|
|
// and ease specifying callbacks for revocation, renewal, etc.
|
|
|
|
Secrets []*Secret
|
|
|
|
|
2019-07-05 23:55:40 +00:00
|
|
|
// InitializeFunc is the callback, which if set, will be invoked via
|
|
|
|
// Initialize() just after a plugin has been mounted.
|
|
|
|
InitializeFunc InitializeFunc
|
|
|
|
|
2016-04-19 18:21:27 +00:00
|
|
|
// PeriodicFunc is the callback, which if set, will be invoked when the
|
2016-04-19 01:06:26 +00:00
|
|
|
// periodic timer of RollbackManager ticks. This can be used by
|
2016-04-19 18:21:27 +00:00
|
|
|
// backends to do anything it wishes to do periodically.
|
2016-04-19 01:06:26 +00:00
|
|
|
//
|
2016-04-19 18:21:27 +00:00
|
|
|
// PeriodicFunc can be invoked to, say to periodically delete stale
|
|
|
|
// entries in backend's storage, while the backend is still being used.
|
|
|
|
// (Note the different of this action from what `Clean` does, which is
|
|
|
|
// invoked just before the backend is unmounted).
|
|
|
|
PeriodicFunc periodicFunc
|
2016-04-19 01:06:26 +00:00
|
|
|
|
|
|
|
// WALRollback is called when a WAL entry (see wal.go) has to be rolled
|
2015-03-21 10:08:13 +00:00
|
|
|
// back. It is called with the data from the entry.
|
2015-03-21 10:03:59 +00:00
|
|
|
//
|
2016-04-19 01:06:26 +00:00
|
|
|
// WALRollbackMinAge is the minimum age of a WAL entry before it is attempted
|
2015-03-21 10:03:59 +00:00
|
|
|
// to be rolled back. This should be longer than the maximum time it takes
|
|
|
|
// to successfully create a secret.
|
2016-04-19 01:06:26 +00:00
|
|
|
WALRollback WALRollbackFunc
|
|
|
|
WALRollbackMinAge time.Duration
|
2015-03-18 00:15:23 +00:00
|
|
|
|
2015-09-10 14:11:37 +00:00
|
|
|
// Clean is called on unload to clean up e.g any existing connections
|
|
|
|
// to the backend, if required.
|
2015-09-10 01:58:09 +00:00
|
|
|
Clean CleanupFunc
|
2015-09-10 14:11:37 +00:00
|
|
|
|
2017-01-07 23:18:22 +00:00
|
|
|
// Invalidate is called when a keys is modified if required
|
|
|
|
Invalidate InvalidateFunc
|
|
|
|
|
2015-04-11 21:46:09 +00:00
|
|
|
// AuthRenew is the callback to call when a RenewRequest for an
|
|
|
|
// authentication comes in. By default, renewal won't be allowed.
|
|
|
|
// See the built-in AuthRenew helpers in lease.go for common callbacks.
|
|
|
|
AuthRenew OperationFunc
|
|
|
|
|
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
|
|
|
// Type is the logical.BackendType for the backend implementation
|
|
|
|
BackendType logical.BackendType
|
|
|
|
|
2016-08-19 20:45:17 +00:00
|
|
|
logger log.Logger
|
2015-09-02 19:56:58 +00:00
|
|
|
system logical.SystemView
|
2015-08-27 18:25:07 +00:00
|
|
|
once sync.Once
|
|
|
|
pathsRe []*regexp.Regexp
|
2015-03-14 04:11:19 +00:00
|
|
|
}
|
|
|
|
|
2016-04-19 18:21:27 +00:00
|
|
|
// periodicFunc is the callback called when the RollbackManager's timer ticks.
|
|
|
|
// This can be utilized by the backends to do anything it wants.
|
2018-01-19 06:44:44 +00:00
|
|
|
type periodicFunc func(context.Context, *logical.Request) error
|
2016-04-19 01:06:26 +00:00
|
|
|
|
2015-03-14 07:19:25 +00:00
|
|
|
// OperationFunc is the callback called for an operation on a path.
|
2018-01-08 18:31:38 +00:00
|
|
|
type OperationFunc func(context.Context, *logical.Request, *FieldData) (*logical.Response, error)
|
|
|
|
|
2018-03-20 18:54:10 +00:00
|
|
|
// ExistenceFunc is the callback called for an existence check on a path.
|
2018-01-08 18:31:38 +00:00
|
|
|
type ExistenceFunc func(context.Context, *logical.Request, *FieldData) (bool, error)
|
2015-03-14 07:19:25 +00:00
|
|
|
|
2016-04-19 01:06:26 +00:00
|
|
|
// WALRollbackFunc is the callback for rollbacks.
|
2018-01-19 06:44:44 +00:00
|
|
|
type WALRollbackFunc func(context.Context, *logical.Request, string, interface{}) error
|
2015-03-21 10:03:59 +00:00
|
|
|
|
2015-09-10 14:11:37 +00:00
|
|
|
// CleanupFunc is the callback for backend unload.
|
2018-01-19 06:44:44 +00:00
|
|
|
type CleanupFunc func(context.Context)
|
2015-09-10 14:11:37 +00:00
|
|
|
|
2017-01-07 23:18:22 +00:00
|
|
|
// InvalidateFunc is the callback for backend key invalidation.
|
2018-01-19 06:44:44 +00:00
|
|
|
type InvalidateFunc func(context.Context, string)
|
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
|
|
|
|
2019-07-05 23:55:40 +00:00
|
|
|
// InitializeFunc is the callback, which if set, will be invoked via
|
|
|
|
// Initialize() just after a plugin has been mounted.
|
|
|
|
type InitializeFunc func(context.Context, *logical.InitializationRequest) error
|
|
|
|
|
|
|
|
// Initialize is the logical.Backend implementation.
|
|
|
|
func (b *Backend) Initialize(ctx context.Context, req *logical.InitializationRequest) error {
|
|
|
|
if b.InitializeFunc != nil {
|
|
|
|
return b.InitializeFunc(ctx, req)
|
|
|
|
}
|
|
|
|
return 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
|
|
|
// HandleExistenceCheck is the logical.Backend implementation.
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *Backend) HandleExistenceCheck(ctx context.Context, req *logical.Request) (checkFound bool, exists bool, err error) {
|
2016-01-07 20:10:05 +00:00
|
|
|
b.once.Do(b.init)
|
|
|
|
|
|
|
|
// Ensure we are only doing this when one of the correct operations is in play
|
|
|
|
switch req.Operation {
|
|
|
|
case logical.CreateOperation:
|
|
|
|
case logical.UpdateOperation:
|
|
|
|
default:
|
2016-01-12 20:09:16 +00:00
|
|
|
return false, false, fmt.Errorf("incorrect operation type %v for an existence check", req.Operation)
|
2016-01-07 20:10:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Find the matching route
|
|
|
|
path, captures := b.route(req.Path)
|
|
|
|
if path == nil {
|
2016-01-12 20:09:16 +00:00
|
|
|
return false, false, logical.ErrUnsupportedPath
|
2016-01-07 20:10:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if path.ExistenceCheck == nil {
|
2016-01-12 20:09:16 +00:00
|
|
|
return false, false, nil
|
2016-01-07 20:10:05 +00:00
|
|
|
}
|
|
|
|
|
2016-01-12 20:09:16 +00:00
|
|
|
checkFound = true
|
|
|
|
|
2016-01-07 20:10:05 +00:00
|
|
|
// Build up the data for the route, with the URL taking priority
|
|
|
|
// for the fields over the PUT data.
|
|
|
|
raw := make(map[string]interface{}, len(path.Fields))
|
|
|
|
for k, v := range req.Data {
|
|
|
|
raw[k] = v
|
|
|
|
}
|
|
|
|
for k, v := range captures {
|
|
|
|
raw[k] = v
|
|
|
|
}
|
|
|
|
|
|
|
|
fd := FieldData{
|
|
|
|
Raw: raw,
|
2021-04-08 16:43:39 +00:00
|
|
|
Schema: path.Fields,
|
|
|
|
}
|
2016-01-07 20:10:05 +00:00
|
|
|
|
2016-01-12 20:09:16 +00:00
|
|
|
err = fd.Validate()
|
2016-01-07 20:10:05 +00:00
|
|
|
if err != nil {
|
2016-07-28 19:19:27 +00:00
|
|
|
return false, false, errutil.UserError{Err: err.Error()}
|
2016-01-07 20:10:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Call the callback with the request and the data
|
2018-01-08 18:31:38 +00:00
|
|
|
exists, err = path.ExistenceCheck(ctx, req, &fd)
|
2016-01-12 20:09:16 +00:00
|
|
|
return
|
2016-01-07 20:10:05 +00:00
|
|
|
}
|
|
|
|
|
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
|
|
|
// HandleRequest is the logical.Backend implementation.
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *Backend) HandleRequest(ctx context.Context, req *logical.Request) (*logical.Response, error) {
|
2015-04-04 03:36:47 +00:00
|
|
|
b.once.Do(b.init)
|
|
|
|
|
2015-03-19 18:41:41 +00:00
|
|
|
// Check for special cased global operations. These don't route
|
|
|
|
// to a specific Path.
|
|
|
|
switch req.Operation {
|
2015-03-19 19:20:25 +00:00
|
|
|
case logical.RenewOperation:
|
|
|
|
fallthrough
|
2015-03-19 18:41:41 +00:00
|
|
|
case logical.RevokeOperation:
|
2018-01-08 18:31:38 +00:00
|
|
|
return b.handleRevokeRenew(ctx, req)
|
2015-03-19 18:41:41 +00:00
|
|
|
case logical.RollbackOperation:
|
2018-01-19 06:44:44 +00:00
|
|
|
return b.handleRollback(ctx, req)
|
2015-03-18 00:15:23 +00:00
|
|
|
}
|
|
|
|
|
2015-04-04 03:36:47 +00:00
|
|
|
// If the path is empty and it is a help operation, handle that.
|
|
|
|
if req.Path == "" && req.Operation == logical.HelpOperation {
|
|
|
|
return b.handleRootHelp()
|
|
|
|
}
|
|
|
|
|
2015-03-14 06:58:20 +00:00
|
|
|
// Find the matching route
|
|
|
|
path, captures := b.route(req.Path)
|
|
|
|
if path == nil {
|
2015-03-15 21:57:19 +00:00
|
|
|
return nil, logical.ErrUnsupportedPath
|
2015-03-14 06:58:20 +00:00
|
|
|
}
|
|
|
|
|
2018-09-18 03:03:00 +00:00
|
|
|
// Check if a feature is required and if the license has that feature
|
|
|
|
if path.FeatureRequired != license.FeatureNone {
|
|
|
|
hasFeature := b.system.HasFeature(path.FeatureRequired)
|
|
|
|
if !hasFeature {
|
|
|
|
return nil, logical.CodedError(401, "Feature Not Enabled")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-14 06:58:20 +00:00
|
|
|
// Build up the data for the route, with the URL taking priority
|
|
|
|
// for the fields over the PUT data.
|
|
|
|
raw := make(map[string]interface{}, len(path.Fields))
|
|
|
|
for k, v := range req.Data {
|
|
|
|
raw[k] = v
|
|
|
|
}
|
|
|
|
for k, v := range captures {
|
|
|
|
raw[k] = v
|
|
|
|
}
|
|
|
|
|
2018-11-05 20:24:39 +00:00
|
|
|
// Look up the callback for this operation, preferring the
|
|
|
|
// path.Operations definition if present.
|
2015-03-14 17:12:50 +00:00
|
|
|
var callback OperationFunc
|
2018-11-05 20:24:39 +00:00
|
|
|
|
|
|
|
if path.Operations != nil {
|
|
|
|
if op, ok := path.Operations[req.Operation]; ok {
|
2020-01-07 22:04:08 +00:00
|
|
|
|
|
|
|
// Check whether this operation should be forwarded
|
2020-01-08 13:59:44 +00:00
|
|
|
if sysView := b.System(); sysView != nil {
|
|
|
|
replState := sysView.ReplicationState()
|
|
|
|
props := op.Properties()
|
2020-01-07 22:04:08 +00:00
|
|
|
|
2020-01-08 13:59:44 +00:00
|
|
|
if props.ForwardPerformanceStandby && replState.HasState(consts.ReplicationPerformanceStandby) {
|
|
|
|
return nil, logical.ErrReadOnly
|
|
|
|
}
|
2020-01-07 22:04:08 +00:00
|
|
|
|
2020-01-08 13:59:44 +00:00
|
|
|
if props.ForwardPerformanceSecondary && !sysView.LocalMount() && replState.HasState(consts.ReplicationPerformanceSecondary) {
|
|
|
|
return nil, logical.ErrReadOnly
|
|
|
|
}
|
2020-01-07 22:04:08 +00:00
|
|
|
}
|
|
|
|
|
2018-11-05 20:24:39 +00:00
|
|
|
callback = op.Handler()
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
callback = path.Callbacks[req.Operation]
|
2015-03-14 17:12:50 +00:00
|
|
|
}
|
2018-11-05 20:24:39 +00:00
|
|
|
ok := callback != nil
|
|
|
|
|
2015-03-14 17:12:50 +00:00
|
|
|
if !ok {
|
2015-05-07 22:39:43 +00:00
|
|
|
if req.Operation == logical.HelpOperation {
|
2018-11-05 20:24:39 +00:00
|
|
|
callback = path.helpCallback(b)
|
2015-03-14 17:12:50 +00:00
|
|
|
ok = true
|
|
|
|
}
|
2015-03-14 07:19:25 +00:00
|
|
|
}
|
|
|
|
if !ok {
|
2015-03-15 21:57:19 +00:00
|
|
|
return nil, logical.ErrUnsupportedOperation
|
2015-03-14 07:19:25 +00:00
|
|
|
}
|
2015-08-27 16:41:03 +00:00
|
|
|
|
2015-08-11 16:34:14 +00:00
|
|
|
fd := FieldData{
|
|
|
|
Raw: raw,
|
2021-04-08 16:43:39 +00:00
|
|
|
Schema: path.Fields,
|
|
|
|
}
|
2015-08-27 16:41:03 +00:00
|
|
|
|
2015-08-11 16:34:14 +00:00
|
|
|
if req.Operation != logical.HelpOperation {
|
2015-08-27 16:41:03 +00:00
|
|
|
err := fd.Validate()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2015-08-11 16:34:14 +00:00
|
|
|
}
|
2015-03-14 07:19:25 +00:00
|
|
|
|
2018-01-08 18:31:38 +00:00
|
|
|
return callback(ctx, req, &fd)
|
2015-03-14 06:58:20 +00:00
|
|
|
}
|
|
|
|
|
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
|
|
|
// SpecialPaths is the logical.Backend implementation.
|
2015-03-31 00:46:18 +00:00
|
|
|
func (b *Backend) SpecialPaths() *logical.Paths {
|
|
|
|
return b.PathsSpecial
|
2015-03-14 06:58:20 +00:00
|
|
|
}
|
|
|
|
|
2017-01-07 23:18:22 +00:00
|
|
|
// Cleanup is used to release resources and prepare to stop the backend
|
2018-01-19 06:44:44 +00:00
|
|
|
func (b *Backend) Cleanup(ctx context.Context) {
|
2015-09-10 14:11:37 +00:00
|
|
|
if b.Clean != nil {
|
2018-01-19 06:44:44 +00:00
|
|
|
b.Clean(ctx)
|
2015-09-10 14:11:37 +00:00
|
|
|
}
|
|
|
|
}
|
2015-09-10 01:58:09 +00:00
|
|
|
|
2017-01-07 23:18:22 +00:00
|
|
|
// InvalidateKey is used to clear caches and reset internal state on key changes
|
2018-01-19 06:44:44 +00:00
|
|
|
func (b *Backend) InvalidateKey(ctx context.Context, key string) {
|
2017-01-07 23:18:22 +00:00
|
|
|
if b.Invalidate != nil {
|
2018-01-19 06:44:44 +00:00
|
|
|
b.Invalidate(ctx, key)
|
2017-01-07 23:18:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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
|
|
|
// Setup is used to initialize the backend with the initial backend configuration
|
2018-01-19 06:44:44 +00:00
|
|
|
func (b *Backend) Setup(ctx context.Context, config *logical.BackendConfig) error {
|
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
|
|
|
b.logger = config.Logger
|
|
|
|
b.system = config.System
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-10-17 17:33:00 +00:00
|
|
|
// GetRandomReader returns an io.Reader to use for generating key material in
|
|
|
|
// backends. If the backend has access to an external entropy source it will
|
|
|
|
// return that, otherwise it returns crypto/rand.Reader.
|
|
|
|
func (b *Backend) GetRandomReader() io.Reader {
|
|
|
|
if sourcer, ok := b.System().(entropy.Sourcer); ok {
|
|
|
|
return entropy.NewReader(sourcer)
|
|
|
|
}
|
|
|
|
|
|
|
|
return rand.Reader
|
|
|
|
}
|
|
|
|
|
2015-04-04 18:39:58 +00:00
|
|
|
// Logger can be used to get the logger. If no logger has been set,
|
|
|
|
// the logs will be discarded.
|
2016-08-19 20:45:17 +00:00
|
|
|
func (b *Backend) Logger() log.Logger {
|
2015-04-04 18:39:58 +00:00
|
|
|
if b.logger != nil {
|
|
|
|
return b.logger
|
|
|
|
}
|
|
|
|
|
2018-04-03 00:46:59 +00:00
|
|
|
return logging.NewVaultLoggerWithWriter(ioutil.Discard, log.NoLevel)
|
2015-04-04 18:39:58 +00:00
|
|
|
}
|
|
|
|
|
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
|
|
|
// System returns the backend's system view.
|
2015-09-02 19:56:58 +00:00
|
|
|
func (b *Backend) System() logical.SystemView {
|
|
|
|
return b.system
|
|
|
|
}
|
|
|
|
|
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
|
|
|
// Type returns the backend type
|
|
|
|
func (b *Backend) Type() logical.BackendType {
|
|
|
|
return b.BackendType
|
|
|
|
}
|
|
|
|
|
2015-03-14 06:48:49 +00:00
|
|
|
// Route looks up the path that would be used for a given path string.
|
2015-03-14 06:17:25 +00:00
|
|
|
func (b *Backend) Route(path string) *Path {
|
2015-03-14 06:48:49 +00:00
|
|
|
result, _ := b.route(path)
|
|
|
|
return result
|
2015-03-14 06:17:25 +00:00
|
|
|
}
|
|
|
|
|
2015-03-19 13:59:01 +00:00
|
|
|
// Secret is used to look up the secret with the given type.
|
|
|
|
func (b *Backend) Secret(k string) *Secret {
|
|
|
|
for _, s := range b.Secrets {
|
|
|
|
if s.Type == k {
|
|
|
|
return s
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-03-14 06:25:17 +00:00
|
|
|
func (b *Backend) init() {
|
|
|
|
b.pathsRe = make([]*regexp.Regexp, len(b.Paths))
|
|
|
|
for i, p := range b.Paths {
|
2015-04-02 00:56:03 +00:00
|
|
|
if len(p.Pattern) == 0 {
|
|
|
|
panic(fmt.Sprintf("Routing pattern cannot be blank"))
|
|
|
|
}
|
2015-04-02 00:53:02 +00:00
|
|
|
// Automatically anchor the pattern
|
2015-04-02 00:56:03 +00:00
|
|
|
if p.Pattern[0] != '^' {
|
2015-04-02 00:53:02 +00:00
|
|
|
p.Pattern = "^" + p.Pattern
|
|
|
|
}
|
|
|
|
if p.Pattern[len(p.Pattern)-1] != '$' {
|
|
|
|
p.Pattern = p.Pattern + "$"
|
|
|
|
}
|
2015-03-14 06:25:17 +00:00
|
|
|
b.pathsRe[i] = regexp.MustCompile(p.Pattern)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-14 06:48:49 +00:00
|
|
|
func (b *Backend) route(path string) (*Path, map[string]string) {
|
|
|
|
b.once.Do(b.init)
|
|
|
|
|
|
|
|
for i, re := range b.pathsRe {
|
|
|
|
matches := re.FindStringSubmatch(path)
|
|
|
|
if matches == nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
// We have a match, determine the mapping of the captures and
|
|
|
|
// store that for returning.
|
|
|
|
var captures map[string]string
|
|
|
|
path := b.Paths[i]
|
|
|
|
if captureNames := re.SubexpNames(); len(captureNames) > 1 {
|
|
|
|
captures = make(map[string]string, len(captureNames))
|
|
|
|
for i, name := range captureNames {
|
|
|
|
if name != "" {
|
|
|
|
captures[name] = matches[i]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return path, captures
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2015-04-04 03:36:47 +00:00
|
|
|
func (b *Backend) handleRootHelp() (*logical.Response, error) {
|
2015-04-04 04:00:23 +00:00
|
|
|
// Build a mapping of the paths and get the paths alphabetized to
|
|
|
|
// make the output prettier.
|
|
|
|
pathsMap := make(map[string]*Path)
|
2015-04-04 03:36:47 +00:00
|
|
|
paths := make([]string, 0, len(b.Paths))
|
2015-04-04 04:00:23 +00:00
|
|
|
for i, p := range b.pathsRe {
|
2015-04-04 03:36:47 +00:00
|
|
|
paths = append(paths, p.String())
|
2015-04-04 04:00:23 +00:00
|
|
|
pathsMap[p.String()] = b.Paths[i]
|
|
|
|
}
|
|
|
|
sort.Strings(paths)
|
|
|
|
|
|
|
|
// Build the path data
|
|
|
|
pathData := make([]rootHelpTemplatePath, 0, len(paths))
|
|
|
|
for _, route := range paths {
|
|
|
|
p := pathsMap[route]
|
|
|
|
pathData = append(pathData, rootHelpTemplatePath{
|
|
|
|
Path: route,
|
2015-04-04 04:10:54 +00:00
|
|
|
Help: strings.TrimSpace(p.HelpSynopsis),
|
2015-04-04 04:00:23 +00:00
|
|
|
})
|
2015-04-04 03:36:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
help, err := executeTemplate(rootHelpTemplate, &rootHelpTemplateData{
|
2015-04-04 04:10:54 +00:00
|
|
|
Help: strings.TrimSpace(b.Help),
|
2015-04-04 04:00:23 +00:00
|
|
|
Paths: pathData,
|
2015-04-04 03:36:47 +00:00
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2018-11-05 20:24:39 +00:00
|
|
|
// Build OpenAPI response for the entire backend
|
|
|
|
doc := NewOASDocument()
|
|
|
|
if err := documentPaths(b, doc); err != nil {
|
|
|
|
b.Logger().Warn("error generating OpenAPI", "error", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return logical.HelpResponse(help, nil, doc), nil
|
2015-04-04 03:36:47 +00:00
|
|
|
}
|
|
|
|
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *Backend) handleRevokeRenew(ctx context.Context, req *logical.Request) (*logical.Response, error) {
|
2015-04-09 21:21:06 +00:00
|
|
|
// Special case renewal of authentication for credential backends
|
|
|
|
if req.Operation == logical.RenewOperation && req.Auth != nil {
|
2018-01-08 18:31:38 +00:00
|
|
|
return b.handleAuthRenew(ctx, req)
|
2015-04-09 21:21:06 +00:00
|
|
|
}
|
|
|
|
|
2015-03-19 22:11:42 +00:00
|
|
|
if req.Secret == nil {
|
|
|
|
return nil, fmt.Errorf("request has no secret")
|
2015-03-19 18:41:41 +00:00
|
|
|
}
|
|
|
|
|
2015-03-19 22:11:42 +00:00
|
|
|
rawSecretType, ok := req.Secret.InternalData["secret_type"]
|
2015-03-19 18:41:41 +00:00
|
|
|
if !ok {
|
2015-03-19 22:11:42 +00:00
|
|
|
return nil, fmt.Errorf("secret is unsupported by this backend")
|
2015-03-19 18:41:41 +00:00
|
|
|
}
|
2015-03-19 22:11:42 +00:00
|
|
|
secretType, ok := rawSecretType.(string)
|
|
|
|
if !ok {
|
2015-03-19 18:41:41 +00:00
|
|
|
return nil, fmt.Errorf("secret is unsupported by this backend")
|
|
|
|
}
|
|
|
|
|
|
|
|
secret := b.Secret(secretType)
|
|
|
|
if secret == nil {
|
|
|
|
return nil, fmt.Errorf("secret is unsupported by this backend")
|
|
|
|
}
|
|
|
|
|
2015-03-19 19:20:25 +00:00
|
|
|
switch req.Operation {
|
|
|
|
case logical.RenewOperation:
|
2018-01-08 18:31:38 +00:00
|
|
|
return secret.HandleRenew(ctx, req)
|
2015-03-19 19:20:25 +00:00
|
|
|
case logical.RevokeOperation:
|
2018-01-08 18:31:38 +00:00
|
|
|
return secret.HandleRevoke(ctx, req)
|
2015-03-19 19:20:25 +00:00
|
|
|
default:
|
2018-04-05 15:49:21 +00:00
|
|
|
return nil, fmt.Errorf("invalid operation for revoke/renew: %q", req.Operation)
|
2015-03-19 19:20:25 +00:00
|
|
|
}
|
2015-03-19 18:41:41 +00:00
|
|
|
}
|
|
|
|
|
2019-05-10 19:11:42 +00:00
|
|
|
// handleRollback invokes the PeriodicFunc set on the backend. It also does a
|
|
|
|
// WAL rollback operation.
|
2018-01-19 06:44:44 +00:00
|
|
|
func (b *Backend) handleRollback(ctx context.Context, req *logical.Request) (*logical.Response, error) {
|
2016-04-19 18:21:27 +00:00
|
|
|
// Response is not expected from the periodic operation.
|
2019-05-13 15:04:06 +00:00
|
|
|
var resp *logical.Response
|
|
|
|
|
|
|
|
merr := new(multierror.Error)
|
2016-04-19 18:21:27 +00:00
|
|
|
if b.PeriodicFunc != nil {
|
2018-01-19 06:44:44 +00:00
|
|
|
if err := b.PeriodicFunc(ctx, req); err != nil {
|
2019-05-10 19:11:42 +00:00
|
|
|
merr = multierror.Append(merr, err)
|
2016-04-19 01:06:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-13 15:04:06 +00:00
|
|
|
if b.WALRollback != nil {
|
|
|
|
var err error
|
|
|
|
resp, err = b.handleWALRollback(ctx, req)
|
|
|
|
if err != nil {
|
|
|
|
merr = multierror.Append(merr, err)
|
|
|
|
}
|
2019-05-10 19:11:42 +00:00
|
|
|
}
|
2019-05-13 15:04:06 +00:00
|
|
|
return resp, merr.ErrorOrNil()
|
2016-04-19 01:06:26 +00:00
|
|
|
}
|
|
|
|
|
2018-01-08 18:31:38 +00:00
|
|
|
func (b *Backend) handleAuthRenew(ctx context.Context, req *logical.Request) (*logical.Response, error) {
|
2015-04-11 21:46:09 +00:00
|
|
|
if b.AuthRenew == nil {
|
|
|
|
return logical.ErrorResponse("this auth type doesn't support renew"), nil
|
|
|
|
}
|
2015-04-11 04:21:06 +00:00
|
|
|
|
2018-01-08 18:31:38 +00:00
|
|
|
return b.AuthRenew(ctx, req, nil)
|
2015-04-09 21:21:06 +00:00
|
|
|
}
|
|
|
|
|
2018-01-19 06:44:44 +00:00
|
|
|
func (b *Backend) handleWALRollback(ctx context.Context, req *logical.Request) (*logical.Response, error) {
|
2016-04-19 01:06:26 +00:00
|
|
|
if b.WALRollback == nil {
|
2015-03-18 00:15:23 +00:00
|
|
|
return nil, logical.ErrUnsupportedOperation
|
|
|
|
}
|
|
|
|
|
|
|
|
var merr error
|
2018-01-19 06:44:44 +00:00
|
|
|
keys, err := ListWAL(ctx, req.Storage)
|
2015-03-18 00:15:23 +00:00
|
|
|
if err != nil {
|
2015-03-18 00:58:05 +00:00
|
|
|
return logical.ErrorResponse(err.Error()), nil
|
|
|
|
}
|
|
|
|
if len(keys) == 0 {
|
|
|
|
return nil, nil
|
2015-03-18 00:15:23 +00:00
|
|
|
}
|
|
|
|
|
2015-03-18 00:58:05 +00:00
|
|
|
// Calculate the minimum time that the WAL entries could be
|
|
|
|
// created in order to be rolled back.
|
2016-04-19 01:06:26 +00:00
|
|
|
age := b.WALRollbackMinAge
|
2015-03-18 00:58:05 +00:00
|
|
|
if age == 0 {
|
|
|
|
age = 10 * time.Minute
|
|
|
|
}
|
2016-07-07 21:44:14 +00:00
|
|
|
minAge := time.Now().Add(-1 * age)
|
2015-03-21 10:18:33 +00:00
|
|
|
if _, ok := req.Data["immediate"]; ok {
|
2016-07-07 21:44:14 +00:00
|
|
|
minAge = time.Now().Add(1000 * time.Hour)
|
2015-03-21 10:18:33 +00:00
|
|
|
}
|
2015-03-18 00:58:05 +00:00
|
|
|
|
2015-03-18 00:15:23 +00:00
|
|
|
for _, k := range keys {
|
2018-01-19 06:44:44 +00:00
|
|
|
entry, err := GetWAL(ctx, req.Storage, k)
|
2015-03-18 00:15:23 +00:00
|
|
|
if err != nil {
|
|
|
|
merr = multierror.Append(merr, err)
|
|
|
|
continue
|
|
|
|
}
|
2015-03-18 00:58:05 +00:00
|
|
|
if entry == nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the entry isn't old enough, then don't roll it back
|
2016-07-12 20:28:27 +00:00
|
|
|
if !time.Unix(entry.CreatedAt, 0).Before(minAge) {
|
2015-03-18 00:58:05 +00:00
|
|
|
continue
|
|
|
|
}
|
2015-03-18 00:15:23 +00:00
|
|
|
|
2016-04-19 01:06:26 +00:00
|
|
|
// Attempt a WAL rollback
|
2018-01-19 06:44:44 +00:00
|
|
|
err = b.WALRollback(ctx, req, entry.Kind, entry.Data)
|
2015-03-21 10:08:13 +00:00
|
|
|
if err != nil {
|
2018-04-05 15:49:21 +00:00
|
|
|
err = errwrap.Wrapf(fmt.Sprintf("error rolling back %q entry: {{err}}", entry.Kind), err)
|
2015-03-21 10:08:13 +00:00
|
|
|
}
|
|
|
|
if err == nil {
|
2018-01-19 06:44:44 +00:00
|
|
|
err = DeleteWAL(ctx, req.Storage, k)
|
2015-03-21 10:08:13 +00:00
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
merr = multierror.Append(merr, err)
|
2015-03-18 00:15:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if merr == nil {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return logical.ErrorResponse(merr.Error()), nil
|
|
|
|
}
|
|
|
|
|
2015-03-14 04:11:19 +00:00
|
|
|
// FieldSchema is a basic schema to describe the format of a path field.
|
|
|
|
type FieldSchema struct {
|
2015-03-14 17:12:50 +00:00
|
|
|
Type FieldType
|
|
|
|
Default interface{}
|
|
|
|
Description string
|
2018-11-05 20:24:39 +00:00
|
|
|
Required bool
|
|
|
|
Deprecated bool
|
2019-01-09 00:50:24 +00:00
|
|
|
|
2019-03-28 21:40:56 +00:00
|
|
|
// Query indicates this field will be sent as a query parameter:
|
|
|
|
//
|
|
|
|
// /v1/foo/bar?some_param=some_value
|
|
|
|
//
|
|
|
|
// It doesn't affect handling of the value, but may be used for documentation.
|
|
|
|
Query bool
|
|
|
|
|
2019-01-09 00:50:24 +00:00
|
|
|
// AllowedValues is an optional list of permitted values for this field.
|
|
|
|
// This constraint is not (yet) enforced by the framework, but the list is
|
|
|
|
// output as part of OpenAPI generation and may effect documentation and
|
|
|
|
// dynamic UI generation.
|
|
|
|
AllowedValues []interface{}
|
2019-01-29 23:35:37 +00:00
|
|
|
|
2019-06-19 23:48:58 +00:00
|
|
|
// DisplayAttrs provides hints for UI and documentation generators. They
|
|
|
|
// will be included in OpenAPI output if set.
|
|
|
|
DisplayAttrs *DisplayAttributes
|
2015-03-14 04:15:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// DefaultOrZero returns the default value if it is set, or otherwise
|
|
|
|
// the zero value of the type.
|
|
|
|
func (s *FieldSchema) DefaultOrZero() interface{} {
|
|
|
|
if s.Default != nil {
|
2017-02-17 22:25:53 +00:00
|
|
|
switch s.Type {
|
2019-06-26 17:15:36 +00:00
|
|
|
case TypeDurationSecond, TypeSignedDurationSecond:
|
2019-06-20 18:28:32 +00:00
|
|
|
resultDur, err := parseutil.ParseDurationSecond(s.Default)
|
|
|
|
if err != nil {
|
2017-02-17 22:25:53 +00:00
|
|
|
return s.Type.Zero()
|
|
|
|
}
|
2019-06-20 18:28:32 +00:00
|
|
|
return int(resultDur.Seconds())
|
2017-02-17 22:25:53 +00:00
|
|
|
|
|
|
|
default:
|
|
|
|
return s.Default
|
|
|
|
}
|
2015-03-14 04:15:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return s.Type.Zero()
|
2015-03-14 04:11:19 +00:00
|
|
|
}
|
|
|
|
|
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
|
|
|
// Zero returns the correct zero-value for a specific FieldType
|
2015-03-14 04:11:19 +00:00
|
|
|
func (t FieldType) Zero() interface{} {
|
|
|
|
switch t {
|
2018-06-02 01:30:59 +00:00
|
|
|
case TypeString, TypeNameString, TypeLowerCaseString:
|
2015-03-14 04:11:19 +00:00
|
|
|
return ""
|
|
|
|
case TypeInt:
|
|
|
|
return 0
|
|
|
|
case TypeBool:
|
|
|
|
return false
|
2015-03-31 23:43:37 +00:00
|
|
|
case TypeMap:
|
|
|
|
return map[string]interface{}{}
|
2017-11-07 16:11:49 +00:00
|
|
|
case TypeKVPairs:
|
|
|
|
return map[string]string{}
|
2019-06-26 17:15:36 +00:00
|
|
|
case TypeDurationSecond, TypeSignedDurationSecond:
|
2015-06-17 22:56:26 +00:00
|
|
|
return 0
|
2017-04-18 20:02:31 +00:00
|
|
|
case TypeSlice:
|
|
|
|
return []interface{}{}
|
|
|
|
case TypeStringSlice, TypeCommaStringSlice:
|
|
|
|
return []string{}
|
2018-03-02 23:01:13 +00:00
|
|
|
case TypeCommaIntSlice:
|
|
|
|
return []int{}
|
2018-08-13 18:02:44 +00:00
|
|
|
case TypeHeader:
|
|
|
|
return http.Header{}
|
2020-05-04 22:22:28 +00:00
|
|
|
case TypeFloat:
|
|
|
|
return 0.0
|
2020-09-09 20:53:51 +00:00
|
|
|
case TypeTime:
|
|
|
|
return time.Time{}
|
2015-03-14 04:11:19 +00:00
|
|
|
default:
|
|
|
|
panic("unknown type: " + t.String())
|
|
|
|
}
|
|
|
|
}
|
2015-04-04 03:36:47 +00:00
|
|
|
|
|
|
|
type rootHelpTemplateData struct {
|
|
|
|
Help string
|
2015-04-04 04:00:23 +00:00
|
|
|
Paths []rootHelpTemplatePath
|
|
|
|
}
|
|
|
|
|
|
|
|
type rootHelpTemplatePath struct {
|
|
|
|
Path string
|
|
|
|
Help string
|
2015-04-04 03:36:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const rootHelpTemplate = `
|
|
|
|
## DESCRIPTION
|
|
|
|
|
|
|
|
{{.Help}}
|
|
|
|
|
|
|
|
## PATHS
|
|
|
|
|
|
|
|
The following paths are supported by this backend. To view help for
|
|
|
|
any of the paths below, use the help command with any route matching
|
2015-04-04 04:00:23 +00:00
|
|
|
the path pattern. Note that depending on the policy of your auth token,
|
|
|
|
you may or may not be able to access certain paths.
|
|
|
|
|
|
|
|
{{range .Paths}}{{indent 4 .Path}}
|
|
|
|
{{indent 8 .Help}}
|
2015-04-04 03:36:47 +00:00
|
|
|
|
|
|
|
{{end}}
|
|
|
|
|
|
|
|
`
|