mirror of
https://github.com/hashicorp/vault.git
synced 2025-08-10 08:37:00 +02:00
* Fix style inconsistency * Fix typos * Update website/content/docs/platform/k8s/vso/secret-transformation.mdx Co-authored-by: Jonathan Frappier <92055993+jonathanfrappier@users.noreply.github.com> * Update website/content/docs/platform/k8s/helm/terraform.mdx Co-authored-by: Theron Voran <tvoran@users.noreply.github.com> * Update website/content/docs/platform/k8s/injector/annotations.mdx Co-authored-by: Theron Voran <tvoran@users.noreply.github.com> --------- Co-authored-by: Jonathan Frappier <92055993+jonathanfrappier@users.noreply.github.com> Co-authored-by: Theron Voran <tvoran@users.noreply.github.com>
337 lines
9.0 KiB
Plaintext
337 lines
9.0 KiB
Plaintext
---
|
|
layout: docs
|
|
page_title: Add a containerized secrets plugin to Vault
|
|
description: >-
|
|
Add a containerized secrets plugin to your Vault instance.
|
|
---
|
|
|
|
# Add a containerized secrets plugin to Vault
|
|
|
|
Run your external secrets plugins in containers to increases the isolation
|
|
between the plugin and Vault.
|
|
|
|
## Before you start
|
|
|
|
- **Your Vault instance must be running on Linux**.
|
|
- **Your Vault instance must have local access to the Docker Engine API**.
|
|
Vault uses the [Docker SDK](https://pkg.go.dev/github.com/docker/docker) to
|
|
manage containerized plugins.
|
|
- **You must have [gVisor](https://gvisor.dev/docs/user_guide/install/)
|
|
installed**. Vault uses `runsc` as the entrypoint to your container runtime.
|
|
- **If you are using a container runtime other than gVisor, you must have a
|
|
`runsc`-compatible container runtime installed**.
|
|
|
|
## Step 1: Install your container engine
|
|
|
|
Install one of the supported container engines:
|
|
|
|
- [Docker](https://docs.docker.com/engine/install/)
|
|
- [Rootless Docker](https://docs.docker.com/engine/security/rootless/)
|
|
|
|
## Step 2: Configure your container runtime
|
|
|
|
Update your container engine to use `runsc` for Unix sockets between the host
|
|
and plugin binary.
|
|
|
|
<Tabs>
|
|
|
|
<Tab heading="Docker">
|
|
|
|
1. Add `runsc` to your
|
|
[Docker daemon configuration](https://docs.docker.com/config/daemon):
|
|
|
|
```shell-session
|
|
$ sudo tee PATH_TO_DOCKER_DAEMON_CONFIG_FILE <<EOF
|
|
{
|
|
"runtimes": {
|
|
"runsc": {
|
|
"path": "PATH_TO_RUNSC_INSTALLATION",
|
|
"runtimeArgs": [
|
|
"--host-uds=all"
|
|
]
|
|
}
|
|
}
|
|
}
|
|
EOF
|
|
```
|
|
|
|
1. Restart Docker:
|
|
|
|
```shell-session
|
|
$ sudo systemctl reload docker
|
|
```
|
|
|
|
</Tab>
|
|
|
|
<Tab heading="Rootless Docker">
|
|
|
|
1. Create a configuration directory if it does not exist already:
|
|
|
|
```shell-session
|
|
$ mkdir -p ~/.config/docker
|
|
```
|
|
|
|
1. Add `runsc` to your Docker configuration:
|
|
|
|
```shell-session
|
|
$ tee ~/.config/docker/daemon.json <<EOF
|
|
{
|
|
"runtimes": {
|
|
"runsc": {
|
|
"path": "PATH_TO_RUNSC_INSTALLATION",
|
|
"runtimeArgs": [
|
|
"--host-uds=all"
|
|
"--ignore-cgroups"
|
|
]
|
|
}
|
|
}
|
|
}
|
|
EOF
|
|
```
|
|
|
|
1. Restart Docker:
|
|
|
|
```shell-session
|
|
$ systemctl --user restart docker
|
|
```
|
|
|
|
</Tab>
|
|
|
|
</Tabs>
|
|
|
|
## Step 3: Update the HashiCorp `go-plugin` library
|
|
|
|
You must build your plugin locally with v1.5.0+ of the HashiCorp
|
|
[`go-plugin`](https://github.com/hashicorp/go-plugin) library to ensure the
|
|
finished binary is compatible with containerization.
|
|
|
|
Use `go install` to pull the latest version of the plugin library from the
|
|
`hashicorp/go-plugin` repo on GitHub:
|
|
|
|
```shell-session
|
|
$ go install github.com/hashicorp/go-plugin@latest
|
|
```
|
|
|
|
<Tip title="The Vault SDK includes go-plugin">
|
|
|
|
If you build with the Vault SDK, you can update `go-plugin` with `go install`
|
|
by pulling the latest SDK version from the `hashicorp/vault` repo:
|
|
|
|
`go install github.com/hashicorp/vault/sdk@latest`
|
|
|
|
</Tip>
|
|
|
|
|
|
## Step 4: Build the plugin container
|
|
|
|
Containerized plugins must run as a binary in the finished container and
|
|
behave the same whether run in a container or as a standalone application:
|
|
|
|
1. Build your plugin binary so it runs on Linux.
|
|
1. Create a container file for your plugin with the compiled binary as the
|
|
entry-point.
|
|
1. Build the image with a unique tag.
|
|
|
|
For example, to build a containerized version of the built-in key-value (KV)
|
|
secrets plugin for Docker:
|
|
|
|
1. Clone the latest version of the KV secrets plugin from
|
|
`hashicorp/vault-plugin-secrets-kv`.
|
|
```shell-session
|
|
$ git clone https://github.com/hashicorp/vault-plugin-secrets-kv.git
|
|
```
|
|
1. Build the Go binary for Linux.
|
|
```shell-session
|
|
$ cd vault-plugin-secrets-kv ; CGO_ENABLED=0 GOOS=linux \
|
|
go build -o kv cmd/vault-plugin-secrets-kv/main.go
|
|
```
|
|
1. Create an empty Dockerfile.
|
|
```shell-session
|
|
$ touch Dockerfile
|
|
```
|
|
1. Update the empty `Dockerfile` with your infrastructure build details and the
|
|
compiled binary as the entry-point.
|
|
```Dockerfile
|
|
FROM gcr.io/distroless/static-debian12
|
|
COPY kv /bin/kv
|
|
ENTRYPOINT [ "/bin/kv" ]
|
|
```
|
|
1. Build the container image and assign an identifiable tag.
|
|
```shell-session
|
|
$ docker build -t hashicorp/vault-plugin-secrets-kv:mycontainer .
|
|
```
|
|
|
|
## Step 5: Register the plugin
|
|
|
|
Registering a containerized plugin with Vault is similar to registering any
|
|
other external plugin that is available locally to Vault.
|
|
|
|
1. Store the SHA256 of the plugin image:
|
|
```shell-session
|
|
$ export SHA256=$(docker images \
|
|
--no-trunc \
|
|
--format="{{ .ID }}" \
|
|
YOUR_PLUGIN_IMAGE_TAG | cut -d: -f2)
|
|
```
|
|
For example:
|
|
|
|
<CodeBlockConfig hideClipboard>
|
|
|
|
```shell-session
|
|
$ export SHA256=$(docker images \
|
|
--no-trunc \
|
|
--format="{{ .ID }}" \
|
|
hashicorp/vault-plugin-secrets-kv:mycontainer | cut -d: -f2)
|
|
```
|
|
|
|
</CodeBlockConfig>
|
|
|
|
1. Register the plugin with `vault plugin register` and specify your plugin
|
|
image with the `oci_image` flag:
|
|
```shell-session
|
|
$ vault plugin register \
|
|
-sha256="${SHA256}" \
|
|
-oci_image=YOUR_PLUGIN_IMAGE_TAG \
|
|
NEW_PLUGIN_TYPE NEW_PLUGIN_ID
|
|
```
|
|
For example:
|
|
|
|
<CodeBlockConfig hideClipboard>
|
|
|
|
```shell-session
|
|
$ vault plugin register \
|
|
-sha256="${SHA256}" \
|
|
-oci_image=hashicorp/vault-plugin-secrets-kv:mycontainer \
|
|
secret my-kv-container
|
|
```
|
|
|
|
</CodeBlockConfig>
|
|
|
|
1. Enable the new plugin for your Vault instance with `vault secrets enable` and
|
|
the new plugin ID:
|
|
```shell-session
|
|
$ vault secrets enable NEW_PLUGIN_ID
|
|
```
|
|
For example:
|
|
|
|
<CodeBlockConfig hideClipboard>
|
|
|
|
```shell-session
|
|
$ vault secrets enable my-kv-container
|
|
```
|
|
|
|
</CodeBlockConfig>
|
|
|
|
|
|
<Tip title="Customize container behavior with registration flags">
|
|
|
|
You can provide additional information about the image entrypoint, command,
|
|
and environment with the `-command`, `-args`, and `-env` flags for
|
|
`vault plugin register`.
|
|
|
|
</Tip>
|
|
|
|
## Step 6: Test your plugin
|
|
|
|
Now that the container is registered with Vault, you should be able to interact
|
|
with it like any other plugin. Try writing then fetching a new secret with your
|
|
new plugin.
|
|
|
|
|
|
1. Use `vault write` to store a secret with your containerized plugin:
|
|
```shell-session
|
|
$ vault write NEW_PLUGIN_ID/SECRET_PATH SECRET_KEY=SECRET_VALUE
|
|
```
|
|
For example:
|
|
|
|
<CodeBlockConfig hideClipboard>
|
|
|
|
```shell-session
|
|
$ vault write my-kv-container/testing subject=containers
|
|
Success! Data written to: my-kv-container/testing
|
|
```
|
|
|
|
</CodeBlockConfig>
|
|
|
|
1. Fetch the secret you just wrote:
|
|
```shell-session
|
|
$ vault read NEW_PLUGIN_ID/SECRET_PATH
|
|
```
|
|
For example:
|
|
|
|
<CodeBlockConfig hideClipboard>
|
|
|
|
```shell-session
|
|
$ vault read my-kv-container/testing
|
|
===== Data =====
|
|
Key Value
|
|
--- -----
|
|
subject containers
|
|
```
|
|
|
|
</CodeBlockConfig>
|
|
|
|
## Use alternative runtimes ((#alt-runtimes))
|
|
|
|
You can force Vault to use alternative runtimes provided the runtime is
|
|
installed locally.
|
|
|
|
To use an alternative runtime:
|
|
|
|
1. Register and name the runtime with `vault plugin runtime register`. For
|
|
example, to register the default Docker runtime (`runc`) as `docker-rt`:
|
|
```shell-session
|
|
$ vault plugin runtime register \
|
|
-oci_runtime=runc \
|
|
-type=container docker-rt
|
|
```
|
|
|
|
1. Use the `--runtime` flag during plugin registration to tell Vault what
|
|
runtime to use:
|
|
```shell-session
|
|
$ vault plugin register \
|
|
-runtime=RUNTIME_NAME \
|
|
-sha256="${SHA256}" \
|
|
-oci_image=YOUR_PLUGIN_IMAGE_TAG \
|
|
NEW_PLUGIN_TYPE NEW_PLUGIN_ID
|
|
```
|
|
For example:
|
|
|
|
<CodeBlockConfig hideClipboard>
|
|
|
|
```shell-session
|
|
$ vault plugin register \
|
|
-runtime=docker-rt \
|
|
-sha256="${SHA256}" \
|
|
-oci_image=hashicorp/vault-plugin-secrets-kv:mycontainer \
|
|
secret my-kv-container
|
|
```
|
|
|
|
</CodeBlockConfig>
|
|
|
|
## Troubleshooting
|
|
|
|
### Invalid backend version error
|
|
|
|
If you run into the following error while registering your plugin:
|
|
|
|
<CodeBlockConfig hideClipboard>
|
|
|
|
```plaintext
|
|
invalid backend version error: 2 errors occurred:
|
|
* error creating container: Error response from daemon: error while looking up the specified runtime path: exec: " /usr/bin/runsc": stat /usr/bin/runsc: no such file or directory
|
|
* error creating container: Error response from daemon: error while looking up the specified runtime path: exec: " /usr/bin/runsc": stat /usr/bin/runsc: no such file or directory
|
|
```
|
|
|
|
</CodeBlockConfig>
|
|
|
|
it means that Vault cannot find the executable for `runsc`. Confirm the
|
|
following is true before trying again:
|
|
|
|
1. You have gVisor installed locally to Vault.
|
|
1. The path to `runsc` is correct in you your Docker configuration.
|
|
1. Vault has permission to run the `runsc` executable.
|
|
|
|
If you still get errors when registering a plugin, the recommended workaround is
|
|
to use the default Docker runtime (`runc`) as an
|
|
[alternative runtime](#alt-runtimes). |