vaultkeeper 0.5.1 → 0.5.3
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 +59 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +19 -1
- package/dist/index.d.ts +19 -1
- package/dist/index.js +59 -22
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1617,7 +1617,13 @@ function validateConfig(config) {
|
|
|
1617
1617
|
if (typeof config.defaults.ttlMinutes !== "number" || config.defaults.ttlMinutes <= 0) {
|
|
1618
1618
|
throw new Error("Config defaults.ttlMinutes must be a positive number");
|
|
1619
1619
|
}
|
|
1620
|
-
|
|
1620
|
+
let tier = config.defaults.trustTier;
|
|
1621
|
+
if (typeof tier === "string") {
|
|
1622
|
+
const parsed = Number(tier);
|
|
1623
|
+
if (!Number.isNaN(parsed)) {
|
|
1624
|
+
tier = parsed;
|
|
1625
|
+
}
|
|
1626
|
+
}
|
|
1621
1627
|
if (tier !== 1 && tier !== 2 && tier !== 3) {
|
|
1622
1628
|
throw new Error("Config defaults.trustTier must be 1, 2, or 3");
|
|
1623
1629
|
}
|
|
@@ -2019,7 +2025,6 @@ var SecretAccessorTarget = class {
|
|
|
2019
2025
|
};
|
|
2020
2026
|
function createSecretAccessor(secretValue) {
|
|
2021
2027
|
let consumed = false;
|
|
2022
|
-
const revokeHolder = { fn: void 0 };
|
|
2023
2028
|
function readImpl(callback) {
|
|
2024
2029
|
if (consumed) {
|
|
2025
2030
|
throw new Error("SecretAccessor has already been consumed \u2014 call getSecret() again to obtain a new accessor");
|
|
@@ -2030,7 +2035,6 @@ function createSecretAccessor(secretValue) {
|
|
|
2030
2035
|
callback(buf);
|
|
2031
2036
|
} finally {
|
|
2032
2037
|
buf.fill(0);
|
|
2033
|
-
revokeHolder.fn?.();
|
|
2034
2038
|
}
|
|
2035
2039
|
}
|
|
2036
2040
|
function inspectImpl() {
|
|
@@ -2088,9 +2092,7 @@ function createSecretAccessor(secretValue) {
|
|
|
2088
2092
|
return ["read", INSPECT_CUSTOM];
|
|
2089
2093
|
}
|
|
2090
2094
|
};
|
|
2091
|
-
|
|
2092
|
-
revokeHolder.fn = revoke;
|
|
2093
|
-
return proxy;
|
|
2095
|
+
return new Proxy(target, handler);
|
|
2094
2096
|
}
|
|
2095
2097
|
|
|
2096
2098
|
// src/access/sign-util.ts
|
|
@@ -2284,7 +2286,8 @@ async function runDoctor(options) {
|
|
|
2284
2286
|
nextSteps: ["Unsupported platform. vaultkeeper supports macOS, Linux, and Windows."]
|
|
2285
2287
|
};
|
|
2286
2288
|
}
|
|
2287
|
-
const
|
|
2289
|
+
const enabledTypes = enabledBackendTypes(options?.backends);
|
|
2290
|
+
const entries = buildCheckList(platform, enabledTypes);
|
|
2288
2291
|
const resolved = await Promise.all(
|
|
2289
2292
|
entries.map(async ({ check, required }) => {
|
|
2290
2293
|
const result = await check();
|
|
@@ -2318,24 +2321,48 @@ async function runDoctor(options) {
|
|
|
2318
2321
|
const checks = resolved.map(({ result }) => result);
|
|
2319
2322
|
return { checks, ready, warnings, nextSteps };
|
|
2320
2323
|
}
|
|
2321
|
-
function
|
|
2324
|
+
function enabledBackendTypes(backends) {
|
|
2325
|
+
if (backends === void 0) return null;
|
|
2326
|
+
const types = /* @__PURE__ */ new Set();
|
|
2327
|
+
for (const b of backends) {
|
|
2328
|
+
if (b.enabled) types.add(b.type);
|
|
2329
|
+
}
|
|
2330
|
+
return types;
|
|
2331
|
+
}
|
|
2332
|
+
function buildCheckList(platform, enabledTypes) {
|
|
2322
2333
|
const entries = [{ check: checkOpenssl, required: true }];
|
|
2323
2334
|
if (platform === "darwin") {
|
|
2324
|
-
entries.push({
|
|
2335
|
+
entries.push({
|
|
2336
|
+
check: checkSecurity,
|
|
2337
|
+
required: enabledTypes === null || enabledTypes.has("keychain")
|
|
2338
|
+
});
|
|
2325
2339
|
entries.push({ check: checkBash, required: false });
|
|
2326
2340
|
} else if (platform === "win32") {
|
|
2327
|
-
entries.push({
|
|
2341
|
+
entries.push({
|
|
2342
|
+
check: checkPowershell,
|
|
2343
|
+
required: enabledTypes === null || enabledTypes.has("dpapi")
|
|
2344
|
+
});
|
|
2328
2345
|
} else {
|
|
2329
2346
|
entries.push({ check: checkBash, required: true });
|
|
2330
|
-
entries.push({
|
|
2347
|
+
entries.push({
|
|
2348
|
+
check: checkSecretTool,
|
|
2349
|
+
required: enabledTypes === null || enabledTypes.has("secret-tool")
|
|
2350
|
+
});
|
|
2331
2351
|
}
|
|
2332
|
-
entries.push({
|
|
2333
|
-
|
|
2352
|
+
entries.push({
|
|
2353
|
+
check: checkOp,
|
|
2354
|
+
required: enabledTypes?.has("1password") ?? false
|
|
2355
|
+
});
|
|
2356
|
+
entries.push({
|
|
2357
|
+
check: checkYkman,
|
|
2358
|
+
required: enabledTypes?.has("yubikey") ?? false
|
|
2359
|
+
});
|
|
2334
2360
|
return entries;
|
|
2335
2361
|
}
|
|
2336
2362
|
|
|
2337
2363
|
// src/vault.ts
|
|
2338
2364
|
var usageCounts = /* @__PURE__ */ new Map();
|
|
2365
|
+
var USAGE_MAP_MAX_SIZE = 1e4;
|
|
2339
2366
|
var VaultKeeper = class _VaultKeeper {
|
|
2340
2367
|
#config;
|
|
2341
2368
|
#keyManager;
|
|
@@ -2351,23 +2378,29 @@ var VaultKeeper = class _VaultKeeper {
|
|
|
2351
2378
|
* Runs doctor checks (unless skipped), loads config, and sets up the key manager.
|
|
2352
2379
|
*/
|
|
2353
2380
|
static async init(options) {
|
|
2381
|
+
const configDir = options?.configDir ?? getDefaultConfigDir();
|
|
2382
|
+
const config = options?.config ?? await loadConfig(configDir);
|
|
2354
2383
|
if (options?.skipDoctor !== true) {
|
|
2355
|
-
const doctorResult = await runDoctor();
|
|
2384
|
+
const doctorResult = await runDoctor({ backends: config.backends });
|
|
2356
2385
|
if (!doctorResult.ready) {
|
|
2357
2386
|
throw new VaultError(
|
|
2358
2387
|
`System not ready: ${doctorResult.nextSteps.join("; ")}`
|
|
2359
2388
|
);
|
|
2360
2389
|
}
|
|
2361
2390
|
}
|
|
2362
|
-
const configDir = options?.configDir ?? getDefaultConfigDir();
|
|
2363
|
-
const config = options?.config ?? await loadConfig(configDir);
|
|
2364
2391
|
const keyManager = new KeyManager();
|
|
2365
2392
|
await keyManager.init();
|
|
2366
2393
|
const vault = new _VaultKeeper(config, keyManager, configDir);
|
|
2367
2394
|
vault.#backend = vault.#resolveBackend();
|
|
2368
2395
|
return vault;
|
|
2369
2396
|
}
|
|
2370
|
-
/**
|
|
2397
|
+
/**
|
|
2398
|
+
* Run doctor checks without full initialization.
|
|
2399
|
+
*
|
|
2400
|
+
* Uses conservative platform defaults — all platform-native dependency
|
|
2401
|
+
* checks are treated as required regardless of any backend configuration.
|
|
2402
|
+
* For config-aware scoping, call `runDoctor({ backends })` directly.
|
|
2403
|
+
*/
|
|
2371
2404
|
static async doctor() {
|
|
2372
2405
|
return runDoctor();
|
|
2373
2406
|
}
|
|
@@ -2431,12 +2464,16 @@ var VaultKeeper = class _VaultKeeper {
|
|
|
2431
2464
|
const jti = claims.jti;
|
|
2432
2465
|
const currentCount = usageCounts.get(jti) ?? 0;
|
|
2433
2466
|
validateClaims(claims, currentCount);
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
usageCounts.delete(jti);
|
|
2437
|
-
blockToken(jti);
|
|
2438
|
-
} else {
|
|
2467
|
+
if (claims.use !== null) {
|
|
2468
|
+
const newCount = currentCount + 1;
|
|
2439
2469
|
usageCounts.set(jti, newCount);
|
|
2470
|
+
if (usageCounts.size > USAGE_MAP_MAX_SIZE) {
|
|
2471
|
+
const oldest = usageCounts.keys().next().value;
|
|
2472
|
+
if (oldest !== void 0) {
|
|
2473
|
+
usageCounts.delete(oldest);
|
|
2474
|
+
blockToken(oldest);
|
|
2475
|
+
}
|
|
2476
|
+
}
|
|
2440
2477
|
}
|
|
2441
2478
|
const token = createCapabilityToken(claims);
|
|
2442
2479
|
const response = { keyStatus };
|