@zincapp/znvault-cli 2.16.5 → 2.17.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.
- package/dist/commands/apikey/conditions.d.ts +6 -0
- package/dist/commands/apikey/conditions.d.ts.map +1 -0
- package/dist/commands/apikey/conditions.js +57 -0
- package/dist/commands/apikey/conditions.js.map +1 -0
- package/dist/commands/apikey/create.d.ts +6 -0
- package/dist/commands/apikey/create.d.ts.map +1 -0
- package/dist/commands/apikey/create.js +106 -0
- package/dist/commands/apikey/create.js.map +1 -0
- package/dist/commands/apikey/delete.d.ts +6 -0
- package/dist/commands/apikey/delete.d.ts.map +1 -0
- package/dist/commands/apikey/delete.js +29 -0
- package/dist/commands/apikey/delete.js.map +1 -0
- package/dist/commands/apikey/enable-disable.d.ts +6 -0
- package/dist/commands/apikey/enable-disable.d.ts.map +1 -0
- package/dist/commands/apikey/enable-disable.js +44 -0
- package/dist/commands/apikey/enable-disable.js.map +1 -0
- package/dist/commands/apikey/helpers.d.ts +23 -0
- package/dist/commands/apikey/helpers.d.ts.map +1 -0
- package/dist/commands/apikey/helpers.js +135 -0
- package/dist/commands/apikey/helpers.js.map +1 -0
- package/dist/commands/apikey/index.d.ts +10 -0
- package/dist/commands/apikey/index.d.ts.map +1 -0
- package/dist/commands/apikey/index.js +33 -0
- package/dist/commands/apikey/index.js.map +1 -0
- package/dist/commands/apikey/list.d.ts +6 -0
- package/dist/commands/apikey/list.d.ts.map +1 -0
- package/dist/commands/apikey/list.js +74 -0
- package/dist/commands/apikey/list.js.map +1 -0
- package/dist/commands/apikey/managed/bind.d.ts +6 -0
- package/dist/commands/apikey/managed/bind.d.ts.map +1 -0
- package/dist/commands/apikey/managed/bind.js +52 -0
- package/dist/commands/apikey/managed/bind.js.map +1 -0
- package/dist/commands/apikey/managed/conditions.d.ts +6 -0
- package/dist/commands/apikey/managed/conditions.d.ts.map +1 -0
- package/dist/commands/apikey/managed/conditions.js +62 -0
- package/dist/commands/apikey/managed/conditions.js.map +1 -0
- package/dist/commands/apikey/managed/config.d.ts +6 -0
- package/dist/commands/apikey/managed/config.d.ts.map +1 -0
- package/dist/commands/apikey/managed/config.js +52 -0
- package/dist/commands/apikey/managed/config.js.map +1 -0
- package/dist/commands/apikey/managed/create.d.ts +6 -0
- package/dist/commands/apikey/managed/create.d.ts.map +1 -0
- package/dist/commands/apikey/managed/create.js +82 -0
- package/dist/commands/apikey/managed/create.js.map +1 -0
- package/dist/commands/apikey/managed/delete.d.ts +6 -0
- package/dist/commands/apikey/managed/delete.d.ts.map +1 -0
- package/dist/commands/apikey/managed/delete.js +29 -0
- package/dist/commands/apikey/managed/delete.js.map +1 -0
- package/dist/commands/apikey/managed/get.d.ts +6 -0
- package/dist/commands/apikey/managed/get.d.ts.map +1 -0
- package/dist/commands/apikey/managed/get.js +31 -0
- package/dist/commands/apikey/managed/get.js.map +1 -0
- package/dist/commands/apikey/managed/helpers.d.ts +5 -0
- package/dist/commands/apikey/managed/helpers.d.ts.map +1 -0
- package/dist/commands/apikey/managed/helpers.js +70 -0
- package/dist/commands/apikey/managed/helpers.js.map +1 -0
- package/dist/commands/apikey/managed/index.d.ts +7 -0
- package/dist/commands/apikey/managed/index.d.ts.map +1 -0
- package/dist/commands/apikey/managed/index.js +27 -0
- package/dist/commands/apikey/managed/index.js.map +1 -0
- package/dist/commands/apikey/managed/list.d.ts +6 -0
- package/dist/commands/apikey/managed/list.d.ts.map +1 -0
- package/dist/commands/apikey/managed/list.js +58 -0
- package/dist/commands/apikey/managed/list.js.map +1 -0
- package/dist/commands/apikey/managed/permissions.d.ts +6 -0
- package/dist/commands/apikey/managed/permissions.d.ts.map +1 -0
- package/dist/commands/apikey/managed/permissions.js +73 -0
- package/dist/commands/apikey/managed/permissions.js.map +1 -0
- package/dist/commands/apikey/managed/rotate.d.ts +6 -0
- package/dist/commands/apikey/managed/rotate.d.ts.map +1 -0
- package/dist/commands/apikey/managed/rotate.js +29 -0
- package/dist/commands/apikey/managed/rotate.js.map +1 -0
- package/dist/commands/apikey/managed/types.d.ts +62 -0
- package/dist/commands/apikey/managed/types.d.ts.map +1 -0
- package/dist/commands/apikey/managed/types.js +3 -0
- package/dist/commands/apikey/managed/types.js.map +1 -0
- package/dist/commands/apikey/permissions.d.ts +6 -0
- package/dist/commands/apikey/permissions.d.ts.map +1 -0
- package/dist/commands/apikey/permissions.js +70 -0
- package/dist/commands/apikey/permissions.js.map +1 -0
- package/dist/commands/apikey/policies.d.ts +6 -0
- package/dist/commands/apikey/policies.d.ts.map +1 -0
- package/dist/commands/apikey/policies.js +82 -0
- package/dist/commands/apikey/policies.js.map +1 -0
- package/dist/commands/apikey/rotate.d.ts +6 -0
- package/dist/commands/apikey/rotate.d.ts.map +1 -0
- package/dist/commands/apikey/rotate.js +42 -0
- package/dist/commands/apikey/rotate.js.map +1 -0
- package/dist/commands/apikey/self.d.ts +6 -0
- package/dist/commands/apikey/self.d.ts.map +1 -0
- package/dist/commands/apikey/self.js +96 -0
- package/dist/commands/apikey/self.js.map +1 -0
- package/dist/commands/apikey/show.d.ts +6 -0
- package/dist/commands/apikey/show.d.ts.map +1 -0
- package/dist/commands/apikey/show.js +79 -0
- package/dist/commands/apikey/show.js.map +1 -0
- package/dist/commands/apikey/types.d.ts +83 -0
- package/dist/commands/apikey/types.d.ts.map +1 -0
- package/dist/commands/apikey/types.js +3 -0
- package/dist/commands/apikey/types.js.map +1 -0
- package/dist/commands/apikey.d.ts +8 -2
- package/dist/commands/apikey.d.ts.map +1 -1
- package/dist/commands/apikey.js +9 -1296
- package/dist/commands/apikey.js.map +1 -1
- package/dist/commands/device.d.ts.map +1 -1
- package/dist/commands/device.js +8 -5
- package/dist/commands/device.js.map +1 -1
- package/dist/commands/plugin.d.ts.map +1 -1
- package/dist/commands/plugin.js +29 -7
- package/dist/commands/plugin.js.map +1 -1
- package/dist/commands/secret/copy.d.ts +6 -0
- package/dist/commands/secret/copy.d.ts.map +1 -0
- package/dist/commands/secret/copy.js +43 -0
- package/dist/commands/secret/copy.js.map +1 -0
- package/dist/commands/secret/create.d.ts +6 -0
- package/dist/commands/secret/create.d.ts.map +1 -0
- package/dist/commands/secret/create.js +297 -0
- package/dist/commands/secret/create.js.map +1 -0
- package/dist/commands/secret/decrypt.d.ts +6 -0
- package/dist/commands/secret/decrypt.d.ts.map +1 -0
- package/dist/commands/secret/decrypt.js +104 -0
- package/dist/commands/secret/decrypt.js.map +1 -0
- package/dist/commands/secret/delete.d.ts +6 -0
- package/dist/commands/secret/delete.d.ts.map +1 -0
- package/dist/commands/secret/delete.js +60 -0
- package/dist/commands/secret/delete.js.map +1 -0
- package/dist/commands/secret/get.d.ts +6 -0
- package/dist/commands/secret/get.d.ts.map +1 -0
- package/dist/commands/secret/get.js +60 -0
- package/dist/commands/secret/get.js.map +1 -0
- package/dist/commands/secret/helpers.d.ts +11 -0
- package/dist/commands/secret/helpers.d.ts.map +1 -0
- package/dist/commands/secret/helpers.js +59 -0
- package/dist/commands/secret/helpers.js.map +1 -0
- package/dist/commands/secret/history.d.ts +6 -0
- package/dist/commands/secret/history.d.ts.map +1 -0
- package/dist/commands/secret/history.js +52 -0
- package/dist/commands/secret/history.js.map +1 -0
- package/dist/commands/secret/index.d.ts +12 -0
- package/dist/commands/secret/index.d.ts.map +1 -0
- package/dist/commands/secret/index.js +49 -0
- package/dist/commands/secret/index.js.map +1 -0
- package/dist/commands/secret/list.d.ts +6 -0
- package/dist/commands/secret/list.d.ts.map +1 -0
- package/dist/commands/secret/list.js +72 -0
- package/dist/commands/secret/list.js.map +1 -0
- package/dist/commands/secret/pem-analysis.d.ts +32 -0
- package/dist/commands/secret/pem-analysis.d.ts.map +1 -0
- package/dist/commands/secret/pem-analysis.js +190 -0
- package/dist/commands/secret/pem-analysis.js.map +1 -0
- package/dist/commands/secret/resolve.d.ts +17 -0
- package/dist/commands/secret/resolve.d.ts.map +1 -0
- package/dist/commands/secret/resolve.js +36 -0
- package/dist/commands/secret/resolve.js.map +1 -0
- package/dist/commands/secret/rotate.d.ts +6 -0
- package/dist/commands/secret/rotate.d.ts.map +1 -0
- package/dist/commands/secret/rotate.js +72 -0
- package/dist/commands/secret/rotate.js.map +1 -0
- package/dist/commands/secret/types.d.ts +123 -0
- package/dist/commands/secret/types.d.ts.map +1 -0
- package/dist/commands/secret/types.js +3 -0
- package/dist/commands/secret/types.js.map +1 -0
- package/dist/commands/secret/update.d.ts +6 -0
- package/dist/commands/secret/update.d.ts.map +1 -0
- package/dist/commands/secret/update.js +124 -0
- package/dist/commands/secret/update.js.map +1 -0
- package/dist/commands/secret.d.ts +8 -2
- package/dist/commands/secret.d.ts.map +1 -1
- package/dist/commands/secret.js +6 -1131
- package/dist/commands/secret.js.map +1 -1
- package/dist/index.js +48 -4
- package/dist/index.js.map +1 -1
- package/dist/lib/client/apikeys.d.ts +34 -0
- package/dist/lib/client/apikeys.d.ts.map +1 -0
- package/dist/lib/client/apikeys.js +113 -0
- package/dist/lib/client/apikeys.js.map +1 -0
- package/dist/lib/client/audit.d.ts +21 -0
- package/dist/lib/client/audit.d.ts.map +1 -0
- package/dist/lib/client/audit.js +40 -0
- package/dist/lib/client/audit.js.map +1 -0
- package/dist/lib/client/health.d.ts +30 -0
- package/dist/lib/client/health.d.ts.map +1 -0
- package/dist/lib/client/health.js +55 -0
- package/dist/lib/client/health.js.map +1 -0
- package/dist/lib/client/http.d.ts +50 -0
- package/dist/lib/client/http.d.ts.map +1 -0
- package/dist/lib/client/http.js +333 -0
- package/dist/lib/client/http.js.map +1 -0
- package/dist/lib/client/index.d.ts +156 -0
- package/dist/lib/client/index.d.ts.map +1 -0
- package/dist/lib/client/index.js +172 -0
- package/dist/lib/client/index.js.map +1 -0
- package/dist/lib/client/lockdown.d.ts +23 -0
- package/dist/lib/client/lockdown.d.ts.map +1 -0
- package/dist/lib/client/lockdown.js +48 -0
- package/dist/lib/client/lockdown.js.map +1 -0
- package/dist/lib/client/managed-keys.d.ts +18 -0
- package/dist/lib/client/managed-keys.d.ts.map +1 -0
- package/dist/lib/client/managed-keys.js +190 -0
- package/dist/lib/client/managed-keys.js.map +1 -0
- package/dist/lib/client/policies.d.ts +35 -0
- package/dist/lib/client/policies.d.ts.map +1 -0
- package/dist/lib/client/policies.js +131 -0
- package/dist/lib/client/policies.js.map +1 -0
- package/dist/lib/client/tenants.d.ts +29 -0
- package/dist/lib/client/tenants.d.ts.map +1 -0
- package/dist/lib/client/tenants.js +56 -0
- package/dist/lib/client/tenants.js.map +1 -0
- package/dist/lib/client/types.d.ts +45 -0
- package/dist/lib/client/types.d.ts.map +1 -0
- package/dist/lib/client/types.js +3 -0
- package/dist/lib/client/types.js.map +1 -0
- package/dist/lib/client/users.d.ts +44 -0
- package/dist/lib/client/users.d.ts.map +1 -0
- package/dist/lib/client/users.js +116 -0
- package/dist/lib/client/users.js.map +1 -0
- package/dist/lib/client.d.ts +11 -246
- package/dist/lib/client.d.ts.map +1 -1
- package/dist/lib/client.js +10 -999
- package/dist/lib/client.js.map +1 -1
- package/dist/lib/command-error-handler.d.ts +99 -0
- package/dist/lib/command-error-handler.d.ts.map +1 -0
- package/dist/lib/command-error-handler.js +108 -0
- package/dist/lib/command-error-handler.js.map +1 -0
- package/dist/lib/config/apikey.d.ts +29 -0
- package/dist/lib/config/apikey.d.ts.map +1 -0
- package/dist/lib/config/apikey.js +58 -0
- package/dist/lib/config/apikey.js.map +1 -0
- package/dist/lib/config/cache.d.ts +47 -0
- package/dist/lib/config/cache.d.ts.map +1 -0
- package/dist/lib/config/cache.js +84 -0
- package/dist/lib/config/cache.js.map +1 -0
- package/dist/lib/config/credentials.d.ts +33 -0
- package/dist/lib/config/credentials.d.ts.map +1 -0
- package/dist/lib/config/credentials.js +70 -0
- package/dist/lib/config/credentials.js.map +1 -0
- package/dist/lib/config/getters.d.ts +28 -0
- package/dist/lib/config/getters.d.ts.map +1 -0
- package/dist/lib/config/getters.js +65 -0
- package/dist/lib/config/getters.js.map +1 -0
- package/dist/lib/config/index.d.ts +17 -0
- package/dist/lib/config/index.d.ts.map +1 -0
- package/dist/lib/config/index.js +21 -0
- package/dist/lib/config/index.js.map +1 -0
- package/dist/lib/config/migration.d.ts +10 -0
- package/dist/lib/config/migration.d.ts.map +1 -0
- package/dist/lib/config/migration.js +59 -0
- package/dist/lib/config/migration.js.map +1 -0
- package/dist/lib/config/plugins.d.ts +25 -0
- package/dist/lib/config/plugins.d.ts.map +1 -0
- package/dist/lib/config/plugins.js +58 -0
- package/dist/lib/config/plugins.js.map +1 -0
- package/dist/lib/config/profile.d.ts +42 -0
- package/dist/lib/config/profile.d.ts.map +1 -0
- package/dist/lib/config/profile.js +154 -0
- package/dist/lib/config/profile.js.map +1 -0
- package/dist/lib/config/store.d.ts +23 -0
- package/dist/lib/config/store.d.ts.map +1 -0
- package/dist/lib/config/store.js +41 -0
- package/dist/lib/config/store.js.map +1 -0
- package/dist/lib/config/types.d.ts +44 -0
- package/dist/lib/config/types.d.ts.map +1 -0
- package/dist/lib/config/types.js +8 -0
- package/dist/lib/config/types.js.map +1 -0
- package/dist/lib/config/validation.d.ts +38 -0
- package/dist/lib/config/validation.d.ts.map +1 -0
- package/dist/lib/config/validation.js +146 -0
- package/dist/lib/config/validation.js.map +1 -0
- package/dist/lib/config.d.ts +5 -158
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +26 -424
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/constants.d.ts +65 -0
- package/dist/lib/constants.d.ts.map +1 -0
- package/dist/lib/constants.js +90 -0
- package/dist/lib/constants.js.map +1 -0
- package/dist/lib/db.d.ts +4 -0
- package/dist/lib/db.d.ts.map +1 -1
- package/dist/lib/db.js +77 -46
- package/dist/lib/db.js.map +1 -1
- package/dist/lib/format-helpers.d.ts +63 -0
- package/dist/lib/format-helpers.d.ts.map +1 -0
- package/dist/lib/format-helpers.js +219 -0
- package/dist/lib/format-helpers.js.map +1 -0
- package/dist/lib/visual.d.ts +22 -0
- package/dist/lib/visual.d.ts.map +1 -1
- package/dist/lib/visual.js +83 -0
- package/dist/lib/visual.js.map +1 -1
- package/dist/services/signature-verifier.d.ts.map +1 -1
- package/dist/services/signature-verifier.js +11 -4
- package/dist/services/signature-verifier.js.map +1 -1
- package/dist/services/update-installer.d.ts +7 -0
- package/dist/services/update-installer.d.ts.map +1 -1
- package/dist/services/update-installer.js +58 -19
- package/dist/services/update-installer.js.map +1 -1
- package/package.json +1 -1
package/dist/lib/client.js
CHANGED
|
@@ -1,1002 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
import http from 'node:http';
|
|
3
|
-
import { getConfig, getCredentials, getApiKey, hasApiKey, storeCredentials, isTokenExpired, getEnvCredentials, hasEnvCredentials, } from './config.js';
|
|
1
|
+
// Path: src/lib/client.ts
|
|
4
2
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
3
|
+
* Backward compatibility re-export
|
|
4
|
+
*
|
|
5
|
+
* This file maintains the original import path for existing code:
|
|
6
|
+
* import { client, VaultClient } from './lib/client.js';
|
|
7
|
+
*
|
|
8
|
+
* The implementation has been moved to src/lib/client/ for better organization.
|
|
7
9
|
*/
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const HOUR_IN_SECONDS = 60 * 60;
|
|
12
|
-
const MINUTE_IN_SECONDS = 60;
|
|
13
|
-
// Use days only for 7+ days and evenly divisible
|
|
14
|
-
if (seconds >= WEEK_IN_SECONDS && seconds % DAY_IN_SECONDS === 0) {
|
|
15
|
-
return `${seconds / DAY_IN_SECONDS}d`;
|
|
16
|
-
}
|
|
17
|
-
// Use hours if evenly divisible by hours
|
|
18
|
-
if (seconds >= HOUR_IN_SECONDS && seconds % HOUR_IN_SECONDS === 0) {
|
|
19
|
-
return `${seconds / HOUR_IN_SECONDS}h`;
|
|
20
|
-
}
|
|
21
|
-
// Use minutes if evenly divisible
|
|
22
|
-
if (seconds >= MINUTE_IN_SECONDS && seconds % MINUTE_IN_SECONDS === 0) {
|
|
23
|
-
return `${seconds / MINUTE_IN_SECONDS}m`;
|
|
24
|
-
}
|
|
25
|
-
return `${seconds}s`;
|
|
26
|
-
}
|
|
27
|
-
class VaultClient {
|
|
28
|
-
baseUrl;
|
|
29
|
-
insecure;
|
|
30
|
-
timeout;
|
|
31
|
-
constructor() {
|
|
32
|
-
const config = getConfig();
|
|
33
|
-
this.baseUrl = config.url;
|
|
34
|
-
this.insecure = config.insecure;
|
|
35
|
-
this.timeout = config.timeout;
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Update client configuration
|
|
39
|
-
*/
|
|
40
|
-
configure(url, insecure) {
|
|
41
|
-
if (url)
|
|
42
|
-
this.baseUrl = url;
|
|
43
|
-
if (insecure !== undefined)
|
|
44
|
-
this.insecure = insecure;
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Make an HTTP request
|
|
48
|
-
*/
|
|
49
|
-
async request(options) {
|
|
50
|
-
const url = new URL(this.baseUrl);
|
|
51
|
-
url.pathname = options.path;
|
|
52
|
-
if (options.query) {
|
|
53
|
-
for (const [key, value] of Object.entries(options.query)) {
|
|
54
|
-
if (value !== undefined) {
|
|
55
|
-
url.searchParams.set(key, String(value));
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
const headers = {
|
|
60
|
-
'Accept': 'application/json',
|
|
61
|
-
};
|
|
62
|
-
// Only set Content-Type for requests with a body
|
|
63
|
-
if (options.body !== undefined && options.body !== null) {
|
|
64
|
-
headers['Content-Type'] = 'application/json';
|
|
65
|
-
}
|
|
66
|
-
// Add authentication
|
|
67
|
-
if (!options.skipAuth) {
|
|
68
|
-
const apiKey = getApiKey();
|
|
69
|
-
if (hasApiKey() && apiKey) {
|
|
70
|
-
headers['X-API-Key'] = apiKey;
|
|
71
|
-
}
|
|
72
|
-
else {
|
|
73
|
-
const credentials = getCredentials();
|
|
74
|
-
if (credentials) {
|
|
75
|
-
// Check if token is expired and try to refresh
|
|
76
|
-
if (isTokenExpired() && credentials.refreshToken) {
|
|
77
|
-
await this.refreshToken();
|
|
78
|
-
}
|
|
79
|
-
const updatedCredentials = getCredentials();
|
|
80
|
-
if (updatedCredentials) {
|
|
81
|
-
headers.Authorization = `Bearer ${updatedCredentials.accessToken}`;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
else if (hasEnvCredentials()) {
|
|
85
|
-
// Auto-login with env credentials
|
|
86
|
-
const envCreds = getEnvCredentials();
|
|
87
|
-
if (envCreds) {
|
|
88
|
-
await this.login(envCreds.username, envCreds.password);
|
|
89
|
-
const newCredentials = getCredentials();
|
|
90
|
-
if (newCredentials) {
|
|
91
|
-
headers.Authorization = `Bearer ${newCredentials.accessToken}`;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
const requestOptions = {
|
|
98
|
-
hostname: url.hostname,
|
|
99
|
-
port: url.port || (url.protocol === 'https:' ? 443 : 80),
|
|
100
|
-
path: url.pathname + url.search,
|
|
101
|
-
method: options.method,
|
|
102
|
-
headers,
|
|
103
|
-
timeout: this.timeout,
|
|
104
|
-
rejectUnauthorized: !this.insecure,
|
|
105
|
-
};
|
|
106
|
-
return new Promise((resolve, reject) => {
|
|
107
|
-
const protocol = url.protocol === 'https:' ? https : http;
|
|
108
|
-
const req = protocol.request(requestOptions, (res) => {
|
|
109
|
-
let data = '';
|
|
110
|
-
res.on('data', (chunk) => (data += String(chunk)));
|
|
111
|
-
res.on('end', () => {
|
|
112
|
-
try {
|
|
113
|
-
const parsed = data ? JSON.parse(data) : {};
|
|
114
|
-
if (res.statusCode && res.statusCode >= 400) {
|
|
115
|
-
const error = parsed;
|
|
116
|
-
reject(new Error(error.message || `Request failed with status ${res.statusCode}`));
|
|
117
|
-
}
|
|
118
|
-
else {
|
|
119
|
-
resolve(parsed);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
catch {
|
|
123
|
-
if (res.statusCode && res.statusCode >= 400) {
|
|
124
|
-
reject(new Error(`Request failed with status ${res.statusCode}`));
|
|
125
|
-
}
|
|
126
|
-
else {
|
|
127
|
-
resolve(data);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
});
|
|
131
|
-
});
|
|
132
|
-
req.on('error', reject);
|
|
133
|
-
req.on('timeout', () => {
|
|
134
|
-
req.destroy();
|
|
135
|
-
reject(new Error('Request timeout'));
|
|
136
|
-
});
|
|
137
|
-
if (options.body !== undefined && options.body !== null) {
|
|
138
|
-
req.write(JSON.stringify(options.body));
|
|
139
|
-
}
|
|
140
|
-
req.end();
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
// ============ Authentication ============
|
|
144
|
-
async login(username, password, totp) {
|
|
145
|
-
const response = await this.request({
|
|
146
|
-
method: 'POST',
|
|
147
|
-
path: '/auth/login',
|
|
148
|
-
body: { username, password, totpCode: totp },
|
|
149
|
-
skipAuth: true,
|
|
150
|
-
});
|
|
151
|
-
// Store credentials
|
|
152
|
-
storeCredentials({
|
|
153
|
-
accessToken: response.accessToken,
|
|
154
|
-
refreshToken: response.refreshToken,
|
|
155
|
-
expiresAt: Date.now() + response.expiresIn * 1000,
|
|
156
|
-
userId: response.user.id,
|
|
157
|
-
username: response.user.username,
|
|
158
|
-
role: response.user.role,
|
|
159
|
-
tenantId: response.user.tenantId,
|
|
160
|
-
});
|
|
161
|
-
return response;
|
|
162
|
-
}
|
|
163
|
-
async refreshToken() {
|
|
164
|
-
const credentials = getCredentials();
|
|
165
|
-
if (!credentials?.refreshToken) {
|
|
166
|
-
throw new Error('No refresh token available');
|
|
167
|
-
}
|
|
168
|
-
const response = await this.request({
|
|
169
|
-
method: 'POST',
|
|
170
|
-
path: '/auth/refresh',
|
|
171
|
-
body: { refreshToken: credentials.refreshToken },
|
|
172
|
-
skipAuth: true,
|
|
173
|
-
});
|
|
174
|
-
storeCredentials({
|
|
175
|
-
...credentials,
|
|
176
|
-
accessToken: response.accessToken,
|
|
177
|
-
refreshToken: response.refreshToken,
|
|
178
|
-
expiresAt: Date.now() + response.expiresIn * 1000,
|
|
179
|
-
});
|
|
180
|
-
}
|
|
181
|
-
// ============ Health ============
|
|
182
|
-
async health() {
|
|
183
|
-
return this.request({
|
|
184
|
-
method: 'GET',
|
|
185
|
-
path: '/v1/health',
|
|
186
|
-
skipAuth: true,
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
async leaderHealth() {
|
|
190
|
-
return this.request({
|
|
191
|
-
method: 'GET',
|
|
192
|
-
path: '/v1/health/leader',
|
|
193
|
-
skipAuth: true,
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
// ============ Cluster ============
|
|
197
|
-
async clusterStatus() {
|
|
198
|
-
return this.request({
|
|
199
|
-
method: 'GET',
|
|
200
|
-
path: '/v1/admin/cluster',
|
|
201
|
-
});
|
|
202
|
-
}
|
|
203
|
-
async clusterTakeover() {
|
|
204
|
-
return this.request({
|
|
205
|
-
method: 'POST',
|
|
206
|
-
path: '/v1/admin/cluster/takeover',
|
|
207
|
-
});
|
|
208
|
-
}
|
|
209
|
-
async clusterPromote(nodeId) {
|
|
210
|
-
return this.request({
|
|
211
|
-
method: 'POST',
|
|
212
|
-
path: `/v1/admin/cluster/nodes/${nodeId}/promote`,
|
|
213
|
-
});
|
|
214
|
-
}
|
|
215
|
-
async clusterRelease() {
|
|
216
|
-
return this.request({
|
|
217
|
-
method: 'POST',
|
|
218
|
-
path: '/v1/admin/cluster/release',
|
|
219
|
-
});
|
|
220
|
-
}
|
|
221
|
-
async clusterMaintenance(enable) {
|
|
222
|
-
return this.request({
|
|
223
|
-
method: 'POST',
|
|
224
|
-
path: '/v1/admin/cluster/maintenance',
|
|
225
|
-
body: { enable },
|
|
226
|
-
});
|
|
227
|
-
}
|
|
228
|
-
// ============ Tenants ============
|
|
229
|
-
async listTenants(options) {
|
|
230
|
-
const response = await this.request({
|
|
231
|
-
method: 'GET',
|
|
232
|
-
path: '/v1/tenants',
|
|
233
|
-
query: {
|
|
234
|
-
status: options?.status,
|
|
235
|
-
withUsage: options?.withUsage,
|
|
236
|
-
pageSize: 1000,
|
|
237
|
-
},
|
|
238
|
-
});
|
|
239
|
-
return response.items;
|
|
240
|
-
}
|
|
241
|
-
async createTenant(data) {
|
|
242
|
-
const response = await this.request({
|
|
243
|
-
method: 'POST',
|
|
244
|
-
path: '/v1/tenants',
|
|
245
|
-
body: data,
|
|
246
|
-
});
|
|
247
|
-
return response.data;
|
|
248
|
-
}
|
|
249
|
-
async getTenant(id, withUsage) {
|
|
250
|
-
const response = await this.request({
|
|
251
|
-
method: 'GET',
|
|
252
|
-
path: `/v1/tenants/${id}`,
|
|
253
|
-
query: { withUsage },
|
|
254
|
-
});
|
|
255
|
-
return response.data;
|
|
256
|
-
}
|
|
257
|
-
async updateTenant(id, data) {
|
|
258
|
-
const response = await this.request({
|
|
259
|
-
method: 'PATCH',
|
|
260
|
-
path: `/v1/tenants/${id}`,
|
|
261
|
-
body: data,
|
|
262
|
-
});
|
|
263
|
-
return response.data;
|
|
264
|
-
}
|
|
265
|
-
async deleteTenant(id) {
|
|
266
|
-
await this.request({
|
|
267
|
-
method: 'DELETE',
|
|
268
|
-
path: `/v1/tenants/${id}`,
|
|
269
|
-
});
|
|
270
|
-
}
|
|
271
|
-
async getTenantUsage(id) {
|
|
272
|
-
return this.request({
|
|
273
|
-
method: 'GET',
|
|
274
|
-
path: `/v1/tenants/${id}/usage`,
|
|
275
|
-
});
|
|
276
|
-
}
|
|
277
|
-
// ============ Users ============
|
|
278
|
-
async listUsers(options) {
|
|
279
|
-
const response = await this.request({
|
|
280
|
-
method: 'GET',
|
|
281
|
-
path: '/v1/users',
|
|
282
|
-
query: {
|
|
283
|
-
tenantId: options?.tenantId,
|
|
284
|
-
role: options?.role,
|
|
285
|
-
status: options?.status,
|
|
286
|
-
pageSize: 1000,
|
|
287
|
-
},
|
|
288
|
-
});
|
|
289
|
-
return response.items;
|
|
290
|
-
}
|
|
291
|
-
async createUser(data) {
|
|
292
|
-
return this.request({
|
|
293
|
-
method: 'POST',
|
|
294
|
-
path: '/v1/users',
|
|
295
|
-
body: data,
|
|
296
|
-
});
|
|
297
|
-
}
|
|
298
|
-
async getUser(id) {
|
|
299
|
-
return this.request({
|
|
300
|
-
method: 'GET',
|
|
301
|
-
path: `/v1/users/${id}`,
|
|
302
|
-
});
|
|
303
|
-
}
|
|
304
|
-
async updateUser(id, data) {
|
|
305
|
-
return this.request({
|
|
306
|
-
method: 'PUT',
|
|
307
|
-
path: `/v1/users/${id}`,
|
|
308
|
-
body: data,
|
|
309
|
-
});
|
|
310
|
-
}
|
|
311
|
-
async deleteUser(id) {
|
|
312
|
-
await this.request({
|
|
313
|
-
method: 'DELETE',
|
|
314
|
-
path: `/v1/users/${id}`,
|
|
315
|
-
});
|
|
316
|
-
}
|
|
317
|
-
async unlockUser(id) {
|
|
318
|
-
return this.request({
|
|
319
|
-
method: 'PUT',
|
|
320
|
-
path: `/v1/users/${id}`,
|
|
321
|
-
body: { status: 'active', failedAttempts: 0, lockedUntil: null },
|
|
322
|
-
});
|
|
323
|
-
}
|
|
324
|
-
async resetUserPassword(id, newPassword) {
|
|
325
|
-
return this.request({
|
|
326
|
-
method: 'POST',
|
|
327
|
-
path: `/v1/users/${id}/reset-password`,
|
|
328
|
-
body: { newPassword },
|
|
329
|
-
});
|
|
330
|
-
}
|
|
331
|
-
async disableUserTotp(id) {
|
|
332
|
-
return this.request({
|
|
333
|
-
method: 'POST',
|
|
334
|
-
path: `/v1/users/${id}/totp/disable`,
|
|
335
|
-
});
|
|
336
|
-
}
|
|
337
|
-
// ============ Superadmins ============
|
|
338
|
-
async listSuperadmins() {
|
|
339
|
-
const users = await this.listUsers({ role: 'superadmin' });
|
|
340
|
-
return users.map(u => ({
|
|
341
|
-
id: u.id,
|
|
342
|
-
username: u.username,
|
|
343
|
-
email: u.email,
|
|
344
|
-
status: u.status,
|
|
345
|
-
totpEnabled: u.totpEnabled,
|
|
346
|
-
failedAttempts: u.failedAttempts,
|
|
347
|
-
lockedUntil: u.lockedUntil,
|
|
348
|
-
lastLogin: u.lastLogin,
|
|
349
|
-
createdAt: u.createdAt,
|
|
350
|
-
}));
|
|
351
|
-
}
|
|
352
|
-
async createSuperadmin(data) {
|
|
353
|
-
return this.request({
|
|
354
|
-
method: 'POST',
|
|
355
|
-
path: '/v1/superadmins',
|
|
356
|
-
body: data,
|
|
357
|
-
});
|
|
358
|
-
}
|
|
359
|
-
async resetSuperadminPassword(username, password) {
|
|
360
|
-
return this.request({
|
|
361
|
-
method: 'POST',
|
|
362
|
-
path: `/v1/superadmins/${username}/password`,
|
|
363
|
-
body: { password },
|
|
364
|
-
});
|
|
365
|
-
}
|
|
366
|
-
async unlockSuperadmin(username) {
|
|
367
|
-
return this.request({
|
|
368
|
-
method: 'POST',
|
|
369
|
-
path: `/v1/superadmins/${username}/unlock`,
|
|
370
|
-
});
|
|
371
|
-
}
|
|
372
|
-
async disableSuperadmin(username) {
|
|
373
|
-
return this.request({
|
|
374
|
-
method: 'POST',
|
|
375
|
-
path: `/v1/superadmins/${username}/disable`,
|
|
376
|
-
});
|
|
377
|
-
}
|
|
378
|
-
async enableSuperadmin(username) {
|
|
379
|
-
return this.request({
|
|
380
|
-
method: 'POST',
|
|
381
|
-
path: `/v1/superadmins/${username}/enable`,
|
|
382
|
-
});
|
|
383
|
-
}
|
|
384
|
-
// ============ Lockdown ============
|
|
385
|
-
async getLockdownStatus() {
|
|
386
|
-
return this.request({
|
|
387
|
-
method: 'GET',
|
|
388
|
-
path: '/v1/admin/lockdown/status',
|
|
389
|
-
});
|
|
390
|
-
}
|
|
391
|
-
async triggerLockdown(level, reason) {
|
|
392
|
-
return this.request({
|
|
393
|
-
method: 'POST',
|
|
394
|
-
path: '/v1/admin/lockdown/trigger',
|
|
395
|
-
body: { level, reason },
|
|
396
|
-
});
|
|
397
|
-
}
|
|
398
|
-
async clearLockdown(reason) {
|
|
399
|
-
return this.request({
|
|
400
|
-
method: 'POST',
|
|
401
|
-
path: '/v1/admin/lockdown/clear',
|
|
402
|
-
body: { reason },
|
|
403
|
-
});
|
|
404
|
-
}
|
|
405
|
-
async getLockdownHistory(limit) {
|
|
406
|
-
const response = await this.request({
|
|
407
|
-
method: 'GET',
|
|
408
|
-
path: '/v1/admin/lockdown/history',
|
|
409
|
-
query: { limit: limit ?? 50 },
|
|
410
|
-
});
|
|
411
|
-
return response.items;
|
|
412
|
-
}
|
|
413
|
-
async getThreats(options) {
|
|
414
|
-
const response = await this.request({
|
|
415
|
-
method: 'GET',
|
|
416
|
-
path: '/v1/admin/lockdown/threats',
|
|
417
|
-
query: {
|
|
418
|
-
category: options?.category,
|
|
419
|
-
since: options?.since,
|
|
420
|
-
limit: options?.limit ?? 100,
|
|
421
|
-
},
|
|
422
|
-
});
|
|
423
|
-
return response.items;
|
|
424
|
-
}
|
|
425
|
-
// ============ Audit ============
|
|
426
|
-
async listAudit(options) {
|
|
427
|
-
const response = await this.request({
|
|
428
|
-
method: 'GET',
|
|
429
|
-
path: '/v1/audit',
|
|
430
|
-
query: {
|
|
431
|
-
client_cn: options?.user,
|
|
432
|
-
action: options?.action,
|
|
433
|
-
start_date: options?.startDate,
|
|
434
|
-
end_date: options?.endDate,
|
|
435
|
-
limit: options?.limit ?? 100,
|
|
436
|
-
},
|
|
437
|
-
});
|
|
438
|
-
return response.items;
|
|
439
|
-
}
|
|
440
|
-
async verifyAuditChain() {
|
|
441
|
-
return this.request({
|
|
442
|
-
method: 'GET',
|
|
443
|
-
path: '/v1/audit/verify',
|
|
444
|
-
});
|
|
445
|
-
}
|
|
446
|
-
async exportAudit(options) {
|
|
447
|
-
return this.request({
|
|
448
|
-
method: 'GET',
|
|
449
|
-
path: '/v1/audit',
|
|
450
|
-
query: {
|
|
451
|
-
format: options?.format ?? 'json',
|
|
452
|
-
start_date: options?.startDate,
|
|
453
|
-
end_date: options?.endDate,
|
|
454
|
-
limit: 10000,
|
|
455
|
-
},
|
|
456
|
-
});
|
|
457
|
-
}
|
|
458
|
-
// ============ API Keys (Independent, tenant-scoped) ============
|
|
459
|
-
async createApiKey(data) {
|
|
460
|
-
return this.request({
|
|
461
|
-
method: 'POST',
|
|
462
|
-
path: '/auth/api-keys',
|
|
463
|
-
query: data.tenantId ? { tenantId: data.tenantId } : undefined,
|
|
464
|
-
body: {
|
|
465
|
-
name: data.name,
|
|
466
|
-
description: data.description,
|
|
467
|
-
expiresInDays: data.expiresInDays,
|
|
468
|
-
permissions: data.permissions,
|
|
469
|
-
ipAllowlist: data.ipAllowlist,
|
|
470
|
-
conditions: data.conditions,
|
|
471
|
-
},
|
|
472
|
-
});
|
|
473
|
-
}
|
|
474
|
-
async listApiKeys(tenantId) {
|
|
475
|
-
return this.request({
|
|
476
|
-
method: 'GET',
|
|
477
|
-
path: '/auth/api-keys',
|
|
478
|
-
query: tenantId ? { tenantId } : undefined,
|
|
479
|
-
});
|
|
480
|
-
}
|
|
481
|
-
async getApiKey(id, tenantId) {
|
|
482
|
-
return this.request({
|
|
483
|
-
method: 'GET',
|
|
484
|
-
path: `/auth/api-keys/${id}`,
|
|
485
|
-
query: tenantId ? { tenantId } : undefined,
|
|
486
|
-
});
|
|
487
|
-
}
|
|
488
|
-
async deleteApiKey(id, tenantId) {
|
|
489
|
-
await this.request({
|
|
490
|
-
method: 'DELETE',
|
|
491
|
-
path: `/auth/api-keys/${id}`,
|
|
492
|
-
query: tenantId ? { tenantId } : undefined,
|
|
493
|
-
});
|
|
494
|
-
}
|
|
495
|
-
async rotateApiKey(id, name, tenantId) {
|
|
496
|
-
return this.request({
|
|
497
|
-
method: 'POST',
|
|
498
|
-
path: `/auth/api-keys/${id}/rotate`,
|
|
499
|
-
query: tenantId ? { tenantId } : undefined,
|
|
500
|
-
body: name ? { name } : {},
|
|
501
|
-
});
|
|
502
|
-
}
|
|
503
|
-
async updateApiKeyPermissions(id, permissions, tenantId) {
|
|
504
|
-
const response = await this.request({
|
|
505
|
-
method: 'PATCH',
|
|
506
|
-
path: `/auth/api-keys/${id}/permissions`,
|
|
507
|
-
query: tenantId ? { tenantId } : undefined,
|
|
508
|
-
body: { permissions },
|
|
509
|
-
});
|
|
510
|
-
return response.apiKey;
|
|
511
|
-
}
|
|
512
|
-
async updateApiKeyConditions(id, conditions, tenantId) {
|
|
513
|
-
const response = await this.request({
|
|
514
|
-
method: 'PATCH',
|
|
515
|
-
path: `/auth/api-keys/${id}/conditions`,
|
|
516
|
-
query: tenantId ? { tenantId } : undefined,
|
|
517
|
-
body: { conditions },
|
|
518
|
-
});
|
|
519
|
-
return response.apiKey;
|
|
520
|
-
}
|
|
521
|
-
async setApiKeyEnabled(id, enabled, tenantId) {
|
|
522
|
-
const response = await this.request({
|
|
523
|
-
method: 'PATCH',
|
|
524
|
-
path: `/auth/api-keys/${id}/enabled`,
|
|
525
|
-
query: tenantId ? { tenantId } : undefined,
|
|
526
|
-
body: { enabled },
|
|
527
|
-
});
|
|
528
|
-
return response.apiKey;
|
|
529
|
-
}
|
|
530
|
-
// =========================================================================
|
|
531
|
-
// Permissions API
|
|
532
|
-
// =========================================================================
|
|
533
|
-
/**
|
|
534
|
-
* Get all available permissions from the database
|
|
535
|
-
* This is the single source of truth for valid permission IDs
|
|
536
|
-
*/
|
|
537
|
-
async getPermissions(category) {
|
|
538
|
-
return this.request({
|
|
539
|
-
method: 'GET',
|
|
540
|
-
path: '/v1/permissions',
|
|
541
|
-
query: category ? { category } : undefined,
|
|
542
|
-
});
|
|
543
|
-
}
|
|
544
|
-
/**
|
|
545
|
-
* Validate a list of permission IDs against the database
|
|
546
|
-
*/
|
|
547
|
-
async validatePermissions(permissions) {
|
|
548
|
-
return this.request({
|
|
549
|
-
method: 'POST',
|
|
550
|
-
path: '/v1/permissions/validate',
|
|
551
|
-
body: { permissions },
|
|
552
|
-
});
|
|
553
|
-
}
|
|
554
|
-
async getApiKeyPolicies(id, tenantId) {
|
|
555
|
-
return this.request({
|
|
556
|
-
method: 'GET',
|
|
557
|
-
path: `/auth/api-keys/${id}/policies`,
|
|
558
|
-
query: tenantId ? { tenantId } : undefined,
|
|
559
|
-
});
|
|
560
|
-
}
|
|
561
|
-
async attachApiKeyPolicy(keyId, policyId, tenantId) {
|
|
562
|
-
return this.request({
|
|
563
|
-
method: 'POST',
|
|
564
|
-
path: `/auth/api-keys/${keyId}/policies/${policyId}`,
|
|
565
|
-
query: tenantId ? { tenantId } : undefined,
|
|
566
|
-
});
|
|
567
|
-
}
|
|
568
|
-
async detachApiKeyPolicy(keyId, policyId, tenantId) {
|
|
569
|
-
return this.request({
|
|
570
|
-
method: 'DELETE',
|
|
571
|
-
path: `/auth/api-keys/${keyId}/policies/${policyId}`,
|
|
572
|
-
query: tenantId ? { tenantId } : undefined,
|
|
573
|
-
});
|
|
574
|
-
}
|
|
575
|
-
async getApiKeySelf() {
|
|
576
|
-
return this.request({
|
|
577
|
-
method: 'GET',
|
|
578
|
-
path: '/auth/api-keys/self',
|
|
579
|
-
});
|
|
580
|
-
}
|
|
581
|
-
async rotateApiKeySelf(name) {
|
|
582
|
-
return this.request({
|
|
583
|
-
method: 'POST',
|
|
584
|
-
path: '/auth/api-keys/self/rotate',
|
|
585
|
-
body: name ? { name } : {},
|
|
586
|
-
});
|
|
587
|
-
}
|
|
588
|
-
// ============ Managed API Keys ============
|
|
589
|
-
async createManagedApiKey(data) {
|
|
590
|
-
const response = await this.request({
|
|
591
|
-
method: 'POST',
|
|
592
|
-
path: '/auth/api-keys',
|
|
593
|
-
query: data.tenantId ? { tenantId: data.tenantId } : undefined,
|
|
594
|
-
body: {
|
|
595
|
-
name: data.name,
|
|
596
|
-
description: data.description,
|
|
597
|
-
expiresInDays: data.expiresInDays,
|
|
598
|
-
permissions: data.permissions,
|
|
599
|
-
ipAllowlist: data.ipAllowlist,
|
|
600
|
-
conditions: data.conditions,
|
|
601
|
-
managed: data.managed,
|
|
602
|
-
},
|
|
603
|
-
});
|
|
604
|
-
// Transform server response to CLI format
|
|
605
|
-
const serverKey = response.apiKey;
|
|
606
|
-
return {
|
|
607
|
-
apiKey: {
|
|
608
|
-
id: serverKey.id,
|
|
609
|
-
tenant_id: serverKey.tenant_id,
|
|
610
|
-
created_by: serverKey.created_by,
|
|
611
|
-
name: serverKey.name,
|
|
612
|
-
description: serverKey.description,
|
|
613
|
-
prefix: serverKey.prefix,
|
|
614
|
-
expires_at: serverKey.expires_at,
|
|
615
|
-
last_used: null,
|
|
616
|
-
created_at: serverKey.created_at,
|
|
617
|
-
ip_allowlist: null,
|
|
618
|
-
permissions: serverKey.permissions,
|
|
619
|
-
conditions: serverKey.conditions,
|
|
620
|
-
created_by_username: undefined,
|
|
621
|
-
enabled: serverKey.enabled,
|
|
622
|
-
rotation_count: serverKey.rotation_count,
|
|
623
|
-
last_rotation: serverKey.last_rotation,
|
|
624
|
-
is_managed: serverKey.is_managed,
|
|
625
|
-
rotation_mode: serverKey.rotation_mode,
|
|
626
|
-
rotation_interval: serverKey.rotation_interval_seconds ? formatSecondsToHuman(serverKey.rotation_interval_seconds) : undefined,
|
|
627
|
-
grace_period: formatSecondsToHuman(serverKey.grace_period_seconds),
|
|
628
|
-
notify_before: serverKey.notify_before,
|
|
629
|
-
webhook_url: serverKey.webhook_url,
|
|
630
|
-
next_rotation_at: serverKey.next_rotation_at,
|
|
631
|
-
last_bound_at: serverKey.last_bound_at,
|
|
632
|
-
},
|
|
633
|
-
message: response.message,
|
|
634
|
-
};
|
|
635
|
-
}
|
|
636
|
-
async listManagedApiKeys(tenantId) {
|
|
637
|
-
const response = await this.request({
|
|
638
|
-
method: 'GET',
|
|
639
|
-
path: '/auth/api-keys/managed',
|
|
640
|
-
query: tenantId ? { tenantId } : undefined,
|
|
641
|
-
});
|
|
642
|
-
// Transform each key
|
|
643
|
-
return {
|
|
644
|
-
items: response.items.map(key => ({
|
|
645
|
-
id: key.id,
|
|
646
|
-
tenant_id: key.tenant_id,
|
|
647
|
-
created_by: key.created_by,
|
|
648
|
-
name: key.name,
|
|
649
|
-
description: key.description,
|
|
650
|
-
prefix: key.prefix,
|
|
651
|
-
expires_at: key.expires_at,
|
|
652
|
-
last_used: key.last_used,
|
|
653
|
-
created_at: key.created_at,
|
|
654
|
-
ip_allowlist: null,
|
|
655
|
-
permissions: key.permissions,
|
|
656
|
-
conditions: key.conditions,
|
|
657
|
-
created_by_username: key.created_by_username,
|
|
658
|
-
enabled: key.enabled,
|
|
659
|
-
rotation_count: key.rotation_count,
|
|
660
|
-
last_rotation: key.last_rotation,
|
|
661
|
-
is_managed: key.is_managed,
|
|
662
|
-
rotation_mode: key.rotation_mode,
|
|
663
|
-
rotation_interval: key.rotation_interval_seconds ? formatSecondsToHuman(key.rotation_interval_seconds) : undefined,
|
|
664
|
-
grace_period: formatSecondsToHuman(key.grace_period_seconds),
|
|
665
|
-
notify_before: key.notify_before,
|
|
666
|
-
webhook_url: key.rotation_webhook_url ?? undefined,
|
|
667
|
-
next_rotation_at: key.next_rotation_at,
|
|
668
|
-
last_bound_at: key.first_used_at ?? undefined,
|
|
669
|
-
})),
|
|
670
|
-
pagination: response.pagination,
|
|
671
|
-
};
|
|
672
|
-
}
|
|
673
|
-
async getManagedApiKey(name, tenantId) {
|
|
674
|
-
const info = await this.request({
|
|
675
|
-
method: 'GET',
|
|
676
|
-
path: `/auth/api-keys/managed/${encodeURIComponent(name)}`,
|
|
677
|
-
query: tenantId ? { tenantId } : undefined,
|
|
678
|
-
});
|
|
679
|
-
// Transform to CLI's ManagedAPIKey format (snake_case)
|
|
680
|
-
return {
|
|
681
|
-
id: info.id,
|
|
682
|
-
tenant_id: info.tenantId,
|
|
683
|
-
created_by: info.createdBy ?? null,
|
|
684
|
-
name: info.name,
|
|
685
|
-
description: info.description ?? null,
|
|
686
|
-
prefix: info.prefix,
|
|
687
|
-
expires_at: info.expiresAt ?? '',
|
|
688
|
-
last_used: info.lastUsed ?? null,
|
|
689
|
-
created_at: info.createdAt ?? '',
|
|
690
|
-
ip_allowlist: null, // Not returned by server
|
|
691
|
-
permissions: info.permissions,
|
|
692
|
-
conditions: undefined,
|
|
693
|
-
created_by_username: info.createdByUsername,
|
|
694
|
-
enabled: info.enabled,
|
|
695
|
-
rotation_count: info.rotationCount,
|
|
696
|
-
last_rotation: info.lastRotatedAt ?? null,
|
|
697
|
-
is_managed: info.isManaged,
|
|
698
|
-
rotation_mode: info.rotationMode,
|
|
699
|
-
rotation_interval: info.rotationIntervalSeconds ? formatSecondsToHuman(info.rotationIntervalSeconds) : undefined,
|
|
700
|
-
grace_period: formatSecondsToHuman(info.gracePeriodSeconds),
|
|
701
|
-
notify_before: info.notifyBefore,
|
|
702
|
-
webhook_url: info.webhookUrl,
|
|
703
|
-
next_rotation_at: info.nextRotationAt,
|
|
704
|
-
last_bound_at: info.lastBoundAt,
|
|
705
|
-
};
|
|
706
|
-
}
|
|
707
|
-
async bindManagedApiKey(name, tenantId) {
|
|
708
|
-
return this.request({
|
|
709
|
-
method: 'POST',
|
|
710
|
-
path: `/auth/api-keys/managed/${encodeURIComponent(name)}/bind`,
|
|
711
|
-
query: tenantId ? { tenantId } : undefined,
|
|
712
|
-
body: {},
|
|
713
|
-
});
|
|
714
|
-
}
|
|
715
|
-
async rotateManagedApiKey(name, tenantId) {
|
|
716
|
-
return this.request({
|
|
717
|
-
method: 'POST',
|
|
718
|
-
path: `/auth/api-keys/managed/${encodeURIComponent(name)}/rotate`,
|
|
719
|
-
query: tenantId ? { tenantId } : undefined,
|
|
720
|
-
body: {},
|
|
721
|
-
});
|
|
722
|
-
}
|
|
723
|
-
async updateManagedApiKeyConfig(name, config, tenantId) {
|
|
724
|
-
const info = await this.request({
|
|
725
|
-
method: 'PATCH',
|
|
726
|
-
path: `/auth/api-keys/managed/${encodeURIComponent(name)}/config`,
|
|
727
|
-
query: tenantId ? { tenantId } : undefined,
|
|
728
|
-
body: config,
|
|
729
|
-
});
|
|
730
|
-
// Transform to CLI's ManagedAPIKey format (snake_case)
|
|
731
|
-
return {
|
|
732
|
-
id: info.id,
|
|
733
|
-
tenant_id: info.tenantId,
|
|
734
|
-
created_by: info.createdBy ?? null,
|
|
735
|
-
name: info.name,
|
|
736
|
-
description: info.description ?? null,
|
|
737
|
-
prefix: info.prefix,
|
|
738
|
-
expires_at: info.expiresAt ?? '',
|
|
739
|
-
last_used: info.lastUsed ?? null,
|
|
740
|
-
created_at: info.createdAt ?? '',
|
|
741
|
-
ip_allowlist: null,
|
|
742
|
-
permissions: info.permissions,
|
|
743
|
-
conditions: undefined,
|
|
744
|
-
created_by_username: info.createdByUsername,
|
|
745
|
-
enabled: info.enabled,
|
|
746
|
-
rotation_count: info.rotationCount,
|
|
747
|
-
last_rotation: info.lastRotatedAt ?? null,
|
|
748
|
-
is_managed: info.isManaged,
|
|
749
|
-
rotation_mode: info.rotationMode,
|
|
750
|
-
rotation_interval: info.rotationIntervalSeconds ? formatSecondsToHuman(info.rotationIntervalSeconds) : undefined,
|
|
751
|
-
grace_period: formatSecondsToHuman(info.gracePeriodSeconds),
|
|
752
|
-
notify_before: info.notifyBefore,
|
|
753
|
-
webhook_url: info.webhookUrl,
|
|
754
|
-
next_rotation_at: info.nextRotationAt,
|
|
755
|
-
last_bound_at: info.lastBoundAt,
|
|
756
|
-
};
|
|
757
|
-
}
|
|
758
|
-
async deleteManagedApiKey(name, tenantId) {
|
|
759
|
-
// First get the managed key to find its ID
|
|
760
|
-
const key = await this.getManagedApiKey(name, tenantId);
|
|
761
|
-
// Then delete via the standard API key delete endpoint
|
|
762
|
-
await this.request({
|
|
763
|
-
method: 'DELETE',
|
|
764
|
-
path: `/auth/api-keys/${encodeURIComponent(key.id)}`,
|
|
765
|
-
query: tenantId ? { tenantId } : undefined,
|
|
766
|
-
});
|
|
767
|
-
}
|
|
768
|
-
// ============ ABAC Policies ============
|
|
769
|
-
async listPolicies(options) {
|
|
770
|
-
return this.request({
|
|
771
|
-
method: 'GET',
|
|
772
|
-
path: '/v1/policies',
|
|
773
|
-
query: {
|
|
774
|
-
tenantId: options?.tenantId,
|
|
775
|
-
enabled: options?.enabled,
|
|
776
|
-
effect: options?.effect,
|
|
777
|
-
search: options?.search,
|
|
778
|
-
page: options?.page,
|
|
779
|
-
pageSize: options?.pageSize ?? 100,
|
|
780
|
-
},
|
|
781
|
-
});
|
|
782
|
-
}
|
|
783
|
-
async getPolicy(id) {
|
|
784
|
-
return this.request({
|
|
785
|
-
method: 'GET',
|
|
786
|
-
path: `/v1/policies/${id}`,
|
|
787
|
-
});
|
|
788
|
-
}
|
|
789
|
-
async createPolicy(data) {
|
|
790
|
-
return this.request({
|
|
791
|
-
method: 'POST',
|
|
792
|
-
path: '/v1/policies',
|
|
793
|
-
body: data,
|
|
794
|
-
});
|
|
795
|
-
}
|
|
796
|
-
async updatePolicy(id, data) {
|
|
797
|
-
return this.request({
|
|
798
|
-
method: 'PATCH',
|
|
799
|
-
path: `/v1/policies/${id}`,
|
|
800
|
-
body: data,
|
|
801
|
-
});
|
|
802
|
-
}
|
|
803
|
-
async deletePolicy(id) {
|
|
804
|
-
await this.request({
|
|
805
|
-
method: 'DELETE',
|
|
806
|
-
path: `/v1/policies/${id}`,
|
|
807
|
-
});
|
|
808
|
-
}
|
|
809
|
-
async togglePolicy(id, enabled) {
|
|
810
|
-
return this.request({
|
|
811
|
-
method: 'POST',
|
|
812
|
-
path: `/v1/policies/${id}/toggle`,
|
|
813
|
-
body: { enabled },
|
|
814
|
-
});
|
|
815
|
-
}
|
|
816
|
-
async validatePolicy(policy) {
|
|
817
|
-
return this.request({
|
|
818
|
-
method: 'POST',
|
|
819
|
-
path: '/v1/policies/validate',
|
|
820
|
-
body: policy,
|
|
821
|
-
});
|
|
822
|
-
}
|
|
823
|
-
async getPolicyAttachments(policyId) {
|
|
824
|
-
return this.request({
|
|
825
|
-
method: 'GET',
|
|
826
|
-
path: `/v1/policies/${policyId}/attachments`,
|
|
827
|
-
});
|
|
828
|
-
}
|
|
829
|
-
async attachPolicyToUser(policyId, userId) {
|
|
830
|
-
return this.request({
|
|
831
|
-
method: 'POST',
|
|
832
|
-
path: `/v1/policies/${policyId}/attach/user`,
|
|
833
|
-
body: { userId },
|
|
834
|
-
});
|
|
835
|
-
}
|
|
836
|
-
async attachPolicyToRole(policyId, roleId) {
|
|
837
|
-
return this.request({
|
|
838
|
-
method: 'POST',
|
|
839
|
-
path: `/v1/policies/${policyId}/attach/role`,
|
|
840
|
-
body: { roleId },
|
|
841
|
-
});
|
|
842
|
-
}
|
|
843
|
-
async detachPolicyFromUser(policyId, userId) {
|
|
844
|
-
return this.request({
|
|
845
|
-
method: 'DELETE',
|
|
846
|
-
path: `/v1/policies/${policyId}/attach/user/${userId}`,
|
|
847
|
-
});
|
|
848
|
-
}
|
|
849
|
-
async detachPolicyFromRole(policyId, roleId) {
|
|
850
|
-
return this.request({
|
|
851
|
-
method: 'DELETE',
|
|
852
|
-
path: `/v1/policies/${policyId}/attach/role/${roleId}`,
|
|
853
|
-
});
|
|
854
|
-
}
|
|
855
|
-
async getUserPolicies(userId) {
|
|
856
|
-
const response = await this.request({
|
|
857
|
-
method: 'GET',
|
|
858
|
-
path: `/v1/users/${userId}/policies`,
|
|
859
|
-
});
|
|
860
|
-
return response.policies;
|
|
861
|
-
}
|
|
862
|
-
async getRolePolicies(roleId) {
|
|
863
|
-
const response = await this.request({
|
|
864
|
-
method: 'GET',
|
|
865
|
-
path: `/v1/roles/${roleId}/policies`,
|
|
866
|
-
});
|
|
867
|
-
return response.policies;
|
|
868
|
-
}
|
|
869
|
-
async testPolicy(request) {
|
|
870
|
-
return this.request({
|
|
871
|
-
method: 'POST',
|
|
872
|
-
path: '/v1/policies/test',
|
|
873
|
-
body: request,
|
|
874
|
-
});
|
|
875
|
-
}
|
|
876
|
-
// ============ Generic methods for arbitrary endpoints ============
|
|
877
|
-
/**
|
|
878
|
-
* Generic GET request
|
|
879
|
-
* @param path - Path may include query string (e.g., '/v1/secrets?tenant=foo')
|
|
880
|
-
*/
|
|
881
|
-
async get(path) {
|
|
882
|
-
// Handle paths that include query strings
|
|
883
|
-
const [basePath, queryString] = path.split('?');
|
|
884
|
-
const query = {};
|
|
885
|
-
if (queryString) {
|
|
886
|
-
const params = new URLSearchParams(queryString);
|
|
887
|
-
for (const [key, value] of params.entries()) {
|
|
888
|
-
query[key] = value;
|
|
889
|
-
}
|
|
890
|
-
}
|
|
891
|
-
return this.request({ method: 'GET', path: basePath, query: Object.keys(query).length > 0 ? query : undefined });
|
|
892
|
-
}
|
|
893
|
-
/**
|
|
894
|
-
* Generic POST request
|
|
895
|
-
* @param path - Path may include query string (e.g., '/v1/sso/apps?tenantId=foo')
|
|
896
|
-
*/
|
|
897
|
-
async post(path, body) {
|
|
898
|
-
const [basePath, queryString] = path.split('?');
|
|
899
|
-
const query = {};
|
|
900
|
-
if (queryString) {
|
|
901
|
-
const params = new URLSearchParams(queryString);
|
|
902
|
-
for (const [key, value] of params.entries()) {
|
|
903
|
-
query[key] = value;
|
|
904
|
-
}
|
|
905
|
-
}
|
|
906
|
-
return this.request({ method: 'POST', path: basePath, body, query: Object.keys(query).length > 0 ? query : undefined });
|
|
907
|
-
}
|
|
908
|
-
/**
|
|
909
|
-
* Generic DELETE request
|
|
910
|
-
* @param path - Path may include query string
|
|
911
|
-
*/
|
|
912
|
-
async delete(path) {
|
|
913
|
-
const [basePath, queryString] = path.split('?');
|
|
914
|
-
const query = {};
|
|
915
|
-
if (queryString) {
|
|
916
|
-
const params = new URLSearchParams(queryString);
|
|
917
|
-
for (const [key, value] of params.entries()) {
|
|
918
|
-
query[key] = value;
|
|
919
|
-
}
|
|
920
|
-
}
|
|
921
|
-
return this.request({ method: 'DELETE', path: basePath, query: Object.keys(query).length > 0 ? query : undefined });
|
|
922
|
-
}
|
|
923
|
-
/**
|
|
924
|
-
* Generic PUT request
|
|
925
|
-
* @param path - Path may include query string
|
|
926
|
-
*/
|
|
927
|
-
async put(path, body) {
|
|
928
|
-
const [basePath, queryString] = path.split('?');
|
|
929
|
-
const query = {};
|
|
930
|
-
if (queryString) {
|
|
931
|
-
const params = new URLSearchParams(queryString);
|
|
932
|
-
for (const [key, value] of params.entries()) {
|
|
933
|
-
query[key] = value;
|
|
934
|
-
}
|
|
935
|
-
}
|
|
936
|
-
return this.request({ method: 'PUT', path: basePath, body, query: Object.keys(query).length > 0 ? query : undefined });
|
|
937
|
-
}
|
|
938
|
-
/**
|
|
939
|
-
* Generic PATCH request
|
|
940
|
-
* @param path - Path may include query string
|
|
941
|
-
*/
|
|
942
|
-
async patch(path, body) {
|
|
943
|
-
const [basePath, queryString] = path.split('?');
|
|
944
|
-
const query = {};
|
|
945
|
-
if (queryString) {
|
|
946
|
-
const params = new URLSearchParams(queryString);
|
|
947
|
-
for (const [key, value] of params.entries()) {
|
|
948
|
-
query[key] = value;
|
|
949
|
-
}
|
|
950
|
-
}
|
|
951
|
-
return this.request({ method: 'PATCH', path: basePath, body, query: Object.keys(query).length > 0 ? query : undefined });
|
|
952
|
-
}
|
|
953
|
-
/**
|
|
954
|
-
* Get WebSocket URL for a given endpoint path
|
|
955
|
-
*/
|
|
956
|
-
getWebSocketUrl(wsPath) {
|
|
957
|
-
const url = new URL(this.baseUrl);
|
|
958
|
-
url.protocol = url.protocol === 'https:' ? 'wss:' : 'ws:';
|
|
959
|
-
url.pathname = wsPath;
|
|
960
|
-
return url.toString();
|
|
961
|
-
}
|
|
962
|
-
/**
|
|
963
|
-
* Get authentication headers for WebSocket connection
|
|
964
|
-
*/
|
|
965
|
-
async getAuthHeaders() {
|
|
966
|
-
const headers = {};
|
|
967
|
-
const apiKey = getApiKey();
|
|
968
|
-
if (hasApiKey() && apiKey) {
|
|
969
|
-
headers['X-API-Key'] = apiKey;
|
|
970
|
-
}
|
|
971
|
-
else {
|
|
972
|
-
const credentials = getCredentials();
|
|
973
|
-
if (credentials) {
|
|
974
|
-
// Check if token is expired and try to refresh
|
|
975
|
-
if (isTokenExpired() && credentials.refreshToken) {
|
|
976
|
-
await this.refreshToken();
|
|
977
|
-
}
|
|
978
|
-
const updatedCredentials = getCredentials();
|
|
979
|
-
if (updatedCredentials) {
|
|
980
|
-
headers.Authorization = `Bearer ${updatedCredentials.accessToken}`;
|
|
981
|
-
}
|
|
982
|
-
}
|
|
983
|
-
else if (hasEnvCredentials()) {
|
|
984
|
-
// Auto-login with env credentials
|
|
985
|
-
const envCreds = getEnvCredentials();
|
|
986
|
-
if (envCreds) {
|
|
987
|
-
await this.login(envCreds.username, envCreds.password);
|
|
988
|
-
const newCredentials = getCredentials();
|
|
989
|
-
if (newCredentials) {
|
|
990
|
-
headers.Authorization = `Bearer ${newCredentials.accessToken}`;
|
|
991
|
-
}
|
|
992
|
-
}
|
|
993
|
-
}
|
|
994
|
-
}
|
|
995
|
-
return headers;
|
|
996
|
-
}
|
|
997
|
-
}
|
|
998
|
-
// Export singleton instance
|
|
999
|
-
export const client = new VaultClient();
|
|
1000
|
-
// Export class for testing
|
|
1001
|
-
export { VaultClient };
|
|
10
|
+
export { client, VaultClient } from './client/index.js';
|
|
11
|
+
// Re-export all domain clients for advanced use cases
|
|
12
|
+
export { HttpClient, HealthClient, ClusterClient, TenantsClient, UsersClient, SuperadminsClient, LockdownClient, AuditClient, ApiKeysClient, ManagedKeysClient, PoliciesClient, PermissionsClient, } from './client/index.js';
|
|
1002
13
|
//# sourceMappingURL=client.js.map
|