vaultkeeper 0.3.0 → 1.0.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/index.cjs +170 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +183 -2
- package/dist/index.d.ts +183 -2
- package/dist/index.js +170 -2
- package/dist/index.js.map +1 -1
- package/dist/one-password-worker.js +80 -0
- package/dist/one-password-worker.js.map +1 -0
- package/package.json +2 -1
package/dist/index.cjs
CHANGED
|
@@ -5,6 +5,7 @@ var fs5 = require('fs/promises');
|
|
|
5
5
|
var path5 = require('path');
|
|
6
6
|
var os4 = require('os');
|
|
7
7
|
var crypto4 = require('crypto');
|
|
8
|
+
require('url');
|
|
8
9
|
var fs4 = require('fs');
|
|
9
10
|
var jose = require('jose');
|
|
10
11
|
|
|
@@ -162,6 +163,22 @@ var IdentityMismatchError = class extends VaultError {
|
|
|
162
163
|
this.currentHash = currentHash;
|
|
163
164
|
}
|
|
164
165
|
};
|
|
166
|
+
var InvalidAlgorithmError = class extends VaultError {
|
|
167
|
+
/**
|
|
168
|
+
* The algorithm that was requested.
|
|
169
|
+
*/
|
|
170
|
+
algorithm;
|
|
171
|
+
/**
|
|
172
|
+
* The set of algorithms that are allowed.
|
|
173
|
+
*/
|
|
174
|
+
allowed;
|
|
175
|
+
constructor(message, algorithm, allowed) {
|
|
176
|
+
super(message);
|
|
177
|
+
this.name = "InvalidAlgorithmError";
|
|
178
|
+
this.algorithm = algorithm;
|
|
179
|
+
this.allowed = allowed;
|
|
180
|
+
}
|
|
181
|
+
};
|
|
165
182
|
var SetupError = class extends VaultError {
|
|
166
183
|
/**
|
|
167
184
|
* The name of the dependency that caused the setup failure.
|
|
@@ -205,6 +222,7 @@ function isListableBackend(backend) {
|
|
|
205
222
|
// src/backend/registry.ts
|
|
206
223
|
var BackendRegistry = class {
|
|
207
224
|
static backends = /* @__PURE__ */ new Map();
|
|
225
|
+
static setups = /* @__PURE__ */ new Map();
|
|
208
226
|
/**
|
|
209
227
|
* Register a backend factory.
|
|
210
228
|
* @param type - Backend type identifier
|
|
@@ -217,7 +235,7 @@ var BackendRegistry = class {
|
|
|
217
235
|
* Create a backend instance by type.
|
|
218
236
|
* @param type - Backend type identifier
|
|
219
237
|
* @returns A SecretBackend instance
|
|
220
|
-
* @throws
|
|
238
|
+
* @throws {@link BackendUnavailableError} if the backend type is not registered
|
|
221
239
|
*/
|
|
222
240
|
static create(type) {
|
|
223
241
|
const factory = this.backends.get(type);
|
|
@@ -264,6 +282,46 @@ var BackendRegistry = class {
|
|
|
264
282
|
);
|
|
265
283
|
return results.filter((type) => type !== null);
|
|
266
284
|
}
|
|
285
|
+
/**
|
|
286
|
+
* Register a setup factory for a backend type.
|
|
287
|
+
* @param type - Backend type identifier
|
|
288
|
+
* @param factory - Factory function that creates a setup generator
|
|
289
|
+
*/
|
|
290
|
+
static registerSetup(type, factory) {
|
|
291
|
+
this.setups.set(type, factory);
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Get the setup factory for a backend type, if one is registered.
|
|
295
|
+
* @param type - Backend type identifier
|
|
296
|
+
* @returns The setup factory, or `undefined` if none is registered
|
|
297
|
+
*/
|
|
298
|
+
static getSetup(type) {
|
|
299
|
+
return this.setups.get(type);
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Check whether a setup factory is registered for the given backend type.
|
|
303
|
+
* @param type - Backend type identifier
|
|
304
|
+
* @returns `true` if a setup factory is registered
|
|
305
|
+
*/
|
|
306
|
+
static hasSetup(type) {
|
|
307
|
+
return this.setups.has(type);
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Clear all registered backend factories.
|
|
311
|
+
* Intended for use in tests only.
|
|
312
|
+
* @internal
|
|
313
|
+
*/
|
|
314
|
+
static clearBackends() {
|
|
315
|
+
this.backends.clear();
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Clear all registered setup factories.
|
|
319
|
+
* Intended for use in tests only.
|
|
320
|
+
* @internal
|
|
321
|
+
*/
|
|
322
|
+
static clearSetups() {
|
|
323
|
+
this.setups.clear();
|
|
324
|
+
}
|
|
267
325
|
};
|
|
268
326
|
async function execCommand(command, args, options) {
|
|
269
327
|
const result = await execCommandFull(command, args);
|
|
@@ -513,6 +571,21 @@ function validateBackendEntry(entry, index) {
|
|
|
513
571
|
}
|
|
514
572
|
result.path = entry.path;
|
|
515
573
|
}
|
|
574
|
+
if (entry.options !== void 0) {
|
|
575
|
+
if (!isObject(entry.options)) {
|
|
576
|
+
throw new Error(`backends[${String(index)}].options must be an object`);
|
|
577
|
+
}
|
|
578
|
+
const opts = {};
|
|
579
|
+
for (const [k, v] of Object.entries(entry.options)) {
|
|
580
|
+
if (typeof v !== "string") {
|
|
581
|
+
throw new Error(
|
|
582
|
+
`backends[${String(index)}].options["${k}"] must be a string`
|
|
583
|
+
);
|
|
584
|
+
}
|
|
585
|
+
opts[k] = v;
|
|
586
|
+
}
|
|
587
|
+
result.options = opts;
|
|
588
|
+
}
|
|
516
589
|
return result;
|
|
517
590
|
}
|
|
518
591
|
function validateConfig(config) {
|
|
@@ -1016,6 +1089,55 @@ function createSecretAccessor(secretValue) {
|
|
|
1016
1089
|
return proxy;
|
|
1017
1090
|
}
|
|
1018
1091
|
|
|
1092
|
+
// src/access/sign-util.ts
|
|
1093
|
+
var ALLOWED_ALGORITHMS = /* @__PURE__ */ new Set(["sha256", "sha384", "sha512"]);
|
|
1094
|
+
function resolveAlgorithmForKey(key, override) {
|
|
1095
|
+
const keyType = key.asymmetricKeyType;
|
|
1096
|
+
if (keyType === "ed25519" || keyType === "ed448") {
|
|
1097
|
+
return { signAlg: null, label: keyType };
|
|
1098
|
+
}
|
|
1099
|
+
const alg = (override ?? "sha256").toLowerCase();
|
|
1100
|
+
if (!ALLOWED_ALGORITHMS.has(alg)) {
|
|
1101
|
+
throw new InvalidAlgorithmError(
|
|
1102
|
+
`Unsupported algorithm '${alg}'. Allowed: ${[...ALLOWED_ALGORITHMS].join(", ")}`,
|
|
1103
|
+
alg,
|
|
1104
|
+
[...ALLOWED_ALGORITHMS]
|
|
1105
|
+
);
|
|
1106
|
+
}
|
|
1107
|
+
return { signAlg: alg, label: alg };
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
// src/access/delegated-sign.ts
|
|
1111
|
+
function delegatedSign(secretPem, request) {
|
|
1112
|
+
const key = crypto4__namespace.createPrivateKey(secretPem);
|
|
1113
|
+
const { signAlg, label } = resolveAlgorithmForKey(key, request.algorithm);
|
|
1114
|
+
const data = Buffer.isBuffer(request.data) ? request.data : Buffer.from(request.data);
|
|
1115
|
+
const signature = crypto4__namespace.sign(signAlg, data, key);
|
|
1116
|
+
return {
|
|
1117
|
+
signature: signature.toString("base64"),
|
|
1118
|
+
algorithm: label
|
|
1119
|
+
};
|
|
1120
|
+
}
|
|
1121
|
+
function delegatedVerify(request) {
|
|
1122
|
+
let key;
|
|
1123
|
+
try {
|
|
1124
|
+
key = crypto4__namespace.createPublicKey(request.publicKey);
|
|
1125
|
+
} catch {
|
|
1126
|
+
return false;
|
|
1127
|
+
}
|
|
1128
|
+
if (typeof request.publicKey === "string" && request.publicKey.includes("PRIVATE KEY")) {
|
|
1129
|
+
return false;
|
|
1130
|
+
}
|
|
1131
|
+
const { signAlg } = resolveAlgorithmForKey(key, request.algorithm);
|
|
1132
|
+
const sig = Buffer.from(request.signature, "base64");
|
|
1133
|
+
try {
|
|
1134
|
+
const data = Buffer.isBuffer(request.data) ? request.data : Buffer.from(request.data);
|
|
1135
|
+
return crypto4__namespace.verify(signAlg, data, key, sig);
|
|
1136
|
+
} catch {
|
|
1137
|
+
return false;
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1019
1141
|
// src/doctor/checks.ts
|
|
1020
1142
|
function parseVersion(raw) {
|
|
1021
1143
|
const match = /(\d+)\.(\d+)\.(\d+)/.exec(raw);
|
|
@@ -1373,6 +1495,52 @@ var VaultKeeper = class _VaultKeeper {
|
|
|
1373
1495
|
const claims = validateCapabilityToken(token);
|
|
1374
1496
|
return createSecretAccessor(claims.val);
|
|
1375
1497
|
}
|
|
1498
|
+
/**
|
|
1499
|
+
* Sign data using the private key embedded in a capability token.
|
|
1500
|
+
*
|
|
1501
|
+
* The signing key is extracted from the token's encrypted claims, used
|
|
1502
|
+
* for a single `crypto.sign()` call, and never exposed to the caller.
|
|
1503
|
+
* The algorithm is auto-detected from the key type unless overridden
|
|
1504
|
+
* in the request.
|
|
1505
|
+
*
|
|
1506
|
+
* @param token - A `CapabilityToken` obtained from `authorize()`.
|
|
1507
|
+
* @param request - The data to sign and optional algorithm override.
|
|
1508
|
+
* @returns The base64-encoded signature and algorithm label, together
|
|
1509
|
+
* with the vault metadata (`vaultResponse`).
|
|
1510
|
+
* @throws {VaultError} If `token` is invalid or was not created by this
|
|
1511
|
+
* vault instance.
|
|
1512
|
+
* @throws {InvalidAlgorithmError} If `request.algorithm` is not in the
|
|
1513
|
+
* allowed set (e.g. `'md5'`).
|
|
1514
|
+
*/
|
|
1515
|
+
async sign(token, request) {
|
|
1516
|
+
const claims = validateCapabilityToken(token);
|
|
1517
|
+
const result = delegatedSign(claims.val, request);
|
|
1518
|
+
await Promise.resolve();
|
|
1519
|
+
return {
|
|
1520
|
+
result,
|
|
1521
|
+
vaultResponse: { keyStatus: "current" }
|
|
1522
|
+
};
|
|
1523
|
+
}
|
|
1524
|
+
/**
|
|
1525
|
+
* Verify a signature using a public key.
|
|
1526
|
+
*
|
|
1527
|
+
* This is a static method — no VaultKeeper instance, secrets, or
|
|
1528
|
+
* capability tokens are required. It is safe to call from CI or any
|
|
1529
|
+
* context that has access to public key material.
|
|
1530
|
+
*
|
|
1531
|
+
* Returns `false` for invalid key material, malformed signatures, or
|
|
1532
|
+
* any verification failure (except disallowed algorithms, which throw).
|
|
1533
|
+
*
|
|
1534
|
+
* @throws {InvalidAlgorithmError} If `request.algorithm` is not in the
|
|
1535
|
+
* allowed set (e.g. `'md5'`).
|
|
1536
|
+
*
|
|
1537
|
+
* @param request - The data, signature, public key, and optional
|
|
1538
|
+
* algorithm override.
|
|
1539
|
+
* @returns `true` if the signature is valid, `false` otherwise.
|
|
1540
|
+
*/
|
|
1541
|
+
static verify(request) {
|
|
1542
|
+
return delegatedVerify(request);
|
|
1543
|
+
}
|
|
1376
1544
|
/**
|
|
1377
1545
|
* Rotate the current encryption key.
|
|
1378
1546
|
*
|
|
@@ -1497,6 +1665,7 @@ exports.CapabilityToken = CapabilityToken;
|
|
|
1497
1665
|
exports.DeviceNotPresentError = DeviceNotPresentError;
|
|
1498
1666
|
exports.FilesystemError = FilesystemError;
|
|
1499
1667
|
exports.IdentityMismatchError = IdentityMismatchError;
|
|
1668
|
+
exports.InvalidAlgorithmError = InvalidAlgorithmError;
|
|
1500
1669
|
exports.KeyRevokedError = KeyRevokedError;
|
|
1501
1670
|
exports.KeyRotatedError = KeyRotatedError;
|
|
1502
1671
|
exports.PluginNotFoundError = PluginNotFoundError;
|