@friggframework/devtools 2.0.0-next.24 → 2.0.0-next.25

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.
@@ -102,6 +102,309 @@ const modifyHandlerPaths = (functions) => {
102
102
  return modifiedFunctions;
103
103
  };
104
104
 
105
+ // Helper function to create VPC infrastructure resources
106
+ const createVPCInfrastructure = (AppDefinition) => {
107
+ const vpcResources = {
108
+ // VPC
109
+ FriggVPC: {
110
+ Type: 'AWS::EC2::VPC',
111
+ Properties: {
112
+ CidrBlock: AppDefinition.vpc.cidrBlock || '10.0.0.0/16',
113
+ EnableDnsHostnames: true,
114
+ EnableDnsSupport: true,
115
+ Tags: [
116
+ { Key: 'Name', Value: '${self:service}-${self:provider.stage}-vpc' }
117
+ ]
118
+ }
119
+ },
120
+
121
+ // Internet Gateway
122
+ FriggInternetGateway: {
123
+ Type: 'AWS::EC2::InternetGateway',
124
+ Properties: {
125
+ Tags: [
126
+ { Key: 'Name', Value: '${self:service}-${self:provider.stage}-igw' }
127
+ ]
128
+ }
129
+ },
130
+
131
+ // Attach Internet Gateway to VPC
132
+ FriggVPCGatewayAttachment: {
133
+ Type: 'AWS::EC2::VPCGatewayAttachment',
134
+ Properties: {
135
+ VpcId: { Ref: 'FriggVPC' },
136
+ InternetGatewayId: { Ref: 'FriggInternetGateway' }
137
+ }
138
+ },
139
+
140
+ // Public Subnet for NAT Gateway
141
+ FriggPublicSubnet: {
142
+ Type: 'AWS::EC2::Subnet',
143
+ Properties: {
144
+ VpcId: { Ref: 'FriggVPC' },
145
+ CidrBlock: '10.0.1.0/24',
146
+ AvailabilityZone: { 'Fn::Select': [0, { 'Fn::GetAZs': '' }] },
147
+ MapPublicIpOnLaunch: true,
148
+ Tags: [
149
+ { Key: 'Name', Value: '${self:service}-${self:provider.stage}-public-subnet' }
150
+ ]
151
+ }
152
+ },
153
+
154
+ // Private Subnet 1 for Lambda
155
+ FriggPrivateSubnet1: {
156
+ Type: 'AWS::EC2::Subnet',
157
+ Properties: {
158
+ VpcId: { Ref: 'FriggVPC' },
159
+ CidrBlock: '10.0.2.0/24',
160
+ AvailabilityZone: { 'Fn::Select': [0, { 'Fn::GetAZs': '' }] },
161
+ Tags: [
162
+ { Key: 'Name', Value: '${self:service}-${self:provider.stage}-private-subnet-1' }
163
+ ]
164
+ }
165
+ },
166
+
167
+ // Private Subnet 2 for Lambda (different AZ for redundancy)
168
+ FriggPrivateSubnet2: {
169
+ Type: 'AWS::EC2::Subnet',
170
+ Properties: {
171
+ VpcId: { Ref: 'FriggVPC' },
172
+ CidrBlock: '10.0.3.0/24',
173
+ AvailabilityZone: { 'Fn::Select': [1, { 'Fn::GetAZs': '' }] },
174
+ Tags: [
175
+ { Key: 'Name', Value: '${self:service}-${self:provider.stage}-private-subnet-2' }
176
+ ]
177
+ }
178
+ },
179
+
180
+ // Elastic IP for NAT Gateway
181
+ FriggNATGatewayEIP: {
182
+ Type: 'AWS::EC2::EIP',
183
+ Properties: {
184
+ Domain: 'vpc',
185
+ Tags: [
186
+ { Key: 'Name', Value: '${self:service}-${self:provider.stage}-nat-eip' }
187
+ ]
188
+ },
189
+ DependsOn: 'FriggVPCGatewayAttachment'
190
+ },
191
+
192
+ // NAT Gateway for private subnet internet access
193
+ FriggNATGateway: {
194
+ Type: 'AWS::EC2::NatGateway',
195
+ Properties: {
196
+ AllocationId: { 'Fn::GetAtt': ['FriggNATGatewayEIP', 'AllocationId'] },
197
+ SubnetId: { Ref: 'FriggPublicSubnet' },
198
+ Tags: [
199
+ { Key: 'Name', Value: '${self:service}-${self:provider.stage}-nat-gateway' }
200
+ ]
201
+ }
202
+ },
203
+
204
+ // Public Route Table
205
+ FriggPublicRouteTable: {
206
+ Type: 'AWS::EC2::RouteTable',
207
+ Properties: {
208
+ VpcId: { Ref: 'FriggVPC' },
209
+ Tags: [
210
+ { Key: 'Name', Value: '${self:service}-${self:provider.stage}-public-rt' }
211
+ ]
212
+ }
213
+ },
214
+
215
+ // Public Route to Internet Gateway
216
+ FriggPublicRoute: {
217
+ Type: 'AWS::EC2::Route',
218
+ Properties: {
219
+ RouteTableId: { Ref: 'FriggPublicRouteTable' },
220
+ DestinationCidrBlock: '0.0.0.0/0',
221
+ GatewayId: { Ref: 'FriggInternetGateway' }
222
+ },
223
+ DependsOn: 'FriggVPCGatewayAttachment'
224
+ },
225
+
226
+ // Associate Public Subnet with Public Route Table
227
+ FriggPublicSubnetRouteTableAssociation: {
228
+ Type: 'AWS::EC2::SubnetRouteTableAssociation',
229
+ Properties: {
230
+ SubnetId: { Ref: 'FriggPublicSubnet' },
231
+ RouteTableId: { Ref: 'FriggPublicRouteTable' }
232
+ }
233
+ },
234
+
235
+ // Private Route Table
236
+ FriggPrivateRouteTable: {
237
+ Type: 'AWS::EC2::RouteTable',
238
+ Properties: {
239
+ VpcId: { Ref: 'FriggVPC' },
240
+ Tags: [
241
+ { Key: 'Name', Value: '${self:service}-${self:provider.stage}-private-rt' }
242
+ ]
243
+ }
244
+ },
245
+
246
+ // Private Route to NAT Gateway
247
+ FriggPrivateRoute: {
248
+ Type: 'AWS::EC2::Route',
249
+ Properties: {
250
+ RouteTableId: { Ref: 'FriggPrivateRouteTable' },
251
+ DestinationCidrBlock: '0.0.0.0/0',
252
+ NatGatewayId: { Ref: 'FriggNATGateway' }
253
+ }
254
+ },
255
+
256
+ // Associate Private Subnet 1 with Private Route Table
257
+ FriggPrivateSubnet1RouteTableAssociation: {
258
+ Type: 'AWS::EC2::SubnetRouteTableAssociation',
259
+ Properties: {
260
+ SubnetId: { Ref: 'FriggPrivateSubnet1' },
261
+ RouteTableId: { Ref: 'FriggPrivateRouteTable' }
262
+ }
263
+ },
264
+
265
+ // Associate Private Subnet 2 with Private Route Table
266
+ FriggPrivateSubnet2RouteTableAssociation: {
267
+ Type: 'AWS::EC2::SubnetRouteTableAssociation',
268
+ Properties: {
269
+ SubnetId: { Ref: 'FriggPrivateSubnet2' },
270
+ RouteTableId: { Ref: 'FriggPrivateRouteTable' }
271
+ }
272
+ },
273
+
274
+ // Security Group for Lambda functions
275
+ FriggLambdaSecurityGroup: {
276
+ Type: 'AWS::EC2::SecurityGroup',
277
+ Properties: {
278
+ GroupDescription: 'Security group for Frigg Lambda functions',
279
+ VpcId: { Ref: 'FriggVPC' },
280
+ SecurityGroupEgress: [
281
+ {
282
+ IpProtocol: 'tcp',
283
+ FromPort: 443,
284
+ ToPort: 443,
285
+ CidrIp: '0.0.0.0/0',
286
+ Description: 'HTTPS outbound'
287
+ },
288
+ {
289
+ IpProtocol: 'tcp',
290
+ FromPort: 80,
291
+ ToPort: 80,
292
+ CidrIp: '0.0.0.0/0',
293
+ Description: 'HTTP outbound'
294
+ },
295
+ {
296
+ IpProtocol: 'tcp',
297
+ FromPort: 53,
298
+ ToPort: 53,
299
+ CidrIp: '0.0.0.0/0',
300
+ Description: 'DNS TCP'
301
+ },
302
+ {
303
+ IpProtocol: 'udp',
304
+ FromPort: 53,
305
+ ToPort: 53,
306
+ CidrIp: '0.0.0.0/0',
307
+ Description: 'DNS UDP'
308
+ }
309
+ ],
310
+ Tags: [
311
+ { Key: 'Name', Value: '${self:service}-${self:provider.stage}-lambda-sg' }
312
+ ]
313
+ }
314
+ }
315
+ };
316
+
317
+ // Add VPC Endpoints for cost optimization
318
+ if (AppDefinition.vpc.enableVPCEndpoints !== false) {
319
+ // S3 Gateway Endpoint (free)
320
+ vpcResources.FriggS3VPCEndpoint = {
321
+ Type: 'AWS::EC2::VPCEndpoint',
322
+ Properties: {
323
+ VpcId: { Ref: 'FriggVPC' },
324
+ ServiceName: 'com.amazonaws.${self:provider.region}.s3',
325
+ VpcEndpointType: 'Gateway',
326
+ RouteTableIds: [
327
+ { Ref: 'FriggPrivateRouteTable' }
328
+ ]
329
+ }
330
+ };
331
+
332
+ // DynamoDB Gateway Endpoint (free)
333
+ vpcResources.FriggDynamoDBVPCEndpoint = {
334
+ Type: 'AWS::EC2::VPCEndpoint',
335
+ Properties: {
336
+ VpcId: { Ref: 'FriggVPC' },
337
+ ServiceName: 'com.amazonaws.${self:provider.region}.dynamodb',
338
+ VpcEndpointType: 'Gateway',
339
+ RouteTableIds: [
340
+ { Ref: 'FriggPrivateRouteTable' }
341
+ ]
342
+ }
343
+ };
344
+
345
+ // KMS Interface Endpoint (paid, but useful if using KMS)
346
+ if (AppDefinition.encryption?.useDefaultKMSForFieldLevelEncryption === true) {
347
+ vpcResources.FriggKMSVPCEndpoint = {
348
+ Type: 'AWS::EC2::VPCEndpoint',
349
+ Properties: {
350
+ VpcId: { Ref: 'FriggVPC' },
351
+ ServiceName: 'com.amazonaws.${self:provider.region}.kms',
352
+ VpcEndpointType: 'Interface',
353
+ SubnetIds: [
354
+ { Ref: 'FriggPrivateSubnet1' },
355
+ { Ref: 'FriggPrivateSubnet2' }
356
+ ],
357
+ SecurityGroupIds: [
358
+ { Ref: 'FriggVPCEndpointSecurityGroup' }
359
+ ],
360
+ PrivateDnsEnabled: true
361
+ }
362
+ };
363
+ }
364
+
365
+ // Secrets Manager Interface Endpoint (paid, but useful for secrets)
366
+ vpcResources.FriggSecretsManagerVPCEndpoint = {
367
+ Type: 'AWS::EC2::VPCEndpoint',
368
+ Properties: {
369
+ VpcId: { Ref: 'FriggVPC' },
370
+ ServiceName: 'com.amazonaws.${self:provider.region}.secretsmanager',
371
+ VpcEndpointType: 'Interface',
372
+ SubnetIds: [
373
+ { Ref: 'FriggPrivateSubnet1' },
374
+ { Ref: 'FriggPrivateSubnet2' }
375
+ ],
376
+ SecurityGroupIds: [
377
+ { Ref: 'FriggVPCEndpointSecurityGroup' }
378
+ ],
379
+ PrivateDnsEnabled: true
380
+ }
381
+ };
382
+
383
+ // Security Group for VPC Endpoints
384
+ vpcResources.FriggVPCEndpointSecurityGroup = {
385
+ Type: 'AWS::EC2::SecurityGroup',
386
+ Properties: {
387
+ GroupDescription: 'Security group for Frigg VPC Endpoints',
388
+ VpcId: { Ref: 'FriggVPC' },
389
+ SecurityGroupIngress: [
390
+ {
391
+ IpProtocol: 'tcp',
392
+ FromPort: 443,
393
+ ToPort: 443,
394
+ SourceSecurityGroupId: { Ref: 'FriggLambdaSecurityGroup' },
395
+ Description: 'HTTPS from Lambda'
396
+ }
397
+ ],
398
+ Tags: [
399
+ { Key: 'Name', Value: '${self:service}-${self:provider.stage}-vpc-endpoint-sg' }
400
+ ]
401
+ }
402
+ };
403
+ }
404
+
405
+ return vpcResources;
406
+ };
407
+
105
408
  const composeServerlessDefinition = (AppDefinition) => {
106
409
  const definition = {
107
410
  frameworkVersion: '>=3.17.0',
@@ -353,6 +656,51 @@ const composeServerlessDefinition = (AppDefinition) => {
353
656
  };
354
657
  }
355
658
 
659
+ // VPC Configuration based on App Definition
660
+ if (AppDefinition.vpc?.enable === true) {
661
+ // Create VPC config from App Definition or use auto-created resources
662
+ const vpcConfig = {};
663
+
664
+ if (AppDefinition.vpc.securityGroupIds) {
665
+ // User provided custom security groups
666
+ vpcConfig.securityGroupIds = AppDefinition.vpc.securityGroupIds;
667
+ } else {
668
+ // Use auto-created security group
669
+ vpcConfig.securityGroupIds = [{ Ref: 'FriggLambdaSecurityGroup' }];
670
+ }
671
+
672
+ if (AppDefinition.vpc.subnetIds) {
673
+ // User provided custom subnets
674
+ vpcConfig.subnetIds = AppDefinition.vpc.subnetIds;
675
+ } else {
676
+ // Use auto-created private subnets
677
+ vpcConfig.subnetIds = [
678
+ { Ref: 'FriggPrivateSubnet1' },
679
+ { Ref: 'FriggPrivateSubnet2' }
680
+ ];
681
+ }
682
+
683
+ // Set VPC config for Lambda functions
684
+ definition.provider.vpc = vpcConfig;
685
+
686
+ // Add VPC-related IAM permissions
687
+ definition.provider.iamRoleStatements.push({
688
+ Effect: 'Allow',
689
+ Action: [
690
+ 'ec2:CreateNetworkInterface',
691
+ 'ec2:DescribeNetworkInterfaces',
692
+ 'ec2:DeleteNetworkInterface',
693
+ 'ec2:AttachNetworkInterface',
694
+ 'ec2:DetachNetworkInterface'
695
+ ],
696
+ Resource: '*'
697
+ });
698
+
699
+ // Add VPC infrastructure resources to CloudFormation
700
+ const vpcResources = createVPCInfrastructure(AppDefinition);
701
+ Object.assign(definition.resources.Resources, vpcResources);
702
+ }
703
+
356
704
  // Add integration-specific functions and resources
357
705
  for (const integration of AppDefinition.integrations) {
358
706
  const integrationName = integration.Definition.name;
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@friggframework/devtools",
3
3
  "prettier": "@friggframework/prettier-config",
4
- "version": "2.0.0-next.24",
4
+ "version": "2.0.0-next.25",
5
5
  "dependencies": {
6
6
  "@babel/eslint-parser": "^7.18.9",
7
7
  "@babel/parser": "^7.25.3",
8
8
  "@babel/traverse": "^7.25.3",
9
- "@friggframework/test": "2.0.0-next.24",
9
+ "@friggframework/test": "2.0.0-next.25",
10
10
  "@hapi/boom": "^10.0.1",
11
11
  "@inquirer/prompts": "^5.3.8",
12
12
  "axios": "^1.7.2",
@@ -27,8 +27,8 @@
27
27
  "serverless-http": "^2.7.0"
28
28
  },
29
29
  "devDependencies": {
30
- "@friggframework/eslint-config": "2.0.0-next.24",
31
- "@friggframework/prettier-config": "2.0.0-next.24",
30
+ "@friggframework/eslint-config": "2.0.0-next.25",
31
+ "@friggframework/prettier-config": "2.0.0-next.25",
32
32
  "prettier": "^2.7.1",
33
33
  "serverless": "3.39.0",
34
34
  "serverless-dotenv-plugin": "^6.0.0",
@@ -60,5 +60,5 @@
60
60
  "publishConfig": {
61
61
  "access": "public"
62
62
  },
63
- "gitHead": "b1a00897238f7734a67342a3f72f1e9b6504800f"
63
+ "gitHead": "d758d225a2cfbe4038ecc2b777cd6826949312fb"
64
64
  }