@seekrit/cli 0.47.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.js +225 -150
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -4986,7 +4986,7 @@ async function createAgentTaskToken() {
|
|
|
4986
4986
|
}
|
|
4987
4987
|
//#endregion
|
|
4988
4988
|
//#region package.json
|
|
4989
|
-
var version = "0.
|
|
4989
|
+
var version = "1.0.0";
|
|
4990
4990
|
//#endregion
|
|
4991
4991
|
//#region ../../packages/api-client/src/index.ts
|
|
4992
4992
|
var SeekritApiError = class extends Error {
|
|
@@ -5765,7 +5765,18 @@ function parseDurationSeconds(input, flag) {
|
|
|
5765
5765
|
d: 86400
|
|
5766
5766
|
}[m[2] || "s"] ?? 1);
|
|
5767
5767
|
}
|
|
5768
|
-
/**
|
|
5768
|
+
/**
|
|
5769
|
+
* Prompt without echoing input (for passphrases).
|
|
5770
|
+
*
|
|
5771
|
+
* Piping the answer in (`echo … | seekrit secrets get …`) is supported and
|
|
5772
|
+
* common in CI, so this reads stdin rather than insisting on a TTY. But stdin
|
|
5773
|
+
* can also close with nothing on it — `< /dev/null`, a closed pipe, an agent
|
|
5774
|
+
* spawning us with no stdin — and readline signals that by emitting `close`
|
|
5775
|
+
* without ever calling the `question` callback. Left unhandled the promise
|
|
5776
|
+
* never settles, the event loop drains, and Node exits **0** having printed
|
|
5777
|
+
* nothing: `V=$(seekrit secrets get X)` silently yields an empty value and a
|
|
5778
|
+
* success status. So treat EOF-without-an-answer as the error it is.
|
|
5779
|
+
*/
|
|
5769
5780
|
function promptHidden(question) {
|
|
5770
5781
|
const muted = new Writable({ write(_chunk, _encoding, callback) {
|
|
5771
5782
|
callback();
|
|
@@ -5776,8 +5787,15 @@ function promptHidden(question) {
|
|
|
5776
5787
|
output: muted,
|
|
5777
5788
|
terminal: true
|
|
5778
5789
|
});
|
|
5779
|
-
return new Promise((resolve) => {
|
|
5790
|
+
return new Promise((resolve, reject) => {
|
|
5791
|
+
let answered = false;
|
|
5792
|
+
rl.on("close", () => {
|
|
5793
|
+
if (answered) return;
|
|
5794
|
+
process.stderr.write("\n");
|
|
5795
|
+
reject(/* @__PURE__ */ new Error("no passphrase on stdin — set SEEKRIT_PASSPHRASE, pipe it in, or run this in a terminal"));
|
|
5796
|
+
});
|
|
5780
5797
|
rl.question("", (answer) => {
|
|
5798
|
+
answered = true;
|
|
5781
5799
|
rl.close();
|
|
5782
5800
|
process.stderr.write("\n");
|
|
5783
5801
|
resolve(answer);
|
|
@@ -5853,9 +5871,23 @@ const CLI_CLIENT = `cli/${version}`;
|
|
|
5853
5871
|
* `flag > env > .env` credential resolution. Empty for every command but
|
|
5854
5872
|
* `seekrit run`, which loads `.env` before authenticating.
|
|
5855
5873
|
*/
|
|
5874
|
+
/**
|
|
5875
|
+
* A `SEEKRIT_*` value, or undefined if it is absent *or blank*.
|
|
5876
|
+
*
|
|
5877
|
+
* Blank has to mean absent. An unset CI secret, a `${VAR}` that expanded to
|
|
5878
|
+
* nothing, a bare `export SEEKRIT_TOKEN=` — all arrive as `""`, and `??` only
|
|
5879
|
+
* falls back on null/undefined. Left alone, an empty `SEEKRIT_API_URL` makes
|
|
5880
|
+
* every request relative and an empty `SEEKRIT_TOKEN` authenticates as a
|
|
5881
|
+
* bearer of nothing: a 401 where the honest answer is "you have no
|
|
5882
|
+
* credentials", pointing at the API instead of at the missing variable.
|
|
5883
|
+
*/
|
|
5884
|
+
function present(value) {
|
|
5885
|
+
const trimmed = value?.trim();
|
|
5886
|
+
return trimmed ? trimmed : void 0;
|
|
5887
|
+
}
|
|
5856
5888
|
function tryBuildContext(dotenvVars = {}) {
|
|
5857
5889
|
const config = readGlobalConfig();
|
|
5858
|
-
const fromEnv = (key) => process.env[key] ?? dotenvVars[key];
|
|
5890
|
+
const fromEnv = (key) => present(process.env[key]) ?? present(dotenvVars[key]);
|
|
5859
5891
|
const apiUrl = fromEnv("SEEKRIT_API_URL") ?? config.apiUrl ?? "https://api.seekrit.dev";
|
|
5860
5892
|
const token = fromEnv("SEEKRIT_TOKEN") ?? config.token ?? config.sessionToken;
|
|
5861
5893
|
const devUser = fromEnv("SEEKRIT_DEV_USER") ?? config.devUser;
|
|
@@ -5888,6 +5920,24 @@ function isTokenAuth(ctx) {
|
|
|
5888
5920
|
return ctx.auth.type === "bearer" && isServiceToken(ctx.auth.token);
|
|
5889
5921
|
}
|
|
5890
5922
|
/**
|
|
5923
|
+
* Render an unhandled error for the top-level handler.
|
|
5924
|
+
*
|
|
5925
|
+
* `fetch` reports every transport failure as the same opaque `TypeError: fetch
|
|
5926
|
+
* failed` and hides the reason (ECONNREFUSED, DNS, TLS) in `cause`. That is the
|
|
5927
|
+
* single most common thing to go wrong — a stale `SEEKRIT_API_URL`, a dev
|
|
5928
|
+
* server that isn't up, a VPN that is down — and "error: fetch failed" names
|
|
5929
|
+
* neither the address we tried nor why it failed. So unwrap it and say both.
|
|
5930
|
+
*/
|
|
5931
|
+
function describeError(err) {
|
|
5932
|
+
if (!(err instanceof Error)) return String(err);
|
|
5933
|
+
if (err.message !== "fetch failed") return err.message;
|
|
5934
|
+
const config = readGlobalConfig();
|
|
5935
|
+
const apiUrl = present(process.env.SEEKRIT_API_URL) ?? config.apiUrl ?? "https://api.seekrit.dev";
|
|
5936
|
+
const cause = err.cause;
|
|
5937
|
+
const reason = cause instanceof Error ? cause.code ?? cause.message : void 0;
|
|
5938
|
+
return `cannot reach the seekrit API at ${apiUrl}${reason ? ` (${reason})` : ""} — check SEEKRIT_API_URL, your network, and that the API is up`;
|
|
5939
|
+
}
|
|
5940
|
+
/**
|
|
5891
5941
|
* Recover the calling principal's private key:
|
|
5892
5942
|
* - service tokens carry their private key in the token string;
|
|
5893
5943
|
* - users fetch their passphrase-encrypted key from the API and unlock it.
|
|
@@ -6150,7 +6200,7 @@ async function resolvePrincipal(ctx, orgId, options) {
|
|
|
6150
6200
|
}
|
|
6151
6201
|
/** The `--org/--app/--group/--env` selection every grant command shares. */
|
|
6152
6202
|
function withEnvTarget(cmd) {
|
|
6153
|
-
return cmd.option("--org <slug>").option("--app <slug>", "application slug (defaults to seekrit.json)").option("--group <slug>", "target a group environment instead of an app").requiredOption("--env <slug>");
|
|
6203
|
+
return cmd.option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--app <slug>", "application slug (defaults to seekrit.json)").option("--group <slug>", "target a group environment instead of an app").requiredOption("--env <slug>", "environment slug");
|
|
6154
6204
|
}
|
|
6155
6205
|
/**
|
|
6156
6206
|
* Environment key grants — who can decrypt what.
|
|
@@ -6185,7 +6235,7 @@ function registerAccessCommands(program) {
|
|
|
6185
6235
|
col("id", (g) => g.principalId)
|
|
6186
6236
|
], "nobody holds a key for this environment"));
|
|
6187
6237
|
});
|
|
6188
|
-
withEnvTarget(grant.command("rm").alias("revoke").description("take away a member's or token's access to an environment's key").option("--user <email>", "revoke an org member by email").option("--token <tokenId>", "revoke a service token by id (skt_…)").option("--yes", "skip the confirmation prompt")).action(async (options) => {
|
|
6238
|
+
withEnvTarget(grant.command("rm").alias("revoke").description("take away a member's or token's access to an environment's key").option("--user <email>", "revoke an org member by email").option("--token <tokenId>", "revoke a service token by id (skt_…)").option("-y, --yes", "skip the confirmation prompt")).action(async (options) => {
|
|
6189
6239
|
if (!options.user === !options.token) fail("pass exactly one of --user or --token");
|
|
6190
6240
|
const ctx = buildContext();
|
|
6191
6241
|
const { orgId, envId, label } = await resolveEnvTarget(ctx, options);
|
|
@@ -6231,7 +6281,7 @@ function registerAccountCommands(program) {
|
|
|
6231
6281
|
col("id", (s) => `${s.id}${s.id === currentSessionId ? " (this one)" : ""}`)
|
|
6232
6282
|
], options.all ? "no CLI sessions" : "no active CLI sessions (try --all)"));
|
|
6233
6283
|
});
|
|
6234
|
-
session.command("revoke <sessionId>").description("sign a device out — its token stops working immediately").option("--yes", "skip the confirmation prompt").action(async (sessionId, options) => {
|
|
6284
|
+
session.command("revoke <sessionId>").description("sign a device out — its token stops working immediately").option("-y, --yes", "skip the confirmation prompt").action(async (sessionId, options) => {
|
|
6235
6285
|
const ctx = buildContext();
|
|
6236
6286
|
const self = ctx.auth.type === "bearer" && isCliSessionToken(ctx.auth.token) && parseCliSessionToken(ctx.auth.token).sessionId === sessionId;
|
|
6237
6287
|
await confirmDestructive(options.yes, self ? `${sessionId} is the session you are using right now — sign it out?` : `Sign out ${sessionId}?`);
|
|
@@ -6962,7 +7012,7 @@ async function kmsRecoverMaterial(ctx, orgId, keyId, version) {
|
|
|
6962
7012
|
}
|
|
6963
7013
|
function registerKmsCommands(program) {
|
|
6964
7014
|
const kms = program.command("kms").description("managed keys for application-layer encryption & signing (client-side)");
|
|
6965
|
-
kms.command("create").description("create a managed key (material is generated locally and wrapped, never sent)").requiredOption("--name <name>", "org-unique key name").requiredOption("--purpose <purpose>", "encrypt | sign").option("--org <slug>").option("--app <slug>", "scope the key to an application").option("--group <slug>", "scope the key to a group").option("--grant-user <email>", "also grant an org member (repeatable)", collect$7, []).option("--grant-token <tokenId>", "also grant a service token (repeatable)", collect$7, []).action(async (options) => {
|
|
7015
|
+
kms.command("create").description("create a managed key (material is generated locally and wrapped, never sent)").requiredOption("--name <name>", "org-unique key name").requiredOption("--purpose <purpose>", "encrypt | sign").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--app <slug>", "scope the key to an application").option("--group <slug>", "scope the key to a group").option("--grant-user <email>", "also grant an org member (repeatable)", collect$7, []).option("--grant-token <tokenId>", "also grant a service token (repeatable)", collect$7, []).action(async (options) => {
|
|
6966
7016
|
if (options.purpose !== "encrypt" && options.purpose !== "sign") fail("--purpose must be encrypt or sign");
|
|
6967
7017
|
if (options.app && options.group) fail("pass at most one of --app or --group");
|
|
6968
7018
|
const ctx = buildContext();
|
|
@@ -7015,7 +7065,7 @@ function registerKmsCommands(program) {
|
|
|
7015
7065
|
const { key } = await ctx.client.createKmsKey(org.id, input);
|
|
7016
7066
|
console.error(`created ${key.purpose} key ${key.name} (${key.id}), ${grants.length} grant(s)`);
|
|
7017
7067
|
});
|
|
7018
|
-
kms.command("ls").description("list keys you can see").option("--org <slug>").action(async (options) => {
|
|
7068
|
+
kms.command("ls").description("list keys you can see").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (options) => {
|
|
7019
7069
|
const ctx = buildContext();
|
|
7020
7070
|
const org = await resolveOrg(ctx, options.org);
|
|
7021
7071
|
const { keys } = await ctx.client.listKmsKeys(org.id);
|
|
@@ -7029,7 +7079,7 @@ function registerKmsCommands(program) {
|
|
|
7029
7079
|
console.log(`${k.name}\t${k.purpose}\tv${k.currentVersion}\t${scope}\t${k.id}${state}`);
|
|
7030
7080
|
}
|
|
7031
7081
|
});
|
|
7032
|
-
kms.command("grant").description("grant a principal use of a key's current version").requiredOption("--key <name>", "key name or id").option("--org <slug>").option("--user <email>", "grant an org member").option("--token <tokenId>", "grant a service token").action(async (options) => {
|
|
7082
|
+
kms.command("grant").description("grant a principal use of a key's current version").requiredOption("--key <name>", "key name or id").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--user <email>", "grant an org member").option("--token <tokenId>", "grant a service token").action(async (options) => {
|
|
7033
7083
|
if (!options.user === !options.token) fail("pass exactly one of --user or --token");
|
|
7034
7084
|
const ctx = buildContext();
|
|
7035
7085
|
const org = await resolveOrg(ctx, options.org);
|
|
@@ -7043,19 +7093,20 @@ function registerKmsCommands(program) {
|
|
|
7043
7093
|
});
|
|
7044
7094
|
console.error(`granted ${key.name} to ${recipient.principalId}`);
|
|
7045
7095
|
});
|
|
7046
|
-
kms.command("revoke").description("revoke a principal from a key (all versions)").requiredOption("--key <name>", "key name or id").option("--org <slug>").option("--user <email>").option("--token <tokenId>").action(async (options) => {
|
|
7096
|
+
kms.command("revoke").description("revoke a principal from a key (all versions)").requiredOption("--key <name>", "key name or id").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--user <email>", "revoke this user's grant").option("--token <tokenId>", "revoke this service token's grant").option("-y, --yes", "skip the confirmation").action(async (options) => {
|
|
7047
7097
|
if (!options.user === !options.token) fail("pass exactly one of --user or --token");
|
|
7048
7098
|
const ctx = buildContext();
|
|
7049
7099
|
const org = await resolveOrg(ctx, options.org);
|
|
7050
7100
|
const key = await kmsResolveKey(ctx, org.id, options.key);
|
|
7051
7101
|
const recipient = await kmsResolveRecipient(ctx, org.id, options);
|
|
7102
|
+
await confirmDestructive(options.yes, `Revoke ${recipient.principalId} from ${key.name}? Anything already decrypted stays decrypted.`);
|
|
7052
7103
|
await ctx.client.revokeKmsKey(org.id, key.id, {
|
|
7053
7104
|
principalType: recipient.principalType,
|
|
7054
7105
|
principalId: recipient.principalId
|
|
7055
7106
|
});
|
|
7056
7107
|
console.error(`revoked ${recipient.principalId} from ${key.name}`);
|
|
7057
7108
|
});
|
|
7058
|
-
kms.command("rotate").description("add a new key version and re-wrap it for every current grantee").requiredOption("--key <name>", "key name or id").option("--org <slug>").action(async (options) => {
|
|
7109
|
+
kms.command("rotate").description("add a new key version and re-wrap it for every current grantee").requiredOption("--key <name>", "key name or id").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (options) => {
|
|
7059
7110
|
const ctx = buildContext();
|
|
7060
7111
|
const org = await resolveOrg(ctx, options.org);
|
|
7061
7112
|
const key = await kmsResolveKey(ctx, org.id, options.key);
|
|
@@ -7089,21 +7140,23 @@ function registerKmsCommands(program) {
|
|
|
7089
7140
|
});
|
|
7090
7141
|
console.error(`rotated ${rotated.name} to v${rotated.currentVersion} (${grants.length} grantees)`);
|
|
7091
7142
|
});
|
|
7092
|
-
kms.command("disable").description("disable a key (blocks all use: encrypt/decrypt/sign and new grants/rotations)").requiredOption("--key <name>", "key name or id").option("--org <slug>").action(async (options) => {
|
|
7143
|
+
kms.command("disable").description("disable a key (blocks all use: encrypt/decrypt/sign and new grants/rotations)").requiredOption("--key <name>", "key name or id").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("-y, --yes", "skip the confirmation").action(async (options) => {
|
|
7093
7144
|
const ctx = buildContext();
|
|
7094
7145
|
const org = await resolveOrg(ctx, options.org);
|
|
7095
7146
|
const key = await kmsResolveKey(ctx, org.id, options.key);
|
|
7147
|
+
await confirmDestructive(options.yes, `Disable ${key.name}? Every encrypt, decrypt, and sign against it starts failing.`);
|
|
7096
7148
|
await ctx.client.disableKmsKey(org.id, key.id);
|
|
7097
7149
|
console.error(`disabled ${key.name}`);
|
|
7098
7150
|
});
|
|
7099
|
-
kms.command("delete").description("delete a key (hides it from all listings; the name frees up for reuse)").requiredOption("--key <name>", "key name or id").option("--org <slug>").action(async (options) => {
|
|
7151
|
+
kms.command("delete").description("delete a key (hides it from all listings; the name frees up for reuse)").requiredOption("--key <name>", "key name or id").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("-y, --yes", "skip the confirmation").action(async (options) => {
|
|
7100
7152
|
const ctx = buildContext();
|
|
7101
7153
|
const org = await resolveOrg(ctx, options.org);
|
|
7102
7154
|
const key = await kmsResolveKey(ctx, org.id, options.key);
|
|
7155
|
+
await confirmDestructive(options.yes, `Delete ${key.name}? Any ciphertext or signature still relying on it becomes unrecoverable.`);
|
|
7103
7156
|
await ctx.client.deleteKmsKey(org.id, key.id);
|
|
7104
7157
|
console.error(`deleted ${key.name}`);
|
|
7105
7158
|
});
|
|
7106
|
-
kms.command("encrypt").description("encrypt stdin under a key (prints a ce1 ciphertext blob)").requiredOption("--key <name>", "key name or id").option("--org <slug>").option("--context <ctx>", "encryption context bound as AAD (required identically to decrypt)").action(async (options) => {
|
|
7159
|
+
kms.command("encrypt").description("encrypt stdin under a key (prints a ce1 ciphertext blob)").requiredOption("--key <name>", "key name or id").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--context <ctx>", "encryption context bound as AAD (required identically to decrypt)").action(async (options) => {
|
|
7107
7160
|
const ctx = buildContext();
|
|
7108
7161
|
const org = await resolveOrg(ctx, options.org);
|
|
7109
7162
|
const key = await kmsResolveKey(ctx, org.id, options.key);
|
|
@@ -7116,7 +7169,7 @@ function registerKmsCommands(program) {
|
|
|
7116
7169
|
}, plaintext, options.context ?? "");
|
|
7117
7170
|
console.log(blob);
|
|
7118
7171
|
});
|
|
7119
|
-
kms.command("decrypt").description("decrypt a ce1 blob from stdin").requiredOption("--key <name>", "key name or id").option("--org <slug>").option("--context <ctx>", "the same encryption context used to encrypt").action(async (options) => {
|
|
7172
|
+
kms.command("decrypt").description("decrypt a ce1 blob from stdin").requiredOption("--key <name>", "key name or id").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--context <ctx>", "the same encryption context used to encrypt").action(async (options) => {
|
|
7120
7173
|
const ctx = buildContext();
|
|
7121
7174
|
const org = await resolveOrg(ctx, options.org);
|
|
7122
7175
|
const key = await kmsResolveKey(ctx, org.id, options.key);
|
|
@@ -7125,7 +7178,7 @@ function registerKmsCommands(program) {
|
|
|
7125
7178
|
const { material } = await kmsRecoverMaterial(ctx, org.id, key.id, ref.version);
|
|
7126
7179
|
console.log(await kmsDecrypt(material, blob, options.context ?? ""));
|
|
7127
7180
|
});
|
|
7128
|
-
kms.command("generate-data-key").description("generate a data key: prints JSON {plaintextBase64, wrapped}").requiredOption("--key <name>", "key name or id").option("--org <slug>").action(async (options) => {
|
|
7181
|
+
kms.command("generate-data-key").description("generate a data key: prints JSON {plaintextBase64, wrapped}").requiredOption("--key <name>", "key name or id").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (options) => {
|
|
7129
7182
|
const ctx = buildContext();
|
|
7130
7183
|
const org = await resolveOrg(ctx, options.org);
|
|
7131
7184
|
const key = await kmsResolveKey(ctx, org.id, options.key);
|
|
@@ -7140,7 +7193,7 @@ function registerKmsCommands(program) {
|
|
|
7140
7193
|
wrapped: dk.wrapped
|
|
7141
7194
|
}));
|
|
7142
7195
|
});
|
|
7143
|
-
kms.command("open-data-key").description("recover a data key from a dk1 blob on stdin (prints plaintext base64)").requiredOption("--key <name>", "key name or id").option("--org <slug>").action(async (options) => {
|
|
7196
|
+
kms.command("open-data-key").description("recover a data key from a dk1 blob on stdin (prints plaintext base64)").requiredOption("--key <name>", "key name or id").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (options) => {
|
|
7144
7197
|
const ctx = buildContext();
|
|
7145
7198
|
const org = await resolveOrg(ctx, options.org);
|
|
7146
7199
|
const key = await kmsResolveKey(ctx, org.id, options.key);
|
|
@@ -7149,7 +7202,7 @@ function registerKmsCommands(program) {
|
|
|
7149
7202
|
const { material } = await kmsRecoverMaterial(ctx, org.id, key.id, ref.version);
|
|
7150
7203
|
console.log(toBase64(await decryptDataKey(material, wrapped)));
|
|
7151
7204
|
});
|
|
7152
|
-
kms.command("sign").description("sign stdin with a signing key (prints an sg1 signature)").requiredOption("--key <name>", "key name or id").option("--org <slug>").action(async (options) => {
|
|
7205
|
+
kms.command("sign").description("sign stdin with a signing key (prints an sg1 signature)").requiredOption("--key <name>", "key name or id").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (options) => {
|
|
7153
7206
|
const ctx = buildContext();
|
|
7154
7207
|
const org = await resolveOrg(ctx, options.org);
|
|
7155
7208
|
const key = await kmsResolveKey(ctx, org.id, options.key);
|
|
@@ -7162,7 +7215,7 @@ function registerKmsCommands(program) {
|
|
|
7162
7215
|
version: currentVersion
|
|
7163
7216
|
}, message));
|
|
7164
7217
|
});
|
|
7165
|
-
kms.command("verify").description("verify an sg1 signature over stdin (exit 0 = valid)").requiredOption("--key <name>", "key name or id").requiredOption("--signature <sg1>", "the signature blob").option("--org <slug>").action(async (options) => {
|
|
7218
|
+
kms.command("verify").description("verify an sg1 signature over stdin (exit 0 = valid)").requiredOption("--key <name>", "key name or id").requiredOption("--signature <sg1>", "the signature blob").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (options) => {
|
|
7166
7219
|
const ctx = buildContext();
|
|
7167
7220
|
const org = await resolveOrg(ctx, options.org);
|
|
7168
7221
|
const key = await kmsResolveKey(ctx, org.id, options.key);
|
|
@@ -7264,7 +7317,7 @@ async function buildRecoveryConfig(ctx, orgId, thresholdRaw, custodianRefs) {
|
|
|
7264
7317
|
}
|
|
7265
7318
|
function registerRecoveryCommands(program) {
|
|
7266
7319
|
const recovery = program.command("recovery").description("customer-controlled M-of-N recovery (zero-knowledge)");
|
|
7267
|
-
recovery.command("status").description("show recovery configuration and environment coverage").option("--org <slug>").action(async (options) => {
|
|
7320
|
+
recovery.command("status").description("show recovery configuration and environment coverage").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (options) => {
|
|
7268
7321
|
const ctx = buildContext();
|
|
7269
7322
|
const org = await resolveOrg(ctx, options.org);
|
|
7270
7323
|
const { recovery: status } = await ctx.client.getRecovery(org.id);
|
|
@@ -7278,7 +7331,7 @@ function registerRecoveryCommands(program) {
|
|
|
7278
7331
|
for (const cst of status.custodians) console.log(` - ${cst.label ?? cst.principalId} (${cst.principalType}, share #${cst.shareIndex})`);
|
|
7279
7332
|
if (status.coverage.unprotectedEnvIds.length > 0) console.log(`${status.coverage.unprotectedEnvIds.length} environment(s) not yet protected — run \`seekrit recovery sync\``);
|
|
7280
7333
|
});
|
|
7281
|
-
recovery.command("setup").description("enable recovery: split a fresh recovery key across custodians").requiredOption("--threshold <M>", "custodians required to recover (M in M-of-N)").option("--custodian <email|skt_id>", "a recovery custodian (repeatable)", collect$6, []).option("--org <slug>").action(async (options) => {
|
|
7334
|
+
recovery.command("setup").description("enable recovery: split a fresh recovery key across custodians").requiredOption("--threshold <M>", "custodians required to recover (M in M-of-N)").option("--custodian <email|skt_id>", "a recovery custodian (repeatable)", collect$6, []).option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (options) => {
|
|
7282
7335
|
const ctx = buildContext();
|
|
7283
7336
|
const org = await resolveOrg(ctx, options.org);
|
|
7284
7337
|
const config = await buildRecoveryConfig(ctx, org.id, options.threshold, options.custodian);
|
|
@@ -7291,12 +7344,12 @@ function registerRecoveryCommands(program) {
|
|
|
7291
7344
|
console.error(`recovery-protected ${wrapped} environment(s) you can decrypt`);
|
|
7292
7345
|
if (skipped > 0) console.error(`${skipped} environment(s) need another admin to run \`seekrit recovery sync\``);
|
|
7293
7346
|
});
|
|
7294
|
-
recovery.command("sync").description("recovery-protect environments you can decrypt but that aren't yet covered").option("--org <slug>").action(async (options) => {
|
|
7347
|
+
recovery.command("sync").description("recovery-protect environments you can decrypt but that aren't yet covered").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (options) => {
|
|
7295
7348
|
const ctx = buildContext();
|
|
7296
7349
|
const { wrapped, skipped } = await syncRecoveryGrants(ctx, (await resolveOrg(ctx, options.org)).id);
|
|
7297
7350
|
console.error(`recovery-protected ${wrapped} environment(s); skipped ${skipped} you cannot decrypt`);
|
|
7298
7351
|
});
|
|
7299
|
-
recovery.command("rotate").description("rotate the recovery key (new keypair, custodians, and env re-wraps)").requiredOption("--threshold <M>", "custodians required to recover (M in M-of-N)").option("--custodian <email|skt_id>", "a recovery custodian (repeatable)", collect$6, []).option("--org <slug>").action(async (options) => {
|
|
7352
|
+
recovery.command("rotate").description("rotate the recovery key (new keypair, custodians, and env re-wraps)").requiredOption("--threshold <M>", "custodians required to recover (M in M-of-N)").option("--custodian <email|skt_id>", "a recovery custodian (repeatable)", collect$6, []).option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (options) => {
|
|
7300
7353
|
const ctx = buildContext();
|
|
7301
7354
|
const org = await resolveOrg(ctx, options.org);
|
|
7302
7355
|
const config = await buildRecoveryConfig(ctx, org.id, options.threshold, options.custodian);
|
|
@@ -7309,13 +7362,14 @@ function registerRecoveryCommands(program) {
|
|
|
7309
7362
|
console.error(`re-wrapped ${wrapped} environment(s) you can decrypt to the new recovery key`);
|
|
7310
7363
|
if (skipped > 0) console.error(`${skipped} environment(s) still need another admin to run \`seekrit recovery sync\``);
|
|
7311
7364
|
});
|
|
7312
|
-
recovery.command("disable").description("disable recovery and remove all recovery grants").option("--org <slug>").action(async (options) => {
|
|
7365
|
+
recovery.command("disable").description("disable recovery and remove all recovery grants").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("-y, --yes", "skip the confirmation").action(async (options) => {
|
|
7313
7366
|
const ctx = buildContext();
|
|
7314
7367
|
const org = await resolveOrg(ctx, options.org);
|
|
7368
|
+
await confirmDestructive(options.yes, `Disable recovery for ${org.slug}? Every custodian share is dropped, and the org loses its break-glass path.`);
|
|
7315
7369
|
await ctx.client.disableRecovery(org.id);
|
|
7316
7370
|
console.error("recovery disabled; recovery grants removed");
|
|
7317
7371
|
});
|
|
7318
|
-
recovery.command("request").description("start a recovery ceremony (defaults to recovering access for yourself)").option("--target-user <email>", "recover access for another member").option("--target-token <id>", "recover access for a service token").option("--reason <text>", "note recorded in the audit trail").option("--org <slug>").action(async (options) => {
|
|
7372
|
+
recovery.command("request").description("start a recovery ceremony (defaults to recovering access for yourself)").option("--target-user <email>", "recover access for another member").option("--target-token <id>", "recover access for a service token").option("--reason <text>", "note recorded in the audit trail").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (options) => {
|
|
7319
7373
|
const ctx = buildContext();
|
|
7320
7374
|
const org = await resolveOrg(ctx, options.org);
|
|
7321
7375
|
const target = options.targetUser || options.targetToken ? await kmsResolveRecipient(ctx, org.id, {
|
|
@@ -7332,7 +7386,7 @@ function registerRecoveryCommands(program) {
|
|
|
7332
7386
|
console.error(` custodians run: seekrit recovery approve ${request.id}`);
|
|
7333
7387
|
console.error(` then the target: seekrit recovery complete ${request.id}`);
|
|
7334
7388
|
});
|
|
7335
|
-
recovery.command("approve").description("as a custodian, contribute your share to a recovery request").argument("<requestId>").option("--org <slug>").action(async (requestId, options) => {
|
|
7389
|
+
recovery.command("approve").description("as a custodian, contribute your share to a recovery request").argument("<requestId>").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (requestId, options) => {
|
|
7336
7390
|
const ctx = buildContext();
|
|
7337
7391
|
const org = await resolveOrg(ctx, options.org);
|
|
7338
7392
|
const { request } = await ctx.client.getRecoveryRequest(org.id, requestId);
|
|
@@ -7345,7 +7399,7 @@ function registerRecoveryCommands(program) {
|
|
|
7345
7399
|
});
|
|
7346
7400
|
console.error(`contributed share #${myShare.shareIndex}: ${res.contributed}/${res.threshold} collected${res.quorumReached ? " — quorum reached" : ""}`);
|
|
7347
7401
|
});
|
|
7348
|
-
recovery.command("complete").description("as the recovery target, reconstruct the key and restore your access").argument("<requestId>").option("--org <slug>").action(async (requestId, options) => {
|
|
7402
|
+
recovery.command("complete").description("as the recovery target, reconstruct the key and restore your access").argument("<requestId>").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (requestId, options) => {
|
|
7349
7403
|
const ctx = buildContext();
|
|
7350
7404
|
const org = await resolveOrg(ctx, options.org);
|
|
7351
7405
|
const { request, contributions, quorumReached } = await ctx.client.getRecoveryRequest(org.id, requestId);
|
|
@@ -7369,9 +7423,10 @@ function registerRecoveryCommands(program) {
|
|
|
7369
7423
|
});
|
|
7370
7424
|
console.error(`recovery complete: restored access to ${restored.length} environment(s)`);
|
|
7371
7425
|
});
|
|
7372
|
-
recovery.command("cancel").description("cancel an open recovery request").argument("<requestId>").option("--org <slug>").action(async (requestId, options) => {
|
|
7426
|
+
recovery.command("cancel").description("cancel an open recovery request").argument("<requestId>").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("-y, --yes", "skip the confirmation").action(async (requestId, options) => {
|
|
7373
7427
|
const ctx = buildContext();
|
|
7374
7428
|
const org = await resolveOrg(ctx, options.org);
|
|
7429
|
+
await confirmDestructive(options.yes, `Cancel recovery request ${requestId}? Approvals already collected are discarded.`);
|
|
7375
7430
|
await ctx.client.cancelRecoveryRequest(org.id, requestId);
|
|
7376
7431
|
console.error(`recovery request ${requestId} canceled`);
|
|
7377
7432
|
});
|
|
@@ -7385,7 +7440,7 @@ function registerRecoveryCommands(program) {
|
|
|
7385
7440
|
*/
|
|
7386
7441
|
function registerAppCommands(program) {
|
|
7387
7442
|
const app = program.command("app").description("manage applications");
|
|
7388
|
-
app.command("list").alias("ls").description("list applications in an organization").option("--org <slug>").option("--json", "print the raw API response").action(async (options) => {
|
|
7443
|
+
app.command("list").alias("ls").description("list applications in an organization").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--json", "print the raw API response").action(async (options) => {
|
|
7389
7444
|
const ctx = buildContext();
|
|
7390
7445
|
const ref = await resolveOrg(ctx, options.org);
|
|
7391
7446
|
const { apps } = await ctx.client.listApps(ref.id);
|
|
@@ -7396,7 +7451,7 @@ function registerAppCommands(program) {
|
|
|
7396
7451
|
col("id", (a) => a.id)
|
|
7397
7452
|
], "no applications — create one with `seekrit app create`"));
|
|
7398
7453
|
});
|
|
7399
|
-
app.command("show [slug]").description("show an application, its environments, and your access to each").option("--org <slug>").option("--app <slug>", "application slug (defaults to seekrit.json)").option("--json", "print the raw API response").action(async (slug, options) => {
|
|
7454
|
+
app.command("show [slug]").description("show an application, its environments, and your access to each").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--app <slug>", "application slug (defaults to seekrit.json)").option("--json", "print the raw API response").action(async (slug, options) => {
|
|
7400
7455
|
const ctx = buildContext();
|
|
7401
7456
|
const ref = await resolveApp(ctx, {
|
|
7402
7457
|
org: options.org,
|
|
@@ -7432,7 +7487,7 @@ function registerAppCommands(program) {
|
|
|
7432
7487
|
}
|
|
7433
7488
|
});
|
|
7434
7489
|
});
|
|
7435
|
-
app.command("create").description("create an application").option("--org <slug>").requiredOption("--name <name>").requiredOption("--slug <slug>").action(async (options) => {
|
|
7490
|
+
app.command("create").description("create an application").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").requiredOption("--name <name>", "display name").requiredOption("--slug <slug>", "url-safe identifier (permanent)").action(async (options) => {
|
|
7436
7491
|
const ctx = buildContext();
|
|
7437
7492
|
const orgRef = await resolveOrg(ctx, options.org);
|
|
7438
7493
|
const created = await ctx.client.createApp(orgRef.id, {
|
|
@@ -7441,7 +7496,7 @@ function registerAppCommands(program) {
|
|
|
7441
7496
|
});
|
|
7442
7497
|
console.error(`created app ${created.app.slug} (${created.app.id})`);
|
|
7443
7498
|
});
|
|
7444
|
-
app.command("rename [slug]").description("change an application's display name (the slug is permanent)").option("--org <slug>").option("--app <slug>", "application slug (defaults to seekrit.json)").requiredOption("--name <name>", "new display name").action(async (slug, options) => {
|
|
7499
|
+
app.command("rename [slug]").description("change an application's display name (the slug is permanent)").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--app <slug>", "application slug (defaults to seekrit.json)").requiredOption("--name <name>", "new display name").action(async (slug, options) => {
|
|
7445
7500
|
const ctx = buildContext();
|
|
7446
7501
|
const ref = await resolveApp(ctx, {
|
|
7447
7502
|
org: options.org,
|
|
@@ -7450,7 +7505,7 @@ function registerAppCommands(program) {
|
|
|
7450
7505
|
const { app: row } = await ctx.client.updateApp(ref.orgId, ref.id, { name: options.name });
|
|
7451
7506
|
console.error(`renamed ${row.slug} to "${row.name}"`);
|
|
7452
7507
|
});
|
|
7453
|
-
app.command("rm <slug>").alias("delete").description("delete an application and every environment and secret in it").option("--org <slug>").option("--yes", "skip the confirmation prompt").action(async (slug, options) => {
|
|
7508
|
+
app.command("rm <slug>").alias("delete").description("delete an application and every environment and secret in it").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("-y, --yes", "skip the confirmation prompt").action(async (slug, options) => {
|
|
7454
7509
|
const ctx = buildContext();
|
|
7455
7510
|
const ref = await resolveApp(ctx, {
|
|
7456
7511
|
org: options.org,
|
|
@@ -7462,7 +7517,7 @@ function registerAppCommands(program) {
|
|
|
7462
7517
|
console.error(`deleted app ${ref.slug}`);
|
|
7463
7518
|
});
|
|
7464
7519
|
const env = program.command("env").description("manage environments");
|
|
7465
|
-
env.command("list").alias("ls").description("list an application's environments").option("--org <slug>").option("--app <slug>", "application slug (defaults to seekrit.json)").option("--json", "print the raw API response").action(async (options) => {
|
|
7520
|
+
env.command("list").alias("ls").description("list an application's environments").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--app <slug>", "application slug (defaults to seekrit.json)").option("--json", "print the raw API response").action(async (options) => {
|
|
7466
7521
|
const ctx = buildContext();
|
|
7467
7522
|
const ref = await resolveApp(ctx, options);
|
|
7468
7523
|
const { environments } = await ctx.client.getApp(ref.orgId, ref.id);
|
|
@@ -7473,7 +7528,7 @@ function registerAppCommands(program) {
|
|
|
7473
7528
|
col("id", (e) => e.id)
|
|
7474
7529
|
], "no environments — create one with `seekrit env create`"));
|
|
7475
7530
|
});
|
|
7476
|
-
env.command("show").description("show one environment: composed groups, who holds a key, secret count").option("--org <slug>").option("--app <slug>", "application slug (defaults to seekrit.json)").requiredOption("--env <slug>").option("--json", "print the raw API response").action(async (options) => {
|
|
7531
|
+
env.command("show").description("show one environment: composed groups, who holds a key, secret count").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--app <slug>", "application slug (defaults to seekrit.json)").requiredOption("--env <slug>", "environment slug").option("--json", "print the raw API response").action(async (options) => {
|
|
7477
7532
|
const ctx = buildContext();
|
|
7478
7533
|
const target = await resolveAppEnv(ctx, options);
|
|
7479
7534
|
const [{ environment }, { groups }, { secrets }, { branches }] = await Promise.all([
|
|
@@ -7513,7 +7568,7 @@ function registerAppCommands(program) {
|
|
|
7513
7568
|
}
|
|
7514
7569
|
});
|
|
7515
7570
|
});
|
|
7516
|
-
env.command("create").description("create an application environment (generates its data key locally)").option("--org <slug>").requiredOption("--app <slug>").requiredOption("--name <name>").requiredOption("--slug <slug>").action(async (options) => {
|
|
7571
|
+
env.command("create").description("create an application environment (generates its data key locally)").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").requiredOption("--app <slug>", "application slug").requiredOption("--name <name>", "display name").requiredOption("--slug <slug>", "url-safe identifier (permanent)").action(async (options) => {
|
|
7517
7572
|
const ctx = buildContext();
|
|
7518
7573
|
const orgRef = await resolveOrg(ctx, options.org);
|
|
7519
7574
|
const { apps } = await ctx.client.listApps(orgRef.id);
|
|
@@ -7532,7 +7587,7 @@ function registerAppCommands(program) {
|
|
|
7532
7587
|
});
|
|
7533
7588
|
console.error(`created environment ${created.environment.slug} (${created.environment.id})`);
|
|
7534
7589
|
});
|
|
7535
|
-
env.command("rm").alias("delete").description("delete an environment and every secret in it").option("--org <slug>").option("--app <slug>", "application slug (defaults to seekrit.json)").option("--group <slug>", "delete a group environment instead of an app one").requiredOption("--env <slug>").option("--yes", "skip the confirmation prompt").action(async (options) => {
|
|
7590
|
+
env.command("rm").alias("delete").description("delete an environment and every secret in it").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--app <slug>", "application slug (defaults to seekrit.json)").option("--group <slug>", "delete a group environment instead of an app one").requiredOption("--env <slug>", "environment slug").option("-y, --yes", "skip the confirmation prompt").action(async (options) => {
|
|
7536
7591
|
const ctx = buildContext();
|
|
7537
7592
|
const target = await resolveEnvTarget(ctx, options);
|
|
7538
7593
|
const { secrets } = await ctx.client.listSecrets(target.orgId, target.envId);
|
|
@@ -7541,7 +7596,7 @@ function registerAppCommands(program) {
|
|
|
7541
7596
|
console.error(`deleted ${target.label}`);
|
|
7542
7597
|
});
|
|
7543
7598
|
const envGroups = env.command("groups").description("compose shared groups into an application environment");
|
|
7544
|
-
envGroups.command("add").description("compose a group into an app environment").option("--org <slug>").requiredOption("--app <slug>").requiredOption("--env <slug>").requiredOption("--group <slug>").option("--position <n>", "precedence among groups (higher wins)").action(async (options) => {
|
|
7599
|
+
envGroups.command("add").description("compose a group into an app environment").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").requiredOption("--app <slug>", "application slug").requiredOption("--env <slug>", "environment slug").requiredOption("--group <slug>", "group slug").option("--position <n>", "precedence among groups (higher wins)").action(async (options) => {
|
|
7545
7600
|
const ctx = buildContext();
|
|
7546
7601
|
const target = await resolveAppEnv(ctx, options);
|
|
7547
7602
|
const group = await resolveGroup(ctx, {
|
|
@@ -7554,7 +7609,7 @@ function registerAppCommands(program) {
|
|
|
7554
7609
|
});
|
|
7555
7610
|
console.error(`composed ${group.slug} into ${target.appSlug}/${target.envSlug}`);
|
|
7556
7611
|
});
|
|
7557
|
-
envGroups.command("list").alias("ls").description("list groups composed into an app environment").option("--org <slug>").requiredOption("--app <slug>").requiredOption("--env <slug>").option("--json", "print the raw API response").action(async (options) => {
|
|
7612
|
+
envGroups.command("list").alias("ls").description("list groups composed into an app environment").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").requiredOption("--app <slug>", "application slug").requiredOption("--env <slug>", "environment slug").option("--json", "print the raw API response").action(async (options) => {
|
|
7558
7613
|
const ctx = buildContext();
|
|
7559
7614
|
const target = await resolveAppEnv(ctx, options);
|
|
7560
7615
|
const { groups } = await ctx.client.listEnvGroups(target.orgId, target.envId);
|
|
@@ -7564,13 +7619,14 @@ function registerAppCommands(program) {
|
|
|
7564
7619
|
col("name", (g) => g.name)
|
|
7565
7620
|
], "no groups composed into this environment"));
|
|
7566
7621
|
});
|
|
7567
|
-
envGroups.command("rm").description("remove a group from an app environment").option("--org <slug>").requiredOption("--app <slug>").requiredOption("--env <slug>").requiredOption("--group <slug>").action(async (options) => {
|
|
7622
|
+
envGroups.command("rm").description("remove a group from an app environment").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").requiredOption("--app <slug>", "application slug").requiredOption("--env <slug>", "environment slug").requiredOption("--group <slug>", "group slug").option("-y, --yes", "skip the confirmation prompt").action(async (options) => {
|
|
7568
7623
|
const ctx = buildContext();
|
|
7569
7624
|
const target = await resolveAppEnv(ctx, options);
|
|
7570
7625
|
const group = await resolveGroup(ctx, {
|
|
7571
7626
|
org: options.org,
|
|
7572
7627
|
group: options.group
|
|
7573
7628
|
});
|
|
7629
|
+
await confirmDestructive(options.yes, `Remove ${group.slug} from ${target.appSlug}/${target.envSlug}? Everything it contributed disappears from that environment.`);
|
|
7574
7630
|
await ctx.client.unlinkEnvGroup(target.orgId, target.envId, group.id);
|
|
7575
7631
|
console.error(`removed ${group.slug} from ${target.appSlug}/${target.envSlug}`);
|
|
7576
7632
|
});
|
|
@@ -8593,7 +8649,7 @@ async function decryptArchive(archive, key, filter) {
|
|
|
8593
8649
|
}
|
|
8594
8650
|
function registerArchiveCommands(program) {
|
|
8595
8651
|
const archive = program.command("archive").description("export the whole org as one signed file, and open it offline");
|
|
8596
|
-
archive.command("create").description("download a signed archive of everything seekrit stores for the org").option("--org <slug>").option("-o, --out <file>", "write the archive here (default: ./seekrit-<org>-<date>.json)").option("--no-versions", "omit each secret's ciphertext history").option("--no-audit", "omit the audit trail").option("--audit-limit <n>", "keep at most this many of the newest audit rows", Number).option("--json", "print the archive to stdout instead of writing a file").action(async (options) => {
|
|
8652
|
+
archive.command("create").description("download a signed archive of everything seekrit stores for the org").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("-o, --out <file>", "write the archive here (default: ./seekrit-<org>-<date>.json)").option("--no-versions", "omit each secret's ciphertext history").option("--no-audit", "omit the audit trail").option("--audit-limit <n>", "keep at most this many of the newest audit rows", Number).option("--json", "print the archive to stdout instead of writing a file").action(async (options) => {
|
|
8597
8653
|
const ctx = buildContext();
|
|
8598
8654
|
const ref = await resolveOrg(ctx, options.org);
|
|
8599
8655
|
const input = {
|
|
@@ -8706,7 +8762,7 @@ function registerArchiveCommands(program) {
|
|
|
8706
8762
|
} catch {}
|
|
8707
8763
|
fail("none of the recovery shares in this archive unwrap with that key");
|
|
8708
8764
|
});
|
|
8709
|
-
archive.command("decrypt <file>").description("decrypt an archive's secrets with your own key (offline)").option("-o, --out <dir>", "write one file per environment into this directory").option("--stdout", "print plaintext to stdout instead of writing files").option("--env <label>", "only this environment (app/env, group@env, slug, or id)").option("--format <format>", "dotenv | json | shell", "dotenv").option("--token <skt_…>", "decrypt as a service token instead of a passphrase").option("--key-file <path>", "decrypt with a private key JWK file").option("--share <file>", "custodian share for an offline quorum (repeatable)", collect$5).option("--yes", "skip the confirmation when printing plaintext to stdout").action(async (file, options) => {
|
|
8765
|
+
archive.command("decrypt <file>").description("decrypt an archive's secrets with your own key (offline)").option("-o, --out <dir>", "write one file per environment into this directory").option("--stdout", "print plaintext to stdout instead of writing files").option("--env <label>", "only this environment (app/env, group@env, slug, or id)").option("--format <format>", "dotenv | json | shell", "dotenv").option("--token <skt_…>", "decrypt as a service token instead of a passphrase").option("--key-file <path>", "decrypt with a private key JWK file").option("--share <file>", "custodian share for an offline quorum (repeatable)", collect$5).option("-y, --yes", "skip the confirmation when printing plaintext to stdout").action(async (file, options) => {
|
|
8710
8766
|
if (!options.out && !options.stdout) fail("choose a destination: --out <dir> to write files, or --stdout to print plaintext");
|
|
8711
8767
|
if (![
|
|
8712
8768
|
"dotenv",
|
|
@@ -8764,7 +8820,7 @@ function parseLimit(raw) {
|
|
|
8764
8820
|
*/
|
|
8765
8821
|
function registerAuditCommands(program) {
|
|
8766
8822
|
const audit = program.command("audit").description("read the org audit trail");
|
|
8767
|
-
audit.command("list", { isDefault: true }).alias("ls").description("show the org audit trail").option("--org <slug>").option("--limit <n>", `entries per page (max ${MAX_PAGE})`, "50").option("--action <action>", "only this action, e.g. env.key_granted").option("--resource-type <type>", "only this resource type, e.g. environment").option("--cursor <cursor>", "continue from a previous page's cursor").option("--all", "page through the whole trail, not just the first page").option("--metadata", "include each entry's metadata as JSON").option("--json", "print the raw API response").action(async (options) => {
|
|
8823
|
+
audit.command("list", { isDefault: true }).alias("ls").description("show the org audit trail").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--limit <n>", `entries per page (max ${MAX_PAGE})`, "50").option("--action <action>", "only this action, e.g. env.key_granted").option("--resource-type <type>", "only this resource type, e.g. environment").option("--cursor <cursor>", "continue from a previous page's cursor").option("--all", "page through the whole trail, not just the first page").option("--metadata", "include each entry's metadata as JSON").option("--json", "print the raw API response").action(async (options) => {
|
|
8768
8824
|
if (options.action && !AUDIT_ACTIONS.includes(options.action)) fail(`unknown action "${options.action}" — see \`seekrit audit actions\``);
|
|
8769
8825
|
const ctx = buildContext();
|
|
8770
8826
|
const ref = await resolveOrg(ctx, options.org);
|
|
@@ -8847,7 +8903,7 @@ function resolveBaseCredential(opts) {
|
|
|
8847
8903
|
function registerAwsCommands(program) {
|
|
8848
8904
|
const aws = program.command("aws").description("temporary AWS credentials (STS AssumeRole, zero-knowledge)");
|
|
8849
8905
|
const target = aws.command("target").description("manage AWS role targets");
|
|
8850
|
-
target.command("add").description("register an assumable IAM role to issue temporary credentials from").requiredOption("--name <name>", "display name, e.g. prod-deploy").requiredOption("--role-arn <arn>", "the IAM role to assume, arn:aws:iam::<acct>:role/<name>").requiredOption("--region <region>", "region whose STS endpoint to call, e.g. us-east-1").option("--org <slug>").option("--external-id <id>", "STS ExternalId the role's trust policy requires").option("--session-policy <file>", "path to an inline session policy JSON (further restricts)").option("--max-ttl <duration>", "clamp requested credential lifetime, e.g. 8h").option("--access-key-id <id>", "base IAM access key id (else AWS_ACCESS_KEY_ID)").option("--secret-access-key <secret>", "base IAM secret (else AWS_SECRET_ACCESS_KEY)").action(async (options) => {
|
|
8906
|
+
target.command("add").description("register an assumable IAM role to issue temporary credentials from").requiredOption("--name <name>", "display name, e.g. prod-deploy").requiredOption("--role-arn <arn>", "the IAM role to assume, arn:aws:iam::<acct>:role/<name>").requiredOption("--region <region>", "region whose STS endpoint to call, e.g. us-east-1").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--external-id <id>", "STS ExternalId the role's trust policy requires").option("--session-policy <file>", "path to an inline session policy JSON (further restricts)").option("--max-ttl <duration>", "clamp requested credential lifetime, e.g. 8h").option("--access-key-id <id>", "base IAM access key id (else AWS_ACCESS_KEY_ID)").option("--secret-access-key <secret>", "base IAM secret (else AWS_SECRET_ACCESS_KEY)").action(async (options) => {
|
|
8851
8907
|
const ctx = buildContext();
|
|
8852
8908
|
const org = await resolveOrg(ctx, options.org);
|
|
8853
8909
|
const sessionPolicy = options.sessionPolicy ? readFileSync(options.sessionPolicy, "utf8").trim() : void 0;
|
|
@@ -8872,7 +8928,7 @@ function registerAwsCommands(program) {
|
|
|
8872
8928
|
console.error("\nEnsure the role trusts the admin principal, then `seekrit aws lease`:\n");
|
|
8873
8929
|
console.log(awsTrustPolicyInstructions(config));
|
|
8874
8930
|
});
|
|
8875
|
-
target.command("list").description("list AWS role targets").option("--org <slug>").action(async (options) => {
|
|
8931
|
+
target.command("list").description("list AWS role targets").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (options) => {
|
|
8876
8932
|
const ctx = buildContext();
|
|
8877
8933
|
const org = await resolveOrg(ctx, options.org);
|
|
8878
8934
|
const { targets } = await ctx.client.listLeaseTargets(org.id);
|
|
@@ -8882,7 +8938,7 @@ function registerAwsCommands(program) {
|
|
|
8882
8938
|
console.log(`${t.id}\t${t.name}\t${cfg.region}\t${cfg.roleArn}`);
|
|
8883
8939
|
}
|
|
8884
8940
|
});
|
|
8885
|
-
target.command("trust <targetId>").description("reprint the IAM trust-policy setup for an AWS target").option("--org <slug>").action(async (targetId, options) => {
|
|
8941
|
+
target.command("trust <targetId>").description("reprint the IAM trust-policy setup for an AWS target").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (targetId, options) => {
|
|
8886
8942
|
const ctx = buildContext();
|
|
8887
8943
|
const org = await resolveOrg(ctx, options.org);
|
|
8888
8944
|
const { targets } = await ctx.client.listLeaseTargets(org.id);
|
|
@@ -8892,13 +8948,14 @@ function registerAwsCommands(program) {
|
|
|
8892
8948
|
if (cfg.provider !== "aws") fail("not an aws target (see `seekrit pg`/`seekrit ssh`)");
|
|
8893
8949
|
console.log(awsTrustPolicyInstructions(cfg));
|
|
8894
8950
|
});
|
|
8895
|
-
target.command("rm <targetId>").description("delete an AWS role target").option("--org <slug>").action(async (targetId, options) => {
|
|
8951
|
+
target.command("rm <targetId>").description("delete an AWS role target").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("-y, --yes", "skip the confirmation").action(async (targetId, options) => {
|
|
8896
8952
|
const ctx = buildContext();
|
|
8897
8953
|
const org = await resolveOrg(ctx, options.org);
|
|
8954
|
+
await confirmDestructive(options.yes, `Remove target ${targetId}? New leases against it stop working.`);
|
|
8898
8955
|
await ctx.client.deleteLeaseTarget(org.id, targetId);
|
|
8899
8956
|
console.error(`deleted ${targetId}`);
|
|
8900
8957
|
});
|
|
8901
|
-
aws.command("lease <target>").description("mint short-lived AWS credentials; prints ready-to-source export lines").option("--org <slug>").option("--ttl <duration>", "credential lifetime, e.g. 15m, 1h, 12h", "1h").option("--json", "print the full credential as JSON").action(async (targetRef, options) => {
|
|
8958
|
+
aws.command("lease <target>").description("mint short-lived AWS credentials; prints ready-to-source export lines").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--ttl <duration>", "credential lifetime, e.g. 15m, 1h, 12h", "1h").option("--json", "print the full credential as JSON").action(async (targetRef, options) => {
|
|
8902
8959
|
const ctx = buildContext();
|
|
8903
8960
|
const org = await resolveOrg(ctx, options.org);
|
|
8904
8961
|
const { targets } = await ctx.client.listLeaseTargets(org.id);
|
|
@@ -8928,7 +8985,7 @@ function registerAwsCommands(program) {
|
|
|
8928
8985
|
console.log(`export AWS_REGION=${cred.region}`);
|
|
8929
8986
|
}
|
|
8930
8987
|
});
|
|
8931
|
-
aws.command("leases").description("list AWS leases (the ledger — never secret material)").option("--org <slug>").action(async (options) => {
|
|
8988
|
+
aws.command("leases").description("list AWS leases (the ledger — never secret material)").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (options) => {
|
|
8932
8989
|
const ctx = buildContext();
|
|
8933
8990
|
const org = await resolveOrg(ctx, options.org);
|
|
8934
8991
|
const { leases } = await ctx.client.listLeases(org.id);
|
|
@@ -8937,9 +8994,10 @@ function registerAwsCommands(program) {
|
|
|
8937
8994
|
console.log(`${l.id}\t${l.status}\texpires ${l.expiresAt}`);
|
|
8938
8995
|
}
|
|
8939
8996
|
});
|
|
8940
|
-
aws.command("revoke <leaseId>").description("mark a lease revoked in the ledger (STS credentials stay valid until they expire)").option("--org <slug>").action(async (leaseId, options) => {
|
|
8997
|
+
aws.command("revoke <leaseId>").description("mark a lease revoked in the ledger (STS credentials stay valid until they expire)").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("-y, --yes", "skip the confirmation").action(async (leaseId, options) => {
|
|
8941
8998
|
const ctx = buildContext();
|
|
8942
8999
|
const org = await resolveOrg(ctx, options.org);
|
|
9000
|
+
await confirmDestructive(options.yes, `Revoke lease ${leaseId}? Credentials already issued stay valid until they expire.`);
|
|
8943
9001
|
await ctx.client.revokeLease(org.id, leaseId);
|
|
8944
9002
|
console.error(`revoked ${leaseId} (issued credentials remain valid until they expire)`);
|
|
8945
9003
|
});
|
|
@@ -8960,7 +9018,7 @@ function usageLine(usage) {
|
|
|
8960
9018
|
*/
|
|
8961
9019
|
function registerBillingCommands(program) {
|
|
8962
9020
|
const billing = program.command("billing").description("plan, usage, and subscription");
|
|
8963
|
-
billing.command("show", { isDefault: true }).description("show the org's plan, what it includes, and current usage").option("--org <slug>").option("--json", "print the raw API response").action(async (options) => {
|
|
9021
|
+
billing.command("show", { isDefault: true }).description("show the org's plan, what it includes, and current usage").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--json", "print the raw API response").action(async (options) => {
|
|
8964
9022
|
const ctx = buildContext();
|
|
8965
9023
|
const ref = await resolveOrg(ctx, options.org);
|
|
8966
9024
|
const info = await ctx.client.getBilling(ref.id);
|
|
@@ -8987,7 +9045,7 @@ function registerBillingCommands(program) {
|
|
|
8987
9045
|
}
|
|
8988
9046
|
});
|
|
8989
9047
|
});
|
|
8990
|
-
billing.command("entitlements").description("list every entitlement this org resolves to").option("--org <slug>").option("--json", "print the raw API response").action(async (options) => {
|
|
9048
|
+
billing.command("entitlements").description("list every entitlement this org resolves to").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--json", "print the raw API response").action(async (options) => {
|
|
8991
9049
|
const ctx = buildContext();
|
|
8992
9050
|
const ref = await resolveOrg(ctx, options.org);
|
|
8993
9051
|
const info = await ctx.client.getBilling(ref.id);
|
|
@@ -8997,7 +9055,7 @@ function registerBillingCommands(program) {
|
|
|
8997
9055
|
col("source", (e) => e.source)
|
|
8998
9056
|
]));
|
|
8999
9057
|
});
|
|
9000
|
-
billing.command("checkout <family>").description(`start a self-serve upgrade (${VISIBLE_PLAN_FAMILY_IDS.join(" | ")}) — prints a URL`).option("--org <slug>").action(async (family, options) => {
|
|
9058
|
+
billing.command("checkout <family>").description(`start a self-serve upgrade (${VISIBLE_PLAN_FAMILY_IDS.join(" | ")}) — prints a URL`).option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (family, options) => {
|
|
9001
9059
|
if (!PLAN_FAMILY_IDS.includes(family)) fail(`unknown plan "${family}" — one of: ${PLAN_FAMILY_IDS.join(", ")}`);
|
|
9002
9060
|
const ctx = buildContext();
|
|
9003
9061
|
const ref = await resolveOrg(ctx, options.org);
|
|
@@ -9005,14 +9063,14 @@ function registerBillingCommands(program) {
|
|
|
9005
9063
|
console.error("open this to complete checkout:");
|
|
9006
9064
|
console.log(url);
|
|
9007
9065
|
});
|
|
9008
|
-
billing.command("portal").description("open the billing portal (prints a URL) to manage payment and invoices").option("--org <slug>").action(async (options) => {
|
|
9066
|
+
billing.command("portal").description("open the billing portal (prints a URL) to manage payment and invoices").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (options) => {
|
|
9009
9067
|
const ctx = buildContext();
|
|
9010
9068
|
const ref = await resolveOrg(ctx, options.org);
|
|
9011
9069
|
const { url } = await ctx.client.openBillingPortal(ref.id);
|
|
9012
9070
|
console.error("open this to manage billing:");
|
|
9013
9071
|
console.log(url);
|
|
9014
9072
|
});
|
|
9015
|
-
billing.command("cancel").description("cancel the subscription and drop back to the Free plan").option("--org <slug>").option("--yes", "skip the confirmation prompt").action(async (options) => {
|
|
9073
|
+
billing.command("cancel").description("cancel the subscription and drop back to the Free plan").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("-y, --yes", "skip the confirmation prompt").action(async (options) => {
|
|
9016
9074
|
const ctx = buildContext();
|
|
9017
9075
|
const ref = await resolveOrg(ctx, options.org);
|
|
9018
9076
|
await confirmDestructive(options.yes, `Cancel ${ref.slug}'s subscription and move it to the Free plan?`);
|
|
@@ -9055,7 +9113,7 @@ async function resolveBranchParent(ctx, opts) {
|
|
|
9055
9113
|
*/
|
|
9056
9114
|
function registerBranchCommands(program) {
|
|
9057
9115
|
const branch = program.command("branch").description("ephemeral per-PR / preview configs layered on an environment");
|
|
9058
|
-
branch.command("create <slug>").description("fork an environment into an ephemeral branch (inherits its secrets)").option("--org <slug>").option("--app <slug>", "application slug (defaults to seekrit.json)").requiredOption("--from <env>", "the environment to branch").option("--name <name>", "display name (defaults to the slug)").option("--ttl <duration>", "lifetime: 12h, 7d, 2w, … or `never`", "7d").option("--no-share", "don't give the parent's other readers access to this branch").action(async (slug, options) => {
|
|
9116
|
+
branch.command("create <slug>").description("fork an environment into an ephemeral branch (inherits its secrets)").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--app <slug>", "application slug (defaults to seekrit.json)").requiredOption("--from <env>", "the environment to branch").option("--name <name>", "display name (defaults to the slug)").option("--ttl <duration>", "lifetime: 12h, 7d, 2w, … or `never`", "7d").option("--no-share", "don't give the parent's other readers access to this branch").action(async (slug, options) => {
|
|
9059
9117
|
const ctx = buildContext();
|
|
9060
9118
|
const parent = await resolveBranchParent(ctx, {
|
|
9061
9119
|
org: options.org,
|
|
@@ -9093,7 +9151,7 @@ function registerBranchCommands(program) {
|
|
|
9093
9151
|
console.error(created.branch.expiresAt ? `expires ${created.branch.expiresAt}` : "no expiry — delete it explicitly when the PR closes");
|
|
9094
9152
|
if (grants.length > 0) console.error(`shared with ${grants.length} other reader(s)`);
|
|
9095
9153
|
});
|
|
9096
|
-
branch.command("list").alias("ls").description("list branches in an application (or of one environment)").option("--org <slug>").option("--app <slug>", "application slug (defaults to seekrit.json)").option("--env <slug>", "only branches of this environment").option("--json", "print the raw API response").action(async (options) => {
|
|
9154
|
+
branch.command("list").alias("ls").description("list branches in an application (or of one environment)").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--app <slug>", "application slug (defaults to seekrit.json)").option("--env <slug>", "only branches of this environment").option("--json", "print the raw API response").action(async (options) => {
|
|
9097
9155
|
const ctx = buildContext();
|
|
9098
9156
|
const branches = options.env ? await (async () => {
|
|
9099
9157
|
const parent = await resolveAppEnv(ctx, options);
|
|
@@ -9109,10 +9167,11 @@ function registerBranchCommands(program) {
|
|
|
9109
9167
|
col("id", (b) => b.id)
|
|
9110
9168
|
], "no branches — create one with `seekrit branch create`"));
|
|
9111
9169
|
});
|
|
9112
|
-
branch.command("delete <slug>").alias("rm").description("tear down a branch and everything it overrode").option("--org <slug>").option("--app <slug>", "application slug (defaults to seekrit.json)").action(async (slug, options) => {
|
|
9170
|
+
branch.command("delete <slug>").alias("rm").description("tear down a branch and everything it overrode").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--app <slug>", "application slug (defaults to seekrit.json)").option("-y, --yes", "skip the confirmation").action(async (slug, options) => {
|
|
9113
9171
|
const ctx = buildContext();
|
|
9114
9172
|
const app = await resolveApp(ctx, options);
|
|
9115
9173
|
const target = await resolveBranch(ctx, app, slug);
|
|
9174
|
+
await confirmDestructive(options.yes, `Tear down branch ${app.slug}#${target.slug} and every override in it?`);
|
|
9116
9175
|
await ctx.client.deleteBranch(app.orgId, target.id);
|
|
9117
9176
|
console.error(`deleted branch ${app.slug}#${target.slug}`);
|
|
9118
9177
|
});
|
|
@@ -9325,7 +9384,7 @@ function resolveServiceAccountKey(opts) {
|
|
|
9325
9384
|
function registerGcpCommands(program) {
|
|
9326
9385
|
const gcp = program.command("gcp").description("temporary GCP credentials (IAM generateAccessToken, zero-knowledge)");
|
|
9327
9386
|
const target = gcp.command("target").description("manage GCP service-account targets");
|
|
9328
|
-
target.command("add").description("register an impersonable service account to issue temporary tokens from").requiredOption("--name <name>", "display name, e.g. prod-deploy").requiredOption("--service-account <email>", "the service account to impersonate, name@project.iam.gserviceaccount.com").option("--org <slug>").option("--scope <scope>", "OAuth scope to grant (repeatable; default cloud-platform)", collectList$1).option("--delegate <email>", "delegation-chain service account (repeatable)", collectList$1).option("--max-ttl <duration>", "clamp requested token lifetime, e.g. 1h").option("--key-file <path>", "source SA key JSON (else GOOGLE_APPLICATION_CREDENTIALS)").action(async (options) => {
|
|
9387
|
+
target.command("add").description("register an impersonable service account to issue temporary tokens from").requiredOption("--name <name>", "display name, e.g. prod-deploy").requiredOption("--service-account <email>", "the service account to impersonate, name@project.iam.gserviceaccount.com").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--scope <scope>", "OAuth scope to grant (repeatable; default cloud-platform)", collectList$1).option("--delegate <email>", "delegation-chain service account (repeatable)", collectList$1).option("--max-ttl <duration>", "clamp requested token lifetime, e.g. 1h").option("--key-file <path>", "source SA key JSON (else GOOGLE_APPLICATION_CREDENTIALS)").action(async (options) => {
|
|
9329
9388
|
const ctx = buildContext();
|
|
9330
9389
|
const org = await resolveOrg(ctx, options.org);
|
|
9331
9390
|
const config = {
|
|
@@ -9348,7 +9407,7 @@ function registerGcpCommands(program) {
|
|
|
9348
9407
|
console.error("\nGrant the source SA the token-creator role, then `seekrit gcp lease`:\n");
|
|
9349
9408
|
console.log(gcpSetupInstructions(config));
|
|
9350
9409
|
});
|
|
9351
|
-
target.command("list").description("list GCP service-account targets").option("--org <slug>").action(async (options) => {
|
|
9410
|
+
target.command("list").description("list GCP service-account targets").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (options) => {
|
|
9352
9411
|
const ctx = buildContext();
|
|
9353
9412
|
const org = await resolveOrg(ctx, options.org);
|
|
9354
9413
|
const { targets } = await ctx.client.listLeaseTargets(org.id);
|
|
@@ -9358,7 +9417,7 @@ function registerGcpCommands(program) {
|
|
|
9358
9417
|
console.log(`${t.id}\t${t.name}\t${cfg.serviceAccount}`);
|
|
9359
9418
|
}
|
|
9360
9419
|
});
|
|
9361
|
-
target.command("setup <targetId>").description("reprint the IAM setup for a GCP target").option("--org <slug>").action(async (targetId, options) => {
|
|
9420
|
+
target.command("setup <targetId>").description("reprint the IAM setup for a GCP target").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (targetId, options) => {
|
|
9362
9421
|
const ctx = buildContext();
|
|
9363
9422
|
const org = await resolveOrg(ctx, options.org);
|
|
9364
9423
|
const { targets } = await ctx.client.listLeaseTargets(org.id);
|
|
@@ -9368,13 +9427,14 @@ function registerGcpCommands(program) {
|
|
|
9368
9427
|
if (cfg.provider !== "gcp") fail("not a gcp target (see `seekrit aws`/`seekrit ssh`)");
|
|
9369
9428
|
console.log(gcpSetupInstructions(cfg));
|
|
9370
9429
|
});
|
|
9371
|
-
target.command("rm <targetId>").description("delete a GCP service-account target").option("--org <slug>").action(async (targetId, options) => {
|
|
9430
|
+
target.command("rm <targetId>").description("delete a GCP service-account target").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("-y, --yes", "skip the confirmation").action(async (targetId, options) => {
|
|
9372
9431
|
const ctx = buildContext();
|
|
9373
9432
|
const org = await resolveOrg(ctx, options.org);
|
|
9433
|
+
await confirmDestructive(options.yes, `Remove target ${targetId}? New leases against it stop working.`);
|
|
9374
9434
|
await ctx.client.deleteLeaseTarget(org.id, targetId);
|
|
9375
9435
|
console.error(`deleted ${targetId}`);
|
|
9376
9436
|
});
|
|
9377
|
-
gcp.command("lease <target>").description("mint a short-lived GCP access token; prints ready-to-source export lines").option("--org <slug>").option("--ttl <duration>", "token lifetime, e.g. 15m, 1h", "1h").option("--json", "print the full credential as JSON").action(async (targetRef, options) => {
|
|
9437
|
+
gcp.command("lease <target>").description("mint a short-lived GCP access token; prints ready-to-source export lines").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--ttl <duration>", "token lifetime, e.g. 15m, 1h", "1h").option("--json", "print the full credential as JSON").action(async (targetRef, options) => {
|
|
9378
9438
|
const ctx = buildContext();
|
|
9379
9439
|
const org = await resolveOrg(ctx, options.org);
|
|
9380
9440
|
const { targets } = await ctx.client.listLeaseTargets(org.id);
|
|
@@ -9399,7 +9459,7 @@ function registerGcpCommands(program) {
|
|
|
9399
9459
|
console.log(`export GOOGLE_OAUTH_ACCESS_TOKEN=${cred.accessToken}`);
|
|
9400
9460
|
}
|
|
9401
9461
|
});
|
|
9402
|
-
gcp.command("leases").description("list GCP leases (the ledger — never secret material)").option("--org <slug>").action(async (options) => {
|
|
9462
|
+
gcp.command("leases").description("list GCP leases (the ledger — never secret material)").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (options) => {
|
|
9403
9463
|
const ctx = buildContext();
|
|
9404
9464
|
const org = await resolveOrg(ctx, options.org);
|
|
9405
9465
|
const { leases } = await ctx.client.listLeases(org.id);
|
|
@@ -9408,9 +9468,10 @@ function registerGcpCommands(program) {
|
|
|
9408
9468
|
console.log(`${l.id}\t${l.status}\texpires ${l.expiresAt}`);
|
|
9409
9469
|
}
|
|
9410
9470
|
});
|
|
9411
|
-
gcp.command("revoke <leaseId>").description("mark a lease revoked in the ledger (tokens stay valid until they expire)").option("--org <slug>").action(async (leaseId, options) => {
|
|
9471
|
+
gcp.command("revoke <leaseId>").description("mark a lease revoked in the ledger (tokens stay valid until they expire)").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("-y, --yes", "skip the confirmation").action(async (leaseId, options) => {
|
|
9412
9472
|
const ctx = buildContext();
|
|
9413
9473
|
const org = await resolveOrg(ctx, options.org);
|
|
9474
|
+
await confirmDestructive(options.yes, `Revoke lease ${leaseId}? Tokens already issued stay valid until they expire.`);
|
|
9414
9475
|
await ctx.client.revokeLease(org.id, leaseId);
|
|
9415
9476
|
console.error(`revoked ${leaseId} (issued tokens remain valid until they expire)`);
|
|
9416
9477
|
});
|
|
@@ -9424,7 +9485,7 @@ function registerGcpCommands(program) {
|
|
|
9424
9485
|
*/
|
|
9425
9486
|
function registerGroupCommands(program) {
|
|
9426
9487
|
const group = program.command("group").description("manage shared groups (reusable secret bags)");
|
|
9427
|
-
group.command("list").alias("ls").description("list shared groups in an organization").option("--org <slug>").option("--json", "print the raw API response").action(async (options) => {
|
|
9488
|
+
group.command("list").alias("ls").description("list shared groups in an organization").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--json", "print the raw API response").action(async (options) => {
|
|
9428
9489
|
const ctx = buildContext();
|
|
9429
9490
|
const ref = await resolveOrg(ctx, options.org);
|
|
9430
9491
|
const { groups } = await ctx.client.listGroups(ref.id);
|
|
@@ -9435,7 +9496,7 @@ function registerGroupCommands(program) {
|
|
|
9435
9496
|
col("id", (g) => g.id)
|
|
9436
9497
|
], "no groups — create one with `seekrit group create`"));
|
|
9437
9498
|
});
|
|
9438
|
-
group.command("show <slug>").description("show a group and the environments (value sets) it holds").option("--org <slug>").option("--json", "print the raw API response").action(async (slug, options) => {
|
|
9499
|
+
group.command("show <slug>").description("show a group and the environments (value sets) it holds").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--json", "print the raw API response").action(async (slug, options) => {
|
|
9439
9500
|
const ctx = buildContext();
|
|
9440
9501
|
const ref = await resolveGroup(ctx, {
|
|
9441
9502
|
org: options.org,
|
|
@@ -9461,7 +9522,7 @@ function registerGroupCommands(program) {
|
|
|
9461
9522
|
], "no environments — create one with `seekrit group env create`");
|
|
9462
9523
|
});
|
|
9463
9524
|
});
|
|
9464
|
-
group.command("create").description("create a shared group").option("--org <slug>").requiredOption("--name <name>").requiredOption("--slug <slug>").action(async (options) => {
|
|
9525
|
+
group.command("create").description("create a shared group").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").requiredOption("--name <name>", "display name").requiredOption("--slug <slug>", "url-safe identifier (permanent)").action(async (options) => {
|
|
9465
9526
|
const ctx = buildContext();
|
|
9466
9527
|
const orgRef = await resolveOrg(ctx, options.org);
|
|
9467
9528
|
const created = await ctx.client.createGroup(orgRef.id, {
|
|
@@ -9470,7 +9531,7 @@ function registerGroupCommands(program) {
|
|
|
9470
9531
|
});
|
|
9471
9532
|
console.error(`created group ${created.group.slug} (${created.group.id})`);
|
|
9472
9533
|
});
|
|
9473
|
-
group.command("rename <slug>").description("change a group's display name (the slug is permanent)").option("--org <slug>").requiredOption("--name <name>", "new display name").action(async (slug, options) => {
|
|
9534
|
+
group.command("rename <slug>").description("change a group's display name (the slug is permanent)").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").requiredOption("--name <name>", "new display name").action(async (slug, options) => {
|
|
9474
9535
|
const ctx = buildContext();
|
|
9475
9536
|
const ref = await resolveGroup(ctx, {
|
|
9476
9537
|
org: options.org,
|
|
@@ -9479,7 +9540,7 @@ function registerGroupCommands(program) {
|
|
|
9479
9540
|
const { group: row } = await ctx.client.updateGroup(ref.orgId, ref.id, { name: options.name });
|
|
9480
9541
|
console.error(`renamed ${row.slug} to "${row.name}"`);
|
|
9481
9542
|
});
|
|
9482
|
-
group.command("rm <slug>").alias("delete").description("delete a group, its environments, and their secrets").option("--org <slug>").option("--yes", "skip the confirmation prompt").action(async (slug, options) => {
|
|
9543
|
+
group.command("rm <slug>").alias("delete").description("delete a group, its environments, and their secrets").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("-y, --yes", "skip the confirmation prompt").action(async (slug, options) => {
|
|
9483
9544
|
const ctx = buildContext();
|
|
9484
9545
|
const ref = await resolveGroup(ctx, {
|
|
9485
9546
|
org: options.org,
|
|
@@ -9491,7 +9552,7 @@ function registerGroupCommands(program) {
|
|
|
9491
9552
|
console.error(`deleted group ${ref.slug}`);
|
|
9492
9553
|
});
|
|
9493
9554
|
const groupEnv = group.command("env").description("manage a group’s environments (per-slug value sets / variants)");
|
|
9494
|
-
groupEnv.command("list").alias("ls").description("list a group's environments").option("--org <slug>").requiredOption("--group <slug>").option("--json", "print the raw API response").action(async (options) => {
|
|
9555
|
+
groupEnv.command("list").alias("ls").description("list a group's environments").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").requiredOption("--group <slug>", "group slug").option("--json", "print the raw API response").action(async (options) => {
|
|
9495
9556
|
const ctx = buildContext();
|
|
9496
9557
|
const ref = await resolveGroup(ctx, options);
|
|
9497
9558
|
const { environments } = await ctx.client.listGroupEnvs(ref.orgId, ref.id);
|
|
@@ -9502,7 +9563,7 @@ function registerGroupCommands(program) {
|
|
|
9502
9563
|
col("id", (e) => e.id)
|
|
9503
9564
|
], "no environments — create one with `seekrit group env create`"));
|
|
9504
9565
|
});
|
|
9505
|
-
groupEnv.command("create").description("create a group environment (generates its data key locally)").option("--org <slug>").requiredOption("--group <slug>").requiredOption("--name <name>").requiredOption("--slug <slug>").action(async (options) => {
|
|
9566
|
+
groupEnv.command("create").description("create a group environment (generates its data key locally)").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").requiredOption("--group <slug>", "group slug").requiredOption("--name <name>", "display name").requiredOption("--slug <slug>", "url-safe identifier (permanent)").action(async (options) => {
|
|
9506
9567
|
const ctx = buildContext();
|
|
9507
9568
|
const groupRef = await resolveGroup(ctx, {
|
|
9508
9569
|
org: options.org,
|
|
@@ -9534,7 +9595,7 @@ function registerGroupCommands(program) {
|
|
|
9534
9595
|
*/
|
|
9535
9596
|
function registerHoneyTokenCommands(program) {
|
|
9536
9597
|
const honey = program.command("honey-token").description("plant decoy credentials that alert when anyone tries to use them");
|
|
9537
|
-
honey.command("create").description("mint a decoy credential; prints it once").requiredOption("--name <name>", "display name, e.g. legacy-ci-bait").option("--org <slug>").option("--placement <note>", "where you're planting it (echoed in the alert email)").action(async (options) => {
|
|
9598
|
+
honey.command("create").description("mint a decoy credential; prints it once").requiredOption("--name <name>", "display name, e.g. legacy-ci-bait").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--placement <note>", "where you're planting it (echoed in the alert email)").action(async (options) => {
|
|
9538
9599
|
const ctx = buildContext();
|
|
9539
9600
|
const orgRef = await resolveOrg(ctx, options.org);
|
|
9540
9601
|
const created = await createHoneyToken();
|
|
@@ -9547,7 +9608,7 @@ function registerHoneyTokenCommands(program) {
|
|
|
9547
9608
|
console.error("decoy created — save it now, it is not stored. Plant it somewhere a thief would look, NOT anywhere your own tooling reads: a deploy script that tries it by mistake trips the alarm just as loudly. It grants nothing.");
|
|
9548
9609
|
console.log(created.token);
|
|
9549
9610
|
});
|
|
9550
|
-
honey.command("list").alias("ls").description("list decoy credentials and whether any have been tripped").option("--org <slug>").option("--json", "print the raw API response").action(async (options) => {
|
|
9611
|
+
honey.command("list").alias("ls").description("list decoy credentials and whether any have been tripped").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--json", "print the raw API response").action(async (options) => {
|
|
9551
9612
|
const ctx = buildContext();
|
|
9552
9613
|
const orgRef = await resolveOrg(ctx, options.org);
|
|
9553
9614
|
const { honeyTokens } = await ctx.client.listHoneyTokens(orgRef.id);
|
|
@@ -9560,7 +9621,7 @@ function registerHoneyTokenCommands(program) {
|
|
|
9560
9621
|
col("id", (t) => t.id)
|
|
9561
9622
|
], "no decoys planted — create one with `seekrit honey-token create`"));
|
|
9562
9623
|
});
|
|
9563
|
-
honey.command("delete <honeyTokenId>").alias("rm").description("delete a decoy (stops it alerting)").option("--org <slug>").option("--yes", "skip the confirmation prompt").action(async (honeyTokenId, options) => {
|
|
9624
|
+
honey.command("delete <honeyTokenId>").alias("rm").description("delete a decoy (stops it alerting)").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("-y, --yes", "skip the confirmation prompt").action(async (honeyTokenId, options) => {
|
|
9564
9625
|
const ctx = buildContext();
|
|
9565
9626
|
const orgRef = await resolveOrg(ctx, options.org);
|
|
9566
9627
|
await confirmDestructive(options.yes, `Delete ${honeyTokenId}? Wherever you planted it goes back to being unwatched — pull the bait too.`);
|
|
@@ -9584,7 +9645,7 @@ function collectHeader(value, acc = {}) {
|
|
|
9584
9645
|
*/
|
|
9585
9646
|
function registerLogSinkCommands(program) {
|
|
9586
9647
|
const sink = program.command("log-sink").description("stream the audit trail to your own OTLP collector (SIEM)");
|
|
9587
|
-
sink.command("show", { isDefault: true }).description("show the configured log sink and its delivery health").option("--org <slug>").option("--json", "print the raw API response").action(async (options) => {
|
|
9648
|
+
sink.command("show", { isDefault: true }).description("show the configured log sink and its delivery health").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--json", "print the raw API response").action(async (options) => {
|
|
9588
9649
|
const ctx = buildContext();
|
|
9589
9650
|
const ref = await resolveOrg(ctx, options.org);
|
|
9590
9651
|
const { sink: config } = await ctx.client.getLogSink(ref.id);
|
|
@@ -9603,7 +9664,7 @@ function registerLogSinkCommands(program) {
|
|
|
9603
9664
|
]);
|
|
9604
9665
|
});
|
|
9605
9666
|
});
|
|
9606
|
-
sink.command("set <endpoint>").description("point the audit export at an OTLP/HTTP logs endpoint").option("--org <slug>").option("--header <name: value>", "auth header to send (repeatable; values are write-only)", collectHeader).option("--clear-headers", "send no headers at all (drops the stored ones)").option("--disabled", "save the config but stop shipping").action(async (endpoint, options) => {
|
|
9667
|
+
sink.command("set <endpoint>").description("point the audit export at an OTLP/HTTP logs endpoint").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--header <name: value>", "auth header to send (repeatable; values are write-only)", collectHeader).option("--clear-headers", "send no headers at all (drops the stored ones)").option("--disabled", "save the config but stop shipping").action(async (endpoint, options) => {
|
|
9607
9668
|
if (options.header && options.clearHeaders) fail("pass either --header or --clear-headers, not both");
|
|
9608
9669
|
const ctx = buildContext();
|
|
9609
9670
|
const ref = await resolveOrg(ctx, options.org);
|
|
@@ -9615,7 +9676,7 @@ function registerLogSinkCommands(program) {
|
|
|
9615
9676
|
});
|
|
9616
9677
|
console.error(`log sink → ${config.endpoint} (${config.enabled ? "enabled" : "disabled"}) — test it with \`seekrit log-sink test\``);
|
|
9617
9678
|
});
|
|
9618
|
-
sink.command("test").description("send a probe to the configured endpoint and report the result").option("--org <slug>").option("--json", "print the raw API response").action(async (options) => {
|
|
9679
|
+
sink.command("test").description("send a probe to the configured endpoint and report the result").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--json", "print the raw API response").action(async (options) => {
|
|
9619
9680
|
const ctx = buildContext();
|
|
9620
9681
|
const ref = await resolveOrg(ctx, options.org);
|
|
9621
9682
|
const result = await ctx.client.testLogSink(ref.id);
|
|
@@ -9628,7 +9689,7 @@ function registerLogSinkCommands(program) {
|
|
|
9628
9689
|
});
|
|
9629
9690
|
if (!result.ok) process.exitCode = 1;
|
|
9630
9691
|
});
|
|
9631
|
-
sink.command("rm").alias("delete").description("stop exporting the audit trail and forget the endpoint").option("--org <slug>").option("--yes", "skip the confirmation prompt").action(async (options) => {
|
|
9692
|
+
sink.command("rm").alias("delete").description("stop exporting the audit trail and forget the endpoint").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("-y, --yes", "skip the confirmation prompt").action(async (options) => {
|
|
9632
9693
|
const ctx = buildContext();
|
|
9633
9694
|
const ref = await resolveOrg(ctx, options.org);
|
|
9634
9695
|
await confirmDestructive(options.yes, `Remove ${ref.slug}'s audit log export?`);
|
|
@@ -9762,7 +9823,7 @@ function resolveAdminUri(uri) {
|
|
|
9762
9823
|
function registerMongoCommands(program) {
|
|
9763
9824
|
const mongo = program.command("mongodb").description("temporary MongoDB credentials (createUser, zero-knowledge delivery)");
|
|
9764
9825
|
const target = mongo.command("target").description("manage MongoDB targets");
|
|
9765
|
-
target.command("add").description("register a MongoDB cluster to issue temporary credentials from").requiredOption("--name <name>", "display name, e.g. prod-app").requiredOption("--database <db>", "the database leased users get access to, e.g. app").option("--uri <uri>", "admin connection string (else SEEKRIT_MONGODB_ADMIN_URL)").option("--org <slug>").option("--access <level>", "readonly | readwrite | custom", "readonly").option("--role <role@db>", "grant for a custom target (repeatable)", collect$4, []).option("--auth-source <db>", "authentication database (default admin)").option("--max-ttl <duration>", "clamp requested credential lifetime, e.g. 8h").option("--no-tls", "disable TLS to the cluster (TLS is on by default)").action(async (options) => {
|
|
9826
|
+
target.command("add").description("register a MongoDB cluster to issue temporary credentials from").requiredOption("--name <name>", "display name, e.g. prod-app").requiredOption("--database <db>", "the database leased users get access to, e.g. app").option("--uri <uri>", "admin connection string (else SEEKRIT_MONGODB_ADMIN_URL)").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--access <level>", "readonly | readwrite | custom", "readonly").option("--role <role@db>", "grant for a custom target (repeatable)", collect$4, []).option("--auth-source <db>", "authentication database (default admin)").option("--max-ttl <duration>", "clamp requested credential lifetime, e.g. 8h").option("--no-tls", "disable TLS to the cluster (TLS is on by default)").action(async (options) => {
|
|
9766
9827
|
const ctx = buildContext();
|
|
9767
9828
|
const org = await resolveOrg(ctx, options.org);
|
|
9768
9829
|
const adminUri = resolveAdminUri(options.uri);
|
|
@@ -9793,7 +9854,7 @@ function registerMongoCommands(program) {
|
|
|
9793
9854
|
console.error("\nEnsure a provisioning user exists, then `seekrit mongodb lease`:\n");
|
|
9794
9855
|
console.log(mongoAdminSetupInstructions(config));
|
|
9795
9856
|
});
|
|
9796
|
-
target.command("list").description("list MongoDB targets").option("--org <slug>").action(async (options) => {
|
|
9857
|
+
target.command("list").description("list MongoDB targets").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (options) => {
|
|
9797
9858
|
const ctx = buildContext();
|
|
9798
9859
|
const org = await resolveOrg(ctx, options.org);
|
|
9799
9860
|
const { targets } = await ctx.client.listLeaseTargets(org.id);
|
|
@@ -9804,13 +9865,14 @@ function registerMongoCommands(program) {
|
|
|
9804
9865
|
console.log(`${t.id}\t${t.name}\t${host}\t${cfg.connection.database}\t${cfg.accessLevel ?? "readonly"}`);
|
|
9805
9866
|
}
|
|
9806
9867
|
});
|
|
9807
|
-
target.command("rm <targetId>").description("delete a MongoDB target").option("--org <slug>").action(async (targetId, options) => {
|
|
9868
|
+
target.command("rm <targetId>").description("delete a MongoDB target").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("-y, --yes", "skip the confirmation").action(async (targetId, options) => {
|
|
9808
9869
|
const ctx = buildContext();
|
|
9809
9870
|
const org = await resolveOrg(ctx, options.org);
|
|
9871
|
+
await confirmDestructive(options.yes, `Remove target ${targetId}? New leases against it stop working.`);
|
|
9810
9872
|
await ctx.client.deleteLeaseTarget(org.id, targetId);
|
|
9811
9873
|
console.error(`deleted ${targetId}`);
|
|
9812
9874
|
});
|
|
9813
|
-
mongo.command("lease <target>").description("mint short-lived MongoDB credentials; prints a ready-to-use connection URI").option("--org <slug>").option("--ttl <duration>", "credential lifetime, e.g. 30m, 1h, 8h", "1h").option("--json", "print the full credential as JSON").action(async (targetRef, options) => {
|
|
9875
|
+
mongo.command("lease <target>").description("mint short-lived MongoDB credentials; prints a ready-to-use connection URI").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--ttl <duration>", "credential lifetime, e.g. 30m, 1h, 8h", "1h").option("--json", "print the full credential as JSON").action(async (targetRef, options) => {
|
|
9814
9876
|
const ctx = buildContext();
|
|
9815
9877
|
const org = await resolveOrg(ctx, options.org);
|
|
9816
9878
|
const { targets } = await ctx.client.listLeaseTargets(org.id);
|
|
@@ -9829,7 +9891,7 @@ function registerMongoCommands(program) {
|
|
|
9829
9891
|
if (options.json) console.log(JSON.stringify(cred, null, 2));
|
|
9830
9892
|
else console.log(`export MONGODB_URI='${cred.uri}'`);
|
|
9831
9893
|
});
|
|
9832
|
-
mongo.command("leases").description("list MongoDB leases (the ledger — never secret material)").option("--org <slug>").action(async (options) => {
|
|
9894
|
+
mongo.command("leases").description("list MongoDB leases (the ledger — never secret material)").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (options) => {
|
|
9833
9895
|
const ctx = buildContext();
|
|
9834
9896
|
const org = await resolveOrg(ctx, options.org);
|
|
9835
9897
|
const { leases } = await ctx.client.listLeases(org.id);
|
|
@@ -9838,9 +9900,10 @@ function registerMongoCommands(program) {
|
|
|
9838
9900
|
console.log(`${l.id}\t${l.status}\texpires ${l.expiresAt}`);
|
|
9839
9901
|
}
|
|
9840
9902
|
});
|
|
9841
|
-
mongo.command("revoke <leaseId>").description("revoke a lease now (drops the MongoDB user immediately)").option("--org <slug>").action(async (leaseId, options) => {
|
|
9903
|
+
mongo.command("revoke <leaseId>").description("revoke a lease now (drops the MongoDB user immediately)").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("-y, --yes", "skip the confirmation").action(async (leaseId, options) => {
|
|
9842
9904
|
const ctx = buildContext();
|
|
9843
9905
|
const org = await resolveOrg(ctx, options.org);
|
|
9906
|
+
await confirmDestructive(options.yes, `Revoke lease ${leaseId} now? Its MongoDB user is dropped immediately.`);
|
|
9844
9907
|
await ctx.client.revokeLease(org.id, leaseId);
|
|
9845
9908
|
console.error(`revoked ${leaseId} (the MongoDB user has been dropped)`);
|
|
9846
9909
|
});
|
|
@@ -9922,7 +9985,7 @@ function generateUserName$1(prefix = "tmp") {
|
|
|
9922
9985
|
function registerMysqlCommands(program) {
|
|
9923
9986
|
const mysql = program.command("mysql").description("temporary MySQL/MariaDB credentials (short-lived, zero-knowledge)");
|
|
9924
9987
|
const target = mysql.command("target").description("manage provisioning targets");
|
|
9925
|
-
target.command("add").description("register a MySQL/MariaDB server to lease credentials from").requiredOption("--name <name>", "display name, e.g. prod-db").option("--org <slug>").requiredOption("--host <host>", "database host").option("--port <port>", "database port", "3306").requiredOption("--database <name>", "database to grant access to").option("--access <level>", "readonly | readwrite | custom", "readonly").option("--user-host <host>", "host part of created accounts ('name'@'<host>')", "%").option("--executor <mode>", "in_do | remote", "in_do").option("--provisioner-url <url>", "customer provisioner URL (remote executor)").option("--hmac-key <base64>", "shared HMAC key for the remote executor (or set SEEKRIT_PROVISIONER_HMAC_KEY); `seekrit provisioner keygen` mints one").option("--admin-url <url>", "in_do: admin mysql:// connection string (or set SEEKRIT_MYSQL_ADMIN_URL); wrapped locally").option("--create-statement <sql>", "custom CREATE template (repeatable)", collect$3, []).option("--revoke-statement <sql>", "custom REVOKE template (repeatable)", collect$3, []).action(async (options) => {
|
|
9988
|
+
target.command("add").description("register a MySQL/MariaDB server to lease credentials from").requiredOption("--name <name>", "display name, e.g. prod-db").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").requiredOption("--host <host>", "database host").option("--port <port>", "database port", "3306").requiredOption("--database <name>", "database to grant access to").option("--access <level>", "readonly | readwrite | custom", "readonly").option("--user-host <host>", "host part of created accounts ('name'@'<host>')", "%").option("--executor <mode>", "in_do | remote", "in_do").option("--provisioner-url <url>", "customer provisioner URL (remote executor)").option("--hmac-key <base64>", "shared HMAC key for the remote executor (or set SEEKRIT_PROVISIONER_HMAC_KEY); `seekrit provisioner keygen` mints one").option("--admin-url <url>", "in_do: admin mysql:// connection string (or set SEEKRIT_MYSQL_ADMIN_URL); wrapped locally").option("--create-statement <sql>", "custom CREATE template (repeatable)", collect$3, []).option("--revoke-statement <sql>", "custom REVOKE template (repeatable)", collect$3, []).action(async (options) => {
|
|
9926
9989
|
const ctx = buildContext();
|
|
9927
9990
|
const org = await resolveOrg(ctx, options.org);
|
|
9928
9991
|
const executor = options.executor === "remote" ? "remote" : "in_do";
|
|
@@ -9964,7 +10027,7 @@ function registerMysqlCommands(program) {
|
|
|
9964
10027
|
});
|
|
9965
10028
|
console.error(`registered ${accessLevel} target ${created.name} (${created.id})`);
|
|
9966
10029
|
});
|
|
9967
|
-
target.command("list").description("list provisioning targets").option("--org <slug>").action(async (options) => {
|
|
10030
|
+
target.command("list").description("list provisioning targets").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (options) => {
|
|
9968
10031
|
const ctx = buildContext();
|
|
9969
10032
|
const org = await resolveOrg(ctx, options.org);
|
|
9970
10033
|
const { targets } = await ctx.client.listLeaseTargets(org.id);
|
|
@@ -9974,13 +10037,14 @@ function registerMysqlCommands(program) {
|
|
|
9974
10037
|
console.log(`${t.id}\t${t.name}\t${cfg.connection.host}:${cfg.connection.port}/${cfg.connection.database}\t${cfg.accessLevel ?? "custom"}\t${cfg.executor}`);
|
|
9975
10038
|
}
|
|
9976
10039
|
});
|
|
9977
|
-
target.command("rm <targetId>").description("remove a provisioning target").option("--org <slug>").action(async (targetId, options) => {
|
|
10040
|
+
target.command("rm <targetId>").description("remove a provisioning target").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("-y, --yes", "skip the confirmation").action(async (targetId, options) => {
|
|
9978
10041
|
const ctx = buildContext();
|
|
9979
10042
|
const org = await resolveOrg(ctx, options.org);
|
|
10043
|
+
await confirmDestructive(options.yes, `Remove target ${targetId}? New leases against it stop working.`);
|
|
9980
10044
|
await ctx.client.deleteLeaseTarget(org.id, targetId);
|
|
9981
10045
|
console.error(`removed ${targetId}`);
|
|
9982
10046
|
});
|
|
9983
|
-
mysql.command("lease <target>").description("mint a temporary credential; prints a ready-to-use connection URL").option("--org <slug>").option("--user <name>", "user name to create (default: a random tmp_ name)").option("--ttl <duration>", "lifetime, e.g. 30m, 1h, 7d", "1h").option("--json", "print the full connection as JSON").action(async (targetRef, options) => {
|
|
10047
|
+
mysql.command("lease <target>").description("mint a temporary credential; prints a ready-to-use connection URL").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--user <name>", "user name to create (default: a random tmp_ name)").option("--ttl <duration>", "lifetime, e.g. 30m, 1h, 7d", "1h").option("--json", "print the full connection as JSON").action(async (targetRef, options) => {
|
|
9984
10048
|
const ctx = buildContext();
|
|
9985
10049
|
const org = await resolveOrg(ctx, options.org);
|
|
9986
10050
|
const { targets } = await ctx.client.listLeaseTargets(org.id);
|
|
@@ -10006,7 +10070,7 @@ function registerMysqlCommands(program) {
|
|
|
10006
10070
|
}, null, 2));
|
|
10007
10071
|
else console.log(url);
|
|
10008
10072
|
});
|
|
10009
|
-
mysql.command("leases").description("list leases (the ledger — never secret material)").option("--org <slug>").action(async (options) => {
|
|
10073
|
+
mysql.command("leases").description("list leases (the ledger — never secret material)").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (options) => {
|
|
10010
10074
|
const ctx = buildContext();
|
|
10011
10075
|
const org = await resolveOrg(ctx, options.org);
|
|
10012
10076
|
const { leases } = await ctx.client.listLeases(org.id);
|
|
@@ -10015,9 +10079,10 @@ function registerMysqlCommands(program) {
|
|
|
10015
10079
|
console.log(`${l.id}\t${l.status}\t${l.resourceRef}\texpires ${l.expiresAt}`);
|
|
10016
10080
|
}
|
|
10017
10081
|
});
|
|
10018
|
-
mysql.command("revoke <leaseId>").description("revoke a lease now (drops the user immediately)").option("--org <slug>").action(async (leaseId, options) => {
|
|
10082
|
+
mysql.command("revoke <leaseId>").description("revoke a lease now (drops the user immediately)").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("-y, --yes", "skip the confirmation").action(async (leaseId, options) => {
|
|
10019
10083
|
const ctx = buildContext();
|
|
10020
10084
|
const org = await resolveOrg(ctx, options.org);
|
|
10085
|
+
await confirmDestructive(options.yes, `Revoke lease ${leaseId} now? Its MySQL user is dropped immediately.`);
|
|
10021
10086
|
await ctx.client.revokeLease(org.id, leaseId);
|
|
10022
10087
|
console.error(`revoked ${leaseId}`);
|
|
10023
10088
|
});
|
|
@@ -10089,20 +10154,20 @@ function registerOrgCommands(program) {
|
|
|
10089
10154
|
]);
|
|
10090
10155
|
});
|
|
10091
10156
|
});
|
|
10092
|
-
org.command("create").description("create an organization (you become its owner)").requiredOption("--name <name>").requiredOption("--slug <slug>").action(async (options) => {
|
|
10157
|
+
org.command("create").description("create an organization (you become its owner)").requiredOption("--name <name>", "display name").requiredOption("--slug <slug>", "url-safe identifier (permanent)").action(async (options) => {
|
|
10093
10158
|
const created = await buildContext().client.createOrg({
|
|
10094
10159
|
name: options.name,
|
|
10095
10160
|
slug: options.slug
|
|
10096
10161
|
});
|
|
10097
10162
|
console.error(`created org ${created.org.slug} (${created.org.id})`);
|
|
10098
10163
|
});
|
|
10099
|
-
org.command("rename").description("change an organization's display name (the slug is permanent)").option("--org <slug>").requiredOption("--name <name>", "new display name").action(async (options) => {
|
|
10164
|
+
org.command("rename").description("change an organization's display name (the slug is permanent)").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").requiredOption("--name <name>", "new display name").action(async (options) => {
|
|
10100
10165
|
const ctx = buildContext();
|
|
10101
10166
|
const ref = await resolveOrg(ctx, options.org);
|
|
10102
10167
|
const { org: row } = await ctx.client.updateOrg(ref.id, { name: options.name });
|
|
10103
10168
|
console.error(`renamed ${row.slug} to "${row.name}"`);
|
|
10104
10169
|
});
|
|
10105
|
-
org.command("member").description("view organization members").command("list").alias("ls").description("list members, and whether each has finished key setup").option("--org <slug>").option("--json", "print the raw API response").action(async (options) => {
|
|
10170
|
+
org.command("member").description("view organization members").command("list").alias("ls").description("list members, and whether each has finished key setup").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--json", "print the raw API response").action(async (options) => {
|
|
10106
10171
|
const ctx = buildContext();
|
|
10107
10172
|
const ref = await resolveOrg(ctx, options.org);
|
|
10108
10173
|
const { members } = await ctx.client.listMembers(ref.id);
|
|
@@ -10115,7 +10180,7 @@ function registerOrgCommands(program) {
|
|
|
10115
10180
|
], "no members"));
|
|
10116
10181
|
});
|
|
10117
10182
|
const invite = org.command("invite").description("manage pending invitations");
|
|
10118
|
-
invite.command("list").alias("ls").description("list outstanding invitations").option("--org <slug>").option("--json", "print the raw API response").action(async (options) => {
|
|
10183
|
+
invite.command("list").alias("ls").description("list outstanding invitations").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--json", "print the raw API response").action(async (options) => {
|
|
10119
10184
|
const ctx = buildContext();
|
|
10120
10185
|
const ref = await resolveOrg(ctx, options.org);
|
|
10121
10186
|
const { invites } = await ctx.client.listInvites(ref.id);
|
|
@@ -10126,7 +10191,7 @@ function registerOrgCommands(program) {
|
|
|
10126
10191
|
col("id", (i) => i.id)
|
|
10127
10192
|
], "no pending invitations"));
|
|
10128
10193
|
});
|
|
10129
|
-
invite.command("add <email>").description("invite someone to the organization").option("--org <slug>").option("--role <role>", "admin | member", "member").action(async (email, options) => {
|
|
10194
|
+
invite.command("add <email>").description("invite someone to the organization").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--role <role>", "admin | member", "member").action(async (email, options) => {
|
|
10130
10195
|
if (options.role !== "admin" && options.role !== "member") fail("--role must be admin or member");
|
|
10131
10196
|
const ctx = buildContext();
|
|
10132
10197
|
const ref = await resolveOrg(ctx, options.org);
|
|
@@ -10136,13 +10201,13 @@ function registerOrgCommands(program) {
|
|
|
10136
10201
|
});
|
|
10137
10202
|
console.error(`invited ${row.email} as ${row.role} (${row.id}) — they join when they first sign in`);
|
|
10138
10203
|
});
|
|
10139
|
-
invite.command("rm <inviteId>").description("rescind an invitation").option("--org <slug>").action(async (inviteId, options) => {
|
|
10204
|
+
invite.command("rm <inviteId>").description("rescind an invitation").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (inviteId, options) => {
|
|
10140
10205
|
const ctx = buildContext();
|
|
10141
10206
|
const ref = await resolveOrg(ctx, options.org);
|
|
10142
10207
|
await ctx.client.revokeInvite(ref.id, inviteId);
|
|
10143
10208
|
console.error(`${inviteId} revoked`);
|
|
10144
10209
|
});
|
|
10145
|
-
org.command("mfa").description("show or set the org-wide second-factor requirement").option("--org <slug>").option("--set <policy>", "required | optional").option("--json", "print the raw API response").action(async (options) => {
|
|
10210
|
+
org.command("mfa").description("show or set the org-wide second-factor requirement").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--set <policy>", "required | optional").option("--json", "print the raw API response").action(async (options) => {
|
|
10146
10211
|
const ctx = buildContext();
|
|
10147
10212
|
const ref = await resolveOrg(ctx, options.org);
|
|
10148
10213
|
if (options.set !== void 0 && options.set !== "required" && options.set !== "optional") fail("--set must be required or optional");
|
|
@@ -10155,7 +10220,7 @@ function registerOrgCommands(program) {
|
|
|
10155
10220
|
console.log(policy.required ? "required for all members" : "optional");
|
|
10156
10221
|
});
|
|
10157
10222
|
});
|
|
10158
|
-
org.command("tree").description("print the org's applications, environments, and groups as a tree").option("--org <slug>").option("--json", "print the raw API response").action(async (options) => {
|
|
10223
|
+
org.command("tree").description("print the org's applications, environments, and groups as a tree").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--json", "print the raw API response").action(async (options) => {
|
|
10159
10224
|
const ctx = buildContext();
|
|
10160
10225
|
const ref = await resolveOrg(ctx, options.org);
|
|
10161
10226
|
const [{ apps }, { groups }] = await Promise.all([ctx.client.listApps(ref.id), ctx.client.listGroups(ref.id)]);
|
|
@@ -11021,7 +11086,7 @@ function generateRoleName(prefix = "tmp") {
|
|
|
11021
11086
|
function registerPgCommands(program) {
|
|
11022
11087
|
const pg = program.command("pg").description("temporary Postgres credentials (short-lived, zero-knowledge)");
|
|
11023
11088
|
const target = pg.command("target").description("manage provisioning targets");
|
|
11024
|
-
target.command("add").description("register a Postgres cluster to lease credentials from").requiredOption("--name <name>", "display name, e.g. prod-db").option("--org <slug>").requiredOption("--host <host>", "database host").option("--port <port>", "database port", "5432").requiredOption("--database <name>", "database to connect to").option("--access <level>", "readonly | readwrite | custom", "readonly").option("--schema <name>", "schema for preset grants", "public").option("--executor <mode>", "in_do | remote", "in_do").option("--provisioner-url <url>", "customer provisioner URL (remote executor)").option("--hmac-key <base64>", "shared HMAC key for the remote executor (or set SEEKRIT_PROVISIONER_HMAC_KEY); `seekrit provisioner keygen` mints one").option("--admin-url <url>", "in_do: admin postgres:// connection string (or set SEEKRIT_PG_ADMIN_URL); wrapped locally").option("--create-statement <sql>", "custom CREATE template (repeatable)", collect$2, []).option("--revoke-statement <sql>", "custom REVOKE template (repeatable)", collect$2, []).action(async (options) => {
|
|
11089
|
+
target.command("add").description("register a Postgres cluster to lease credentials from").requiredOption("--name <name>", "display name, e.g. prod-db").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").requiredOption("--host <host>", "database host").option("--port <port>", "database port", "5432").requiredOption("--database <name>", "database to connect to").option("--access <level>", "readonly | readwrite | custom", "readonly").option("--schema <name>", "schema for preset grants", "public").option("--executor <mode>", "in_do | remote", "in_do").option("--provisioner-url <url>", "customer provisioner URL (remote executor)").option("--hmac-key <base64>", "shared HMAC key for the remote executor (or set SEEKRIT_PROVISIONER_HMAC_KEY); `seekrit provisioner keygen` mints one").option("--admin-url <url>", "in_do: admin postgres:// connection string (or set SEEKRIT_PG_ADMIN_URL); wrapped locally").option("--create-statement <sql>", "custom CREATE template (repeatable)", collect$2, []).option("--revoke-statement <sql>", "custom REVOKE template (repeatable)", collect$2, []).action(async (options) => {
|
|
11025
11090
|
const ctx = buildContext();
|
|
11026
11091
|
const org = await resolveOrg(ctx, options.org);
|
|
11027
11092
|
const executor = options.executor === "remote" ? "remote" : "in_do";
|
|
@@ -11067,7 +11132,7 @@ function registerPgCommands(program) {
|
|
|
11067
11132
|
console.log(bootstrap);
|
|
11068
11133
|
}
|
|
11069
11134
|
});
|
|
11070
|
-
target.command("list").description("list provisioning targets").option("--org <slug>").action(async (options) => {
|
|
11135
|
+
target.command("list").description("list provisioning targets").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (options) => {
|
|
11071
11136
|
const ctx = buildContext();
|
|
11072
11137
|
const org = await resolveOrg(ctx, options.org);
|
|
11073
11138
|
const { targets } = await ctx.client.listLeaseTargets(org.id);
|
|
@@ -11077,7 +11142,7 @@ function registerPgCommands(program) {
|
|
|
11077
11142
|
console.log(`${t.id}\t${t.name}\t${cfg.connection.host}:${cfg.connection.port}/${cfg.connection.database}\t${cfg.accessLevel ?? "custom"}\t${cfg.executor}`);
|
|
11078
11143
|
}
|
|
11079
11144
|
});
|
|
11080
|
-
target.command("setup-sql <targetId>").description("print the one-time group-role setup SQL for a preset target").option("--org <slug>").action(async (targetId, options) => {
|
|
11145
|
+
target.command("setup-sql <targetId>").description("print the one-time group-role setup SQL for a preset target").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (targetId, options) => {
|
|
11081
11146
|
const ctx = buildContext();
|
|
11082
11147
|
const org = await resolveOrg(ctx, options.org);
|
|
11083
11148
|
const { targets } = await ctx.client.listLeaseTargets(org.id);
|
|
@@ -11089,13 +11154,14 @@ function registerPgCommands(program) {
|
|
|
11089
11154
|
if (!bootstrap) fail("this is a custom target — it has no generated setup SQL");
|
|
11090
11155
|
console.log(bootstrap);
|
|
11091
11156
|
});
|
|
11092
|
-
target.command("rm <targetId>").description("remove a provisioning target").option("--org <slug>").action(async (targetId, options) => {
|
|
11157
|
+
target.command("rm <targetId>").description("remove a provisioning target").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("-y, --yes", "skip the confirmation").action(async (targetId, options) => {
|
|
11093
11158
|
const ctx = buildContext();
|
|
11094
11159
|
const org = await resolveOrg(ctx, options.org);
|
|
11160
|
+
await confirmDestructive(options.yes, `Remove target ${targetId}? New leases against it stop working.`);
|
|
11095
11161
|
await ctx.client.deleteLeaseTarget(org.id, targetId);
|
|
11096
11162
|
console.error(`removed ${targetId}`);
|
|
11097
11163
|
});
|
|
11098
|
-
pg.command("lease <target>").description("mint a temporary credential; prints a ready-to-use connection URL").option("--org <slug>").option("--role <name>", "role name to create (default: a random tmp_ name)").option("--ttl <duration>", "lifetime, e.g. 30m, 1h, 7d", "1h").option("--json", "print the full connection as JSON").action(async (targetRef, options) => {
|
|
11164
|
+
pg.command("lease <target>").description("mint a temporary credential; prints a ready-to-use connection URL").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--role <name>", "role name to create (default: a random tmp_ name)").option("--ttl <duration>", "lifetime, e.g. 30m, 1h, 7d", "1h").option("--json", "print the full connection as JSON").action(async (targetRef, options) => {
|
|
11099
11165
|
const ctx = buildContext();
|
|
11100
11166
|
const org = await resolveOrg(ctx, options.org);
|
|
11101
11167
|
const { targets } = await ctx.client.listLeaseTargets(org.id);
|
|
@@ -11121,15 +11187,16 @@ function registerPgCommands(program) {
|
|
|
11121
11187
|
}, null, 2));
|
|
11122
11188
|
else console.log(url);
|
|
11123
11189
|
});
|
|
11124
|
-
pg.command("leases").description("list leases (the ledger — never secret material)").option("--org <slug>").action(async (options) => {
|
|
11190
|
+
pg.command("leases").description("list leases (the ledger — never secret material)").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (options) => {
|
|
11125
11191
|
const ctx = buildContext();
|
|
11126
11192
|
const org = await resolveOrg(ctx, options.org);
|
|
11127
11193
|
const { leases } = await ctx.client.listLeases(org.id);
|
|
11128
11194
|
for (const l of leases) console.log(`${l.id}\t${l.status}\t${l.resourceRef}\texpires ${l.expiresAt}`);
|
|
11129
11195
|
});
|
|
11130
|
-
pg.command("revoke <leaseId>").description("revoke a lease now (drops the role immediately)").option("--org <slug>").action(async (leaseId, options) => {
|
|
11196
|
+
pg.command("revoke <leaseId>").description("revoke a lease now (drops the role immediately)").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("-y, --yes", "skip the confirmation").action(async (leaseId, options) => {
|
|
11131
11197
|
const ctx = buildContext();
|
|
11132
11198
|
const org = await resolveOrg(ctx, options.org);
|
|
11199
|
+
await confirmDestructive(options.yes, `Revoke lease ${leaseId} now? Its Postgres role is dropped immediately.`);
|
|
11133
11200
|
await ctx.client.revokeLease(org.id, leaseId);
|
|
11134
11201
|
console.error(`revoked ${leaseId}`);
|
|
11135
11202
|
});
|
|
@@ -11626,7 +11693,7 @@ function generateUserName(prefix = "tmp") {
|
|
|
11626
11693
|
function registerRedisCommands(program) {
|
|
11627
11694
|
const redis = program.command("redis").description("temporary Redis credentials (short-lived, zero-knowledge)");
|
|
11628
11695
|
const target = redis.command("target").description("manage provisioning targets");
|
|
11629
|
-
target.command("add").description("register a Redis server to lease credentials from").requiredOption("--name <name>", "display name, e.g. prod-cache").option("--org <slug>").requiredOption("--host <host>", "redis host").option("--port <port>", "redis port", "6379").option("--db <index>", "logical database index (the /<n> in the URL)").option("--access <level>", "readonly | readwrite | custom", "readonly").option("--executor <mode>", "in_do | remote", "in_do").option("--provisioner-url <url>", "customer provisioner URL (remote executor)").option("--hmac-key <base64>", "shared HMAC key for the remote executor (or set SEEKRIT_PROVISIONER_HMAC_KEY); `seekrit provisioner keygen` mints one").option("--admin-url <url>", "in_do: admin redis:// (or rediss://) connection string (or set SEEKRIT_REDIS_ADMIN_URL); wrapped locally").option("--create-statement <cmd>", "custom SETUSER template (repeatable)", collect$1, []).option("--revoke-statement <cmd>", "custom DELUSER template (repeatable)", collect$1, []).action(async (options) => {
|
|
11696
|
+
target.command("add").description("register a Redis server to lease credentials from").requiredOption("--name <name>", "display name, e.g. prod-cache").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").requiredOption("--host <host>", "redis host").option("--port <port>", "redis port", "6379").option("--db <index>", "logical database index (the /<n> in the URL)").option("--access <level>", "readonly | readwrite | custom", "readonly").option("--executor <mode>", "in_do | remote", "in_do").option("--provisioner-url <url>", "customer provisioner URL (remote executor)").option("--hmac-key <base64>", "shared HMAC key for the remote executor (or set SEEKRIT_PROVISIONER_HMAC_KEY); `seekrit provisioner keygen` mints one").option("--admin-url <url>", "in_do: admin redis:// (or rediss://) connection string (or set SEEKRIT_REDIS_ADMIN_URL); wrapped locally").option("--create-statement <cmd>", "custom SETUSER template (repeatable)", collect$1, []).option("--revoke-statement <cmd>", "custom DELUSER template (repeatable)", collect$1, []).action(async (options) => {
|
|
11630
11697
|
const ctx = buildContext();
|
|
11631
11698
|
const org = await resolveOrg(ctx, options.org);
|
|
11632
11699
|
const executor = options.executor === "remote" ? "remote" : "in_do";
|
|
@@ -11667,7 +11734,7 @@ function registerRedisCommands(program) {
|
|
|
11667
11734
|
});
|
|
11668
11735
|
console.error(`registered ${accessLevel} target ${created.name} (${created.id})`);
|
|
11669
11736
|
});
|
|
11670
|
-
target.command("list").description("list provisioning targets").option("--org <slug>").action(async (options) => {
|
|
11737
|
+
target.command("list").description("list provisioning targets").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (options) => {
|
|
11671
11738
|
const ctx = buildContext();
|
|
11672
11739
|
const org = await resolveOrg(ctx, options.org);
|
|
11673
11740
|
const { targets } = await ctx.client.listLeaseTargets(org.id);
|
|
@@ -11678,13 +11745,14 @@ function registerRedisCommands(program) {
|
|
|
11678
11745
|
console.log(`${t.id}\t${t.name}\t${cfg.connection.host}:${cfg.connection.port}/${db}\t${cfg.accessLevel ?? "custom"}\t${cfg.executor}`);
|
|
11679
11746
|
}
|
|
11680
11747
|
});
|
|
11681
|
-
target.command("rm <targetId>").description("remove a provisioning target").option("--org <slug>").action(async (targetId, options) => {
|
|
11748
|
+
target.command("rm <targetId>").description("remove a provisioning target").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("-y, --yes", "skip the confirmation").action(async (targetId, options) => {
|
|
11682
11749
|
const ctx = buildContext();
|
|
11683
11750
|
const org = await resolveOrg(ctx, options.org);
|
|
11751
|
+
await confirmDestructive(options.yes, `Remove target ${targetId}? New leases against it stop working.`);
|
|
11684
11752
|
await ctx.client.deleteLeaseTarget(org.id, targetId);
|
|
11685
11753
|
console.error(`removed ${targetId}`);
|
|
11686
11754
|
});
|
|
11687
|
-
redis.command("lease <target>").description("mint a temporary credential; prints a ready-to-use connection URL").option("--org <slug>").option("--user <name>", "ACL user name to create (default: a random tmp_ name)").option("--ttl <duration>", "lifetime, e.g. 30m, 1h, 7d", "1h").option("--json", "print the full connection as JSON").action(async (targetRef, options) => {
|
|
11755
|
+
redis.command("lease <target>").description("mint a temporary credential; prints a ready-to-use connection URL").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--user <name>", "ACL user name to create (default: a random tmp_ name)").option("--ttl <duration>", "lifetime, e.g. 30m, 1h, 7d", "1h").option("--json", "print the full connection as JSON").action(async (targetRef, options) => {
|
|
11688
11756
|
const ctx = buildContext();
|
|
11689
11757
|
const org = await resolveOrg(ctx, options.org);
|
|
11690
11758
|
const { targets } = await ctx.client.listLeaseTargets(org.id);
|
|
@@ -11710,7 +11778,7 @@ function registerRedisCommands(program) {
|
|
|
11710
11778
|
}, null, 2));
|
|
11711
11779
|
else console.log(url);
|
|
11712
11780
|
});
|
|
11713
|
-
redis.command("leases").description("list leases (the ledger — never secret material)").option("--org <slug>").action(async (options) => {
|
|
11781
|
+
redis.command("leases").description("list leases (the ledger — never secret material)").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (options) => {
|
|
11714
11782
|
const ctx = buildContext();
|
|
11715
11783
|
const org = await resolveOrg(ctx, options.org);
|
|
11716
11784
|
const { leases } = await ctx.client.listLeases(org.id);
|
|
@@ -11719,9 +11787,10 @@ function registerRedisCommands(program) {
|
|
|
11719
11787
|
console.log(`${l.id}\t${l.status}\t${l.resourceRef}\texpires ${l.expiresAt}`);
|
|
11720
11788
|
}
|
|
11721
11789
|
});
|
|
11722
|
-
redis.command("revoke <leaseId>").description("revoke a lease now (deletes the ACL user immediately)").option("--org <slug>").action(async (leaseId, options) => {
|
|
11790
|
+
redis.command("revoke <leaseId>").description("revoke a lease now (deletes the ACL user immediately)").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("-y, --yes", "skip the confirmation").action(async (leaseId, options) => {
|
|
11723
11791
|
const ctx = buildContext();
|
|
11724
11792
|
const org = await resolveOrg(ctx, options.org);
|
|
11793
|
+
await confirmDestructive(options.yes, `Revoke lease ${leaseId} now? Its Redis ACL user is deleted immediately.`);
|
|
11725
11794
|
await ctx.client.revokeLease(org.id, leaseId);
|
|
11726
11795
|
console.error(`revoked ${leaseId}`);
|
|
11727
11796
|
});
|
|
@@ -11813,7 +11882,7 @@ function buildConfig$1(kind, options) {
|
|
|
11813
11882
|
}
|
|
11814
11883
|
function registerRotationCommands(program) {
|
|
11815
11884
|
const rotation = program.command("rotation").description("managed rotation of stored secret values (scheduled, zero-knowledge)");
|
|
11816
|
-
rotation.command("enable <secretName>").description("configure rotation for an existing secret").option("--org <slug>").option("--app <slug>").option("--group <slug>", "rotate a secret in a group environment").requiredOption("--env <slug>").requiredOption("--kind <kind>", "generated | postgres | mysql | redis").requiredOption("--every <duration>", "rotation cadence, e.g. 24h, 30d").option("--username <name>", "the EXISTING database account to re-key (db kinds)").option("--target <idOrName>", "registered lease target to rotate against (db kinds)").option("--user-host <host>", "MySQL account host part (default %)").option("--length <n>", "generated value length", "32").option("--alphabet <set>", "generated kind only: alphanumeric | hex | base64url | printable", "alphanumeric").option("--now", "rotate immediately as well as on the schedule").action(async (secretName, options) => {
|
|
11885
|
+
rotation.command("enable <secretName>").description("configure rotation for an existing secret").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--app <slug>", "application slug (defaults to seekrit.json)").option("--group <slug>", "rotate a secret in a group environment").requiredOption("--env <slug>", "environment slug").requiredOption("--kind <kind>", "generated | postgres | mysql | redis").requiredOption("--every <duration>", "rotation cadence, e.g. 24h, 30d").option("--username <name>", "the EXISTING database account to re-key (db kinds)").option("--target <idOrName>", "registered lease target to rotate against (db kinds)").option("--user-host <host>", "MySQL account host part (default %)").option("--length <n>", "generated value length", "32").option("--alphabet <set>", "generated kind only: alphanumeric | hex | base64url | printable", "alphanumeric").option("--now", "rotate immediately as well as on the schedule").action(async (secretName, options) => {
|
|
11817
11886
|
const ctx = buildContext();
|
|
11818
11887
|
const target = await resolveEnvTarget(ctx, options);
|
|
11819
11888
|
const config = buildConfig$1(options.kind, options);
|
|
@@ -11843,7 +11912,7 @@ function registerRotationCommands(program) {
|
|
|
11843
11912
|
else console.error(`first rotation: ${created.nextRotateAt}`);
|
|
11844
11913
|
console.log(created.id);
|
|
11845
11914
|
});
|
|
11846
|
-
rotation.command("list").description("list rotation policies (schedules only — never values)").option("--org <slug>").option("--json", "print the full policies as JSON").action(async (options) => {
|
|
11915
|
+
rotation.command("list").description("list rotation policies (schedules only — never values)").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--json", "print the full policies as JSON").action(async (options) => {
|
|
11847
11916
|
const ctx = buildContext();
|
|
11848
11917
|
const org = await resolveOrg(ctx, options.org);
|
|
11849
11918
|
const { rotations } = await ctx.client.listRotations(org.id);
|
|
@@ -11857,43 +11926,44 @@ function registerRotationCommands(program) {
|
|
|
11857
11926
|
}
|
|
11858
11927
|
for (const r of rotations) console.log(rotationLine(r));
|
|
11859
11928
|
});
|
|
11860
|
-
rotation.command("show <rotationOrSecret>").description("show one policy, including the last failure if any").option("--org <slug>").action(async (ref, options) => {
|
|
11929
|
+
rotation.command("show <rotationOrSecret>").description("show one policy, including the last failure if any").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (ref, options) => {
|
|
11861
11930
|
const ctx = buildContext();
|
|
11862
11931
|
const r = await resolveRotation(ctx, (await resolveOrg(ctx, options.org)).id, ref);
|
|
11863
11932
|
console.log(JSON.stringify(r, null, 2));
|
|
11864
11933
|
});
|
|
11865
|
-
rotation.command("rotate <rotationOrSecret>").description("rotate now (the same path the scheduler uses)").option("--org <slug>").action(async (ref, options) => {
|
|
11934
|
+
rotation.command("rotate <rotationOrSecret>").description("rotate now (the same path the scheduler uses)").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (ref, options) => {
|
|
11866
11935
|
const ctx = buildContext();
|
|
11867
11936
|
const org = await resolveOrg(ctx, options.org);
|
|
11868
11937
|
const r = await resolveRotation(ctx, org.id, ref);
|
|
11869
11938
|
const { version, rotatedAt } = await ctx.client.rotateSecretNow(org.id, r.id);
|
|
11870
11939
|
console.error(`rotated ${r.secretName} at ${rotatedAt} — now at version ${version}. Read it with \`seekrit secrets get ${r.secretName}\`.`);
|
|
11871
11940
|
});
|
|
11872
|
-
rotation.command("pause <rotationOrSecret>").description("stop rotating, keeping the policy").option("--org <slug>").action(async (ref, options) => {
|
|
11941
|
+
rotation.command("pause <rotationOrSecret>").description("stop rotating, keeping the policy").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (ref, options) => {
|
|
11873
11942
|
const ctx = buildContext();
|
|
11874
11943
|
const org = await resolveOrg(ctx, options.org);
|
|
11875
11944
|
const r = await resolveRotation(ctx, org.id, ref);
|
|
11876
11945
|
await ctx.client.updateRotation(org.id, r.id, { status: "paused" });
|
|
11877
11946
|
console.error(`paused rotation of ${r.secretName}`);
|
|
11878
11947
|
});
|
|
11879
|
-
rotation.command("resume <rotationOrSecret>").description("resume rotating (also clears a failed streak)").option("--org <slug>").action(async (ref, options) => {
|
|
11948
|
+
rotation.command("resume <rotationOrSecret>").description("resume rotating (also clears a failed streak)").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (ref, options) => {
|
|
11880
11949
|
const ctx = buildContext();
|
|
11881
11950
|
const org = await resolveOrg(ctx, options.org);
|
|
11882
11951
|
const r = await resolveRotation(ctx, org.id, ref);
|
|
11883
11952
|
const { rotation: updated } = await ctx.client.updateRotation(org.id, r.id, { status: "active" });
|
|
11884
11953
|
console.error(`resumed rotation of ${r.secretName} — next ${updated.nextRotateAt}`);
|
|
11885
11954
|
});
|
|
11886
|
-
rotation.command("set-interval <rotationOrSecret>").description("change the cadence").requiredOption("--every <duration>", "new cadence, e.g. 24h, 30d").option("--org <slug>").action(async (ref, options) => {
|
|
11955
|
+
rotation.command("set-interval <rotationOrSecret>").description("change the cadence").requiredOption("--every <duration>", "new cadence, e.g. 24h, 30d").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (ref, options) => {
|
|
11887
11956
|
const ctx = buildContext();
|
|
11888
11957
|
const org = await resolveOrg(ctx, options.org);
|
|
11889
11958
|
const r = await resolveRotation(ctx, org.id, ref);
|
|
11890
11959
|
const { rotation: updated } = await ctx.client.updateRotation(org.id, r.id, { intervalSeconds: parseDurationSeconds(options.every, "--every") });
|
|
11891
11960
|
console.error(`${updated.secretName} now rotates every ${formatInterval(updated.intervalSeconds)} — next ${updated.nextRotateAt}`);
|
|
11892
11961
|
});
|
|
11893
|
-
rotation.command("disable <rotationOrSecret>").description("stop rotating and remove the policy (the secret is untouched)").option("--org <slug>").action(async (ref, options) => {
|
|
11962
|
+
rotation.command("disable <rotationOrSecret>").description("stop rotating and remove the policy (the secret is untouched)").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("-y, --yes", "skip the confirmation").action(async (ref, options) => {
|
|
11894
11963
|
const ctx = buildContext();
|
|
11895
11964
|
const org = await resolveOrg(ctx, options.org);
|
|
11896
11965
|
const r = await resolveRotation(ctx, org.id, ref);
|
|
11966
|
+
await confirmDestructive(options.yes, `Stop rotating ${r.secretName} and delete its policy? The current value stays as it is.`);
|
|
11897
11967
|
const { rotatorRevoked } = await ctx.client.disableRotation(org.id, r.id);
|
|
11898
11968
|
console.error(`disabled rotation of ${r.secretName}${rotatorRevoked ? " — rotator key access revoked for this environment" : ""}`);
|
|
11899
11969
|
});
|
|
@@ -12112,7 +12182,7 @@ function parseTtlSeconds(input) {
|
|
|
12112
12182
|
function registerSshCommands(program) {
|
|
12113
12183
|
const ssh = program.command("ssh").description("temporary SSH access (short-lived certificates, zero-knowledge)");
|
|
12114
12184
|
const target = ssh.command("target").description("manage SSH CA targets");
|
|
12115
|
-
target.command("add").description("create an SSH certificate authority to issue certs from").requiredOption("--name <name>", "display name, e.g. prod-fleet").option("--org <slug>").option("--host <host>", "default host the printed ssh command connects to").option("--user <login>", "default login user (a cert principal)").option("--principal <name>", "allow-list a principal certs may request (repeatable)", collect, []).option("--extension <name>", "cert extension to grant, e.g. permit-pty (repeatable)", collect, []).option("--max-ttl <duration>", "clamp requested cert lifetime, e.g. 8h").action(async (options) => {
|
|
12185
|
+
target.command("add").description("create an SSH certificate authority to issue certs from").requiredOption("--name <name>", "display name, e.g. prod-fleet").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--host <host>", "default host the printed ssh command connects to").option("--user <login>", "default login user (a cert principal)").option("--principal <name>", "allow-list a principal certs may request (repeatable)", collect, []).option("--extension <name>", "cert extension to grant, e.g. permit-pty (repeatable)", collect, []).option("--max-ttl <duration>", "clamp requested cert lifetime, e.g. 8h").action(async (options) => {
|
|
12116
12186
|
const ctx = buildContext();
|
|
12117
12187
|
const org = await resolveOrg(ctx, options.org);
|
|
12118
12188
|
const ca = await generateSshCaKeyPair(`seekrit-ca:${options.name}`);
|
|
@@ -12139,7 +12209,7 @@ function registerSshCommands(program) {
|
|
|
12139
12209
|
console.error("\nInstall the CA on your hosts, then issue certs with `seekrit ssh lease`:\n");
|
|
12140
12210
|
console.log(sshHostSetupInstructions(config));
|
|
12141
12211
|
});
|
|
12142
|
-
target.command("list").description("list SSH CA targets").option("--org <slug>").action(async (options) => {
|
|
12212
|
+
target.command("list").description("list SSH CA targets").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (options) => {
|
|
12143
12213
|
const ctx = buildContext();
|
|
12144
12214
|
const org = await resolveOrg(ctx, options.org);
|
|
12145
12215
|
const { targets } = await ctx.client.listLeaseTargets(org.id);
|
|
@@ -12151,7 +12221,7 @@ function registerSshCommands(program) {
|
|
|
12151
12221
|
console.log(`${t.id}\t${t.name}\t${where}\tprincipals=${principals}`);
|
|
12152
12222
|
}
|
|
12153
12223
|
});
|
|
12154
|
-
target.command("setup <targetId>").description("reprint the one-time host setup for an SSH target").option("--org <slug>").action(async (targetId, options) => {
|
|
12224
|
+
target.command("setup <targetId>").description("reprint the one-time host setup for an SSH target").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (targetId, options) => {
|
|
12155
12225
|
const ctx = buildContext();
|
|
12156
12226
|
const org = await resolveOrg(ctx, options.org);
|
|
12157
12227
|
const { targets } = await ctx.client.listLeaseTargets(org.id);
|
|
@@ -12161,13 +12231,14 @@ function registerSshCommands(program) {
|
|
|
12161
12231
|
if (cfg.provider !== "ssh") fail("not an ssh target (see `seekrit pg`)");
|
|
12162
12232
|
console.log(sshHostSetupInstructions(cfg));
|
|
12163
12233
|
});
|
|
12164
|
-
target.command("rm <targetId>").description("delete an SSH CA target").option("--org <slug>").action(async (targetId, options) => {
|
|
12234
|
+
target.command("rm <targetId>").description("delete an SSH CA target").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("-y, --yes", "skip the confirmation").action(async (targetId, options) => {
|
|
12165
12235
|
const ctx = buildContext();
|
|
12166
12236
|
const org = await resolveOrg(ctx, options.org);
|
|
12237
|
+
await confirmDestructive(options.yes, `Remove target ${targetId}? New leases against it stop working.`);
|
|
12167
12238
|
await ctx.client.deleteLeaseTarget(org.id, targetId);
|
|
12168
12239
|
console.error(`deleted ${targetId}`);
|
|
12169
12240
|
});
|
|
12170
|
-
ssh.command("lease <target>").description("mint a short-lived SSH certificate; prints a ready-to-run ssh command").option("--org <slug>").option("--principal <name>", "login user to request (repeatable; default from target)", collect, []).option("--ttl <duration>", "certificate lifetime, e.g. 30m, 1h, 8h", "1h").option("--out <dir>", "directory to write the key + cert (default: a temp dir)").option("--json", "print key/cert paths and the certificate as JSON").action(async (targetRef, options) => {
|
|
12241
|
+
ssh.command("lease <target>").description("mint a short-lived SSH certificate; prints a ready-to-run ssh command").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--principal <name>", "login user to request (repeatable; default from target)", collect, []).option("--ttl <duration>", "certificate lifetime, e.g. 30m, 1h, 8h", "1h").option("--out <dir>", "directory to write the key + cert (default: a temp dir)").option("--json", "print key/cert paths and the certificate as JSON").action(async (targetRef, options) => {
|
|
12171
12242
|
const ctx = buildContext();
|
|
12172
12243
|
const org = await resolveOrg(ctx, options.org);
|
|
12173
12244
|
const { targets } = await ctx.client.listLeaseTargets(org.id);
|
|
@@ -12205,7 +12276,7 @@ function registerSshCommands(program) {
|
|
|
12205
12276
|
}, null, 2));
|
|
12206
12277
|
else console.log(command);
|
|
12207
12278
|
});
|
|
12208
|
-
ssh.command("leases").description("list SSH leases (the ledger — never secret material)").option("--org <slug>").action(async (options) => {
|
|
12279
|
+
ssh.command("leases").description("list SSH leases (the ledger — never secret material)").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (options) => {
|
|
12209
12280
|
const ctx = buildContext();
|
|
12210
12281
|
const org = await resolveOrg(ctx, options.org);
|
|
12211
12282
|
const { leases } = await ctx.client.listLeases(org.id);
|
|
@@ -12214,9 +12285,10 @@ function registerSshCommands(program) {
|
|
|
12214
12285
|
console.log(`${l.id}\t${l.status}\texpires ${l.expiresAt}`);
|
|
12215
12286
|
}
|
|
12216
12287
|
});
|
|
12217
|
-
ssh.command("revoke <leaseId>").description("mark a lease revoked in the ledger (the cert stays valid until it expires)").option("--org <slug>").action(async (leaseId, options) => {
|
|
12288
|
+
ssh.command("revoke <leaseId>").description("mark a lease revoked in the ledger (the cert stays valid until it expires)").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("-y, --yes", "skip the confirmation").action(async (leaseId, options) => {
|
|
12218
12289
|
const ctx = buildContext();
|
|
12219
12290
|
const org = await resolveOrg(ctx, options.org);
|
|
12291
|
+
await confirmDestructive(options.yes, `Revoke lease ${leaseId}? Certificates already issued stay valid until they expire.`);
|
|
12220
12292
|
await ctx.client.revokeLease(org.id, leaseId);
|
|
12221
12293
|
console.error(`revoked ${leaseId} (issued certs remain valid until they expire)`);
|
|
12222
12294
|
});
|
|
@@ -12732,7 +12804,7 @@ async function resolveConnection(ctx, orgId, ref) {
|
|
|
12732
12804
|
}
|
|
12733
12805
|
function registerSyncCommands(program) {
|
|
12734
12806
|
const sync = program.command("sync").description("push environments to a third-party platform (Vercel, Cloudflare, …)");
|
|
12735
|
-
sync.command("connections").alias("conns").description("list destination accounts seekrit can push to").option("--org <slug>").option("--json", "print the raw API response").action(async (options) => {
|
|
12807
|
+
sync.command("connections").alias("conns").description("list destination accounts seekrit can push to").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--json", "print the raw API response").action(async (options) => {
|
|
12736
12808
|
const ctx = buildContext();
|
|
12737
12809
|
const ref = await resolveOrg(ctx, options.org);
|
|
12738
12810
|
const { connections } = await ctx.client.listSyncConnections(ref.id);
|
|
@@ -12744,7 +12816,7 @@ function registerSyncCommands(program) {
|
|
|
12744
12816
|
col("id", (c) => c.id)
|
|
12745
12817
|
], "no connections — add one with `seekrit sync connect`"));
|
|
12746
12818
|
});
|
|
12747
|
-
sync.command("connect").description("register a destination account (reads its API token from stdin)").option("--org <slug>").requiredOption("--name <name>", "what to call this account, e.g. acme-vercel").option("--provider <kind>", SYNC_PROVIDER_KINDS.join(" | "), "vercel").option("--team-id <id>", "vercel: Team id (omit for a personal account)").option("--token-kind <kind>", `railway: ${RAILWAY_TOKEN_KINDS.join(" | ")}`, "account").option("--account-id <id>", "cloudflare: account ID (32 hex, from the dashboard sidebar) · netlify: team slug or account ID").option("--region <region>", "aws: region ID, e.g. us-east-1").option("--access-key-id <id>", "aws: IAM access key ID (the secret key is read from stdin)").option("--azure-tenant-id <id>", "azure-key-vault: Entra Directory (tenant) ID, a GUID").option("--azure-client-id <id>", "azure-key-vault: Application (client) ID of the service principal, a GUID (its client secret is read from stdin)").option("--azure-cloud <cloud>", `azure-key-vault: ${AZURE_CLOUDS.join(" | ")}`, "public").option("--base-url <url>", "github-actions: GitHub Enterprise Server API root (omit for github.com) · langgraph-platform: self-hosted LangSmith control-plane root").option("--project-id <id>", "gcp: project ID or number whose Secret Manager to write").option("--langgraph-region <region>", `langgraph-platform: ${LANGGRAPH_PLATFORM_REGIONS.join(" | ")} (omit for us)`).option("--langgraph-tenant <id>", "langgraph-platform: LangSmith workspace UUID (only an org-scoped key needs it)").action(async (options) => {
|
|
12819
|
+
sync.command("connect").description("register a destination account (reads its API token from stdin)").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").requiredOption("--name <name>", "what to call this account, e.g. acme-vercel").option("--provider <kind>", SYNC_PROVIDER_KINDS.join(" | "), "vercel").option("--team-id <id>", "vercel: Team id (omit for a personal account)").option("--token-kind <kind>", `railway: ${RAILWAY_TOKEN_KINDS.join(" | ")}`, "account").option("--account-id <id>", "cloudflare: account ID (32 hex, from the dashboard sidebar) · netlify: team slug or account ID").option("--region <region>", "aws: region ID, e.g. us-east-1").option("--access-key-id <id>", "aws: IAM access key ID (the secret key is read from stdin)").option("--azure-tenant-id <id>", "azure-key-vault: Entra Directory (tenant) ID, a GUID").option("--azure-client-id <id>", "azure-key-vault: Application (client) ID of the service principal, a GUID (its client secret is read from stdin)").option("--azure-cloud <cloud>", `azure-key-vault: ${AZURE_CLOUDS.join(" | ")}`, "public").option("--base-url <url>", "github-actions: GitHub Enterprise Server API root (omit for github.com) · langgraph-platform: self-hosted LangSmith control-plane root").option("--project-id <id>", "gcp: project ID or number whose Secret Manager to write").option("--langgraph-region <region>", `langgraph-platform: ${LANGGRAPH_PLATFORM_REGIONS.join(" | ")} (omit for us)`).option("--langgraph-tenant <id>", "langgraph-platform: LangSmith workspace UUID (only an org-scoped key needs it)").action(async (options) => {
|
|
12748
12820
|
const provider = assertProvider(options.provider);
|
|
12749
12821
|
const ctx = buildContext();
|
|
12750
12822
|
const ref = await resolveOrg(ctx, options.org);
|
|
@@ -12761,7 +12833,7 @@ function registerSyncCommands(program) {
|
|
|
12761
12833
|
});
|
|
12762
12834
|
console.error(`connected ${created.connection.name} (${created.connection.id})`);
|
|
12763
12835
|
});
|
|
12764
|
-
destinationOptions(sync.command("verify <connection>").description("check a stored credential against a destination").option("--org <slug>").option("--provider <kind>", SYNC_PROVIDER_KINDS.join(" | "), "vercel")).option("--json", "print the raw API response").action(async (connection, options) => {
|
|
12836
|
+
destinationOptions(sync.command("verify <connection>").description("check a stored credential against a destination").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--provider <kind>", SYNC_PROVIDER_KINDS.join(" | "), "vercel")).option("--json", "print the raw API response").action(async (connection, options) => {
|
|
12765
12837
|
const provider = assertProvider(options.provider);
|
|
12766
12838
|
const ctx = buildContext();
|
|
12767
12839
|
const ref = await resolveOrg(ctx, options.org);
|
|
@@ -12770,7 +12842,7 @@ function registerSyncCommands(program) {
|
|
|
12770
12842
|
emit(options, result, () => printFields([["result", result.ok ? "ok" : "failed"], ["error", result.error ?? null]]));
|
|
12771
12843
|
if (!result.ok) process.exitCode = 1;
|
|
12772
12844
|
});
|
|
12773
|
-
sync.command("disconnect <connection>").description("delete a destination account, its bindings, and its keypair").option("--org <slug>").option("--yes", "skip the confirmation prompt").action(async (connection, options) => {
|
|
12845
|
+
sync.command("disconnect <connection>").description("delete a destination account, its bindings, and its keypair").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("-y, --yes", "skip the confirmation prompt").action(async (connection, options) => {
|
|
12774
12846
|
const ctx = buildContext();
|
|
12775
12847
|
const ref = await resolveOrg(ctx, options.org);
|
|
12776
12848
|
const conn = await resolveConnection(ctx, ref.id, connection);
|
|
@@ -12780,7 +12852,7 @@ function registerSyncCommands(program) {
|
|
|
12780
12852
|
await ctx.client.deleteSyncConnection(ref.id, conn.id);
|
|
12781
12853
|
console.error(`disconnected ${conn.name}`);
|
|
12782
12854
|
});
|
|
12783
|
-
sync.command("bindings").description("list which environments are syncing where").option("--org <slug>").option("--json", "print the raw API response").action(async (options) => {
|
|
12855
|
+
sync.command("bindings").description("list which environments are syncing where").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--json", "print the raw API response").action(async (options) => {
|
|
12784
12856
|
const ctx = buildContext();
|
|
12785
12857
|
const ref = await resolveOrg(ctx, options.org);
|
|
12786
12858
|
const [{ bindings }, { connections }] = await Promise.all([ctx.client.listSyncBindings(ref.id), ctx.client.listSyncConnections(ref.id)]);
|
|
@@ -12795,7 +12867,7 @@ function registerSyncCommands(program) {
|
|
|
12795
12867
|
col("id", (b) => b.id)
|
|
12796
12868
|
], "nothing is syncing — enable it with `seekrit sync enable`"));
|
|
12797
12869
|
});
|
|
12798
|
-
destinationOptions(sync.command("enable").description("start syncing one environment to a destination (lets seekrit decrypt it)").option("--org <slug>").requiredOption("--connection <name>", "destination account, by name or id").option("--app <slug>", "application slug (defaults to seekrit.json)").requiredOption("--env <slug>", "the environment to push").option("--provider <kind>", SYNC_PROVIDER_KINDS.join(" | "), "vercel")).option("--prefix <prefix>", "prepend this to every destination key name").option("--include <globs>", "comma-separated name globs to push (default: all)").option("--exclude <globs>", "comma-separated name globs to skip").option("--on-delete <action>", "delete | retain — what happens when a secret is removed", "delete").option("--mode <mode>", "auto (push on write) | manual", "auto").option("--acknowledge-decryption", "confirm that seekrit's servers may decrypt this environment to push it").action(async (options) => {
|
|
12870
|
+
destinationOptions(sync.command("enable").description("start syncing one environment to a destination (lets seekrit decrypt it)").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").requiredOption("--connection <name>", "destination account, by name or id").option("--app <slug>", "application slug (defaults to seekrit.json)").requiredOption("--env <slug>", "the environment to push").option("--provider <kind>", SYNC_PROVIDER_KINDS.join(" | "), "vercel")).option("--prefix <prefix>", "prepend this to every destination key name").option("--include <globs>", "comma-separated name globs to push (default: all)").option("--exclude <globs>", "comma-separated name globs to skip").option("--on-delete <action>", "delete | retain — what happens when a secret is removed", "delete").option("--mode <mode>", "auto (push on write) | manual", "auto").option("--acknowledge-decryption", "confirm that seekrit's servers may decrypt this environment to push it").action(async (options) => {
|
|
12799
12871
|
const provider = assertProvider(options.provider);
|
|
12800
12872
|
if (options.onDelete !== "delete" && options.onDelete !== "retain") fail("--on-delete must be delete or retain");
|
|
12801
12873
|
if (options.mode !== "auto" && options.mode !== "manual") fail("--mode must be auto or manual");
|
|
@@ -12834,26 +12906,26 @@ function registerSyncCommands(program) {
|
|
|
12834
12906
|
console.error(`syncing ${target.appSlug}/${target.envSlug} → ${conn.name} ${describeDestination(destination)} (${binding.id})`);
|
|
12835
12907
|
if (binding.mode === "manual") console.error("mode is manual — push with `seekrit sync run`");
|
|
12836
12908
|
});
|
|
12837
|
-
sync.command("pause <bindingId>").description("stop pushing on this binding without deleting it").option("--org <slug>").action(async (bindingId, options) => {
|
|
12909
|
+
sync.command("pause <bindingId>").description("stop pushing on this binding without deleting it").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (bindingId, options) => {
|
|
12838
12910
|
const ctx = buildContext();
|
|
12839
12911
|
const ref = await resolveOrg(ctx, options.org);
|
|
12840
12912
|
await ctx.client.updateSyncBinding(ref.id, bindingId, { enabled: false });
|
|
12841
12913
|
console.error(`${bindingId} paused`);
|
|
12842
12914
|
});
|
|
12843
|
-
sync.command("resume <bindingId>").description("start pushing on a paused binding again").option("--org <slug>").action(async (bindingId, options) => {
|
|
12915
|
+
sync.command("resume <bindingId>").description("start pushing on a paused binding again").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").action(async (bindingId, options) => {
|
|
12844
12916
|
const ctx = buildContext();
|
|
12845
12917
|
const ref = await resolveOrg(ctx, options.org);
|
|
12846
12918
|
await ctx.client.updateSyncBinding(ref.id, bindingId, { enabled: true });
|
|
12847
12919
|
console.error(`${bindingId} resumed`);
|
|
12848
12920
|
});
|
|
12849
|
-
sync.command("disable <bindingId>").alias("rm").description("stop syncing an environment and revoke seekrit's key for it").option("--org <slug>").option("--yes", "skip the confirmation prompt").action(async (bindingId, options) => {
|
|
12921
|
+
sync.command("disable <bindingId>").alias("rm").description("stop syncing an environment and revoke seekrit's key for it").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("-y, --yes", "skip the confirmation prompt").action(async (bindingId, options) => {
|
|
12850
12922
|
const ctx = buildContext();
|
|
12851
12923
|
const ref = await resolveOrg(ctx, options.org);
|
|
12852
12924
|
await confirmDestructive(options.yes, `Delete binding ${bindingId}? Values already pushed stay on the destination.`);
|
|
12853
12925
|
await ctx.client.deleteSyncBinding(ref.id, bindingId);
|
|
12854
12926
|
console.error(`${bindingId} deleted`);
|
|
12855
12927
|
});
|
|
12856
|
-
sync.command("run <bindingId>").description("push now, synchronously, and report what landed").option("--org <slug>").option("--json", "print the raw API response").action(async (bindingId, options) => {
|
|
12928
|
+
sync.command("run <bindingId>").description("push now, synchronously, and report what landed").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--json", "print the raw API response").action(async (bindingId, options) => {
|
|
12857
12929
|
const ctx = buildContext();
|
|
12858
12930
|
const ref = await resolveOrg(ctx, options.org);
|
|
12859
12931
|
const { run } = await ctx.client.runSyncBinding(ref.id, bindingId);
|
|
@@ -12872,7 +12944,7 @@ function registerSyncCommands(program) {
|
|
|
12872
12944
|
});
|
|
12873
12945
|
if (run.status !== "succeeded") process.exitCode = 1;
|
|
12874
12946
|
});
|
|
12875
|
-
sync.command("runs").description("show the sync run history").option("--org <slug>").option("--binding <id>", "only runs of this binding").option("--json", "print the raw API response").action(async (options) => {
|
|
12947
|
+
sync.command("runs").description("show the sync run history").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--binding <id>", "only runs of this binding").option("--json", "print the raw API response").action(async (options) => {
|
|
12876
12948
|
const ctx = buildContext();
|
|
12877
12949
|
const ref = await resolveOrg(ctx, options.org);
|
|
12878
12950
|
const { runs } = await ctx.client.listSyncRuns(ref.id, options.binding);
|
|
@@ -13038,6 +13110,7 @@ async function runLogout() {
|
|
|
13038
13110
|
console.error("not signed in");
|
|
13039
13111
|
return;
|
|
13040
13112
|
}
|
|
13113
|
+
if (!sessionToken) console.error(config.token ? "signed out — the stored service token was removed from this machine" : "signed out");
|
|
13041
13114
|
if (sessionToken) {
|
|
13042
13115
|
const api = new SeekritClient({
|
|
13043
13116
|
baseUrl: process.env.SEEKRIT_API_URL ?? config.apiUrl ?? "https://api.seekrit.dev",
|
|
@@ -13255,9 +13328,10 @@ withTarget(secrets.command("restore <name> <version>").description("roll a secre
|
|
|
13255
13328
|
const { secret, restoredFrom } = await ctx.client.restoreSecret(orgId, envId, name, parseVersion(version));
|
|
13256
13329
|
console.error(`${name} restored from v${restoredFrom} — now v${secret.version}`);
|
|
13257
13330
|
});
|
|
13258
|
-
withTarget(secrets.command("rm <name>").description("delete a secret")).action(async (name, options) => {
|
|
13331
|
+
withTarget(secrets.command("rm <name>").description("delete a secret and its whole version history").option("-y, --yes", "skip the confirmation")).action(async (name, options) => {
|
|
13259
13332
|
const ctx = buildContext();
|
|
13260
|
-
const { orgId, envId } = await resolveEnvTarget(ctx, options);
|
|
13333
|
+
const { orgId, envId, label } = await resolveEnvTarget(ctx, options);
|
|
13334
|
+
await confirmDestructive(options.yes, `Delete ${name} from ${label}, including every earlier version? This cannot be undone.`);
|
|
13261
13335
|
await ctx.client.deleteSecret(orgId, envId, name);
|
|
13262
13336
|
console.error(`${name} deleted`);
|
|
13263
13337
|
});
|
|
@@ -13342,8 +13416,7 @@ async function materializeForRun(options) {
|
|
|
13342
13416
|
branch
|
|
13343
13417
|
}, dotenvVars);
|
|
13344
13418
|
} catch (err) {
|
|
13345
|
-
|
|
13346
|
-
console.error(`seekrit: continuing without seekrit-managed secrets: ${message}`);
|
|
13419
|
+
console.error(`seekrit: continuing without seekrit-managed secrets: ${describeError(err)}`);
|
|
13347
13420
|
const values = {};
|
|
13348
13421
|
const provenance = {};
|
|
13349
13422
|
overlayEnvFiles(values, provenance, envFiles);
|
|
@@ -13463,7 +13536,7 @@ async function reapStragglers(pids, signal) {
|
|
|
13463
13536
|
process.kill(pid, "SIGKILL");
|
|
13464
13537
|
} catch {}
|
|
13465
13538
|
}
|
|
13466
|
-
program.command("run").description("run a command with decrypted secrets injected (process env > .env > app > group)").passThroughOptions().option("--org <slug>").option("--app <slug>", "application slug (token path infers this)").option("--env <slug>", "environment slug (token path infers this)").option("--branch <slug>", "read a branch of that environment (or $SEEKRIT_BRANCH)").option("--with <group=env>", "override one group’s slice for this run", collectKv).option("--env-file <path>", "a .env file to overlay (repeatable; default .env)", collectList).option("--explain", "print where each variable resolved from (to stderr)").option("--no-interpolate", "leave ${OTHER_SECRET} references as literal text").option("--cache", "keep a last-known-good copy of the encrypted response and fall back to it when the API is unreachable (off by default; SEEKRIT_CACHE=1)").option("--cache-dir <path>", "where to keep it (default: $XDG_CACHE_HOME/seekrit)").option("--cache-max-age <duration>", "how stale a cached copy may be and still be used, e.g. 15m, 24h, 7d (default: 24h)").argument("<command...>", "command to run (prefix with -- to pass flags)").action(async (commandParts, options) => {
|
|
13539
|
+
program.command("run").description("run a command with decrypted secrets injected (process env > .env > app > group)").passThroughOptions().option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--app <slug>", "application slug (token path infers this)").option("--env <slug>", "environment slug (token path infers this)").option("--branch <slug>", "read a branch of that environment (or $SEEKRIT_BRANCH)").option("--with <group=env>", "override one group’s slice for this run", collectKv).option("--env-file <path>", "a .env file to overlay (repeatable; default .env)", collectList).option("--explain", "print where each variable resolved from (to stderr)").option("--no-interpolate", "leave ${OTHER_SECRET} references as literal text").option("--cache", "keep a last-known-good copy of the encrypted response and fall back to it when the API is unreachable (off by default; SEEKRIT_CACHE=1)").option("--cache-dir <path>", "where to keep it (default: $XDG_CACHE_HOME/seekrit)").option("--cache-max-age <duration>", "how stale a cached copy may be and still be used, e.g. 15m, 24h, 7d (default: 24h)").argument("<command...>", "command to run (prefix with -- to pass flags)").action(async (commandParts, options) => {
|
|
13467
13540
|
const [cmd, ...args] = commandParts;
|
|
13468
13541
|
if (!cmd) fail("no command given");
|
|
13469
13542
|
const { values, provenance, interpolated, unresolvedRefs } = await materializeForRun(options);
|
|
@@ -13515,7 +13588,7 @@ program.command("run").description("run a command with decrypted secrets injecte
|
|
|
13515
13588
|
});
|
|
13516
13589
|
child.on("error", (err) => fail(`failed to start ${cmd}: ${err.message}`));
|
|
13517
13590
|
});
|
|
13518
|
-
program.command("export").description("print decrypted secrets (dotenv, json, or shell)").option("--org <slug>").option("--app <slug>", "application slug (token path infers this)").option("--env <slug>", "environment slug (token path infers this)").option("--branch <slug>", "read a branch of that environment (or $SEEKRIT_BRANCH)").option("--with <group=env>", "override one group’s slice", collectKv).option("--env-file <path>", "a .env file to overlay (repeatable; default .env)", collectList).option("--explain", "print where each variable resolved from (to stderr)").option("--no-interpolate", "leave ${OTHER_SECRET} references as literal text").option("--cache", "keep a last-known-good copy of the encrypted response and fall back to it when the API is unreachable (off by default; SEEKRIT_CACHE=1)").option("--cache-dir <path>", "where to keep it (default: $XDG_CACHE_HOME/seekrit)").option("--cache-max-age <duration>", "how stale a cached copy may be and still be used, e.g. 15m, 24h, 7d (default: 24h)").option("--format <format>", "dotenv | json | shell", "dotenv").action(async (options) => {
|
|
13591
|
+
program.command("export").description("print decrypted secrets (dotenv, json, or shell)").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--app <slug>", "application slug (token path infers this)").option("--env <slug>", "environment slug (token path infers this)").option("--branch <slug>", "read a branch of that environment (or $SEEKRIT_BRANCH)").option("--with <group=env>", "override one group’s slice", collectKv).option("--env-file <path>", "a .env file to overlay (repeatable; default .env)", collectList).option("--explain", "print where each variable resolved from (to stderr)").option("--no-interpolate", "leave ${OTHER_SECRET} references as literal text").option("--cache", "keep a last-known-good copy of the encrypted response and fall back to it when the API is unreachable (off by default; SEEKRIT_CACHE=1)").option("--cache-dir <path>", "where to keep it (default: $XDG_CACHE_HOME/seekrit)").option("--cache-max-age <duration>", "how stale a cached copy may be and still be used, e.g. 15m, 24h, 7d (default: 24h)").option("--format <format>", "dotenv | json | shell", "dotenv").action(async (options) => {
|
|
13519
13592
|
if (![
|
|
13520
13593
|
"dotenv",
|
|
13521
13594
|
"json",
|
|
@@ -13531,7 +13604,7 @@ program.command("export").description("print decrypted secrets (dotenv, json, or
|
|
|
13531
13604
|
registerAccessCommands(program);
|
|
13532
13605
|
registerHoneyTokenCommands(program);
|
|
13533
13606
|
const token = program.command("token").description("manage service tokens (CI, docker, agents)");
|
|
13534
|
-
token.command("create").description("create a service token (runtime, or --admin for provisioning); prints it once").requiredOption("--name <name>", "display name, e.g. ci-deploy").option("--org <slug>").option("--app <slug>", "application to bind the token to (runtime tokens)").option("--env <slug>", "environment to bind the token to (runtime tokens)").option("--admin", "mint an org-scoped admin token that can provision structure (no env binding required)").option("--allow <group=env>", "also grant an alternate group slice (for `run --with`)", collectKv).option("--no-grant", "skip auto-granting the env + composed group keys").action(async (options) => {
|
|
13607
|
+
token.command("create").description("create a service token (runtime, or --admin for provisioning); prints it once").requiredOption("--name <name>", "display name, e.g. ci-deploy").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--app <slug>", "application to bind the token to (runtime tokens)").option("--env <slug>", "environment to bind the token to (runtime tokens)").option("--admin", "mint an org-scoped admin token that can provision structure (no env binding required)").option("--allow <group=env>", "also grant an alternate group slice (for `run --with`)", collectKv).option("--no-grant", "skip auto-granting the env + composed group keys").action(async (options) => {
|
|
13535
13608
|
const ctx = buildContext();
|
|
13536
13609
|
const role = options.admin ? "admin" : "member";
|
|
13537
13610
|
const boundToEnv = Boolean(options.app || options.env);
|
|
@@ -13580,7 +13653,7 @@ token.command("create").description("create a service token (runtime, or --admin
|
|
|
13580
13653
|
console.error(`${role} token created${granted ? " and granted" : ""} for ${scope} — save it now, it is not stored:`);
|
|
13581
13654
|
console.log(created.token);
|
|
13582
13655
|
});
|
|
13583
|
-
token.command("list").alias("ls").description("list service tokens").option("--org <slug>").option("--json", "print the raw API response").action(async (options) => {
|
|
13656
|
+
token.command("list").alias("ls").description("list service tokens").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("--json", "print the raw API response").action(async (options) => {
|
|
13584
13657
|
const ctx = buildContext();
|
|
13585
13658
|
const orgRef = await resolveOrg(ctx, options.org);
|
|
13586
13659
|
const { tokens } = await ctx.client.listTokens(orgRef.id);
|
|
@@ -13594,15 +13667,17 @@ token.command("list").alias("ls").description("list service tokens").option("--o
|
|
|
13594
13667
|
col("id", (t) => t.id)
|
|
13595
13668
|
], "no service tokens — create one with `seekrit token create`"));
|
|
13596
13669
|
});
|
|
13597
|
-
token.command("revoke <tokenId>").description("revoke a service token").option("--org <slug>").action(async (tokenId, options) => {
|
|
13670
|
+
token.command("revoke <tokenId>").description("revoke a service token").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("-y, --yes", "skip the confirmation").action(async (tokenId, options) => {
|
|
13598
13671
|
const ctx = buildContext();
|
|
13599
13672
|
const orgRef = await resolveOrg(ctx, options.org);
|
|
13673
|
+
await confirmDestructive(options.yes, `Revoke ${tokenId}? Anything still presenting it stops resolving immediately.`);
|
|
13600
13674
|
await ctx.client.revokeToken(orgRef.id, tokenId);
|
|
13601
13675
|
console.error(`${tokenId} revoked`);
|
|
13602
13676
|
});
|
|
13603
|
-
token.command("delete <tokenId>").description("permanently delete a revoked service token (revoke it first)").option("--org <slug>").action(async (tokenId, options) => {
|
|
13677
|
+
token.command("delete <tokenId>").description("permanently delete a revoked service token (revoke it first)").option("--org <slug>", "organization slug (defaults to seekrit.json, or your only org)").option("-y, --yes", "skip the confirmation").action(async (tokenId, options) => {
|
|
13604
13678
|
const ctx = buildContext();
|
|
13605
13679
|
const orgRef = await resolveOrg(ctx, options.org);
|
|
13680
|
+
await confirmDestructive(options.yes, `Permanently delete ${tokenId}? Its audit history keeps the id, but the token row is gone.`);
|
|
13606
13681
|
await ctx.client.deleteToken(orgRef.id, tokenId);
|
|
13607
13682
|
console.error(`${tokenId} deleted`);
|
|
13608
13683
|
});
|
|
@@ -13633,7 +13708,7 @@ registerSyncCommands(program);
|
|
|
13633
13708
|
registerBillingCommands(program);
|
|
13634
13709
|
const argv = process.argv.map((arg) => arg === "-v" ? "--version" : arg);
|
|
13635
13710
|
program.parseAsync(argv).catch((err) => {
|
|
13636
|
-
fail(
|
|
13711
|
+
fail(describeError(err));
|
|
13637
13712
|
});
|
|
13638
13713
|
//#endregion
|
|
13639
13714
|
export { verifyMessage as A, toBase64 as B, isServiceToken as C, importVerifyingKey as D, importSigningKey as E, kmsBlobKeyRef as F, kmsDecrypt as I, kmsEncrypt as L, generateMysqlCredential as M, generateDataKey as N, signMessage as O, generateEncryptKeyMaterial as P, wrapDek as R, createServiceToken as S, generateSigningKeyMaterial as T, parseBranchTtl as V, isTokenAuth as _, ensureM2mAdminToken as a, writeProjectConfig as b, kmsResolveKey as c, resolveAppEnv as d, resolveBranch as f, getDek as g, resolveOrg as h, materializeEnv as i, generatePostgresCredential as j, signatureKeyRef as k, kmsResolveRecipient as l, resolveGroup as m, fetchDecryptedSecrets as n, kmsCallerIdentity as o, resolveEnvTarget as p, fetchDecryptedVersion as r, kmsRecoverMaterial as s, encryptAndSetSecret as t, resolveApp as u, tryBuildContext as v, parseServiceToken as w, version as x, setFailThrows as y, generateDek as z };
|