open-vault/sdk/logical/system_view.go

243 lines
8.3 KiB
Go
Raw Normal View History

package logical
2017-02-16 18:37:21 +00:00
import (
"context"
2017-03-16 00:14:48 +00:00
"errors"
"fmt"
"io"
2017-02-16 18:37:21 +00:00
"time"
"github.com/hashicorp/vault/sdk/helper/consts"
"github.com/hashicorp/vault/sdk/helper/license"
"github.com/hashicorp/vault/sdk/helper/pluginutil"
"github.com/hashicorp/vault/sdk/helper/wrapping"
2017-02-16 18:37:21 +00:00
)
// SystemView exposes system configuration information in a safe way
// for logical backends to consume
type SystemView interface {
2015-08-27 16:14:03 +00:00
// DefaultLeaseTTL returns the default lease TTL set in Vault configuration
DefaultLeaseTTL() time.Duration
2015-08-27 16:14:03 +00:00
// MaxLeaseTTL returns the max lease TTL set in Vault configuration; backend
// authors should take care not to issue credentials that last longer than
// this value, as Vault will revoke them
MaxLeaseTTL() time.Duration
// Returns true if the mount is tainted. A mount is tainted if it is in the
// process of being unmounted. This should only be used in special
// circumstances; a primary use-case is as a guard in revocation functions.
// If revocation of a backend's leases fails it can keep the unmounting
// process from being successful. If the reason for this failure is not
// relevant when the mount is tainted (for instance, saving a CRL to disk
// when the stored CRL will be removed during the unmounting process
// anyways), we can ignore the errors to allow unmounting to complete.
Tainted() bool
// Returns true if caching is disabled. If true, no caches should be used,
// despite known slowdowns.
CachingDisabled() bool
// When run from a system view attached to a request, indicates whether the
// request is affecting a local mount or not
LocalMount() bool
// ReplicationState indicates the state of cluster replication
2017-02-16 18:37:21 +00:00
ReplicationState() consts.ReplicationState
2017-03-16 00:14:48 +00:00
2018-09-18 03:03:00 +00:00
// HasFeature returns true if the feature is currently enabled
HasFeature(feature license.Features) bool
2017-03-16 00:14:48 +00:00
// ResponseWrapData wraps the given data in a cubbyhole and returns the
// token used to unwrap.
ResponseWrapData(ctx context.Context, data map[string]interface{}, ttl time.Duration, jwt bool) (*wrapping.ResponseWrapInfo, error)
2017-04-04 00:52:29 +00:00
2017-04-11 00:12:52 +00:00
// LookupPlugin looks into the plugin catalog for a plugin with the given
// name. Returns a PluginRunner or an error if a plugin can not be found.
LookupPlugin(ctx context.Context, pluginName string, pluginType consts.PluginType) (*pluginutil.PluginRunner, error)
// LookupPluginVersion looks into the plugin catalog for a plugin with the given
// name and version. Returns a PluginRunner or an error if a plugin can not be found.
LookupPluginVersion(ctx context.Context, pluginName string, pluginType consts.PluginType, version string) (*pluginutil.PluginRunner, error)
2017-04-11 00:12:52 +00:00
// ListVersionedPlugins returns information about all plugins of a certain
// type in the catalog, including any versioning information stored for them.
ListVersionedPlugins(ctx context.Context, pluginType consts.PluginType) ([]pluginutil.VersionedPlugin, error)
feature: multiplexing support for database plugins (#14033) * feat: DB plugin multiplexing (#13734) * WIP: start from main and get a plugin runner from core * move MultiplexedClient map to plugin catalog - call sys.NewPluginClient from PluginFactory - updates to getPluginClient - thread through isMetadataMode * use go-plugin ClientProtocol interface - call sys.NewPluginClient from dbplugin.NewPluginClient * move PluginSets to dbplugin package - export dbplugin HandshakeConfig - small refactor of PluginCatalog.getPluginClient * add removeMultiplexedClient; clean up on Close() - call client.Kill from plugin catalog - set rpcClient when muxed client exists * add ID to dbplugin.DatabasePluginClient struct * only create one plugin process per plugin type * update NewPluginClient to return connection ID to sdk - wrap grpc.ClientConn so we can inject the ID into context - get ID from context on grpc server * add v6 multiplexing protocol version * WIP: backwards compat for db plugins * Ensure locking on plugin catalog access - Create public GetPluginClient method for plugin catalog - rename postgres db plugin * use the New constructor for db plugins * grpc server: use write lock for Close and rlock for CRUD * cleanup MultiplexedClients on Close * remove TODO * fix multiplexing regression with grpc server connection * cleanup grpc server instances on close * embed ClientProtocol in Multiplexer interface * use PluginClientConfig arg to make NewPluginClient plugin type agnostic * create a new plugin process for non-muxed plugins * feat: plugin multiplexing: handle plugin client cleanup (#13896) * use closure for plugin client cleanup * log and return errors; add comments * move rpcClient wrapping to core for ID injection * refactor core plugin client and sdk * remove unused ID method * refactor and only wrap clientConn on multiplexed plugins * rename structs and do not export types * Slight refactor of system view interface * Revert "Slight refactor of system view interface" This reverts commit 73d420e5cd2f0415e000c5a9284ea72a58016dd6. * Revert "Revert "Slight refactor of system view interface"" This reverts commit f75527008a1db06d04a23e04c3059674be8adb5f. * only provide pluginRunner arg to the internal newPluginClient method * embed ClientProtocol in pluginClient and name logger * Add back MLock support * remove enableMlock arg from setupPluginCatalog * rename plugin util interface to PluginClient Co-authored-by: Brian Kassouf <bkassouf@hashicorp.com> * feature: multiplexing: fix unit tests (#14007) * fix grpc_server tests and add coverage * update run_config tests * add happy path test case for grpc_server ID from context * update test helpers * feat: multiplexing: handle v5 plugin compiled with new sdk * add mux supported flag and increase test coverage * set multiplexingSupport field in plugin server * remove multiplexingSupport field in sdk * revert postgres to non-multiplexed * add comments on grpc server fields * use pointer receiver on grpc server methods * add changelog * use pointer for grpcserver instance * Use a gRPC server to determine if a plugin should be multiplexed * Apply suggestions from code review Co-authored-by: Brian Kassouf <briankassouf@users.noreply.github.com> * add lock to removePluginClient * add multiplexingSupport field to externalPlugin struct * do not send nil to grpc MultiplexingSupport * check err before logging * handle locking scenario for cleanupFunc * allow ServeConfigMultiplex to dispense v5 plugin * reposition structs, add err check and comments * add comment on locking for cleanupExternalPlugin Co-authored-by: Brian Kassouf <bkassouf@hashicorp.com> Co-authored-by: Brian Kassouf <briankassouf@users.noreply.github.com>
2022-02-17 14:50:33 +00:00
// NewPluginClient returns a client for managing the lifecycle of plugin
// processes
NewPluginClient(ctx context.Context, config pluginutil.PluginClientConfig) (pluginutil.PluginClient, error)
2017-05-04 17:41:59 +00:00
// MlockEnabled returns the configuration setting for enabling mlock on
2017-04-24 19:21:49 +00:00
// plugins.
MlockEnabled() bool
// EntityInfo returns a subset of information related to the identity entity
// for the given entity id
EntityInfo(entityID string) (*Entity, error)
2018-08-03 16:32:17 +00:00
// GroupsForEntity returns the group membership information for the provided
// entity id
GroupsForEntity(entityID string) ([]*Group, error)
2018-08-03 16:32:17 +00:00
// PluginEnv returns Vault environment information used by plugins
PluginEnv(context.Context) (*PluginEnvironment, error)
// VaultVersion returns the version string for the currently running Vault.
VaultVersion(context.Context) (string, error)
// GeneratePasswordFromPolicy generates a password from the policy referenced.
// If the policy does not exist, this will return an error.
GeneratePasswordFromPolicy(ctx context.Context, policyName string) (password string, err error)
}
type PasswordPolicy interface {
// Generate a random password
Generate(context.Context, io.Reader) (string, error)
}
type ExtendedSystemView interface {
Auditor() Auditor
ForwardGenericRequest(context.Context, *Request) (*Response, error)
}
type PasswordGenerator func() (password string, err error)
type StaticSystemView struct {
DefaultLeaseTTLVal time.Duration
MaxLeaseTTLVal time.Duration
SudoPrivilegeVal bool
TaintedVal bool
CachingDisabledVal bool
Primary bool
2017-04-24 19:21:49 +00:00
EnableMlock bool
LocalMountVal bool
2017-02-16 18:37:21 +00:00
ReplicationStateVal consts.ReplicationState
EntityVal *Entity
GroupsVal []*Group
2018-09-18 03:03:00 +00:00
Features license.Features
2018-08-03 16:32:17 +00:00
PluginEnvironment *PluginEnvironment
PasswordPolicies map[string]PasswordGenerator
VersionString string
}
type noopAuditor struct{}
func (a noopAuditor) AuditRequest(ctx context.Context, input *LogInput) error {
return nil
}
func (a noopAuditor) AuditResponse(ctx context.Context, input *LogInput) error {
return nil
}
func (d StaticSystemView) Auditor() Auditor {
return noopAuditor{}
}
func (d StaticSystemView) ForwardGenericRequest(ctx context.Context, req *Request) (*Response, error) {
return nil, errors.New("ForwardGenericRequest is not implemented in StaticSystemView")
}
func (d StaticSystemView) DefaultLeaseTTL() time.Duration {
return d.DefaultLeaseTTLVal
}
func (d StaticSystemView) MaxLeaseTTL() time.Duration {
return d.MaxLeaseTTLVal
}
func (d StaticSystemView) SudoPrivilege(_ context.Context, path string, token string) bool {
return d.SudoPrivilegeVal
}
func (d StaticSystemView) Tainted() bool {
return d.TaintedVal
}
func (d StaticSystemView) CachingDisabled() bool {
return d.CachingDisabledVal
}
func (d StaticSystemView) LocalMount() bool {
return d.LocalMountVal
}
2017-02-16 18:37:21 +00:00
func (d StaticSystemView) ReplicationState() consts.ReplicationState {
return d.ReplicationStateVal
}
2017-03-16 00:14:48 +00:00
feature: multiplexing support for database plugins (#14033) * feat: DB plugin multiplexing (#13734) * WIP: start from main and get a plugin runner from core * move MultiplexedClient map to plugin catalog - call sys.NewPluginClient from PluginFactory - updates to getPluginClient - thread through isMetadataMode * use go-plugin ClientProtocol interface - call sys.NewPluginClient from dbplugin.NewPluginClient * move PluginSets to dbplugin package - export dbplugin HandshakeConfig - small refactor of PluginCatalog.getPluginClient * add removeMultiplexedClient; clean up on Close() - call client.Kill from plugin catalog - set rpcClient when muxed client exists * add ID to dbplugin.DatabasePluginClient struct * only create one plugin process per plugin type * update NewPluginClient to return connection ID to sdk - wrap grpc.ClientConn so we can inject the ID into context - get ID from context on grpc server * add v6 multiplexing protocol version * WIP: backwards compat for db plugins * Ensure locking on plugin catalog access - Create public GetPluginClient method for plugin catalog - rename postgres db plugin * use the New constructor for db plugins * grpc server: use write lock for Close and rlock for CRUD * cleanup MultiplexedClients on Close * remove TODO * fix multiplexing regression with grpc server connection * cleanup grpc server instances on close * embed ClientProtocol in Multiplexer interface * use PluginClientConfig arg to make NewPluginClient plugin type agnostic * create a new plugin process for non-muxed plugins * feat: plugin multiplexing: handle plugin client cleanup (#13896) * use closure for plugin client cleanup * log and return errors; add comments * move rpcClient wrapping to core for ID injection * refactor core plugin client and sdk * remove unused ID method * refactor and only wrap clientConn on multiplexed plugins * rename structs and do not export types * Slight refactor of system view interface * Revert "Slight refactor of system view interface" This reverts commit 73d420e5cd2f0415e000c5a9284ea72a58016dd6. * Revert "Revert "Slight refactor of system view interface"" This reverts commit f75527008a1db06d04a23e04c3059674be8adb5f. * only provide pluginRunner arg to the internal newPluginClient method * embed ClientProtocol in pluginClient and name logger * Add back MLock support * remove enableMlock arg from setupPluginCatalog * rename plugin util interface to PluginClient Co-authored-by: Brian Kassouf <bkassouf@hashicorp.com> * feature: multiplexing: fix unit tests (#14007) * fix grpc_server tests and add coverage * update run_config tests * add happy path test case for grpc_server ID from context * update test helpers * feat: multiplexing: handle v5 plugin compiled with new sdk * add mux supported flag and increase test coverage * set multiplexingSupport field in plugin server * remove multiplexingSupport field in sdk * revert postgres to non-multiplexed * add comments on grpc server fields * use pointer receiver on grpc server methods * add changelog * use pointer for grpcserver instance * Use a gRPC server to determine if a plugin should be multiplexed * Apply suggestions from code review Co-authored-by: Brian Kassouf <briankassouf@users.noreply.github.com> * add lock to removePluginClient * add multiplexingSupport field to externalPlugin struct * do not send nil to grpc MultiplexingSupport * check err before logging * handle locking scenario for cleanupFunc * allow ServeConfigMultiplex to dispense v5 plugin * reposition structs, add err check and comments * add comment on locking for cleanupExternalPlugin Co-authored-by: Brian Kassouf <bkassouf@hashicorp.com> Co-authored-by: Brian Kassouf <briankassouf@users.noreply.github.com>
2022-02-17 14:50:33 +00:00
func (d StaticSystemView) NewPluginClient(ctx context.Context, config pluginutil.PluginClientConfig) (pluginutil.PluginClient, error) {
return nil, errors.New("NewPluginClient is not implemented in StaticSystemView")
}
func (d StaticSystemView) ResponseWrapData(_ context.Context, data map[string]interface{}, ttl time.Duration, jwt bool) (*wrapping.ResponseWrapInfo, error) {
return nil, errors.New("ResponseWrapData is not implemented in StaticSystemView")
2017-03-16 00:14:48 +00:00
}
2017-04-04 00:52:29 +00:00
2018-11-07 01:21:24 +00:00
func (d StaticSystemView) LookupPlugin(_ context.Context, _ string, _ consts.PluginType) (*pluginutil.PluginRunner, error) {
2017-04-11 18:50:34 +00:00
return nil, errors.New("LookupPlugin is not implemented in StaticSystemView")
2017-04-04 00:52:29 +00:00
}
2017-04-11 00:12:52 +00:00
func (d StaticSystemView) LookupPluginVersion(_ context.Context, _ string, _ consts.PluginType, _ string) (*pluginutil.PluginRunner, error) {
return nil, errors.New("LookupPluginVersion is not implemented in StaticSystemView")
}
func (d StaticSystemView) ListVersionedPlugins(_ context.Context, _ consts.PluginType) ([]pluginutil.VersionedPlugin, error) {
return nil, errors.New("ListVersionedPlugins is not implemented in StaticSystemView")
}
2017-04-24 19:21:49 +00:00
func (d StaticSystemView) MlockEnabled() bool {
return d.EnableMlock
2017-04-11 00:12:52 +00:00
}
func (d StaticSystemView) EntityInfo(entityID string) (*Entity, error) {
return d.EntityVal, nil
}
2018-08-03 16:32:17 +00:00
func (d StaticSystemView) GroupsForEntity(entityID string) ([]*Group, error) {
return d.GroupsVal, nil
}
2018-09-18 03:03:00 +00:00
func (d StaticSystemView) HasFeature(feature license.Features) bool {
return d.Features.HasFeature(feature)
}
2018-08-03 16:32:17 +00:00
func (d StaticSystemView) PluginEnv(_ context.Context) (*PluginEnvironment, error) {
return d.PluginEnvironment, nil
}
func (d StaticSystemView) VaultVersion(_ context.Context) (string, error) {
return d.VersionString, nil
}
func (d StaticSystemView) GeneratePasswordFromPolicy(ctx context.Context, policyName string) (password string, err error) {
select {
case <-ctx.Done():
return "", fmt.Errorf("context timed out")
default:
}
if d.PasswordPolicies == nil {
return "", fmt.Errorf("password policy not found")
}
policy, exists := d.PasswordPolicies[policyName]
if !exists {
return "", fmt.Errorf("password policy not found")
}
return policy()
}
func (d *StaticSystemView) SetPasswordPolicy(name string, generator PasswordGenerator) {
if d.PasswordPolicies == nil {
d.PasswordPolicies = map[string]PasswordGenerator{}
}
d.PasswordPolicies[name] = generator
}
func (d *StaticSystemView) DeletePasswordPolicy(name string) (existed bool) {
_, existed = d.PasswordPolicies[name]
delete(d.PasswordPolicies, name)
return existed
}