@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 ADDED
@@ -0,0 +1,341 @@
1
+ # @varlock/hashicorp-vault-plugin
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@varlock/hashicorp-vault-plugin.svg)](https://www.npmjs.com/package/@varlock/hashicorp-vault-plugin) [![GitHub stars](https://img.shields.io/github/stars/dmno-dev/varlock.svg?style=social&label=Star)](https://github.com/dmno-dev/varlock) [![license](https://img.shields.io/npm/l/@varlock/hashicorp-vault-plugin.svg)](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