Export¶
vkv export requires an engine path (--path or --engine-path) and supports the following export formats (specify via --format flag).
See the CLI Reference for more details on the supported flags and env vars.
Warning
Vault allows / in the name of a KV engine. This makes it difficult for vkv to distinguish between directories and the KV engine name..
If your KV engine name/mount contains a / you have to specify it using --engine-path|-e, otherwise vkv will output the secrets wrong.
This also applies for any vkv import ... operations.
Info
vkv handles 3 different path arguments, specified using -e|-p
root path: any normal KV mount. Use-p.engine-path: in case your KV mount contains a/. Use-e.sub path: the path to the corresponding directory within a KV mount. When using-pthis is everything after the first/: e.g:kv/prod/db/; root path=kv, subpath=prod/db. In conjunction with a-eyou can specify a sub-path by using -p:-e=kv/prod -p=db.
base¶
Each secret shows its current version ([v=N]), when that version was created ((created X ago)) and any custom metadata ([key=value]):
> vkv export -p secret -f=base
secret/ [desc=key/value secret storage] [type=kv2]
├── admin [v=1] (created 5 minutes ago) [key=value]
│ └── sub=********
├── demo [v=1] (created 5 minutes ago)
│ └── foo=***
└── sub
├── demo [v=1] (created 5 minutes ago)
│ ├── demo=***********
│ ├── password=*******
│ └── user=*****
└── sub2
└── demo [v=2] (created 5 minutes ago) [admin=false key=value]
├── foo=***
├── password=********
└── user=****
Info
In a terminal, path elements are shown in bold and the version/age annotation in cyan. Colors are disabled automatically when the output is piped or redirected. Use --show-version=false to hide the [v=N] (created X ago) annotation.
yaml¶
Info
yaml and json always export real values (no masking) using flat, full secret-path keys. This keeps the output easy to consume programmatically and lets it be piped straight back into vkv import.
> vkv export -p secret -f=yaml
admin:
sub: password
demo:
foo: bar
sub/demo:
demo: hello world
password: s3cre5<
user: admin
sub/sub2/demo:
foo: bar
password: password
user: user
json¶
> vkv export -p secret -f=json
{
"admin": {
"sub": "password"
},
"demo": {
"foo": "bar"
},
"sub/demo": {
"demo": "hello world",
"password": "s3cre5<",
"user": "admin"
},
"sub/sub2/demo": {
"foo": "bar",
"password": "password",
"user": "user"
}
}
all-versions¶
The --all-versions flag exports every version of each KVv2 secret instead of only the latest one. It is supported by the base, yaml and json formats.
In the base (tree) format each version is shown with its creation time (and deleted/destroyed status), the key/value pairs it contained, and any custom metadata next to the secret name:
> vkv export -p secret --all-versions
secret/ [kv2] (key/value secret storage)
├── admin {key=value}
│ └── [Version 1 created 4 minutes ago]
│ └── sub=********
├── demo
│ └── [Version 1 created 4 minutes ago]
│ └── foo=***
└── sub
├── demo
│ └── [Version 1 created 4 minutes ago]
│ ├── demo=***********
│ ├── password=*******
│ └── user=*****
└── sub2
└── demo {admin=false key=value}
├── [Version 2 created 4 minutes ago]
│ ├── foo=***
│ ├── password=********
│ └── user=****
└── [Version 1 created 4 minutes ago]
├── foo=***
├── password=********
└── user=****
Info
In a terminal, path elements are shown in bold, version headers in cyan and metadata dimmed. Colors are automatically disabled when the output is piped or redirected.
The yaml and json formats emit the full version history per secret, including timestamps, destroyed/deletion_time status and custom metadata:
> vkv export -p secret/sub/sub2 --all-versions -f=json
{
"sub/sub2/demo": {
"custom_metadata": {
"admin": "false",
"key": "value"
},
"versions": [
{
"version": 2,
"created_time": "2024-05-28T05:57:52Z",
"destroyed": false,
"data": {
"foo": "bar",
"password": "password",
"user": "user"
}
},
{
"version": 1,
"created_time": "2024-05-28T04:47:54Z",
"destroyed": false,
"data": {
"foo": "bar",
"password": "password",
"user": "user"
}
}
]
}
}
export¶
> vkv export -p secret -f=export
export admin='key'
export demo='hello world'
export foo='bar'
export password='password'
export sub='password'
eval $(vkv export -p secret -f=export)
echo $admin
key
policy¶
> vkv export -p secret -f=policy
PATH CREATE READ UPDATE DELETE LIST ROOT
secret/sub/sub2/demo ✖ ✖ ✖ ✖ ✖ ✔
secret/admin ✖ ✖ ✖ ✖ ✖ ✔
secret/demo ✖ ✖ ✖ ✖ ✖ ✔
secret/sub/demo ✖ ✖ ✖ ✖ ✖ ✔
markdown¶
> vkv export -p secret -f=markdown
| PATH | KEY | VALUE | VERSION | METADATA |
|----------------------|----------|-------------|---------|-----------------------|
| secret/admin | sub | ******** | 1 | key=value |
| secret/demo | foo | *** | 1 | |
| secret/sub/demo | demo | *********** | 1 | |
| | password | ****** | | |
| | user | ***** | | |
| secret/sub/sub2/demo | admin | *** | 2 | admin=false key=value |
| | foo | *** | | |
| | password | ******** | | |
| | user | **** | | |
template¶
template is a special output format that allows you, render the output using Golangs template engine. Format template requires either a --template-file or a --template-string flag or the equivalent env vars.
The secrets are passed as map with the secret path as the key and the actual secrets as values:
# <PATH> <SECRETS>
secret/admin map[sub:password]
secret/demo map[foo:bar]
secret/sub/demo map[demo:hello world password:s3cre5< user:admin]
secret/sub/sub2/demo map[foo:bar password:password user:user]
Here is an advanced template that renders the secrets in a special env var export format. Note that within a --template-file or a --template-string the following functions are available: http://masterminds.github.io/sprig/:
# export.tmpl
{{- range $path, $secrets := . }}
{{- range $key, $value := $secrets }}
export {{ list $path $key | join "/" | replace "/" "_" | upper | trimPrefix "SECRET_" }}={{ $value | squote -}}
{{ end -}}
{{- end }}
This would result in the following output:
> vkv export -p secret -f=template --template-file=export.tmpl
export ADMIN_SUB='password'
export DEMO_FOO='bar'
export SUB_DEMO_DEMO='hello world'
export SUB_DEMO_PASSWORD='s3cre5<'
export SUB_DEMO_USER='admin'
export SUB_SUB2_DEMO_FOO='bar'
export SUB_SUB2_DEMO_PASSWORD='password'
export SUB_SUB2_DEMO_USER='user'
The yaml and json formats already emit flat, non-nested paths (see above). For the template format the secrets are passed to the template nested by default; enable --merge-paths to receive them as flat, full-path keys instead: