@caelo-cms/provisioning 0.10.38 → 0.10.40

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.
Files changed (66) hide show
  1. package/dist/admin-domain.d.ts +21 -3
  2. package/dist/admin-domain.d.ts.map +1 -1
  3. package/dist/admin-domain.js +88 -16
  4. package/dist/admin-domain.js.map +1 -1
  5. package/dist/cert-wait.d.ts +84 -0
  6. package/dist/cert-wait.d.ts.map +1 -0
  7. package/dist/cert-wait.js +95 -0
  8. package/dist/cert-wait.js.map +1 -0
  9. package/dist/checkpoint-secrets.d.ts +88 -0
  10. package/dist/checkpoint-secrets.d.ts.map +1 -0
  11. package/dist/checkpoint-secrets.js +245 -0
  12. package/dist/checkpoint-secrets.js.map +1 -0
  13. package/dist/cli.js +160 -28
  14. package/dist/cli.js.map +1 -1
  15. package/dist/dns/groups.d.ts +36 -0
  16. package/dist/dns/groups.d.ts.map +1 -0
  17. package/dist/dns/groups.js +46 -0
  18. package/dist/dns/groups.js.map +1 -0
  19. package/dist/gcloud-components.d.ts +42 -0
  20. package/dist/gcloud-components.d.ts.map +1 -0
  21. package/dist/gcloud-components.js +53 -0
  22. package/dist/gcloud-components.js.map +1 -0
  23. package/dist/gcloud.d.ts +14 -0
  24. package/dist/gcloud.d.ts.map +1 -1
  25. package/dist/gcloud.js +18 -5
  26. package/dist/gcloud.js.map +1 -1
  27. package/dist/install-state.d.ts +19 -1
  28. package/dist/install-state.d.ts.map +1 -1
  29. package/dist/install-state.js +37 -3
  30. package/dist/install-state.js.map +1 -1
  31. package/dist/lifecycle.d.ts.map +1 -1
  32. package/dist/lifecycle.js +24 -3
  33. package/dist/lifecycle.js.map +1 -1
  34. package/dist/redirects-emit.d.ts +0 -13
  35. package/dist/redirects-emit.d.ts.map +1 -1
  36. package/dist/redirects-emit.js +19 -0
  37. package/dist/redirects-emit.js.map +1 -1
  38. package/dist/regions.d.ts.map +1 -1
  39. package/dist/regions.js +4 -1
  40. package/dist/regions.js.map +1 -1
  41. package/dist/runtime-secrets.d.ts +13 -1
  42. package/dist/runtime-secrets.d.ts.map +1 -1
  43. package/dist/runtime-secrets.js +40 -4
  44. package/dist/runtime-secrets.js.map +1 -1
  45. package/dist/self-hosted-roles.d.ts.map +1 -1
  46. package/dist/self-hosted-roles.js +2 -0
  47. package/dist/self-hosted-roles.js.map +1 -1
  48. package/dist/stack-contract.d.ts +16 -2
  49. package/dist/stack-contract.d.ts.map +1 -1
  50. package/dist/stack-contract.js +24 -1
  51. package/dist/stack-contract.js.map +1 -1
  52. package/dist/wizard.d.ts +5 -19
  53. package/dist/wizard.d.ts.map +1 -1
  54. package/dist/wizard.js +53 -4
  55. package/dist/wizard.js.map +1 -1
  56. package/dist/wizards/gcp-pulumi.d.ts +21 -0
  57. package/dist/wizards/gcp-pulumi.d.ts.map +1 -1
  58. package/dist/wizards/gcp-pulumi.js +25 -5
  59. package/dist/wizards/gcp-pulumi.js.map +1 -1
  60. package/dist/wizards/gcp.d.ts.map +1 -1
  61. package/dist/wizards/gcp.js +160 -116
  62. package/dist/wizards/gcp.js.map +1 -1
  63. package/package.json +3 -3
  64. package/stacks/gcp/index.ts +20 -3
  65. package/stacks/gcp-firebase/index.ts +20 -5
  66. package/stacks/self-hosted/index.ts +3 -1
