@kitsy/cnos 1.10.0 → 1.11.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/build/index.cjs +331 -63
- package/dist/build/index.d.cts +1 -1
- package/dist/build/index.d.ts +1 -1
- package/dist/build/index.js +13 -15
- package/dist/{chunk-A5U7EZCJ.js → chunk-2DMCB3PK.js} +1 -1
- package/dist/{chunk-RTHKUGJV.js → chunk-5JGNRADB.js} +1 -1
- package/dist/{chunk-3EZGPQCE.js → chunk-DPC2BV3S.js} +1 -1
- package/dist/{chunk-FHXLOWAB.js → chunk-KJ57PF47.js} +1 -1
- package/dist/{chunk-ESBHCFC6.js → chunk-NU25VFA2.js} +1 -1
- package/dist/{chunk-UGLATJJD.js → chunk-RNTTPI5S.js} +1 -1
- package/dist/{chunk-UKNL2Y4N.js → chunk-T3E57MSQ.js} +1 -1
- package/dist/{chunk-CSA4L64V.js → chunk-V3USPV5U.js} +8 -8
- package/dist/{chunk-MQ4WG3K6.js → chunk-WPB4HB2K.js} +320 -49
- package/dist/{chunk-EIK7OUFP.js → chunk-X4PBPUKL.js} +157 -37
- package/dist/configure/index.cjs +329 -59
- package/dist/configure/index.d.cts +3 -3
- package/dist/configure/index.d.ts +3 -3
- package/dist/configure/index.js +8 -8
- package/dist/{core-Ud1o2MBn.d.cts → core-CGJObpyy.d.cts} +40 -2
- package/dist/{core-Ud1o2MBn.d.ts → core-CGJObpyy.d.ts} +40 -2
- package/dist/{envNaming-DxxqiGKN.d.cts → envNaming-DIaBgT6E.d.cts} +1 -1
- package/dist/{envNaming-CPwXl4I6.d.ts → envNaming-_WD9sLZI.d.ts} +1 -1
- package/dist/index.cjs +480 -91
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +10 -10
- package/dist/internal.cjs +89 -23
- package/dist/internal.d.cts +3 -3
- package/dist/internal.d.ts +3 -3
- package/dist/internal.js +2 -2
- package/dist/plugin/basic-schema.cjs +4 -1
- package/dist/plugin/basic-schema.d.cts +1 -1
- package/dist/plugin/basic-schema.d.ts +1 -1
- package/dist/plugin/basic-schema.js +2 -2
- package/dist/plugin/cli-args.cjs +4 -1
- package/dist/plugin/cli-args.d.cts +1 -1
- package/dist/plugin/cli-args.d.ts +1 -1
- package/dist/plugin/cli-args.js +2 -2
- package/dist/plugin/dotenv.cjs +6 -3
- package/dist/plugin/dotenv.d.cts +2 -2
- package/dist/plugin/dotenv.d.ts +2 -2
- package/dist/plugin/dotenv.js +2 -2
- package/dist/plugin/env-export.cjs +5 -2
- package/dist/plugin/env-export.d.cts +2 -2
- package/dist/plugin/env-export.d.ts +2 -2
- package/dist/plugin/env-export.js +2 -2
- package/dist/plugin/filesystem.cjs +13 -10
- package/dist/plugin/filesystem.d.cts +1 -1
- package/dist/plugin/filesystem.d.ts +1 -1
- package/dist/plugin/filesystem.js +2 -2
- package/dist/plugin/process-env.cjs +4 -1
- package/dist/plugin/process-env.d.cts +2 -2
- package/dist/plugin/process-env.d.ts +2 -2
- package/dist/plugin/process-env.js +2 -2
- package/dist/runtime/index.cjs +480 -91
- package/dist/runtime/index.d.cts +13 -6
- package/dist/runtime/index.d.ts +13 -6
- package/dist/runtime/index.js +10 -10
- package/dist/{toPublicEnv-fUZMRUOz.d.cts → toPublicEnv-C3A8aLjo.d.cts} +1 -1
- package/dist/{toPublicEnv-C9wPSpRo.d.ts → toPublicEnv-DLNNcEso.d.ts} +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1603,11 +1603,19 @@ function normalizeVaults(vaults) {
|
|
|
1603
1603
|
throw new CnosManifestError(`Vault "${name}" requires a provider`);
|
|
1604
1604
|
}
|
|
1605
1605
|
const normalizedAuth = normalizeVaultAuth(name, provider, definition.auth);
|
|
1606
|
-
const normalizedMapping =
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1606
|
+
const normalizedMapping = normalizeVaultMapping(definition.mapping);
|
|
1607
|
+
const fallback = (definition.fallback ?? []).map((entry, index) => {
|
|
1608
|
+
const fallbackProvider = entry.provider?.trim();
|
|
1609
|
+
if (!fallbackProvider) {
|
|
1610
|
+
throw new CnosManifestError(`Vault "${name}" fallback ${index + 1} requires a provider`);
|
|
1611
|
+
}
|
|
1612
|
+
const fallbackMapping = normalizeVaultMapping(entry.mapping);
|
|
1613
|
+
return {
|
|
1614
|
+
provider: fallbackProvider,
|
|
1615
|
+
auth: normalizeVaultAuth(name, fallbackProvider, entry.auth),
|
|
1616
|
+
...Object.keys(fallbackMapping).length > 0 ? { mapping: fallbackMapping } : {}
|
|
1617
|
+
};
|
|
1618
|
+
});
|
|
1611
1619
|
return [
|
|
1612
1620
|
name,
|
|
1613
1621
|
{
|
|
@@ -1615,12 +1623,20 @@ function normalizeVaults(vaults) {
|
|
|
1615
1623
|
auth: normalizedAuth,
|
|
1616
1624
|
...Object.keys(normalizedMapping).length > 0 ? {
|
|
1617
1625
|
mapping: normalizedMapping
|
|
1618
|
-
} : {}
|
|
1626
|
+
} : {},
|
|
1627
|
+
...fallback.length > 0 ? { fallback } : {}
|
|
1619
1628
|
}
|
|
1620
1629
|
];
|
|
1621
1630
|
})
|
|
1622
1631
|
);
|
|
1623
1632
|
}
|
|
1633
|
+
function normalizeVaultMapping(mapping) {
|
|
1634
|
+
return Object.fromEntries(
|
|
1635
|
+
Object.entries(mapping ?? {}).filter(
|
|
1636
|
+
(entry) => typeof entry[0] === "string" && typeof entry[1] === "string"
|
|
1637
|
+
).map(([envVar, logicalRef]) => [envVar.trim(), logicalRef.trim()]).filter(([envVar, logicalRef]) => envVar.length > 0 && logicalRef.length > 0)
|
|
1638
|
+
);
|
|
1639
|
+
}
|
|
1624
1640
|
function normalizeAuthSources(value) {
|
|
1625
1641
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
1626
1642
|
return void 0;
|
|
@@ -2568,7 +2584,7 @@ function isObject(value) {
|
|
|
2568
2584
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
2569
2585
|
}
|
|
2570
2586
|
function isSecretReference(value) {
|
|
2571
|
-
return isObject(value) && typeof value.provider === "string" && value.provider.trim().length > 0 && typeof value.ref === "string" && value.ref.trim().length > 0 && (value.vault === void 0 && true || typeof value.vault === "string" && value.vault.trim().length > 0) && Object.keys(value).every((key) => ["provider", "ref", "vault"].includes(key));
|
|
2587
|
+
return isObject(value) && (value.provider === void 0 || typeof value.provider === "string" && value.provider.trim().length > 0) && typeof value.ref === "string" && value.ref.trim().length > 0 && (value.vault === void 0 && true || typeof value.vault === "string" && value.vault.trim().length > 0) && Object.keys(value).every((key) => ["provider", "ref", "vault"].includes(key));
|
|
2572
2588
|
}
|
|
2573
2589
|
function resolveSecretStoreRoot(processEnv = process.env) {
|
|
2574
2590
|
return import_node_path11.default.resolve(expandHomePath(processEnv.CNOS_SECRET_HOME ?? "~/.cnos/secrets"));
|
|
@@ -2915,6 +2931,23 @@ var SecretCache = class {
|
|
|
2915
2931
|
get(vaultId, ref) {
|
|
2916
2932
|
return this.cache.get(`${vaultId}:${ref}`);
|
|
2917
2933
|
}
|
|
2934
|
+
delete(vaultId, ref) {
|
|
2935
|
+
this.cache.delete(`${vaultId}:${ref}`);
|
|
2936
|
+
}
|
|
2937
|
+
replace(vaultId, secrets) {
|
|
2938
|
+
this.clear(vaultId);
|
|
2939
|
+
this.load(vaultId, secrets);
|
|
2940
|
+
}
|
|
2941
|
+
entriesForVault(vaultId) {
|
|
2942
|
+
const entries = /* @__PURE__ */ new Map();
|
|
2943
|
+
for (const [key, value] of this.cache) {
|
|
2944
|
+
const prefix = `${vaultId}:`;
|
|
2945
|
+
if (key.startsWith(prefix)) {
|
|
2946
|
+
entries.set(key.slice(prefix.length), value);
|
|
2947
|
+
}
|
|
2948
|
+
}
|
|
2949
|
+
return entries;
|
|
2950
|
+
}
|
|
2918
2951
|
clear(vaultId) {
|
|
2919
2952
|
if (!vaultId) {
|
|
2920
2953
|
this.cache.clear();
|
|
@@ -3080,7 +3113,7 @@ var LocalSecretVaultProvider = class _LocalSecretVaultProvider {
|
|
|
3080
3113
|
};
|
|
3081
3114
|
|
|
3082
3115
|
// ../core/src/secrets/providers/registry.ts
|
|
3083
|
-
function createSecretVaultProvider(vaultId, definition, processEnv) {
|
|
3116
|
+
function createSecretVaultProvider(vaultId, definition, processEnv, factories = []) {
|
|
3084
3117
|
if (definition.provider === "local") {
|
|
3085
3118
|
return new LocalSecretVaultProvider(vaultId, definition, processEnv);
|
|
3086
3119
|
}
|
|
@@ -3090,9 +3123,30 @@ function createSecretVaultProvider(vaultId, definition, processEnv) {
|
|
|
3090
3123
|
if (definition.provider === "github-secrets") {
|
|
3091
3124
|
return new GithubSecretsVaultProvider(vaultId, definition, processEnv);
|
|
3092
3125
|
}
|
|
3126
|
+
const factory = factories.find((candidate) => candidate.provider === definition.provider);
|
|
3127
|
+
if (factory) {
|
|
3128
|
+
return factory.create(vaultId, definition, processEnv);
|
|
3129
|
+
}
|
|
3093
3130
|
throw new CnosManifestError(`Unsupported vault provider: ${definition.provider}`);
|
|
3094
3131
|
}
|
|
3095
3132
|
|
|
3133
|
+
// ../core/src/secrets/providerCompatibility.ts
|
|
3134
|
+
function assertSecretRefVaultProviderCompatible(manifest, ref, logicalKey = "secret ref") {
|
|
3135
|
+
if (!ref.vault || !ref.provider) {
|
|
3136
|
+
return;
|
|
3137
|
+
}
|
|
3138
|
+
const definition = manifest.vaults[ref.vault];
|
|
3139
|
+
if (!definition || definition.provider === ref.provider) {
|
|
3140
|
+
return;
|
|
3141
|
+
}
|
|
3142
|
+
throw new CnosManifestError(
|
|
3143
|
+
`Secret ref "${logicalKey}" declares provider "${ref.provider}" but vault "${ref.vault}" uses provider "${definition.provider}". Remove the ref provider or use a matching vault.`
|
|
3144
|
+
);
|
|
3145
|
+
}
|
|
3146
|
+
|
|
3147
|
+
// ../core/src/secrets/resolveAuth.ts
|
|
3148
|
+
var import_promises12 = require("fs/promises");
|
|
3149
|
+
|
|
3096
3150
|
// ../core/src/secrets/prompt.ts
|
|
3097
3151
|
var import_node_readline = __toESM(require("readline"), 1);
|
|
3098
3152
|
var import_node_stream = require("stream");
|
|
@@ -3133,6 +3187,23 @@ function toAuthError(vaultId, sources) {
|
|
|
3133
3187
|
`Cannot authenticate to vault "${vaultId}". Tried: ${sources.join(", ")}. Set ${getVaultPassphraseEnvVar(vaultId)} or run cnos vault auth ${vaultId}.`
|
|
3134
3188
|
);
|
|
3135
3189
|
}
|
|
3190
|
+
async function resolveTokenFromSource(source, processEnv) {
|
|
3191
|
+
if (source.startsWith("env:")) {
|
|
3192
|
+
return processEnv[source.slice(4)] || void 0;
|
|
3193
|
+
}
|
|
3194
|
+
if (source.startsWith("file:")) {
|
|
3195
|
+
try {
|
|
3196
|
+
const value = await (0, import_promises12.readFile)(expandHomePath(source.slice("file:".length)), "utf8");
|
|
3197
|
+
return value.trim() || void 0;
|
|
3198
|
+
} catch {
|
|
3199
|
+
return void 0;
|
|
3200
|
+
}
|
|
3201
|
+
}
|
|
3202
|
+
if (source.startsWith("keychain:")) {
|
|
3203
|
+
return readKeychain(source.slice("keychain:".length));
|
|
3204
|
+
}
|
|
3205
|
+
return void 0;
|
|
3206
|
+
}
|
|
3136
3207
|
async function resolveVaultAuth(vaultId, definition, processEnv = process.env) {
|
|
3137
3208
|
const sessionKey = await resolveVaultSessionKey(vaultId, processEnv);
|
|
3138
3209
|
if (sessionKey) {
|
|
@@ -3148,6 +3219,32 @@ async function resolveVaultAuth(vaultId, definition, processEnv = process.env) {
|
|
|
3148
3219
|
...definition.auth?.config ? { config: definition.auth.config } : {}
|
|
3149
3220
|
};
|
|
3150
3221
|
}
|
|
3222
|
+
if (definition.auth?.method === "iam") {
|
|
3223
|
+
return {
|
|
3224
|
+
method: "iam",
|
|
3225
|
+
...definition.auth?.config ? { config: definition.auth.config } : {}
|
|
3226
|
+
};
|
|
3227
|
+
}
|
|
3228
|
+
if (definition.auth?.method === "environment") {
|
|
3229
|
+
return {
|
|
3230
|
+
method: "environment",
|
|
3231
|
+
...definition.auth?.config ? { config: definition.auth.config } : {}
|
|
3232
|
+
};
|
|
3233
|
+
}
|
|
3234
|
+
const tokenSources = definition.auth?.token?.from ?? [];
|
|
3235
|
+
for (const source of tokenSources) {
|
|
3236
|
+
const token = await resolveTokenFromSource(source, processEnv);
|
|
3237
|
+
if (token) {
|
|
3238
|
+
return {
|
|
3239
|
+
token,
|
|
3240
|
+
method: "token",
|
|
3241
|
+
...definition.auth?.config ? { config: definition.auth.config } : {}
|
|
3242
|
+
};
|
|
3243
|
+
}
|
|
3244
|
+
}
|
|
3245
|
+
if (definition.auth?.method === "token") {
|
|
3246
|
+
throw toAuthError(vaultId, [getVaultSessionKeyEnvVar(vaultId), ...tokenSources]);
|
|
3247
|
+
}
|
|
3151
3248
|
const sources = definition.auth?.passphrase?.from ?? [getVaultPassphraseEnvVar(vaultId)];
|
|
3152
3249
|
for (const source of sources) {
|
|
3153
3250
|
if (source.startsWith("env:")) {
|
|
@@ -3199,22 +3296,76 @@ function collectSecretDescriptors(graph) {
|
|
|
3199
3296
|
ref: entry.value
|
|
3200
3297
|
}));
|
|
3201
3298
|
}
|
|
3202
|
-
|
|
3299
|
+
function secretGroupKey(manifest, descriptor) {
|
|
3300
|
+
assertSecretRefVaultProviderCompatible(manifest, descriptor.ref, descriptor.logicalKey);
|
|
3301
|
+
const vaultId = descriptor.ref.vault ?? "default";
|
|
3302
|
+
const provider = descriptor.ref.provider ?? manifest.vaults[vaultId]?.provider ?? "local";
|
|
3303
|
+
return `${vaultId}\0${provider}`;
|
|
3304
|
+
}
|
|
3305
|
+
function vaultDefinitionForRef(manifest, ref) {
|
|
3306
|
+
assertSecretRefVaultProviderCompatible(manifest, ref);
|
|
3307
|
+
const vaultId = ref.vault ?? "default";
|
|
3308
|
+
const base = manifest.vaults[vaultId] ?? { provider: "local", auth: { passphrase: { from: [] } } };
|
|
3309
|
+
if (!ref.provider || ref.provider === base.provider) {
|
|
3310
|
+
return base;
|
|
3311
|
+
}
|
|
3312
|
+
return {
|
|
3313
|
+
...base,
|
|
3314
|
+
provider: ref.provider
|
|
3315
|
+
};
|
|
3316
|
+
}
|
|
3317
|
+
async function resolveFromDefinition(vaultId, definition, refs, processEnv, factories) {
|
|
3318
|
+
const runtimeDefinition = {
|
|
3319
|
+
provider: definition.provider,
|
|
3320
|
+
...definition.auth ? { auth: definition.auth } : {},
|
|
3321
|
+
...definition.mapping ? { mapping: definition.mapping } : {}
|
|
3322
|
+
};
|
|
3323
|
+
const provider = createSecretVaultProvider(vaultId, runtimeDefinition, processEnv, factories);
|
|
3324
|
+
const auth = await resolveVaultAuth(vaultId, runtimeDefinition, processEnv);
|
|
3325
|
+
await provider.authenticate(auth);
|
|
3326
|
+
return provider.batchGet(refs.map((entry) => entry.ref.ref));
|
|
3327
|
+
}
|
|
3328
|
+
async function batchResolveSecrets(graph, manifest, processEnv = process.env, factories = []) {
|
|
3203
3329
|
const cache = new SecretCache();
|
|
3204
3330
|
const descriptors = collectSecretDescriptors(graph);
|
|
3205
3331
|
const grouped = descriptors.reduce((accumulator, descriptor) => {
|
|
3206
|
-
const
|
|
3207
|
-
const bucket = accumulator.get(
|
|
3332
|
+
const key = secretGroupKey(manifest, descriptor);
|
|
3333
|
+
const bucket = accumulator.get(key) ?? [];
|
|
3208
3334
|
bucket.push(descriptor);
|
|
3209
|
-
accumulator.set(
|
|
3335
|
+
accumulator.set(key, bucket);
|
|
3210
3336
|
return accumulator;
|
|
3211
3337
|
}, /* @__PURE__ */ new Map());
|
|
3212
|
-
for (const
|
|
3213
|
-
const
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
const
|
|
3338
|
+
for (const refs of grouped.values()) {
|
|
3339
|
+
const first = refs[0];
|
|
3340
|
+
if (!first) {
|
|
3341
|
+
continue;
|
|
3342
|
+
}
|
|
3343
|
+
const vaultId = first.ref.vault ?? "default";
|
|
3344
|
+
const definition = vaultDefinitionForRef(manifest, first.ref);
|
|
3345
|
+
const definitions = [definition, ...definition.fallback ?? []];
|
|
3346
|
+
const resolved = /* @__PURE__ */ new Map();
|
|
3347
|
+
let remaining = refs;
|
|
3348
|
+
let lastError;
|
|
3349
|
+
for (const candidate of definitions) {
|
|
3350
|
+
try {
|
|
3351
|
+
const candidateValues = await resolveFromDefinition(vaultId, candidate, remaining, processEnv, factories);
|
|
3352
|
+
for (const descriptor of remaining) {
|
|
3353
|
+
const value = candidateValues.get(descriptor.ref.ref);
|
|
3354
|
+
if (value !== void 0) {
|
|
3355
|
+
resolved.set(descriptor.ref.ref, value);
|
|
3356
|
+
}
|
|
3357
|
+
}
|
|
3358
|
+
remaining = remaining.filter((descriptor) => !resolved.has(descriptor.ref.ref));
|
|
3359
|
+
if (remaining.length === 0) {
|
|
3360
|
+
break;
|
|
3361
|
+
}
|
|
3362
|
+
} catch (error) {
|
|
3363
|
+
lastError = error;
|
|
3364
|
+
}
|
|
3365
|
+
}
|
|
3366
|
+
if (resolved.size === 0 && lastError) {
|
|
3367
|
+
throw lastError;
|
|
3368
|
+
}
|
|
3218
3369
|
cache.load(vaultId, resolved);
|
|
3219
3370
|
await appendAuditEvent(
|
|
3220
3371
|
{
|
|
@@ -3235,7 +3386,11 @@ function resolveSecretEntryValue(key, value, cache) {
|
|
|
3235
3386
|
return value;
|
|
3236
3387
|
}
|
|
3237
3388
|
const vaultId = value.vault ?? "default";
|
|
3238
|
-
|
|
3389
|
+
const resolved = cache.get(vaultId, value.ref);
|
|
3390
|
+
if (resolved !== void 0 || cache.isVaultAuthenticated(vaultId)) {
|
|
3391
|
+
return resolved;
|
|
3392
|
+
}
|
|
3393
|
+
return value;
|
|
3239
3394
|
}
|
|
3240
3395
|
|
|
3241
3396
|
// ../core/src/runtime/projection.ts
|
|
@@ -3338,19 +3493,117 @@ function configHash(values) {
|
|
|
3338
3493
|
function shouldProjectResolvedValue(sourceId) {
|
|
3339
3494
|
return sourceId !== "process-env";
|
|
3340
3495
|
}
|
|
3496
|
+
var SAFE_PROJECTED_CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
3497
|
+
"address",
|
|
3498
|
+
"audience",
|
|
3499
|
+
"clientid",
|
|
3500
|
+
"endpoint",
|
|
3501
|
+
"mount",
|
|
3502
|
+
"namespace",
|
|
3503
|
+
"path",
|
|
3504
|
+
"projectid",
|
|
3505
|
+
"region",
|
|
3506
|
+
"scope",
|
|
3507
|
+
"scopes",
|
|
3508
|
+
"serviceaccountemail",
|
|
3509
|
+
"tenant",
|
|
3510
|
+
"tenantid",
|
|
3511
|
+
"url",
|
|
3512
|
+
"version",
|
|
3513
|
+
"vaulturl"
|
|
3514
|
+
]);
|
|
3515
|
+
function isSafeProjectedConfigKey(key) {
|
|
3516
|
+
return SAFE_PROJECTED_CONFIG_KEYS.has(key.replace(/[^A-Za-z0-9]/g, "").toLowerCase());
|
|
3517
|
+
}
|
|
3518
|
+
function sanitizeProjectedConfigValue(value) {
|
|
3519
|
+
if (Array.isArray(value)) {
|
|
3520
|
+
return value.map((item) => sanitizeProjectedConfigValue(item));
|
|
3521
|
+
}
|
|
3522
|
+
if (!value || typeof value !== "object") {
|
|
3523
|
+
return value;
|
|
3524
|
+
}
|
|
3525
|
+
return stableSortObject(
|
|
3526
|
+
Object.fromEntries(
|
|
3527
|
+
Object.entries(value).map(([key, item]) => [key, sanitizeProjectedConfigValue(item)]).filter(([key, item]) => {
|
|
3528
|
+
if (item && typeof item === "object" && !Array.isArray(item)) {
|
|
3529
|
+
return Object.keys(item).length > 0;
|
|
3530
|
+
}
|
|
3531
|
+
return isSafeProjectedConfigKey(key);
|
|
3532
|
+
})
|
|
3533
|
+
)
|
|
3534
|
+
);
|
|
3535
|
+
}
|
|
3536
|
+
function sanitizeProjectedConfig(config) {
|
|
3537
|
+
const sanitized = sanitizeProjectedConfigValue(config);
|
|
3538
|
+
if (!sanitized || typeof sanitized !== "object" || Array.isArray(sanitized)) {
|
|
3539
|
+
return void 0;
|
|
3540
|
+
}
|
|
3541
|
+
return Object.keys(sanitized).length > 0 ? sanitized : void 0;
|
|
3542
|
+
}
|
|
3543
|
+
function projectVaultAuth(definition) {
|
|
3544
|
+
const auth = definition.auth;
|
|
3545
|
+
if (!auth) {
|
|
3546
|
+
return void 0;
|
|
3547
|
+
}
|
|
3548
|
+
const config = auth.config ? sanitizeProjectedConfig(auth.config) : void 0;
|
|
3549
|
+
const projected = {
|
|
3550
|
+
...auth.method ? { method: auth.method } : {},
|
|
3551
|
+
...auth.passphrase?.from ? {
|
|
3552
|
+
passphrase: {
|
|
3553
|
+
from: [...auth.passphrase.from]
|
|
3554
|
+
}
|
|
3555
|
+
} : {},
|
|
3556
|
+
...auth.token?.from ? {
|
|
3557
|
+
token: {
|
|
3558
|
+
from: [...auth.token.from]
|
|
3559
|
+
}
|
|
3560
|
+
} : {},
|
|
3561
|
+
...config ? { config } : {}
|
|
3562
|
+
};
|
|
3563
|
+
return Object.keys(projected).length > 0 ? projected : void 0;
|
|
3564
|
+
}
|
|
3565
|
+
function projectVaultDefinition(definition) {
|
|
3566
|
+
const auth = projectVaultAuth(definition);
|
|
3567
|
+
const mapping = definition.mapping ? stableSortObject(definition.mapping) : void 0;
|
|
3568
|
+
const fallback = definition.fallback?.map((entry) => projectVaultDefinition({
|
|
3569
|
+
provider: entry.provider,
|
|
3570
|
+
...entry.auth ? { auth: entry.auth } : {},
|
|
3571
|
+
...entry.mapping ? { mapping: entry.mapping } : {}
|
|
3572
|
+
}));
|
|
3573
|
+
return {
|
|
3574
|
+
provider: definition.provider,
|
|
3575
|
+
...auth ? { auth } : {},
|
|
3576
|
+
...mapping && Object.keys(mapping).length > 0 ? { mapping } : {},
|
|
3577
|
+
...fallback && fallback.length > 0 ? { fallback } : {}
|
|
3578
|
+
};
|
|
3579
|
+
}
|
|
3580
|
+
function projectReferencedVaults(manifest, vaultIds) {
|
|
3581
|
+
const projected = {};
|
|
3582
|
+
for (const vaultId of Array.from(vaultIds).sort((left, right) => left.localeCompare(right))) {
|
|
3583
|
+
const definition = manifest.vaults[vaultId];
|
|
3584
|
+
if (definition) {
|
|
3585
|
+
projected[vaultId] = projectVaultDefinition(definition);
|
|
3586
|
+
}
|
|
3587
|
+
}
|
|
3588
|
+
return Object.keys(projected).length > 0 ? projected : void 0;
|
|
3589
|
+
}
|
|
3341
3590
|
function toServerProjection(graph, manifest, cnosVersion = "0.0.0-dev", helpers = {}) {
|
|
3342
3591
|
const values = {};
|
|
3343
3592
|
const derived = {};
|
|
3344
3593
|
const secretRefs = {};
|
|
3594
|
+
const referencedVaultIds = /* @__PURE__ */ new Set();
|
|
3345
3595
|
const namespaces = /* @__PURE__ */ new Set();
|
|
3346
3596
|
const runtimeNamespaces = /* @__PURE__ */ new Set();
|
|
3347
3597
|
const publicKeys = Array.from(graph.entries.values()).filter((entry) => entry.namespace === "public").map((entry) => entry.key.slice("public.".length)).sort((left, right) => left.localeCompare(right));
|
|
3348
3598
|
for (const [key, entry] of graph.entries) {
|
|
3349
3599
|
if (entry.namespace === "secret" && isSecretReference(entry.value)) {
|
|
3600
|
+
assertSecretRefVaultProviderCompatible(manifest, entry.value, key);
|
|
3350
3601
|
const vaultId = entry.value.vault ?? "default";
|
|
3602
|
+
const provider = entry.value.provider ?? manifest.vaults[vaultId]?.provider ?? "local";
|
|
3351
3603
|
const envVar = resolveProjectedEnvVar(manifest, vaultId, entry.value.ref);
|
|
3604
|
+
referencedVaultIds.add(vaultId);
|
|
3352
3605
|
secretRefs[key.slice("secret.".length)] = {
|
|
3353
|
-
provider
|
|
3606
|
+
provider,
|
|
3354
3607
|
vault: vaultId,
|
|
3355
3608
|
ref: entry.value.ref,
|
|
3356
3609
|
...envVar ? {
|
|
@@ -3396,6 +3649,7 @@ function toServerProjection(graph, manifest, cnosVersion = "0.0.0-dev", helpers
|
|
|
3396
3649
|
namespaces.add(entry.namespace);
|
|
3397
3650
|
}
|
|
3398
3651
|
}
|
|
3652
|
+
const vaults = projectReferencedVaults(manifest, referencedVaultIds);
|
|
3399
3653
|
return {
|
|
3400
3654
|
version: 1,
|
|
3401
3655
|
workspace: graph.workspace.workspaceId,
|
|
@@ -3405,6 +3659,7 @@ function toServerProjection(graph, manifest, cnosVersion = "0.0.0-dev", helpers
|
|
|
3405
3659
|
values: stableSortObject(values),
|
|
3406
3660
|
derived: stableSortObject(derived),
|
|
3407
3661
|
secretRefs: stableSortObject(secretRefs),
|
|
3662
|
+
...vaults ? { vaults } : {},
|
|
3408
3663
|
publicKeys,
|
|
3409
3664
|
runtimeNamespaces: Array.from(runtimeNamespaces).sort((left, right) => left.localeCompare(right)),
|
|
3410
3665
|
meta: {
|
|
@@ -3519,9 +3774,10 @@ function toPublicEnv(graph, manifest, options = {}, helpers = {}) {
|
|
|
3519
3774
|
}
|
|
3520
3775
|
|
|
3521
3776
|
// ../core/src/orchestrator/runtime.ts
|
|
3522
|
-
function createRuntime(manifest, graph, plugins = [], secretCache, processEnv = process.env, cnosVersion = "0.0.0-dev") {
|
|
3777
|
+
function createRuntime(manifest, graph, plugins = [], secretCache, processEnv = process.env, cnosVersion = "0.0.0-dev", secretVaultProviders = []) {
|
|
3523
3778
|
const runtimeProviders = createDefaultRuntimeProviders(manifest, processEnv);
|
|
3524
3779
|
const derivedSupport = createDerivedRuntimeSupport(graph, manifest, runtimeProviders);
|
|
3780
|
+
let activeSecretCache = secretCache;
|
|
3525
3781
|
function resolveProjectedSourceKey(key) {
|
|
3526
3782
|
if (!key.startsWith("public.")) {
|
|
3527
3783
|
return key;
|
|
@@ -3538,30 +3794,38 @@ function createRuntime(manifest, graph, plugins = [], secretCache, processEnv =
|
|
|
3538
3794
|
if (!entry || entry.namespace !== "secret" || !isSecretReference(entry.value)) {
|
|
3539
3795
|
return;
|
|
3540
3796
|
}
|
|
3541
|
-
if (!
|
|
3797
|
+
if (!activeSecretCache) {
|
|
3542
3798
|
return;
|
|
3543
3799
|
}
|
|
3544
3800
|
const vaultId = entry.value.vault ?? "default";
|
|
3545
|
-
const
|
|
3546
|
-
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
|
|
3801
|
+
const refreshed = await batchResolveSecrets(
|
|
3802
|
+
{
|
|
3803
|
+
...graph,
|
|
3804
|
+
entries: /* @__PURE__ */ new Map([[key, entry]])
|
|
3805
|
+
},
|
|
3806
|
+
manifest,
|
|
3807
|
+
processEnv,
|
|
3808
|
+
secretVaultProviders
|
|
3809
|
+
);
|
|
3810
|
+
const resolved = refreshed.get(vaultId, entry.value.ref);
|
|
3811
|
+
const existing = activeSecretCache.entriesForVault(vaultId);
|
|
3812
|
+
existing.delete(entry.value.ref);
|
|
3813
|
+
if (resolved !== void 0) {
|
|
3814
|
+
existing.set(entry.value.ref, resolved);
|
|
3555
3815
|
}
|
|
3816
|
+
activeSecretCache.replace(vaultId, existing);
|
|
3556
3817
|
}
|
|
3557
3818
|
async function refreshAllSecrets() {
|
|
3558
|
-
if (!
|
|
3819
|
+
if (!activeSecretCache) {
|
|
3559
3820
|
return;
|
|
3560
3821
|
}
|
|
3561
|
-
const
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
|
|
3822
|
+
const refreshed = await batchResolveSecrets(
|
|
3823
|
+
graph,
|
|
3824
|
+
manifest,
|
|
3825
|
+
processEnv,
|
|
3826
|
+
secretVaultProviders
|
|
3827
|
+
);
|
|
3828
|
+
activeSecretCache = refreshed;
|
|
3565
3829
|
}
|
|
3566
3830
|
function readLogicalKey2(key) {
|
|
3567
3831
|
const resolved = derivedSupport.read(key, (ref) => {
|
|
@@ -3569,10 +3833,10 @@ function createRuntime(manifest, graph, plugins = [], secretCache, processEnv =
|
|
|
3569
3833
|
if (!entry2) {
|
|
3570
3834
|
return void 0;
|
|
3571
3835
|
}
|
|
3572
|
-
if (!
|
|
3836
|
+
if (!activeSecretCache) {
|
|
3573
3837
|
return entry2.value;
|
|
3574
3838
|
}
|
|
3575
|
-
return resolveSecretEntryValue(ref, entry2.value,
|
|
3839
|
+
return resolveSecretEntryValue(ref, entry2.value, activeSecretCache);
|
|
3576
3840
|
});
|
|
3577
3841
|
if (resolved !== void 0 || graph.entries.has(key) || manifest.runtimeNamespaces[key.split(".")[0] ?? ""]) {
|
|
3578
3842
|
return resolved;
|
|
@@ -3581,10 +3845,10 @@ function createRuntime(manifest, graph, plugins = [], secretCache, processEnv =
|
|
|
3581
3845
|
if (!entry) {
|
|
3582
3846
|
return void 0;
|
|
3583
3847
|
}
|
|
3584
|
-
if (!
|
|
3848
|
+
if (!activeSecretCache) {
|
|
3585
3849
|
return entry.value;
|
|
3586
3850
|
}
|
|
3587
|
-
return resolveSecretEntryValue(key, entry.value,
|
|
3851
|
+
return resolveSecretEntryValue(key, entry.value, activeSecretCache);
|
|
3588
3852
|
}
|
|
3589
3853
|
return {
|
|
3590
3854
|
manifest,
|
|
@@ -3621,10 +3885,10 @@ function createRuntime(manifest, graph, plugins = [], secretCache, processEnv =
|
|
|
3621
3885
|
if (!entry) {
|
|
3622
3886
|
return void 0;
|
|
3623
3887
|
}
|
|
3624
|
-
if (!
|
|
3888
|
+
if (!activeSecretCache) {
|
|
3625
3889
|
return entry.value;
|
|
3626
3890
|
}
|
|
3627
|
-
return resolveSecretEntryValue(candidate, entry.value,
|
|
3891
|
+
return resolveSecretEntryValue(candidate, entry.value, activeSecretCache);
|
|
3628
3892
|
})
|
|
3629
3893
|
});
|
|
3630
3894
|
},
|
|
@@ -3815,7 +4079,12 @@ async function createCnos(options = {}) {
|
|
|
3815
4079
|
});
|
|
3816
4080
|
const schemaApplied = applySchemaRules(graph, loadedManifest.manifest.schema);
|
|
3817
4081
|
const promotedGraph = promoteToPublic(schemaApplied.graph, loadedManifest.manifest);
|
|
3818
|
-
const secretCache = options.secretResolution === "lazy" ? new SecretCache() : await batchResolveSecrets(
|
|
4082
|
+
const secretCache = options.secretResolution === "lazy" ? new SecretCache() : await batchResolveSecrets(
|
|
4083
|
+
promotedGraph,
|
|
4084
|
+
loadedManifest.manifest,
|
|
4085
|
+
options.processEnv,
|
|
4086
|
+
options.secretVaultProviders
|
|
4087
|
+
);
|
|
3819
4088
|
return createRuntime(
|
|
3820
4089
|
loadedManifest.manifest,
|
|
3821
4090
|
appendMetaEntries({
|
|
@@ -3825,12 +4094,13 @@ async function createCnos(options = {}) {
|
|
|
3825
4094
|
plugins,
|
|
3826
4095
|
secretCache,
|
|
3827
4096
|
options.processEnv,
|
|
3828
|
-
options.cnosVersion
|
|
4097
|
+
options.cnosVersion,
|
|
4098
|
+
options.secretVaultProviders
|
|
3829
4099
|
);
|
|
3830
4100
|
}
|
|
3831
4101
|
|
|
3832
4102
|
// ../core/src/runtime/dump.ts
|
|
3833
|
-
var
|
|
4103
|
+
var import_promises13 = require("fs/promises");
|
|
3834
4104
|
var import_node_path13 = __toESM(require("path"), 1);
|
|
3835
4105
|
|
|
3836
4106
|
// ../core/src/utils/envNaming.ts
|
|
@@ -3868,7 +4138,7 @@ function envVarToLogicalKey(envVar, config = {}) {
|
|
|
3868
4138
|
// package.json
|
|
3869
4139
|
var package_default = {
|
|
3870
4140
|
name: "@kitsy/cnos",
|
|
3871
|
-
version: "1.
|
|
4141
|
+
version: "1.11.1",
|
|
3872
4142
|
description: "Batteries-included CNOS runtime package wired with the official plugins.",
|
|
3873
4143
|
type: "module",
|
|
3874
4144
|
main: "./dist/index.cjs",
|
|
@@ -4067,7 +4337,7 @@ function createCliArgsPlugin() {
|
|
|
4067
4337
|
}
|
|
4068
4338
|
|
|
4069
4339
|
// ../../plugins/dotenv/src/index.ts
|
|
4070
|
-
var
|
|
4340
|
+
var import_promises14 = require("fs/promises");
|
|
4071
4341
|
var import_node_path14 = __toESM(require("path"), 1);
|
|
4072
4342
|
var DOTENV_PLUGIN_ID = "@kitsy/cnos/plugins/dotenv";
|
|
4073
4343
|
function parseDoubleQuoted(value) {
|
|
@@ -4154,7 +4424,7 @@ function dotenvEntriesFromObject(values, mapping = {}, originFile, workspaceId =
|
|
|
4154
4424
|
}
|
|
4155
4425
|
async function readIfPresent(filePath) {
|
|
4156
4426
|
try {
|
|
4157
|
-
return await (0,
|
|
4427
|
+
return await (0, import_promises14.readFile)(filePath, "utf8");
|
|
4158
4428
|
} catch {
|
|
4159
4429
|
return void 0;
|
|
4160
4430
|
}
|
|
@@ -4220,16 +4490,16 @@ function createPublicEnvExportPlugin() {
|
|
|
4220
4490
|
}
|
|
4221
4491
|
|
|
4222
4492
|
// ../../plugins/filesystem/src/filesystemSecretsReader.ts
|
|
4223
|
-
var
|
|
4493
|
+
var import_promises16 = require("fs/promises");
|
|
4224
4494
|
|
|
4225
4495
|
// ../../plugins/filesystem/src/helpers.ts
|
|
4226
|
-
var
|
|
4496
|
+
var import_promises15 = require("fs/promises");
|
|
4227
4497
|
var import_node_path15 = __toESM(require("path"), 1);
|
|
4228
4498
|
var YAML_EXTENSIONS = /* @__PURE__ */ new Set([".yml", ".yaml"]);
|
|
4229
4499
|
var FILESYSTEM_PLUGIN_ID = "@kitsy/cnos/plugins/filesystem";
|
|
4230
4500
|
async function existsDirectory(targetPath) {
|
|
4231
4501
|
try {
|
|
4232
|
-
const stat2 = await (0,
|
|
4502
|
+
const stat2 = await (0, import_promises15.readdir)(targetPath);
|
|
4233
4503
|
void stat2;
|
|
4234
4504
|
return true;
|
|
4235
4505
|
} catch {
|
|
@@ -4237,7 +4507,7 @@ async function existsDirectory(targetPath) {
|
|
|
4237
4507
|
}
|
|
4238
4508
|
}
|
|
4239
4509
|
async function collectYamlFiles(root) {
|
|
4240
|
-
const entries = await (0,
|
|
4510
|
+
const entries = await (0, import_promises15.readdir)(root, { withFileTypes: true });
|
|
4241
4511
|
const results = [];
|
|
4242
4512
|
for (const entry of entries.sort((left, right) => left.name.localeCompare(right.name))) {
|
|
4243
4513
|
const absolutePath = import_node_path15.default.join(root, entry.name);
|
|
@@ -4339,7 +4609,7 @@ function createFilesystemSecretsPlugin() {
|
|
|
4339
4609
|
);
|
|
4340
4610
|
const entries = [];
|
|
4341
4611
|
for (const file of files) {
|
|
4342
|
-
const document = await (0,
|
|
4612
|
+
const document = await (0, import_promises16.readFile)(file.absolutePath, "utf8");
|
|
4343
4613
|
const fileEntries = filesystemSecretsReader(file.relativePath, document, file.workspaceId);
|
|
4344
4614
|
for (const entry of fileEntries) {
|
|
4345
4615
|
const metadata = toSecretReferenceMetadata(entry.value);
|
|
@@ -4355,7 +4625,7 @@ function createFilesystemSecretsPlugin() {
|
|
|
4355
4625
|
}
|
|
4356
4626
|
|
|
4357
4627
|
// ../../plugins/filesystem/src/filesystemValuesReader.ts
|
|
4358
|
-
var
|
|
4628
|
+
var import_promises17 = require("fs/promises");
|
|
4359
4629
|
function filesystemValuesReader(filePath, document, workspaceId = "default") {
|
|
4360
4630
|
return yamlObjectToEntries(document, filePath, "value", "filesystem-values", workspaceId);
|
|
4361
4631
|
}
|
|
@@ -4376,7 +4646,7 @@ function createFilesystemValuesPlugin() {
|
|
|
4376
4646
|
).map(([namespace]) => namespace);
|
|
4377
4647
|
const entries = [];
|
|
4378
4648
|
for (const file of files) {
|
|
4379
|
-
const document = await (0,
|
|
4649
|
+
const document = await (0, import_promises17.readFile)(file.absolutePath, "utf8");
|
|
4380
4650
|
entries.push(...filesystemValuesReader(file.relativePath, document, file.workspaceId));
|
|
4381
4651
|
}
|
|
4382
4652
|
for (const namespace of customNamespaces) {
|
|
@@ -4391,7 +4661,7 @@ function createFilesystemValuesPlugin() {
|
|
|
4391
4661
|
layers
|
|
4392
4662
|
);
|
|
4393
4663
|
for (const file of namespaceFiles) {
|
|
4394
|
-
const document = await (0,
|
|
4664
|
+
const document = await (0, import_promises17.readFile)(file.absolutePath, "utf8");
|
|
4395
4665
|
entries.push(...yamlObjectToEntries(document, file.relativePath, namespace, "filesystem-values", file.workspaceId));
|
|
4396
4666
|
}
|
|
4397
4667
|
}
|
|
@@ -4647,6 +4917,19 @@ function graphRequiresSecretHydration(graph) {
|
|
|
4647
4917
|
|
|
4648
4918
|
// src/runtime/index.ts
|
|
4649
4919
|
var NOT_READY_MESSAGE = "CNOS not initialized. Call await cnos.ready() or use cnos run.";
|
|
4920
|
+
var bootstrappedProjection;
|
|
4921
|
+
var singletonRuntimeProviders = /* @__PURE__ */ new Map();
|
|
4922
|
+
var singletonSecretVaultProviders = /* @__PURE__ */ new Map();
|
|
4923
|
+
function registerSingletonSecretVaultProvider(factory) {
|
|
4924
|
+
singletonSecretVaultProviders.set(factory.provider, factory);
|
|
4925
|
+
}
|
|
4926
|
+
function mergeSecretVaultProviders(factories = []) {
|
|
4927
|
+
const merged = new Map(singletonSecretVaultProviders);
|
|
4928
|
+
for (const factory of factories) {
|
|
4929
|
+
merged.set(factory.provider, factory);
|
|
4930
|
+
}
|
|
4931
|
+
return Array.from(merged.values());
|
|
4932
|
+
}
|
|
4650
4933
|
function getRuntimeOrThrow() {
|
|
4651
4934
|
const runtime = getSingletonRuntime();
|
|
4652
4935
|
if (!runtime) {
|
|
@@ -4710,6 +4993,7 @@ function attachBootstrappedGraph(graph) {
|
|
|
4710
4993
|
if (getSingletonRuntime()) {
|
|
4711
4994
|
return;
|
|
4712
4995
|
}
|
|
4996
|
+
bootstrappedProjection = void 0;
|
|
4713
4997
|
const bootstrappedManifest = {
|
|
4714
4998
|
version: 1,
|
|
4715
4999
|
project: {
|
|
@@ -4780,6 +5064,9 @@ function attachBootstrappedGraph(graph) {
|
|
|
4780
5064
|
schema: {}
|
|
4781
5065
|
};
|
|
4782
5066
|
const runtimeProviders = createDefaultRuntimeProviders(bootstrappedManifest, process.env);
|
|
5067
|
+
for (const [namespace, provider] of singletonRuntimeProviders) {
|
|
5068
|
+
registerRuntimeProvider(bootstrappedManifest, runtimeProviders, namespace, provider);
|
|
5069
|
+
}
|
|
4783
5070
|
const derivedSupport = createDerivedRuntimeSupport(graph, bootstrappedManifest, runtimeProviders);
|
|
4784
5071
|
const resolveProjectedSourceKey = (key) => {
|
|
4785
5072
|
if (!key.startsWith("public.")) {
|
|
@@ -4848,6 +5135,7 @@ function attachBootstrappedGraph(graph) {
|
|
|
4848
5135
|
},
|
|
4849
5136
|
registerRuntimeProvider(namespace, provider) {
|
|
4850
5137
|
registerRuntimeProvider(bootstrappedManifest, runtimeProviders, namespace, provider);
|
|
5138
|
+
singletonRuntimeProviders.set(namespace, provider);
|
|
4851
5139
|
},
|
|
4852
5140
|
async refreshSecrets() {
|
|
4853
5141
|
return;
|
|
@@ -4859,7 +5147,7 @@ function attachBootstrappedGraph(graph) {
|
|
|
4859
5147
|
setSingletonRuntime(runtime);
|
|
4860
5148
|
setBootstrappedSecretHydrationRequired(graphRequiresSecretHydration(graph));
|
|
4861
5149
|
}
|
|
4862
|
-
function toBootstrappedManifest(graph, runtimeNamespaces = []) {
|
|
5150
|
+
function toBootstrappedManifest(graph, runtimeNamespaces = [], vaults = {}) {
|
|
4863
5151
|
return {
|
|
4864
5152
|
version: 1,
|
|
4865
5153
|
project: {
|
|
@@ -4920,7 +5208,7 @@ function toBootstrappedManifest(graph, runtimeNamespaces = []) {
|
|
|
4920
5208
|
])
|
|
4921
5209
|
)
|
|
4922
5210
|
},
|
|
4923
|
-
vaults
|
|
5211
|
+
vaults,
|
|
4924
5212
|
writePolicy: {
|
|
4925
5213
|
define: {
|
|
4926
5214
|
defaultProfile: graph.profile,
|
|
@@ -5055,14 +5343,34 @@ function graphFromProjection(projection) {
|
|
|
5055
5343
|
}
|
|
5056
5344
|
};
|
|
5057
5345
|
}
|
|
5058
|
-
function
|
|
5346
|
+
function vaultDefinitionFromProjection(manifest, projection, key, ref) {
|
|
5347
|
+
assertSecretRefVaultProviderCompatible(manifest, ref, key);
|
|
5348
|
+
const vaultId = ref.vault ?? "default";
|
|
5349
|
+
const projected = projection.vaults?.[vaultId];
|
|
5350
|
+
const mapping = {
|
|
5351
|
+
...projected?.mapping ?? {},
|
|
5352
|
+
...ref.envVar ? { [ref.envVar]: ref.ref } : {}
|
|
5353
|
+
};
|
|
5354
|
+
return {
|
|
5355
|
+
provider: projected?.provider ?? ref.provider ?? "local",
|
|
5356
|
+
...projected?.auth ? { auth: projected.auth } : {},
|
|
5357
|
+
...Object.keys(mapping).length > 0 ? { mapping } : {},
|
|
5358
|
+
...projected?.fallback ? { fallback: projected.fallback } : {}
|
|
5359
|
+
};
|
|
5360
|
+
}
|
|
5361
|
+
function attachBootstrappedProjection(projection, force = false, options = {}) {
|
|
5059
5362
|
if (getSingletonRuntime() && !force) {
|
|
5060
5363
|
return;
|
|
5061
5364
|
}
|
|
5365
|
+
bootstrappedProjection = projection;
|
|
5062
5366
|
const graph = graphFromProjection(projection);
|
|
5063
|
-
const manifest = toBootstrappedManifest(graph, projection.runtimeNamespaces);
|
|
5367
|
+
const manifest = toBootstrappedManifest(graph, projection.runtimeNamespaces, projection.vaults ?? {});
|
|
5064
5368
|
const hydratedSecrets = /* @__PURE__ */ new Map();
|
|
5369
|
+
const secretVaultProviders = mergeSecretVaultProviders(options.secretVaultProviders);
|
|
5065
5370
|
const runtimeProviders = createDefaultRuntimeProviders(manifest, process.env);
|
|
5371
|
+
for (const [namespace, provider] of singletonRuntimeProviders) {
|
|
5372
|
+
registerRuntimeProvider(manifest, runtimeProviders, namespace, provider);
|
|
5373
|
+
}
|
|
5066
5374
|
const derivedSupport = createDerivedRuntimeSupport(graph, manifest, runtimeProviders);
|
|
5067
5375
|
const resolveProjectedSourceKey = (key) => {
|
|
5068
5376
|
if (!key.startsWith("public.")) {
|
|
@@ -5075,32 +5383,95 @@ function attachBootstrappedProjection(projection, force = false) {
|
|
|
5075
5383
|
const fallback = `value.${key.slice("public.".length)}`;
|
|
5076
5384
|
return graph.entries.has(fallback) ? fallback : key;
|
|
5077
5385
|
};
|
|
5078
|
-
const
|
|
5386
|
+
const projectedDescriptorForKey = (key) => {
|
|
5079
5387
|
const entry = graph.entries.get(key);
|
|
5080
5388
|
if (!entry || entry.namespace !== "secret") {
|
|
5081
|
-
return
|
|
5082
|
-
}
|
|
5083
|
-
if (hydratedSecrets.has(key)) {
|
|
5084
|
-
return hydratedSecrets.get(key);
|
|
5389
|
+
return void 0;
|
|
5085
5390
|
}
|
|
5086
5391
|
const ref = projection.secretRefs[key.slice("secret.".length)];
|
|
5087
5392
|
if (!ref) {
|
|
5088
5393
|
return void 0;
|
|
5089
5394
|
}
|
|
5090
|
-
const definition =
|
|
5091
|
-
|
|
5092
|
-
|
|
5093
|
-
|
|
5094
|
-
|
|
5095
|
-
|
|
5096
|
-
} : {}
|
|
5395
|
+
const definition = vaultDefinitionFromProjection(manifest, projection, key, ref);
|
|
5396
|
+
return {
|
|
5397
|
+
key,
|
|
5398
|
+
ref,
|
|
5399
|
+
vaultId: ref.vault ?? "default",
|
|
5400
|
+
definitions: [definition, ...definition.fallback ?? []]
|
|
5097
5401
|
};
|
|
5098
|
-
|
|
5099
|
-
|
|
5100
|
-
|
|
5101
|
-
|
|
5102
|
-
|
|
5103
|
-
|
|
5402
|
+
};
|
|
5403
|
+
const runtimeDefinitionForCandidate = (candidate) => ({
|
|
5404
|
+
provider: candidate.provider,
|
|
5405
|
+
...candidate.auth ? { auth: candidate.auth } : {},
|
|
5406
|
+
...candidate.mapping ? { mapping: candidate.mapping } : {}
|
|
5407
|
+
});
|
|
5408
|
+
const hydrateProjectedSecrets = async (keys) => {
|
|
5409
|
+
const requestedKeys = keys ?? Object.keys(projection.secretRefs).map((segment) => `secret.${segment}`);
|
|
5410
|
+
let remaining = requestedKeys.filter((key) => !hydratedSecrets.has(key)).map((key) => projectedDescriptorForKey(key)).filter((descriptor) => Boolean(descriptor));
|
|
5411
|
+
const lastErrors = /* @__PURE__ */ new Map();
|
|
5412
|
+
let candidateIndex = 0;
|
|
5413
|
+
while (remaining.length > 0) {
|
|
5414
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
5415
|
+
const exhausted = [];
|
|
5416
|
+
for (const descriptor of remaining) {
|
|
5417
|
+
const candidate = descriptor.definitions[candidateIndex];
|
|
5418
|
+
if (!candidate) {
|
|
5419
|
+
exhausted.push(descriptor);
|
|
5420
|
+
continue;
|
|
5421
|
+
}
|
|
5422
|
+
const groupKey = `${descriptor.vaultId}\0${candidate.provider}`;
|
|
5423
|
+
const group = grouped.get(groupKey) ?? {
|
|
5424
|
+
vaultId: descriptor.vaultId,
|
|
5425
|
+
definition: candidate,
|
|
5426
|
+
descriptors: []
|
|
5427
|
+
};
|
|
5428
|
+
group.descriptors.push(descriptor);
|
|
5429
|
+
grouped.set(groupKey, group);
|
|
5430
|
+
}
|
|
5431
|
+
if (grouped.size === 0) {
|
|
5432
|
+
remaining = exhausted;
|
|
5433
|
+
break;
|
|
5434
|
+
}
|
|
5435
|
+
const unresolved = [...exhausted];
|
|
5436
|
+
for (const group of grouped.values()) {
|
|
5437
|
+
const runtimeDefinition = runtimeDefinitionForCandidate(group.definition);
|
|
5438
|
+
try {
|
|
5439
|
+
const provider = createSecretVaultProvider(
|
|
5440
|
+
group.vaultId,
|
|
5441
|
+
runtimeDefinition,
|
|
5442
|
+
process.env,
|
|
5443
|
+
secretVaultProviders
|
|
5444
|
+
);
|
|
5445
|
+
const auth = await resolveVaultAuth(group.vaultId, runtimeDefinition, process.env);
|
|
5446
|
+
await provider.authenticate(auth);
|
|
5447
|
+
const refs = Array.from(new Set(group.descriptors.map((descriptor) => descriptor.ref.ref))).sort((left, right) => left.localeCompare(right));
|
|
5448
|
+
const values = await provider.batchGet(refs);
|
|
5449
|
+
for (const descriptor of group.descriptors) {
|
|
5450
|
+
const value = values.get(descriptor.ref.ref);
|
|
5451
|
+
if (value !== void 0) {
|
|
5452
|
+
hydratedSecrets.set(descriptor.key, value);
|
|
5453
|
+
lastErrors.delete(descriptor.key);
|
|
5454
|
+
} else {
|
|
5455
|
+
unresolved.push(descriptor);
|
|
5456
|
+
}
|
|
5457
|
+
}
|
|
5458
|
+
} catch (error) {
|
|
5459
|
+
for (const descriptor of group.descriptors) {
|
|
5460
|
+
lastErrors.set(descriptor.key, error);
|
|
5461
|
+
unresolved.push(descriptor);
|
|
5462
|
+
}
|
|
5463
|
+
}
|
|
5464
|
+
}
|
|
5465
|
+
remaining = unresolved.filter((descriptor) => !hydratedSecrets.has(descriptor.key));
|
|
5466
|
+
candidateIndex += 1;
|
|
5467
|
+
}
|
|
5468
|
+
for (const descriptor of remaining) {
|
|
5469
|
+
const error = lastErrors.get(descriptor.key);
|
|
5470
|
+
if (error) {
|
|
5471
|
+
throw error;
|
|
5472
|
+
}
|
|
5473
|
+
hydratedSecrets.set(descriptor.key, void 0);
|
|
5474
|
+
}
|
|
5104
5475
|
};
|
|
5105
5476
|
const runtime = {
|
|
5106
5477
|
manifest,
|
|
@@ -5170,14 +5541,14 @@ function attachBootstrappedProjection(projection, force = false) {
|
|
|
5170
5541
|
toNamespace(namespace) {
|
|
5171
5542
|
return toNamespaceObject(graph, namespace, (key) => this.read(key));
|
|
5172
5543
|
},
|
|
5173
|
-
toEnv(
|
|
5174
|
-
return toEnv(graph, manifest,
|
|
5544
|
+
toEnv(options2) {
|
|
5545
|
+
return toEnv(graph, manifest, options2, {
|
|
5175
5546
|
read: (key) => this.read(key),
|
|
5176
5547
|
isRuntimeDependent: (key) => derivedSupport.isRuntimeDependentKey(key)
|
|
5177
5548
|
});
|
|
5178
5549
|
},
|
|
5179
|
-
toPublicEnv(
|
|
5180
|
-
return toPublicEnv(graph, manifest,
|
|
5550
|
+
toPublicEnv(options2) {
|
|
5551
|
+
return toPublicEnv(graph, manifest, options2, {
|
|
5181
5552
|
read: (key) => derivedSupport.toConcreteValue(
|
|
5182
5553
|
resolveProjectedSourceKey(key),
|
|
5183
5554
|
(ref) => {
|
|
@@ -5200,16 +5571,18 @@ function attachBootstrappedProjection(projection, force = false) {
|
|
|
5200
5571
|
},
|
|
5201
5572
|
registerRuntimeProvider(namespace, provider) {
|
|
5202
5573
|
registerRuntimeProvider(manifest, runtimeProviders, namespace, provider);
|
|
5574
|
+
singletonRuntimeProviders.set(namespace, provider);
|
|
5203
5575
|
},
|
|
5204
5576
|
async refreshSecrets() {
|
|
5205
|
-
|
|
5577
|
+
const keys = Object.keys(projection.secretRefs).map((segment) => `secret.${segment}`);
|
|
5578
|
+
for (const key of keys) {
|
|
5206
5579
|
hydratedSecrets.delete(key);
|
|
5207
|
-
await resolveSecretValue(key);
|
|
5208
5580
|
}
|
|
5581
|
+
await hydrateProjectedSecrets(keys);
|
|
5209
5582
|
},
|
|
5210
5583
|
async refreshSecret(key) {
|
|
5211
5584
|
hydratedSecrets.delete(key);
|
|
5212
|
-
await
|
|
5585
|
+
await hydrateProjectedSecrets([key]);
|
|
5213
5586
|
}
|
|
5214
5587
|
};
|
|
5215
5588
|
setSingletonRuntime(runtime);
|
|
@@ -5316,14 +5689,23 @@ var cnos = Object.assign(
|
|
|
5316
5689
|
console.log(formatted);
|
|
5317
5690
|
return formatted;
|
|
5318
5691
|
},
|
|
5319
|
-
async loadProjection(source) {
|
|
5692
|
+
async loadProjection(source, options = {}) {
|
|
5320
5693
|
const resolvedSource = import_node_path16.default.resolve(source);
|
|
5321
5694
|
const projection = deserializeServerProjection((0, import_node_fs.readFileSync)(resolvedSource, "utf8"));
|
|
5322
|
-
attachBootstrappedProjection(projection, true);
|
|
5695
|
+
attachBootstrappedProjection(projection, true, options);
|
|
5323
5696
|
setBootstrappedSecretHydrationRequired(Object.keys(projection.secretRefs).length > 0);
|
|
5324
5697
|
},
|
|
5325
5698
|
registerRuntimeProvider(namespace, provider) {
|
|
5326
5699
|
getRuntimeOrThrow().registerRuntimeProvider(namespace, provider);
|
|
5700
|
+
singletonRuntimeProviders.set(namespace, provider);
|
|
5701
|
+
},
|
|
5702
|
+
registerSecretVaultProvider(factory) {
|
|
5703
|
+
registerSingletonSecretVaultProvider(factory);
|
|
5704
|
+
},
|
|
5705
|
+
registerSecretVaultProviders(factories) {
|
|
5706
|
+
for (const factory of factories) {
|
|
5707
|
+
registerSingletonSecretVaultProvider(factory);
|
|
5708
|
+
}
|
|
5327
5709
|
},
|
|
5328
5710
|
async refreshSecrets() {
|
|
5329
5711
|
await getRuntimeOrThrow().refreshSecrets();
|
|
@@ -5332,10 +5714,14 @@ var cnos = Object.assign(
|
|
|
5332
5714
|
async refreshSecret(key) {
|
|
5333
5715
|
await getRuntimeOrThrow().refreshSecret(key);
|
|
5334
5716
|
},
|
|
5335
|
-
async ready() {
|
|
5717
|
+
async ready(options = {}) {
|
|
5336
5718
|
const runtime = getSingletonRuntime();
|
|
5719
|
+
const secretVaultProviders = mergeSecretVaultProviders(options.secretVaultProviders);
|
|
5337
5720
|
if (runtime && getBootstrappedSecretHydrationRequired()) {
|
|
5338
|
-
|
|
5721
|
+
const runtimeToHydrate = bootstrappedProjection && secretVaultProviders.length > 0 ? (attachBootstrappedProjection(bootstrappedProjection, true, {
|
|
5722
|
+
secretVaultProviders
|
|
5723
|
+
}), getRuntimeOrThrow()) : runtime;
|
|
5724
|
+
await runtimeToHydrate.refreshSecrets();
|
|
5339
5725
|
setBootstrappedSecretHydrationRequired(false);
|
|
5340
5726
|
return;
|
|
5341
5727
|
}
|
|
@@ -5347,7 +5733,10 @@ var cnos = Object.assign(
|
|
|
5347
5733
|
await existing;
|
|
5348
5734
|
return;
|
|
5349
5735
|
}
|
|
5350
|
-
const readyPromise = createCnos2(
|
|
5736
|
+
const readyPromise = createCnos2({
|
|
5737
|
+
...options,
|
|
5738
|
+
secretVaultProviders
|
|
5739
|
+
}).then((runtime2) => {
|
|
5351
5740
|
setSingletonRuntime(runtime2);
|
|
5352
5741
|
setBootstrappedSecretHydrationRequired(false);
|
|
5353
5742
|
return runtime2;
|