@stacksjs/ts-cloud-core 0.1.3 → 0.1.6
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/README.md +98 -13
- package/package.json +12 -3
- package/src/advanced-features.test.ts +0 -465
- package/src/aws/cloudformation.ts +0 -421
- package/src/aws/cloudfront.ts +0 -158
- package/src/aws/credentials.test.ts +0 -132
- package/src/aws/credentials.ts +0 -545
- package/src/aws/index.ts +0 -87
- package/src/aws/s3.test.ts +0 -188
- package/src/aws/s3.ts +0 -1088
- package/src/aws/signature.test.ts +0 -670
- package/src/aws/signature.ts +0 -1155
- package/src/backup/disaster-recovery.test.ts +0 -726
- package/src/backup/disaster-recovery.ts +0 -500
- package/src/backup/index.ts +0 -34
- package/src/backup/manager.test.ts +0 -498
- package/src/backup/manager.ts +0 -432
- package/src/cicd/circleci.ts +0 -430
- package/src/cicd/github-actions.ts +0 -424
- package/src/cicd/gitlab-ci.ts +0 -255
- package/src/cicd/index.ts +0 -8
- package/src/cli/history.ts +0 -396
- package/src/cli/index.ts +0 -10
- package/src/cli/progress.ts +0 -458
- package/src/cli/repl.ts +0 -454
- package/src/cli/suggestions.ts +0 -327
- package/src/cli/table.test.ts +0 -319
- package/src/cli/table.ts +0 -332
- package/src/cloudformation/builder.test.ts +0 -327
- package/src/cloudformation/builder.ts +0 -378
- package/src/cloudformation/builders/api-gateway.ts +0 -449
- package/src/cloudformation/builders/cache.ts +0 -334
- package/src/cloudformation/builders/cdn.ts +0 -278
- package/src/cloudformation/builders/compute.ts +0 -485
- package/src/cloudformation/builders/database.ts +0 -392
- package/src/cloudformation/builders/functions.ts +0 -343
- package/src/cloudformation/builders/messaging.ts +0 -140
- package/src/cloudformation/builders/monitoring.ts +0 -300
- package/src/cloudformation/builders/network.ts +0 -264
- package/src/cloudformation/builders/queue.ts +0 -147
- package/src/cloudformation/builders/security.ts +0 -399
- package/src/cloudformation/builders/storage.ts +0 -285
- package/src/cloudformation/index.ts +0 -30
- package/src/cloudformation/types.ts +0 -173
- package/src/compliance/aws-config.ts +0 -543
- package/src/compliance/cloudtrail.ts +0 -376
- package/src/compliance/compliance.test.ts +0 -423
- package/src/compliance/guardduty.ts +0 -446
- package/src/compliance/index.ts +0 -66
- package/src/compliance/security-hub.ts +0 -456
- package/src/containers/build-optimization.ts +0 -416
- package/src/containers/containers.test.ts +0 -508
- package/src/containers/image-scanning.ts +0 -360
- package/src/containers/index.ts +0 -9
- package/src/containers/registry.ts +0 -293
- package/src/containers/service-mesh.ts +0 -520
- package/src/database/database.test.ts +0 -762
- package/src/database/index.ts +0 -9
- package/src/database/migrations.ts +0 -444
- package/src/database/performance.ts +0 -528
- package/src/database/replicas.ts +0 -534
- package/src/database/users.ts +0 -494
- package/src/dependency-graph.ts +0 -143
- package/src/deployment/ab-testing.ts +0 -582
- package/src/deployment/blue-green.ts +0 -452
- package/src/deployment/canary.ts +0 -500
- package/src/deployment/deployment.test.ts +0 -526
- package/src/deployment/index.ts +0 -61
- package/src/deployment/progressive.ts +0 -62
- package/src/dns/dns.test.ts +0 -641
- package/src/dns/dnssec.ts +0 -315
- package/src/dns/index.ts +0 -8
- package/src/dns/resolver.ts +0 -496
- package/src/dns/routing.ts +0 -593
- package/src/email/advanced/analytics.ts +0 -445
- package/src/email/advanced/index.ts +0 -11
- package/src/email/advanced/rules.ts +0 -465
- package/src/email/advanced/scheduling.ts +0 -352
- package/src/email/advanced/search.ts +0 -412
- package/src/email/advanced/shared-mailboxes.ts +0 -404
- package/src/email/advanced/templates.ts +0 -455
- package/src/email/advanced/threading.ts +0 -281
- package/src/email/analytics.ts +0 -467
- package/src/email/bounce-handling.ts +0 -425
- package/src/email/email.test.ts +0 -431
- package/src/email/handlers/__tests__/inbound.test.ts +0 -38
- package/src/email/handlers/__tests__/outbound.test.ts +0 -37
- package/src/email/handlers/converter.ts +0 -227
- package/src/email/handlers/feedback.ts +0 -228
- package/src/email/handlers/inbound.ts +0 -169
- package/src/email/handlers/outbound.ts +0 -178
- package/src/email/index.ts +0 -15
- package/src/email/reputation.ts +0 -303
- package/src/email/templates.ts +0 -352
- package/src/errors/index.test.ts +0 -434
- package/src/errors/index.ts +0 -416
- package/src/health-checks/index.ts +0 -40
- package/src/index.ts +0 -360
- package/src/intrinsic-functions.ts +0 -118
- package/src/lambda/concurrency.ts +0 -330
- package/src/lambda/destinations.ts +0 -345
- package/src/lambda/dlq.ts +0 -425
- package/src/lambda/index.ts +0 -11
- package/src/lambda/lambda.test.ts +0 -840
- package/src/lambda/layers.ts +0 -263
- package/src/lambda/versions.ts +0 -376
- package/src/lambda/vpc.ts +0 -399
- package/src/local/config.ts +0 -114
- package/src/local/index.ts +0 -6
- package/src/local/mock-aws.ts +0 -351
- package/src/modules/ai.ts +0 -340
- package/src/modules/api.ts +0 -478
- package/src/modules/auth.ts +0 -805
- package/src/modules/cache.ts +0 -417
- package/src/modules/cdn.ts +0 -1062
- package/src/modules/communication.ts +0 -1094
- package/src/modules/compute.ts +0 -3348
- package/src/modules/database.ts +0 -554
- package/src/modules/deployment.ts +0 -1079
- package/src/modules/dns.ts +0 -337
- package/src/modules/email.ts +0 -1538
- package/src/modules/filesystem.ts +0 -515
- package/src/modules/index.ts +0 -32
- package/src/modules/messaging.ts +0 -486
- package/src/modules/monitoring.ts +0 -2086
- package/src/modules/network.ts +0 -664
- package/src/modules/parameter-store.ts +0 -325
- package/src/modules/permissions.ts +0 -1081
- package/src/modules/phone.ts +0 -494
- package/src/modules/queue.ts +0 -1260
- package/src/modules/redirects.ts +0 -464
- package/src/modules/registry.ts +0 -699
- package/src/modules/search.ts +0 -401
- package/src/modules/secrets.ts +0 -416
- package/src/modules/security.ts +0 -731
- package/src/modules/sms.ts +0 -389
- package/src/modules/storage.ts +0 -1120
- package/src/modules/workflow.ts +0 -680
- package/src/multi-account/config.ts +0 -521
- package/src/multi-account/index.ts +0 -7
- package/src/multi-account/manager.ts +0 -427
- package/src/multi-region/cross-region.ts +0 -410
- package/src/multi-region/index.ts +0 -8
- package/src/multi-region/manager.ts +0 -483
- package/src/multi-region/regions.ts +0 -435
- package/src/network-security/index.ts +0 -48
- package/src/observability/index.ts +0 -9
- package/src/observability/logs.ts +0 -522
- package/src/observability/metrics.ts +0 -460
- package/src/observability/observability.test.ts +0 -782
- package/src/observability/synthetics.ts +0 -568
- package/src/observability/xray.ts +0 -358
- package/src/phone/advanced/analytics.ts +0 -349
- package/src/phone/advanced/callbacks.ts +0 -428
- package/src/phone/advanced/index.ts +0 -8
- package/src/phone/advanced/ivr-builder.ts +0 -504
- package/src/phone/advanced/recording.ts +0 -310
- package/src/phone/handlers/__tests__/incoming-call.test.ts +0 -40
- package/src/phone/handlers/incoming-call.ts +0 -117
- package/src/phone/handlers/missed-call.ts +0 -116
- package/src/phone/handlers/voicemail.ts +0 -179
- package/src/phone/index.ts +0 -9
- package/src/presets/api-backend.ts +0 -134
- package/src/presets/data-pipeline.ts +0 -204
- package/src/presets/extend.test.ts +0 -295
- package/src/presets/extend.ts +0 -297
- package/src/presets/fullstack-app.ts +0 -144
- package/src/presets/index.ts +0 -27
- package/src/presets/jamstack.ts +0 -135
- package/src/presets/microservices.ts +0 -167
- package/src/presets/ml-api.ts +0 -208
- package/src/presets/nodejs-server.ts +0 -104
- package/src/presets/nodejs-serverless.ts +0 -114
- package/src/presets/realtime-app.ts +0 -184
- package/src/presets/static-site.ts +0 -64
- package/src/presets/traditional-web-app.ts +0 -339
- package/src/presets/wordpress.ts +0 -138
- package/src/preview/github.test.ts +0 -249
- package/src/preview/github.ts +0 -297
- package/src/preview/index.ts +0 -37
- package/src/preview/manager.test.ts +0 -440
- package/src/preview/manager.ts +0 -326
- package/src/preview/notifications.test.ts +0 -582
- package/src/preview/notifications.ts +0 -341
- package/src/queue/batch-processing.ts +0 -402
- package/src/queue/dlq-monitoring.ts +0 -402
- package/src/queue/fifo.ts +0 -342
- package/src/queue/index.ts +0 -9
- package/src/queue/management.ts +0 -428
- package/src/queue/queue.test.ts +0 -429
- package/src/resource-mgmt/index.ts +0 -39
- package/src/resource-naming.ts +0 -62
- package/src/s3/index.ts +0 -523
- package/src/schema/cloud-config.schema.json +0 -554
- package/src/schema/index.ts +0 -68
- package/src/security/certificate-manager.ts +0 -492
- package/src/security/index.ts +0 -9
- package/src/security/scanning.ts +0 -545
- package/src/security/secrets-manager.ts +0 -476
- package/src/security/secrets-rotation.ts +0 -456
- package/src/security/security.test.ts +0 -738
- package/src/sms/advanced/ab-testing.ts +0 -389
- package/src/sms/advanced/analytics.ts +0 -336
- package/src/sms/advanced/campaigns.ts +0 -523
- package/src/sms/advanced/chatbot.ts +0 -224
- package/src/sms/advanced/index.ts +0 -10
- package/src/sms/advanced/link-tracking.ts +0 -248
- package/src/sms/advanced/mms.ts +0 -308
- package/src/sms/handlers/__tests__/send.test.ts +0 -40
- package/src/sms/handlers/delivery-status.ts +0 -133
- package/src/sms/handlers/receive.ts +0 -162
- package/src/sms/handlers/send.ts +0 -174
- package/src/sms/index.ts +0 -9
- package/src/stack-diff.ts +0 -389
- package/src/static-site/index.ts +0 -85
- package/src/template-builder.ts +0 -110
- package/src/template-validator.ts +0 -574
- package/src/utils/cache.ts +0 -291
- package/src/utils/diff.ts +0 -269
- package/src/utils/hash.ts +0 -227
- package/src/utils/index.ts +0 -8
- package/src/utils/parallel.ts +0 -294
- package/src/validators/credentials.test.ts +0 -274
- package/src/validators/credentials.ts +0 -233
- package/src/validators/quotas.test.ts +0 -434
- package/src/validators/quotas.ts +0 -217
- package/test/ai.test.ts +0 -327
- package/test/api.test.ts +0 -511
- package/test/auth.test.ts +0 -632
- package/test/cache.test.ts +0 -406
- package/test/cdn.test.ts +0 -247
- package/test/compute.test.ts +0 -861
- package/test/database.test.ts +0 -523
- package/test/deployment.test.ts +0 -499
- package/test/dns.test.ts +0 -270
- package/test/email.test.ts +0 -439
- package/test/filesystem.test.ts +0 -382
- package/test/integration.test.ts +0 -350
- package/test/messaging.test.ts +0 -514
- package/test/monitoring.test.ts +0 -634
- package/test/network.test.ts +0 -425
- package/test/permissions.test.ts +0 -488
- package/test/queue.test.ts +0 -484
- package/test/registry.test.ts +0 -306
- package/test/security.test.ts +0 -462
- package/test/storage.test.ts +0 -463
- package/test/template-validator.test.ts +0 -559
- package/test/workflow.test.ts +0 -592
- package/tsconfig.json +0 -16
- package/tsconfig.tsbuildinfo +0 -1
package/src/modules/network.ts
DELETED
|
@@ -1,664 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
EC2EIP,
|
|
3
|
-
EC2FlowLog,
|
|
4
|
-
EC2InternetGateway,
|
|
5
|
-
EC2NatGateway,
|
|
6
|
-
EC2Route,
|
|
7
|
-
EC2RouteTable,
|
|
8
|
-
EC2Subnet,
|
|
9
|
-
EC2SubnetRouteTableAssociation,
|
|
10
|
-
EC2VPC,
|
|
11
|
-
EC2VPCGatewayAttachment,
|
|
12
|
-
} from '@stacksjs/ts-cloud-aws-types'
|
|
13
|
-
import type { EnvironmentType } from '@stacksjs/ts-cloud-types'
|
|
14
|
-
import { Fn } from '../intrinsic-functions'
|
|
15
|
-
import { generateLogicalId, generateResourceName } from '../resource-naming'
|
|
16
|
-
|
|
17
|
-
export interface VpcOptions {
|
|
18
|
-
slug: string
|
|
19
|
-
environment: EnvironmentType
|
|
20
|
-
cidr?: string
|
|
21
|
-
enableDnsHostnames?: boolean
|
|
22
|
-
enableDnsSupport?: boolean
|
|
23
|
-
zones?: number
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export interface SubnetOptions {
|
|
27
|
-
slug: string
|
|
28
|
-
environment: EnvironmentType
|
|
29
|
-
vpcId: string
|
|
30
|
-
type: 'public' | 'private' | 'isolated'
|
|
31
|
-
cidr: string
|
|
32
|
-
availabilityZone: string
|
|
33
|
-
mapPublicIp?: boolean
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export interface NatGatewayOptions {
|
|
37
|
-
slug: string
|
|
38
|
-
environment: EnvironmentType
|
|
39
|
-
subnetId: string
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export interface FlowLogOptions {
|
|
43
|
-
slug: string
|
|
44
|
-
environment: EnvironmentType
|
|
45
|
-
resourceId: string
|
|
46
|
-
resourceType: 'VPC' | 'Subnet'
|
|
47
|
-
trafficType?: 'ACCEPT' | 'REJECT' | 'ALL'
|
|
48
|
-
logGroupName?: string
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Network Module - VPC, Subnets, NAT, Internet Gateway
|
|
53
|
-
* Provides clean API for creating and configuring networking resources
|
|
54
|
-
*/
|
|
55
|
-
export class Network {
|
|
56
|
-
/**
|
|
57
|
-
* Create a VPC with optional multi-AZ configuration
|
|
58
|
-
*/
|
|
59
|
-
static createVpc(options: VpcOptions): {
|
|
60
|
-
vpc: EC2VPC
|
|
61
|
-
logicalId: string
|
|
62
|
-
} {
|
|
63
|
-
const {
|
|
64
|
-
slug,
|
|
65
|
-
environment,
|
|
66
|
-
cidr = '10.0.0.0/16',
|
|
67
|
-
enableDnsHostnames = true,
|
|
68
|
-
enableDnsSupport = true,
|
|
69
|
-
} = options
|
|
70
|
-
|
|
71
|
-
const resourceName = generateResourceName({
|
|
72
|
-
slug,
|
|
73
|
-
environment,
|
|
74
|
-
resourceType: 'vpc',
|
|
75
|
-
})
|
|
76
|
-
|
|
77
|
-
const logicalId = generateLogicalId(resourceName)
|
|
78
|
-
|
|
79
|
-
const vpc: EC2VPC = {
|
|
80
|
-
Type: 'AWS::EC2::VPC',
|
|
81
|
-
Properties: {
|
|
82
|
-
CidrBlock: cidr,
|
|
83
|
-
EnableDnsHostnames: enableDnsHostnames,
|
|
84
|
-
EnableDnsSupport: enableDnsSupport,
|
|
85
|
-
Tags: [
|
|
86
|
-
{ Key: 'Name', Value: resourceName },
|
|
87
|
-
{ Key: 'Environment', Value: environment },
|
|
88
|
-
],
|
|
89
|
-
},
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
return { vpc, logicalId }
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Create a subnet in a VPC
|
|
97
|
-
*/
|
|
98
|
-
static createSubnet(options: SubnetOptions): {
|
|
99
|
-
subnet: EC2Subnet
|
|
100
|
-
logicalId: string
|
|
101
|
-
} {
|
|
102
|
-
const {
|
|
103
|
-
slug,
|
|
104
|
-
environment,
|
|
105
|
-
vpcId,
|
|
106
|
-
type,
|
|
107
|
-
cidr,
|
|
108
|
-
availabilityZone,
|
|
109
|
-
mapPublicIp = type === 'public',
|
|
110
|
-
} = options
|
|
111
|
-
|
|
112
|
-
const resourceName = generateResourceName({
|
|
113
|
-
slug,
|
|
114
|
-
environment,
|
|
115
|
-
resourceType: `subnet-${type}`,
|
|
116
|
-
})
|
|
117
|
-
|
|
118
|
-
const logicalId = generateLogicalId(`${resourceName}-${availabilityZone}`)
|
|
119
|
-
|
|
120
|
-
const subnet: EC2Subnet = {
|
|
121
|
-
Type: 'AWS::EC2::Subnet',
|
|
122
|
-
Properties: {
|
|
123
|
-
VpcId: vpcId,
|
|
124
|
-
CidrBlock: cidr,
|
|
125
|
-
AvailabilityZone: availabilityZone,
|
|
126
|
-
MapPublicIpOnLaunch: mapPublicIp,
|
|
127
|
-
Tags: [
|
|
128
|
-
{ Key: 'Name', Value: `${resourceName}-${availabilityZone}` },
|
|
129
|
-
{ Key: 'Environment', Value: environment },
|
|
130
|
-
{ Key: 'Type', Value: type },
|
|
131
|
-
],
|
|
132
|
-
},
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
return { subnet, logicalId }
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Create Internet Gateway
|
|
140
|
-
*/
|
|
141
|
-
static createInternetGateway(
|
|
142
|
-
slug: string,
|
|
143
|
-
environment: EnvironmentType,
|
|
144
|
-
): {
|
|
145
|
-
internetGateway: EC2InternetGateway
|
|
146
|
-
logicalId: string
|
|
147
|
-
} {
|
|
148
|
-
const resourceName = generateResourceName({
|
|
149
|
-
slug,
|
|
150
|
-
environment,
|
|
151
|
-
resourceType: 'igw',
|
|
152
|
-
})
|
|
153
|
-
|
|
154
|
-
const logicalId = generateLogicalId(resourceName)
|
|
155
|
-
|
|
156
|
-
const internetGateway: EC2InternetGateway = {
|
|
157
|
-
Type: 'AWS::EC2::InternetGateway',
|
|
158
|
-
Properties: {
|
|
159
|
-
Tags: [
|
|
160
|
-
{ Key: 'Name', Value: resourceName },
|
|
161
|
-
{ Key: 'Environment', Value: environment },
|
|
162
|
-
],
|
|
163
|
-
},
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
return { internetGateway, logicalId }
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
/**
|
|
170
|
-
* Attach Internet Gateway to VPC
|
|
171
|
-
*/
|
|
172
|
-
static attachInternetGateway(
|
|
173
|
-
vpcLogicalId: string,
|
|
174
|
-
igwLogicalId: string,
|
|
175
|
-
): {
|
|
176
|
-
attachment: EC2VPCGatewayAttachment
|
|
177
|
-
logicalId: string
|
|
178
|
-
} {
|
|
179
|
-
const logicalId = generateLogicalId(`${vpcLogicalId}-igw-attachment`)
|
|
180
|
-
|
|
181
|
-
const attachment: EC2VPCGatewayAttachment = {
|
|
182
|
-
Type: 'AWS::EC2::VPCGatewayAttachment',
|
|
183
|
-
Properties: {
|
|
184
|
-
VpcId: Fn.Ref(vpcLogicalId),
|
|
185
|
-
InternetGatewayId: Fn.Ref(igwLogicalId),
|
|
186
|
-
},
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
return { attachment, logicalId }
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* Create Elastic IP for NAT Gateway
|
|
194
|
-
*/
|
|
195
|
-
static createEip(
|
|
196
|
-
slug: string,
|
|
197
|
-
environment: EnvironmentType,
|
|
198
|
-
): {
|
|
199
|
-
eip: EC2EIP
|
|
200
|
-
logicalId: string
|
|
201
|
-
} {
|
|
202
|
-
const resourceName = generateResourceName({
|
|
203
|
-
slug,
|
|
204
|
-
environment,
|
|
205
|
-
resourceType: 'eip',
|
|
206
|
-
})
|
|
207
|
-
|
|
208
|
-
const logicalId = generateLogicalId(resourceName)
|
|
209
|
-
|
|
210
|
-
const eip: EC2EIP = {
|
|
211
|
-
Type: 'AWS::EC2::EIP',
|
|
212
|
-
Properties: {
|
|
213
|
-
Domain: 'vpc',
|
|
214
|
-
Tags: [
|
|
215
|
-
{ Key: 'Name', Value: resourceName },
|
|
216
|
-
{ Key: 'Environment', Value: environment },
|
|
217
|
-
],
|
|
218
|
-
},
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
return { eip, logicalId }
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
/**
|
|
225
|
-
* Create NAT Gateway (with cost warning in comments)
|
|
226
|
-
*/
|
|
227
|
-
static createNatGateway(
|
|
228
|
-
options: NatGatewayOptions,
|
|
229
|
-
eipLogicalId: string,
|
|
230
|
-
): {
|
|
231
|
-
natGateway: EC2NatGateway
|
|
232
|
-
logicalId: string
|
|
233
|
-
} {
|
|
234
|
-
const { slug, environment, subnetId } = options
|
|
235
|
-
|
|
236
|
-
const resourceName = generateResourceName({
|
|
237
|
-
slug,
|
|
238
|
-
environment,
|
|
239
|
-
resourceType: 'nat',
|
|
240
|
-
})
|
|
241
|
-
|
|
242
|
-
const logicalId = generateLogicalId(resourceName)
|
|
243
|
-
|
|
244
|
-
const natGateway: EC2NatGateway = {
|
|
245
|
-
Type: 'AWS::EC2::NatGateway',
|
|
246
|
-
Properties: {
|
|
247
|
-
AllocationId: Fn.GetAtt(eipLogicalId, 'AllocationId') as any,
|
|
248
|
-
SubnetId: subnetId,
|
|
249
|
-
Tags: [
|
|
250
|
-
{ Key: 'Name', Value: resourceName },
|
|
251
|
-
{ Key: 'Environment', Value: environment },
|
|
252
|
-
{ Key: 'Warning', Value: 'NAT Gateway incurs hourly charges' },
|
|
253
|
-
],
|
|
254
|
-
},
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
return { natGateway, logicalId }
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
/**
|
|
261
|
-
* Create Route Table
|
|
262
|
-
*/
|
|
263
|
-
static createRouteTable(
|
|
264
|
-
slug: string,
|
|
265
|
-
environment: EnvironmentType,
|
|
266
|
-
vpcLogicalId: string,
|
|
267
|
-
type: 'public' | 'private',
|
|
268
|
-
): {
|
|
269
|
-
routeTable: EC2RouteTable
|
|
270
|
-
logicalId: string
|
|
271
|
-
} {
|
|
272
|
-
const resourceName = generateResourceName({
|
|
273
|
-
slug,
|
|
274
|
-
environment,
|
|
275
|
-
resourceType: `rt-${type}`,
|
|
276
|
-
})
|
|
277
|
-
|
|
278
|
-
const logicalId = generateLogicalId(resourceName)
|
|
279
|
-
|
|
280
|
-
const routeTable: EC2RouteTable = {
|
|
281
|
-
Type: 'AWS::EC2::RouteTable',
|
|
282
|
-
Properties: {
|
|
283
|
-
VpcId: Fn.Ref(vpcLogicalId),
|
|
284
|
-
Tags: [
|
|
285
|
-
{ Key: 'Name', Value: resourceName },
|
|
286
|
-
{ Key: 'Environment', Value: environment },
|
|
287
|
-
{ Key: 'Type', Value: type },
|
|
288
|
-
],
|
|
289
|
-
},
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
return { routeTable, logicalId }
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
/**
|
|
296
|
-
* Create Route (e.g., for Internet Gateway or NAT Gateway)
|
|
297
|
-
*/
|
|
298
|
-
static createRoute(
|
|
299
|
-
routeTableLogicalId: string,
|
|
300
|
-
destination: string,
|
|
301
|
-
target: {
|
|
302
|
-
type: 'igw' | 'nat' | 'instance'
|
|
303
|
-
logicalId: string
|
|
304
|
-
},
|
|
305
|
-
): {
|
|
306
|
-
route: EC2Route
|
|
307
|
-
logicalId: string
|
|
308
|
-
} {
|
|
309
|
-
const logicalId = generateLogicalId(`${routeTableLogicalId}-route-${target.type}`)
|
|
310
|
-
|
|
311
|
-
const route: EC2Route = {
|
|
312
|
-
Type: 'AWS::EC2::Route',
|
|
313
|
-
Properties: {
|
|
314
|
-
RouteTableId: Fn.Ref(routeTableLogicalId),
|
|
315
|
-
DestinationCidrBlock: destination,
|
|
316
|
-
},
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
// Set the appropriate gateway based on type
|
|
320
|
-
if (target.type === 'igw') {
|
|
321
|
-
route.Properties.GatewayId = Fn.Ref(target.logicalId)
|
|
322
|
-
}
|
|
323
|
-
else if (target.type === 'nat') {
|
|
324
|
-
route.Properties.NatGatewayId = Fn.Ref(target.logicalId)
|
|
325
|
-
}
|
|
326
|
-
else if (target.type === 'instance') {
|
|
327
|
-
route.Properties.InstanceId = Fn.Ref(target.logicalId)
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
return { route, logicalId }
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
/**
|
|
334
|
-
* Associate Subnet with Route Table
|
|
335
|
-
*/
|
|
336
|
-
static associateSubnetWithRouteTable(
|
|
337
|
-
subnetLogicalId: string,
|
|
338
|
-
routeTableLogicalId: string,
|
|
339
|
-
): {
|
|
340
|
-
association: EC2SubnetRouteTableAssociation
|
|
341
|
-
logicalId: string
|
|
342
|
-
} {
|
|
343
|
-
const logicalId = generateLogicalId(`${subnetLogicalId}-rt-assoc`)
|
|
344
|
-
|
|
345
|
-
const association: EC2SubnetRouteTableAssociation = {
|
|
346
|
-
Type: 'AWS::EC2::SubnetRouteTableAssociation',
|
|
347
|
-
Properties: {
|
|
348
|
-
SubnetId: Fn.Ref(subnetLogicalId),
|
|
349
|
-
RouteTableId: Fn.Ref(routeTableLogicalId),
|
|
350
|
-
},
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
return { association, logicalId }
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
/**
|
|
357
|
-
* Enable VPC Flow Logs
|
|
358
|
-
*/
|
|
359
|
-
static enableFlowLogs(options: FlowLogOptions): {
|
|
360
|
-
flowLog: EC2FlowLog
|
|
361
|
-
logicalId: string
|
|
362
|
-
} {
|
|
363
|
-
const {
|
|
364
|
-
slug,
|
|
365
|
-
environment,
|
|
366
|
-
resourceId,
|
|
367
|
-
resourceType,
|
|
368
|
-
trafficType = 'ALL',
|
|
369
|
-
logGroupName,
|
|
370
|
-
} = options
|
|
371
|
-
|
|
372
|
-
const resourceName = generateResourceName({
|
|
373
|
-
slug,
|
|
374
|
-
environment,
|
|
375
|
-
resourceType: 'flowlog',
|
|
376
|
-
})
|
|
377
|
-
|
|
378
|
-
const logicalId = generateLogicalId(resourceName)
|
|
379
|
-
|
|
380
|
-
const flowLog: EC2FlowLog = {
|
|
381
|
-
Type: 'AWS::EC2::FlowLog',
|
|
382
|
-
Properties: {
|
|
383
|
-
ResourceType: resourceType,
|
|
384
|
-
ResourceIds: [resourceId],
|
|
385
|
-
TrafficType: trafficType,
|
|
386
|
-
LogDestinationType: 'cloud-watch-logs',
|
|
387
|
-
LogGroupName: logGroupName || `/aws/vpc/${slug}-${environment}`,
|
|
388
|
-
Tags: [
|
|
389
|
-
{ Key: 'Name', Value: resourceName },
|
|
390
|
-
{ Key: 'Environment', Value: environment },
|
|
391
|
-
],
|
|
392
|
-
},
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
return { flowLog, logicalId }
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
/**
|
|
399
|
-
* Calculate subnet CIDRs for a VPC
|
|
400
|
-
* Splits a VPC CIDR into smaller subnets
|
|
401
|
-
*/
|
|
402
|
-
static calculateSubnetCidrs(
|
|
403
|
-
vpcCidr: string,
|
|
404
|
-
zones: number,
|
|
405
|
-
subnetsPerZone = 3, // public, private, isolated
|
|
406
|
-
): string[] {
|
|
407
|
-
const [baseIp, vpcMask] = vpcCidr.split('/')
|
|
408
|
-
const vpcMaskNum = Number.parseInt(vpcMask, 10)
|
|
409
|
-
|
|
410
|
-
// Calculate new subnet mask (add bits for zones and subnet types)
|
|
411
|
-
const bitsNeeded = Math.ceil(Math.log2(zones * subnetsPerZone))
|
|
412
|
-
const subnetMask = vpcMaskNum + bitsNeeded
|
|
413
|
-
|
|
414
|
-
if (subnetMask > 28) {
|
|
415
|
-
throw new Error('VPC CIDR is too small to accommodate requested subnets')
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
const [a, b, c, d] = baseIp.split('.').map(Number)
|
|
419
|
-
const baseIpNum = (a << 24) + (b << 16) + (c << 8) + d
|
|
420
|
-
|
|
421
|
-
const subnetSize = 2 ** (32 - subnetMask)
|
|
422
|
-
const cidrs: string[] = []
|
|
423
|
-
|
|
424
|
-
for (let i = 0; i < zones * subnetsPerZone; i++) {
|
|
425
|
-
const subnetIpNum = baseIpNum + i * subnetSize
|
|
426
|
-
const subnetIp = [
|
|
427
|
-
(subnetIpNum >>> 24) & 0xFF,
|
|
428
|
-
(subnetIpNum >>> 16) & 0xFF,
|
|
429
|
-
(subnetIpNum >>> 8) & 0xFF,
|
|
430
|
-
subnetIpNum & 0xFF,
|
|
431
|
-
].join('.')
|
|
432
|
-
cidrs.push(`${subnetIp}/${subnetMask}`)
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
return cidrs
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
/**
|
|
439
|
-
* Get available availability zones for a region
|
|
440
|
-
* Returns zone suffixes (a, b, c, etc.)
|
|
441
|
-
*/
|
|
442
|
-
static getAvailabilityZones(region: string, count: number): string[] {
|
|
443
|
-
const zoneSuffixes = ['a', 'b', 'c', 'd', 'e', 'f']
|
|
444
|
-
return zoneSuffixes.slice(0, count).map(suffix => `${region}${suffix}`)
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
/**
|
|
448
|
-
* Create a complete multi-AZ network setup with optional NAT Gateway
|
|
449
|
-
* This creates VPC, public/private subnets, IGW, and optionally NAT
|
|
450
|
-
*/
|
|
451
|
-
static createMultiAzNetwork(options: {
|
|
452
|
-
slug: string
|
|
453
|
-
environment: EnvironmentType
|
|
454
|
-
region: string
|
|
455
|
-
cidr?: string
|
|
456
|
-
zones?: number
|
|
457
|
-
enableNatGateway?: boolean
|
|
458
|
-
singleNatGateway?: boolean // Use single NAT for cost savings (not HA)
|
|
459
|
-
enableFlowLogs?: boolean
|
|
460
|
-
}): {
|
|
461
|
-
resources: Record<string, any>
|
|
462
|
-
outputs: {
|
|
463
|
-
vpcId: string
|
|
464
|
-
publicSubnetIds: string[]
|
|
465
|
-
privateSubnetIds: string[]
|
|
466
|
-
natGatewayIds?: string[]
|
|
467
|
-
}
|
|
468
|
-
} {
|
|
469
|
-
const {
|
|
470
|
-
slug,
|
|
471
|
-
environment,
|
|
472
|
-
region,
|
|
473
|
-
cidr = '10.0.0.0/16',
|
|
474
|
-
zones = 3,
|
|
475
|
-
enableNatGateway = false,
|
|
476
|
-
singleNatGateway = false,
|
|
477
|
-
enableFlowLogs = false,
|
|
478
|
-
} = options
|
|
479
|
-
|
|
480
|
-
const resources: Record<string, any> = {}
|
|
481
|
-
const publicSubnetIds: string[] = []
|
|
482
|
-
const privateSubnetIds: string[] = []
|
|
483
|
-
const natGatewayIds: string[] = []
|
|
484
|
-
|
|
485
|
-
// Create VPC
|
|
486
|
-
const { vpc, logicalId: vpcLogicalId } = Network.createVpc({
|
|
487
|
-
slug,
|
|
488
|
-
environment,
|
|
489
|
-
cidr,
|
|
490
|
-
})
|
|
491
|
-
resources[vpcLogicalId] = vpc
|
|
492
|
-
|
|
493
|
-
// Create Internet Gateway
|
|
494
|
-
const { internetGateway, logicalId: igwLogicalId } = Network.createInternetGateway(slug, environment)
|
|
495
|
-
resources[igwLogicalId] = internetGateway
|
|
496
|
-
|
|
497
|
-
// Attach IGW to VPC
|
|
498
|
-
const { attachment, logicalId: attachmentLogicalId } = Network.attachInternetGateway(vpcLogicalId, igwLogicalId)
|
|
499
|
-
resources[attachmentLogicalId] = attachment
|
|
500
|
-
|
|
501
|
-
// Create public route table
|
|
502
|
-
const { routeTable: publicRouteTable, logicalId: publicRtLogicalId } = Network.createRouteTable(
|
|
503
|
-
slug,
|
|
504
|
-
environment,
|
|
505
|
-
vpcLogicalId,
|
|
506
|
-
'public',
|
|
507
|
-
)
|
|
508
|
-
resources[publicRtLogicalId] = publicRouteTable
|
|
509
|
-
|
|
510
|
-
// Create route to IGW in public route table
|
|
511
|
-
const { route: publicRoute, logicalId: publicRouteLogicalId } = Network.createRoute(
|
|
512
|
-
publicRtLogicalId,
|
|
513
|
-
'0.0.0.0/0',
|
|
514
|
-
{ type: 'igw', logicalId: igwLogicalId },
|
|
515
|
-
)
|
|
516
|
-
publicRoute.DependsOn = attachmentLogicalId
|
|
517
|
-
resources[publicRouteLogicalId] = publicRoute
|
|
518
|
-
|
|
519
|
-
// Calculate subnet CIDRs
|
|
520
|
-
const subnetCidrs = Network.calculateSubnetCidrs(cidr, zones, 2) // public + private
|
|
521
|
-
const availabilityZones = Network.getAvailabilityZones(region, zones)
|
|
522
|
-
|
|
523
|
-
// Create private route table(s)
|
|
524
|
-
const privateRouteTables: string[] = []
|
|
525
|
-
|
|
526
|
-
// Create subnets for each AZ
|
|
527
|
-
for (let i = 0; i < zones; i++) {
|
|
528
|
-
const az = availabilityZones[i]
|
|
529
|
-
const publicCidr = subnetCidrs[i * 2]
|
|
530
|
-
const privateCidr = subnetCidrs[i * 2 + 1]
|
|
531
|
-
|
|
532
|
-
// Public subnet
|
|
533
|
-
const { subnet: publicSubnet, logicalId: publicSubnetLogicalId } = Network.createSubnet({
|
|
534
|
-
slug,
|
|
535
|
-
environment,
|
|
536
|
-
vpcId: Fn.Ref(vpcLogicalId) as any,
|
|
537
|
-
type: 'public',
|
|
538
|
-
cidr: publicCidr,
|
|
539
|
-
availabilityZone: az,
|
|
540
|
-
})
|
|
541
|
-
resources[publicSubnetLogicalId] = publicSubnet
|
|
542
|
-
publicSubnetIds.push(publicSubnetLogicalId)
|
|
543
|
-
|
|
544
|
-
// Associate public subnet with public route table
|
|
545
|
-
const { association: publicAssoc, logicalId: publicAssocLogicalId } = Network.associateSubnetWithRouteTable(
|
|
546
|
-
publicSubnetLogicalId,
|
|
547
|
-
publicRtLogicalId,
|
|
548
|
-
)
|
|
549
|
-
resources[publicAssocLogicalId] = publicAssoc
|
|
550
|
-
|
|
551
|
-
// Private subnet
|
|
552
|
-
const { subnet: privateSubnet, logicalId: privateSubnetLogicalId } = Network.createSubnet({
|
|
553
|
-
slug,
|
|
554
|
-
environment,
|
|
555
|
-
vpcId: Fn.Ref(vpcLogicalId) as any,
|
|
556
|
-
type: 'private',
|
|
557
|
-
cidr: privateCidr,
|
|
558
|
-
availabilityZone: az,
|
|
559
|
-
})
|
|
560
|
-
resources[privateSubnetLogicalId] = privateSubnet
|
|
561
|
-
privateSubnetIds.push(privateSubnetLogicalId)
|
|
562
|
-
|
|
563
|
-
// Create NAT Gateway if enabled
|
|
564
|
-
if (enableNatGateway && (!singleNatGateway || i === 0)) {
|
|
565
|
-
// Create EIP for NAT
|
|
566
|
-
const { eip, logicalId: eipLogicalId } = Network.createEip(`${slug}-${az}`, environment)
|
|
567
|
-
resources[eipLogicalId] = eip
|
|
568
|
-
|
|
569
|
-
// Create NAT Gateway in public subnet
|
|
570
|
-
const { natGateway, logicalId: natLogicalId } = Network.createNatGateway(
|
|
571
|
-
{ slug: `${slug}-${az}`, environment, subnetId: Fn.Ref(publicSubnetLogicalId) as any },
|
|
572
|
-
eipLogicalId,
|
|
573
|
-
)
|
|
574
|
-
natGateway.DependsOn = attachmentLogicalId
|
|
575
|
-
resources[natLogicalId] = natGateway
|
|
576
|
-
natGatewayIds.push(natLogicalId)
|
|
577
|
-
|
|
578
|
-
// Create private route table for this AZ
|
|
579
|
-
const { routeTable: privateRt, logicalId: privateRtLogicalId } = Network.createRouteTable(
|
|
580
|
-
`${slug}-${az}`,
|
|
581
|
-
environment,
|
|
582
|
-
vpcLogicalId,
|
|
583
|
-
'private',
|
|
584
|
-
)
|
|
585
|
-
resources[privateRtLogicalId] = privateRt
|
|
586
|
-
privateRouteTables.push(privateRtLogicalId)
|
|
587
|
-
|
|
588
|
-
// Create route to NAT in private route table
|
|
589
|
-
const { route: natRoute, logicalId: natRouteLogicalId } = Network.createRoute(
|
|
590
|
-
privateRtLogicalId,
|
|
591
|
-
'0.0.0.0/0',
|
|
592
|
-
{ type: 'nat', logicalId: natLogicalId },
|
|
593
|
-
)
|
|
594
|
-
resources[natRouteLogicalId] = natRoute
|
|
595
|
-
|
|
596
|
-
// Associate private subnet with its route table
|
|
597
|
-
const { association: privateAssoc, logicalId: privateAssocLogicalId } = Network.associateSubnetWithRouteTable(
|
|
598
|
-
privateSubnetLogicalId,
|
|
599
|
-
privateRtLogicalId,
|
|
600
|
-
)
|
|
601
|
-
resources[privateAssocLogicalId] = privateAssoc
|
|
602
|
-
}
|
|
603
|
-
else if (enableNatGateway && singleNatGateway && i > 0) {
|
|
604
|
-
// Reuse single NAT gateway for all private subnets
|
|
605
|
-
const { association: privateAssoc, logicalId: privateAssocLogicalId } = Network.associateSubnetWithRouteTable(
|
|
606
|
-
privateSubnetLogicalId,
|
|
607
|
-
privateRouteTables[0],
|
|
608
|
-
)
|
|
609
|
-
resources[privateAssocLogicalId] = privateAssoc
|
|
610
|
-
}
|
|
611
|
-
else {
|
|
612
|
-
// No NAT - private subnets are isolated
|
|
613
|
-
const { routeTable: isolatedRt, logicalId: isolatedRtLogicalId } = Network.createRouteTable(
|
|
614
|
-
`${slug}-${az}-isolated`,
|
|
615
|
-
environment,
|
|
616
|
-
vpcLogicalId,
|
|
617
|
-
'private',
|
|
618
|
-
)
|
|
619
|
-
resources[isolatedRtLogicalId] = isolatedRt
|
|
620
|
-
|
|
621
|
-
const { association: isolatedAssoc, logicalId: isolatedAssocLogicalId } = Network.associateSubnetWithRouteTable(
|
|
622
|
-
privateSubnetLogicalId,
|
|
623
|
-
isolatedRtLogicalId,
|
|
624
|
-
)
|
|
625
|
-
resources[isolatedAssocLogicalId] = isolatedAssoc
|
|
626
|
-
}
|
|
627
|
-
}
|
|
628
|
-
|
|
629
|
-
// Enable flow logs if requested
|
|
630
|
-
if (enableFlowLogs) {
|
|
631
|
-
const { flowLog, logicalId: flowLogId } = Network.enableFlowLogs({
|
|
632
|
-
slug,
|
|
633
|
-
environment,
|
|
634
|
-
resourceId: Fn.Ref(vpcLogicalId) as any,
|
|
635
|
-
resourceType: 'VPC',
|
|
636
|
-
})
|
|
637
|
-
resources[flowLogId] = flowLog
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
return {
|
|
641
|
-
resources,
|
|
642
|
-
outputs: {
|
|
643
|
-
vpcId: vpcLogicalId,
|
|
644
|
-
publicSubnetIds,
|
|
645
|
-
privateSubnetIds,
|
|
646
|
-
natGatewayIds: natGatewayIds.length > 0 ? natGatewayIds : undefined,
|
|
647
|
-
},
|
|
648
|
-
}
|
|
649
|
-
}
|
|
650
|
-
|
|
651
|
-
/**
|
|
652
|
-
* NAT Gateway cost warning
|
|
653
|
-
* NAT Gateways cost ~$32/month plus data transfer charges
|
|
654
|
-
*/
|
|
655
|
-
static readonly NatGatewayCostWarning = `
|
|
656
|
-
⚠️ NAT Gateway Cost Warning:
|
|
657
|
-
- Each NAT Gateway costs approximately $32-45/month (hourly charges)
|
|
658
|
-
- Data processing charges: $0.045/GB processed
|
|
659
|
-
- For development environments, consider:
|
|
660
|
-
- Using a single NAT Gateway (singleNatGateway: true)
|
|
661
|
-
- Using NAT Instances instead (cheaper but requires management)
|
|
662
|
-
- Disabling NAT entirely for isolated private subnets
|
|
663
|
-
`
|
|
664
|
-
}
|