open-vault/helper/builtinplugins/registry.go

207 lines
8.3 KiB
Go
Raw Normal View History

2018-11-07 01:21:24 +00:00
package builtinplugins
import (
credAliCloud "github.com/hashicorp/vault-plugin-auth-alicloud"
credAzure "github.com/hashicorp/vault-plugin-auth-azure"
credCentrify "github.com/hashicorp/vault-plugin-auth-centrify"
credCF "github.com/hashicorp/vault-plugin-auth-cf"
2018-11-07 01:21:24 +00:00
credGcp "github.com/hashicorp/vault-plugin-auth-gcp/plugin"
credJWT "github.com/hashicorp/vault-plugin-auth-jwt"
credKerb "github.com/hashicorp/vault-plugin-auth-kerberos"
2018-11-07 01:21:24 +00:00
credKube "github.com/hashicorp/vault-plugin-auth-kubernetes"
credOCI "github.com/hashicorp/vault-plugin-auth-oci"
dbCouchbase "github.com/hashicorp/vault-plugin-database-couchbase"
dbElastic "github.com/hashicorp/vault-plugin-database-elasticsearch"
dbMongoAtlas "github.com/hashicorp/vault-plugin-database-mongodbatlas"
dbSnowflake "github.com/hashicorp/vault-plugin-database-snowflake"
logicalAd "github.com/hashicorp/vault-plugin-secrets-ad/plugin"
logicalAlicloud "github.com/hashicorp/vault-plugin-secrets-alicloud"
logicalAzure "github.com/hashicorp/vault-plugin-secrets-azure"
logicalGcp "github.com/hashicorp/vault-plugin-secrets-gcp/plugin"
logicalGcpKms "github.com/hashicorp/vault-plugin-secrets-gcpkms"
logicalKube "github.com/hashicorp/vault-plugin-secrets-kubernetes"
logicalKv "github.com/hashicorp/vault-plugin-secrets-kv"
logicalMongoAtlas "github.com/hashicorp/vault-plugin-secrets-mongodbatlas"
logicalOpenLDAP "github.com/hashicorp/vault-plugin-secrets-openldap"
logicalTerraform "github.com/hashicorp/vault-plugin-secrets-terraform"
2018-11-07 01:21:24 +00:00
credAppId "github.com/hashicorp/vault/builtin/credential/app-id"
credAppRole "github.com/hashicorp/vault/builtin/credential/approle"
credAws "github.com/hashicorp/vault/builtin/credential/aws"
credCert "github.com/hashicorp/vault/builtin/credential/cert"
credGitHub "github.com/hashicorp/vault/builtin/credential/github"
credLdap "github.com/hashicorp/vault/builtin/credential/ldap"
credOkta "github.com/hashicorp/vault/builtin/credential/okta"
credRadius "github.com/hashicorp/vault/builtin/credential/radius"
credUserpass "github.com/hashicorp/vault/builtin/credential/userpass"
logicalAws "github.com/hashicorp/vault/builtin/logical/aws"
logicalCass "github.com/hashicorp/vault/builtin/logical/cassandra"
logicalConsul "github.com/hashicorp/vault/builtin/logical/consul"
logicalMongo "github.com/hashicorp/vault/builtin/logical/mongodb"
logicalMssql "github.com/hashicorp/vault/builtin/logical/mssql"
logicalMysql "github.com/hashicorp/vault/builtin/logical/mysql"
logicalNomad "github.com/hashicorp/vault/builtin/logical/nomad"
logicalPki "github.com/hashicorp/vault/builtin/logical/pki"
logicalPostgres "github.com/hashicorp/vault/builtin/logical/postgresql"
logicalRabbit "github.com/hashicorp/vault/builtin/logical/rabbitmq"
logicalSsh "github.com/hashicorp/vault/builtin/logical/ssh"
logicalTotp "github.com/hashicorp/vault/builtin/logical/totp"
logicalTransit "github.com/hashicorp/vault/builtin/logical/transit"
dbCass "github.com/hashicorp/vault/plugins/database/cassandra"
dbHana "github.com/hashicorp/vault/plugins/database/hana"
dbInflux "github.com/hashicorp/vault/plugins/database/influxdb"
dbMongo "github.com/hashicorp/vault/plugins/database/mongodb"
dbMssql "github.com/hashicorp/vault/plugins/database/mssql"
dbMysql "github.com/hashicorp/vault/plugins/database/mysql"
dbPostgres "github.com/hashicorp/vault/plugins/database/postgresql"
dbRedshift "github.com/hashicorp/vault/plugins/database/redshift"
"github.com/hashicorp/vault/sdk/helper/consts"
"github.com/hashicorp/vault/sdk/logical"
2018-11-07 01:21:24 +00:00
)
// Registry is inherently thread-safe because it's immutable.
// Thus, rather than creating multiple instances of it, we only need one.
var Registry = newRegistry()
2019-07-22 17:14:53 +00:00
var addExternalPlugins = addExtPluginsImpl
2018-11-07 01:21:24 +00:00
// BuiltinFactory is the func signature that should be returned by
// the plugin's New() func.
type BuiltinFactory func() (interface{}, error)
func newRegistry() *registry {
2019-07-22 17:14:53 +00:00
reg := &registry{
2018-11-07 01:21:24 +00:00
credentialBackends: map[string]logical.Factory{
"alicloud": credAliCloud.Factory,
"app-id": credAppId.Factory,
"approle": credAppRole.Factory,
"aws": credAws.Factory,
"azure": credAzure.Factory,
"centrify": credCentrify.Factory,
"cert": credCert.Factory,
"cf": credCF.Factory,
2018-11-07 01:21:24 +00:00
"gcp": credGcp.Factory,
"github": credGitHub.Factory,
"jwt": credJWT.Factory,
"kerberos": credKerb.Factory,
2018-11-07 01:21:24 +00:00
"kubernetes": credKube.Factory,
"ldap": credLdap.Factory,
"oci": credOCI.Factory,
"oidc": credJWT.Factory,
2018-11-07 01:21:24 +00:00
"okta": credOkta.Factory,
"pcf": credCF.Factory, // Deprecated.
2018-11-07 01:21:24 +00:00
"radius": credRadius.Factory,
"userpass": credUserpass.Factory,
},
databasePlugins: map[string]BuiltinFactory{
// These four plugins all use the same mysql implementation but with
// different username settings passed by the constructor.
"mysql-database-plugin": dbMysql.New(dbMysql.DefaultUserNameTemplate),
"mysql-aurora-database-plugin": dbMysql.New(dbMysql.DefaultLegacyUserNameTemplate),
"mysql-rds-database-plugin": dbMysql.New(dbMysql.DefaultLegacyUserNameTemplate),
"mysql-legacy-database-plugin": dbMysql.New(dbMysql.DefaultLegacyUserNameTemplate),
2018-11-07 01:21:24 +00:00
"cassandra-database-plugin": dbCass.New,
"couchbase-database-plugin": dbCouchbase.New,
"elasticsearch-database-plugin": dbElastic.New,
"hana-database-plugin": dbHana.New,
"influxdb-database-plugin": dbInflux.New,
"mongodb-database-plugin": dbMongo.New,
"mongodbatlas-database-plugin": dbMongoAtlas.New,
"mssql-database-plugin": dbMssql.New,
"postgresql-database-plugin": dbPostgres.New,
"redshift-database-plugin": dbRedshift.New,
"snowflake-database-plugin": dbSnowflake.New,
2018-11-07 01:21:24 +00:00
},
logicalBackends: map[string]logical.Factory{
2020-02-07 22:09:39 +00:00
"ad": logicalAd.Factory,
"alicloud": logicalAlicloud.Factory,
"aws": logicalAws.Factory,
"azure": logicalAzure.Factory,
"cassandra": logicalCass.Factory, // Deprecated
2020-02-07 22:09:39 +00:00
"consul": logicalConsul.Factory,
"gcp": logicalGcp.Factory,
"gcpkms": logicalGcpKms.Factory,
"kubernetes": logicalKube.Factory,
2020-02-07 22:09:39 +00:00
"kv": logicalKv.Factory,
"mongodb": logicalMongo.Factory, // Deprecated
2020-02-07 22:09:39 +00:00
"mongodbatlas": logicalMongoAtlas.Factory,
"mssql": logicalMssql.Factory, // Deprecated
"mysql": logicalMysql.Factory, // Deprecated
2020-02-07 22:09:39 +00:00
"nomad": logicalNomad.Factory,
"openldap": logicalOpenLDAP.Factory,
2020-02-07 22:09:39 +00:00
"pki": logicalPki.Factory,
"postgresql": logicalPostgres.Factory, // Deprecated
2020-02-07 22:09:39 +00:00
"rabbitmq": logicalRabbit.Factory,
"ssh": logicalSsh.Factory,
"terraform": logicalTerraform.Factory,
2020-02-07 22:09:39 +00:00
"totp": logicalTotp.Factory,
"transit": logicalTransit.Factory,
2018-11-07 01:21:24 +00:00
},
}
2019-07-22 17:14:53 +00:00
addExternalPlugins(reg)
return reg
2018-11-07 01:21:24 +00:00
}
2019-07-22 17:14:53 +00:00
func addExtPluginsImpl(r *registry) {}
2018-11-07 01:21:24 +00:00
type registry struct {
credentialBackends map[string]logical.Factory
databasePlugins map[string]BuiltinFactory
logicalBackends map[string]logical.Factory
}
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
// Get returns the Factory func for a particular backend plugin from the
// plugins map.
2018-11-07 01:21:24 +00:00
func (r *registry) Get(name string, pluginType consts.PluginType) (func() (interface{}, error), bool) {
switch pluginType {
case consts.PluginTypeCredential:
f, ok := r.credentialBackends[name]
return toFunc(f), ok
case consts.PluginTypeSecrets:
f, ok := r.logicalBackends[name]
return toFunc(f), ok
case consts.PluginTypeDatabase:
f, ok := r.databasePlugins[name]
return f, ok
default:
return nil, false
}
}
// Keys returns the list of plugin names that are considered builtin plugins.
func (r *registry) Keys(pluginType consts.PluginType) []string {
var keys []string
switch pluginType {
case consts.PluginTypeDatabase:
for key := range r.databasePlugins {
keys = append(keys, key)
}
case consts.PluginTypeCredential:
for key := range r.credentialBackends {
keys = append(keys, key)
}
case consts.PluginTypeSecrets:
for key := range r.logicalBackends {
keys = append(keys, key)
}
}
return keys
}
func (r *registry) Contains(name string, pluginType consts.PluginType) bool {
for _, key := range r.Keys(pluginType) {
if key == name {
return true
}
}
return false
}
func toFunc(ifc interface{}) func() (interface{}, error) {
return func() (interface{}, error) {
return ifc, nil
}
}