@zincapp/zn-vault-agent 1.3.0

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.
Files changed (88) hide show
  1. package/README.md +701 -0
  2. package/deploy/logrotate.d/zn-vault-agent +14 -0
  3. package/deploy/systemd/zn-vault-agent.service +75 -0
  4. package/dist/commands/certs.d.ts +3 -0
  5. package/dist/commands/certs.d.ts.map +1 -0
  6. package/dist/commands/certs.js +369 -0
  7. package/dist/commands/certs.js.map +1 -0
  8. package/dist/commands/exec.d.ts +3 -0
  9. package/dist/commands/exec.d.ts.map +1 -0
  10. package/dist/commands/exec.js +193 -0
  11. package/dist/commands/exec.js.map +1 -0
  12. package/dist/commands/login.d.ts +3 -0
  13. package/dist/commands/login.d.ts.map +1 -0
  14. package/dist/commands/login.js +234 -0
  15. package/dist/commands/login.js.map +1 -0
  16. package/dist/commands/secrets.d.ts +3 -0
  17. package/dist/commands/secrets.d.ts.map +1 -0
  18. package/dist/commands/secrets.js +445 -0
  19. package/dist/commands/secrets.js.map +1 -0
  20. package/dist/commands/setup.d.ts +9 -0
  21. package/dist/commands/setup.d.ts.map +1 -0
  22. package/dist/commands/setup.js +346 -0
  23. package/dist/commands/setup.js.map +1 -0
  24. package/dist/commands/start.d.ts +3 -0
  25. package/dist/commands/start.d.ts.map +1 -0
  26. package/dist/commands/start.js +113 -0
  27. package/dist/commands/start.js.map +1 -0
  28. package/dist/commands/status.d.ts +3 -0
  29. package/dist/commands/status.d.ts.map +1 -0
  30. package/dist/commands/status.js +85 -0
  31. package/dist/commands/status.js.map +1 -0
  32. package/dist/commands/sync.d.ts +3 -0
  33. package/dist/commands/sync.d.ts.map +1 -0
  34. package/dist/commands/sync.js +126 -0
  35. package/dist/commands/sync.js.map +1 -0
  36. package/dist/index.d.ts +3 -0
  37. package/dist/index.d.ts.map +1 -0
  38. package/dist/index.js +28 -0
  39. package/dist/index.js.map +1 -0
  40. package/dist/lib/api.d.ts +104 -0
  41. package/dist/lib/api.d.ts.map +1 -0
  42. package/dist/lib/api.js +338 -0
  43. package/dist/lib/api.js.map +1 -0
  44. package/dist/lib/config.d.ts +164 -0
  45. package/dist/lib/config.d.ts.map +1 -0
  46. package/dist/lib/config.js +299 -0
  47. package/dist/lib/config.js.map +1 -0
  48. package/dist/lib/deployer.d.ts +22 -0
  49. package/dist/lib/deployer.d.ts.map +1 -0
  50. package/dist/lib/deployer.js +407 -0
  51. package/dist/lib/deployer.js.map +1 -0
  52. package/dist/lib/health.d.ts +68 -0
  53. package/dist/lib/health.d.ts.map +1 -0
  54. package/dist/lib/health.js +216 -0
  55. package/dist/lib/health.js.map +1 -0
  56. package/dist/lib/logger.d.ts +38 -0
  57. package/dist/lib/logger.d.ts.map +1 -0
  58. package/dist/lib/logger.js +161 -0
  59. package/dist/lib/logger.js.map +1 -0
  60. package/dist/lib/metrics.d.ts +50 -0
  61. package/dist/lib/metrics.d.ts.map +1 -0
  62. package/dist/lib/metrics.js +273 -0
  63. package/dist/lib/metrics.js.map +1 -0
  64. package/dist/lib/secret-deployer.d.ts +22 -0
  65. package/dist/lib/secret-deployer.d.ts.map +1 -0
  66. package/dist/lib/secret-deployer.js +201 -0
  67. package/dist/lib/secret-deployer.js.map +1 -0
  68. package/dist/lib/validation.d.ts +25 -0
  69. package/dist/lib/validation.d.ts.map +1 -0
  70. package/dist/lib/validation.js +257 -0
  71. package/dist/lib/validation.js.map +1 -0
  72. package/dist/lib/websocket.d.ts +74 -0
  73. package/dist/lib/websocket.d.ts.map +1 -0
  74. package/dist/lib/websocket.js +441 -0
  75. package/dist/lib/websocket.js.map +1 -0
  76. package/dist/services/api-key-renewal.d.ts +13 -0
  77. package/dist/services/api-key-renewal.d.ts.map +1 -0
  78. package/dist/services/api-key-renewal.js +204 -0
  79. package/dist/services/api-key-renewal.js.map +1 -0
  80. package/dist/services/npm-auto-update.d.ts +60 -0
  81. package/dist/services/npm-auto-update.d.ts.map +1 -0
  82. package/dist/services/npm-auto-update.js +245 -0
  83. package/dist/services/npm-auto-update.js.map +1 -0
  84. package/dist/types/update.d.ts +19 -0
  85. package/dist/types/update.d.ts.map +1 -0
  86. package/dist/types/update.js +7 -0
  87. package/dist/types/update.js.map +1 -0
  88. package/package.json +74 -0
