@varlock/hashicorp-vault-plugin 0.0.0 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +341 -0
- package/dist/plugin.cjs +1267 -0
- package/dist/plugin.cjs.map +1 -0
- package/dist/plugin.d.cts +2 -0
- package/package.json +50 -6
package/README.md
ADDED
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
# @varlock/hashicorp-vault-plugin
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@varlock/hashicorp-vault-plugin) [](https://github.com/dmno-dev/varlock) [](https://github.com/dmno-dev/varlock/blob/main/LICENSE)
|
|
4
|
+
|
|
5
|
+
This package is a [Varlock](https://varlock.dev) [plugin](https://varlock.dev/guides/plugins/) that enables loading data from [HashiCorp Vault](https://www.vaultproject.io/) (KV v2 secrets engine) / [OpenBao](https://openbao.org/) into your configuration.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Zero-config authentication** - Automatically uses Vault token from environment or CLI
|
|
10
|
+
- **AppRole authentication** - For automated and CI/CD workflows
|
|
11
|
+
- **Vault CLI integration** - Works seamlessly with `vault login` for local development
|
|
12
|
+
- **Auto-infer secret keys** from environment variable names
|
|
13
|
+
- **JSON key extraction** from secrets using `#` syntax or named `key` parameter
|
|
14
|
+
- **Path prefixing** with `pathPrefix` option for organized secret management
|
|
15
|
+
- **Default path** support for sharing a common secret path across items
|
|
16
|
+
- Support for Vault Enterprise namespaces
|
|
17
|
+
- Support for multiple Vault instances
|
|
18
|
+
- Automatic AppRole token caching and renewal
|
|
19
|
+
- Lightweight implementation using REST API (no heavy Vault SDK dependencies)
|
|
20
|
+
|
|
21
|
+
## Installation
|
|
22
|
+
|
|
23
|
+
If you are in a JavaScript based project and have a package.json file, you can either install the plugin explicitly
|
|
24
|
+
```bash
|
|
25
|
+
npm install @varlock/hashicorp-vault-plugin
|
|
26
|
+
```
|
|
27
|
+
And then register the plugin without any version number
|
|
28
|
+
```env-spec title=".env.schema"
|
|
29
|
+
# @plugin(@varlock/hashicorp-vault-plugin)
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Otherwise just set the explicit version number when you register it
|
|
33
|
+
```env-spec title=".env.schema"
|
|
34
|
+
# @plugin(@varlock/hashicorp-vault-plugin@1.2.3)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
See our [Plugin Guide](https://varlock.dev/guides/plugins/#installation) for more details.
|
|
38
|
+
|
|
39
|
+
## Setup + Auth
|
|
40
|
+
|
|
41
|
+
After registering the plugin, you must initialize it with the `@initHcpVault` root decorator.
|
|
42
|
+
|
|
43
|
+
### Automatic auth
|
|
44
|
+
|
|
45
|
+
For most use cases, you only need to provide the Vault URL:
|
|
46
|
+
|
|
47
|
+
```env-spec
|
|
48
|
+
# @plugin(@varlock/hashicorp-vault-plugin)
|
|
49
|
+
# @initHcpVault(url="https://vault.example.com:8200")
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**How this works:**
|
|
53
|
+
|
|
54
|
+
- **Local development:** Run `vault login` → automatically uses the token from `~/.vault-token`
|
|
55
|
+
- **CI/CD pipelines:** Wire up a token explicitly via `token=$VAULT_TOKEN`
|
|
56
|
+
- **Works everywhere** with zero configuration beyond the URL!
|
|
57
|
+
|
|
58
|
+
### AppRole auth (For automated workflows)
|
|
59
|
+
|
|
60
|
+
For CI/CD or server environments, use AppRole authentication:
|
|
61
|
+
|
|
62
|
+
```env-spec
|
|
63
|
+
# @plugin(@varlock/hashicorp-vault-plugin)
|
|
64
|
+
# @initHcpVault(
|
|
65
|
+
# url="https://vault.example.com:8200",
|
|
66
|
+
# roleId=$VAULT_ROLE_ID,
|
|
67
|
+
# secretId=$VAULT_SECRET_ID
|
|
68
|
+
# )
|
|
69
|
+
# ---
|
|
70
|
+
|
|
71
|
+
VAULT_ROLE_ID=
|
|
72
|
+
# @sensitive
|
|
73
|
+
VAULT_SECRET_ID=
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
You would then need to inject these env vars using your CI/CD system.
|
|
77
|
+
|
|
78
|
+
### Explicit token
|
|
79
|
+
|
|
80
|
+
You can also provide a token directly:
|
|
81
|
+
|
|
82
|
+
```env-spec
|
|
83
|
+
# @initHcpVault(
|
|
84
|
+
# url="https://vault.example.com:8200",
|
|
85
|
+
# token=$VAULT_TOKEN
|
|
86
|
+
# )
|
|
87
|
+
# ---
|
|
88
|
+
|
|
89
|
+
# @type=vaultToken @sensitive
|
|
90
|
+
VAULT_TOKEN=
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Authentication Priority
|
|
94
|
+
|
|
95
|
+
The plugin tries authentication methods in this order:
|
|
96
|
+
1. **Explicit token** - If `token` is provided in `@initHcpVault()`
|
|
97
|
+
2. **AppRole** - If both `roleId` and `secretId` are provided
|
|
98
|
+
3. **CLI token file** - From `~/.vault-token` (created by `vault login`) or `~/.bao-token` (created by `bao login` for OpenBao)
|
|
99
|
+
|
|
100
|
+
### Vault Enterprise namespaces
|
|
101
|
+
|
|
102
|
+
For Vault Enterprise, specify the namespace:
|
|
103
|
+
|
|
104
|
+
```env-spec
|
|
105
|
+
# @initHcpVault(url="https://vault.example.com:8200", namespace="admin/team-a")
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Multiple instances
|
|
109
|
+
|
|
110
|
+
If you need to connect to multiple Vault instances, register named instances:
|
|
111
|
+
|
|
112
|
+
```env-spec
|
|
113
|
+
# @initHcpVault(id=prod, url="https://vault-prod.example.com:8200")
|
|
114
|
+
# @initHcpVault(id=dev, url="https://vault-dev.example.com:8200")
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Reading secrets
|
|
118
|
+
|
|
119
|
+
This plugin introduces the `vaultSecret()` function to fetch secret values from Vault's KV v2 secrets engine.
|
|
120
|
+
|
|
121
|
+
Since Vault KV v2 always stores key/value pairs, the item key (variable name) is automatically used as the JSON key to extract from the secret. You can override this with `#KEY` syntax or the `key` parameter.
|
|
122
|
+
|
|
123
|
+
```env-spec title=".env.schema"
|
|
124
|
+
# @plugin(@varlock/hashicorp-vault-plugin)
|
|
125
|
+
# @initHcpVault(url="https://vault.example.com:8200")
|
|
126
|
+
# ---
|
|
127
|
+
|
|
128
|
+
# Fetches "secret/db/config" and extracts "DB_HOST" key
|
|
129
|
+
DB_HOST=vaultSecret("secret/db/config")
|
|
130
|
+
|
|
131
|
+
# Override the extracted key with # syntax
|
|
132
|
+
DB_PASSWORD=vaultSecret("secret/db/config#password")
|
|
133
|
+
|
|
134
|
+
# Or use named "key" parameter
|
|
135
|
+
DB_PORT=vaultSecret("secret/db/config", key="PORT")
|
|
136
|
+
|
|
137
|
+
# Fetch entire secret as JSON blob
|
|
138
|
+
DB_CONFIG=vaultSecret("secret/db/config", raw=true)
|
|
139
|
+
|
|
140
|
+
# If using multiple instances
|
|
141
|
+
PROD_KEY=vaultSecret(prod, "secret/api/keys")
|
|
142
|
+
DEV_KEY=vaultSecret(dev, "secret/api/keys")
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Default path
|
|
146
|
+
|
|
147
|
+
Use `defaultPath` to set a common path for secrets when no path argument is provided:
|
|
148
|
+
|
|
149
|
+
```env-spec
|
|
150
|
+
# @initHcpVault(url="https://vault.example.com:8200", defaultPath=secret/myapp/config)
|
|
151
|
+
# ---
|
|
152
|
+
|
|
153
|
+
# Both fetch from "secret/myapp/config" extracting item key
|
|
154
|
+
DB_PASSWORD=vaultSecret()
|
|
155
|
+
API_KEY=vaultSecret()
|
|
156
|
+
|
|
157
|
+
# Override the inferred key using # syntax
|
|
158
|
+
STRIPE_KEY=vaultSecret("#stripe_api_key")
|
|
159
|
+
|
|
160
|
+
# Explicit path still extracts item key by default
|
|
161
|
+
OTHER_SECRET=vaultSecret("secret/other/path")
|
|
162
|
+
|
|
163
|
+
# Or override key on explicit path
|
|
164
|
+
OTHER_KEY=vaultSecret("secret/other/path#SPECIFIC_KEY")
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Path prefixing
|
|
168
|
+
|
|
169
|
+
Use `pathPrefix` to automatically prefix all secret paths:
|
|
170
|
+
|
|
171
|
+
```env-spec
|
|
172
|
+
# @initHcpVault(url="https://vault.example.com:8200", pathPrefix="secret/myapp")
|
|
173
|
+
# ---
|
|
174
|
+
|
|
175
|
+
# Fetches from "secret/myapp/db/config"
|
|
176
|
+
DB_HOST=vaultSecret("db/config#HOST")
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
You can even use dynamic prefixes:
|
|
180
|
+
|
|
181
|
+
```env-spec
|
|
182
|
+
# @initHcpVault(url="https://vault.example.com:8200", pathPrefix="secret/${ENV}")
|
|
183
|
+
# In prod: fetches from "secret/prod/..."
|
|
184
|
+
# In dev: fetches from "secret/dev/..."
|
|
185
|
+
DB_HOST=vaultSecret("db/config#HOST")
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Bulk loading secrets
|
|
189
|
+
|
|
190
|
+
Use `raw=true` with `@setValuesBulk` to load all key/value pairs from a Vault path at once, instead of wiring up each secret individually:
|
|
191
|
+
|
|
192
|
+
```env-spec
|
|
193
|
+
# @initHcpVault(url="https://vault.example.com:8200")
|
|
194
|
+
# @setValuesBulk(vaultSecret("secret/myapp/config", raw=true))
|
|
195
|
+
# ---
|
|
196
|
+
|
|
197
|
+
DB_HOST=
|
|
198
|
+
DB_PASSWORD=
|
|
199
|
+
API_KEY=
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
This fetches all keys from `secret/myapp/config` and maps them to matching item keys.
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
## Reference
|
|
207
|
+
|
|
208
|
+
### Root decorators
|
|
209
|
+
|
|
210
|
+
#### `@initHcpVault()`
|
|
211
|
+
|
|
212
|
+
Initialize a HashiCorp Vault plugin instance.
|
|
213
|
+
|
|
214
|
+
**Parameters:**
|
|
215
|
+
|
|
216
|
+
- `url: string` (required) - Vault server URL (e.g., `https://vault.example.com:8200`)
|
|
217
|
+
- `token?: string` - Explicit Vault authentication token
|
|
218
|
+
- `roleId?: string` - AppRole role ID for automated authentication
|
|
219
|
+
- `secretId?: string` - AppRole secret ID for automated authentication
|
|
220
|
+
- `namespace?: string` - Vault Enterprise namespace
|
|
221
|
+
- `defaultPath?: string` - Default secret path when no path argument is given to `vaultSecret()`
|
|
222
|
+
- `pathPrefix?: string` - Prefix automatically prepended to all secret paths
|
|
223
|
+
- `id?: string` - Instance identifier for multiple instances (defaults to `_default`)
|
|
224
|
+
|
|
225
|
+
### Functions
|
|
226
|
+
|
|
227
|
+
#### `vaultSecret()`
|
|
228
|
+
|
|
229
|
+
Fetch a secret from HashiCorp Vault's KV v2 secrets engine.
|
|
230
|
+
|
|
231
|
+
**Signatures:**
|
|
232
|
+
|
|
233
|
+
- `vaultSecret()` - Uses `defaultPath`, extracts item key
|
|
234
|
+
- `vaultSecret(secretRef)` - Fetch by explicit path, extracts item key
|
|
235
|
+
- `vaultSecret(secretRef, key="jsonKey")` - Fetch and extract a specific key
|
|
236
|
+
- `vaultSecret(secretRef, raw=true)` - Fetch all key/value pairs as JSON blob (useful with `@setValuesBulk`)
|
|
237
|
+
- `vaultSecret(instanceId, secretRef)` - Fetch from a specific Vault instance
|
|
238
|
+
|
|
239
|
+
**Key extraction:**
|
|
240
|
+
|
|
241
|
+
By default, the item key (variable name) is used as the JSON key to extract from the secret. You can override this with `#KEY` syntax in the path or the named `key` parameter, or use `raw=true` to get the full key/value blob.
|
|
242
|
+
|
|
243
|
+
**Secret Ref Formats:**
|
|
244
|
+
|
|
245
|
+
- Path only: `"secret/myapp/config"` (extracts item key from the secret)
|
|
246
|
+
- Path with key override: `"secret/myapp/config#DB_PASSWORD"` (extracts specific key)
|
|
247
|
+
|
|
248
|
+
**How paths work:**
|
|
249
|
+
|
|
250
|
+
Vault KV v2 stores key/value pairs at a path. Given a path like `secret/myapp/config`, the plugin calls `GET /v1/secret/data/myapp/config` (the first path segment is the mount point, and `/data/` is inserted for the KV v2 API).
|
|
251
|
+
|
|
252
|
+
### Data Types
|
|
253
|
+
|
|
254
|
+
- `vaultToken` - HashiCorp Vault authentication token (sensitive)
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
## Vault Setup
|
|
259
|
+
|
|
260
|
+
### Enable KV v2 Secrets Engine
|
|
261
|
+
|
|
262
|
+
```bash
|
|
263
|
+
# KV v2 is enabled by default at "secret/" in dev mode
|
|
264
|
+
# For production, enable it explicitly:
|
|
265
|
+
vault secrets enable -version=2 -path=secret kv
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### Create a Policy
|
|
269
|
+
|
|
270
|
+
```hcl
|
|
271
|
+
# policy.hcl - Allow reading secrets
|
|
272
|
+
path "secret/data/*" {
|
|
273
|
+
capabilities = ["read"]
|
|
274
|
+
}
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
```bash
|
|
278
|
+
vault policy write varlock-reader policy.hcl
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### Set Up AppRole Auth (Recommended for CI/CD)
|
|
282
|
+
|
|
283
|
+
AppRole is the recommended auth method for automated workflows:
|
|
284
|
+
|
|
285
|
+
```bash
|
|
286
|
+
# Enable AppRole auth method
|
|
287
|
+
vault auth enable approle
|
|
288
|
+
|
|
289
|
+
# Create a role
|
|
290
|
+
vault write auth/approle/role/varlock-role \
|
|
291
|
+
secret_id_ttl=24h \
|
|
292
|
+
token_ttl=1h \
|
|
293
|
+
token_max_ttl=4h \
|
|
294
|
+
token_policies=varlock-reader
|
|
295
|
+
|
|
296
|
+
# Get the role ID
|
|
297
|
+
vault read auth/approle/role/varlock-role/role-id
|
|
298
|
+
|
|
299
|
+
# Generate a secret ID
|
|
300
|
+
vault write -f auth/approle/role/varlock-role/secret-id
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
Save the `role_id` and `secret_id` from the output for your CI/CD configuration.
|
|
304
|
+
|
|
305
|
+
### Create a Token (For simple setups)
|
|
306
|
+
|
|
307
|
+
```bash
|
|
308
|
+
# Create a token with the reader policy
|
|
309
|
+
vault token create -policy=varlock-reader -ttl=24h
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### Store Secrets
|
|
313
|
+
|
|
314
|
+
```bash
|
|
315
|
+
# Store a single key/value
|
|
316
|
+
vault kv put secret/myapp/config DB_PASSWORD=supersecret
|
|
317
|
+
|
|
318
|
+
# Store multiple keys
|
|
319
|
+
vault kv put secret/myapp/config \
|
|
320
|
+
DB_HOST=db.example.com \
|
|
321
|
+
DB_PASSWORD=supersecret \
|
|
322
|
+
API_KEY=abc123
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
## Troubleshooting
|
|
326
|
+
|
|
327
|
+
### Secret not found
|
|
328
|
+
- Verify the secret exists: `vault kv get secret/myapp/config`
|
|
329
|
+
- Check the mount point is correct (first path segment, typically `secret`)
|
|
330
|
+
- Ensure you're using KV v2, not KV v1 (different API format)
|
|
331
|
+
|
|
332
|
+
### Permission denied
|
|
333
|
+
- Check your token's policies: `vault token lookup`
|
|
334
|
+
- Ensure your policy includes `read` capability on `secret/data/*` (note the `/data/` prefix for KV v2)
|
|
335
|
+
- For AppRole: verify the role has the correct policies attached
|
|
336
|
+
|
|
337
|
+
### Authentication failed
|
|
338
|
+
- **Local dev:** Run `vault login` (or `bao login` for OpenBao) and ensure `VAULT_ADDR` is set correctly
|
|
339
|
+
- **CI/CD:** Verify your token or AppRole credentials are properly wired up in `@initHcpVault()`
|
|
340
|
+
- Check if the token has expired: `vault token lookup`
|
|
341
|
+
- For AppRole: verify the secret ID hasn't expired and generate a new one if needed
|