@intentius/chant-lexicon-gcp 0.0.15
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/integrity.json +36 -0
- package/dist/manifest.json +12 -0
- package/dist/meta.json +10919 -0
- package/dist/rules/gcp-helpers.ts +117 -0
- package/dist/rules/hardcoded-project.ts +58 -0
- package/dist/rules/hardcoded-region.ts +56 -0
- package/dist/rules/public-iam.ts +43 -0
- package/dist/rules/wgc101.ts +56 -0
- package/dist/rules/wgc102.ts +35 -0
- package/dist/rules/wgc103.ts +45 -0
- package/dist/rules/wgc104.ts +42 -0
- package/dist/rules/wgc105.ts +46 -0
- package/dist/rules/wgc106.ts +36 -0
- package/dist/rules/wgc107.ts +39 -0
- package/dist/rules/wgc108.ts +41 -0
- package/dist/rules/wgc109.ts +39 -0
- package/dist/rules/wgc110.ts +38 -0
- package/dist/rules/wgc111.ts +54 -0
- package/dist/rules/wgc112.ts +56 -0
- package/dist/rules/wgc113.ts +42 -0
- package/dist/rules/wgc201.ts +36 -0
- package/dist/rules/wgc202.ts +39 -0
- package/dist/rules/wgc203.ts +44 -0
- package/dist/rules/wgc204.ts +39 -0
- package/dist/rules/wgc301.ts +34 -0
- package/dist/rules/wgc302.ts +34 -0
- package/dist/rules/wgc303.ts +37 -0
- package/dist/skills/chant-gcp-patterns.md +367 -0
- package/dist/skills/chant-gcp-security.md +276 -0
- package/dist/skills/chant-gcp.md +108 -0
- package/dist/types/index.d.ts +26529 -0
- package/package.json +35 -0
- package/src/actions/index.ts +52 -0
- package/src/codegen/docs-cli.ts +7 -0
- package/src/codegen/docs.ts +820 -0
- package/src/codegen/generate-cli.ts +24 -0
- package/src/codegen/generate.ts +252 -0
- package/src/codegen/naming.test.ts +49 -0
- package/src/codegen/naming.ts +132 -0
- package/src/codegen/package.ts +66 -0
- package/src/composites/cloud-function.ts +117 -0
- package/src/composites/cloud-run-service.ts +124 -0
- package/src/composites/cloud-sql-instance.ts +126 -0
- package/src/composites/composites.test.ts +432 -0
- package/src/composites/gcs-bucket.ts +111 -0
- package/src/composites/gke-cluster.ts +125 -0
- package/src/composites/index.ts +20 -0
- package/src/composites/managed-certificate.ts +79 -0
- package/src/composites/private-service.ts +95 -0
- package/src/composites/pubsub-pipeline.ts +102 -0
- package/src/composites/secure-project.ts +128 -0
- package/src/composites/vpc-network.ts +165 -0
- package/src/coverage.test.ts +27 -0
- package/src/coverage.ts +51 -0
- package/src/default-labels.test.ts +111 -0
- package/src/default-labels.ts +93 -0
- package/src/generated/index.d.ts +26529 -0
- package/src/generated/index.ts +1723 -0
- package/src/generated/lexicon-gcp.json +10919 -0
- package/src/generated/runtime.ts +4 -0
- package/src/import/generator.test.ts +125 -0
- package/src/import/generator.ts +82 -0
- package/src/import/parser.test.ts +167 -0
- package/src/import/parser.ts +80 -0
- package/src/import/roundtrip.test.ts +66 -0
- package/src/index.ts +54 -0
- package/src/lint/post-synth/gcp-helpers.ts +117 -0
- package/src/lint/post-synth/index.ts +20 -0
- package/src/lint/post-synth/post-synth.test.ts +693 -0
- package/src/lint/post-synth/wgc101.ts +56 -0
- package/src/lint/post-synth/wgc102.ts +35 -0
- package/src/lint/post-synth/wgc103.ts +45 -0
- package/src/lint/post-synth/wgc104.ts +42 -0
- package/src/lint/post-synth/wgc105.ts +46 -0
- package/src/lint/post-synth/wgc106.ts +36 -0
- package/src/lint/post-synth/wgc107.ts +39 -0
- package/src/lint/post-synth/wgc108.ts +41 -0
- package/src/lint/post-synth/wgc109.ts +39 -0
- package/src/lint/post-synth/wgc110.ts +38 -0
- package/src/lint/post-synth/wgc111.ts +54 -0
- package/src/lint/post-synth/wgc112.ts +56 -0
- package/src/lint/post-synth/wgc113.ts +42 -0
- package/src/lint/post-synth/wgc201.ts +36 -0
- package/src/lint/post-synth/wgc202.ts +39 -0
- package/src/lint/post-synth/wgc203.ts +44 -0
- package/src/lint/post-synth/wgc204.ts +39 -0
- package/src/lint/post-synth/wgc301.ts +34 -0
- package/src/lint/post-synth/wgc302.ts +34 -0
- package/src/lint/post-synth/wgc303.ts +37 -0
- package/src/lint/rules/hardcoded-project.ts +58 -0
- package/src/lint/rules/hardcoded-region.ts +56 -0
- package/src/lint/rules/index.ts +3 -0
- package/src/lint/rules/public-iam.ts +43 -0
- package/src/lint/rules/rules.test.ts +63 -0
- package/src/lsp/completions.test.ts +67 -0
- package/src/lsp/completions.ts +17 -0
- package/src/lsp/hover.test.ts +66 -0
- package/src/lsp/hover.ts +54 -0
- package/src/package-cli.ts +24 -0
- package/src/plugin.test.ts +250 -0
- package/src/plugin.ts +405 -0
- package/src/pseudo.test.ts +40 -0
- package/src/pseudo.ts +19 -0
- package/src/serializer.test.ts +250 -0
- package/src/serializer.ts +232 -0
- package/src/skills/chant-gcp-patterns.md +367 -0
- package/src/skills/chant-gcp-security.md +276 -0
- package/src/skills/chant-gcp.md +108 -0
- package/src/spec/fetch.test.ts +16 -0
- package/src/spec/fetch.ts +121 -0
- package/src/spec/parse.test.ts +163 -0
- package/src/spec/parse.ts +432 -0
- package/src/testdata/compute-instance.yaml +93 -0
- package/src/testdata/iam-policy-member.yaml +66 -0
- package/src/testdata/manifests/compute-instance.yaml +18 -0
- package/src/testdata/manifests/full-app.yaml +34 -0
- package/src/testdata/manifests/storage-bucket.yaml +12 -0
- package/src/testdata/storage-bucket.yaml +100 -0
- package/src/validate-cli.ts +13 -0
- package/src/validate.test.ts +38 -0
- package/src/validate.ts +30 -0
- package/src/variables.ts +15 -0
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
---
|
|
2
|
+
source: chant-lexicon
|
|
3
|
+
lexicon: gcp
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Advanced GCP Config Connector Patterns with Chant
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
Advanced patterns for GCP Config Connector manifest generation with chant, covering
|
|
11
|
+
resource references, annotations, pseudo-parameters, composites, multi-project
|
|
12
|
+
patterns, and parameters/outputs.
|
|
13
|
+
|
|
14
|
+
## Resource Reference Linking
|
|
15
|
+
|
|
16
|
+
Config Connector resources reference each other using `resourceRef` fields.
|
|
17
|
+
|
|
18
|
+
### By Name (same namespace)
|
|
19
|
+
|
|
20
|
+
Reference a resource within the same Kubernetes namespace:
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
export const network = new VPCNetwork({ autoCreateSubnetworks: false });
|
|
24
|
+
|
|
25
|
+
export const subnet = new ComputeSubnetwork({
|
|
26
|
+
networkRef: { name: network },
|
|
27
|
+
ipCidrRange: "10.0.0.0/24",
|
|
28
|
+
region: "us-central1",
|
|
29
|
+
});
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Serializes to:
|
|
33
|
+
|
|
34
|
+
```yaml
|
|
35
|
+
spec:
|
|
36
|
+
networkRef:
|
|
37
|
+
name: my-network
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### By External Reference (cross-project)
|
|
41
|
+
|
|
42
|
+
Reference a resource in another GCP project or managed externally:
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
export const subnet = new ComputeSubnetwork({
|
|
46
|
+
networkRef: {
|
|
47
|
+
external: "projects/shared-vpc-project/global/networks/shared-vpc",
|
|
48
|
+
},
|
|
49
|
+
ipCidrRange: "10.0.1.0/24",
|
|
50
|
+
region: "us-central1",
|
|
51
|
+
});
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
External refs bypass WGC111 (dangling reference check) since they reference
|
|
55
|
+
resources outside the template.
|
|
56
|
+
|
|
57
|
+
## Default Annotations and Labels
|
|
58
|
+
|
|
59
|
+
### defaultAnnotations
|
|
60
|
+
|
|
61
|
+
Apply project-wide annotations to all Config Connector resources:
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
import { defaultAnnotations, GCP } from "@intentius/chant-lexicon-gcp";
|
|
65
|
+
|
|
66
|
+
export const annotations = defaultAnnotations({
|
|
67
|
+
"cnrm.cloud.google.com/project-id": GCP.ProjectId,
|
|
68
|
+
"cnrm.cloud.google.com/deletion-policy": "abandon",
|
|
69
|
+
});
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
All resources in the output will receive these annotations in `metadata.annotations`.
|
|
73
|
+
|
|
74
|
+
### defaultLabels
|
|
75
|
+
|
|
76
|
+
Apply project-wide Kubernetes labels:
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
import { defaultLabels } from "@intentius/chant-lexicon-gcp";
|
|
80
|
+
|
|
81
|
+
export const labels = defaultLabels({
|
|
82
|
+
"app.kubernetes.io/managed-by": "chant",
|
|
83
|
+
"environment": "production",
|
|
84
|
+
});
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
All resources will receive these labels in `metadata.labels`.
|
|
88
|
+
|
|
89
|
+
## Pseudo-Parameters
|
|
90
|
+
|
|
91
|
+
Pseudo-parameters are resolved at deploy time. Use the `GCP` namespace:
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
import { GCP } from "@intentius/chant-lexicon-gcp";
|
|
95
|
+
|
|
96
|
+
// GCP.ProjectId → resolves to the target GCP project ID
|
|
97
|
+
// GCP.Region → resolves to the target region
|
|
98
|
+
// GCP.Zone → resolves to the target zone
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Usage in annotations:
|
|
102
|
+
|
|
103
|
+
```ts
|
|
104
|
+
export const annotations = defaultAnnotations({
|
|
105
|
+
"cnrm.cloud.google.com/project-id": GCP.ProjectId,
|
|
106
|
+
});
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Individual imports also work:
|
|
110
|
+
|
|
111
|
+
```ts
|
|
112
|
+
import { ProjectId, Region, Zone } from "@intentius/chant-lexicon-gcp";
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Composites
|
|
116
|
+
|
|
117
|
+
Composites are higher-level abstractions that create multiple related Config Connector
|
|
118
|
+
resources with secure defaults.
|
|
119
|
+
|
|
120
|
+
### GkeCluster
|
|
121
|
+
|
|
122
|
+
GKE cluster with node pool, workload identity, and autoscaling:
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
import { GkeCluster } from "@intentius/chant-lexicon-gcp";
|
|
126
|
+
|
|
127
|
+
const { cluster, nodePool } = GkeCluster({
|
|
128
|
+
name: "my-cluster",
|
|
129
|
+
location: "us-central1",
|
|
130
|
+
machineType: "e2-medium",
|
|
131
|
+
minNodeCount: 1,
|
|
132
|
+
maxNodeCount: 10,
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
export { cluster, nodePool };
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### CloudRunService
|
|
139
|
+
|
|
140
|
+
Cloud Run service with optional public access IAM:
|
|
141
|
+
|
|
142
|
+
```ts
|
|
143
|
+
import { CloudRunService } from "@intentius/chant-lexicon-gcp";
|
|
144
|
+
|
|
145
|
+
const { service } = CloudRunService({
|
|
146
|
+
name: "my-api",
|
|
147
|
+
image: "gcr.io/my-project/my-api:latest",
|
|
148
|
+
location: "us-central1",
|
|
149
|
+
port: 8080,
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
export { service };
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### CloudSqlInstance
|
|
156
|
+
|
|
157
|
+
SQL instance with database and user:
|
|
158
|
+
|
|
159
|
+
```ts
|
|
160
|
+
import { CloudSqlInstance } from "@intentius/chant-lexicon-gcp";
|
|
161
|
+
|
|
162
|
+
const { instance, database, user } = CloudSqlInstance({
|
|
163
|
+
name: "my-db",
|
|
164
|
+
databaseVersion: "POSTGRES_15",
|
|
165
|
+
tier: "db-custom-2-8192",
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
export { instance, database, user };
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### GcsBucket
|
|
172
|
+
|
|
173
|
+
Storage bucket with encryption, uniform access, and lifecycle:
|
|
174
|
+
|
|
175
|
+
```ts
|
|
176
|
+
import { GcsBucket } from "@intentius/chant-lexicon-gcp";
|
|
177
|
+
|
|
178
|
+
const { bucket } = GcsBucket({
|
|
179
|
+
name: "my-data-bucket",
|
|
180
|
+
location: "US",
|
|
181
|
+
storageClass: "STANDARD",
|
|
182
|
+
kmsKeyName: "projects/p/locations/l/keyRings/kr/cryptoKeys/k",
|
|
183
|
+
lifecycleDeleteAfterDays: 365,
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
export { bucket };
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### VpcNetwork
|
|
190
|
+
|
|
191
|
+
VPC network with subnets, firewall rules, and Cloud NAT:
|
|
192
|
+
|
|
193
|
+
```ts
|
|
194
|
+
import { VpcNetwork } from "@intentius/chant-lexicon-gcp";
|
|
195
|
+
|
|
196
|
+
const { network, subnets, firewall, router, nat } = VpcNetwork({
|
|
197
|
+
name: "my-vpc",
|
|
198
|
+
subnets: [
|
|
199
|
+
{ name: "app-subnet", ipCidrRange: "10.0.1.0/24", region: "us-central1" },
|
|
200
|
+
{ name: "data-subnet", ipCidrRange: "10.0.2.0/24", region: "us-central1" },
|
|
201
|
+
],
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
export { network, subnets, firewall, router, nat };
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### PubSubPipeline
|
|
208
|
+
|
|
209
|
+
Topic + subscription with optional dead-letter queue:
|
|
210
|
+
|
|
211
|
+
```ts
|
|
212
|
+
import { PubSubPipeline } from "@intentius/chant-lexicon-gcp";
|
|
213
|
+
|
|
214
|
+
const { topic, subscription, dlqTopic } = PubSubPipeline({
|
|
215
|
+
name: "order-events",
|
|
216
|
+
enableDeadLetterQueue: true,
|
|
217
|
+
maxDeliveryAttempts: 5,
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
export { topic, subscription, dlqTopic };
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### CloudFunctionWithTrigger
|
|
224
|
+
|
|
225
|
+
Cloud Function with source bucket and trigger:
|
|
226
|
+
|
|
227
|
+
```ts
|
|
228
|
+
import { CloudFunctionWithTrigger } from "@intentius/chant-lexicon-gcp";
|
|
229
|
+
|
|
230
|
+
const { function: fn, sourceBucket } = CloudFunctionWithTrigger({
|
|
231
|
+
name: "process-orders",
|
|
232
|
+
runtime: "nodejs20",
|
|
233
|
+
entryPoint: "handler",
|
|
234
|
+
triggerType: "pubsub",
|
|
235
|
+
pubsubTopicName: "order-events",
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
export { fn, sourceBucket };
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### PrivateService
|
|
242
|
+
|
|
243
|
+
Private service networking (VPC peering for managed services):
|
|
244
|
+
|
|
245
|
+
```ts
|
|
246
|
+
import { PrivateService } from "@intentius/chant-lexicon-gcp";
|
|
247
|
+
|
|
248
|
+
const { address, connection } = PrivateService({
|
|
249
|
+
name: "private-svc",
|
|
250
|
+
networkName: "my-vpc",
|
|
251
|
+
prefixLength: 16,
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
export { address, connection };
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### ManagedCertificate
|
|
258
|
+
|
|
259
|
+
Google-managed SSL certificate with optional HTTPS proxy:
|
|
260
|
+
|
|
261
|
+
```ts
|
|
262
|
+
import { ManagedCertificate } from "@intentius/chant-lexicon-gcp";
|
|
263
|
+
|
|
264
|
+
const { certificate } = ManagedCertificate({
|
|
265
|
+
name: "my-cert",
|
|
266
|
+
domains: ["example.com", "www.example.com"],
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
export { certificate };
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### SecureProject
|
|
273
|
+
|
|
274
|
+
GCP project with audit logging, API enablement, and owner IAM:
|
|
275
|
+
|
|
276
|
+
```ts
|
|
277
|
+
import { SecureProject } from "@intentius/chant-lexicon-gcp";
|
|
278
|
+
|
|
279
|
+
const { project, auditConfig, services } = SecureProject({
|
|
280
|
+
name: "my-secure-project",
|
|
281
|
+
orgId: "123456789",
|
|
282
|
+
billingAccountRef: { external: "AAAAAA-BBBBBB-CCCCCC" },
|
|
283
|
+
owner: "user:admin@example.com",
|
|
284
|
+
enabledApis: ["compute.googleapis.com", "container.googleapis.com"],
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
export { project, auditConfig, services };
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
## Multi-Project Patterns
|
|
291
|
+
|
|
292
|
+
### Project Annotation
|
|
293
|
+
|
|
294
|
+
Bind resources to a specific GCP project:
|
|
295
|
+
|
|
296
|
+
```ts
|
|
297
|
+
export const annotations = defaultAnnotations({
|
|
298
|
+
"cnrm.cloud.google.com/project-id": GCP.ProjectId,
|
|
299
|
+
});
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
### ConfigConnectorContext
|
|
303
|
+
|
|
304
|
+
When managing multiple projects, use ConfigConnectorContext per namespace:
|
|
305
|
+
|
|
306
|
+
```yaml
|
|
307
|
+
apiVersion: core.cnrm.cloud.google.com/v1beta1
|
|
308
|
+
kind: ConfigConnectorContext
|
|
309
|
+
metadata:
|
|
310
|
+
name: configconnectorcontext.core.cnrm.cloud.google.com
|
|
311
|
+
namespace: project-a
|
|
312
|
+
spec:
|
|
313
|
+
googleServiceAccount: cnrm-system@project-a.iam.gserviceaccount.com
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
### Cross-Project References
|
|
317
|
+
|
|
318
|
+
Use external refs to reference resources in other projects:
|
|
319
|
+
|
|
320
|
+
```ts
|
|
321
|
+
export const peering = new ComputeNetworkPeering({
|
|
322
|
+
networkRef: { name: localNetwork },
|
|
323
|
+
peerNetworkRef: {
|
|
324
|
+
external: "projects/other-project/global/networks/other-vpc",
|
|
325
|
+
},
|
|
326
|
+
});
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
## CoreParameter and StackOutput
|
|
330
|
+
|
|
331
|
+
### CoreParameter
|
|
332
|
+
|
|
333
|
+
Define deploy-time parameters:
|
|
334
|
+
|
|
335
|
+
```ts
|
|
336
|
+
import { CoreParameter } from "@intentius/chant";
|
|
337
|
+
|
|
338
|
+
export const environment = new CoreParameter({
|
|
339
|
+
name: "environment",
|
|
340
|
+
type: "string",
|
|
341
|
+
default: "dev",
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
export const region = new CoreParameter({
|
|
345
|
+
name: "region",
|
|
346
|
+
type: "string",
|
|
347
|
+
default: "us-central1",
|
|
348
|
+
});
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
### StackOutput
|
|
352
|
+
|
|
353
|
+
Export values from the synthesized output:
|
|
354
|
+
|
|
355
|
+
```ts
|
|
356
|
+
import { StackOutput } from "@intentius/chant";
|
|
357
|
+
|
|
358
|
+
export const bucketName = new StackOutput({
|
|
359
|
+
name: "bucketName",
|
|
360
|
+
value: bucket,
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
export const clusterEndpoint = new StackOutput({
|
|
364
|
+
name: "clusterEndpoint",
|
|
365
|
+
value: cluster,
|
|
366
|
+
});
|
|
367
|
+
```
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
---
|
|
2
|
+
source: chant-lexicon
|
|
3
|
+
lexicon: gcp
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# GCP Security Best Practices for Chant
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
Security patterns and best practices for GCP Config Connector manifests generated with chant.
|
|
11
|
+
These patterns map directly to the post-synth checks (WGC101–WGC303) and help AI agents
|
|
12
|
+
produce secure-by-default infrastructure.
|
|
13
|
+
|
|
14
|
+
## Encryption
|
|
15
|
+
|
|
16
|
+
### CMEK via Cloud KMS
|
|
17
|
+
|
|
18
|
+
Use customer-managed encryption keys (CMEK) for StorageBucket and other resources:
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
|
+
import { StorageBucket, KMSCryptoKey, KMSKeyRing } from "@intentius/chant-lexicon-gcp";
|
|
22
|
+
|
|
23
|
+
export const keyRing = new KMSKeyRing({
|
|
24
|
+
location: "us-central1",
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
export const cryptoKey = new KMSCryptoKey({
|
|
28
|
+
keyRingRef: { name: keyRing },
|
|
29
|
+
purpose: "ENCRYPT_DECRYPT",
|
|
30
|
+
rotationPeriod: "7776000s",
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
export const bucket = new StorageBucket({
|
|
34
|
+
location: "US",
|
|
35
|
+
encryption: {
|
|
36
|
+
defaultKmsKeyName: cryptoKey,
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### SQLInstance Encryption and Backup
|
|
42
|
+
|
|
43
|
+
Always configure backup and encryption on Cloud SQL instances:
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
export const db = new SQLInstance({
|
|
47
|
+
databaseVersion: "POSTGRES_15",
|
|
48
|
+
settings: {
|
|
49
|
+
tier: "db-custom-2-8192",
|
|
50
|
+
backupConfiguration: {
|
|
51
|
+
enabled: true,
|
|
52
|
+
pointInTimeRecoveryEnabled: true,
|
|
53
|
+
},
|
|
54
|
+
ipConfiguration: {
|
|
55
|
+
requireSsl: true,
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### KMS Key Rotation
|
|
62
|
+
|
|
63
|
+
Always set a rotation period on KMS encryption keys:
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
export const key = new KMSCryptoKey({
|
|
67
|
+
keyRingRef: { name: keyRing },
|
|
68
|
+
purpose: "ENCRYPT_DECRYPT",
|
|
69
|
+
rotationPeriod: "7776000s", // 90 days
|
|
70
|
+
});
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## IAM
|
|
74
|
+
|
|
75
|
+
### Workload Identity
|
|
76
|
+
|
|
77
|
+
Enable Workload Identity on GKE clusters instead of using node service account keys:
|
|
78
|
+
|
|
79
|
+
```ts
|
|
80
|
+
export const cluster = new GKECluster({
|
|
81
|
+
location: GCP.Region,
|
|
82
|
+
workloadIdentityConfig: {
|
|
83
|
+
workloadPool: "PROJECT_ID.svc.id.goog",
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Least-Privilege Roles
|
|
89
|
+
|
|
90
|
+
Use specific predefined roles instead of overly broad roles:
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
// Good: specific role
|
|
94
|
+
export const binding = new IAMPolicyMember({
|
|
95
|
+
member: "serviceAccount:my-sa@PROJECT.iam.gserviceaccount.com",
|
|
96
|
+
role: "roles/storage.objectViewer",
|
|
97
|
+
resourceRef: { name: bucket },
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
// Bad: overly broad
|
|
101
|
+
// role: "roles/editor"
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### No Service Account Keys
|
|
105
|
+
|
|
106
|
+
Avoid creating service account keys — use Workload Identity or federated identity instead.
|
|
107
|
+
|
|
108
|
+
### Avoid Public IAM Bindings
|
|
109
|
+
|
|
110
|
+
Never use `allUsers` or `allAuthenticatedUsers` as IAM members unless intentional:
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
// Bad — flagged by WGC102
|
|
114
|
+
export const publicAccess = new IAMPolicyMember({
|
|
115
|
+
member: "allUsers",
|
|
116
|
+
role: "roles/run.invoker",
|
|
117
|
+
});
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Network Security
|
|
121
|
+
|
|
122
|
+
### VPC Service Controls
|
|
123
|
+
|
|
124
|
+
Use AccessContextManager service perimeters to protect sensitive resources:
|
|
125
|
+
|
|
126
|
+
```ts
|
|
127
|
+
import { AccessContextManagerServicePerimeter } from "@intentius/chant-lexicon-gcp";
|
|
128
|
+
|
|
129
|
+
export const perimeter = new AccessContextManagerServicePerimeter({
|
|
130
|
+
title: "my-perimeter",
|
|
131
|
+
perimeterType: "PERIMETER_TYPE_REGULAR",
|
|
132
|
+
status: {
|
|
133
|
+
restrictedServices: [
|
|
134
|
+
"storage.googleapis.com",
|
|
135
|
+
"bigquery.googleapis.com",
|
|
136
|
+
],
|
|
137
|
+
},
|
|
138
|
+
});
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Private Cloud SQL
|
|
142
|
+
|
|
143
|
+
Never allow `0.0.0.0/0` in Cloud SQL authorized networks:
|
|
144
|
+
|
|
145
|
+
```ts
|
|
146
|
+
// Good: private access only
|
|
147
|
+
export const db = new SQLInstance({
|
|
148
|
+
settings: {
|
|
149
|
+
ipConfiguration: {
|
|
150
|
+
ipv4Enabled: false,
|
|
151
|
+
privateNetworkRef: { name: myVpc },
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
});
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Firewall Rules
|
|
158
|
+
|
|
159
|
+
Avoid overly permissive source ranges in firewall rules:
|
|
160
|
+
|
|
161
|
+
```ts
|
|
162
|
+
// Bad — flagged by WGC109
|
|
163
|
+
export const firewall = new ComputeFirewall({
|
|
164
|
+
sourceRanges: ["0.0.0.0/0"],
|
|
165
|
+
allowed: [{ protocol: "tcp", ports: ["22"] }],
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
// Good: specific CIDR
|
|
169
|
+
export const firewall = new ComputeFirewall({
|
|
170
|
+
sourceRanges: ["10.0.0.0/8"],
|
|
171
|
+
allowed: [{ protocol: "tcp", ports: ["22"] }],
|
|
172
|
+
});
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## Audit & Logging
|
|
176
|
+
|
|
177
|
+
### IAMAuditConfig
|
|
178
|
+
|
|
179
|
+
Enable data access audit logging:
|
|
180
|
+
|
|
181
|
+
```ts
|
|
182
|
+
import { IAMAuditConfig } from "@intentius/chant-lexicon-gcp";
|
|
183
|
+
|
|
184
|
+
export const auditConfig = new IAMAuditConfig({
|
|
185
|
+
service: "allServices",
|
|
186
|
+
auditLogConfigs: [
|
|
187
|
+
{ logType: "ADMIN_READ" },
|
|
188
|
+
{ logType: "DATA_READ" },
|
|
189
|
+
{ logType: "DATA_WRITE" },
|
|
190
|
+
],
|
|
191
|
+
});
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## Other Best Practices
|
|
195
|
+
|
|
196
|
+
### Deletion Policy
|
|
197
|
+
|
|
198
|
+
Set deletion policies on stateful resources to prevent accidental deletion:
|
|
199
|
+
|
|
200
|
+
```ts
|
|
201
|
+
// Use the annotation on metadata
|
|
202
|
+
metadata:
|
|
203
|
+
annotations:
|
|
204
|
+
cnrm.cloud.google.com/deletion-policy: abandon
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Or use `defaultAnnotations`:
|
|
208
|
+
|
|
209
|
+
```ts
|
|
210
|
+
export const annotations = defaultAnnotations({
|
|
211
|
+
"cnrm.cloud.google.com/deletion-policy": "abandon",
|
|
212
|
+
});
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Shielded VMs
|
|
216
|
+
|
|
217
|
+
Enable shielded VM features on ComputeInstance:
|
|
218
|
+
|
|
219
|
+
```ts
|
|
220
|
+
export const vm = new ComputeInstance({
|
|
221
|
+
machineType: "e2-medium",
|
|
222
|
+
zone: "us-central1-a",
|
|
223
|
+
shieldedInstanceConfig: {
|
|
224
|
+
enableSecureBoot: true,
|
|
225
|
+
enableVtpm: true,
|
|
226
|
+
enableIntegrityMonitoring: true,
|
|
227
|
+
},
|
|
228
|
+
});
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### Uniform Bucket-Level Access
|
|
232
|
+
|
|
233
|
+
Enable uniform bucket-level access on storage buckets:
|
|
234
|
+
|
|
235
|
+
```ts
|
|
236
|
+
export const bucket = new StorageBucket({
|
|
237
|
+
location: "US",
|
|
238
|
+
uniformBucketLevelAccess: true,
|
|
239
|
+
});
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### Object Versioning
|
|
243
|
+
|
|
244
|
+
Enable versioning on storage buckets for data protection:
|
|
245
|
+
|
|
246
|
+
```ts
|
|
247
|
+
export const bucket = new StorageBucket({
|
|
248
|
+
location: "US",
|
|
249
|
+
versioning: { enabled: true },
|
|
250
|
+
});
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
## Post-Synth Check Reference
|
|
254
|
+
|
|
255
|
+
| Check | Severity | Description |
|
|
256
|
+
|-------|----------|-------------|
|
|
257
|
+
| WGC101 | warning | StorageBucket or SQLInstance without encryption |
|
|
258
|
+
| WGC102 | warning | Public IAM binding (allUsers/allAuthenticatedUsers) in output |
|
|
259
|
+
| WGC103 | warning | Missing `cnrm.cloud.google.com/project-id` annotation |
|
|
260
|
+
| WGC104 | warning | StorageBucket without uniformBucketLevelAccess |
|
|
261
|
+
| WGC105 | warning | SQLInstance with 0.0.0.0/0 in authorizedNetworks |
|
|
262
|
+
| WGC106 | info | Missing deletion policy annotation |
|
|
263
|
+
| WGC107 | warning | StorageBucket without versioning |
|
|
264
|
+
| WGC108 | warning | SQLInstance without backup configuration |
|
|
265
|
+
| WGC109 | warning | ComputeFirewall with 0.0.0.0/0 source range |
|
|
266
|
+
| WGC110 | warning | KMSCryptoKey without rotation period |
|
|
267
|
+
| WGC111 | warning | Dangling resourceRef (referenced name not in output) |
|
|
268
|
+
| WGC112 | error | Missing or invalid apiVersion |
|
|
269
|
+
| WGC113 | warning | Alpha API version (prefer v1beta1 or v1) |
|
|
270
|
+
| WGC201 | info | Missing managed-by label |
|
|
271
|
+
| WGC202 | warning | GKE cluster without Workload Identity |
|
|
272
|
+
| WGC203 | warning | Overly broad OAuth scope (cloud-platform) |
|
|
273
|
+
| WGC204 | warning | ComputeInstance without shielded VM config |
|
|
274
|
+
| WGC301 | info | No IAMAuditConfig in output |
|
|
275
|
+
| WGC302 | info | No Service resource (API enablement) in output |
|
|
276
|
+
| WGC303 | info | Missing VPC Service Controls |
|