@@ -1,6 +1,8 @@
1
1
  /**
2
2
  * `cms-provision admin-domain enable` — serve a gcp-firebase admin at
3
- * `admin.<domain>` instead of its `*.run.app` URL.
3
+ * `admin.<domain>` instead of its `*.run.app` URL — and, the same way,
4
+ * `cms-provision staging-domain enable` (#650): serve the protected staging
5
+ * site at `staging.<domain>` from the gateway, which gates and proxies it.
4
6
  *
5
7
  * The gcp-firebase stack only creates that Cloud Run domain mapping behind
6
8
  * `provisionAdminDomain=true`, off by default: Google refuses a mapping
@@ -44,11 +46,27 @@ export type AdminDomainResult = {
44
46
  status: "failed";
45
47
  error: string;
46
48
  };
47
- export declare function enableAdminDomain(opts: {
49
+ /** What `staging-domain enable` reports; same shape as the admin's. */
50
+ export type StagingDomainResult = AdminDomainResult;
51
+ interface DomainOpts {
48
52
  projectId: string;
49
53
  region: string;
50
54
  domain: string;
51
55
  run?: Run;
52
- }): Promise<AdminDomainResult>;
56
+ /** Progress lines (the one-time `beta` component install); defaults to stdout. */
57
+ log?: (message: string) => void;
58
+ }
59
+ export declare function enableAdminDomain(opts: DomainOpts): Promise<AdminDomainResult>;
60
+ /**
61
+ * #650 — map the install's staging host (its setting, default
62
+ * `staging.<domain>`; any FQDN) to the gateway, which serves the protected
63
+ * staging site. Cloud Run refuses domain-mapped requests while a service's
64
+ * ingress is internal-only, so the gateway's ingress is opened first (the
65
+ * stack declares the same since #650; installs from before keep the old
66
+ * value until this runs). Idempotent like the admin mapping.
67
+ */
68
+ export declare function enableStagingDomain(opts: DomainOpts & {
69
+ stagingHost: string;
70
+ }): Promise<StagingDomainResult>;
53
71
  export {};
54
72
  //# sourceMappingURL=admin-domain.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"admin-domain.d.ts","sourceRoot":"","sources":["../src/admin-domain.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAA2B,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAEzE,KAAK,GAAG,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;AAErD,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,MAAM,iBAAiB,GACzB;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,cAAc,EAAE,CAAA;CAAE,GACnF;IAAE,MAAM,EAAE,oBAAoB,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GACxE;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAexC,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAC5C,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,GAAG,CAAC;CACX,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAyF7B"}
