@caelo-cms/provisioning 0.11.8 → 0.11.10
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 +10 -1
- package/dist/admin-domain.d.ts.map +1 -1
- package/dist/admin-domain.js +13 -3
- package/dist/admin-domain.js.map +1 -1
- package/dist/adopt-existing.d.ts +6 -1
- package/dist/adopt-existing.d.ts.map +1 -1
- package/dist/adopt-existing.js +86 -0
- package/dist/adopt-existing.js.map +1 -1
- package/dist/agent/command.d.ts +20 -0
- package/dist/agent/command.d.ts.map +1 -1
- package/dist/agent/command.js +32 -9
- package/dist/agent/command.js.map +1 -1
- package/dist/agent/run.d.ts +2 -0
- package/dist/agent/run.d.ts.map +1 -1
- package/dist/agent/run.js +5 -1
- package/dist/agent/run.js.map +1 -1
- package/dist/agent-db.js +65 -3
- package/dist/aws-task-roles.d.ts +4 -2
- package/dist/aws-task-roles.d.ts.map +1 -1
- package/dist/aws-task-roles.js +4 -1
- package/dist/aws-task-roles.js.map +1 -1
- package/dist/caddy.d.ts +21 -4
- package/dist/caddy.d.ts.map +1 -1
- package/dist/caddy.js +27 -3
- package/dist/caddy.js.map +1 -1
- package/dist/cli.js +12 -3
- package/dist/cli.js.map +1 -1
- package/dist/cloudsql-tls.d.ts +63 -0
- package/dist/cloudsql-tls.d.ts.map +1 -0
- package/dist/cloudsql-tls.js +289 -0
- package/dist/cloudsql-tls.js.map +1 -0
- package/dist/compose.d.ts +29 -6
- package/dist/compose.d.ts.map +1 -1
- package/dist/compose.js +95 -23
- package/dist/compose.js.map +1 -1
- package/dist/converge-checkpoint.d.ts +1 -0
- package/dist/converge-checkpoint.d.ts.map +1 -1
- package/dist/converge-checkpoint.js +8 -1
- package/dist/converge-checkpoint.js.map +1 -1
- package/dist/converge-job-gcp.d.ts.map +1 -1
- package/dist/converge-job-gcp.js +2 -11
- package/dist/converge-job-gcp.js.map +1 -1
- package/dist/deployed-release.d.ts +4 -1
- package/dist/deployed-release.d.ts.map +1 -1
- package/dist/deployed-release.js +18 -8
- package/dist/deployed-release.js.map +1 -1
- package/dist/gcp-names.d.ts +21 -0
- package/dist/gcp-names.d.ts.map +1 -1
- package/dist/gcp-names.js +24 -0
- package/dist/gcp-names.js.map +1 -1
- package/dist/gcp-url-map.d.ts.map +1 -1
- package/dist/gcp-url-map.js +6 -2
- package/dist/gcp-url-map.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/infra-contract.d.ts +1 -1
- package/dist/infra-contract.d.ts.map +1 -1
- package/dist/infra-contract.js +24 -1
- package/dist/infra-contract.js.map +1 -1
- package/dist/install-state.d.ts +6 -0
- package/dist/install-state.d.ts.map +1 -1
- package/dist/install-state.js +17 -4
- package/dist/install-state.js.map +1 -1
- package/dist/lifecycle.d.ts.map +1 -1
- package/dist/lifecycle.js +17 -8
- package/dist/lifecycle.js.map +1 -1
- package/dist/mcp-auth-proxy-setup.d.ts +48 -0
- package/dist/mcp-auth-proxy-setup.d.ts.map +1 -0
- package/dist/mcp-auth-proxy-setup.js +280 -0
- package/dist/mcp-auth-proxy-setup.js.map +1 -0
- package/dist/release-manifest.d.ts +25 -1
- package/dist/release-manifest.d.ts.map +1 -1
- package/dist/release-manifest.js +36 -3
- package/dist/release-manifest.js.map +1 -1
- package/dist/remote-mcp.d.ts +55 -18
- package/dist/remote-mcp.d.ts.map +1 -1
- package/dist/remote-mcp.js +307 -77
- package/dist/remote-mcp.js.map +1 -1
- package/dist/runtime-secrets.d.ts +9 -0
- package/dist/runtime-secrets.d.ts.map +1 -1
- package/dist/runtime-secrets.js +21 -10
- package/dist/runtime-secrets.js.map +1 -1
- package/dist/seal-key-rotation.d.ts +7 -7
- package/dist/seal-key-rotation.d.ts.map +1 -1
- package/dist/seal-key-rotation.js +22 -22
- package/dist/seal-key-rotation.js.map +1 -1
- package/dist/self-hosted-db-tls.d.ts +37 -0
- package/dist/self-hosted-db-tls.d.ts.map +1 -0
- package/dist/self-hosted-db-tls.js +220 -0
- package/dist/self-hosted-db-tls.js.map +1 -0
- package/dist/self-hosted-release.d.ts +3 -1
- package/dist/self-hosted-release.d.ts.map +1 -1
- package/dist/self-hosted-release.js +33 -9
- package/dist/self-hosted-release.js.map +1 -1
- package/dist/self-hosted-roles.d.ts +34 -0
- package/dist/self-hosted-roles.d.ts.map +1 -1
- package/dist/self-hosted-roles.js +52 -0
- package/dist/self-hosted-roles.js.map +1 -1
- package/dist/self-hosted-start.d.ts +0 -21
- package/dist/self-hosted-start.d.ts.map +1 -1
- package/dist/self-hosted-start.js +39 -1
- package/dist/self-hosted-start.js.map +1 -1
- package/dist/self-hosted-upgrade.d.ts +15 -6
- package/dist/self-hosted-upgrade.d.ts.map +1 -1
- package/dist/self-hosted-upgrade.js +72 -23
- package/dist/self-hosted-upgrade.js.map +1 -1
- package/dist/stack-contract.d.ts +170 -25
- package/dist/stack-contract.d.ts.map +1 -1
- package/dist/stack-contract.js +314 -37
- package/dist/stack-contract.js.map +1 -1
- package/dist/stack-converge.d.ts +31 -0
- package/dist/stack-converge.d.ts.map +1 -1
- package/dist/stack-converge.js +71 -30
- package/dist/stack-converge.js.map +1 -1
- package/dist/upgrade/app-roll.d.ts +25 -4
- package/dist/upgrade/app-roll.d.ts.map +1 -1
- package/dist/upgrade/app-roll.js +63 -17
- package/dist/upgrade/app-roll.js.map +1 -1
- package/dist/upgrade/converge.d.ts.map +1 -1
- package/dist/upgrade/converge.js +99 -12
- package/dist/upgrade/converge.js.map +1 -1
- package/dist/upgrade/health.d.ts +31 -7
- package/dist/upgrade/health.d.ts.map +1 -1
- package/dist/upgrade/health.js +41 -17
- package/dist/upgrade/health.js.map +1 -1
- package/dist/upgrade/image-forms.d.ts +1 -1
- package/dist/upgrade/image-forms.d.ts.map +1 -1
- package/dist/upgrade/image-forms.js +24 -7
- package/dist/upgrade/image-forms.js.map +1 -1
- package/dist/upgrade/release-images.d.ts +12 -3
- package/dist/upgrade/release-images.d.ts.map +1 -1
- package/dist/upgrade/release-images.js +13 -4
- package/dist/upgrade/release-images.js.map +1 -1
- package/dist/upgrade/upgrade.d.ts +13 -3
- package/dist/upgrade/upgrade.d.ts.map +1 -1
- package/dist/upgrade/upgrade.js +34 -2
- package/dist/upgrade/upgrade.js.map +1 -1
- package/dist/upgrader-gcp.d.ts +12 -0
- package/dist/upgrader-gcp.d.ts.map +1 -1
- package/dist/upgrader-gcp.js +49 -1
- package/dist/upgrader-gcp.js.map +1 -1
- package/dist/upgrader-iam-preflight.d.ts.map +1 -1
- package/dist/upgrader-iam-preflight.js +6 -1
- package/dist/upgrader-iam-preflight.js.map +1 -1
- package/dist/upgrader-job.d.ts +1 -1
- package/dist/upgrader-job.d.ts.map +1 -1
- package/dist/upgrader-job.js +20 -14
- package/dist/upgrader-job.js.map +1 -1
- package/dist/upgrader-records.d.ts +1 -1
- package/dist/upgrader-records.d.ts.map +1 -1
- package/dist/upgrader-records.js +26 -7
- package/dist/upgrader-records.js.map +1 -1
- package/dist/upgrader-setup.d.ts.map +1 -1
- package/dist/upgrader-setup.js +10 -5
- package/dist/upgrader-setup.js.map +1 -1
- package/dist/wizards/gcp-cost.d.ts.map +1 -1
- package/dist/wizards/gcp-cost.js +22 -7
- package/dist/wizards/gcp-cost.js.map +1 -1
- package/dist/wizards/gcp.d.ts.map +1 -1
- package/dist/wizards/gcp.js +43 -17
- package/dist/wizards/gcp.js.map +1 -1
- package/package.json +2 -2
- package/src/admin-domain.test.ts +9 -8
- package/src/admin-domain.ts +13 -3
- package/src/admin-memory.test.ts +1 -0
- package/src/adopt-existing.test.ts +39 -0
- package/src/adopt-existing.ts +83 -1
- package/src/agent/command.test.ts +49 -1
- package/src/agent/command.ts +36 -9
- package/src/agent/run.test.ts +19 -0
- package/src/agent/run.ts +11 -2
- package/src/aws-task-roles.ts +5 -2
- package/src/caddy-redirects.docker.test.ts +2 -0
- package/src/caddy-redirects.test.ts +3 -0
- package/src/caddy-validate.test.ts +7 -1
- package/src/caddy.test.ts +39 -1
- package/src/caddy.ts +36 -4
- package/src/checkpoint-secrets.test.ts +14 -6
- package/src/cli.ts +12 -1
- package/src/cloudsql-tls.test.ts +225 -0
- package/src/cloudsql-tls.ts +352 -0
- package/src/compose.ts +125 -24
- package/src/converge-checkpoint.ts +8 -1
- package/src/converge-job-gcp.ts +2 -11
- package/src/database-tls-builders.test.ts +55 -0
- package/src/deployed-release.test.ts +104 -40
- package/src/deployed-release.ts +30 -9
- package/src/gateway-env-isolation.test.ts +10 -5
- package/src/gcp-names.ts +31 -0
- package/src/gcp-url-map.test.ts +6 -8
- package/src/gcp-url-map.ts +6 -2
- package/src/index.test.ts +7 -1
- package/src/index.ts +1 -0
- package/src/infra-contract.test.ts +5 -3
- package/src/infra-contract.ts +24 -1
- package/src/install-state.ts +26 -4
- package/src/lifecycle.ts +20 -11
- package/src/mcp-auth-proxy-setup.test.ts +305 -0
- package/src/mcp-auth-proxy-setup.ts +374 -0
- package/src/mcp-iap-stacks.test.ts +1 -1
- package/src/media-volume.test.ts +1 -1
- package/src/operator-access-stacks.test.ts +1 -1
- package/src/operator-access.test.ts +5 -4
- package/src/pool-budget-stacks.test.ts +1 -1
- package/src/release-manifest.test.ts +25 -0
- package/src/release-manifest.ts +59 -4
- package/src/remote-mcp-stack-config.test.ts +19 -9
- package/src/remote-mcp.test.ts +252 -57
- package/src/remote-mcp.ts +336 -77
- package/src/runtime-secrets.test.ts +20 -7
- package/src/runtime-secrets.ts +50 -9
- package/src/seal-key-rotation.test.ts +2 -2
- package/src/seal-key-rotation.ts +25 -25
- package/src/self-hosted-compose.test.ts +108 -5
- package/src/self-hosted-db-tls.test.ts +111 -0
- package/src/self-hosted-db-tls.ts +287 -0
- package/src/self-hosted-release-resolve.test.ts +71 -0
- package/src/self-hosted-release.ts +41 -11
- package/src/self-hosted-roles.test.ts +54 -0
- package/src/self-hosted-roles.ts +58 -0
- package/src/self-hosted-start.test.ts +34 -2
- package/src/self-hosted-start.ts +20 -2
- package/src/self-hosted-upgrade.test.ts +103 -14
- package/src/self-hosted-upgrade.ts +115 -29
- package/src/stack-contract-parity.test.ts +79 -12
- package/src/stack-contract.test.ts +169 -29
- package/src/stack-contract.ts +362 -42
- package/src/stack-converge-secrets.test.ts +26 -13
- package/src/stack-converge.test.ts +199 -26
- package/src/stack-converge.ts +92 -30
- package/src/state-store.test.ts +2 -1
- package/src/upgrade/app-roll.ts +97 -19
- package/src/upgrade/converge.ts +120 -11
- package/src/upgrade/health.test.ts +63 -25
- package/src/upgrade/health.ts +54 -22
- package/src/upgrade/image-forms.test.ts +34 -0
- package/src/upgrade/image-forms.ts +23 -8
- package/src/upgrade/release-images.test.ts +5 -1
- package/src/upgrade/release-images.ts +22 -6
- package/src/upgrade/upgrade.test.ts +353 -44
- package/src/upgrade/upgrade.ts +55 -6
- package/src/upgrader-gcp.ts +65 -3
- package/src/upgrader-iam-preflight.test.ts +19 -0
- package/src/upgrader-iam-preflight.ts +6 -0
- package/src/upgrader-job.test.ts +101 -27
- package/src/upgrader-job.ts +27 -14
- package/src/upgrader-records.test.ts +97 -12
- package/src/upgrader-records.ts +28 -11
- package/src/upgrader-setup.test.ts +2 -0
- package/src/upgrader-setup.ts +10 -4
- package/src/wizards/gcp-cost.test.ts +50 -0
- package/src/wizards/gcp-cost.ts +24 -7
- package/src/wizards/gcp.ts +55 -14
- package/stacks/aws/index.ts +32 -14
- package/stacks/azure/index.ts +57 -18
- package/stacks/gcp/index.ts +83 -23
- package/stacks/gcp-firebase/index.ts +162 -33
- package/stacks/self-hosted/README.md +2 -1
- package/stacks/self-hosted/index.ts +11 -1
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { type GcloudRunner, type Sleep } from "./gcloud-retry.js";
|
|
2
|
+
import type { HttpFetch } from "./runtime-secrets.js";
|
|
3
|
+
import type { LiveEnvValue } from "./stack-converge.js";
|
|
4
|
+
/** The install's Cloud SQL instance. */
|
|
5
|
+
export interface CloudSqlTlsTarget {
|
|
6
|
+
readonly projectId: string;
|
|
7
|
+
readonly env: string;
|
|
8
|
+
readonly sqlInstance: string;
|
|
9
|
+
}
|
|
10
|
+
export interface CloudSqlTlsDeps {
|
|
11
|
+
readonly run: GcloudRunner;
|
|
12
|
+
readonly http?: HttpFetch;
|
|
13
|
+
readonly sleep?: Sleep;
|
|
14
|
+
}
|
|
15
|
+
export type CloudSqlTlsResult = {
|
|
16
|
+
readonly ok: true;
|
|
17
|
+
readonly host: string;
|
|
18
|
+
readonly done: string[];
|
|
19
|
+
} | {
|
|
20
|
+
readonly ok: false;
|
|
21
|
+
readonly error: string;
|
|
22
|
+
readonly done: string[];
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Bring the instance to verify-full: shared CA with an active server
|
|
26
|
+
* certificate from it, encrypted connections only, its DNS name resolving
|
|
27
|
+
* in the VPC. Returns the host every client must dial.
|
|
28
|
+
*/
|
|
29
|
+
export declare function ensureCloudSqlVerifyFull(t: CloudSqlTlsTarget, deps: CloudSqlTlsDeps): Promise<CloudSqlTlsResult>;
|
|
30
|
+
/** The plain values of `names` in a service's live env (secret refs and unset vars skipped). */
|
|
31
|
+
export declare function liveDatabaseUrls(liveEnv: ReadonlyMap<string, LiveEnvValue>, names: readonly string[]): Record<string, string>;
|
|
32
|
+
/** Whether a database URL dials an IP literal (an unparsable one does not). */
|
|
33
|
+
export declare function dialsIpAddress(url: string): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* `url` with its host replaced by `host`, everything else kept — or null
|
|
36
|
+
* when it already dials a host name (nothing to move).
|
|
37
|
+
*/
|
|
38
|
+
export declare function urlOnDnsHost(url: string, host: string): string | null;
|
|
39
|
+
/**
|
|
40
|
+
* Switch the live database URLs of `services` from the instance's IP to
|
|
41
|
+
* `host`, keeping their `sslmode` (the running image may not carry the CA
|
|
42
|
+
* bundle yet; the roll sets verify-full with the image that does). Every
|
|
43
|
+
* reader of the database host — the rolls, the migration job, the upgrader
|
|
44
|
+
* and operator-access jobs — takes it from these URLs, so after this they
|
|
45
|
+
* all dial the name the server's certificate carries.
|
|
46
|
+
*
|
|
47
|
+
* @param liveUrls the plain URL values each service carries now
|
|
48
|
+
*/
|
|
49
|
+
export declare function moveServicesToDnsHost(target: {
|
|
50
|
+
readonly projectId: string;
|
|
51
|
+
readonly region: string;
|
|
52
|
+
}, services: readonly {
|
|
53
|
+
readonly serviceName: string;
|
|
54
|
+
readonly liveUrls: Readonly<Record<string, string>>;
|
|
55
|
+
}[], host: string, deps: CloudSqlTlsDeps): Promise<{
|
|
56
|
+
ok: true;
|
|
57
|
+
done: string[];
|
|
58
|
+
} | {
|
|
59
|
+
ok: false;
|
|
60
|
+
error: string;
|
|
61
|
+
done: string[];
|
|
62
|
+
}>;
|
|
63
|
+
//# sourceMappingURL=cloudsql-tls.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloudsql-tls.d.ts","sourceRoot":"","sources":["../src/cloudsql-tls.ts"],"names":[],"mappings":"AA+CA,OAAO,EAAE,KAAK,YAAY,EAA2B,KAAK,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC3F,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAOtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,wCAAwC;AACxC,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,GAAG,EAAE,YAAY,CAAC;IAC3B,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;CACxB;AAED,MAAM,MAAM,iBAAiB,GACzB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,GACrE;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAwE5E;;;;GAIG;AACH,wBAAsB,wBAAwB,CAC5C,CAAC,EAAE,iBAAiB,EACpB,IAAI,EAAE,eAAe,GACpB,OAAO,CAAC,iBAAiB,CAAC,CAmH5B;AAED,gGAAgG;AAChG,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,YAAY,CAAC,EAC1C,KAAK,EAAE,SAAS,MAAM,EAAE,GACvB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAOxB;AAED,+EAA+E;AAC/E,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAMnD;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAKrE;AAED;;;;;;;;;GASG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE;IAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAC/D,QAAQ,EAAE,SAAS;IACjB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACrD,EAAE,EACH,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,eAAe,GACpB,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CA+BtF"}
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
2
|
+
/**
|
|
3
|
+
* #1338 (gateway hardening L6) — converge a Cloud SQL install to
|
|
4
|
+
* `sslmode=verify-full` through gcloud, the way `cms-provision upgrade`
|
|
5
|
+
* converges everything else (stack-converge.ts; it never runs Pulumi).
|
|
6
|
+
*
|
|
7
|
+
* Verify-full checks the server certificate's chain AND that it names the
|
|
8
|
+
* host the client dialled. On Cloud SQL that needs three things the stacks
|
|
9
|
+
* declare for a new install (stacks/gcp, stacks/gcp-firebase) and this
|
|
10
|
+
* module brings an existing one to:
|
|
11
|
+
*
|
|
12
|
+
* 1. The shared server CA (`GOOGLE_MANAGED_CAS_CA`): "The SAN field
|
|
13
|
+
* contains the hostname (DNS name of the instance) for all types of
|
|
14
|
+
* instances", while the default per-instance CA names one "only for
|
|
15
|
+
* instances enabled with Private Service Connect"
|
|
16
|
+
* (docs.cloud.google.com/sql/docs/postgres/authorize-ssl). An instance
|
|
17
|
+
* may move from per-instance to shared, not back. After the move the
|
|
18
|
+
* instance needs a server certificate from the new CA: "create a new
|
|
19
|
+
* server certificate with `gcloud sql ssl server-certs create`", then
|
|
20
|
+
* "complete the rotation with `gcloud sql ssl server-certs rotate`"
|
|
21
|
+
* (docs.cloud.google.com/sql/docs/postgres/manage-ssl-instance). The
|
|
22
|
+
* rotation restarts nothing a client keeps: open connections drop and
|
|
23
|
+
* reconnect; every client already uses TLS (`sslmode=require` before).
|
|
24
|
+
* `sslMode=ENCRYPTED_ONLY` refuses plaintext from then on.
|
|
25
|
+
* 2. Resolution of the instance's DNS name (`dnsNames`, the
|
|
26
|
+
* PRIVATE_SERVICES_ACCESS entry, `….sql-psa.goog`) inside the VPC:
|
|
27
|
+
* "create the DNS record in a private DNS zone in the corresponding
|
|
28
|
+
* Virtual Private Cloud (VPC) network"
|
|
29
|
+
* (docs.cloud.google.com/sql/docs/postgres/configure-ssl-instance).
|
|
30
|
+
* 3. The services dialling that name. They read it from their own
|
|
31
|
+
* `*_DATABASE_URL`, and so does every job the upgrade derives from the
|
|
32
|
+
* admin's (migrations, upgrader, operator access): {@link
|
|
33
|
+
* moveServicesToDnsHost} switches the host of the live URLs first,
|
|
34
|
+
* keeping their current `sslmode`, so the old image keeps working until
|
|
35
|
+
* the roll sets verify-full with the image that carries the CA bundle.
|
|
36
|
+
*
|
|
37
|
+
* The CA the clients trust is Google's published shared-CA bundle, shipped
|
|
38
|
+
* in every image (shared database-tls.ts `CLOUD_SQL_CA_BUNDLE`): it covers
|
|
39
|
+
* the root and every regional CA, so a server-certificate rotation needs no
|
|
40
|
+
* change on the client side.
|
|
41
|
+
*
|
|
42
|
+
* Every step reads before it writes and is a no-op when already in shape,
|
|
43
|
+
* so a re-run after a failure picks up where the last one stopped.
|
|
44
|
+
*/
|
|
45
|
+
import { isIpLiteral } from "@caelo-cms/shared";
|
|
46
|
+
import { realSleep, runWithRetry } from "./gcloud-retry.js";
|
|
47
|
+
import { CLOUD_SQL_SERVER_CA_MODE, CLOUD_SQL_SSL_MODE, cloudSqlDnsZoneName, cloudSqlPrivateDnsName, } from "./stack-contract.js";
|
|
48
|
+
const NOT_FOUND = /NOT_FOUND|not found|does not exist|404/i;
|
|
49
|
+
const SQL_ADMIN = "https://sqladmin.googleapis.com/v1";
|
|
50
|
+
async function describeInstance(t, run) {
|
|
51
|
+
const r = await run([
|
|
52
|
+
"sql",
|
|
53
|
+
"instances",
|
|
54
|
+
"describe",
|
|
55
|
+
t.sqlInstance,
|
|
56
|
+
`--project=${t.projectId}`,
|
|
57
|
+
"--format=json",
|
|
58
|
+
]);
|
|
59
|
+
if (!r.ok)
|
|
60
|
+
return { ok: false, error: `describe ${t.sqlInstance}: ${r.stderr.trim()}` };
|
|
61
|
+
try {
|
|
62
|
+
return { ok: true, d: JSON.parse(r.stdout) };
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return { ok: false, error: `describe ${t.sqlInstance}: gcloud printed no JSON` };
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/** The instance's server certificates and which one is active (Cloud SQL Admin API). */
|
|
69
|
+
async function listServerCertificates(t, run, http) {
|
|
70
|
+
const token = await run(["auth", "print-access-token"]);
|
|
71
|
+
const bearer = token.ok ? token.stdout.trim() : "";
|
|
72
|
+
if (!bearer)
|
|
73
|
+
return { ok: false, error: `gcloud auth print-access-token: ${token.stderr.trim()}` };
|
|
74
|
+
const res = await http(`${SQL_ADMIN}/projects/${encodeURIComponent(t.projectId)}/instances/${encodeURIComponent(t.sqlInstance)}/listServerCertificates`, { method: "GET", headers: { Authorization: `Bearer ${bearer}` } });
|
|
75
|
+
const text = await res.text();
|
|
76
|
+
if (!res.ok) {
|
|
77
|
+
return {
|
|
78
|
+
ok: false,
|
|
79
|
+
error: `list server certificates: HTTP ${res.status} ${text.slice(0, 300)}`,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
const body = JSON.parse(text);
|
|
83
|
+
return {
|
|
84
|
+
ok: true,
|
|
85
|
+
activeVersion: body.activeVersion ?? null,
|
|
86
|
+
fingerprints: (body.serverCerts ?? []).map((c) => c.sha1Fingerprint ?? "").filter(Boolean),
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Bring the instance to verify-full: shared CA with an active server
|
|
91
|
+
* certificate from it, encrypted connections only, its DNS name resolving
|
|
92
|
+
* in the VPC. Returns the host every client must dial.
|
|
93
|
+
*/
|
|
94
|
+
export async function ensureCloudSqlVerifyFull(t, deps) {
|
|
95
|
+
const sleep = deps.sleep ?? realSleep;
|
|
96
|
+
const run = (args) => runWithRetry(deps.run, sleep, args);
|
|
97
|
+
const http = deps.http ?? fetch;
|
|
98
|
+
const done = [];
|
|
99
|
+
const fail = (error) => ({ ok: false, error, done });
|
|
100
|
+
const project = `--project=${t.projectId}`;
|
|
101
|
+
let described = await describeInstance(t, run);
|
|
102
|
+
if (!described.ok)
|
|
103
|
+
return fail(described.error);
|
|
104
|
+
const ip = described.d.settings?.ipConfiguration;
|
|
105
|
+
const patch = [];
|
|
106
|
+
if (ip?.serverCaMode !== CLOUD_SQL_SERVER_CA_MODE) {
|
|
107
|
+
patch.push(`--server-ca-mode=${CLOUD_SQL_SERVER_CA_MODE}`);
|
|
108
|
+
}
|
|
109
|
+
if (ip?.sslMode !== CLOUD_SQL_SSL_MODE)
|
|
110
|
+
patch.push(`--ssl-mode=${CLOUD_SQL_SSL_MODE}`);
|
|
111
|
+
if (patch.length > 0) {
|
|
112
|
+
const r = await run(["sql", "instances", "patch", t.sqlInstance, project, ...patch, "--quiet"]);
|
|
113
|
+
if (!r.ok)
|
|
114
|
+
return fail(`patch ${t.sqlInstance} (${patch.join(" ")}): ${r.stderr.trim()}`);
|
|
115
|
+
done.push(`Cloud SQL ${t.sqlInstance}: ${patch.join(" ")}`);
|
|
116
|
+
}
|
|
117
|
+
// The active server certificate must come from the shared CA. Before the
|
|
118
|
+
// move there is none in the list the shared CA keeps; after an
|
|
119
|
+
// interrupted run there may be an upcoming one that was never rotated in.
|
|
120
|
+
const certs = await listServerCertificates(t, run, http);
|
|
121
|
+
if (!certs.ok)
|
|
122
|
+
return fail(certs.error);
|
|
123
|
+
const activeShared = certs.activeVersion !== null && certs.fingerprints.includes(certs.activeVersion);
|
|
124
|
+
if (!activeShared) {
|
|
125
|
+
const upcoming = certs.fingerprints.filter((f) => f !== certs.activeVersion);
|
|
126
|
+
if (upcoming.length === 0) {
|
|
127
|
+
const c = await run([
|
|
128
|
+
"sql",
|
|
129
|
+
"ssl",
|
|
130
|
+
"server-certs",
|
|
131
|
+
"create",
|
|
132
|
+
`--instance=${t.sqlInstance}`,
|
|
133
|
+
project,
|
|
134
|
+
]);
|
|
135
|
+
if (!c.ok)
|
|
136
|
+
return fail(`create a server certificate: ${c.stderr.trim()}`);
|
|
137
|
+
done.push(`Cloud SQL ${t.sqlInstance}: server certificate from the shared CA created`);
|
|
138
|
+
}
|
|
139
|
+
const rot = await run([
|
|
140
|
+
"sql",
|
|
141
|
+
"ssl",
|
|
142
|
+
"server-certs",
|
|
143
|
+
"rotate",
|
|
144
|
+
`--instance=${t.sqlInstance}`,
|
|
145
|
+
project,
|
|
146
|
+
"--quiet",
|
|
147
|
+
]);
|
|
148
|
+
if (!rot.ok)
|
|
149
|
+
return fail(`rotate to the shared-CA server certificate: ${rot.stderr.trim()}`);
|
|
150
|
+
done.push(`Cloud SQL ${t.sqlInstance}: rotated onto the shared-CA server certificate`);
|
|
151
|
+
described = await describeInstance(t, run);
|
|
152
|
+
if (!described.ok)
|
|
153
|
+
return fail(described.error);
|
|
154
|
+
}
|
|
155
|
+
const host = cloudSqlPrivateDnsName(described.d.dnsNames);
|
|
156
|
+
if (!host) {
|
|
157
|
+
return fail(`${t.sqlInstance} reports no PRIVATE_SERVICES_ACCESS DNS name (dnsNames) although it uses the shared CA; verify-full needs it. Check the instance's private IP configuration and re-run.`);
|
|
158
|
+
}
|
|
159
|
+
const privateIp = described.d.ipAddresses?.find((a) => a.type === "PRIVATE")?.ipAddress;
|
|
160
|
+
if (!privateIp)
|
|
161
|
+
return fail(`${t.sqlInstance} has no private IP address`);
|
|
162
|
+
const network = ip?.privateNetwork?.split("/").pop();
|
|
163
|
+
if (!network)
|
|
164
|
+
return fail(`${t.sqlInstance} names no private network`);
|
|
165
|
+
const zone = cloudSqlDnsZoneName(t.env);
|
|
166
|
+
const fqdn = `${host}.`;
|
|
167
|
+
const z = await run(["dns", "managed-zones", "describe", zone, project, "--format=json"]);
|
|
168
|
+
if (z.ok) {
|
|
169
|
+
const existing = JSON.parse(z.stdout).dnsName?.toLowerCase();
|
|
170
|
+
if (existing !== fqdn) {
|
|
171
|
+
return fail(`the private DNS zone ${zone} serves ${existing ?? "(no name)"}, not the instance's DNS name ${fqdn}. If the instance was replaced, delete the zone (gcloud dns managed-zones delete ${zone} ${project}) after removing its records, then re-run.`);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
else if (NOT_FOUND.test(z.stderr)) {
|
|
175
|
+
const c = await run([
|
|
176
|
+
"dns",
|
|
177
|
+
"managed-zones",
|
|
178
|
+
"create",
|
|
179
|
+
zone,
|
|
180
|
+
project,
|
|
181
|
+
`--dns-name=${fqdn}`,
|
|
182
|
+
"--visibility=private",
|
|
183
|
+
`--networks=${network}`,
|
|
184
|
+
`--description=Caelo ${t.env}: the Cloud SQL instance's DNS name inside the VPC (#1338)`,
|
|
185
|
+
]);
|
|
186
|
+
if (!c.ok)
|
|
187
|
+
return fail(`create the private DNS zone ${zone}: ${c.stderr.trim()}`);
|
|
188
|
+
done.push(`private DNS zone ${zone} (${fqdn}) on network ${network}`);
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
return fail(`describe the private DNS zone ${zone}: ${z.stderr.trim()}`);
|
|
192
|
+
}
|
|
193
|
+
const rec = ["dns", "record-sets"];
|
|
194
|
+
const where = [fqdn, `--zone=${zone}`, "--type=A", project];
|
|
195
|
+
const a = await run([...rec, "describe", ...where, "--format=json"]);
|
|
196
|
+
if (a.ok) {
|
|
197
|
+
const rrdatas = JSON.parse(a.stdout).rrdatas ?? [];
|
|
198
|
+
if (rrdatas.length !== 1 || rrdatas[0] !== privateIp) {
|
|
199
|
+
const u = await run([...rec, "update", ...where, "--ttl=300", `--rrdatas=${privateIp}`]);
|
|
200
|
+
if (!u.ok)
|
|
201
|
+
return fail(`update the A record of ${fqdn}: ${u.stderr.trim()}`);
|
|
202
|
+
done.push(`DNS ${fqdn} A ${rrdatas.join(",") || "(none)"} → ${privateIp}`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
else if (NOT_FOUND.test(a.stderr)) {
|
|
206
|
+
const c = await run([...rec, "create", ...where, "--ttl=300", `--rrdatas=${privateIp}`]);
|
|
207
|
+
if (!c.ok)
|
|
208
|
+
return fail(`create the A record of ${fqdn}: ${c.stderr.trim()}`);
|
|
209
|
+
done.push(`DNS ${fqdn} A ${privateIp}`);
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
return fail(`describe the A record of ${fqdn}: ${a.stderr.trim()}`);
|
|
213
|
+
}
|
|
214
|
+
return { ok: true, host, done };
|
|
215
|
+
}
|
|
216
|
+
/** The plain values of `names` in a service's live env (secret refs and unset vars skipped). */
|
|
217
|
+
export function liveDatabaseUrls(liveEnv, names) {
|
|
218
|
+
const out = {};
|
|
219
|
+
for (const name of names) {
|
|
220
|
+
const v = liveEnv.get(name);
|
|
221
|
+
if (v?.kind === "value" && v.value)
|
|
222
|
+
out[name] = v.value;
|
|
223
|
+
}
|
|
224
|
+
return out;
|
|
225
|
+
}
|
|
226
|
+
/** Whether a database URL dials an IP literal (an unparsable one does not). */
|
|
227
|
+
export function dialsIpAddress(url) {
|
|
228
|
+
try {
|
|
229
|
+
return isIpLiteral(new URL(url).hostname);
|
|
230
|
+
}
|
|
231
|
+
catch {
|
|
232
|
+
return false;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* `url` with its host replaced by `host`, everything else kept — or null
|
|
237
|
+
* when it already dials a host name (nothing to move).
|
|
238
|
+
*/
|
|
239
|
+
export function urlOnDnsHost(url, host) {
|
|
240
|
+
const parsed = new URL(url);
|
|
241
|
+
if (!isIpLiteral(parsed.hostname))
|
|
242
|
+
return null;
|
|
243
|
+
parsed.hostname = host;
|
|
244
|
+
return parsed.toString();
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Switch the live database URLs of `services` from the instance's IP to
|
|
248
|
+
* `host`, keeping their `sslmode` (the running image may not carry the CA
|
|
249
|
+
* bundle yet; the roll sets verify-full with the image that does). Every
|
|
250
|
+
* reader of the database host — the rolls, the migration job, the upgrader
|
|
251
|
+
* and operator-access jobs — takes it from these URLs, so after this they
|
|
252
|
+
* all dial the name the server's certificate carries.
|
|
253
|
+
*
|
|
254
|
+
* @param liveUrls the plain URL values each service carries now
|
|
255
|
+
*/
|
|
256
|
+
export async function moveServicesToDnsHost(target, services, host, deps) {
|
|
257
|
+
const sleep = deps.sleep ?? realSleep;
|
|
258
|
+
const done = [];
|
|
259
|
+
for (const s of services) {
|
|
260
|
+
const moved = Object.entries(s.liveUrls)
|
|
261
|
+
.map(([name, url]) => [name, urlOnDnsHost(url, host)])
|
|
262
|
+
.filter((e) => e[1] !== null);
|
|
263
|
+
if (moved.length === 0)
|
|
264
|
+
continue;
|
|
265
|
+
const r = await runWithRetry(deps.run, sleep, [
|
|
266
|
+
"run",
|
|
267
|
+
"services",
|
|
268
|
+
"update",
|
|
269
|
+
s.serviceName,
|
|
270
|
+
"--region",
|
|
271
|
+
target.region,
|
|
272
|
+
`--project=${target.projectId}`,
|
|
273
|
+
// ^|^ — the values carry `&` and `=`; a custom delimiter keeps gcloud
|
|
274
|
+
// from splitting them.
|
|
275
|
+
`--update-env-vars=^|^${moved.map(([n, u]) => `${n}=${u}`).join("|")}`,
|
|
276
|
+
"--quiet",
|
|
277
|
+
]);
|
|
278
|
+
if (!r.ok) {
|
|
279
|
+
return {
|
|
280
|
+
ok: false,
|
|
281
|
+
error: `move ${s.serviceName} onto the database's DNS name: ${r.stderr.trim()}`,
|
|
282
|
+
done,
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
done.push(`${s.serviceName}: ${moved.map(([n]) => n).join(", ")} → ${host}`);
|
|
286
|
+
}
|
|
287
|
+
return { ok: true, done };
|
|
288
|
+
}
|
|
289
|
+
//# sourceMappingURL=cloudsql-tls.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloudsql-tls.js","sourceRoot":"","sources":["../src/cloudsql-tls.ts"],"names":[],"mappings":"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"}
|
package/dist/compose.d.ts
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import { type ReleaseService } from "./upgrade/release-images.js";
|
|
2
|
-
/** The
|
|
2
|
+
/** The release images, each `ghcr.io/caelo-cms/<svc>@sha256:…`. */
|
|
3
3
|
export interface ReleaseImages {
|
|
4
4
|
readonly mode: "release";
|
|
5
5
|
readonly admin: string;
|
|
6
6
|
readonly gateway: string;
|
|
7
|
+
/**
|
|
8
|
+
* #1328 — the MCP-Auth-Proxy. Absent only for a release recorded before
|
|
9
|
+
* the proxy shipped (a rollback target in release.json): its Compose file
|
|
10
|
+
* then has no proxy service, exactly as that release ran.
|
|
11
|
+
*/
|
|
12
|
+
readonly "mcp-auth-proxy"?: string;
|
|
7
13
|
}
|
|
8
14
|
/**
|
|
9
15
|
* Contributor-only: run the admin + gateway from the Caelo checkout the
|
|
@@ -44,11 +50,18 @@ export declare const MEDIA_DIR = "media";
|
|
|
44
50
|
export declare const MEDIA_ROOT = "/data/media";
|
|
45
51
|
/** The gateway's HTTP port inside the Compose network. */
|
|
46
52
|
export declare const COMPOSE_GATEWAY_PORT = 8090;
|
|
53
|
+
/** #1328 — the MCP-Auth-Proxy's HTTP port inside the Compose network. */
|
|
54
|
+
export declare const COMPOSE_MCP_AUTH_PROXY_PORT = 8095;
|
|
55
|
+
/** #1328 — the Compose service name of the MCP-Auth-Proxy. */
|
|
56
|
+
export declare const COMPOSE_MCP_AUTH_PROXY_SERVICE = "caelo-mcp-auth-proxy";
|
|
47
57
|
/**
|
|
48
|
-
* The Compose services that
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
58
|
+
* The Compose services that touch the databases — what `backup` and
|
|
59
|
+
* `restore` stop while they read or rewrite them. Workers run inside the
|
|
60
|
+
* admin (CLAUDE.md §11.B Tier 5); there is no orchestrator or runner
|
|
61
|
+
* service. The MCP-Auth-Proxy (#1328) is deliberately not here: it holds no
|
|
62
|
+
* database login, so it keeps running, and a release from before it has no
|
|
63
|
+
* such service for `up` to start. Its health is checked wherever the
|
|
64
|
+
* install starts (self-hosted-start.ts) or rolls (self-hosted-upgrade.ts).
|
|
52
65
|
*/
|
|
53
66
|
export declare const COMPOSE_APP_SERVICES: readonly ["caelo-admin", "caelo-gateway"];
|
|
54
67
|
/**
|
|
@@ -58,6 +71,7 @@ export declare const COMPOSE_APP_SERVICES: readonly ["caelo-admin", "caelo-gatew
|
|
|
58
71
|
*/
|
|
59
72
|
export declare const COMPOSE_ADMIN_UPSTREAM = "caelo-admin:5173";
|
|
60
73
|
export declare const COMPOSE_GATEWAY_UPSTREAM = "caelo-gateway:8090";
|
|
74
|
+
export declare const COMPOSE_MCP_AUTH_PROXY_UPSTREAM = "caelo-mcp-auth-proxy:8095";
|
|
61
75
|
/**
|
|
62
76
|
* The Caddy image, pinned to the release the generated Caddyfile is
|
|
63
77
|
* validated against (caddy-validate.test.ts runs `caddy validate` on this
|
|
@@ -125,6 +139,15 @@ export interface ComposeSpec {
|
|
|
125
139
|
* the gateway never gets it.
|
|
126
140
|
*/
|
|
127
141
|
readonly internalSecret: string;
|
|
142
|
+
/**
|
|
143
|
+
* #1338 — SHA-256 (hex) of the database server certificate the Postgres
|
|
144
|
+
* service mounts (`.caelo/postgres-tls/server.crt`). It is part of the
|
|
145
|
+
* service's environment so a renewed certificate changes the service's
|
|
146
|
+
* definition and `docker compose up -d` recreates Postgres: a bind-mounted
|
|
147
|
+
* file whose content changes does not, and Postgres would keep serving
|
|
148
|
+
* the old certificate until verify-full clients refuse it.
|
|
149
|
+
*/
|
|
150
|
+
readonly dbTlsServerCertSha256: string;
|
|
128
151
|
readonly anthropicApiKey?: string;
|
|
129
152
|
readonly resendApiKey?: string;
|
|
130
153
|
readonly diskSize: string;
|
|
@@ -135,7 +158,7 @@ export interface ComposeSpec {
|
|
|
135
158
|
* busy host never OOM-kills the admin at the limit.
|
|
136
159
|
*/
|
|
137
160
|
readonly adminMemory?: string;
|
|
138
|
-
/** Which
|
|
161
|
+
/** Which Caelo images run (see {@link ComposeImages}). */
|
|
139
162
|
readonly images: ComposeImages;
|
|
140
163
|
/**
|
|
141
164
|
* The host ports Caddy listens on (`80` / `443` for a public install —
|
package/dist/compose.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compose.d.ts","sourceRoot":"","sources":["../src/compose.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"compose.d.ts","sourceRoot":"","sources":["../src/compose.ts"],"names":[],"mappings":"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"}
|