@zincapp/znvault-cli 2.18.1 → 2.19.1
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/dynamic-secrets/connection.d.ts +17 -0
- package/dist/commands/dynamic-secrets/connection.d.ts.map +1 -0
- package/dist/commands/dynamic-secrets/connection.js +217 -0
- package/dist/commands/dynamic-secrets/connection.js.map +1 -0
- package/dist/commands/dynamic-secrets/creds.d.ts +5 -0
- package/dist/commands/dynamic-secrets/creds.d.ts.map +1 -0
- package/dist/commands/dynamic-secrets/creds.js +39 -0
- package/dist/commands/dynamic-secrets/creds.js.map +1 -0
- package/dist/commands/dynamic-secrets/helpers.d.ts +5 -0
- package/dist/commands/dynamic-secrets/helpers.d.ts.map +1 -0
- package/dist/commands/dynamic-secrets/helpers.js +36 -0
- package/dist/commands/dynamic-secrets/helpers.js.map +1 -0
- package/dist/commands/dynamic-secrets/index.d.ts +7 -0
- package/dist/commands/dynamic-secrets/index.d.ts.map +1 -0
- package/dist/commands/dynamic-secrets/index.js +173 -0
- package/dist/commands/dynamic-secrets/index.js.map +1 -0
- package/dist/commands/dynamic-secrets/lease.d.ts +11 -0
- package/dist/commands/dynamic-secrets/lease.d.ts.map +1 -0
- package/dist/commands/dynamic-secrets/lease.js +137 -0
- package/dist/commands/dynamic-secrets/lease.js.map +1 -0
- package/dist/commands/dynamic-secrets/role.d.ts +15 -0
- package/dist/commands/dynamic-secrets/role.d.ts.map +1 -0
- package/dist/commands/dynamic-secrets/role.js +184 -0
- package/dist/commands/dynamic-secrets/role.js.map +1 -0
- package/dist/commands/dynamic-secrets/types.d.ts +125 -0
- package/dist/commands/dynamic-secrets/types.d.ts.map +1 -0
- package/dist/commands/dynamic-secrets/types.js +3 -0
- package/dist/commands/dynamic-secrets/types.js.map +1 -0
- package/dist/commands/dynamic-secrets.d.ts +6 -2
- package/dist/commands/dynamic-secrets.d.ts.map +1 -1
- package/dist/commands/dynamic-secrets.js +6 -754
- package/dist/commands/dynamic-secrets.js.map +1 -1
- package/dist/commands/policy/attachments.d.ts +9 -0
- package/dist/commands/policy/attachments.d.ts.map +1 -0
- package/dist/commands/policy/attachments.js +161 -0
- package/dist/commands/policy/attachments.js.map +1 -0
- package/dist/commands/policy/crud.d.ts +8 -0
- package/dist/commands/policy/crud.d.ts.map +1 -0
- package/dist/commands/policy/crud.js +232 -0
- package/dist/commands/policy/crud.js.map +1 -0
- package/dist/commands/policy/helpers.d.ts +13 -0
- package/dist/commands/policy/helpers.d.ts.map +1 -0
- package/dist/commands/policy/helpers.js +61 -0
- package/dist/commands/policy/helpers.js.map +1 -0
- package/dist/commands/policy/index.d.ts +7 -0
- package/dist/commands/policy/index.d.ts.map +1 -0
- package/dist/commands/policy/index.js +160 -0
- package/dist/commands/policy/index.js.map +1 -0
- package/dist/commands/policy/io.d.ts +4 -0
- package/dist/commands/policy/io.d.ts.map +1 -0
- package/dist/commands/policy/io.js +65 -0
- package/dist/commands/policy/io.js.map +1 -0
- package/dist/commands/policy/list.d.ts +4 -0
- package/dist/commands/policy/list.d.ts.map +1 -0
- package/dist/commands/policy/list.js +99 -0
- package/dist/commands/policy/list.js.map +1 -0
- package/dist/commands/policy/test.d.ts +3 -0
- package/dist/commands/policy/test.d.ts.map +1 -0
- package/dist/commands/policy/test.js +58 -0
- package/dist/commands/policy/test.js.map +1 -0
- package/dist/commands/policy/types.d.ts +84 -0
- package/dist/commands/policy/types.d.ts.map +1 -0
- package/dist/commands/policy/types.js +3 -0
- package/dist/commands/policy/types.js.map +1 -0
- package/dist/commands/policy.d.ts +6 -2
- package/dist/commands/policy.d.ts.map +1 -1
- package/dist/commands/policy.js +4 -770
- package/dist/commands/policy.js.map +1 -1
- package/dist/commands/secret/index.d.ts.map +1 -1
- package/dist/commands/secret/index.js +2 -0
- package/dist/commands/secret/index.js.map +1 -1
- package/dist/commands/secret/patch/diff.d.ts +14 -0
- package/dist/commands/secret/patch/diff.d.ts.map +1 -0
- package/dist/commands/secret/patch/diff.js +181 -0
- package/dist/commands/secret/patch/diff.js.map +1 -0
- package/dist/commands/secret/patch/operations.d.ts +77 -0
- package/dist/commands/secret/patch/operations.d.ts.map +1 -0
- package/dist/commands/secret/patch/operations.js +351 -0
- package/dist/commands/secret/patch/operations.js.map +1 -0
- package/dist/commands/secret/patch/parsers.d.ts +22 -0
- package/dist/commands/secret/patch/parsers.d.ts.map +1 -0
- package/dist/commands/secret/patch/parsers.js +349 -0
- package/dist/commands/secret/patch/parsers.js.map +1 -0
- package/dist/commands/secret/patch/types.d.ts +109 -0
- package/dist/commands/secret/patch/types.d.ts.map +1 -0
- package/dist/commands/secret/patch/types.js +22 -0
- package/dist/commands/secret/patch/types.js.map +1 -0
- package/dist/commands/secret/patch.d.ts +9 -0
- package/dist/commands/secret/patch.d.ts.map +1 -0
- package/dist/commands/secret/patch.js +247 -0
- package/dist/commands/secret/patch.js.map +1 -0
- package/dist/lib/db/audit.d.ts +16 -0
- package/dist/lib/db/audit.d.ts.map +1 -0
- package/dist/lib/db/audit.js +60 -0
- package/dist/lib/db/audit.js.map +1 -0
- package/dist/lib/db/client.d.ts +27 -0
- package/dist/lib/db/client.d.ts.map +1 -0
- package/dist/lib/db/client.js +70 -0
- package/dist/lib/db/client.js.map +1 -0
- package/dist/lib/db/emergency.d.ts +50 -0
- package/dist/lib/db/emergency.d.ts.map +1 -0
- package/dist/lib/db/emergency.js +180 -0
- package/dist/lib/db/emergency.js.map +1 -0
- package/dist/lib/db/health.d.ts +14 -0
- package/dist/lib/db/health.d.ts.map +1 -0
- package/dist/lib/db/health.js +177 -0
- package/dist/lib/db/health.js.map +1 -0
- package/dist/lib/db/index.d.ts +56 -0
- package/dist/lib/db/index.d.ts.map +1 -0
- package/dist/lib/db/index.js +107 -0
- package/dist/lib/db/index.js.map +1 -0
- package/dist/lib/db/lockdown.d.ts +15 -0
- package/dist/lib/db/lockdown.d.ts.map +1 -0
- package/dist/lib/db/lockdown.js +67 -0
- package/dist/lib/db/lockdown.js.map +1 -0
- package/dist/lib/db/tenants.d.ts +14 -0
- package/dist/lib/db/tenants.d.ts.map +1 -0
- package/dist/lib/db/tenants.js +88 -0
- package/dist/lib/db/tenants.js.map +1 -0
- package/dist/lib/db/types.d.ts +95 -0
- package/dist/lib/db/types.d.ts.map +1 -0
- package/dist/lib/db/types.js +3 -0
- package/dist/lib/db/types.js.map +1 -0
- package/dist/lib/db/users.d.ts +16 -0
- package/dist/lib/db/users.d.ts.map +1 -0
- package/dist/lib/db/users.js +95 -0
- package/dist/lib/db/users.js.map +1 -0
- package/dist/lib/db.d.ts +4 -112
- package/dist/lib/db.d.ts.map +1 -1
- package/dist/lib/db.js +4 -726
- package/dist/lib/db.js.map +1 -1
- package/package.json +5 -2
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
// Path: src/commands/secret/patch.ts
|
|
2
|
+
import ora from 'ora';
|
|
3
|
+
import { client } from '../../lib/client.js';
|
|
4
|
+
import * as output from '../../lib/output.js';
|
|
5
|
+
import { resolveSecretId } from './resolve.js';
|
|
6
|
+
import { SUPPORTED_FORMATS, PatchError, } from './patch/types.js';
|
|
7
|
+
import { parseSetArgs, parseUnsetArgs, applyOperations, deepClone, } from './patch/operations.js';
|
|
8
|
+
import { getParser, detectFormat } from './patch/parsers.js';
|
|
9
|
+
import { generateDiff, displayDiff, displayOperationsSummary } from './patch/diff.js';
|
|
10
|
+
/**
|
|
11
|
+
* Extract the raw content from a decrypted secret's data
|
|
12
|
+
* Secrets can store data in different formats:
|
|
13
|
+
* - text: { text: "content" }
|
|
14
|
+
* - raw object: { key: value, ... }
|
|
15
|
+
*/
|
|
16
|
+
function extractContent(data) {
|
|
17
|
+
// If it has a "text" field, use that as the raw content
|
|
18
|
+
if (typeof data.text === 'string') {
|
|
19
|
+
return data.text;
|
|
20
|
+
}
|
|
21
|
+
// Otherwise, serialize the data object as JSON
|
|
22
|
+
return JSON.stringify(data, null, 2);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Wrap content back into the data structure
|
|
26
|
+
*/
|
|
27
|
+
function wrapContent(originalData, content, format) {
|
|
28
|
+
// If original had a "text" field, preserve that structure
|
|
29
|
+
if (typeof originalData.text === 'string') {
|
|
30
|
+
return { ...originalData, text: content };
|
|
31
|
+
}
|
|
32
|
+
// Otherwise, parse the content based on format
|
|
33
|
+
const parser = getParser(format);
|
|
34
|
+
return parser.parse(content);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Collect repeatable option values
|
|
38
|
+
*/
|
|
39
|
+
function collect(value, previous) {
|
|
40
|
+
return previous.concat([value]);
|
|
41
|
+
}
|
|
42
|
+
export function registerPatchCommand(secretCmd) {
|
|
43
|
+
secretCmd
|
|
44
|
+
.command('patch <id-or-alias>')
|
|
45
|
+
.description('Partially modify secret data without replacing the entire value')
|
|
46
|
+
.option('--set <path=value>', 'Set/update a key (repeatable)', collect, [])
|
|
47
|
+
.option('--unset <path>', 'Remove a key (repeatable)', collect, [])
|
|
48
|
+
.option('--format <format>', `Force format: ${SUPPORTED_FORMATS.join(', ')}`)
|
|
49
|
+
.option('--dry-run', 'Preview changes without applying')
|
|
50
|
+
.option('--json', 'Output result as JSON')
|
|
51
|
+
.addHelpText('after', `
|
|
52
|
+
Examples:
|
|
53
|
+
# JSON: Set top-level key
|
|
54
|
+
znvault secret patch config/app --set api_version=v2
|
|
55
|
+
|
|
56
|
+
# JSON: Set nested key (dot notation)
|
|
57
|
+
znvault secret patch config/app --set database.host=db.prod.example.com
|
|
58
|
+
|
|
59
|
+
# JSON: Multiple operations
|
|
60
|
+
znvault secret patch config/app \\
|
|
61
|
+
--set database.host=db.example.com \\
|
|
62
|
+
--set database.port=5432 \\
|
|
63
|
+
--unset deprecated_field
|
|
64
|
+
|
|
65
|
+
# ENV: Add/update variables
|
|
66
|
+
znvault secret patch config/env --set DATABASE_URL=postgres://... --unset OLD_VAR
|
|
67
|
+
|
|
68
|
+
# YAML: Nested paths
|
|
69
|
+
znvault secret patch config/k8s --set spec.replicas=3
|
|
70
|
+
|
|
71
|
+
# Array operations
|
|
72
|
+
znvault secret patch config/app --set servers[0]=first-server
|
|
73
|
+
znvault secret patch config/app --set servers[+]=append-new-server
|
|
74
|
+
|
|
75
|
+
# Preview changes
|
|
76
|
+
znvault secret patch config/app --set version=2.0 --dry-run
|
|
77
|
+
|
|
78
|
+
Path Syntax:
|
|
79
|
+
key Top-level key
|
|
80
|
+
a.b.c Nested path
|
|
81
|
+
arr[0] Array index
|
|
82
|
+
arr[+] Append to array
|
|
83
|
+
a.b[0].c Mixed path
|
|
84
|
+
|
|
85
|
+
Value Types:
|
|
86
|
+
true/false Boolean
|
|
87
|
+
123, 45.67 Number
|
|
88
|
+
null Null
|
|
89
|
+
{...}, [...] JSON object/array
|
|
90
|
+
other String
|
|
91
|
+
`)
|
|
92
|
+
.action(async (idOrAlias, options) => {
|
|
93
|
+
// Validate options
|
|
94
|
+
if ((!options.set || options.set.length === 0) &&
|
|
95
|
+
(!options.unset || options.unset.length === 0)) {
|
|
96
|
+
output.error('At least one --set or --unset option is required');
|
|
97
|
+
process.exit(1);
|
|
98
|
+
}
|
|
99
|
+
// Validate format option
|
|
100
|
+
if (options.format !== undefined && !SUPPORTED_FORMATS.includes(options.format)) {
|
|
101
|
+
output.error(`Invalid format: ${options.format}. Supported: ${SUPPORTED_FORMATS.join(', ')}`);
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
|
104
|
+
const spinner = ora('Resolving secret...').start();
|
|
105
|
+
let id;
|
|
106
|
+
let secret;
|
|
107
|
+
try {
|
|
108
|
+
// Resolve alias to UUID
|
|
109
|
+
id = await resolveSecretId(idOrAlias);
|
|
110
|
+
spinner.text = 'Decrypting secret...';
|
|
111
|
+
// Decrypt current secret
|
|
112
|
+
secret = await client.post(`/v1/secrets/${id}/decrypt`, {});
|
|
113
|
+
spinner.stop();
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
spinner.fail('Failed to fetch secret');
|
|
117
|
+
output.error(error.message);
|
|
118
|
+
process.exit(1);
|
|
119
|
+
}
|
|
120
|
+
// Parse operations
|
|
121
|
+
let operations;
|
|
122
|
+
try {
|
|
123
|
+
const setOps = parseSetArgs(options.set ?? []);
|
|
124
|
+
const unsetOps = parseUnsetArgs(options.unset ?? []);
|
|
125
|
+
operations = [...setOps, ...unsetOps];
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
if (error instanceof PatchError) {
|
|
129
|
+
output.error(`Invalid operation: ${error.message}`);
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
output.error(`Failed to parse operations: ${error.message}`);
|
|
133
|
+
}
|
|
134
|
+
process.exit(1);
|
|
135
|
+
}
|
|
136
|
+
// Extract content from secret data
|
|
137
|
+
const originalData = secret.data;
|
|
138
|
+
const originalContent = extractContent(originalData);
|
|
139
|
+
// Detect format
|
|
140
|
+
const format = detectFormat(originalContent, options.format, secret.contentType, secret.subType);
|
|
141
|
+
// Parse content
|
|
142
|
+
let parsedData;
|
|
143
|
+
try {
|
|
144
|
+
const parser = getParser(format);
|
|
145
|
+
parsedData = parser.parse(originalContent);
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
if (error instanceof PatchError) {
|
|
149
|
+
output.error(`Failed to parse secret data as ${format}: ${error.message}`);
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
output.error(`Parse error: ${error.message}`);
|
|
153
|
+
}
|
|
154
|
+
process.exit(1);
|
|
155
|
+
}
|
|
156
|
+
// Clone and apply operations
|
|
157
|
+
const modifiedData = deepClone(parsedData);
|
|
158
|
+
let appliedOps;
|
|
159
|
+
try {
|
|
160
|
+
appliedOps = applyOperations(modifiedData, operations);
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
if (error instanceof PatchError) {
|
|
164
|
+
output.error(`Failed to apply operation: ${error.message}`);
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
output.error(`Operation error: ${error.message}`);
|
|
168
|
+
}
|
|
169
|
+
process.exit(1);
|
|
170
|
+
}
|
|
171
|
+
// Serialize back
|
|
172
|
+
let modifiedContent;
|
|
173
|
+
try {
|
|
174
|
+
const parser = getParser(format);
|
|
175
|
+
modifiedContent = parser.stringify(modifiedData);
|
|
176
|
+
}
|
|
177
|
+
catch (error) {
|
|
178
|
+
if (error instanceof PatchError) {
|
|
179
|
+
output.error(`Failed to serialize to ${format}: ${error.message}`);
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
output.error(`Serialize error: ${error.message}`);
|
|
183
|
+
}
|
|
184
|
+
process.exit(1);
|
|
185
|
+
}
|
|
186
|
+
// Dry-run mode: show diff and exit
|
|
187
|
+
if (options.dryRun) {
|
|
188
|
+
const originalSerialized = getParser(format).stringify(parsedData);
|
|
189
|
+
const diff = generateDiff(originalSerialized, modifiedContent, appliedOps);
|
|
190
|
+
if (options.json) {
|
|
191
|
+
output.json({
|
|
192
|
+
dryRun: true,
|
|
193
|
+
format,
|
|
194
|
+
operations: appliedOps,
|
|
195
|
+
diff: {
|
|
196
|
+
before: diff.before,
|
|
197
|
+
after: diff.after,
|
|
198
|
+
changes: diff.changes,
|
|
199
|
+
},
|
|
200
|
+
});
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
output.info(`Dry-run mode - no changes will be applied`);
|
|
204
|
+
console.log();
|
|
205
|
+
console.log(`Secret: ${secret.alias}`);
|
|
206
|
+
console.log(`Format: ${format}`);
|
|
207
|
+
displayDiff(diff);
|
|
208
|
+
displayOperationsSummary(appliedOps);
|
|
209
|
+
console.log();
|
|
210
|
+
output.info('Run without --dry-run to apply changes');
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
// Apply changes
|
|
214
|
+
const updateSpinner = ora('Applying changes...').start();
|
|
215
|
+
try {
|
|
216
|
+
// Wrap content back into the appropriate data structure
|
|
217
|
+
const newData = wrapContent(originalData, modifiedContent, format);
|
|
218
|
+
// Update the secret
|
|
219
|
+
const result = await client.put(`/v1/secrets/${id}`, {
|
|
220
|
+
data: newData,
|
|
221
|
+
});
|
|
222
|
+
updateSpinner.stop();
|
|
223
|
+
if (options.json) {
|
|
224
|
+
output.json({
|
|
225
|
+
success: true,
|
|
226
|
+
id: result.id,
|
|
227
|
+
alias: result.alias,
|
|
228
|
+
version: result.version,
|
|
229
|
+
format,
|
|
230
|
+
operations: appliedOps,
|
|
231
|
+
});
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
output.success('Secret patched successfully!');
|
|
235
|
+
console.log(` Alias: ${result.alias}`);
|
|
236
|
+
console.log(` Version: ${result.version}`);
|
|
237
|
+
console.log(` Format: ${format}`);
|
|
238
|
+
displayOperationsSummary(appliedOps);
|
|
239
|
+
}
|
|
240
|
+
catch (error) {
|
|
241
|
+
updateSpinner.fail('Failed to update secret');
|
|
242
|
+
output.error(error.message);
|
|
243
|
+
process.exit(1);
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
//# sourceMappingURL=patch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"patch.js","sourceRoot":"","sources":["../../../src/commands/secret/patch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Audit log operations
|
|
3
|
+
*/
|
|
4
|
+
import type { AuditEntry, AuditVerifyResult } from '../../types/index.js';
|
|
5
|
+
import { BaseDBClient } from './client.js';
|
|
6
|
+
export declare class AuditOperations extends BaseDBClient {
|
|
7
|
+
listAudit(options?: {
|
|
8
|
+
user?: string;
|
|
9
|
+
action?: string;
|
|
10
|
+
startDate?: string;
|
|
11
|
+
endDate?: string;
|
|
12
|
+
limit?: number;
|
|
13
|
+
}): Promise<AuditEntry[]>;
|
|
14
|
+
verifyAuditChain(): Promise<AuditVerifyResult>;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=audit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../../src/lib/db/audit.ts"],"names":[],"mappings":"AAEA;;GAEG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAE1E,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,qBAAa,eAAgB,SAAQ,YAAY;IACzC,SAAS,CAAC,OAAO,CAAC,EAAE;QACxB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IA2CnB,gBAAgB,IAAI,OAAO,CAAC,iBAAiB,CAAC;CAwBrD"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// Path: src/lib/db/audit.ts
|
|
2
|
+
import { BaseDBClient } from './client.js';
|
|
3
|
+
export class AuditOperations extends BaseDBClient {
|
|
4
|
+
async listAudit(options) {
|
|
5
|
+
let sql = 'SELECT * FROM audit_log WHERE 1=1';
|
|
6
|
+
const params = [];
|
|
7
|
+
let paramIndex = 1;
|
|
8
|
+
if (options?.user) {
|
|
9
|
+
sql += ` AND (client_cn = $${paramIndex} OR user_id = $${paramIndex})`;
|
|
10
|
+
params.push(options.user);
|
|
11
|
+
paramIndex++;
|
|
12
|
+
}
|
|
13
|
+
if (options?.action) {
|
|
14
|
+
sql += ` AND action = $${paramIndex++}`;
|
|
15
|
+
params.push(options.action);
|
|
16
|
+
}
|
|
17
|
+
if (options?.startDate) {
|
|
18
|
+
sql += ` AND timestamp >= $${paramIndex++}`;
|
|
19
|
+
params.push(new Date(options.startDate));
|
|
20
|
+
}
|
|
21
|
+
if (options?.endDate) {
|
|
22
|
+
sql += ` AND timestamp <= $${paramIndex++}`;
|
|
23
|
+
params.push(new Date(options.endDate));
|
|
24
|
+
}
|
|
25
|
+
sql += ` ORDER BY timestamp DESC LIMIT $${paramIndex}`;
|
|
26
|
+
params.push(options?.limit ?? 100);
|
|
27
|
+
const rows = await this.query(sql, params);
|
|
28
|
+
return rows.map(r => ({
|
|
29
|
+
id: r.id,
|
|
30
|
+
ts: r.timestamp.toISOString(),
|
|
31
|
+
clientCn: r.client_cn ?? '',
|
|
32
|
+
action: r.action,
|
|
33
|
+
resource: r.resource_type ? `${r.resource_type}/${r.resource_id ?? ''}` : '',
|
|
34
|
+
statusCode: r.status_code,
|
|
35
|
+
tenantId: r.tenant_id ?? undefined,
|
|
36
|
+
ip: r.ip_address ?? undefined,
|
|
37
|
+
}));
|
|
38
|
+
}
|
|
39
|
+
async verifyAuditChain() {
|
|
40
|
+
const countResult = await this.queryOne('SELECT COUNT(*) as count FROM audit_log');
|
|
41
|
+
const total = parseInt(countResult?.count ?? '0', 10);
|
|
42
|
+
if (total === 0) {
|
|
43
|
+
return {
|
|
44
|
+
valid: true,
|
|
45
|
+
totalEntries: 0,
|
|
46
|
+
verifiedEntries: 0,
|
|
47
|
+
message: 'No audit entries to verify',
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
// For now, return a basic verification
|
|
51
|
+
// Full HMAC chain verification would require the secret key
|
|
52
|
+
return {
|
|
53
|
+
valid: true,
|
|
54
|
+
totalEntries: total,
|
|
55
|
+
verifiedEntries: total,
|
|
56
|
+
message: `Verified ${total} audit entries (chain integrity check requires API access)`,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=audit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.js","sourceRoot":"","sources":["../../../src/lib/db/audit.ts"],"names":[],"mappings":"AAAA,4BAA4B;AAQ5B,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,OAAO,eAAgB,SAAQ,YAAY;IAC/C,KAAK,CAAC,SAAS,CAAC,OAMf;QACC,IAAI,GAAG,GAAG,mCAAmC,CAAC;QAC9C,MAAM,MAAM,GAAc,EAAE,CAAC;QAC7B,IAAI,UAAU,GAAG,CAAC,CAAC;QAEnB,IAAI,OAAO,EAAE,IAAI,EAAE,CAAC;YAClB,GAAG,IAAI,sBAAsB,UAAU,kBAAkB,UAAU,GAAG,CAAC;YACvE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAC1B,UAAU,EAAE,CAAC;QACf,CAAC;QAED,IAAI,OAAO,EAAE,MAAM,EAAE,CAAC;YACpB,GAAG,IAAI,kBAAkB,UAAU,EAAE,EAAE,CAAC;YACxC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC9B,CAAC;QAED,IAAI,OAAO,EAAE,SAAS,EAAE,CAAC;YACvB,GAAG,IAAI,sBAAsB,UAAU,EAAE,EAAE,CAAC;YAC5C,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;QAC3C,CAAC;QAED,IAAI,OAAO,EAAE,OAAO,EAAE,CAAC;YACrB,GAAG,IAAI,sBAAsB,UAAU,EAAE,EAAE,CAAC;YAC5C,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;QACzC,CAAC;QAED,GAAG,IAAI,mCAAmC,UAAU,EAAE,CAAC;QACvD,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,IAAI,GAAG,CAAC,CAAC;QAEnC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,KAAK,CAAc,GAAG,EAAE,MAAM,CAAC,CAAC;QAExD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACpB,EAAE,EAAE,CAAC,CAAC,EAAE;YACR,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,WAAW,EAAE;YAC7B,QAAQ,EAAE,CAAC,CAAC,SAAS,IAAI,EAAE;YAC3B,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,QAAQ,EAAE,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,aAAa,IAAI,CAAC,CAAC,WAAW,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE;YAC5E,UAAU,EAAE,CAAC,CAAC,WAAW;YACzB,QAAQ,EAAE,CAAC,CAAC,SAAS,IAAI,SAAS;YAClC,EAAE,EAAE,CAAC,CAAC,UAAU,IAAI,SAAS;SAC9B,CAAC,CAAC,CAAC;IACN,CAAC;IAED,KAAK,CAAC,gBAAgB;QACpB,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,QAAQ,CACrC,yCAAyC,CAC1C,CAAC;QACF,MAAM,KAAK,GAAG,QAAQ,CAAC,WAAW,EAAE,KAAK,IAAI,GAAG,EAAE,EAAE,CAAC,CAAC;QAEtD,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;YAChB,OAAO;gBACL,KAAK,EAAE,IAAI;gBACX,YAAY,EAAE,CAAC;gBACf,eAAe,EAAE,CAAC;gBAClB,OAAO,EAAE,4BAA4B;aACtC,CAAC;QACJ,CAAC;QAED,uCAAuC;QACvC,4DAA4D;QAC5D,OAAO;YACL,KAAK,EAAE,IAAI;YACX,YAAY,EAAE,KAAK;YACnB,eAAe,EAAE,KAAK;YACtB,OAAO,EAAE,YAAY,KAAK,4DAA4D;SACvF,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base database client with connection management
|
|
3
|
+
*/
|
|
4
|
+
import pg from 'pg';
|
|
5
|
+
/**
|
|
6
|
+
* Base database client for direct PostgreSQL operations.
|
|
7
|
+
* Used for local mode (running on vault nodes) and emergency operations.
|
|
8
|
+
*/
|
|
9
|
+
export declare class BaseDBClient {
|
|
10
|
+
protected client: pg.Client;
|
|
11
|
+
protected connected: boolean;
|
|
12
|
+
constructor();
|
|
13
|
+
connect(): Promise<void>;
|
|
14
|
+
close(): Promise<void>;
|
|
15
|
+
disconnect(): Promise<void>;
|
|
16
|
+
protected query<T>(sql: string, params?: unknown[]): Promise<T[]>;
|
|
17
|
+
protected queryOne<T>(sql: string, params?: unknown[]): Promise<T | null>;
|
|
18
|
+
/**
|
|
19
|
+
* Execute a command asynchronously with timeout
|
|
20
|
+
*/
|
|
21
|
+
protected execAsync(command: string, timeoutMs: number): Promise<string>;
|
|
22
|
+
/**
|
|
23
|
+
* Get raw pg.Client for direct operations
|
|
24
|
+
*/
|
|
25
|
+
protected getRawClient(): pg.Client;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/lib/db/client.ts"],"names":[],"mappings":"AAEA;;GAEG;AAEH,OAAO,EAAE,MAAM,IAAI,CAAC;AAKpB;;;GAGG;AACH,qBAAa,YAAY;IACvB,SAAS,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC;IAC5B,SAAS,CAAC,SAAS,UAAS;;IAiBtB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAOxB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAOtB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;cAIjB,KAAK,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;cAMvD,QAAQ,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAK/E;;OAEG;cACa,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAY9E;;OAEG;IACH,SAAS,CAAC,YAAY,IAAI,EAAE,CAAC,MAAM;CAGpC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// Path: src/lib/db/client.ts
|
|
2
|
+
/**
|
|
3
|
+
* Base database client with connection management
|
|
4
|
+
*/
|
|
5
|
+
import pg from 'pg';
|
|
6
|
+
import { getLocalConfig } from '../local.js';
|
|
7
|
+
const { Client } = pg;
|
|
8
|
+
/**
|
|
9
|
+
* Base database client for direct PostgreSQL operations.
|
|
10
|
+
* Used for local mode (running on vault nodes) and emergency operations.
|
|
11
|
+
*/
|
|
12
|
+
export class BaseDBClient {
|
|
13
|
+
client;
|
|
14
|
+
connected = false;
|
|
15
|
+
constructor() {
|
|
16
|
+
const config = getLocalConfig();
|
|
17
|
+
if (!config) {
|
|
18
|
+
throw new Error('Database configuration not available.\n' +
|
|
19
|
+
'Either set DATABASE_URL environment variable or run with sudo on a vault node.');
|
|
20
|
+
}
|
|
21
|
+
this.client = new Client({
|
|
22
|
+
connectionString: config.databaseUrl,
|
|
23
|
+
ssl: config.databaseSsl ? { rejectUnauthorized: false } : false,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
async connect() {
|
|
27
|
+
if (!this.connected) {
|
|
28
|
+
await this.client.connect();
|
|
29
|
+
this.connected = true;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
async close() {
|
|
33
|
+
if (this.connected) {
|
|
34
|
+
await this.client.end();
|
|
35
|
+
this.connected = false;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
async disconnect() {
|
|
39
|
+
return this.close();
|
|
40
|
+
}
|
|
41
|
+
async query(sql, params) {
|
|
42
|
+
await this.connect();
|
|
43
|
+
const result = await this.client.query(sql, params);
|
|
44
|
+
return result.rows;
|
|
45
|
+
}
|
|
46
|
+
async queryOne(sql, params) {
|
|
47
|
+
const rows = await this.query(sql, params);
|
|
48
|
+
return rows[0] ?? null;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Execute a command asynchronously with timeout
|
|
52
|
+
*/
|
|
53
|
+
async execAsync(command, timeoutMs) {
|
|
54
|
+
const { exec } = await import('node:child_process');
|
|
55
|
+
const { promisify } = await import('node:util');
|
|
56
|
+
const execPromise = promisify(exec);
|
|
57
|
+
const { stdout } = await execPromise(command, {
|
|
58
|
+
encoding: 'utf-8',
|
|
59
|
+
timeout: timeoutMs,
|
|
60
|
+
});
|
|
61
|
+
return stdout;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Get raw pg.Client for direct operations
|
|
65
|
+
*/
|
|
66
|
+
getRawClient() {
|
|
67
|
+
return this.client;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/lib/db/client.ts"],"names":[],"mappings":"AAAA,6BAA6B;AAE7B;;GAEG;AAEH,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;AAEtB;;;GAGG;AACH,MAAM,OAAO,YAAY;IACb,MAAM,CAAY;IAClB,SAAS,GAAG,KAAK,CAAC;IAE5B;QACE,MAAM,MAAM,GAAG,cAAc,EAAE,CAAC;QAChC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CACb,yCAAyC;gBACzC,gFAAgF,CACjF,CAAC;QACJ,CAAC;QAED,IAAI,CAAC,MAAM,GAAG,IAAI,MAAM,CAAC;YACvB,gBAAgB,EAAE,MAAM,CAAC,WAAW;YACpC,GAAG,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,kBAAkB,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK;SAChE,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,OAAO;QACX,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YAC5B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACxB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;YACxB,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACzB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,UAAU;QACd,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC;IACtB,CAAC;IAES,KAAK,CAAC,KAAK,CAAI,GAAW,EAAE,MAAkB;QACtD,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QACrB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QACpD,OAAO,MAAM,CAAC,IAAW,CAAC;IAC5B,CAAC;IAES,KAAK,CAAC,QAAQ,CAAI,GAAW,EAAE,MAAkB;QACzD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,KAAK,CAAI,GAAG,EAAE,MAAM,CAAC,CAAC;QAC9C,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;IACzB,CAAC;IAED;;OAEG;IACO,KAAK,CAAC,SAAS,CAAC,OAAe,EAAE,SAAiB;QAC1D,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;QACpD,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC;QAChD,MAAM,WAAW,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAEpC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,WAAW,CAAC,OAAO,EAAE;YAC5C,QAAQ,EAAE,OAAO;YACjB,OAAO,EAAE,SAAS;SACnB,CAAC,CAAC;QACH,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;OAEG;IACO,YAAY;QACpB,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;CACF"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { BaseDBClient } from './client.js';
|
|
2
|
+
export interface ConnectionTestResult {
|
|
3
|
+
success: boolean;
|
|
4
|
+
message: string;
|
|
5
|
+
}
|
|
6
|
+
export interface UserStatusResult {
|
|
7
|
+
found: boolean;
|
|
8
|
+
user?: {
|
|
9
|
+
id: string;
|
|
10
|
+
username: string;
|
|
11
|
+
email: string | null;
|
|
12
|
+
role: string;
|
|
13
|
+
status: string;
|
|
14
|
+
totpEnabled: boolean;
|
|
15
|
+
failedAttempts: number;
|
|
16
|
+
lockedUntil: string | null;
|
|
17
|
+
lastLogin: string | null;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export interface OperationResult {
|
|
21
|
+
success: boolean;
|
|
22
|
+
message: string;
|
|
23
|
+
}
|
|
24
|
+
export declare class EmergencyOperations extends BaseDBClient {
|
|
25
|
+
/**
|
|
26
|
+
* Test database connection
|
|
27
|
+
*/
|
|
28
|
+
testConnection(): Promise<ConnectionTestResult>;
|
|
29
|
+
/**
|
|
30
|
+
* Get user by username (for internal use)
|
|
31
|
+
*/
|
|
32
|
+
private getUserByUsername;
|
|
33
|
+
/**
|
|
34
|
+
* Get user status (for diagnostics)
|
|
35
|
+
*/
|
|
36
|
+
getUserStatus(username: string): Promise<UserStatusResult>;
|
|
37
|
+
/**
|
|
38
|
+
* Reset a user's password directly in the database.
|
|
39
|
+
*/
|
|
40
|
+
resetPassword(username: string, newPassword: string): Promise<OperationResult>;
|
|
41
|
+
/**
|
|
42
|
+
* Unlock a locked user account
|
|
43
|
+
*/
|
|
44
|
+
unlockUser(username: string): Promise<OperationResult>;
|
|
45
|
+
/**
|
|
46
|
+
* Disable TOTP for a user
|
|
47
|
+
*/
|
|
48
|
+
disableTotp(username: string): Promise<OperationResult>;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=emergency.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emergency.d.ts","sourceRoot":"","sources":["../../../src/lib/db/emergency.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE;QACL,EAAE,EAAE,MAAM,CAAC;QACX,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QACrB,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,WAAW,EAAE,OAAO,CAAC;QACrB,cAAc,EAAE,MAAM,CAAC;QACvB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;KAC1B,CAAC;CACH;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,mBAAoB,SAAQ,YAAY;IACnD;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC,oBAAoB,CAAC;IAkBrD;;OAEG;YACW,iBAAiB;IAwB/B;;OAEG;IACG,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAsBhE;;OAEG;IACG,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IA+CpF;;OAEG;IACG,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IA8C5D;;OAEG;IACG,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;CA+C9D"}
|