package/README.md ADDED
@@ -0,0 +1,701 @@
1
+ # ZN-Vault Certificate Agent
2
+
3
+ Real-time certificate distribution agent for ZN-Vault. Automatically syncs TLS certificates from your vault to target servers with zero-downtime deployments.
4
+
5
+ ## Features
6
+
7
+ ### Certificate Sync
8
+ - **Real-time updates**: WebSocket connection for instant certificate rotation
9
+ - **Fallback polling**: Periodic sync when WebSocket is unavailable
10
+ - **Atomic deployments**: Uses temp files and rename for safe updates
11
+ - **Automatic rollback**: Reverts on reload or health check failure
12
+ - **Multiple output formats**: Combined (HAProxy), separate cert/key/chain, fullchain (Nginx)
13
+
14
+ ### Secret Sync
15
+ - **File output formats**: `.env`, JSON, YAML, raw value, or custom templates
16
+ - **Automatic sync**: Keep local secret files in sync with vault
17
+ - **Reload hooks**: Run commands after secrets are updated
18
+
19
+ ### Exec Mode
20
+ - **Zero-config injection**: Run any command with secrets as environment variables
21
+ - **No file writes**: Secrets exist only in process memory
22
+ - **Signal forwarding**: Graceful shutdown of child processes
23
+
24
+ ### General
25
+ - **Prometheus metrics**: Full observability via `/metrics` endpoint
26
+ - **Graceful shutdown**: Completes in-flight deployments before exit
27
+ - **Structured logging**: JSON logs with sensitive field redaction
28
+ - **Auto-updates**: Automatic npm-based updates with graceful restarts
29
+ - **API key auto-renewal**: Automatic rotation before expiry
30
+
31
+ ## Quick Start
32
+
33
+ ### Option A: npm Install (Recommended)
34
+
35
+ The fastest way to install on Linux servers:
36
+
37
+ ```bash
38
+ # Install globally via npm
39
+ npm install -g @zincapp/zn-vault-agent
40
+
41
+ # Setup systemd service (as root)
42
+ sudo zn-vault-agent setup
43
+ ```
44
+
45
+ **Requirements:** Node.js 18+ must be installed.
46
+
47
+ **What `setup` does:**
48
+
49
+ 1. Creates `zn-vault-agent` system user/group
50
+ 2. Creates directories: `/etc/zn-vault-agent/`, `/var/lib/zn-vault-agent/`, `/var/log/zn-vault-agent/`
51
+ 3. Installs systemd service (enabled but not started)
52
+ 4. Creates config template at `/etc/zn-vault-agent/agent.env`
53
+
54
+ **Install specific version or channel:**
55
+
56
+ ```bash
57
+ npm install -g @zincapp/zn-vault-agent@1.3.0 # Specific version
58
+ npm install -g @zincapp/zn-vault-agent@beta # Beta channel
59
+ npm install -g @zincapp/zn-vault-agent@next # Development
60
+ ```
61
+
62
+ After installation, configure and start:
63
+
64
+ ```bash
65
+ # 1. Configure the agent
66
+ zn-vault-agent login --url https://vault.example.com \
67
+ --tenant my-tenant --api-key znv_abc123...
68
+
69
+ # 2. Add certificate to sync
70
+ zn-vault-agent certs add <cert-id> \
71
+ --name "haproxy-frontend" \
72
+ --combined /etc/haproxy/certs/frontend.pem \
73
+ --reload "systemctl reload haproxy"
74
+
75
+ # 3. Start service
76
+ sudo systemctl start zn-vault-agent
77
+ ```
78
+
79
+ ### Option B: Using znvault CLI
80
+
81
+ If you already have the `znvault` CLI installed:
82
+
83
+ ```bash
84
+ # Configure CLI (if not already done)
85
+ znvault config set url https://vault.example.com
86
+ znvault login -u admin -p 'password'
87
+
88
+ # Initialize agent config (uses CLI credentials)
89
+ znvault agent init
90
+
91
+ # Add a certificate to sync
92
+ znvault agent add <cert-id> \
93
+ --name "haproxy-frontend" \
94
+ --combined /etc/haproxy/certs/frontend.pem \
95
+ --reload "systemctl reload haproxy"
96
+
97
+ # Test sync (one-time)
98
+ znvault agent sync
99
+
100
+ # Start the daemon
101
+ znvault agent start
102
+ ```
103
+
104
+ ### Option C: Build from Source
105
+
106
+ For development or customization:
107
+
108
+ ```bash
109
+ # Build from source
110
+ cd zn-vault-agent
111
+ npm install
112
+ npm run build
113
+
114
+ # Install system-wide (as root)
115
+ sudo ./deploy/install.sh
116
+
117
+ # Configure
118
+ sudo vim /etc/zn-vault-agent/config.json
119
+
120
+ # Start
121
+ zn-vault-agent start --health-port 9100
122
+ ```
123
+
124
+ ## Authentication
125
+
126
+ The agent supports two authentication methods. **API key authentication is strongly recommended** for production deployments.
127
+
128
+ ### API Key Authentication (Recommended)
129
+
130
+ API keys are more secure than passwords because:
131
+ - They can be scoped to only the permissions the agent needs
132
+ - They can be restricted by IP address
133
+ - They don't require storing user passwords
134
+ - They can be rotated independently of user credentials
135
+
136
+ #### Required Permissions
137
+
138
+ The agent needs only **two permissions** to function:
139
+
140
+ | Permission | Description |
141
+ |------------|-------------|
142
+ | `certificate:read:metadata` | View certificate metadata (expiry, fingerprint) |
143
+ | `certificate:read:value` | Decrypt and download certificate data |
144
+
145
+ #### Creating an API Key
146
+
147
+ ```bash
148
+ # 1. Login to vault as admin
149
+ TOKEN=$(curl -sk -X POST https://vault.example.com/auth/login \
150
+ -H "Content-Type: application/json" \
151
+ -d '{"username":"admin","password":"..."}' | jq -r '.accessToken')
152
+
153
+ # 2. Create a limited-scope API key for the agent
154
+ curl -sk -X POST https://vault.example.com/auth/api-keys \
155
+ -H "Authorization: Bearer $TOKEN" \
156
+ -H "Content-Type: application/json" \
157
+ -d '{
158
+ "name": "cert-agent-prod-server1",
159
+ "expiresInDays": 365,
160
+ "scope": "limited",
161
+ "allowedPermissions": [
162
+ "certificate:read:metadata",
163
+ "certificate:read:value"
164
+ ],
165
+ "ipAllowlist": ["10.0.0.0/8"]
166
+ }'
167
+
168
+ # Response includes the API key (shown only once!)
169
+ # {
170
+ # "key": "znv_abc123...",
171
+ # "message": "⚠️ Save this key - it will not be shown again!"
172
+ # }
173
+ ```
174
+
175
+ #### Via Dashboard
176
+
177
+ In the ZN-Vault dashboard:
178
+ 1. Navigate to **Settings** → **API Keys**
179
+ 2. Click **Create API Key**
180
+ 3. Set name: `cert-agent-<hostname>`
181
+ 4. Set scope: **Limited**
182
+ 5. Select permissions: `certificate:read:metadata`, `certificate:read:value`
183
+ 6. Add IP allowlist if desired
184
+ 7. Set expiration (max 365 days recommended)
185
+ 8. **Save the key immediately** - it won't be shown again!
186
+
187
+ #### Security Best Practices
188
+
189
+ 1. **Use limited scope**: Only grant the two required permissions
190
+ 2. **Add IP allowlist**: Restrict to your server's IP or network CIDR
191
+ 3. **Set expiration**: Use 365 days max, the agent will auto-renew
192
+ 4. **One key per server**: Create unique keys for each agent instance
193
+ 5. **Store securely**: Use `secrets.env` with `0600` permissions
194
+
195
+ #### Automatic API Key Renewal
196
+
197
+ The agent automatically renews API keys before they expire:
198
+
199
+ - **Check frequency**: Every 24 hours
200
+ - **Renewal threshold**: 30 days before expiry
201
+ - **What happens**:
202
+ 1. Agent checks key expiration via `GET /auth/api-keys/self`
203
+ 2. If expiring within 30 days, calls `POST /auth/api-keys/self/rotate`
204
+ 3. New key is saved atomically to config file
205
+ 4. Old key is immediately invalidated
206
+
207
+ **Log output during renewal:**
208
+ ```
209
+ {"level":"info","msg":"API key status","expiresInDays":25,"isExpiringSoon":true}
210
+ {"level":"info","msg":"API key expiring soon, initiating rotation"}
211
+ {"level":"info","msg":"API key rotated successfully","newPrefix":"znv_abc1"}
212
+ {"level":"info","msg":"Config file updated with new API key"}
213
+ ```
214
+
215
+ **Note**: The renewal service only runs when the daemon is active. For environments where the daemon runs intermittently, consider checking key status via `znvault agent status` and rotating manually if needed.
216
+
217
+ ### Password Authentication (Development Only)
218
+
219
+ Password auth stores credentials in the config file. **Not recommended for production.**
220
+
221
+ ```json
222
+ {
223
+ "auth": {
224
+ "username": "agent-user",
225
+ "password": "..."
226
+ }
227
+ }
228
+ ```
229
+
230
+ ## Connection Modes
231
+
232
+ The agent supports two connection modes. **WebSocket is recommended** for production deployments.
233
+
234
+ ### WebSocket Mode (Recommended)
235
+
236
+ WebSocket provides real-time push notifications when certificates or secrets are rotated:
237
+
238
+ ```json
239
+ {
240
+ "websocket": true,
241
+ "pollInterval": 3600
242
+ }
243
+ ```
244
+
245
+ **Benefits:**
246
+ - **Instant updates**: Receives certificate/secret changes immediately
247
+ - **Lower latency**: No waiting for poll interval
248
+ - **Efficient**: Single persistent connection vs repeated HTTP requests
249
+ - **Disconnect alerts**: Server monitors connection health and can alert on disconnect
250
+
251
+ **When WebSocket is unavailable**, the agent falls back to polling automatically.
252
+
253
+ ### Polling Mode
254
+
255
+ Polling periodically checks for updates via HTTP requests:
256
+
257
+ ```json
258
+ {
259
+ "pollInterval": 3600
260
+ }
261
+ ```
262
+
263
+ Use polling when:
264
+ - WebSocket connections are blocked by firewall
265
+ - Updates are infrequent and immediate sync isn't critical
266
+ - Minimizing persistent connections is required
267
+
268
+ ### Recommended Configuration
269
+
270
+ For most deployments, enable both WebSocket and polling as fallback:
271
+
272
+ ```json
273
+ {
274
+ "vaultUrl": "https://vault.example.com",
275
+ "tenantId": "my-tenant",
276
+ "auth": {
277
+ "apiKey": "znv_abc123..."
278
+ },
279
+ "websocket": true,
280
+ "pollInterval": 3600,
281
+ "targets": [...]
282
+ }
283
+ ```
284
+
285
+ ## Configuration
286
+
287
+ Both `znvault agent` CLI and the standalone daemon share the same config file.
288
+
289
+ ### Config File Locations
290
+
291
+ | Context | Location |
292
+ |---------|----------|
293
+ | System (root) | `/etc/zn-vault-agent/config.json` |
294
+ | User | `~/.config/zn-vault-agent/config.json` |
295
+
296
+ ### Config Format
297
+
298
+ ```json
299
+ {
300
+ "vaultUrl": "https://vault.example.com",
301
+ "tenantId": "my-tenant",
302
+ "auth": {
303
+ "apiKey": "znv_abc123..."
304
+ },
305
+ "targets": [
306
+ {
307
+ "certId": "uuid-of-certificate",
308
+ "name": "haproxy-frontend",
309
+ "outputs": {
310
+ "combined": "/etc/haproxy/certs/frontend.pem"
311
+ },
312
+ "owner": "haproxy:haproxy",
313
+ "mode": "0640",
314
+ "reloadCmd": "systemctl reload haproxy",
315
+ "healthCheckCmd": "curl -sf http://localhost:8080/health"
316
+ }
317
+ ],
318
+ "pollInterval": 3600,
319
+ "insecure": false
320
+ }
321
+ ```
322
+
323
+ ### Environment Variables
324
+
325
+ Environment variables override config file values:
326
+
327
+ | Variable | Description |
328
+ |----------|-------------|
329
+ | `ZNVAULT_URL` | Vault server URL |
330
+ | `ZNVAULT_TENANT_ID` | Tenant ID |
331
+ | `ZNVAULT_API_KEY` | API key (preferred) |
332
+ | `ZNVAULT_USERNAME` | Username for password auth |
333
+ | `ZNVAULT_PASSWORD` | Password for password auth |
334
+ | `ZNVAULT_INSECURE` | Skip TLS verification (`true`/`false`) |
335
+ | `ZNVAULT_AGENT_CONFIG_DIR` | Custom config directory |
336
+ | `LOG_LEVEL` | Log level: `trace`, `debug`, `info`, `warn`, `error` |
337
+ | `LOG_FILE` | Optional log file path |
338
+
339
+ ### Output Formats
340
+
341
+ | Output | Description | Use Case |
342
+ |--------|-------------|----------|
343
+ | `combined` | cert + key + chain | HAProxy |
344
+ | `cert` | Certificate only | General |
345
+ | `key` | Private key only | General |
346
+ | `chain` | CA chain certificates | General |
347
+ | `fullchain` | cert + chain | Nginx |
348
+
349
+ ## Commands
350
+
351
+ ### Standalone Agent (`zn-vault-agent`)
352
+
353
+ | Command | Description |
354
+ |---------|-------------|
355
+ | `start` | Start the daemon |
356
+ | `login` | Configure vault credentials |
357
+ | `add <cert-id>` | Add a certificate to sync |
358
+ | `remove <cert-id>` | Remove a certificate |
359
+ | `list` | List configured certificates |
360
+ | `sync` | Manual one-time sync |
361
+ | `status` | Show sync status |
362
+ | `secret add <id>` | Add a secret to sync |
363
+ | `secret remove <name>` | Remove a secret target |
364
+ | `secret list` | List configured secrets |
365
+ | `secret sync` | Sync all secrets |
366
+ | `exec` | Run command with secrets as env vars |
367
+ | `setup` | Install systemd service (requires root) |
368
+
369
+ ```bash
370
+ zn-vault-agent start [options]
371
+
372
+ Options:
373
+ -v, --verbose Enable debug logging
374
+ --health-port <port> Enable health/metrics HTTP server
375
+ --validate Validate config before starting
376
+ --auto-update Enable automatic updates
377
+ ```
378
+
379
+ ## Secret Sync
380
+
381
+ Sync secrets from vault to local files in various formats.
382
+
383
+ > **Note**: Requires a user with `secret:read:value` permission. Admin users cannot decrypt secrets (separation of duties). See [GUIDE.md](docs/GUIDE.md#required-permissions) for role setup.
384
+
385
+ ### Add a Secret Target
386
+
387
+ ```bash
388
+ # Sync to .env file
389
+ zn-vault-agent secret add alias:db/credentials \
390
+ --format env \
391
+ --output /etc/myapp/secrets.env \
392
+ --reload "systemctl restart myapp"
393
+
394
+ # Sync to JSON file
395
+ zn-vault-agent secret add alias:app/config \
396
+ --format json \
397
+ --output /etc/myapp/config.json
398
+
399
+ # Extract single value
400
+ zn-vault-agent secret add alias:api/key \
401
+ --format raw \
402
+ --key apiKey \
403
+ --output /etc/myapp/api-key.txt
404
+
405
+ # Use template
406
+ zn-vault-agent secret add alias:db/prod \
407
+ --format template \
408
+ --template /etc/myapp/config.tmpl \
409
+ --output /etc/myapp/config.yml
410
+ ```
411
+
412
+ ### Output Formats
413
+
414
+ | Format | Description | Example Output |
415
+ |--------|-------------|----------------|
416
+ | `env` | Environment file | `DB_HOST="localhost"` |
417
+ | `json` | JSON object | `{"host": "localhost"}` |
418
+ | `yaml` | YAML document | `host: localhost` |
419
+ | `raw` | Single value (requires `--key`) | `localhost` |
420
+ | `template` | Custom template with `{{ key }}` placeholders | (based on template) |
421
+
422
+ ### Sync Secrets
423
+
424
+ ```bash
425
+ # Sync all configured secrets
426
+ zn-vault-agent secret sync
427
+
428
+ # Sync specific target
429
+ zn-vault-agent secret sync --name db-credentials
430
+ ```
431
+
432
+ ## Exec Mode
433
+
434
+ Run any command with secrets injected as environment variables. Secrets never touch disk.
435
+
436
+ > **Note**: Same permission requirements as Secret Sync - requires `secret:read:value` permission.
437
+
438
+ ### Basic Usage
439
+
440
+ ```bash
441
+ # Single secret
442
+ zn-vault-agent exec \
443
+ -s DB_PASSWORD=alias:db/prod.password \
444
+ -- node server.js
445
+
446
+ # Multiple secrets
447
+ zn-vault-agent exec \
448
+ -s DB_HOST=alias:db/prod.host \
449
+ -s DB_PASSWORD=alias:db/prod.password \
450
+ -s API_KEY=alias:api/key.value \
451
+ -- ./start.sh
452
+
453
+ # Entire secret as JSON
454
+ zn-vault-agent exec \
455
+ -s CONFIG=alias:app/config \
456
+ -- node -e "console.log(JSON.parse(process.env.CONFIG))"
457
+ ```
458
+
459
+ ### Mapping Format
460
+
461
+ ```
462
+ ENV_VAR=secret-id[.key]
463
+
464
+ Examples:
465
+ DB_PASS=alias:db/credentials.password # Specific key
466
+ DB_PASS=abc123.password # UUID with key
467
+ CONFIG=alias:app/config # Entire secret as JSON
468
+ ```
469
+
470
+ ### Export to File
471
+
472
+ ```bash
473
+ # Write secrets to env file (without running a command)
474
+ zn-vault-agent exec \
475
+ -s DB_PASSWORD=alias:db/prod.password \
476
+ -o /tmp/secrets.env
477
+ ```
478
+
479
+ ### CLI Commands (`znvault agent`)
480
+
481
+ The CLI provides the same configuration commands:
482
+
483
+ | Command | Description |
484
+ |---------|-------------|
485
+ | `znvault agent init` | Initialize agent config (uses CLI credentials) |
486
+ | `znvault agent add <cert-id>` | Add a certificate to sync |
487
+ | `znvault agent remove <id-or-name>` | Remove a certificate |
488
+ | `znvault agent list` | List configured certificates |
489
+ | `znvault agent sync` | One-time sync (for testing) |
490
+ | `znvault agent start` | Start the daemon (invokes `zn-vault-agent`) |
491
+ | `znvault agent status` | Show sync status |
492
+
493
+ ## Health & Metrics
494
+
495
+ When started with `--health-port`, the agent exposes:
496
+
497
+ | Endpoint | Description |
498
+ |----------|-------------|
499
+ | `/health` | JSON health status |
500
+ | `/ready` | Readiness probe (Kubernetes) |
501
+ | `/live` | Liveness probe |
502
+ | `/metrics` | Prometheus metrics |
503
+
504
+ ### Prometheus Metrics
505
+
506
+ ```
507
+ # Counters
508
+ znvault_agent_sync_total{status,cert_name}
509
+ znvault_agent_sync_failures_total{cert_name,reason}
510
+ znvault_agent_websocket_reconnects_total
511
+ znvault_agent_api_requests_total{method,status}
512
+
513
+ # Gauges
514
+ znvault_agent_connected
515
+ znvault_agent_certs_tracked
516
+ znvault_agent_last_sync_timestamp{cert_name}
517
+ znvault_agent_cert_expiry_days{cert_id,cert_name}
518
+
519
+ # Histograms
520
+ znvault_agent_sync_duration_seconds{cert_name}
521
+ znvault_agent_api_request_duration_seconds{method}
522
+ ```
523
+
524
+ ## Systemd Installation
525
+
526
+ ```bash
527
+ # Install via npm
528
+ npm install -g @zincapp/zn-vault-agent
529
+
530
+ # Setup systemd (as root)
531
+ sudo zn-vault-agent setup
532
+
533
+ # Configure
534
+ zn-vault-agent login --url https://vault.example.com \
535
+ --tenant my-tenant --api-key znv_abc123...
536
+
537
+ # Enable and start
538
+ sudo systemctl enable --now zn-vault-agent
539
+
540
+ # View logs
541
+ journalctl -u zn-vault-agent -f
542
+ ```
543
+
544
+ ### File Locations
545
+
546
+ | Path | Description |
547
+ |------|-------------|
548
+ | `/usr/local/bin/zn-vault-agent` | Agent binary |
549
+ | `/etc/zn-vault-agent/config.json` | Main configuration |
550
+ | `/etc/zn-vault-agent/secrets.env` | Sensitive credentials |
551
+ | `/var/lib/zn-vault-agent/` | State directory |
552
+ | `/var/log/zn-vault-agent/` | Log files |
553
+
554
+ ## Troubleshooting
555
+
556
+ ### Agent won't start
557
+
558
+ ```bash
559
+ # Check configuration
560
+ zn-vault-agent start --validate
561
+
562
+ # Check logs
563
+ journalctl -u zn-vault-agent -n 50
564
+
565
+ # Test vault connectivity
566
+ curl -k https://your-vault/v1/health
567
+ ```
568
+
569
+ ### Certificates not syncing
570
+
571
+ ```bash
572
+ # Check sync status
573
+ znvault agent status
574
+
575
+ # Force manual sync
576
+ znvault agent sync --force
577
+
578
+ # Check health endpoint
579
+ curl http://localhost:9100/health
580
+ ```
581
+
582
+ ### WebSocket disconnects
583
+
584
+ - Check network connectivity to vault
585
+ - Verify API key is valid
586
+ - Check vault server logs for auth errors
587
+ - Agent will auto-reconnect with exponential backoff
588
+
589
+ ### Permission denied
590
+
591
+ ```bash
592
+ # Check file ownership
593
+ ls -la /etc/ssl/znvault/
594
+
595
+ # Ensure agent can write
596
+ sudo chown zn-vault-agent:zn-vault-agent /etc/ssl/znvault/
597
+
598
+ # Check reload command permissions
599
+ # Agent runs as zn-vault-agent user, may need sudo rules
600
+ ```
601
+
602
+ ## Auto-Update
603
+
604
+ The agent automatically updates itself via npm. Updates are checked every 5 minutes by default.
605
+
606
+ ### How It Works
607
+
608
+ 1. Agent periodically checks `npm view @zincapp/zn-vault-agent version`
609
+ 2. If a newer version is available, it runs `npm install -g @zincapp/zn-vault-agent`
610
+ 3. Agent sends SIGTERM to itself, systemd restarts with new version
611
+ 4. Lock file prevents multiple agents from updating simultaneously
612
+
613
+ ### Configuration
614
+
615
+ Auto-update is **enabled by default**. Configure via environment variables:
616
+
617
+ ```bash
618
+ # In /etc/zn-vault-agent/agent.env:
619
+ AUTO_UPDATE=true # Enable/disable (default: true)
620
+ AUTO_UPDATE_INTERVAL=300 # Check interval in seconds (default: 300)
621
+ AUTO_UPDATE_CHANNEL=latest # Channel: latest, beta, next (default: latest)
622
+ ```
623
+
624
+ Or disable via CLI flag:
625
+
626
+ ```bash
627
+ zn-vault-agent start --no-auto-update
628
+ ```
629
+
630
+ ### Manual Updates
631
+
632
+ ```bash
633
+ # Check for updates
634
+ npm outdated -g @zincapp/zn-vault-agent
635
+
636
+ # Update manually
637
+ npm update -g @zincapp/zn-vault-agent
638
+
639
+ # Install specific version
640
+ npm install -g @zincapp/zn-vault-agent@1.3.0
641
+ ```
642
+
643
+ ### Update Channels (npm dist-tags)
644
+
645
+ | Channel | Command | Description |
646
+ |---------|---------|-------------|
647
+ | `latest` | `npm install -g @zincapp/zn-vault-agent@latest` | Production releases |
648
+ | `beta` | `npm install -g @zincapp/zn-vault-agent@beta` | Pre-release testing |
649
+ | `next` | `npm install -g @zincapp/zn-vault-agent@next` | Development builds |
650
+
651
+ ## Security Considerations
652
+
653
+ ### Authentication
654
+ 1. **Use API keys**: Always use API keys with limited scope in production
655
+ 2. **Scope permissions**: Only grant `certificate:read:metadata` and `certificate:read:value`
656
+ 3. **IP allowlisting**: Restrict API key usage to specific server IPs
657
+ 4. **Rotate annually**: Set expiration to 365 days and rotate before expiry
658
+
659
+ ### Credentials Storage
660
+ 5. **Use secrets.env**: Store `ZNVAULT_API_KEY` in `/etc/zn-vault-agent/secrets.env`
661
+ 6. **File permissions**: `secrets.env` should be `0600` owned by `zn-vault-agent`
662
+ 7. **Never commit**: Keep credentials out of version control
663
+
664
+ ### Runtime Security
665
+ 8. **Reload commands**: Run with minimal privileges (use `sudo` rules if needed)
666
+ 9. **TLS verification**: Never use `insecure: true` in production
667
+ 10. **Network isolation**: Agent only needs outbound HTTPS to vault
668
+
669
+ ### Example secrets.env
670
+
671
+ ```bash
672
+ # /etc/zn-vault-agent/secrets.env
673
+ # Permissions: 0600, Owner: zn-vault-agent:zn-vault-agent
674
+ ZNVAULT_API_KEY=znv_abc123...
675
+ ```
676
+
677
+ ## Documentation
678
+
679
+ For comprehensive documentation including:
680
+ - WebSocket protocol details
681
+ - High availability (HA) setup
682
+ - Cross-node event distribution
683
+ - Advanced troubleshooting
684
+
685
+ See the [Agent Guide](docs/GUIDE.md).
686
+
687
+ ## Development
688
+
689
+ ```bash
690
+ npm install
691
+ npm run dev # Development with hot reload
692
+ npm run build # Build
693
+ npm run typecheck # Type check
694
+ npm run lint # Lint
695
+ npm test # Test
696
+ npm run test:coverage
697
+ ```
698
+
699
+ ## License
700
+
701
+ MIT
@@ -0,0 +1,14 @@
1
+ /var/log/zn-vault-agent/*.log {
2
+ daily
3
+ rotate 14
4
+ compress
5
+ delaycompress
6
+ missingok
7
+ notifempty
8
+ create 0640 zn-vault-agent zn-vault-agent
9
+ sharedscripts
10
+ postrotate
11
+ # Signal the agent to reopen log files
12
+ systemctl kill -s USR1 zn-vault-agent.service 2>/dev/null || true
13
+ endscript
14
+ }