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.js
CHANGED
|
@@ -3,6 +3,7 @@ import * as fs5 from 'fs/promises';
|
|
|
3
3
|
import * as path5 from 'path';
|
|
4
4
|
import * as os4 from 'os';
|
|
5
5
|
import * as crypto4 from 'crypto';
|
|
6
|
+
import 'url';
|
|
6
7
|
import * as fs4 from 'fs';
|
|
7
8
|
import { CompactEncrypt, compactDecrypt } from 'jose';
|
|
8
9
|
|
|
@@ -136,6 +137,22 @@ var IdentityMismatchError = class extends VaultError {
|
|
|
136
137
|
this.currentHash = currentHash;
|
|
137
138
|
}
|
|
138
139
|
};
|
|
140
|
+
var InvalidAlgorithmError = class extends VaultError {
|
|
141
|
+
/**
|
|
142
|
+
* The algorithm that was requested.
|
|
143
|
+
*/
|
|
144
|
+
algorithm;
|
|
145
|
+
/**
|
|
146
|
+
* The set of algorithms that are allowed.
|
|
147
|
+
*/
|
|
148
|
+
allowed;
|
|
149
|
+
constructor(message, algorithm, allowed) {
|
|
150
|
+
super(message);
|
|
151
|
+
this.name = "InvalidAlgorithmError";
|
|
152
|
+
this.algorithm = algorithm;
|
|
153
|
+
this.allowed = allowed;
|
|
154
|
+
}
|
|
155
|
+
};
|
|
139
156
|
var SetupError = class extends VaultError {
|
|
140
157
|
/**
|
|
141
158
|
* The name of the dependency that caused the setup failure.
|
|
@@ -179,6 +196,7 @@ function isListableBackend(backend) {
|
|
|
179
196
|
// src/backend/registry.ts
|
|
180
197
|
var BackendRegistry = class {
|
|
181
198
|
static backends = /* @__PURE__ */ new Map();
|
|
199
|
+
static setups = /* @__PURE__ */ new Map();
|
|
182
200
|
/**
|
|
183
201
|
* Register a backend factory.
|
|
184
202
|
* @param type - Backend type identifier
|
|
@@ -191,7 +209,7 @@ var BackendRegistry = class {
|
|
|
191
209
|
* Create a backend instance by type.
|
|
192
210
|
* @param type - Backend type identifier
|
|
193
211
|
* @returns A SecretBackend instance
|
|
194
|
-
* @throws
|
|
212
|
+
* @throws {@link BackendUnavailableError} if the backend type is not registered
|
|
195
213
|
*/
|
|
196
214
|
static create(type) {
|
|
197
215
|
const factory = this.backends.get(type);
|
|
@@ -238,6 +256,46 @@ var BackendRegistry = class {
|
|
|
238
256
|
);
|
|
239
257
|
return results.filter((type) => type !== null);
|
|
240
258
|
}
|
|
259
|
+
/**
|
|
260
|
+
* Register a setup factory for a backend type.
|
|
261
|
+
* @param type - Backend type identifier
|
|
262
|
+
* @param factory - Factory function that creates a setup generator
|
|
263
|
+
*/
|
|
264
|
+
static registerSetup(type, factory) {
|
|
265
|
+
this.setups.set(type, factory);
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Get the setup factory for a backend type, if one is registered.
|
|
269
|
+
* @param type - Backend type identifier
|
|
270
|
+
* @returns The setup factory, or `undefined` if none is registered
|
|
271
|
+
*/
|
|
272
|
+
static getSetup(type) {
|
|
273
|
+
return this.setups.get(type);
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Check whether a setup factory is registered for the given backend type.
|
|
277
|
+
* @param type - Backend type identifier
|
|
278
|
+
* @returns `true` if a setup factory is registered
|
|
279
|
+
*/
|
|
280
|
+
static hasSetup(type) {
|
|
281
|
+
return this.setups.has(type);
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Clear all registered backend factories.
|
|
285
|
+
* Intended for use in tests only.
|
|
286
|
+
* @internal
|
|
287
|
+
*/
|
|
288
|
+
static clearBackends() {
|
|
289
|
+
this.backends.clear();
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Clear all registered setup factories.
|
|
293
|
+
* Intended for use in tests only.
|
|
294
|
+
* @internal
|
|
295
|
+
*/
|
|
296
|
+
static clearSetups() {
|
|
297
|
+
this.setups.clear();
|
|
298
|
+
}
|
|
241
299
|
};
|
|
242
300
|
async function execCommand(command, args, options) {
|
|
243
301
|
const result = await execCommandFull(command, args);
|
|
@@ -487,6 +545,21 @@ function validateBackendEntry(entry, index) {
|
|
|
487
545
|
}
|
|
488
546
|
result.path = entry.path;
|
|
489
547
|
}
|
|
548
|
+
if (entry.options !== void 0) {
|
|
549
|
+
if (!isObject(entry.options)) {
|
|
550
|
+
throw new Error(`backends[${String(index)}].options must be an object`);
|
|
551
|
+
}
|
|
552
|
+
const opts = {};
|
|
553
|
+
for (const [k, v] of Object.entries(entry.options)) {
|
|
554
|
+
if (typeof v !== "string") {
|
|
555
|
+
throw new Error(
|
|
556
|
+
`backends[${String(index)}].options["${k}"] must be a string`
|
|
557
|
+
);
|
|
558
|
+
}
|
|
559
|
+
opts[k] = v;
|
|
560
|
+
}
|
|
561
|
+
result.options = opts;
|
|
562
|
+
}
|
|
490
563
|
return result;
|
|
491
564
|
}
|
|
492
565
|
function validateConfig(config) {
|
|
@@ -990,6 +1063,55 @@ function createSecretAccessor(secretValue) {
|
|
|
990
1063
|
return proxy;
|
|
991
1064
|
}
|
|
992
1065
|
|
|
1066
|
+
// src/access/sign-util.ts
|
|
1067
|
+
var ALLOWED_ALGORITHMS = /* @__PURE__ */ new Set(["sha256", "sha384", "sha512"]);
|
|
1068
|
+
function resolveAlgorithmForKey(key, override) {
|
|
1069
|
+
const keyType = key.asymmetricKeyType;
|
|
1070
|
+
if (keyType === "ed25519" || keyType === "ed448") {
|
|
1071
|
+
return { signAlg: null, label: keyType };
|
|
1072
|
+
}
|
|
1073
|
+
const alg = (override ?? "sha256").toLowerCase();
|
|
1074
|
+
if (!ALLOWED_ALGORITHMS.has(alg)) {
|
|
1075
|
+
throw new InvalidAlgorithmError(
|
|
1076
|
+
`Unsupported algorithm '${alg}'. Allowed: ${[...ALLOWED_ALGORITHMS].join(", ")}`,
|
|
1077
|
+
alg,
|
|
1078
|
+
[...ALLOWED_ALGORITHMS]
|
|
1079
|
+
);
|
|
1080
|
+
}
|
|
1081
|
+
return { signAlg: alg, label: alg };
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
// src/access/delegated-sign.ts
|
|
1085
|
+
function delegatedSign(secretPem, request) {
|
|
1086
|
+
const key = crypto4.createPrivateKey(secretPem);
|
|
1087
|
+
const { signAlg, label } = resolveAlgorithmForKey(key, request.algorithm);
|
|
1088
|
+
const data = Buffer.isBuffer(request.data) ? request.data : Buffer.from(request.data);
|
|
1089
|
+
const signature = crypto4.sign(signAlg, data, key);
|
|
1090
|
+
return {
|
|
1091
|
+
signature: signature.toString("base64"),
|
|
1092
|
+
algorithm: label
|
|
1093
|
+
};
|
|
1094
|
+
}
|
|
1095
|
+
function delegatedVerify(request) {
|
|
1096
|
+
let key;
|
|
1097
|
+
try {
|
|
1098
|
+
key = crypto4.createPublicKey(request.publicKey);
|
|
1099
|
+
} catch {
|
|
1100
|
+
return false;
|
|
1101
|
+
}
|
|
1102
|
+
if (typeof request.publicKey === "string" && request.publicKey.includes("PRIVATE KEY")) {
|
|
1103
|
+
return false;
|
|
1104
|
+
}
|
|
1105
|
+
const { signAlg } = resolveAlgorithmForKey(key, request.algorithm);
|
|
1106
|
+
const sig = Buffer.from(request.signature, "base64");
|
|
1107
|
+
try {
|
|
1108
|
+
const data = Buffer.isBuffer(request.data) ? request.data : Buffer.from(request.data);
|
|
1109
|
+
return crypto4.verify(signAlg, data, key, sig);
|
|
1110
|
+
} catch {
|
|
1111
|
+
return false;
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
|
+
|
|
993
1115
|
// src/doctor/checks.ts
|
|
994
1116
|
function parseVersion(raw) {
|
|
995
1117
|
const match = /(\d+)\.(\d+)\.(\d+)/.exec(raw);
|
|
@@ -1347,6 +1469,52 @@ var VaultKeeper = class _VaultKeeper {
|
|
|
1347
1469
|
const claims = validateCapabilityToken(token);
|
|
1348
1470
|
return createSecretAccessor(claims.val);
|
|
1349
1471
|
}
|
|
1472
|
+
/**
|
|
1473
|
+
* Sign data using the private key embedded in a capability token.
|
|
1474
|
+
*
|
|
1475
|
+
* The signing key is extracted from the token's encrypted claims, used
|
|
1476
|
+
* for a single `crypto.sign()` call, and never exposed to the caller.
|
|
1477
|
+
* The algorithm is auto-detected from the key type unless overridden
|
|
1478
|
+
* in the request.
|
|
1479
|
+
*
|
|
1480
|
+
* @param token - A `CapabilityToken` obtained from `authorize()`.
|
|
1481
|
+
* @param request - The data to sign and optional algorithm override.
|
|
1482
|
+
* @returns The base64-encoded signature and algorithm label, together
|
|
1483
|
+
* with the vault metadata (`vaultResponse`).
|
|
1484
|
+
* @throws {VaultError} If `token` is invalid or was not created by this
|
|
1485
|
+
* vault instance.
|
|
1486
|
+
* @throws {InvalidAlgorithmError} If `request.algorithm` is not in the
|
|
1487
|
+
* allowed set (e.g. `'md5'`).
|
|
1488
|
+
*/
|
|
1489
|
+
async sign(token, request) {
|
|
1490
|
+
const claims = validateCapabilityToken(token);
|
|
1491
|
+
const result = delegatedSign(claims.val, request);
|
|
1492
|
+
await Promise.resolve();
|
|
1493
|
+
return {
|
|
1494
|
+
result,
|
|
1495
|
+
vaultResponse: { keyStatus: "current" }
|
|
1496
|
+
};
|
|
1497
|
+
}
|
|
1498
|
+
/**
|
|
1499
|
+
* Verify a signature using a public key.
|
|
1500
|
+
*
|
|
1501
|
+
* This is a static method — no VaultKeeper instance, secrets, or
|
|
1502
|
+
* capability tokens are required. It is safe to call from CI or any
|
|
1503
|
+
* context that has access to public key material.
|
|
1504
|
+
*
|
|
1505
|
+
* Returns `false` for invalid key material, malformed signatures, or
|
|
1506
|
+
* any verification failure (except disallowed algorithms, which throw).
|
|
1507
|
+
*
|
|
1508
|
+
* @throws {InvalidAlgorithmError} If `request.algorithm` is not in the
|
|
1509
|
+
* allowed set (e.g. `'md5'`).
|
|
1510
|
+
*
|
|
1511
|
+
* @param request - The data, signature, public key, and optional
|
|
1512
|
+
* algorithm override.
|
|
1513
|
+
* @returns `true` if the signature is valid, `false` otherwise.
|
|
1514
|
+
*/
|
|
1515
|
+
static verify(request) {
|
|
1516
|
+
return delegatedVerify(request);
|
|
1517
|
+
}
|
|
1350
1518
|
/**
|
|
1351
1519
|
* Rotate the current encryption key.
|
|
1352
1520
|
*
|
|
@@ -1463,6 +1631,6 @@ var VaultKeeper = class _VaultKeeper {
|
|
|
1463
1631
|
}
|
|
1464
1632
|
};
|
|
1465
1633
|
|
|
1466
|
-
export { AuthorizationDeniedError, BackendLockedError, BackendRegistry, BackendUnavailableError, CapabilityToken, DeviceNotPresentError, FilesystemError, IdentityMismatchError, KeyRevokedError, KeyRotatedError, PluginNotFoundError, RotationInProgressError, SecretNotFoundError, SetupError, TokenExpiredError, TokenRevokedError, UsageLimitExceededError, VaultError, VaultKeeper, isListableBackend };
|
|
1634
|
+
export { AuthorizationDeniedError, BackendLockedError, BackendRegistry, BackendUnavailableError, CapabilityToken, DeviceNotPresentError, FilesystemError, IdentityMismatchError, InvalidAlgorithmError, KeyRevokedError, KeyRotatedError, PluginNotFoundError, RotationInProgressError, SecretNotFoundError, SetupError, TokenExpiredError, TokenRevokedError, UsageLimitExceededError, VaultError, VaultKeeper, isListableBackend };
|
|
1467
1635
|
//# sourceMappingURL=index.js.map
|
|
1468
1636
|
//# sourceMappingURL=index.js.map
|