diff --git a/website/content/docs/auth/azure.mdx b/website/content/docs/auth/azure.mdx index 053ab238d347..817823c7da85 100644 --- a/website/content/docs/auth/azure.mdx +++ b/website/content/docs/auth/azure.mdx @@ -180,7 +180,7 @@ method as an external plugin. The azure plugin method is integrated into Vault a a builtin method by default. Assuming you have saved the binary `vault-plugin-auth-azure` to some folder and -configured the [plugin directory](/docs/internals/plugins#plugin-directory) +configured the [plugin directory](/docs/plugins/plugin-architecture#plugin-directory) for your server at `path/to/plugins`: 1. Enable the plugin in the catalog: diff --git a/website/content/docs/configuration/index.mdx b/website/content/docs/configuration/index.mdx index b69cdb662a69..c85843140c1a 100644 --- a/website/content/docs/configuration/index.mdx +++ b/website/content/docs/configuration/index.mdx @@ -104,7 +104,7 @@ to specify where the configuration is. ~> Note: Since each plugin runs as a separate process, you need to do the same for each plugin in your [plugins - directory](/docs/internals/plugins#plugin-directory). + directory](/docs/plugins/plugin-architecture#plugin-directory). If you use a Linux distribution with a modern version of systemd, you can add the following directive to the "[Service]" configuration section: diff --git a/website/content/docs/internals/limits.mdx b/website/content/docs/internals/limits.mdx index 84128658c34b..04e3952c69f8 100644 --- a/website/content/docs/internals/limits.mdx +++ b/website/content/docs/internals/limits.mdx @@ -288,7 +288,7 @@ are a function of the alphabet size. ### External plugin limits -The [plugin system](/docs/internals/plugins) launches a separate process +The [plugin system](/docs/plugins) launches a separate process initiated by Vault that communicates over RPC. For each secret engine and auth method that's enabled as an external plugin, Vault will spawn a process on the host system. For the Database Secrets Engines, external database plugins will diff --git a/website/content/docs/internals/plugins.mdx b/website/content/docs/internals/plugins.mdx deleted file mode 100644 index 518fe27f965b..000000000000 --- a/website/content/docs/internals/plugins.mdx +++ /dev/null @@ -1,236 +0,0 @@ ---- -layout: docs -page_title: Plugin System -description: Learn about Vault's plugin system. ---- - -# Plugin System - -All Vault auth and secret backends are considered plugins. This simple concept -allows both built-in and external plugins to be treated like Legos. Any plugin -can exist at multiple different locations. Different versions of a plugin may -be at each one, with each version differing from Vault's version. - -## Built-In Plugins - -Built-in plugins are shipped with Vault, often for commonly used implementations, -and require no additional operator intervention to run. Built-in plugins are -just like any other backend code inside Vault. - -To use a different or edited version of a built-in plugin, you would first edit -the plugin's code or navigate to the Vault version holding the version of the -plugin you desire. Then, you'd `$ cd` into the `cmd/:plugin-name` directory -contained alongside that plugin's code. For instance, for AppRole, you would: -`$ cd vault/builtin/credential/approle/cmd/approle`. Once in that directory, -you would run `$ go build` to obtain a new binary for the AppRole plugin. Then -you would add it to the plugin catalog as per normal, and enable it. - -# Plugin Architecture - -Vault's plugins are completely separate, standalone applications that Vault -executes and communicates with over RPC. This means the plugin process does not -share the same memory space as Vault and therefore can only access the -interfaces and arguments given to it. This also means a crash in a plugin can not -crash the entirety of Vault. - -It is possible to enable a custom plugin with a name that's identical to a -built-in plugin. In such a situation, Vault will always choose the custom plugin -when enabling it. - -## Plugin Lifecycle - -Vault plugins are long-running processes that remain running once they are -spawned by Vault, the parent process. Plugin processes can be started by Vault's -active node and performance standby nodes. Additionally, there are cases where -plugin processes may be terminated by Vault. These cases include but are not -limited to: - -- Vault active node step-down -- Vault barrier seal -- Vault graceful shutdown -- Disabling a Secrets Engine or Auth method that uses external plugins -- Database configured connection deletion -- Database configured connection update -- Database configured connection reset request -- Database root credentials rotation -- WAL Rollback from a previously failed root credentials rotation operation - -The lifecycle of plugin processes are managed automatically by Vault. -Termination of these processes are typical in certain scenarios, such as the -ones listed above. Vault will start plugin processes when needed, typically by -lazily loading the plugin when a request that requires the plugin is received by -Vault. A plugin process may be started or terminated through other internal -processes within Vault as well. Since Vault manages and tracks the lifecycle of -its plugins, these processes should not be terminated by anything other than -Vault. - -## Plugin Communication - -Vault creates a mutually authenticated TLS connection for communication with the -plugin's RPC server. While invoking the plugin process, Vault passes a [wrapping -token](/docs/concepts/response-wrapping) to the -plugin process' environment. This token is single use and has a short TTL. Once -unwrapped, it provides the plugin with a uniquely generated TLS certificate and -private key for it to use to talk to the original Vault process. - -The [`api_addr`][api_addr] must be set in order for the plugin process to -establish communication with the Vault server during mount time. If the storage -backend has HA enabled and supports automatic host address detection -(e.g. Consul), Vault will automatically attempt to determine the `api_addr` as -well. - -~> Note: Prior to Vault version 1.9.2, reading the original connection's TLS -connection state is not supported in plugins. - -## Plugin Registration - -An important consideration of Vault's plugin system is to ensure the plugin -invoked by Vault is authentic and maintains integrity. There are two components -that a Vault operator needs to configure before external plugins can be run, the -plugin directory and the plugin catalog entry. - -### Plugin Directory - -The plugin directory is a configuration option of Vault, and can be specified in -the [configuration file](/docs/configuration). -This setting specifies a directory in which all plugin binaries must live; -_this value cannot be a symbolic link_. A plugin -can not be added to Vault unless it exists in the plugin directory. There is no -default for this configuration option, and if it is not set plugins can not be -added to Vault. - -~> Warning: A Vault operator should take care to lock down the permissions on -this directory to ensure a plugin can not be modified by an unauthorized user -between the time of the SHA check and the time of plugin execution. - -### Plugin Catalog - -The plugin catalog is Vault's list of approved plugins. The catalog is stored in -Vault's barrier and can only be updated by a Vault user with sudo permissions. -Upon adding a new plugin, the plugin name, SHA256 sum of the executable, and the -command that should be used to run the plugin must be provided. The catalog will -make sure the executable referenced in the command exists in the plugin -directory. When added to the catalog the plugin is not automatically executed, -it instead becomes visible to backends and can be executed by them. For more -information on the plugin catalog please see the [Plugin Catalog API -docs](/api/system/plugins-catalog). - -An example of plugin registration in current versions of Vault: - -```shell-session -$ vault plugin register -sha256= \ - secret \ # type - myplugin-database-plugin - -Success! Registered plugin: myplugin-database-plugin -``` - -Vault versions prior to v0.10.4 lacked the `vault plugin` operator and the -registration step for them is: - -```shell-session -$ vault write sys/plugins/catalog/database/myplugin-database-plugin \ - sha256= \ - command="myplugin" - -Success! Data written to: sys/plugins/catalog/database/myplugin-database-plugin -``` - -### Plugin Execution - -When a backend wants to run a plugin, it first looks up the plugin, by name, in -the catalog. It then checks the executable's SHA256 sum against the one -configured in the plugin catalog. Finally Vault runs the command configured in -the catalog, sending along the JWT formatted response wrapping token and mlock -settings. Like Vault, plugins support [the use of mlock when available](/docs/configuration#disable_mlock). - -~> Note: If Vault is configured with `mlock` enabled, then the Vault executable and each -plugin executable in your [plugins directory](/docs/internals/plugins#plugin-directory) must be -given the ability to use the `mlock` syscall. - -### Plugin Upgrades - -Plugins may be updated by registering and reloading them. More details on the -upgrade procedure can be found in [Upgrading Vault Plugins](/docs/upgrading/plugins). - -### Troubleshooting - -#### Unrecognized remote plugin message - -If the following error is encountered when enabling a plugin secret engine or -auth method: - -```sh -Unrecognized remote plugin message: - -This usually means that the plugin is either invalid or simply -needs to be recompiled to support the latest protocol. -``` - -Verify whether the Vault process has `mlock` enabled, and if so run the -following command against the plugin binary: - -```sh -sudo setcap cap_ipc_lock=+ep -``` - -# Plugin Development - -~> Advanced topic! Plugin development is a highly advanced topic in Vault, and -is not required knowledge for day-to-day usage. If you don't plan on writing any -plugins, we recommend not reading this section of the documentation. - -Because Vault communicates to plugins over a RPC interface, you can build and -distribute a plugin for Vault without having to rebuild Vault itself. This makes -it easy for you to build a Vault plugin for your organization's internal use, -for a proprietary API that you don't want to open source, or to prototype -something before contributing it back to the main project. - -In theory, because the plugin interface is HTTP, you could even develop a plugin -using a completely different programming language! (Disclaimer, you would also -have to re-implement the plugin API which is not a trivial amount of work.) - -Developing a plugin is simple. The only knowledge necessary to write -a plugin is basic command-line skills and basic knowledge of the -[Go programming language](http://golang.org). - -Your plugin implementation needs to satisfy the interface for the plugin -type you want to build. You can find these definitions in the docs for the -backend running the plugin. - -```go -package main - -import ( - "os" - - myPlugin "your/plugin/import/path" - "github.com/hashicorp/vault/api" - "github.com/hashicorp/vault/sdk/plugin" -) - -func main() { - apiClientMeta := &api.PluginAPIClientMeta{} - flags := apiClientMeta.FlagSet() - flags.Parse(os.Args[1:]) - - tlsConfig := apiClientMeta.GetTLSConfig() - tlsProviderFunc := api.VaultPluginTLSProvider(tlsConfig) - - err := plugin.Serve(&plugin.ServeOpts{ - BackendFactoryFunc: myPlugin.Factory, - TLSProviderFunc: tlsProviderFunc, - }) - if err != nil { - logger := hclog.New(&hclog.LoggerOptions{}) - - logger.Error("plugin shutting down", "error", err) - os.Exit(1) - } -} -``` - -And that's basically it! You would just need to change `myPlugin` to your actual -plugin. For more information on how to register and enable your plugin, check out the [Building Plugin Backends](https://learn.hashicorp.com/vault/developer/plugin-backends) tutorial. - -[api_addr]: /docs/configuration#api_addr diff --git a/website/content/docs/partnerships.mdx b/website/content/docs/partnerships.mdx index 7e0eb410dd70..187b288e6abf 100644 --- a/website/content/docs/partnerships.mdx +++ b/website/content/docs/partnerships.mdx @@ -16,7 +16,7 @@ This program is intended to be largely a self-service process with links and gui Vault is an Identity-based security solution that leverages trusted sources of identity to keep secrets and application data secured with one centralized, audited workflow for tightly controlling access to secrets across applications, systems, and infrastructure while encrypting data both in flight and at rest. For a full description of the current features please refer to the Vault [website](/). -Vault has a secure [plugin](/docs/internals/plugins) architecture. Vault’s plugins are completely separate, standalone applications that Vault executes and communicates with over RPC. This means the plugin process does not share the same memory space as Vault and therefore can only access the interfaces and arguments given to it. +Vault has a secure [plugin](/docs/plugins) architecture. Vault’s plugins are completely separate, standalone applications that Vault executes and communicates with over RPC. This means the plugin process does not share the same memory space as Vault and therefore can only access the interfaces and arguments given to it. Vault plugins can be built-in and bundled with the Vault binary, or be external that has to be manually mounted. Built-in plugins are developed by HashiCorp, while external plugins can be developed by HashiCorp, technology partners, or the community. There is a curated collection of all plugins, both built-in and external, located on the [Plugin Portal](/docs/plugin-portal). diff --git a/website/content/docs/plugin.mdx b/website/content/docs/plugin.mdx deleted file mode 100644 index 0e930187a039..000000000000 --- a/website/content/docs/plugin.mdx +++ /dev/null @@ -1,54 +0,0 @@ ---- -layout: docs -page_title: Custom Plugin Backends -description: >- - Plugin backends are mountable backends that are implemented using Vault's - plugin system. ---- - -# Custom Plugin Backends - -Plugin backends are the components in Vault that can be implemented separately from Vault's -builtin backends. These backends can be either authentication or secrets engines. - -The [`api_addr`][api_addr] must be set in order for the plugin process to establish -communication with the Vault server during mount time. If the storage backend -has HA enabled and supports automatic host address detection (e.g. Consul), -Vault will automatically attempt to determine the `api_addr` as well. - -Detailed information regarding the plugin system can be found in the -[internals documentation](/docs/internals/plugins). - -# Enabling/Disabling Plugin Backends - -Before a plugin backend can be mounted, it needs to be registered via the -[plugin catalog](/docs/internals/plugins#plugin-catalog). After -the plugin is registered, it can be mounted by specifying the registered plugin name: - -```shell-session -$ vault secrets enable -path=my-secrets passthrough-plugin -Success! Enabled the passthrough-plugin secrets engine at: my-secrets/ -``` - -Listing secrets engines will display secrets engines that are mounted as -plugins: - -```shell-session -$ vault secrets list -Path Type Accessor Plugin Default TTL Max TTL Force No Cache Replication Behavior Description -my-secrets/ plugin plugin_deb84140 passthrough-plugin system system false replicated -``` - -Disabling a plugin backend is the identical to disabling internal secrets engines: - -```shell-session -$ vault secrets disable my-secrets -``` - -# Upgrading Plugins - -Upgrade instructions can be found in the [Upgrading Plugins - Guides][upgrading_plugins] -page. - -[api_addr]: /docs/configuration#api_addr -[upgrading_plugins]: /docs/upgrading/plugins diff --git a/website/content/docs/plugins/index.mdx b/website/content/docs/plugins/index.mdx new file mode 100644 index 000000000000..ca7fd6415f25 --- /dev/null +++ b/website/content/docs/plugins/index.mdx @@ -0,0 +1,39 @@ +--- +layout: docs +page_title: Plugin System +description: Learn about Vault's plugin system. +--- + + +# Plugin System + +All Vault auth methods and secrets engines are considered plugins. This simple concept +allows both built-in and external plugins to be treated like Legos. Any plugin +can exist at multiple different locations. Different versions of a plugin may +be at each location, with each version differing from Vault's version. + +## Built-In Plugins + +Built-in plugins are shipped with Vault, often for commonly used implementations, +and require no additional operator intervention to run. Built-in plugins are +just like any other backend code inside Vault. + +To use a different or edited version of a built-in plugin, the plugin must be +run as an external plugin. See [Overriding Built-in Plugins](/docs/upgrading/plugins#overriding-built-in-plugins) +for details on how to override a built-in plugin in-place. + +## External Plugins + +External plugins are not shipped with Vault and require additional operator +intervention to run. + +To run an external plugin, a binary of the plugin is required. Plugin +binaries can be obtained from [releases.hashicorp.com](https://releases.hashicorp.com/) +or they can be [built from source](/docs/plugins/plugin-development#building-a-plugin-from-source). + +Vault's external plugins are completely separate, standalone applications that +Vault executes and communicates with over RPC. Each time a Vault secret engine +or auth method is mounted, a new process is spawned. However, database plugins +can be made to implement [plugin multiplexing](/docs/plugins/plugin-architecture#plugin-multiplexing) +which allows a single plugin process to be used for multiple database +connections. diff --git a/website/content/docs/plugins/plugin-architecture.mdx b/website/content/docs/plugins/plugin-architecture.mdx new file mode 100644 index 000000000000..420fb1eab4fb --- /dev/null +++ b/website/content/docs/plugins/plugin-architecture.mdx @@ -0,0 +1,190 @@ +--- +layout: docs +page_title: External Plugin Architecture +description: Learn about Vault's plugin architecture. +--- + +# External Plugin Architecture + +Vault's external plugins are completely separate, standalone applications that Vault +executes and communicates with over RPC. This means the plugin process does not +share the same memory space as Vault and therefore can only access the +interfaces and arguments given to it. This also means a crash in a plugin can not +crash the entirety of Vault. + +It is possible to enable a custom plugin with a name that's identical to a +built-in plugin. In such a situation, Vault will always choose the custom plugin +when enabling it. + +## External Plugin Lifecycle + +Vault external plugins are long-running processes that remain running once they are +spawned by Vault, the parent process. Plugin processes can be started by Vault's +active node and performance standby nodes. Additionally, there are cases where +plugin processes may be terminated by Vault. These cases include, but are not +limited to: + +- Vault active node step-down +- Vault barrier seal +- Vault graceful shutdown +- Disabling a Secrets Engine or Auth method that uses external plugins +- Database configured connection deletion +- Database configured connection update +- Database configured connection reset request +- Database root credentials rotation +- WAL Rollback from a previously failed root credentials rotation operation + +The lifecycle of plugin processes are managed automatically by Vault. +Termination of these processes are typical in certain scenarios, such as the +ones listed above. Vault will start plugin processes when needed, typically by +lazily loading the plugin when a request that requires the plugin is received by +Vault. A plugin process may be started or terminated through other internal +processes within Vault as well. Since Vault manages and tracks the lifecycle of +its plugins, these processes should not be terminated by anything other than +Vault. + +### External Plugin Scaling Characteristics + +External plugins are able to leverage [Performance Standbys](/docs/enterprise/performance-standby) +without any explicit action by a plugin author. The default behavior of Vault +Enterprise is to attempt to handle all requests, including requests to plugins, +on performance standbys. If the plugin request makes any attempt to modify +storage, the request will receive a readonly error, and the request routing +code will then forward the request to the active node. In other words, plugins +can scale horizontally on Vault Enterprise without any effort on the plugin +author's part. + +## Plugin Communication + +Vault creates a mutually authenticated TLS connection for communication with +the plugin's RPC server. Database secrets engines make use of the AutoMTLS +feature of [go-plugin](https://www.github.com/hashicorp/go-plugin) which will +automatically negotiate mTLS for transport authentication. For all other +plugins, Vault passes a [wrapping token](/docs/concepts/response-wrapping) to +the plugin process' environment. This token is single use and has a short TTL. +Once unwrapped, it provides the plugin with a uniquely generated TLS +certificate and private key for it to use to talk to the original Vault +process. + +The [`api_addr`](/docs/configuration#api_addr) must be set in order for the +plugin process to establish communication with the Vault server during mount +time. If the storage backend has HA enabled and supports automatic host address +detection (e.g. Consul), Vault will automatically attempt to determine the +`api_addr` as well. + +~> Note: Prior to Vault version 1.9.2, reading the original connection's TLS +connection state is not supported in plugins. + +## Plugin Registration + +An important consideration of Vault's plugin system is to ensure the plugin +invoked by Vault is authentic and maintains integrity. There are two components +that a Vault operator needs to configure before external plugins can be run- the +plugin directory and the plugin catalog entry. + +### Plugin Directory + +The plugin directory is a configuration option of Vault and can be specified in +the [configuration file](/docs/configuration). +This setting specifies a directory in which all plugin binaries must live; +_this value cannot be a symbolic link_. A plugin +cannot be added to Vault unless it exists in the plugin directory. There is no +default for this configuration option, and if it is not set, plugins cannot be +added to Vault. + +~> Warning: A Vault operator should take caution and lock down the permissions on +this directory to ensure a plugin cannot be modified by an unauthorized user +between the time of the SHA check and the time of plugin execution. + +### Plugin Catalog + +The plugin catalog is Vault's list of approved plugins. The catalog is stored in +Vault's barrier and can only be updated by a Vault user with sudo permissions. +Upon adding a new plugin, the plugin name, SHA256 sum of the executable, and the +command that should be used to run the plugin must be provided. The catalog will +ensure the executable referenced in the command exists in the plugin +directory. When added to the catalog, the plugin is not automatically executed, +but becomes visible to backends and can be executed by them. For more +information on the plugin catalog please see the [Plugin Catalog API +docs](/api-docs/system/plugins-catalog). + +An example of plugin registration in current versions of Vault: + +```shell-session +$ vault plugin register -sha256= \ + secret \ # type + myplugin-database-plugin + +Success! Registered plugin: myplugin-database-plugin +``` + +Vault versions prior to v0.10.4 lacked the `vault plugin` operator and the +registration step for them is: + +```shell-session +$ vault write sys/plugins/catalog/database/myplugin-database-plugin \ + sha256= \ + command="myplugin" + +Success! Data written to: sys/plugins/catalog/database/myplugin-database-plugin +``` + +### Plugin Execution + +When a backend wants to run a plugin, it first looks up the plugin, by name, in +the catalog. It then checks the executable's SHA256 sum against the one +configured in the plugin catalog. Finally Vault runs the command configured in +the catalog, sending along the JWT formatted response wrapping token and mlock +settings. Like Vault, plugins support [the use of mlock when available](/docs/configuration#disable_mlock). + +~> Note: If Vault is configured with `mlock` enabled, then the Vault executable +and each plugin executable in your [plugins directory](/docs/plugins/plugin-architecture#plugin-directory) +must be given the ability to use the `mlock` syscall. + +### Plugin Upgrades + +External plugins may be updated by registering and reloading them. More details +on the upgrade procedure can be found in +[Upgrading Vault Plugins](/docs/upgrading/plugins). + +## Plugin Multiplexing + +Database plugins can be made to implement plugin multiplexing, +allowing a single plugin process to be used for multiple database +connections. This single process, per database plugin, will be multiplexed +across all Vault namespaces for mounts of this type. Multiplexing a plugin +does not affect the current behavior of existing plugins. + +To enable multiplexing, the plugin must be compiled with the `ServeMultiplex` +function call from Vault's `dbplugin` package. At this time, there is no +opt-out capability for plugins that implement multiplexing. To use a +non-multiplexed plugin, run an older version of the plugin, i.e., the +plugin calls the `dbplugin.Serve` function. More details +on implementing plugin multiplexing can be found in +[Upgrading Vault Plugins](/docs/secrets/databases/custom#serving-a-plugin-with-multiplexing). + +## Troubleshooting + +### Unrecognized remote plugin message + +If the following error is encountered when enabling a plugin secret engine or +auth method: + + + +```sh +Unrecognized remote plugin message: + +This usually means that the plugin is either invalid or simply +needs to be recompiled to support the latest protocol. +``` + + + +Verify whether the Vault process has `mlock` enabled, and if so, run the +following command against the plugin binary: + +```shell-session +$ sudo setcap cap_ipc_lock=+ep +``` + diff --git a/website/content/docs/plugins/plugin-development.mdx b/website/content/docs/plugins/plugin-development.mdx new file mode 100644 index 000000000000..276ec669ff56 --- /dev/null +++ b/website/content/docs/plugins/plugin-development.mdx @@ -0,0 +1,91 @@ +--- +layout: docs +page_title: Plugin Development +description: Learn about Vault plugin development. +--- + +# Plugin Development + +~> Advanced topic! Plugin development is a highly advanced topic in Vault, and +is not required knowledge for day-to-day usage. If you don't plan on writing any +plugins, we recommend not reading this section of the documentation. + +Because Vault communicates to plugins over a RPC interface, you can build and +distribute a plugin for Vault without having to rebuild Vault itself. This makes +it easy for you to build a Vault plugin for your organization's internal use, +for a proprietary API that you don't want to open source, or to prototype +something before contributing it back to the main project. + +In theory, because the plugin interface is HTTP, you could even develop a plugin +using a completely different programming language! (Disclaimer, you would also +have to re-implement the plugin API which is not a trivial amount of work.) + +Developing a plugin is simple. The only knowledge necessary to write +a plugin is basic command-line skills and basic knowledge of the +[Go programming language](http://golang.org). + +Your plugin implementation needs to satisfy the interface for the plugin +type you want to build. You can find these definitions in the docs for the +backend running the plugin. + +```go +package main + +import ( + "os" + + myPlugin "your/plugin/import/path" + "github.com/hashicorp/vault/api" + "github.com/hashicorp/vault/sdk/plugin" +) + +func main() { + apiClientMeta := &api.PluginAPIClientMeta{} + flags := apiClientMeta.FlagSet() + flags.Parse(os.Args[1:]) + + tlsConfig := apiClientMeta.GetTLSConfig() + tlsProviderFunc := api.VaultPluginTLSProvider(tlsConfig) + + err := plugin.Serve(&plugin.ServeOpts{ + BackendFactoryFunc: myPlugin.Factory, + TLSProviderFunc: tlsProviderFunc, + }) + if err != nil { + logger := hclog.New(&hclog.LoggerOptions{}) + + logger.Error("plugin shutting down", "error", err) + os.Exit(1) + } +} +``` + +And that's basically it! You would just need to change `myPlugin` to your actual +plugin. + +[api_addr]: /docs/configuration#api_addr + +## Building a Plugin from Source + +To build a plugin from source, first navigate to the location holding the +desired plugin version. Next, run `go build` to obtain a new binary for the +plugin. Finally, +[register](/docs/plugins/plugin-architecture#plugin-registration) the +plugin and enable it. + +## Plugin Development - Resources + +For more information on how to register and enable your plugin, refer to the +[Building Plugin Backends](https://learn.hashicorp.com/vault/developer/plugin-backends) +tutorial. + +Other HashiCorp plugin development resources: + +* [vault-auth-plugin-example](https://github.com/hashicorp/vault-auth-plugin-example) +* [Custom Secrets Engines](https://learn.hashicorp.com/collections/vault/custom-secrets-engine) + +### Plugin Development - Resources - Community + +See the [Plugin Portal](/docs/plugins/plugin-portal#community) to find +Community plugin examples/guides developed by community members. HashiCorp does +not validate these for correctness. diff --git a/website/content/docs/plugins/plugin-management.mdx b/website/content/docs/plugins/plugin-management.mdx new file mode 100644 index 000000000000..b634745959fb --- /dev/null +++ b/website/content/docs/plugins/plugin-management.mdx @@ -0,0 +1,69 @@ +--- +layout: docs +page_title: Plugin Management +description: >- + External Plugins are mountable backends that are implemented using Vault's + plugin system. +--- + +# Plugin Management + +External plugins are the components in Vault that can be implemented separately +from Vault's built-in plugins. These plugins can be either authentication or +secrets engines. + +The [`api_addr`][api_addr] must be set in order for the plugin process to +establish communication with the Vault server during mount time. If the storage +backend has HA enabled and supports automatic host address detection (e.g. +Consul), Vault will automatically attempt to determine the `api_addr` as well. + +Detailed information regarding the plugin system can be found in the +[internals documentation](/docs/plugins). + +## Registering External Plugins + +Before an external plugin can be mounted, it needs to be +[registered](/docs/plugins/plugin-architecture#plugin-registration) in the +plugin catalog to ensure the plugin invoked by Vault is authentic and maintains +integrity: + +```shell-session +$ vault plugin register -sha256= \ + secret \ # type + my-secrets + +Success! Registered plugin: myplugin-database-plugin +``` + +## Enabling/Disabling External Plugins + +After the plugin is registered, it can be mounted by specifying the registered +plugin name: + +```shell-session +$ vault secrets enable -path=my-secrets passthrough-plugin +Success! Enabled the passthrough-plugin secrets engine at: my-secrets/ +``` + +Listing secrets engines will display secrets engines that are mounted as +plugins: + +```shell-session +$ vault secrets list +Path Type Accessor Plugin Default TTL Max TTL Force No Cache Replication Behavior Description +my-secrets/ plugin plugin_deb84140 passthrough-plugin system system false replicated +``` + +Disabling an external plugins is identical to disabling a built-in plugin: + +```shell-session +$ vault secrets disable my-secrets +``` + +## Upgrading Plugins + +Upgrade instructions can be found in the [Upgrading Plugins - Guides][upgrading_plugins] +page. + +[api_addr]: /docs/configuration#api_addr +[upgrading_plugins]: /docs/upgrading/plugins diff --git a/website/content/docs/plugin-portal.mdx b/website/content/docs/plugins/plugin-portal.mdx similarity index 97% rename from website/content/docs/plugin-portal.mdx rename to website/content/docs/plugins/plugin-portal.mdx index df563bf67dd7..92a8889e4024 100644 --- a/website/content/docs/plugin-portal.mdx +++ b/website/content/docs/plugins/plugin-portal.mdx @@ -7,10 +7,10 @@ description: A curated collection of official, partner, and community Vault plug # Plugin Portal This page contains a curated collection of official, partner, and community -[Vault plugins](/docs/internals/plugins). +[Vault plugins](/docs/plugins). For more information about plugin development, refer to this [documentation -section](/docs/internals/plugins#plugin-development) and this [Learn +section](/docs/plugins/plugin-development) and this [Learn Guide](https://learn.hashicorp.com/vault/developer/plugin-backends). ## Official @@ -23,7 +23,7 @@ if necessary. If a plugin exists separately under its own repository, follow the instructions within that repository to develop, test, and build the plugin. If a repository exists within the Vault repository, the plugin can be built as instructed in -[here](/docs/internals/plugins#built-in-plugins). +[here](/docs/plugins#built-in-plugins). ### Auth diff --git a/website/content/docs/secrets/databases/custom.mdx b/website/content/docs/secrets/databases/custom.mdx index f33e3b85d345..869f9b749c4f 100644 --- a/website/content/docs/secrets/databases/custom.mdx +++ b/website/content/docs/secrets/databases/custom.mdx @@ -3,7 +3,7 @@ layout: docs page_title: Custom - Database - Secrets Engines description: |- The database secrets engine allows new functionality to be added through a - plugin interface without needing to modify vault's core code. This allows you + plugin interface without needing to modify Vault's core code. This allows you write your own code to generate credentials in any database you wish. It also allows databases that require dynamically linked libraries to be used as plugins while keeping Vault itself statically linked. @@ -19,18 +19,25 @@ for more details. ~> **Advanced topic!** Plugin development is a highly advanced topic in Vault, and is not required knowledge for day-to-day usage. If you don't plan on writing -any plugins, we recommend not reading this section of the documentation. +any plugins, feel free to skip this section of the documentation. The database secrets engine allows new functionality to be added through a -plugin interface without needing to modify vault's core code. This allows you +plugin interface without needing to modify Vault's core code. This allows you write your own code to generate credentials in any database you wish. It also allows databases that require dynamically linked libraries to be used as plugins while keeping Vault itself statically linked. -Please read the [Plugins internals](/docs/internals/plugins) docs for more +Please read the [Plugins internals](/docs/plugins) docs for more information about the plugin system before getting started building your Database plugin. +Database plugins can be made to implement +[plugin multiplexing](/docs/plugins/plugin-architecture#plugin-multiplexing) +which allows a single plugin process to be used for multiple database +connections. To enable multiplexing, the plugin must be compiled with the +`ServeMultiplex` function call from Vault's `dbplugin` package. + + ## Plugin Interface All plugins for the database secrets engine must implement the same interface. This interface @@ -100,12 +107,19 @@ the configuration is valid and able to connect to the database in question. If t false, no connection should be made during the `Initialize` call, but subsequent calls to the other functions will need to open a connection. -## Serving your plugin +## Serving A Plugin + +### Serving A Plugin with Multiplexing + +~> Plugin multiplexing requires `github.com/hashicorp/vault/sdk v0.4.0` or above. + +The plugin runs as a separate binary outside of Vault, so the plugin itself +will need a `main` function. Use the `ServeMultiplex` function within +`sdk/database/dbplugin/v5` to serve your multiplexed plugin. You will also need +to pass some TLS configuration information that Vault uses when initializing +the plugin. -The plugin runs as a separate binary outside of Vault, so the plugin itself will need a `main` -function. Use the `Serve` function within `sdk/database/dbplugin/v5` to serve your plugin. You -will also need to pass some TLS configuration information that Vault uses when initializing the -plugin. Below is an example setup: +Below is an example setup: ```go package main @@ -128,12 +142,7 @@ func main() { } func Run() error { - dbType, err := New() - if err != nil { - return err - } - - dbplugin.Serve(dbType.(dbplugin.Database)) + dbplugin.ServeMultiplex(dbType.(dbplugin.New)) return nil } @@ -172,6 +181,29 @@ func (db *MyDatabase) secretValues() map[string]string { Replacing `MyDatabase` with the actual implementation of your database plugin. +### Serving A Plugin without Multiplexing + +Serving a plugin without multiplexing requires calling the `Serve` function +from `sdk/database/dbplugin/v5` to serve your plugin. You will also need to +pass some TLS configuration information that Vault uses when initializing the +plugin. + +The setup is exactly the same as the multiplexed case above, except for the +`Run` function: + +```go +func Run() error { + dbType, err := New() + if err != nil { + return err + } + + dbplugin.Serve(dbType.(dbplugin.Database)) + + return nil +} +``` + ## Running your plugin The above main package, once built, will supply you with a binary of your @@ -179,7 +211,7 @@ plugin. We also recommend if you are planning on distributing your plugin to build with [gox](https://github.com/mitchellh/gox) for cross platform builds. To use your plugin with the database secrets engine you need to place the binary in the -plugin directory as specified in the [plugin internals](/docs/internals/plugins) docs. +plugin directory as specified in the [plugin internals](/docs/plugins) docs. You should now be able to register your plugin into the vault catalog. To do this your token will need sudo permissions. @@ -200,7 +232,36 @@ $ vault write database/config/mydatabase \ myplugins_connection_details="..." ``` -## Upgrading database plugins +## Upgrading database plugins to leverage plugin multiplexing + +### Background + +Scaling many external plugins can become resource intensive. To address +performance problems with scaling external plugins, database plugins can be +made to implement [plugin multiplexing](/docs/plugins/plugin-architecture#plugin-multiplexing) +which allows a single plugin process to be used for multiple database +connections. To enable multiplexing, the plugin must be compiled with the +`ServeMultiplex` function call from Vault's `dbplugin` package. + +### Upgrading your database plugin to leverage plugin multiplexing + +There is only one step required to upgrade from a non-multiplexed to a +multiplexed database plugin: Change the `Serve` function call to `ServeMultiplex`. + +This will run the RPC server for the plugin just as before. However, the +`ServeMultiplex` function takes the factory function directly as its argument. +This factory function is a function that returns an object that implements the +[`dbplugin.Database` interface](/docs/secrets/databases/custom#plugin-interface). + +### When should plugin multiplexing be avoided? + +Some use cases that should avoid plugin multiplexing might include: + +* Plugin process level separation is required +* Avoiding restart across all mounts/database connections for a plugin type on + crashes or plugin reload calls + +## Upgrading database plugins to the V5 interface ### Background diff --git a/website/content/docs/secrets/venafi.mdx b/website/content/docs/secrets/venafi.mdx index 9ffd2a27bd47..ebe38a536cf2 100644 --- a/website/content/docs/secrets/venafi.mdx +++ b/website/content/docs/secrets/venafi.mdx @@ -24,7 +24,7 @@ workloads are the primary focus of the Venafi secrets engine. As such, revocation is not currently supported. The Venafi secrets engine makes use of HashiCorp Vault's -[plugin system](/docs/internals/plugins) +[plugin system](/docs/plugins) and Venafi's [VCert Client SDK](https://github.com/Venafi/vcert). If you have questions about the Venafi secrets engine, have an issue to report, or have developed improvements that you want to contribute, visit the @@ -104,7 +104,7 @@ and any other dependencies that appear in the Venafi Cloud documentation. Before certificates can be issued, you must complete these steps to configure the Venafi secrets engine: -1. Create the [directory](/docs/internals/plugins#plugin-directory) +1. Create the [directory](/docs/plugins/plugin-architecture#plugin-directory) where your Vault server will look for plugins (e.g. /etc/vault/vault_plugins). The directory must not be a symbolic link. On macOS, for example, /etc is a link to /private/etc. To avoid errors, choose an alternative directory such @@ -138,7 +138,7 @@ Venafi secrets engine: ``` 1. Register the `venafi-pki-backend` plugin in the Vault - [system catalog](/docs/internals/plugins#plugin-catalog): + [system catalog](/docs/plugins/plugin-architecture#plugin-catalog): ```text $ vault write sys/plugins/catalog/secret/venafi-pki-backend \ diff --git a/website/content/docs/upgrading/plugins.mdx b/website/content/docs/upgrading/plugins.mdx index efd5877f3a35..38bff76a9e68 100644 --- a/website/content/docs/upgrading/plugins.mdx +++ b/website/content/docs/upgrading/plugins.mdx @@ -6,11 +6,11 @@ description: These are general upgrade instructions for Vault plugins. # Upgrading Vault Plugins -The following procedure details steps for upgrading a plugin that has already -been registered to the catalog on a running server. This procedure is applicable -to secret, auth, and database plugins. +## External Plugin Upgrade Procedure -## Upgrade Procedure +The following procedure details steps for upgrading an external plugin that has +been registered to the catalog on a running server. This procedure is +applicable to secret engines, auth methods, and database plugins. Vault executes plugin binaries when they are configured and roles are established around them. The binary cannot be modified or replaced while running, so @@ -21,16 +21,41 @@ Instead, you can restart or reload a plugin with the `sys/plugins/reload/backend` [API][plugin_reload_api]. Follow these steps to replace or upgrade a Vault plugin binary: -1. Register plugin_v1 to the catalog -2. Mount the plugin backend -3. Register plugin_v2 to the catalog under the same plugin name, but with - updated command to run plugin_v2 and updated sha256 of plugin_v2 -4. Trigger a plugin reload with `sys/plugins/reload/backend` to reload all +1. [Register][plugin_registration] version 1 of `my-db-plugin` to the catalog + +```shell-session +$ vault plugin register -sha256= \ + database \ # type + my-db-plugin +``` + +2. [Mount][plugin_management] the plugin backend + +```shell-session +$ vault secrets enable database +``` + +3. Register version 2 of `my-db-plugin` to the catalog under the same plugin + name, but with updated command to run version 2 of `my-db-plugin` and updated + sha256 of the new binary + +```shell-session +$ vault plugin register -sha256= \ + database \ # type + my-db-plugin +``` + +4. Trigger a [plugin reload][/docs/commands/plugin/reload] to reload all mounted backends using that plugin or a subset of the mounts using that plugin with either the `plugin` or `mounts` parameter respectively. -Until step 4, the mount will still use plugin_v1, and when the reload is -triggered, Vault will kill plugin_v1’s process and start a plugin_v2 process. +```shell-session +$ vault plugin reload -plugin my-db-plugin +``` + +Until step 4, the mount will still use version 1 of `my-db-plugin`, and when +the reload is triggered, Vault will kill `my-db-plugin`’s process and start the +new plugin process for `my-db-plugin` version 2. -> **Important:** Plugin reload of a new plugin binary must be performed on each Vault instance. Performing a plugin upgrade on a single @@ -38,4 +63,147 @@ instance or through a load balancer can result in mismatched plugin binaries within a cluster. On a replicated cluster this may be accomplished by setting the 'scope' parameter of the reload to 'global'. -[plugin_reload_api]: /api/system/plugins-reload-backend +## Overriding Built-in Plugins + +### Background + +Vault's auth methods and secrets engines are structured as plugins, but this +design is not obvious since many of them are built into Vault. + +You can see them with the Vault plugin list command, for example, the list of +Secrets engines: + +```shell-session +$ vault plugin list secret +Plugins +------- +ad +alicloud +aws +azure +cassandra +consul +gcp +gcpkms +kv +mongodb +mongodbatlas +mssql +mysql +nomad +openldap +pki +postgresql +rabbitmq +ssh +terraform +totp +transit +``` + +This will list all Secrets engines, internal (built-in) or external. To find +out if a plugin is built-in, we can query its info: + +```shell-session +$ vault plugin info secret azure +Key Value +--- ----- +args [] +builtin true +command n/a +name azure +sha256 n/a +``` + +Because these built-in engines are plugins, they can be overridden. This can be +a useful way to leverage features or bug fixes in plugins that are newer than +the version of Vault you're using, without updating or even restarting Vault, +and while retaining the data for your existing mount. + +Assume you have a new version of Azure Secrets and the binary is called +"azure_new". The binary needs to be in the [plugin directory](/docs/plugins/plugin-architecture#plugin-directory) +and can then be registered as either a distinct plugin, or overriding the +current one. + +~> **Important:** do not disable (`vault secrets disable ...`) any mount that has +data you're interested in; that would erase storage. For the in-place update, +register a new plugin atop the built-in one and leave any mounts alone. + +### Procedure for Overriding Built-in Plugins + +The syntax is the same as an external plugin, with the difference being you +name it the same as a built-in: + +```shell-session +$ vault plugin register \ + -sha256= \ + -command=azure_new \ + secret \ + azure +``` + +"-command=azure_new" is the name of the binary, "secret" is the plugin type, +and "azure" is the name of the built-in plugin that we're overriding. We can +verify that the override is in place: + +```shell-session +$ vault plugin info secret azure +Key Value +--- ----- +args [] +builtin false +command azure_new +name azure +sha256 f6f6ec45d37484c257aa9ff80444b9f244aaef1c650edf8a42a2a1d3f00db2c5 +``` + +At this point we've overridden the built-in, but it is not yet actively +handling requests. For that we run: + +```shell-session +$ vault plugin reload -plugin=azure +``` + +### Procedure for Reverting After Overriding A Built-in Plugin + +To revert the override, first deregister the plugin: + +```shell-session +$ vault plugin deregister secret azure +``` + +Next, verify the override has been reverted and we are now using the built-in +plugin: + +```shell-session +$ vault plugin info secret azure +Key Value +--- ----- +args [] +builtin true +command n/a +name azure +sha256 n/a +``` + +Finally, reload the plugin: + +```shell-session +$ vault plugin reload -plugin=azure +``` + +### Caveats to Overriding Built-in Plugins + +* As mentioned earlier, disabling existing mounts will wipe the existing data. +* This type of upgrade affects all uses of the plugin. So if you have 5 + different Azure Secrets mounts, they'll all change after the replacement. If + you don't want that, you'll need to register the plugin under a different name + and start with a fresh mount. +* In most cases, data upgrade and downgrade is not an issue. If the "new" version + introduces new data and you downgrade, the "old" version will ignore the + extraneous data. In some cases upgrading changes existing data in non-backwards + compatible ways, so it is good to check whether this is an issue. + +[plugin_reload_api]: /api-docs/system/plugins-reload-backend +[plugin_registration]: /docs/plugins/plugin-architecture#plugin-registration +[plugin_management]: /docs/plugins/plugin-management#enabling-disabling-external-plugins diff --git a/website/data/docs-nav-data.json b/website/data/docs-nav-data.json index 798ecb4ddd5e..8422e74899e5 100644 --- a/website/data/docs-nav-data.json +++ b/website/data/docs-nav-data.json @@ -76,10 +76,6 @@ "title": "Replication", "path": "internals/replication" }, - { - "title": "Plugins", - "path": "internals/plugins" - }, { "title": "Limits and Maximums", "path": "internals/limits" @@ -1272,14 +1268,30 @@ ] }, { - "title": "Plugin Backends", - "path": "plugin" - }, - { - "title": "Plugin Portal", - "path": "plugin-portal" + "title": "Plugins", + "routes": [ + { + "title": "Overview", + "path": "plugins" + }, + { + "title": "Plugin Architecture", + "path": "plugins/plugin-architecture" + }, + { + "title": "Plugin Development", + "path": "plugins/plugin-development" + }, + { + "title": "Plugin Management", + "path": "plugins/plugin-management" + }, + { + "title": "Plugin Portal", + "path": "plugins/plugin-portal" + } + ] }, - { "title": "Vault Integration Program", "path": "partnerships" diff --git a/website/redirects.next.js b/website/redirects.next.js index 1623a08b2036..2ffea0597fbe 100644 --- a/website/redirects.next.js +++ b/website/redirects.next.js @@ -230,6 +230,16 @@ module.exports = [ destination: '/docs/plugin', permanent: true, }, + { + source: '/docs/internals/plugins', + destination: '/docs/plugin', + permanent: true, + }, + { + source: '/docs/plugin-portal', + destination: '/docs/plugins/plugin-portal', + permanent: true, + }, { source: '/docs/secrets/generic', destination: '/docs/secrets/kv',