@venturekit/infra 0.0.0-dev.20260514025219 → 0.0.0-dev.20260515022321
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/cdk/app-stack.d.ts +330 -0
- package/dist/cdk/app-stack.d.ts.map +1 -0
- package/dist/cdk/app-stack.js +875 -0
- package/dist/cdk/app-stack.js.map +1 -0
- package/dist/cdk/config-stack.d.ts +104 -0
- package/dist/cdk/config-stack.d.ts.map +1 -0
- package/dist/cdk/config-stack.js +161 -0
- package/dist/cdk/config-stack.js.map +1 -0
- package/dist/cdk/data-stack.d.ts +198 -0
- package/dist/cdk/data-stack.d.ts.map +1 -0
- package/dist/cdk/data-stack.js +511 -0
- package/dist/cdk/data-stack.js.map +1 -0
- package/dist/cdk/edge-stack.d.ts +91 -0
- package/dist/cdk/edge-stack.d.ts.map +1 -0
- package/dist/cdk/edge-stack.js +364 -0
- package/dist/cdk/edge-stack.js.map +1 -0
- package/dist/cdk/identity-stack.d.ts +98 -0
- package/dist/cdk/identity-stack.d.ts.map +1 -0
- package/dist/cdk/identity-stack.js +254 -0
- package/dist/cdk/identity-stack.js.map +1 -0
- package/dist/cdk/index.d.ts +16 -0
- package/dist/cdk/index.d.ts.map +1 -1
- package/dist/cdk/index.js +17 -0
- package/dist/cdk/index.js.map +1 -1
- package/dist/cdk/messaging-stack.d.ts +109 -0
- package/dist/cdk/messaging-stack.d.ts.map +1 -0
- package/dist/cdk/messaging-stack.js +320 -0
- package/dist/cdk/messaging-stack.js.map +1 -0
- package/dist/cdk/network-stack.d.ts +87 -0
- package/dist/cdk/network-stack.d.ts.map +1 -0
- package/dist/cdk/network-stack.js +265 -0
- package/dist/cdk/network-stack.js.map +1 -0
- package/dist/cdk/shared/cross-stack-refs.d.ts +278 -0
- package/dist/cdk/shared/cross-stack-refs.d.ts.map +1 -0
- package/dist/cdk/shared/cross-stack-refs.js +326 -0
- package/dist/cdk/shared/cross-stack-refs.js.map +1 -0
- package/dist/cdk/shared/lambda-helpers.d.ts +82 -0
- package/dist/cdk/shared/lambda-helpers.d.ts.map +1 -0
- package/dist/cdk/shared/lambda-helpers.js +201 -0
- package/dist/cdk/shared/lambda-helpers.js.map +1 -0
- package/dist/cdk/shared/ssm-keys.d.ts +460 -0
- package/dist/cdk/shared/ssm-keys.d.ts.map +1 -0
- package/dist/cdk/shared/ssm-keys.js +291 -0
- package/dist/cdk/shared/ssm-keys.js.map +1 -0
- package/dist/cdk/stack.d.ts +3 -11
- package/dist/cdk/stack.d.ts.map +1 -1
- package/dist/cdk/stack.js +184 -41
- package/dist/cdk/stack.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tier 0 — Network stack.
|
|
3
|
+
*
|
|
4
|
+
* Owns: VPC, all subnets (public / private-with-egress / isolated),
|
|
5
|
+
* NAT gateways or fck-nat instances, route tables, the gateway VPC
|
|
6
|
+
* endpoints (S3, DynamoDB), the optional interface endpoints
|
|
7
|
+
* (Secrets Manager — by default off until preset opts in), and the
|
|
8
|
+
* VPC flow log destination.
|
|
9
|
+
*
|
|
10
|
+
* # Lifecycle position
|
|
11
|
+
*
|
|
12
|
+
* Updated almost never (~once a year, when AWS rolls a new fck-nat
|
|
13
|
+
* AMI or the operator adds an AZ). Survives stack delete because
|
|
14
|
+
* everything is RETAIN. The data tier (RDS in private subnets) and
|
|
15
|
+
* the app tier (Lambdas in private subnets) both depend on the
|
|
16
|
+
* network tier's published surface; deleting the network stack
|
|
17
|
+
* orphans every subnet ID + VPC ID — recoverable via `cdk import`,
|
|
18
|
+
* never automatic.
|
|
19
|
+
*
|
|
20
|
+
* # Public surface (via SSM)
|
|
21
|
+
*
|
|
22
|
+
* Published exclusively under `networkKeys` in `shared/ssm-keys.ts`:
|
|
23
|
+
*
|
|
24
|
+
* - `vpcId` — the singular VPC ID
|
|
25
|
+
* - `availabilityZones` — comma-joined, ordered
|
|
26
|
+
* - `privateSubnetIds`, `publicSubnetIds`, `isolatedSubnetIds` —
|
|
27
|
+
* comma-joined, ordered to match `availabilityZones`
|
|
28
|
+
*
|
|
29
|
+
* That's it. Consumers never reach in for individual subnets, NAT
|
|
30
|
+
* IDs, or route table IDs — those are private to this stack.
|
|
31
|
+
*
|
|
32
|
+
* # Why no exports?
|
|
33
|
+
*
|
|
34
|
+
* `cdk.CfnOutput` + `Fn::ImportValue` carries CFN's "consumed export
|
|
35
|
+
* cannot be modified" lock. SSM dynamic references don't. See the
|
|
36
|
+
* long-form rationale in `shared/ssm-keys.ts`.
|
|
37
|
+
*
|
|
38
|
+
* # Free-tier handling
|
|
39
|
+
*
|
|
40
|
+
* On the `free` preset, no VPC is provisioned at all (the preset
|
|
41
|
+
* runs DynamoDB + storage-only Lambdas with no in-VPC dependencies,
|
|
42
|
+
* which keeps the deploy at $0/month). The CLI's stack generator
|
|
43
|
+
* therefore must not instantiate `VentureNetworkStack` when the
|
|
44
|
+
* preset resolves to `free` AND no intent demands a VPC. This stack
|
|
45
|
+
* itself never inspects the preset — it always provisions a VPC
|
|
46
|
+
* when constructed. The instantiation gate lives in the generator.
|
|
47
|
+
*/
|
|
48
|
+
import * as cdk from 'aws-cdk-lib';
|
|
49
|
+
import * as ec2 from 'aws-cdk-lib/aws-ec2';
|
|
50
|
+
import * as logs from 'aws-cdk-lib/aws-logs';
|
|
51
|
+
import { DATA_SAFETY_CONFIG } from '@venturekit/core';
|
|
52
|
+
import { writeSsm, writeSsmStringList } from './shared/cross-stack-refs.js';
|
|
53
|
+
import { networkKeys } from './shared/ssm-keys.js';
|
|
54
|
+
/**
|
|
55
|
+
* Map a `days` retention setting to CDK's `logs.RetentionDays`
|
|
56
|
+
* enum, mirroring the existing helper in the legacy `VentureStack`.
|
|
57
|
+
* Kept inline (rather than imported from `stack.ts`) so this stack
|
|
58
|
+
* compiles independently of the legacy class — once the multi-stack
|
|
59
|
+
* cutover lands and `stack.ts` is deleted (plan §11 step 10), the
|
|
60
|
+
* helper has no other home anyway.
|
|
61
|
+
*/
|
|
62
|
+
function toLogRetention(days) {
|
|
63
|
+
if (days <= 1)
|
|
64
|
+
return logs.RetentionDays.ONE_DAY;
|
|
65
|
+
if (days <= 3)
|
|
66
|
+
return logs.RetentionDays.THREE_DAYS;
|
|
67
|
+
if (days <= 5)
|
|
68
|
+
return logs.RetentionDays.FIVE_DAYS;
|
|
69
|
+
if (days <= 7)
|
|
70
|
+
return logs.RetentionDays.ONE_WEEK;
|
|
71
|
+
if (days <= 14)
|
|
72
|
+
return logs.RetentionDays.TWO_WEEKS;
|
|
73
|
+
if (days <= 30)
|
|
74
|
+
return logs.RetentionDays.ONE_MONTH;
|
|
75
|
+
if (days <= 60)
|
|
76
|
+
return logs.RetentionDays.TWO_MONTHS;
|
|
77
|
+
if (days <= 90)
|
|
78
|
+
return logs.RetentionDays.THREE_MONTHS;
|
|
79
|
+
if (days <= 180)
|
|
80
|
+
return logs.RetentionDays.SIX_MONTHS;
|
|
81
|
+
if (days <= 365)
|
|
82
|
+
return logs.RetentionDays.ONE_YEAR;
|
|
83
|
+
return logs.RetentionDays.INFINITE;
|
|
84
|
+
}
|
|
85
|
+
export class VentureNetworkStack extends cdk.Stack {
|
|
86
|
+
/**
|
|
87
|
+
* In-process VPC reference for sibling stacks deployed in the
|
|
88
|
+
* same `cdk.App` (the standard `cdk deploy --all` case). Sibling
|
|
89
|
+
* stacks that take a direct CDK reference avoid one round-trip
|
|
90
|
+
* through SSM at synth time and get full CDK-typed access to the
|
|
91
|
+
* VPC abstraction, including AZ + subnet ordering.
|
|
92
|
+
*
|
|
93
|
+
* Cross-deploy and cross-account consumers must instead read the
|
|
94
|
+
* SSM parameters and reconstruct via `importVpc` from
|
|
95
|
+
* `shared/cross-stack-refs.ts` — that path uses
|
|
96
|
+
* `Vpc.fromVpcAttributes` which has slightly fewer affordances
|
|
97
|
+
* than the live reference (no `.selectSubnets({ subnetGroupName })`,
|
|
98
|
+
* for example).
|
|
99
|
+
*/
|
|
100
|
+
vpc;
|
|
101
|
+
constructor(scope, id, props) {
|
|
102
|
+
super(scope, id, props);
|
|
103
|
+
const { projectName, stage, envConfig } = props;
|
|
104
|
+
const vpcConfig = envConfig.vpc;
|
|
105
|
+
const dataSafetyConfig = DATA_SAFETY_CONFIG[envConfig.dataSafety];
|
|
106
|
+
// ── Subnet topology ───────────────────────────────────────────
|
|
107
|
+
// Always: public + private-with-egress.
|
|
108
|
+
// Optional: isolated subnets when the preset declares them
|
|
109
|
+
// (medium+ ships isolated for RDS — strict separation between
|
|
110
|
+
// workload subnets and database subnets, no chance of an
|
|
111
|
+
// accidental egress route reaching the DB).
|
|
112
|
+
const subnetConfig = [
|
|
113
|
+
{ name: 'public', subnetType: ec2.SubnetType.PUBLIC, cidrMask: vpcConfig.publicSubnets.cidrMask },
|
|
114
|
+
{ name: 'private', subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS, cidrMask: vpcConfig.privateSubnets.cidrMask },
|
|
115
|
+
];
|
|
116
|
+
if (vpcConfig.isolatedSubnets) {
|
|
117
|
+
subnetConfig.push({
|
|
118
|
+
name: 'isolated',
|
|
119
|
+
subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
|
|
120
|
+
cidrMask: vpcConfig.isolatedSubnets.cidrMask,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
// ── NAT provider ──────────────────────────────────────────────
|
|
124
|
+
// Cost-vs-reliability dial driven by the preset's `natType`:
|
|
125
|
+
//
|
|
126
|
+
// - `'instance'` (nano/micro/medium): fck-nat AL2023 EC2
|
|
127
|
+
// instance, ~$3-25/mo per AZ (vs $33/mo per AZ for managed
|
|
128
|
+
// NAT GW + $0.045/GB processed). Single point of failure
|
|
129
|
+
// in each AZ — the gateway VPC endpoints below + the
|
|
130
|
+
// opt-in interface endpoints below substantially reduce
|
|
131
|
+
// the blast radius of an instance outage.
|
|
132
|
+
//
|
|
133
|
+
// - `'gateway'` (large): managed NAT Gateways, AWS SLA, zero
|
|
134
|
+
// ops, much higher cost.
|
|
135
|
+
//
|
|
136
|
+
// - `'none'` (free): no NAT at all. Private subnets become
|
|
137
|
+
// egress-less; in-VPC dependencies must be reached via
|
|
138
|
+
// gateway/interface endpoints or not at all. Used by the
|
|
139
|
+
// free preset which doesn't put anything in private
|
|
140
|
+
// subnets.
|
|
141
|
+
//
|
|
142
|
+
// fck-nat (Account `568608671756`) AMI is verified ARM64 AL2023
|
|
143
|
+
// and published in every commercial region; we pin the owner ID
|
|
144
|
+
// explicitly to avoid AMI-lookup typo-squatting.
|
|
145
|
+
const natGateways = vpcConfig.natType === 'none' ? 0 : vpcConfig.natGateways;
|
|
146
|
+
let natGatewayProvider;
|
|
147
|
+
if (vpcConfig.natType === 'instance' && natGateways > 0) {
|
|
148
|
+
natGatewayProvider = ec2.NatProvider.instanceV2({
|
|
149
|
+
instanceType: new ec2.InstanceType(vpcConfig.natInstanceType ?? 't4g.nano'),
|
|
150
|
+
machineImage: ec2.MachineImage.lookup({
|
|
151
|
+
name: 'fck-nat-al2023-*-arm64-ebs',
|
|
152
|
+
owners: ['568608671756'],
|
|
153
|
+
}),
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
// natType: 'gateway' leaves natGatewayProvider undefined, which
|
|
157
|
+
// is CDK's signal to provision managed NAT Gateways.
|
|
158
|
+
this.vpc = new ec2.Vpc(this, 'Vpc', {
|
|
159
|
+
maxAzs: vpcConfig.maxAzs,
|
|
160
|
+
natGateways,
|
|
161
|
+
natGatewayProvider,
|
|
162
|
+
ipAddresses: ec2.IpAddresses.cidr(vpcConfig.cidr),
|
|
163
|
+
subnetConfiguration: subnetConfig,
|
|
164
|
+
// Well-Architected: Security — the AWS-default SG allows
|
|
165
|
+
// anything-to-anything within the VPC; we lock it down so any
|
|
166
|
+
// SG attached without an explicit ingress rule effectively
|
|
167
|
+
// can't communicate, forcing thoughtful SG design.
|
|
168
|
+
restrictDefaultSecurityGroup: true,
|
|
169
|
+
});
|
|
170
|
+
// The L2 `ec2.Vpc` construct handles `DeletionPolicy=Retain`
|
|
171
|
+
// automatically when none of its dependents force replacement.
|
|
172
|
+
// We additionally pin `UpdateReplacePolicy=Retain` on the CFN
|
|
173
|
+
// VPC resource itself for production data-safety. CDK does not
|
|
174
|
+
// expose this knob via L2 props, so we drop to L1 here. This is
|
|
175
|
+
// the same pattern used in the legacy `VentureStack` for RDS,
|
|
176
|
+
// S3, etc.
|
|
177
|
+
if (dataSafetyConfig.removalPolicy === 'retain') {
|
|
178
|
+
const cfnVpc = this.vpc.node.defaultChild;
|
|
179
|
+
cfnVpc.cfnOptions.deletionPolicy = cdk.CfnDeletionPolicy.RETAIN;
|
|
180
|
+
cfnVpc.cfnOptions.updateReplacePolicy = cdk.CfnDeletionPolicy.RETAIN;
|
|
181
|
+
}
|
|
182
|
+
// ── Flow logs ─────────────────────────────────────────────────
|
|
183
|
+
// Off by default on cheap presets (logs cost money; small dev
|
|
184
|
+
// environments don't need them). Strictly informational — the
|
|
185
|
+
// VPC functions identically without them.
|
|
186
|
+
if (vpcConfig.flowLogsEnabled) {
|
|
187
|
+
this.vpc.addFlowLog('FlowLog', {
|
|
188
|
+
destination: ec2.FlowLogDestination.toCloudWatchLogs(new logs.LogGroup(this, 'VpcFlowLogGroup', {
|
|
189
|
+
logGroupName: `/venturekit/${projectName}/${stage}/vpc-flow-logs`,
|
|
190
|
+
retention: toLogRetention(vpcConfig.flowLogsRetentionDays),
|
|
191
|
+
removalPolicy: dataSafetyConfig.removalPolicy === 'retain'
|
|
192
|
+
? cdk.RemovalPolicy.RETAIN
|
|
193
|
+
: cdk.RemovalPolicy.DESTROY,
|
|
194
|
+
})),
|
|
195
|
+
trafficType: ec2.FlowLogTrafficType.ALL,
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
// ── Gateway VPC endpoints — always on ─────────────────────────
|
|
199
|
+
// Free at hourly + per-GB rates. The route tables get an entry
|
|
200
|
+
// for the S3 / DynamoDB managed prefix lists pointing at the
|
|
201
|
+
// gateway endpoint, so VPC-internal traffic to those services
|
|
202
|
+
// never hits NAT.
|
|
203
|
+
//
|
|
204
|
+
// The migration runner's CodeBuild job downloads sources from
|
|
205
|
+
// `cdk-hnb659fds-assets-<account>-<region>` in S3; without the
|
|
206
|
+
// S3 gateway endpoint that traffic routes through NAT, which on
|
|
207
|
+
// the small presets is a single fck-nat instance and an outright
|
|
208
|
+
// reliability hazard (tracked as the "DOWNLOAD_SOURCE i/o
|
|
209
|
+
// timeout" production incident).
|
|
210
|
+
this.vpc.addGatewayEndpoint('S3Endpoint', {
|
|
211
|
+
service: ec2.GatewayVpcEndpointAwsService.S3,
|
|
212
|
+
});
|
|
213
|
+
this.vpc.addGatewayEndpoint('DynamoEndpoint', {
|
|
214
|
+
service: ec2.GatewayVpcEndpointAwsService.DYNAMODB,
|
|
215
|
+
});
|
|
216
|
+
// ── Interface endpoints — opt-in via preset ──────────────────
|
|
217
|
+
// ~$7.20/mo per AZ + $0.01/GB processed each, gated by
|
|
218
|
+
// `vpcConfig.enableVpcEndpoints` (off on free/nano, on for
|
|
219
|
+
// micro/medium/large). The single most-impactful endpoint to
|
|
220
|
+
// keep on is Secrets Manager: every VPC-attached Lambda calls
|
|
221
|
+
// `applyDbSecretToEnv()` on cold start, and without the
|
|
222
|
+
// endpoint that call traverses NAT — which on small presets is
|
|
223
|
+
// a single-AZ fck-nat instance whose hang would eat the entire
|
|
224
|
+
// Lambda timeout with no diagnostic output.
|
|
225
|
+
if (vpcConfig.enableVpcEndpoints) {
|
|
226
|
+
// Dedicated SG for interface endpoints. We allow inbound
|
|
227
|
+
// HTTPS from the VPC CIDR rather than from the Lambda SG,
|
|
228
|
+
// because:
|
|
229
|
+
// 1. The Lambda SG doesn't exist yet in this stack — it
|
|
230
|
+
// lives in the app stack.
|
|
231
|
+
// 2. CIDR-based ingress is sufficient: interface endpoint
|
|
232
|
+
// ENIs are addressable only from inside the VPC anyway.
|
|
233
|
+
const endpointSg = new ec2.SecurityGroup(this, 'VpcEndpointsSg', {
|
|
234
|
+
vpc: this.vpc,
|
|
235
|
+
description: `Interface endpoint SG for ${projectName}-${stage}`,
|
|
236
|
+
allowAllOutbound: false,
|
|
237
|
+
});
|
|
238
|
+
endpointSg.addIngressRule(ec2.Peer.ipv4(this.vpc.vpcCidrBlock), ec2.Port.tcp(443), 'HTTPS from anywhere in the VPC');
|
|
239
|
+
this.vpc.addInterfaceEndpoint('SecretsManagerEndpoint', {
|
|
240
|
+
service: ec2.InterfaceVpcEndpointAwsService.SECRETS_MANAGER,
|
|
241
|
+
securityGroups: [endpointSg],
|
|
242
|
+
subnets: { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS },
|
|
243
|
+
privateDnsEnabled: true,
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
// ── Publish the public surface to SSM ─────────────────────────
|
|
247
|
+
// Other tiers (data, app) read these via the
|
|
248
|
+
// `cross-stack-refs.importVpc(...)` helper. We deliberately
|
|
249
|
+
// publish the AZ list AND each subnet group separately rather
|
|
250
|
+
// than a denormalized blob — `Vpc.fromVpcAttributes` consumes
|
|
251
|
+
// them as parallel arrays, and storing the parts independently
|
|
252
|
+
// means a single subnet ID change doesn't churn the whole
|
|
253
|
+
// payload's hash.
|
|
254
|
+
writeSsm(this, networkKeys.vpcId(projectName, stage), this.vpc.vpcId, {
|
|
255
|
+
description: `VPC ID for ${projectName} ${stage}`,
|
|
256
|
+
});
|
|
257
|
+
writeSsmStringList(this, networkKeys.availabilityZones(projectName, stage), this.vpc.availabilityZones, { description: `AZ ordering for ${projectName} ${stage}` });
|
|
258
|
+
writeSsmStringList(this, networkKeys.privateSubnetIds(projectName, stage), this.vpc.privateSubnets.map((s) => s.subnetId), { description: `Private (with-egress) subnet IDs for ${projectName} ${stage}` });
|
|
259
|
+
writeSsmStringList(this, networkKeys.publicSubnetIds(projectName, stage), this.vpc.publicSubnets.map((s) => s.subnetId), { description: `Public subnet IDs for ${projectName} ${stage}` });
|
|
260
|
+
if (vpcConfig.isolatedSubnets) {
|
|
261
|
+
writeSsmStringList(this, networkKeys.isolatedSubnetIds(projectName, stage), this.vpc.isolatedSubnets.map((s) => s.subnetId), { description: `Isolated (no-egress) subnet IDs for ${projectName} ${stage}` });
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
//# sourceMappingURL=network-stack.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"network-stack.js","sourceRoot":"","sources":["../../src/cdk/network-stack.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-stack reference helpers for the lifecycle-aligned multi-stack
|
|
3
|
+
* layout. Producers write SSM `String` parameters; consumers read via
|
|
4
|
+
* CFN dynamic references (`{{resolve:ssm:…}}`) which AWS resolves at
|
|
5
|
+
* deploy time without forming a CFN stack-graph dependency.
|
|
6
|
+
*
|
|
7
|
+
* # Producer side: `writeSsm` / `writeSsmStringList`
|
|
8
|
+
*
|
|
9
|
+
* Producer stacks (network, data, identity, config, messaging, edge)
|
|
10
|
+
* publish their public surface by calling these helpers. The actual
|
|
11
|
+
* CDK construct is `ssm.StringParameter` — we wrap it for two
|
|
12
|
+
* reasons:
|
|
13
|
+
*
|
|
14
|
+
* 1. Stable logical IDs. CDK's default ID derives from the
|
|
15
|
+
* construct path; we want IDs that don't churn across refactors
|
|
16
|
+
* so a producer-side rename (e.g. moving from
|
|
17
|
+
* `VentureDataStack.createRds` to `…createDatabase`) doesn't
|
|
18
|
+
* orphan the parameter and force a redeploy of every consumer.
|
|
19
|
+
* We derive the logical ID from a slug of the parameter name
|
|
20
|
+
* (`/venturekit/p/s/data/rds/main/endpoint` →
|
|
21
|
+
* `SsmVenturekitPSDataRdsMainEndpoint`), which is stable
|
|
22
|
+
* regardless of where in the stack tree the call site lives.
|
|
23
|
+
*
|
|
24
|
+
* 2. Single audit point. Every cross-stack value flowing out of a
|
|
25
|
+
* producer goes through `writeSsm`, so security review can grep
|
|
26
|
+
* one symbol to enumerate the public surface.
|
|
27
|
+
*
|
|
28
|
+
* # Consumer side: `readSsm…` + `import…`
|
|
29
|
+
*
|
|
30
|
+
* Consumers never instantiate AWS resources from raw construct props;
|
|
31
|
+
* they call the typed `import…` helpers below which encapsulate the
|
|
32
|
+
* full `Foo.fromXAttributes({...})` rehydration. That keeps the
|
|
33
|
+
* cross-stack contract narrow: the producer publishes exactly the
|
|
34
|
+
* fields the importer expects, the importer fails loudly at synth if
|
|
35
|
+
* any are missing, and any change to the contract shape forces a
|
|
36
|
+
* coordinated edit at both ends.
|
|
37
|
+
*
|
|
38
|
+
* # Why not `Stack.exportValue` / `Fn::ImportValue`?
|
|
39
|
+
*
|
|
40
|
+
* See the long-form rationale in `ssm-keys.ts`. tl;dr: CFN exports
|
|
41
|
+
* carry a hard "cannot modify a consumed export" lock that makes the
|
|
42
|
+
* stable lower tiers unable to evolve. SSM dynamic references have
|
|
43
|
+
* no such lock.
|
|
44
|
+
*
|
|
45
|
+
* # Why not StringList parameters?
|
|
46
|
+
*
|
|
47
|
+
* SSM `StringList` parameters cannot be referenced by the
|
|
48
|
+
* `{{resolve:ssm:...}}` dynamic-reference syntax — only `String` and
|
|
49
|
+
* `SecureString`. We work around it by storing comma-joined strings
|
|
50
|
+
* via `writeSsmStringList` and splitting on read via
|
|
51
|
+
* `readSsmStringList`. The split happens at deploy time inside CDK
|
|
52
|
+
* after the dynamic reference resolves, so it works transparently.
|
|
53
|
+
*/
|
|
54
|
+
import * as ec2 from 'aws-cdk-lib/aws-ec2';
|
|
55
|
+
import * as s3 from 'aws-cdk-lib/aws-s3';
|
|
56
|
+
import * as cognito from 'aws-cdk-lib/aws-cognito';
|
|
57
|
+
import * as sqs from 'aws-cdk-lib/aws-sqs';
|
|
58
|
+
import * as sns from 'aws-cdk-lib/aws-sns';
|
|
59
|
+
import * as ssm from 'aws-cdk-lib/aws-ssm';
|
|
60
|
+
import * as secretsmanager from 'aws-cdk-lib/aws-secretsmanager';
|
|
61
|
+
import * as apigatewayv2 from 'aws-cdk-lib/aws-apigatewayv2';
|
|
62
|
+
import * as dynamodb from 'aws-cdk-lib/aws-dynamodb';
|
|
63
|
+
import { Construct } from 'constructs';
|
|
64
|
+
/**
|
|
65
|
+
* Convert an SSM parameter name to a stable CDK logical ID.
|
|
66
|
+
*
|
|
67
|
+
* Rules:
|
|
68
|
+
* - Drop the leading slash.
|
|
69
|
+
* - Replace every non-alphanumeric character with a single space.
|
|
70
|
+
* - Title-case each word, drop spaces.
|
|
71
|
+
* - Prefix `Ssm` so logical IDs are namespaced.
|
|
72
|
+
*
|
|
73
|
+
* `/venturekit/myapp/prod/data/rds/main/endpoint` →
|
|
74
|
+
* `SsmVenturekitMyappProdDataRdsMainEndpoint`
|
|
75
|
+
*
|
|
76
|
+
* The output is deterministic, contains only alphanumerics, fits well
|
|
77
|
+
* within CFN's 255-char logical-ID limit (a maximally long key like
|
|
78
|
+
* `/venturekit/<32-char-project>/<8-char-stage>/messaging/queues/<32-char-id>/visibility-timeout-seconds`
|
|
79
|
+
* yields a ~120-char logical ID), and is stable across producer
|
|
80
|
+
* refactors.
|
|
81
|
+
*/
|
|
82
|
+
export declare function logicalIdForParameter(parameterName: string): string;
|
|
83
|
+
export interface WriteSsmOptions {
|
|
84
|
+
/**
|
|
85
|
+
* Optional human-readable description stored on the SSM parameter
|
|
86
|
+
* itself. Useful for operators inspecting parameters via
|
|
87
|
+
* `aws ssm describe-parameters` — the description shows up in the
|
|
88
|
+
* console alongside the key.
|
|
89
|
+
*/
|
|
90
|
+
description?: string;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Publish a single string value to SSM at `name`. Returns the
|
|
94
|
+
* underlying `ssm.StringParameter` so the caller can grant additional
|
|
95
|
+
* IAM permissions (rare; the default SSM-read IAM is sufficient for
|
|
96
|
+
* the dynamic-reference path).
|
|
97
|
+
*
|
|
98
|
+
* Idempotent within one synth: calling `writeSsm` twice with the same
|
|
99
|
+
* name in the same stack throws CDK's standard
|
|
100
|
+
* "Construct with id 'X' already exists" — that's a producer bug
|
|
101
|
+
* (two producers claiming the same key).
|
|
102
|
+
*/
|
|
103
|
+
export declare function writeSsm(scope: Construct, name: string, value: string, opts?: WriteSsmOptions): ssm.StringParameter;
|
|
104
|
+
/**
|
|
105
|
+
* Publish a list as a single comma-joined `String` parameter. Use
|
|
106
|
+
* this for things like subnet ID lists where the consumer needs the
|
|
107
|
+
* individual values back. SSM `StringList` parameters are rejected
|
|
108
|
+
* by the `{{resolve:ssm:…}}` dynamic reference, so we round-trip via
|
|
109
|
+
* comma-joined strings.
|
|
110
|
+
*
|
|
111
|
+
* Throws if any element contains a comma — that would silently
|
|
112
|
+
* corrupt the list on read. AWS resource IDs (subnet IDs, AZ names,
|
|
113
|
+
* security group IDs) are guaranteed comma-free, so this should
|
|
114
|
+
* never fire in practice; the assertion just locks the assumption.
|
|
115
|
+
*/
|
|
116
|
+
export declare function writeSsmStringList(scope: Construct, name: string, values: string[], opts?: WriteSsmOptions): ssm.StringParameter;
|
|
117
|
+
/**
|
|
118
|
+
* Read a single SSM string parameter as a CFN dynamic reference.
|
|
119
|
+
* The returned token resolves to the parameter's current value at
|
|
120
|
+
* deploy time — there is NO build-time / synth-time AWS API call,
|
|
121
|
+
* so this works in hermetic CI without AWS credentials.
|
|
122
|
+
*
|
|
123
|
+
* The token can be passed anywhere CDK accepts a string property
|
|
124
|
+
* (resource ARNs, IDs, env vars). It cannot be inspected at synth
|
|
125
|
+
* time — `console.log(value)` will print `${Token[TOKEN.123]}`,
|
|
126
|
+
* not the actual value.
|
|
127
|
+
*/
|
|
128
|
+
export declare function readSsmString(scope: Construct, name: string): string;
|
|
129
|
+
/**
|
|
130
|
+
* Read a comma-joined `String` parameter and split it back into a
|
|
131
|
+
* list. Used as the symmetric counterpart to `writeSsmStringList`.
|
|
132
|
+
*
|
|
133
|
+
* Implementation note: because the parameter value is a CFN token
|
|
134
|
+
* resolved at deploy time, we cannot call `.split(',')` directly —
|
|
135
|
+
* the token is opaque to JS. CDK's `Fn.split` produces a CFN
|
|
136
|
+
* `Fn::Split` intrinsic that runs at deploy time; we then use
|
|
137
|
+
* `Fn.select` to access individual elements OR pass the whole
|
|
138
|
+
* `cdk.Token`-wrapped array into a context that accepts arrays.
|
|
139
|
+
*
|
|
140
|
+
* `count` is the **expected** number of elements — required because
|
|
141
|
+
* `Fn::Split` returns a length-unknown list and CDK refuses to
|
|
142
|
+
* iterate it without a hint. Callers who don't know the count up
|
|
143
|
+
* front (rare) should pass it through SSM as a separate parameter.
|
|
144
|
+
*/
|
|
145
|
+
export declare function readSsmStringList(scope: Construct, name: string, count: number): string[];
|
|
146
|
+
export interface ImportVpcParams {
|
|
147
|
+
vpcId: string;
|
|
148
|
+
/** AZ list, ordered to match the subnet ID lists. */
|
|
149
|
+
availabilityZones: string[];
|
|
150
|
+
/** Per-AZ private subnet IDs — same length + ordering as `availabilityZones`. */
|
|
151
|
+
privateSubnetIds: string[];
|
|
152
|
+
/** Per-AZ public subnet IDs (optional). */
|
|
153
|
+
publicSubnetIds?: string[];
|
|
154
|
+
/** Per-AZ isolated subnet IDs (optional). */
|
|
155
|
+
isolatedSubnetIds?: string[];
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Reconstruct a VPC abstraction from its public attributes (read out
|
|
159
|
+
* of SSM by the consumer). This deliberately uses
|
|
160
|
+
* `Vpc.fromVpcAttributes` rather than `Vpc.fromLookup` because:
|
|
161
|
+
*
|
|
162
|
+
* 1. `fromLookup` makes a real `ec2:DescribeVpcs` API call at synth
|
|
163
|
+
* time, breaking hermetic CI (the runner needs IAM creds).
|
|
164
|
+
* 2. `fromLookup` writes results into `cdk.context.json`, which
|
|
165
|
+
* then needs to be checked in or regenerated; that's another
|
|
166
|
+
* moving part for no benefit when the consumer already has
|
|
167
|
+
* every needed attribute via SSM.
|
|
168
|
+
*
|
|
169
|
+
* AZ + subnet-ID lists must be the same length and same ordering —
|
|
170
|
+
* CDK uses the index to pair each subnet with its AZ. Lists shorter
|
|
171
|
+
* than the AZ list mean "no subnet in that AZ"; CDK handles that fine.
|
|
172
|
+
*/
|
|
173
|
+
export declare function importVpc(scope: Construct, id: string, params: ImportVpcParams): ec2.IVpc;
|
|
174
|
+
export interface ImportRdsConnectionParams {
|
|
175
|
+
/** Output of `dataKeys.rdsEndpoint`. */
|
|
176
|
+
endpoint: string;
|
|
177
|
+
/** Output of `dataKeys.rdsPort` — string from SSM, parsed to number. */
|
|
178
|
+
port: string | number;
|
|
179
|
+
/** Output of `dataKeys.rdsSecurityGroupId`. */
|
|
180
|
+
securityGroupId: string;
|
|
181
|
+
}
|
|
182
|
+
export interface ImportedRdsConnection {
|
|
183
|
+
/** RDS host (passed straight through; consumer assembles the JDBC URL). */
|
|
184
|
+
endpoint: string;
|
|
185
|
+
/** Port as a number. */
|
|
186
|
+
port: number;
|
|
187
|
+
/**
|
|
188
|
+
* Imported SecurityGroup. The consumer attaches a Lambda SG and
|
|
189
|
+
* calls `rdsSg.connections.allowFrom(lambdaSg, ec2.Port.tcp(port))`
|
|
190
|
+
* — that emits an `AWS::EC2::SecurityGroupIngress` in the consumer
|
|
191
|
+
* stack which is removed cleanly on consumer-stack delete (plan
|
|
192
|
+
* §6.1).
|
|
193
|
+
*/
|
|
194
|
+
securityGroup: ec2.ISecurityGroup;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Import the RDS connection surface (endpoint + port + SG) without
|
|
198
|
+
* actually instantiating an `IDatabaseInstance` — we don't need the
|
|
199
|
+
* full DB abstraction in the app stack, just enough to point Lambdas
|
|
200
|
+
* at it and open the SG.
|
|
201
|
+
*/
|
|
202
|
+
export declare function importRdsConnection(scope: Construct, id: string, params: ImportRdsConnectionParams): ImportedRdsConnection;
|
|
203
|
+
/**
|
|
204
|
+
* Import an S3 bucket by ARN. Returns an `IBucket` so the consumer
|
|
205
|
+
* can call `bucket.grantReadWrite(lambdaRole)` etc. — those grants
|
|
206
|
+
* land in the consumer stack's IAM policy, leaving the bucket
|
|
207
|
+
* itself untouched.
|
|
208
|
+
*
|
|
209
|
+
* `Bucket.fromBucketArn` returns a less-typed view (no
|
|
210
|
+
* encryption/versioning info) than `fromBucketAttributes`, but for
|
|
211
|
+
* IAM grants and env-var injection that's all the app stack needs.
|
|
212
|
+
*/
|
|
213
|
+
export declare function importBucket(scope: Construct, id: string, bucketArn: string): s3.IBucket;
|
|
214
|
+
/**
|
|
215
|
+
* Import a DynamoDB table by ARN. Returns an `ITable` for IAM
|
|
216
|
+
* grants. Note: `Table.fromTableArn` does NOT include the GSI
|
|
217
|
+
* indexes — for `Query` against a GSI, the consumer must call
|
|
218
|
+
* `Table.fromTableAttributes({ tableArn, globalIndexes: ['gsi1'] })`
|
|
219
|
+
* instead. Since most app-stack code paths only read/write the
|
|
220
|
+
* primary key, ARN-only is the common case; we wrap it here for
|
|
221
|
+
* convenience and document the GSI exception.
|
|
222
|
+
*/
|
|
223
|
+
export declare function importDynamoTable(scope: Construct, id: string, tableArn: string): dynamodb.ITable;
|
|
224
|
+
export interface ImportUserPoolParams {
|
|
225
|
+
userPoolId: string;
|
|
226
|
+
userPoolArn: string;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Import a Cognito User Pool. The pool ID is what `AdminInitiateAuth`
|
|
230
|
+
* etc. need at runtime; the ARN is what IAM policies scope to. Both
|
|
231
|
+
* are published by the identity stack via `identityKeys`.
|
|
232
|
+
*/
|
|
233
|
+
export declare function importUserPool(scope: Construct, id: string, params: ImportUserPoolParams): cognito.IUserPool;
|
|
234
|
+
/**
|
|
235
|
+
* Import an SQS queue by ARN. The CDK helper extracts the URL from
|
|
236
|
+
* the ARN under the standard naming convention, which is what
|
|
237
|
+
* Lambda's `addEventSource(new SqsEventSource(queue))` wants.
|
|
238
|
+
*
|
|
239
|
+
* On consumer-stack delete, the resulting `EventSourceMapping` is
|
|
240
|
+
* removed; the queue + DLQ + buffered messages live on in the
|
|
241
|
+
* messaging stack (plan §6.2).
|
|
242
|
+
*/
|
|
243
|
+
export declare function importQueue(scope: Construct, id: string, queueArn: string): sqs.IQueue;
|
|
244
|
+
/**
|
|
245
|
+
* Import an SNS topic by ARN. Used by the app stack to subscribe
|
|
246
|
+
* the bounce-handler Lambda to the notify events topic created in
|
|
247
|
+
* the config tier.
|
|
248
|
+
*/
|
|
249
|
+
export declare function importTopic(scope: Construct, id: string, topicArn: string): sns.ITopic;
|
|
250
|
+
/**
|
|
251
|
+
* Import a Secrets Manager secret by ARN. Used for every
|
|
252
|
+
* cross-stack secret reference (RDS master credentials, federated
|
|
253
|
+
* provider OAuth credentials, WhatsApp tokens, operator-declared
|
|
254
|
+
* `secrets` intents).
|
|
255
|
+
*/
|
|
256
|
+
export declare function importSecret(scope: Construct, id: string, secretArn: string): secretsmanager.ISecret;
|
|
257
|
+
export interface ImportHttpApiParams {
|
|
258
|
+
apiId: string;
|
|
259
|
+
/**
|
|
260
|
+
* Default-stage name. Always `'$default'` for HttpApi today; we
|
|
261
|
+
* still accept it as a parameter for forward-compat with named
|
|
262
|
+
* stages.
|
|
263
|
+
*/
|
|
264
|
+
defaultStageName: string;
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Import an API Gateway HttpApi. The app stack needs this to add
|
|
268
|
+
* routes that target Lambdas in the app stack itself — the route
|
|
269
|
+
* `AWS::ApiGatewayV2::Route` resource lives in the consumer (app)
|
|
270
|
+
* stack and references the imported API by ID.
|
|
271
|
+
*
|
|
272
|
+
* IMPORTANT: `HttpApi.fromHttpApiAttributes` does NOT carry the
|
|
273
|
+
* `defaultStage` in its returned `IHttpApi`; consumers that need
|
|
274
|
+
* to attach access logs or stage variables must manage that
|
|
275
|
+
* separately on the producer (edge) side.
|
|
276
|
+
*/
|
|
277
|
+
export declare function importHttpApi(scope: Construct, id: string, params: ImportHttpApiParams): apigatewayv2.IHttpApi;
|
|
278
|
+
//# sourceMappingURL=cross-stack-refs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cross-stack-refs.d.ts","sourceRoot":"","sources":["../../../src/cdk/shared/cross-stack-refs.ts"],"names":[],"mappings":"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"}
|