1
+ {"version":3,"file":"admin-domain.d.ts","sourceRoot":"","sources":["../src/admin-domain.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,EAA2B,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAGzE,KAAK,GAAG,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;AAErD,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,MAAM,iBAAiB,GACzB;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,cAAc,EAAE,CAAA;CAAE,GACnF;IAAE,MAAM,EAAE,oBAAoB,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GACxE;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAExC,uEAAuE;AACvE,MAAM,MAAM,mBAAmB,GAAG,iBAAiB,CAAC;AAepD,UAAU,UAAU;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,GAAG,CAAC;IACV,kFAAkF;IAClF,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC;AA2CD,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAMpF;AAED;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,UAAU,GAAG;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE,GACzC,OAAO,CAAC,mBAAmB,CAAC,CAwC9B"}
@@ -1,7 +1,9 @@
1
1
  // SPDX-License-Identifier: MPL-2.0
2
2
  /**
3
3
  * `cms-provision admin-domain enable` — serve a gcp-firebase admin at
4
- * `admin.<domain>` instead of its `*.run.app` URL.
4
+ * `admin.<domain>` instead of its `*.run.app` URL — and, the same way,
5
+ * `cms-provision staging-domain enable` (#650): serve the protected staging
6
+ * site at `staging.<domain>` from the gateway, which gates and proxies it.
5
7
  *
6
8
  * The gcp-firebase stack only creates that Cloud Run domain mapping behind
7
9
  * `provisionAdminDomain=true`, off by default: Google refuses a mapping
@@ -26,6 +28,7 @@
26
28
  * from the start.
27
29
  */
28
30
  import { gcloud as defaultGcloud } from "./gcloud.js";
31
+ import { ensureGcloudComponent } from "./gcloud-components.js";
29
32
  function recordsOf(json, hostname) {
30
33
  const parsed = JSON.parse(json);
31
34
  return (parsed.status?.resourceRecords ?? []).map((r) => ({
@@ -34,36 +37,105 @@ function recordsOf(json, hostname) {
34
37
  value: r.rrdata ?? "",
35
38
  }));
36
39
  }
37
- export async function enableAdminDomain(opts) {
38
- const run = opts.run ?? defaultGcloud;
39
- const hostname = `admin.${opts.domain}`;
40
- const scope = [`--region=${opts.region}`, `--project=${opts.projectId}`];
40
+ function logOf(opts) {
41
+ return opts.log ?? ((message) => console.log(message));
42
+ }
43
+ /** The one deployed Cloud Run service of `slug` (Pulumi-suffixed name). */
44
+ async function findService(run, scope, slug) {
45
+ const prefix = `caelo-production-${slug}`;
41
46
  const services = await run([
42
47
  "run",
43
48
  "services",
44
49
  "list",
45
50
  ...scope,
46
- "--filter=metadata.name~^caelo-production-admin",
51
+ `--filter=metadata.name~^${prefix}`,
47
52
  "--format=value(metadata.name)",
48
53
  ]);
49
54
  if (!services.ok) {
50
- return { status: "failed", error: `list Cloud Run services: ${services.stderr.trim()}` };
55
+ return { ok: false, error: `list Cloud Run services: ${services.stderr.trim()}` };
51
56
  }
52
57
  const matches = services.stdout
53
58
  .split("\n")
54
59
  .map((s) => s.trim())
55
60
  .filter(Boolean);
56
- // Fail closed like the other admin lookups: with a leftover service from a
57
- // failed deploy, picking one would bind the domain to the wrong revision.
61
+ // Fail closed like the other service lookups: with a leftover service from
62
+ // a failed deploy, picking one would bind the domain to the wrong revision.
58
63
  const service = matches.length === 1 ? matches[0] : undefined;
59
64
  if (!service) {
60
65
  return {
61
- status: "failed",
66
+ ok: false,
62
67
  error: matches.length === 0
63
- ? "admin Cloud Run service not found: no caelo-production-admin* service"
64
- : `expected exactly one caelo-production-admin* Cloud Run service, found ${matches.length} (${matches.join(", ")}); delete the stale one first`,
68
+ ? `${slug} Cloud Run service not found: no ${prefix}* service`
69
+ : `expected exactly one ${prefix}* Cloud Run service, found ${matches.length} (${matches.join(", ")}); delete the stale one first`,
65
70
  };
66
71
  }
72
+ return { ok: true, service };
73
+ }
74
+ export async function enableAdminDomain(opts) {
75
+ const run = opts.run ?? defaultGcloud;
76
+ const scope = [`--region=${opts.region}`, `--project=${opts.projectId}`];
77
+ const found = await findService(run, scope, "admin");
78
+ if (!found.ok)
79
+ return { status: "failed", error: found.error };
80
+ return mapDomain(run, logOf(opts), scope, opts.domain, `admin.${opts.domain}`, found.service);
81
+ }
82
+ /**
83
+ * #650 — map the install's staging host (its setting, default
84
+ * `staging.<domain>`; any FQDN) to the gateway, which serves the protected
85
+ * staging site. Cloud Run refuses domain-mapped requests while a service's
86
+ * ingress is internal-only, so the gateway's ingress is opened first (the
87
+ * stack declares the same since #650; installs from before keep the old
88
+ * value until this runs). Idempotent like the admin mapping.
89
+ */
90
+ export async function enableStagingDomain(opts) {
91
+ const run = opts.run ?? defaultGcloud;
92
+ const scope = [`--region=${opts.region}`, `--project=${opts.projectId}`];
93
+ const found = await findService(run, scope, "gateway");
94
+ if (!found.ok)
95
+ return { status: "failed", error: found.error };
96
+ const ingress = await run([
97
+ "run",
98
+ "services",
99
+ "describe",
100
+ found.service,
101
+ ...scope,
102
+ '--format=value(metadata.annotations["run.googleapis.com/ingress"])',
103
+ ]);
104
+ if (!ingress.ok) {
105
+ return { status: "failed", error: `read the gateway's ingress: ${ingress.stderr.trim()}` };
106
+ }
107
+ if (ingress.stdout.trim() !== "all") {
108
+ const update = await run([
109
+ "run",
110
+ "services",
111
+ "update",
112
+ found.service,
113
+ ...scope,
114
+ "--ingress=all",
115
+ "--quiet",
116
+ ]);
117
+ if (!update.ok) {
118
+ return {
119
+ status: "failed",
120
+ error: `open the gateway's ingress for the domain mapping: ${update.stderr.trim()}`,
121
+ };
122
+ }
123
+ }
124
+ // Search Console verification: the install domain covers its own
125
+ // subdomains; a host on another domain is verified itself.
126
+ const verifyDomain = opts.stagingHost === opts.domain || opts.stagingHost.endsWith(`.${opts.domain}`)
127
+ ? opts.domain
128
+ : opts.stagingHost;
129
+ return mapDomain(run, logOf(opts), scope, verifyDomain, opts.stagingHost, found.service);
130
+ }
131
+ /** Steps 2–4 of the module doc for `hostname` → `service`. */
132
+ async function mapDomain(run, log, scope, domain, hostname, service) {
133
+ // Fully managed Cloud Run domain mappings exist only on the beta track: the
134
+ // GA `gcloud run domain-mappings` is Cloud Run for Anthos only. Install the
135
+ // component up front instead of letting gcloud ask for it mid-command.
136
+ const beta = await ensureGcloudComponent("beta", { run, log });
137
+ if (!beta.ok)
138
+ return { status: "failed", error: beta.error };
67
139
  const describeArgs = [
68
140
  "beta",
69
141
  "run",
@@ -88,15 +160,15 @@ export async function enableAdminDomain(opts) {
88
160
  return { status: "failed", error: `list verified domains: ${verified.stderr.trim()}` };
89
161
  }
90
162
  const verifiedIds = verified.stdout.split("\n").map((s) => s.trim());
91
- if (!verifiedIds.includes(opts.domain) && !verifiedIds.includes(hostname)) {
92
- const verify = await run(["domains", "verify", opts.domain]);
163
+ if (!verifiedIds.includes(domain) && !verifiedIds.includes(hostname)) {
164
+ const verify = await run(["domains", "verify", domain]);
93
165
  if (!verify.ok) {
94
166
  return {
95
167
  status: "failed",
96
- error: `start domain verification for ${opts.domain}: ${verify.stderr.trim()}`,
168
+ error: `start domain verification for ${domain}: ${verify.stderr.trim()}`,
97
169
  };
98
170
  }
99
- return { status: "needs-verification", hostname, verifyDomain: opts.domain };
171
+ return { status: "needs-verification", hostname, verifyDomain: domain };
100
172
  }
101
173
  const create = await run([
102
174
  "beta",
@@ -1 +1 @@
1
- {"version":3,"file":"admin-domain.js","sourceRoot":"","sources":["../src/admin-domain.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"admin-domain.js","sourceRoot":"","sources":["../src/admin-domain.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Waiting for a Google-managed TLS certificate (§11.C: the CLI polls certs
3
+ * itself instead of telling the operator to check back later).
4
+ *
5
+ * Two certificate sources, one wait loop:
6
+ * - the `gcp` load balancer's managed SSL certificates
7
+ * ({@link lbCertProbe}) — the installer waits for the admin host;
8
+ * - a Cloud Run domain mapping's certificate ({@link domainMappingProbe})
9
+ * — `admin-domain enable` / `staging-domain enable` on gcp-firebase.
10
+ *
11
+ * {@link waitForCert} is pure apart from its injected clock, sleep and
12
+ * probe, so the timeout and progress behaviour is unit-tested without
13
+ * gcloud or real time.
14
+ */
15
+ import type { GcloudResult } from "./gcloud.js";
16
+ type Run = (args: string[]) => Promise<GcloudResult>;
17
+ /** One look at a certificate. */
18
+ export type CertProbe = {
19
+ readonly state: "ready";
20
+ } | {
21
+ readonly state: "pending";
22
+ readonly detail: string;
23
+ }
24
+ /** gcloud itself failed (auth, permissions) — waiting will not fix it. */
25
+ | {
26
+ readonly state: "error";
27
+ readonly error: string;
28
+ };
29
+ export type CertWaitResult = {
30
+ readonly ok: true;
31
+ } | {
32
+ readonly ok: false;
33
+ readonly reason: "timeout";
34
+ readonly lastDetail: string;
35
+ } | {
36
+ readonly ok: false;
37
+ readonly reason: "error";
38
+ readonly error: string;
39
+ };
40
+ export interface CertWaitOpts {
41
+ readonly probe: () => Promise<CertProbe>;
42
+ readonly timeoutMs: number;
43
+ readonly intervalMs: number;
44
+ /** Called whenever the probe's detail text changes (spinner message). */
45
+ readonly onUpdate?: (detail: string) => void;
46
+ readonly sleep?: (ms: number) => Promise<void>;
47
+ readonly now?: () => number;
48
+ }
49
+ /**
50
+ * Poll `probe` until the certificate is ready, gcloud fails, or `timeoutMs`
51
+ * passes. The probe runs once more at the deadline so a certificate that
52
+ * flips during the last interval is not reported as a timeout.
53
+ */
54
+ export declare function waitForCert(opts: CertWaitOpts): Promise<CertWaitResult>;
55
+ /**
56
+ * The certificate state of the Cloud Run domain mapping for `hostname`.
57
+ * Ready once the mapping's `Ready` condition is True (Google sets it after
58
+ * `CertificateProvisioned` and `DomainRoutable`); until then the detail is
59
+ * the first non-True condition's message, which says what Google waits for
60
+ * (usually the DNS record).
61
+ */
62
+ export declare function domainMappingProbe(run: Run, target: {
63
+ readonly hostname: string;
64
+ readonly region: string;
65
+ readonly projectId: string;
66
+ }): Promise<CertProbe>;
67
+ /**
68
+ * Whether the `gcp` load balancer has an ACTIVE managed certificate that
69
+ * covers `hostname`. Any such certificate counts: installs from before the
70
+ * admin got its own certificate serve the admin from the combined one.
71
+ * A certificate is only served once its overall status is ACTIVE, so a
72
+ * combined certificate whose other domain still fails does not count.
73
+ */
74
+ export declare function lbCertProbe(run: Run, target: {
75
+ readonly projectId: string;
76
+ readonly hostname: string;
77
+ }): Promise<CertProbe>;
78
+ /**
79
+ * How long the CLI waits for a certificate before handing the operator the
80
+ * status command. Google documents up to 60 min after DNS resolves.
81
+ */
82
+ export declare const CERT_WAIT_TIMEOUT_MS: number;
83
+ export {};
84
+ //# sourceMappingURL=cert-wait.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cert-wait.d.ts","sourceRoot":"","sources":["../src/cert-wait.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,KAAK,GAAG,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;AAErD,iCAAiC;AACjC,MAAM,MAAM,SAAS,GACjB;IAAE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAC3B;IAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE;AACxD,0EAA0E;GACxE;IAAE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAExD,MAAM,MAAM,cAAc,GACtB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAA;CAAE,GACrB;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAC/E;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7E,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,OAAO,CAAC,SAAS,CAAC,CAAC;IACzC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,yEAAyE;IACzE,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CAC7B;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,cAAc,CAAC,CAiB7E;AASD;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,GAAG,EACR,MAAM,EAAE;IAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACzF,OAAO,CAAC,SAAS,CAAC,CAwBpB;AAOD;;;;;;GAMG;AACH,wBAAsB,WAAW,CAC/B,GAAG,EAAE,GAAG,EACR,MAAM,EAAE;IAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAChE,OAAO,CAAC,SAAS,CAAC,CA+BpB;AAED;;;GAGG;AACH,eAAO,MAAM,oBAAoB,QAAiB,CAAC"}
@@ -0,0 +1,95 @@
1
+ // SPDX-License-Identifier: MPL-2.0
2
+ /**
3
+ * Poll `probe` until the certificate is ready, gcloud fails, or `timeoutMs`
4
+ * passes. The probe runs once more at the deadline so a certificate that
5
+ * flips during the last interval is not reported as a timeout.
6
+ */
7
+ export async function waitForCert(opts) {
8
+ const now = opts.now ?? Date.now;
9
+ const sleep = opts.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
10
+ const deadline = now() + opts.timeoutMs;
11
+ let lastDetail = "";
12
+ for (;;) {
13
+ const p = await opts.probe();
14
+ if (p.state === "ready")
15
+ return { ok: true };
16
+ if (p.state === "error")
17
+ return { ok: false, reason: "error", error: p.error };
18
+ if (p.detail !== lastDetail) {
19
+ lastDetail = p.detail;
20
+ opts.onUpdate?.(p.detail);
21
+ }
22
+ const remaining = deadline - now();
23
+ if (remaining <= 0)
24
+ return { ok: false, reason: "timeout", lastDetail };
25
+ await sleep(Math.min(opts.intervalMs, remaining));
26
+ }
27
+ }
28
+ /**
29
+ * The certificate state of the Cloud Run domain mapping for `hostname`.
30
+ * Ready once the mapping's `Ready` condition is True (Google sets it after
31
+ * `CertificateProvisioned` and `DomainRoutable`); until then the detail is
32
+ * the first non-True condition's message, which says what Google waits for
33
+ * (usually the DNS record).
34
+ */
35
+ export async function domainMappingProbe(run, target) {
36
+ const r = await run([
37
+ "beta",
38
+ "run",
39
+ "domain-mappings",
40
+ "describe",
41
+ `--domain=${target.hostname}`,
42
+ `--region=${target.region}`,
43
+ `--project=${target.projectId}`,
44
+ "--format=json",
45
+ ]);
46
+ if (!r.ok)
47
+ return { state: "error", error: `describe the domain mapping: ${r.stderr.trim()}` };
48
+ const conditions = JSON.parse(r.stdout).status?.conditions ??
49
+ [];
50
+ const ready = conditions.find((c) => c.type === "Ready");
51
+ if (ready?.status === "True")
52
+ return { state: "ready" };
53
+ const blocking = conditions.find((c) => c.type === "CertificateProvisioned" && c.status !== "True") ??
54
+ conditions.find((c) => c.status !== "True");
55
+ const detail = blocking
56
+ ? `${blocking.type}: ${blocking.message || blocking.reason || blocking.status || "pending"}`
57
+ : "Google has not reported the mapping's status yet";
58
+ return { state: "pending", detail };
59
+ }
60
+ /**
61
+ * Whether the `gcp` load balancer has an ACTIVE managed certificate that
62
+ * covers `hostname`. Any such certificate counts: installs from before the
63
+ * admin got its own certificate serve the admin from the combined one.
64
+ * A certificate is only served once its overall status is ACTIVE, so a
65
+ * combined certificate whose other domain still fails does not count.
66
+ */
67
+ export async function lbCertProbe(run, target) {
68
+ const r = await run([
69
+ "compute",
70
+ "ssl-certificates",
71
+ "list",
72
+ "--global",
73
+ `--project=${target.projectId}`,
74
+ "--format=json",
75
+ ]);
76
+ if (!r.ok)
77
+ return { state: "error", error: `list SSL certificates: ${r.stderr.trim()}` };
78
+ const covering = JSON.parse(r.stdout).filter((c) => c.managed?.domainStatus?.[target.hostname] !== undefined);
79
+ if (covering.some((c) => c.managed?.status === "ACTIVE" && c.managed.domainStatus?.[target.hostname] === "ACTIVE")) {
80
+ return { state: "ready" };
81
+ }
82
+ if (covering.length === 0) {
83
+ return { state: "pending", detail: `no managed certificate lists ${target.hostname} yet` };
84
+ }
85
+ const detail = covering
86
+ .map((c) => `${c.name ?? "certificate"}: ${target.hostname} ${c.managed?.domainStatus?.[target.hostname]}`)
87
+ .join("; ");
88
+ return { state: "pending", detail };
89
+ }
90
+ /**
91
+ * How long the CLI waits for a certificate before handing the operator the
92
+ * status command. Google documents up to 60 min after DNS resolves.
93
+ */
94
+ export const CERT_WAIT_TIMEOUT_MS = 60 * 60 * 1000;
95
+ //# sourceMappingURL=cert-wait.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cert-wait.js","sourceRoot":"","sources":["../src/cert-wait.ts"],"names":[],"mappings":"AAAA,mCAAmC;AA2CnC;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAkB;IAClD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC;IACjC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,EAAU,EAAE,EAAE,CAAC,IAAI,OAAO,CAAO,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IAC1F,MAAM,QAAQ,GAAG,GAAG,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC;IACxC,IAAI,UAAU,GAAG,EAAE,CAAC;IACpB,SAAS,CAAC;QACR,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;QAC7B,IAAI,CAAC,CAAC,KAAK,KAAK,OAAO;YAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;QAC7C,IAAI,CAAC,CAAC,KAAK,KAAK,OAAO;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;QAC/E,IAAI,CAAC,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;YAC5B,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC;YACtB,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QAC5B,CAAC;QACD,MAAM,SAAS,GAAG,QAAQ,GAAG,GAAG,EAAE,CAAC;QACnC,IAAI,SAAS,IAAI,CAAC;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC;QACxE,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC;IACpD,CAAC;AACH,CAAC;AASD;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,GAAQ,EACR,MAA0F;IAE1F,MAAM,CAAC,GAAG,MAAM,GAAG,CAAC;QAClB,MAAM;QACN,KAAK;QACL,iBAAiB;QACjB,UAAU;QACV,YAAY,MAAM,CAAC,QAAQ,EAAE;QAC7B,YAAY,MAAM,CAAC,MAAM,EAAE;QAC3B,aAAa,MAAM,CAAC,SAAS,EAAE;QAC/B,eAAe;KAChB,CAAC,CAAC;IACH,IAAI,CAAC,CAAC,CAAC,EAAE;QAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,gCAAgC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC;IAC/F,MAAM,UAAU,GACb,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAsD,CAAC,MAAM,EAAE,UAAU;QAC7F,EAAE,CAAC;IACL,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;IACzD,IAAI,KAAK,EAAE,MAAM,KAAK,MAAM;QAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;IACxD,MAAM,QAAQ,GACZ,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,wBAAwB,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC;QAClF,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;IAC9C,MAAM,MAAM,GAAG,QAAQ;QACrB,CAAC,CAAC,GAAG,QAAQ,CAAC,IAAI,KAAK,QAAQ,CAAC,OAAO,IAAI,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,MAAM,IAAI,SAAS,EAAE;QAC5F,CAAC,CAAC,kDAAkD,CAAC;IACvD,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC;AACtC,CAAC;AAOD;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,GAAQ,EACR,MAAiE;IAEjE,MAAM,CAAC,GAAG,MAAM,GAAG,CAAC;QAClB,SAAS;QACT,kBAAkB;QAClB,MAAM;QACN,UAAU;QACV,aAAa,MAAM,CAAC,SAAS,EAAE;QAC/B,eAAe;KAChB,CAAC,CAAC;IACH,IAAI,CAAC,CAAC,CAAC,EAAE;QAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,0BAA0B,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC;IACzF,MAAM,QAAQ,GAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAA0B,CAAC,MAAM,CACpE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,YAAY,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,SAAS,CAChE,CAAC;IACF,IACE,QAAQ,CAAC,IAAI,CACX,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,OAAO,EAAE,MAAM,KAAK,QAAQ,IAAI,CAAC,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,QAAQ,CAC3F,EACD,CAAC;QACD,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;IAC5B,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,gCAAgC,MAAM,CAAC,QAAQ,MAAM,EAAE,CAAC;IAC7F,CAAC;IACD,MAAM,MAAM,GAAG,QAAQ;SACpB,GAAG,CACF,CAAC,CAAC,EAAE,EAAE,CACJ,GAAG,CAAC,CAAC,IAAI,IAAI,aAAa,KAAK,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC,OAAO,EAAE,YAAY,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CACjG;SACA,IAAI,CAAC,IAAI,CAAC,CAAC;IACd,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC;AACtC,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC"}
@@ -0,0 +1,88 @@
1
+ /** One place a JSON value holds secret material. Never carries the secret itself. */
2
+ export interface SecretFinding {
3
+ /** Dotted path to the offending value, e.g. `steps.pulumi-up-acme.outputs.adminDatabaseUrlOut`. */
4
+ readonly path: string;
5
+ /**
6
+ * `credential-url`: a URL whose user-info carries a password.
7
+ * `token-url`: a URL with a token / secret / password query parameter.
8
+ * `secret-key`: a key whose name marks its value as secret.
9
+ */
10
+ readonly kind: "credential-url" | "token-url" | "secret-key";
11
+ /** For a credential URL: the user whose password it carries. */
12
+ readonly user?: string;
13
+ }
14
+ /**
15
+ * Every place `value` holds secret material.
16
+ *
17
+ * @param value any JSON-shaped value (a checkpoint payload, install.json)
18
+ * @param path the path prefix to report findings under
19
+ */
20
+ export declare function findSecrets(value: unknown, path?: string): SecretFinding[];
21
+ /**
22
+ * Throw when `value` holds secret material. The message names the paths,
23
+ * never the values, so the error itself cannot leak them.
24
+ *
25
+ * @param what what was about to be written, for the message
26
+ */
27
+ export declare function assertNoSecrets(value: unknown, what: string): void;
28
+ /** {@link assertNoSecrets} for a whole checkpoint (see {@link findCheckpointSecrets}). */
29
+ export declare function assertNoCheckpointSecrets(checkpoint: unknown, what: string): void;
30
+ /**
31
+ * {@link findSecrets} for a progress.json checkpoint. Its step names are
32
+ * derived from operator input (`project-<project id>`), so they are
33
+ * identifiers, not field names: a project called `acme-token` must not read
34
+ * as a secret. Only the step payloads (and the other top-level fields) are
35
+ * inspected.
36
+ */
37
+ export declare function findCheckpointSecrets(checkpoint: unknown): SecretFinding[];
38
+ /**
39
+ * `value` without its secret material: secret-named keys and strings that
40
+ * hold a credential or token URL are dropped. Everything else is kept.
41
+ */
42
+ export declare function withoutSecrets(value: unknown): unknown;
43
+ /**
44
+ * The Pulumi outputs worth checkpointing: everything except outputs Pulumi
45
+ * marks secret and anything else that holds secret material (the Owner
46
+ * setup link). Nothing reads secrets back from the checkpoint; code that
47
+ * needs one reads the stack (`readStackOutput`) when it needs it.
48
+ *
49
+ * @param outputs the stack outputs as the Automation API returns them
50
+ */
51
+ export declare function checkpointableOutputs(outputs: Readonly<Record<string, {
52
+ value: unknown;
53
+ secret?: boolean;
54
+ }>>): Record<string, unknown>;
55
+ /** Outcome of {@link scrubProgressFile}. */
56
+ export interface ScrubReport {
57
+ /** What was removed (paths + kinds, never values). Empty when the file was clean or absent. */
58
+ readonly removed: readonly SecretFinding[];
59
+ }
60
+ /**
61
+ * Remove secret material from a `progress.json` in place. The rewrite is
62
+ * atomic (temp file in the same directory, then rename) and the result is
63
+ * mode 0600, so an interrupted scrub never leaves a truncated checkpoint
64
+ * and wizard re-runs still find every completed step.
65
+ *
66
+ * @param path the checkpoint file; a missing file is a no-op
67
+ */
68
+ export declare function scrubProgressFile(path: string): ScrubReport;
69
+ /**
70
+ * Write `value` as JSON to `path` atomically with mode 0600: a temp file in
71
+ * the same directory (so the rename stays on one filesystem), then rename.
72
+ */
73
+ export declare function writeJsonAtomic(path: string, value: unknown): void;
74
+ /**
75
+ * What the operator should do about secrets a scrub removed: one line per
76
+ * affected secret, with the exact command where one exists.
77
+ *
78
+ * @param removed the scrub's findings
79
+ * @param installId the install, named in each command so it acts on the right one
80
+ */
81
+ export declare function rotationHints(removed: readonly SecretFinding[], installId: string): string[];
82
+ /**
83
+ * `text` with every URL password masked (`postgresql://admin_role:***@`),
84
+ * for anything the CLI prints that could carry one (errors from Pulumi or
85
+ * gcloud, for instance). Same masking as the API gateway's error log.
86
+ */
87
+ export declare function redactCredentials(text: string): string;
88
+ //# sourceMappingURL=checkpoint-secrets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkpoint-secrets.d.ts","sourceRoot":"","sources":["../src/checkpoint-secrets.ts"],"names":[],"mappings":"AA4BA,qFAAqF;AACrF,MAAM,WAAW,aAAa;IAC5B,mGAAmG;IACnG,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,gBAAgB,GAAG,WAAW,GAAG,YAAY,CAAC;IAC7D,gEAAgE;IAChE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AA2CD;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,SAAK,GAAG,aAAa,EAAE,CAetE;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAElE;AAED,0FAA0F;AAC1F,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAEjF;AAcD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,OAAO,GAAG,aAAa,EAAE,CAO1E;AAcD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAgBtD;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CAAC,GACtE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAQzB;AAED,4CAA4C;AAC5C,MAAM,WAAW,WAAW;IAC1B,+FAA+F;IAC/F,QAAQ,CAAC,OAAO,EAAE,SAAS,aAAa,EAAE,CAAC;CAC5C;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAO3D;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CASlE;AAID;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,SAAS,aAAa,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAuB5F;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEtD"}