@seekrit/cli 0.17.0 → 0.17.2
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 +203 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7,6 +7,128 @@ import { homedir, tmpdir } from "node:os";
|
|
|
7
7
|
import { dirname, join, parse } from "node:path";
|
|
8
8
|
import { createInterface } from "node:readline";
|
|
9
9
|
import { Writable } from "node:stream";
|
|
10
|
+
/** All catalog keys as a runtime array (for iteration / zod enums). */
|
|
11
|
+
const ENTITLEMENT_KEYS = Object.keys({
|
|
12
|
+
"feature.kms": {
|
|
13
|
+
kind: "feature",
|
|
14
|
+
label: "Managed keys (KMS)",
|
|
15
|
+
description: "Client-side managed keys for application-layer encryption and signing.",
|
|
16
|
+
default: true
|
|
17
|
+
},
|
|
18
|
+
"feature.leases": {
|
|
19
|
+
kind: "feature",
|
|
20
|
+
label: "Temporary access",
|
|
21
|
+
description: "Vault-style short-lived database and cloud credentials.",
|
|
22
|
+
default: true
|
|
23
|
+
},
|
|
24
|
+
"feature.log_sink": {
|
|
25
|
+
kind: "feature",
|
|
26
|
+
label: "Audit log export (SIEM)",
|
|
27
|
+
description: "Stream the audit log to an external OTLP collector.",
|
|
28
|
+
default: true
|
|
29
|
+
},
|
|
30
|
+
"feature.proxy": {
|
|
31
|
+
kind: "feature",
|
|
32
|
+
label: "Agent egress proxy",
|
|
33
|
+
description: "Substitute secrets into outbound requests for untrusted workloads.",
|
|
34
|
+
default: true
|
|
35
|
+
},
|
|
36
|
+
"feature.sso": {
|
|
37
|
+
kind: "feature",
|
|
38
|
+
label: "SSO / SAML",
|
|
39
|
+
description: "Single sign-on beyond the built-in providers.",
|
|
40
|
+
default: true
|
|
41
|
+
},
|
|
42
|
+
"apps.max": {
|
|
43
|
+
kind: "limit",
|
|
44
|
+
label: "Applications",
|
|
45
|
+
description: "Maximum applications in the organization.",
|
|
46
|
+
default: null
|
|
47
|
+
},
|
|
48
|
+
"envs.per_app.max": {
|
|
49
|
+
kind: "limit",
|
|
50
|
+
label: "Environments per application",
|
|
51
|
+
description: "Maximum environments under a single application.",
|
|
52
|
+
default: null
|
|
53
|
+
},
|
|
54
|
+
"secrets.per_env.max": {
|
|
55
|
+
kind: "limit",
|
|
56
|
+
label: "Secrets per environment",
|
|
57
|
+
description: "Maximum secrets in a single environment.",
|
|
58
|
+
default: null
|
|
59
|
+
},
|
|
60
|
+
"groups.max": {
|
|
61
|
+
kind: "limit",
|
|
62
|
+
label: "Groups",
|
|
63
|
+
description: "Maximum reusable secret groups in the organization.",
|
|
64
|
+
default: null
|
|
65
|
+
},
|
|
66
|
+
"tokens.max": {
|
|
67
|
+
kind: "limit",
|
|
68
|
+
label: "Service tokens",
|
|
69
|
+
description: "Maximum active service tokens in the organization.",
|
|
70
|
+
default: null
|
|
71
|
+
},
|
|
72
|
+
"kms.keys.max": {
|
|
73
|
+
kind: "limit",
|
|
74
|
+
label: "Managed keys",
|
|
75
|
+
description: "Maximum managed KMS keys in the organization.",
|
|
76
|
+
default: null
|
|
77
|
+
},
|
|
78
|
+
"lease.targets.max": {
|
|
79
|
+
kind: "limit",
|
|
80
|
+
label: "Lease targets",
|
|
81
|
+
description: "Maximum registered temporary-access targets.",
|
|
82
|
+
default: null
|
|
83
|
+
},
|
|
84
|
+
members: {
|
|
85
|
+
kind: "metered",
|
|
86
|
+
label: "Members",
|
|
87
|
+
description: "Users in the organization. Included in the plan, then billed per seat.",
|
|
88
|
+
default: null,
|
|
89
|
+
metric: "member_count"
|
|
90
|
+
},
|
|
91
|
+
"resolves.monthly": {
|
|
92
|
+
kind: "metered",
|
|
93
|
+
label: "Monthly resolves",
|
|
94
|
+
description: "Secret resolutions per month. Included in the plan, then billed per unit.",
|
|
95
|
+
default: null,
|
|
96
|
+
metric: "monthly_resolves"
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
const PLAN_FAMILY_IDS = Object.keys({
|
|
100
|
+
free: {
|
|
101
|
+
id: "free",
|
|
102
|
+
name: "Free",
|
|
103
|
+
description: "Get started with the essentials.",
|
|
104
|
+
current: 1
|
|
105
|
+
},
|
|
106
|
+
pro: {
|
|
107
|
+
id: "pro",
|
|
108
|
+
name: "Pro",
|
|
109
|
+
description: "For teams running secrets in production.",
|
|
110
|
+
current: 1
|
|
111
|
+
},
|
|
112
|
+
enterprise: {
|
|
113
|
+
id: "enterprise",
|
|
114
|
+
name: "Enterprise",
|
|
115
|
+
description: "Unlimited scale with advanced governance.",
|
|
116
|
+
current: 1
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
//#endregion
|
|
120
|
+
//#region ../../packages/core/src/billing.ts
|
|
121
|
+
/**
|
|
122
|
+
* Lifecycle states a subscription can be in. Mirrors the biller's own states
|
|
123
|
+
* (Stripe) but is provider-neutral so a different biller could map onto it.
|
|
124
|
+
*/
|
|
125
|
+
const SUBSCRIPTION_STATUSES = [
|
|
126
|
+
"trialing",
|
|
127
|
+
"active",
|
|
128
|
+
"past_due",
|
|
129
|
+
"canceled",
|
|
130
|
+
"paused"
|
|
131
|
+
];
|
|
10
132
|
z.enum([
|
|
11
133
|
"postgres",
|
|
12
134
|
"mysql",
|
|
@@ -540,6 +662,9 @@ z.object({
|
|
|
540
662
|
name: nameSchema,
|
|
541
663
|
slug: slugSchema
|
|
542
664
|
});
|
|
665
|
+
z.object({ name: nameSchema });
|
|
666
|
+
z.object({ name: nameSchema });
|
|
667
|
+
z.object({ name: nameSchema });
|
|
543
668
|
z.object({
|
|
544
669
|
email: emailSchema,
|
|
545
670
|
role: inviteRoleSchema.default("member")
|
|
@@ -639,6 +764,26 @@ z.object({
|
|
|
639
764
|
headers: z.record(z.string().min(1).max(256), z.string().max(4096)).optional(),
|
|
640
765
|
enabled: z.boolean().default(true)
|
|
641
766
|
});
|
|
767
|
+
const planFamilySchema = z.enum(PLAN_FAMILY_IDS);
|
|
768
|
+
const subscriptionStatusSchema = z.enum(SUBSCRIPTION_STATUSES);
|
|
769
|
+
z.enum(ENTITLEMENT_KEYS);
|
|
770
|
+
/** An entitlement value: boolean (features), number or null/unlimited (limits, metered). */
|
|
771
|
+
const entitlementValueSchema = z.union([
|
|
772
|
+
z.boolean(),
|
|
773
|
+
z.number(),
|
|
774
|
+
z.null()
|
|
775
|
+
]);
|
|
776
|
+
z.object({
|
|
777
|
+
family: planFamilySchema,
|
|
778
|
+
version: z.number().int().positive().optional(),
|
|
779
|
+
status: subscriptionStatusSchema.default("active")
|
|
780
|
+
});
|
|
781
|
+
z.object({
|
|
782
|
+
value: entitlementValueSchema,
|
|
783
|
+
note: z.string().max(500).nullish(),
|
|
784
|
+
expiresAt: z.iso.datetime().nullish()
|
|
785
|
+
});
|
|
786
|
+
z.object({ family: planFamilySchema });
|
|
642
787
|
z.object({
|
|
643
788
|
cursor: z.string().optional(),
|
|
644
789
|
limit: z.coerce.number().int().min(1).max(200).default(50),
|
|
@@ -1576,7 +1721,7 @@ function isServiceToken(value) {
|
|
|
1576
1721
|
}
|
|
1577
1722
|
//#endregion
|
|
1578
1723
|
//#region package.json
|
|
1579
|
-
var version = "0.17.
|
|
1724
|
+
var version = "0.17.2";
|
|
1580
1725
|
//#endregion
|
|
1581
1726
|
//#region ../../packages/api-client/src/index.ts
|
|
1582
1727
|
var SeekritApiError = class extends Error {
|
|
@@ -1646,6 +1791,10 @@ var SeekritClient = class {
|
|
|
1646
1791
|
getOrg(orgId) {
|
|
1647
1792
|
return this.request("GET", `/v1/orgs/${orgId}`);
|
|
1648
1793
|
}
|
|
1794
|
+
/** Rename an organization (display name only — the slug is immutable). */
|
|
1795
|
+
updateOrg(orgId, input) {
|
|
1796
|
+
return this.request("PATCH", `/v1/orgs/${orgId}`, input);
|
|
1797
|
+
}
|
|
1649
1798
|
listMembers(orgId) {
|
|
1650
1799
|
return this.request("GET", `/v1/orgs/${orgId}/members`);
|
|
1651
1800
|
}
|
|
@@ -1667,6 +1816,10 @@ var SeekritClient = class {
|
|
|
1667
1816
|
getApp(orgId, appId) {
|
|
1668
1817
|
return this.request("GET", `/v1/orgs/${orgId}/apps/${appId}`);
|
|
1669
1818
|
}
|
|
1819
|
+
/** Rename an application (display name only — the slug is immutable). */
|
|
1820
|
+
updateApp(orgId, appId, input) {
|
|
1821
|
+
return this.request("PATCH", `/v1/orgs/${orgId}/apps/${appId}`, input);
|
|
1822
|
+
}
|
|
1670
1823
|
deleteApp(orgId, appId) {
|
|
1671
1824
|
return this.request("DELETE", `/v1/orgs/${orgId}/apps/${appId}`);
|
|
1672
1825
|
}
|
|
@@ -1691,6 +1844,10 @@ var SeekritClient = class {
|
|
|
1691
1844
|
getGroup(orgId, groupId) {
|
|
1692
1845
|
return this.request("GET", `/v1/orgs/${orgId}/groups/${groupId}`);
|
|
1693
1846
|
}
|
|
1847
|
+
/** Rename a group (display name only — the slug is immutable). */
|
|
1848
|
+
updateGroup(orgId, groupId, input) {
|
|
1849
|
+
return this.request("PATCH", `/v1/orgs/${orgId}/groups/${groupId}`, input);
|
|
1850
|
+
}
|
|
1694
1851
|
deleteGroup(orgId, groupId) {
|
|
1695
1852
|
return this.request("DELETE", `/v1/orgs/${orgId}/groups/${groupId}`);
|
|
1696
1853
|
}
|
|
@@ -1748,6 +1905,10 @@ var SeekritClient = class {
|
|
|
1748
1905
|
revokeToken(orgId, tokenId) {
|
|
1749
1906
|
return this.request("DELETE", `/v1/orgs/${orgId}/tokens/${tokenId}`);
|
|
1750
1907
|
}
|
|
1908
|
+
/** Permanently delete a token. Only allowed once it has been revoked. */
|
|
1909
|
+
deleteToken(orgId, tokenId) {
|
|
1910
|
+
return this.request("DELETE", `/v1/orgs/${orgId}/tokens/${tokenId}/permanent`);
|
|
1911
|
+
}
|
|
1751
1912
|
/** Keys the caller can see: all org keys for admins, granted keys otherwise. */
|
|
1752
1913
|
listKmsKeys(orgId) {
|
|
1753
1914
|
return this.request("GET", `/v1/orgs/${orgId}/kms/keys`);
|
|
@@ -1828,6 +1989,40 @@ var SeekritClient = class {
|
|
|
1828
1989
|
testLogSink(orgId) {
|
|
1829
1990
|
return this.request("POST", `/v1/orgs/${orgId}/log-sink/test`);
|
|
1830
1991
|
}
|
|
1992
|
+
/**
|
|
1993
|
+
* The org's plan, effective entitlements, current metered usage ("X of Y"),
|
|
1994
|
+
* overrides, and which self-serve actions are available (`manage`). Readable
|
|
1995
|
+
* by any member; `enforced` reports whether limits are currently active
|
|
1996
|
+
* (false until plans are turned on, when every org has full access).
|
|
1997
|
+
*/
|
|
1998
|
+
getBilling(orgId) {
|
|
1999
|
+
return this.request("GET", `/v1/orgs/${orgId}/billing`);
|
|
2000
|
+
}
|
|
2001
|
+
/**
|
|
2002
|
+
* Start self-serve checkout to upgrade the org to a plan family. Returns a
|
|
2003
|
+
* biller-hosted URL to redirect the browser to. Admin-only; the biller must
|
|
2004
|
+
* be configured (see `getBilling().manage`). The resulting subscription links
|
|
2005
|
+
* back to the org via the checkout webhook.
|
|
2006
|
+
*/
|
|
2007
|
+
startCheckout(orgId, input) {
|
|
2008
|
+
return this.request("POST", `/v1/orgs/${orgId}/billing/checkout`, input);
|
|
2009
|
+
}
|
|
2010
|
+
/**
|
|
2011
|
+
* Open the biller's Billing Portal to manage the existing subscription
|
|
2012
|
+
* (update card, change plan, cancel). Returns a URL to redirect to. Admin-only
|
|
2013
|
+
* and only once a biller customer is linked (see `getBilling().manage.portal`).
|
|
2014
|
+
*/
|
|
2015
|
+
openBillingPortal(orgId) {
|
|
2016
|
+
return this.request("POST", `/v1/orgs/${orgId}/billing/portal`);
|
|
2017
|
+
}
|
|
2018
|
+
/**
|
|
2019
|
+
* Downgrade the org to the Free (default) plan: cancels any active paid
|
|
2020
|
+
* subscription in the biller and reverts the org to Free immediately.
|
|
2021
|
+
* Admin-only. Refetch `getBilling` for the new state.
|
|
2022
|
+
*/
|
|
2023
|
+
cancelSubscription(orgId) {
|
|
2024
|
+
return this.request("POST", `/v1/orgs/${orgId}/billing/cancel`);
|
|
2025
|
+
}
|
|
1831
2026
|
};
|
|
1832
2027
|
const PROJECT_FILE = "seekrit.json";
|
|
1833
2028
|
function globalConfigPath() {
|
|
@@ -2586,7 +2781,7 @@ function registerKmsCommands(program) {
|
|
|
2586
2781
|
});
|
|
2587
2782
|
console.error(`rotated ${rotated.name} to v${rotated.currentVersion} (${grants.length} grantees)`);
|
|
2588
2783
|
});
|
|
2589
|
-
kms.command("disable").description("disable a key (blocks new grants/rotations
|
|
2784
|
+
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) => {
|
|
2590
2785
|
const ctx = buildContext();
|
|
2591
2786
|
const org = await resolveOrg(ctx, options.org);
|
|
2592
2787
|
const key = await kmsResolveKey(ctx, org.id, options.key);
|
|
@@ -3886,6 +4081,12 @@ token.command("revoke <tokenId>").description("revoke a service token").option("
|
|
|
3886
4081
|
await ctx.client.revokeToken(orgRef.id, tokenId);
|
|
3887
4082
|
console.error(`${tokenId} revoked`);
|
|
3888
4083
|
});
|
|
4084
|
+
token.command("delete <tokenId>").description("permanently delete a revoked service token (revoke it first)").option("--org <slug>").action(async (tokenId, options) => {
|
|
4085
|
+
const ctx = buildContext();
|
|
4086
|
+
const orgRef = await resolveOrg(ctx, options.org);
|
|
4087
|
+
await ctx.client.deleteToken(orgRef.id, tokenId);
|
|
4088
|
+
console.error(`${tokenId} deleted`);
|
|
4089
|
+
});
|
|
3889
4090
|
registerPgCommands(program);
|
|
3890
4091
|
registerMysqlCommands(program);
|
|
3891
4092
|
registerRedisCommands(program);
|