@caelo-cms/provisioning 0.2.79 → 0.2.81
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/package.json +3 -2
- package/stacks/gcp/Pulumi.production.yaml +3 -3
- package/stacks/gcp/index.ts +32 -16
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@caelo-cms/provisioning",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.81",
|
|
4
4
|
"private": false,
|
|
5
5
|
"license": "MPL-2.0",
|
|
6
6
|
"description": "Pulumi-driven provisioning for Caelo CMS — `bunx @caelo-cms/provisioning --provider <self-hosted|gcp|aws|azure>` brings up a TLS-served install with Postgres + storage + secrets manager + the admin + the API gateway.",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"prepublishOnly": "tsc -b --force"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@caelo-cms/shared": "^0.2.
|
|
41
|
+
"@caelo-cms/shared": "^0.2.81",
|
|
42
42
|
"@clack/prompts": "1.3.0",
|
|
43
43
|
"@pulumi/aws": "^7",
|
|
44
44
|
"@pulumi/awsx": "^3",
|
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
"@pulumi/command": "^1",
|
|
47
47
|
"@pulumi/gcp": "^9",
|
|
48
48
|
"@pulumi/pulumi": "^3",
|
|
49
|
+
"@pulumi/random": "^4.19.2",
|
|
49
50
|
"kleur": "4.1.5"
|
|
50
51
|
},
|
|
51
52
|
"publishConfig": {
|
|
@@ -2,7 +2,7 @@ encryptionsalt: v1:mEv+SGjVDdU=:v1:1Tmd1g2Yh0KXxhp5:fGsA3LiAPntjAGUMORKO+B1gxQgI
|
|
|
2
2
|
config:
|
|
3
3
|
caelo-gcp:adminMinInstances: "0"
|
|
4
4
|
caelo-gcp:anthropicApiKey:
|
|
5
|
-
secure: v1:
|
|
5
|
+
secure: v1:/RCE2zS+Y8ZrTdcj:gIXucRKkT1vX+qg0yE8Uq3oIL+lHa23wLOheAKeR762d97ydAo332XwfteqJOgDg/scAtD2dict1NoNxNgxXpJnw1jltUi8fsF9vMt9elh2aV71eFB2oRGBlxIWbAgYdXqs/gfMxRtZ8r0dhYADuSCrtTQcI7GAFWg5EhA==
|
|
6
6
|
caelo-gcp:cloudSqlHa: "false"
|
|
7
7
|
caelo-gcp:cloudSqlTier: db-f1-micro
|
|
8
8
|
caelo-gcp:domain: caelo-cms.com
|
|
@@ -12,5 +12,5 @@ config:
|
|
|
12
12
|
caelo-gcp:project: caelo-website
|
|
13
13
|
caelo-gcp:region: europe-west1
|
|
14
14
|
caelo-gcp:wafAdaptiveProtection: "false"
|
|
15
|
-
caelo-gcp:image-digest-admin: sha256:
|
|
16
|
-
caelo-gcp:image-digest-gateway: sha256:
|
|
15
|
+
caelo-gcp:image-digest-admin: sha256:92fb8ee1267de781f37c664e34d299b2f29c6051a113fa1bdbd6fddb753ef81e
|
|
16
|
+
caelo-gcp:image-digest-gateway: sha256:b4ceac2fd371be2850f7fc9549700fcd9e595eae6144f4a87b27192adf0cd9eb
|
package/stacks/gcp/index.ts
CHANGED
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
|
|
20
20
|
import * as gcp from "@pulumi/gcp";
|
|
21
21
|
import * as pulumi from "@pulumi/pulumi";
|
|
22
|
+
import * as random from "@pulumi/random";
|
|
22
23
|
import type { CloudAdapterOutputs, DnsRecord } from "../../dist/adapter.js";
|
|
23
24
|
import { generateBootstrapToken } from "../../dist/bootstrap-token.js";
|
|
24
25
|
|
|
@@ -128,22 +129,37 @@ const sqlPeering = new gcp.servicenetworking.Connection(
|
|
|
128
129
|
// Secret Manager — never env-var literal; runtime mounts via secret_environment_variables
|
|
129
130
|
// =========================================================================
|
|
130
131
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
//
|
|
141
|
-
//
|
|
142
|
-
//
|
|
143
|
-
//
|
|
144
|
-
//
|
|
145
|
-
//
|
|
146
|
-
|
|
132
|
+
// v0.2.81 — secrets MUST be generated by a Pulumi resource that
|
|
133
|
+
// persists in stack state, NOT by `randomHex(32)` at program-eval
|
|
134
|
+
// time. Pulumi re-evaluates the program on every `pulumi up`, so
|
|
135
|
+
// any plain-JS random() call produces a new value each run, and
|
|
136
|
+
// the matching SecretVersion gets re-created with the new value.
|
|
137
|
+
// Symptom: after a re-up, all secrets encrypted under the old KEK
|
|
138
|
+
// (AI provider API keys in ai_providers) became permanently
|
|
139
|
+
// unreadable — and Secret Manager destroyed the prior versions
|
|
140
|
+
// after their soft-delete window so recovery was impossible.
|
|
141
|
+
//
|
|
142
|
+
// `random.RandomBytes` materialises ONCE, persists the bytes in
|
|
143
|
+
// state, reuses on subsequent runs. This is the canonical fix for
|
|
144
|
+
// "auto-generated but stable" secret values in Pulumi.
|
|
145
|
+
// random.RandomBytes uses the @pulumi/random provider, not the gcp
|
|
146
|
+
// one — don't pass `opts` (which carries gcpProvider). Pulumi
|
|
147
|
+
// auto-loads the random provider on first reference.
|
|
148
|
+
const pgPasswordBytes = new random.RandomBytes(`${namePrefix}-pg-password-bytes`, { length: 32 });
|
|
149
|
+
const csrfSecretBytes = new random.RandomBytes(`${namePrefix}-csrf-secret-bytes`, { length: 32 });
|
|
150
|
+
const cookieSecretBytes = new random.RandomBytes(`${namePrefix}-cookie-secret-bytes`, {
|
|
151
|
+
length: 32,
|
|
152
|
+
});
|
|
153
|
+
const kekBytes = new random.RandomBytes(`${namePrefix}-secret-kek-bytes`, { length: 32 });
|
|
154
|
+
|
|
155
|
+
const postgresPassword = pulumi.secret(pgPasswordBytes.hex);
|
|
156
|
+
const csrfSecret = pulumi.secret(csrfSecretBytes.hex);
|
|
157
|
+
const cookieSecret = pulumi.secret(cookieSecretBytes.hex);
|
|
158
|
+
// P18 — project KEK (32 bytes hex) encrypts AI provider API keys
|
|
159
|
+
// + future at-rest secrets in cms_admin. Stable across `pulumi up`
|
|
160
|
+
// (see comment above). Cloud Run binds it as CAELO_SECRET_KEK env
|
|
161
|
+
// via `valueSource.secretKeyRef` below.
|
|
162
|
+
const caeloSecretKek = pulumi.secret(kekBytes.hex);
|
|
147
163
|
// anthropicApiKey is now OPTIONAL — operators configure the key via
|
|
148
164
|
// /security/ai (encrypted into ai_providers) after first login. Setting
|
|
149
165
|
// it via Pulumi config is supported as a backwards-compat path for
|