@caelo-cms/provisioning 0.10.29 → 0.10.31
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/admin-domain.d.ts +54 -0
- package/dist/admin-domain.d.ts.map +1 -0
- package/dist/admin-domain.js +122 -0
- package/dist/admin-domain.js.map +1 -0
- package/dist/cli.js +71 -7
- package/dist/cli.js.map +1 -1
- package/dist/compose.d.ts +7 -9
- package/dist/compose.d.ts.map +1 -1
- package/dist/compose.js +17 -1
- package/dist/compose.js.map +1 -1
- package/dist/deployed-release.d.ts +84 -0
- package/dist/deployed-release.d.ts.map +1 -0
- package/dist/deployed-release.js +182 -0
- package/dist/deployed-release.js.map +1 -0
- package/dist/gcloud-retry.d.ts +16 -0
- package/dist/gcloud-retry.d.ts.map +1 -0
- package/dist/gcloud-retry.js +17 -0
- package/dist/gcloud-retry.js.map +1 -0
- package/dist/gcloud.d.ts.map +1 -1
- package/dist/gcloud.js +2 -0
- package/dist/gcloud.js.map +1 -1
- package/dist/gcp-names.d.ts +58 -0
- package/dist/gcp-names.d.ts.map +1 -0
- package/dist/gcp-names.js +88 -0
- package/dist/gcp-names.js.map +1 -0
- package/dist/install-state.d.ts +31 -0
- package/dist/install-state.d.ts.map +1 -1
- package/dist/install-state.js +38 -0
- package/dist/install-state.js.map +1 -1
- package/dist/lifecycle.d.ts +5 -0
- package/dist/lifecycle.d.ts.map +1 -1
- package/dist/lifecycle.js +340 -50
- package/dist/lifecycle.js.map +1 -1
- package/dist/mcp-iap.d.ts +5 -26
- package/dist/mcp-iap.d.ts.map +1 -1
- package/dist/mcp-iap.js +6 -18
- package/dist/mcp-iap.js.map +1 -1
- package/dist/migration-runner.d.ts +25 -0
- package/dist/migration-runner.d.ts.map +1 -1
- package/dist/migration-runner.js +60 -19
- package/dist/migration-runner.js.map +1 -1
- package/dist/operator-access.d.ts +83 -0
- package/dist/operator-access.d.ts.map +1 -0
- package/dist/operator-access.js +562 -0
- package/dist/operator-access.js.map +1 -0
- package/dist/region-data.d.ts +30 -0
- package/dist/region-data.d.ts.map +1 -0
- package/dist/region-data.js +406 -0
- package/dist/region-data.js.map +1 -0
- package/dist/regions.d.ts +130 -0
- package/dist/regions.d.ts.map +1 -0
- package/dist/regions.js +247 -0
- package/dist/regions.js.map +1 -0
- package/dist/runtime-secrets.d.ts +128 -0
- package/dist/runtime-secrets.d.ts.map +1 -0
- package/dist/runtime-secrets.js +444 -0
- package/dist/runtime-secrets.js.map +1 -0
- package/dist/stack-contract.d.ts +231 -0
- package/dist/stack-contract.d.ts.map +1 -0
- package/dist/stack-contract.js +455 -0
- package/dist/stack-contract.js.map +1 -0
- package/dist/stack-converge.d.ts +183 -0
- package/dist/stack-converge.d.ts.map +1 -0
- package/dist/stack-converge.js +513 -0
- package/dist/stack-converge.js.map +1 -0
- package/dist/wizard.d.ts +7 -0
- package/dist/wizard.d.ts.map +1 -1
- package/dist/wizard.js +11 -1
- package/dist/wizard.js.map +1 -1
- package/dist/wizards/gcp-cost.d.ts +10 -10
- package/dist/wizards/gcp-cost.d.ts.map +1 -1
- package/dist/wizards/gcp-cost.js +40 -3
- package/dist/wizards/gcp-cost.js.map +1 -1
- package/dist/wizards/gcp-firebase.d.ts +2 -0
- package/dist/wizards/gcp-firebase.d.ts.map +1 -1
- package/dist/wizards/gcp-firebase.js +1 -0
- package/dist/wizards/gcp-firebase.js.map +1 -1
- package/dist/wizards/gcp-pulumi.d.ts +51 -1
- package/dist/wizards/gcp-pulumi.d.ts.map +1 -1
- package/dist/wizards/gcp-pulumi.js +89 -6
- package/dist/wizards/gcp-pulumi.js.map +1 -1
- package/dist/wizards/gcp.d.ts +2 -0
- package/dist/wizards/gcp.d.ts.map +1 -1
- package/dist/wizards/gcp.js +171 -23
- package/dist/wizards/gcp.js.map +1 -1
- package/package.json +3 -3
- package/stacks/aws/Pulumi.yaml +5 -2
- package/stacks/aws/README.md +3 -1
- package/stacks/aws/index.ts +21 -1
- package/stacks/azure/Pulumi.yaml +6 -3
- package/stacks/azure/README.md +1 -1
- package/stacks/azure/index.ts +22 -3
- package/stacks/gcp/Pulumi.yaml +5 -5
- package/stacks/gcp/README.md +15 -3
- package/stacks/gcp/index.ts +204 -141
- package/stacks/gcp-firebase/Pulumi.yaml +5 -2
- package/stacks/gcp-firebase/index.ts +169 -76
- package/stacks/self-hosted/Pulumi.yaml +4 -0
- package/stacks/self-hosted/index.ts +3 -0
package/dist/regions.js
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
2
|
+
/**
|
|
3
|
+
* The cloud region an install runs in: which regions each provider adapter
|
|
4
|
+
* can be installed in, what the wizard suggests, and the rule that the
|
|
5
|
+
* region is fixed once an install exists (#607).
|
|
6
|
+
*
|
|
7
|
+
* Why a static list instead of asking the cloud at run time: none of the
|
|
8
|
+
* providers offers one query for "every service this stack needs is
|
|
9
|
+
* available here". GCP's `gcloud run regions list` only covers Cloud Run and
|
|
10
|
+
* needs a project with the API already enabled — i.e. after we created
|
|
11
|
+
* billable state. So each catalog below is the intersection of the per-
|
|
12
|
+
* service region lists from the provider's own documentation (URLs next to
|
|
13
|
+
* each list). Azure is the exception: Microsoft documents no static
|
|
14
|
+
* Container Apps list and names `az provider show` as the source of truth,
|
|
15
|
+
* so the Azure catalog adds that live check on top of its static list and
|
|
16
|
+
* fails loudly when it can't run.
|
|
17
|
+
*
|
|
18
|
+
* The region is immutable after install: Cloud SQL, buckets, secrets, Cloud
|
|
19
|
+
* Run services and the scheduler job all live in it, and moving them is a
|
|
20
|
+
* migration Caelo does not do. A different region on a re-run or `upgrade`
|
|
21
|
+
* is refused, never applied.
|
|
22
|
+
*/
|
|
23
|
+
import { spawn } from "node:child_process";
|
|
24
|
+
import { AWS_REGIONS, AZURE_REGIONS, GCP_REGION_NAMES, GCP_RESTRICTED_REGIONS, GCP_SERVICE_REGIONS, GCP_SERVICES, } from "./region-data.js";
|
|
25
|
+
/** Default {@link CliRunner}: spawns the binary; a missing binary is a failed result. */
|
|
26
|
+
export const runCli = (cmd, args) => new Promise((resolve) => {
|
|
27
|
+
const child = spawn(cmd, [...args], { stdio: ["ignore", "pipe", "pipe"] });
|
|
28
|
+
const out = [];
|
|
29
|
+
const err = [];
|
|
30
|
+
child.stdout.on("data", (c) => out.push(c));
|
|
31
|
+
child.stderr.on("data", (c) => err.push(c));
|
|
32
|
+
child.on("error", (e) => resolve({ ok: false, stdout: "", stderr: e.message }));
|
|
33
|
+
child.on("close", (code) => resolve({
|
|
34
|
+
ok: code === 0,
|
|
35
|
+
stdout: Buffer.concat(out).toString("utf8"),
|
|
36
|
+
stderr: Buffer.concat(err).toString("utf8"),
|
|
37
|
+
}));
|
|
38
|
+
});
|
|
39
|
+
/**
|
|
40
|
+
* Regions where Azure Container Apps managed environments are offered for
|
|
41
|
+
* the signed-in subscription, as the Azure CLI reports them. Never throws;
|
|
42
|
+
* a missing CLI or no permission is an error result.
|
|
43
|
+
*/
|
|
44
|
+
async function queryAzureContainerAppsRegions(run) {
|
|
45
|
+
const r = await run("az", [
|
|
46
|
+
"provider",
|
|
47
|
+
"show",
|
|
48
|
+
"--namespace",
|
|
49
|
+
"Microsoft.App",
|
|
50
|
+
"--query",
|
|
51
|
+
"resourceTypes[?resourceType=='managedEnvironments'].locations | [0]",
|
|
52
|
+
"--output",
|
|
53
|
+
"json",
|
|
54
|
+
]);
|
|
55
|
+
if (!r.ok) {
|
|
56
|
+
return {
|
|
57
|
+
ok: false,
|
|
58
|
+
error: `could not ask Azure where Container Apps is available (az provider show --namespace Microsoft.App): ${r.stderr.trim() || "no output"}. Install the Azure CLI and run \`az login\`, then re-run.`,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
let names;
|
|
62
|
+
try {
|
|
63
|
+
names = JSON.parse(r.stdout);
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return { ok: false, error: `az provider show returned unparseable output: ${r.stdout.trim()}` };
|
|
67
|
+
}
|
|
68
|
+
if (!Array.isArray(names) || names.length === 0) {
|
|
69
|
+
return { ok: false, error: "az provider show listed no Container Apps regions." };
|
|
70
|
+
}
|
|
71
|
+
// The API reports display names ("West Europe"); region ids are the
|
|
72
|
+
// lower-cased name without spaces ("westeurope").
|
|
73
|
+
return {
|
|
74
|
+
ok: true,
|
|
75
|
+
regions: new Set(names.map((n) => String(n).toLowerCase().replace(/\s+/g, ""))),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function gcpCatalog(provider) {
|
|
79
|
+
const services = [...GCP_SERVICES];
|
|
80
|
+
if (provider === "gcp-firebase")
|
|
81
|
+
services.push("Cloud Run domain mapping");
|
|
82
|
+
const lists = services.map((s) => new Set(GCP_SERVICE_REGIONS[s] ?? []));
|
|
83
|
+
const regions = Object.keys(GCP_REGION_NAMES)
|
|
84
|
+
.filter((id) => !GCP_RESTRICTED_REGIONS.includes(id) && lists.every((l) => l.has(id)))
|
|
85
|
+
.map((id) => ({ id, name: GCP_REGION_NAMES[id] }));
|
|
86
|
+
return { provider, euDefault: "europe-west1", regions, services };
|
|
87
|
+
}
|
|
88
|
+
/** The region catalog for `provider`. */
|
|
89
|
+
export function regionCatalog(provider) {
|
|
90
|
+
switch (provider) {
|
|
91
|
+
case "gcp":
|
|
92
|
+
case "gcp-firebase":
|
|
93
|
+
return gcpCatalog(provider);
|
|
94
|
+
case "aws":
|
|
95
|
+
return {
|
|
96
|
+
provider,
|
|
97
|
+
euDefault: "eu-central-1",
|
|
98
|
+
regions: AWS_REGIONS,
|
|
99
|
+
services: ["ECS Fargate", "RDS for PostgreSQL", "S3", "Secrets Manager"],
|
|
100
|
+
};
|
|
101
|
+
case "azure":
|
|
102
|
+
return {
|
|
103
|
+
provider,
|
|
104
|
+
euDefault: "westeurope",
|
|
105
|
+
regions: AZURE_REGIONS,
|
|
106
|
+
services: ["Container Apps", "Database for PostgreSQL flexible server", "Key Vault"],
|
|
107
|
+
liveRegions: queryAzureContainerAppsRegions,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* The regions `provider` can be installed in right now: the static catalog,
|
|
113
|
+
* narrowed by the live query where the catalog has one.
|
|
114
|
+
*/
|
|
115
|
+
export async function installableRegions(provider, run = runCli) {
|
|
116
|
+
const catalog = regionCatalog(provider);
|
|
117
|
+
if (!catalog.liveRegions)
|
|
118
|
+
return { ok: true, regions: [...catalog.regions] };
|
|
119
|
+
const live = await catalog.liveRegions(run);
|
|
120
|
+
if (!live.ok)
|
|
121
|
+
return live;
|
|
122
|
+
return { ok: true, regions: catalog.regions.filter((r) => live.regions.has(r.id)) };
|
|
123
|
+
}
|
|
124
|
+
/** The "valid regions" list for error messages. */
|
|
125
|
+
export function formatRegionList(regions) {
|
|
126
|
+
return regions.map((r) => `${r.id} (${r.name})`).join(", ");
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Check `region` against the installable regions. The error names every
|
|
130
|
+
* valid region, so a non-interactive caller can fix its `--region`.
|
|
131
|
+
*/
|
|
132
|
+
export function checkRegion(provider, region, regions) {
|
|
133
|
+
if (regions.some((r) => r.id === region))
|
|
134
|
+
return { ok: true };
|
|
135
|
+
const services = regionCatalog(provider).services.join(", ");
|
|
136
|
+
return {
|
|
137
|
+
ok: false,
|
|
138
|
+
error: `"${region}" is not a region the ${provider} install can use (it needs ${services} in the same region). Valid regions: ${formatRegionList(regions)}.`,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* The default region configured in the provider's CLI, or null when none
|
|
143
|
+
* is set or the CLI isn't installed (the wizard then suggests the EU
|
|
144
|
+
* default; the operator confirms either way).
|
|
145
|
+
*/
|
|
146
|
+
export async function detectCliRegion(provider, run = runCli, env = process.env) {
|
|
147
|
+
const first = (r) => {
|
|
148
|
+
const v = r.ok ? r.stdout.trim().split("\n")[0]?.trim() : "";
|
|
149
|
+
return v && v !== "(unset)" ? v : null;
|
|
150
|
+
};
|
|
151
|
+
switch (provider) {
|
|
152
|
+
case "gcp":
|
|
153
|
+
case "gcp-firebase":
|
|
154
|
+
return (first(await run("gcloud", ["config", "get-value", "run/region"])) ??
|
|
155
|
+
first(await run("gcloud", ["config", "get-value", "compute/region"])));
|
|
156
|
+
case "aws":
|
|
157
|
+
return (env.AWS_REGION?.trim() ||
|
|
158
|
+
env.AWS_DEFAULT_REGION?.trim() ||
|
|
159
|
+
first(await run("aws", ["configure", "get", "region"])));
|
|
160
|
+
case "azure":
|
|
161
|
+
return first(await run("az", ["config", "get", "defaults.location", "--query", "value", "-o", "tsv"]));
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* The region the picker preselects: the CLI default when it is installable,
|
|
166
|
+
* otherwise the catalog's EU default. `note` explains a skipped CLI default.
|
|
167
|
+
*/
|
|
168
|
+
export function suggestRegion(provider, cliRegion, regions) {
|
|
169
|
+
const euDefault = regionCatalog(provider).euDefault;
|
|
170
|
+
if (cliRegion && regions.some((r) => r.id === cliRegion)) {
|
|
171
|
+
return { region: cliRegion, source: "cli" };
|
|
172
|
+
}
|
|
173
|
+
return {
|
|
174
|
+
region: euDefault,
|
|
175
|
+
source: "eu-default",
|
|
176
|
+
...(cliRegion
|
|
177
|
+
? {
|
|
178
|
+
note: `Your CLI's default region ${cliRegion} lacks a service this install needs (${regionCatalog(provider).services.join(", ")}); suggesting ${euDefault} instead.`,
|
|
179
|
+
}
|
|
180
|
+
: {}),
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
/** Why a region differs from the one an install was created in. */
|
|
184
|
+
export function regionChangeRefusal(installId, recorded, requested) {
|
|
185
|
+
return (`Install ${installId} runs in ${recorded}; its region is fixed after install, so ${requested} can't be applied. ` +
|
|
186
|
+
`Its Cloud SQL database, buckets, secrets and services live in ${recorded}, and moving them is a migration Caelo does not do. ` +
|
|
187
|
+
`Re-run without --region (or with --region ${recorded}). For another region, provision a new install there.`);
|
|
188
|
+
}
|
|
189
|
+
/** Decide the install region; see {@link RegionDecision}. */
|
|
190
|
+
export function decideRegion(input) {
|
|
191
|
+
if (input.recorded && input.deployed && input.recorded !== input.deployed) {
|
|
192
|
+
return {
|
|
193
|
+
kind: "refuse",
|
|
194
|
+
error: `install.json records region ${input.recorded} for ${input.installId}, but its services run in ${input.deployed}. Fix install.json to the region the install runs in, then re-run.`,
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
const fixed = input.recorded ?? input.deployed;
|
|
198
|
+
if (fixed) {
|
|
199
|
+
if (input.requested && input.requested !== fixed) {
|
|
200
|
+
return {
|
|
201
|
+
kind: "refuse",
|
|
202
|
+
error: regionChangeRefusal(input.installId, fixed, input.requested),
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
return { kind: "keep", region: fixed, from: input.recorded ? "install.json" : "deployed" };
|
|
206
|
+
}
|
|
207
|
+
if (input.requested) {
|
|
208
|
+
const check = checkRegion(input.provider, input.requested, input.regions);
|
|
209
|
+
return check.ok
|
|
210
|
+
? { kind: "use", region: input.requested }
|
|
211
|
+
: { kind: "refuse", error: check.error };
|
|
212
|
+
}
|
|
213
|
+
const preselected = input.preselected && checkRegion(input.provider, input.preselected, input.regions).ok
|
|
214
|
+
? input.preselected
|
|
215
|
+
: null;
|
|
216
|
+
if (input.nonInteractive) {
|
|
217
|
+
if (preselected)
|
|
218
|
+
return { kind: "use", region: preselected };
|
|
219
|
+
return {
|
|
220
|
+
kind: "refuse",
|
|
221
|
+
error: `--region is required with --non-interactive: the region is fixed after install, so Caelo won't pick one for you. Valid regions: ${formatRegionList(input.regions)}.`,
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
return preselected ? { kind: "prompt", preselected } : { kind: "prompt" };
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* The region an existing install runs in, for lifecycle commands. Throws an
|
|
228
|
+
* actionable error when install.json has none (no silent default — §2).
|
|
229
|
+
*/
|
|
230
|
+
export function requireInstallRegion(meta) {
|
|
231
|
+
if (!meta.region) {
|
|
232
|
+
throw new Error(`install ${meta.installId} has no region recorded in install.json. Re-run the installer (\`bunx @caelo-cms/provisioning\`, pick "Resume wizard"): it reads the region from the deployed services and records it.`);
|
|
233
|
+
}
|
|
234
|
+
return meta.region;
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Refuse a `--region` that differs from the install's recorded one (used by
|
|
238
|
+
* `upgrade`, which never moves an install). No `requested` passes.
|
|
239
|
+
*/
|
|
240
|
+
export function assertRegionUnchanged(meta, requested) {
|
|
241
|
+
const recorded = requireInstallRegion(meta);
|
|
242
|
+
if (requested && requested !== recorded) {
|
|
243
|
+
throw new Error(regionChangeRefusal(meta.installId, recorded, requested));
|
|
244
|
+
}
|
|
245
|
+
return recorded;
|
|
246
|
+
}
|
|
247
|
+
//# sourceMappingURL=regions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"regions.js","sourceRoot":"","sources":["../src/regions.ts"],"names":[],"mappings":"AAAA,mCAAmC;AAEnC;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EACL,WAAW,EACX,aAAa,EACb,gBAAgB,EAChB,sBAAsB,EACtB,mBAAmB,EACnB,YAAY,GAEb,MAAM,kBAAkB,CAAC;AAe1B,yFAAyF;AACzF,MAAM,CAAC,MAAM,MAAM,GAAc,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAC7C,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;IACtB,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;IAC3E,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,CAAS,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IACpD,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,CAAS,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IACpD,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAChF,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CACzB,OAAO,CAAC;QACN,EAAE,EAAE,IAAI,KAAK,CAAC;QACd,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;QAC3C,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;KAC5C,CAAC,CACH,CAAC;AACJ,CAAC,CAAC,CAAC;AAEL;;;;GAIG;AACH,KAAK,UAAU,8BAA8B,CAC3C,GAAc;IAEd,MAAM,CAAC,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE;QACxB,UAAU;QACV,MAAM;QACN,aAAa;QACb,eAAe;QACf,SAAS;QACT,qEAAqE;QACrE,UAAU;QACV,MAAM;KACP,CAAC,CAAC;IACH,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QACV,OAAO;YACL,EAAE,EAAE,KAAK;YACT,KAAK,EAAE,uGAAuG,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,WAAW,4DAA4D;SACzM,CAAC;IACJ,CAAC;IACD,IAAI,KAAc,CAAC;IACnB,IAAI,CAAC;QACH,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,iDAAiD,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC;IAClG,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,oDAAoD,EAAE,CAAC;IACpF,CAAC;IACD,oEAAoE;IACpE,kDAAkD;IAClD,OAAO;QACL,EAAE,EAAE,IAAI;QACR,OAAO,EAAE,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC;KAChF,CAAC;AACJ,CAAC;AAoBD,SAAS,UAAU,CAAC,QAAgC;IAClD,MAAM,QAAQ,GAAa,CAAC,GAAG,YAAY,CAAC,CAAC;IAC7C,IAAI,QAAQ,KAAK,cAAc;QAAE,QAAQ,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;IAC3E,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,mBAAmB,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACzE,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC;SAC1C,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,sBAAsB,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;SACrF,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,gBAAgB,CAAC,EAAE,CAAW,EAAE,CAAC,CAAC,CAAC;IAC/D,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,cAAc,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;AACpE,CAAC;AAED,yCAAyC;AACzC,MAAM,UAAU,aAAa,CAAC,QAA0B;IACtD,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,KAAK,CAAC;QACX,KAAK,cAAc;YACjB,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC;QAC9B,KAAK,KAAK;YACR,OAAO;gBACL,QAAQ;gBACR,SAAS,EAAE,cAAc;gBACzB,OAAO,EAAE,WAAW;gBACpB,QAAQ,EAAE,CAAC,aAAa,EAAE,oBAAoB,EAAE,IAAI,EAAE,iBAAiB,CAAC;aACzE,CAAC;QACJ,KAAK,OAAO;YACV,OAAO;gBACL,QAAQ;gBACR,SAAS,EAAE,YAAY;gBACvB,OAAO,EAAE,aAAa;gBACtB,QAAQ,EAAE,CAAC,gBAAgB,EAAE,yCAAyC,EAAE,WAAW,CAAC;gBACpF,WAAW,EAAE,8BAA8B;aAC5C,CAAC;IACN,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,QAA0B,EAC1B,MAAiB,MAAM;IAEvB,MAAM,OAAO,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;IACxC,IAAI,CAAC,OAAO,CAAC,WAAW;QAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;IAC7E,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAC5C,IAAI,CAAC,IAAI,CAAC,EAAE;QAAE,OAAO,IAAI,CAAC;IAC1B,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;AACtF,CAAC;AAED,mDAAmD;AACnD,MAAM,UAAU,gBAAgB,CAAC,OAAgC;IAC/D,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC9D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CACzB,QAA0B,EAC1B,MAAc,EACd,OAAgC;IAEhC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IAC9D,MAAM,QAAQ,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7D,OAAO;QACL,EAAE,EAAE,KAAK;QACT,KAAK,EAAE,IAAI,MAAM,yBAAyB,QAAQ,8BAA8B,QAAQ,wCAAwC,gBAAgB,CAAC,OAAO,CAAC,GAAG;KAC7J,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,QAA0B,EAC1B,MAAiB,MAAM,EACvB,MAAoD,OAAO,CAAC,GAAG;IAE/D,MAAM,KAAK,GAAG,CAAC,CAAY,EAAE,EAAE;QAC7B,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7D,OAAO,CAAC,IAAI,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACzC,CAAC,CAAC;IACF,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,KAAK,CAAC;QACX,KAAK,cAAc;YACjB,OAAO,CACL,KAAK,CAAC,MAAM,GAAG,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,WAAW,EAAE,YAAY,CAAC,CAAC,CAAC;gBACjE,KAAK,CAAC,MAAM,GAAG,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,WAAW,EAAE,gBAAgB,CAAC,CAAC,CAAC,CACtE,CAAC;QACJ,KAAK,KAAK;YACR,OAAO,CACL,GAAG,CAAC,UAAU,EAAE,IAAI,EAAE;gBACtB,GAAG,CAAC,kBAAkB,EAAE,IAAI,EAAE;gBAC9B,KAAK,CAAC,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC,WAAW,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,CACxD,CAAC;QACJ,KAAK,OAAO;YACV,OAAO,KAAK,CACV,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE,KAAK,EAAE,mBAAmB,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CACzF,CAAC;IACN,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAC3B,QAA0B,EAC1B,SAAwB,EACxB,OAAgC;IAEhC,MAAM,SAAS,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC;IACpD,IAAI,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,EAAE,CAAC;QACzD,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAC9C,CAAC;IACD,OAAO;QACL,MAAM,EAAE,SAAS;QACjB,MAAM,EAAE,YAAY;QACpB,GAAG,CAAC,SAAS;YACX,CAAC,CAAC;gBACE,IAAI,EAAE,6BAA6B,SAAS,wCAAwC,aAAa,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,SAAS,WAAW;aACrK;YACH,CAAC,CAAC,EAAE,CAAC;KACR,CAAC;AACJ,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,mBAAmB,CACjC,SAAiB,EACjB,QAAgB,EAChB,SAAiB;IAEjB,OAAO,CACL,WAAW,SAAS,YAAY,QAAQ,2CAA2C,SAAS,qBAAqB;QACjH,iEAAiE,QAAQ,sDAAsD;QAC/H,6CAA6C,QAAQ,uDAAuD,CAC7G,CAAC;AACJ,CAAC;AAmBD,6DAA6D;AAC7D,MAAM,UAAU,YAAY,CAAC,KAc5B;IACC,IAAI,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,QAAQ,KAAK,KAAK,CAAC,QAAQ,EAAE,CAAC;QAC1E,OAAO;YACL,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,+BAA+B,KAAK,CAAC,QAAQ,QAAQ,KAAK,CAAC,SAAS,6BAA6B,KAAK,CAAC,QAAQ,oEAAoE;SAC3L,CAAC;IACJ,CAAC;IACD,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,QAAQ,CAAC;IAC/C,IAAI,KAAK,EAAE,CAAC;QACV,IAAI,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,SAAS,KAAK,KAAK,EAAE,CAAC;YACjD,OAAO;gBACL,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,mBAAmB,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;aACpE,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC;IAC7F,CAAC;IACD,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;QACpB,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QAC1E,OAAO,KAAK,CAAC,EAAE;YACb,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,SAAS,EAAE;YAC1C,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC;IAC7C,CAAC;IACD,MAAM,WAAW,GACf,KAAK,CAAC,WAAW,IAAI,WAAW,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE;QACnF,CAAC,CAAC,KAAK,CAAC,WAAW;QACnB,CAAC,CAAC,IAAI,CAAC;IACX,IAAI,KAAK,CAAC,cAAc,EAAE,CAAC;QACzB,IAAI,WAAW;YAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;QAC7D,OAAO;YACL,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,mIAAmI,gBAAgB,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG;SAC7K,CAAC;IACJ,CAAC;IACD,OAAO,WAAW,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;AAC5E,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAGpC;IACC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CACb,WAAW,IAAI,CAAC,SAAS,wLAAwL,CAClN,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC,MAAM,CAAC;AACrB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CACnC,IAAoE,EACpE,SAA6B;IAE7B,MAAM,QAAQ,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;IAC5C,IAAI,SAAS,IAAI,SAAS,KAAK,QAAQ,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC;IAC5E,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { type GcloudRunner, type Sleep } from "./gcloud-retry.js";
|
|
2
|
+
import { CLI_GENERATED_SECRETS, type CloudRunSlug } from "./stack-contract.js";
|
|
3
|
+
export interface RuntimeDeps {
|
|
4
|
+
readonly run?: GcloudRunner;
|
|
5
|
+
readonly sleep?: Sleep;
|
|
6
|
+
/** Generates a new secret value (default: 32 random bytes, hex). */
|
|
7
|
+
readonly generate?: () => string;
|
|
8
|
+
}
|
|
9
|
+
/** 32 random bytes as hex — the shape of every secret the stacks generate. */
|
|
10
|
+
export declare function generateSecretValue(): string;
|
|
11
|
+
export interface EnsureOutcome {
|
|
12
|
+
readonly id: string;
|
|
13
|
+
readonly status: "present" | "applied" | "failed";
|
|
14
|
+
readonly error?: string;
|
|
15
|
+
}
|
|
16
|
+
/** Create the gateway's run SA unless it exists. */
|
|
17
|
+
export declare function ensureGatewayServiceAccount(install: {
|
|
18
|
+
readonly projectId: string;
|
|
19
|
+
readonly env: string;
|
|
20
|
+
}, deps?: RuntimeDeps): Promise<EnsureOutcome>;
|
|
21
|
+
/**
|
|
22
|
+
* Values of CLI-generated secrets a service runs with as plain env vars,
|
|
23
|
+
* for {@link ensureGeneratedSecrets}'s `seed`.
|
|
24
|
+
*/
|
|
25
|
+
export declare function plainGeneratedSecretSeed(liveEnv: ReadonlyMap<string, {
|
|
26
|
+
readonly kind: string;
|
|
27
|
+
readonly value?: string;
|
|
28
|
+
}>): Partial<Record<(typeof CLI_GENERATED_SECRETS)[number], string>>;
|
|
29
|
+
/** Where Secret Manager keeps a secret's payload. */
|
|
30
|
+
export type SecretReplication = {
|
|
31
|
+
readonly kind: "automatic";
|
|
32
|
+
} | {
|
|
33
|
+
readonly kind: "user-managed";
|
|
34
|
+
readonly locations: readonly string[];
|
|
35
|
+
};
|
|
36
|
+
/** The stacks' `secretReplication` config value as a {@link SecretReplication}. */
|
|
37
|
+
export declare function stackSecretReplication(mode: "auto" | "regional", region: string): SecretReplication;
|
|
38
|
+
/**
|
|
39
|
+
* The replication of the install's existing `postgres-password` secret, so
|
|
40
|
+
* secrets created later match what the stack pinned (orgs with a
|
|
41
|
+
* `gcp.resourceLocations` policy reject `automatic`).
|
|
42
|
+
*/
|
|
43
|
+
export declare function readSecretReplication(install: {
|
|
44
|
+
readonly projectId: string;
|
|
45
|
+
readonly env: string;
|
|
46
|
+
}, deps?: RuntimeDeps): Promise<{
|
|
47
|
+
ok: true;
|
|
48
|
+
replication: SecretReplication;
|
|
49
|
+
} | {
|
|
50
|
+
ok: false;
|
|
51
|
+
error: string;
|
|
52
|
+
}>;
|
|
53
|
+
/**
|
|
54
|
+
* Create each secret in `CLI_GENERATED_SECRETS` that is missing, and give
|
|
55
|
+
* one that exists without an enabled version a first version. A secret that
|
|
56
|
+
* already has an enabled version is never touched, so re-runs keep values.
|
|
57
|
+
*
|
|
58
|
+
* `seed` carries values a service already runs with as plain env vars (an
|
|
59
|
+
* operator-set `CAELO_INTERNAL_SECRET`): the new secret starts with that
|
|
60
|
+
* value, so moving the var to Secret Manager migrates the credential
|
|
61
|
+
* instead of silently rotating it under callers that sign with it.
|
|
62
|
+
*/
|
|
63
|
+
export declare function ensureGeneratedSecrets(install: {
|
|
64
|
+
readonly projectId: string;
|
|
65
|
+
readonly env: string;
|
|
66
|
+
readonly replication: SecretReplication;
|
|
67
|
+
readonly seed?: Readonly<Partial<Record<(typeof CLI_GENERATED_SECRETS)[number], string>>>;
|
|
68
|
+
}, deps?: RuntimeDeps): Promise<EnsureOutcome[]>;
|
|
69
|
+
/** The secrets `rotate-secret` can rotate. */
|
|
70
|
+
export declare const ROTATABLE_SECRETS: readonly ["postgres-password", "internal-secret", "tool-approval-secret"];
|
|
71
|
+
export type RotatableSecret = (typeof ROTATABLE_SECRETS)[number];
|
|
72
|
+
/**
|
|
73
|
+
* Why `name` cannot be rotated, or `null` when it can.
|
|
74
|
+
*
|
|
75
|
+
* The KEK is refused: AI provider keys and other at-rest secrets in
|
|
76
|
+
* cms_admin are encrypted under it, and a new KEK without re-encrypting
|
|
77
|
+
* them would make them unreadable.
|
|
78
|
+
*/
|
|
79
|
+
export declare function rotationRefusal(name: string): string | null;
|
|
80
|
+
/** The deployed install `rotateRuntimeSecret` works on. */
|
|
81
|
+
export interface RotationTarget {
|
|
82
|
+
readonly projectId: string;
|
|
83
|
+
readonly region: string;
|
|
84
|
+
readonly env: string;
|
|
85
|
+
/** Deployed (Pulumi-suffixed) Cloud Run service names. */
|
|
86
|
+
readonly services: Readonly<Record<CloudRunSlug, string>>;
|
|
87
|
+
/** Cloud SQL instance name — needed for `postgres-password`. */
|
|
88
|
+
readonly sqlInstance?: string;
|
|
89
|
+
}
|
|
90
|
+
export interface RotationReport {
|
|
91
|
+
readonly ok: boolean;
|
|
92
|
+
/** What happened, in order, for the operator. */
|
|
93
|
+
readonly steps: string[];
|
|
94
|
+
readonly error?: string;
|
|
95
|
+
}
|
|
96
|
+
/** Minimal `fetch` the Cloud SQL Admin API calls need (injectable for tests). */
|
|
97
|
+
export type HttpFetch = (url: string, init: {
|
|
98
|
+
method: string;
|
|
99
|
+
headers: Record<string, string>;
|
|
100
|
+
body?: string;
|
|
101
|
+
}) => Promise<{
|
|
102
|
+
ok: boolean;
|
|
103
|
+
status: number;
|
|
104
|
+
text(): Promise<string>;
|
|
105
|
+
}>;
|
|
106
|
+
/**
|
|
107
|
+
* Rotate one runtime secret: store a new value as a new Secret Manager
|
|
108
|
+
* version and roll every service that reads it, so new revisions resolve
|
|
109
|
+
* `latest` to the new value.
|
|
110
|
+
*
|
|
111
|
+
* Nothing changes unless every reader takes the secret from Secret Manager
|
|
112
|
+
* at `latest` ({@link checkRotationReaders}).
|
|
113
|
+
*
|
|
114
|
+
* `postgres-password` also changes the password of both database roles,
|
|
115
|
+
* first, so the new version never holds a password the database rejects.
|
|
116
|
+
* The password goes to the Cloud SQL Admin API in a request body, never on
|
|
117
|
+
* argv. If a step before the new version is stored fails, the roles are
|
|
118
|
+
* set back to the previous value. Between the password change and the
|
|
119
|
+
* roll, instances of the old revision keep their open connections but
|
|
120
|
+
* cannot open new ones — the roll follows immediately, and it is attempted
|
|
121
|
+
* for every reader even when one fails, so one failed service never leaves
|
|
122
|
+
* the other behind. A failed roll is resumed with the printed commands
|
|
123
|
+
* (rolling again picks up the stored value; it does not rotate again).
|
|
124
|
+
*/
|
|
125
|
+
export declare function rotateRuntimeSecret(target: RotationTarget, secret: RotatableSecret, deps?: RuntimeDeps & {
|
|
126
|
+
readonly http?: HttpFetch;
|
|
127
|
+
}): Promise<RotationReport>;
|
|
128
|
+
//# sourceMappingURL=runtime-secrets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-secrets.d.ts","sourceRoot":"","sources":["../src/runtime-secrets.ts"],"names":[],"mappings":"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"}
|