@friggframework/devtools 2.0.0--canary.490.b68a7c8.0 → 2.0.0--canary.490.12406f7.0
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.
|
@@ -552,7 +552,7 @@ class VpcBuilder extends InfrastructureBuilder {
|
|
|
552
552
|
this.buildNatGatewayFromDecision(decisions.natGateway, appDefinition, discoveredResources, result);
|
|
553
553
|
|
|
554
554
|
// Build VPC Endpoints based on ownership decisions
|
|
555
|
-
this.buildVpcEndpointsFromDecisions(decisions.vpcEndpoints, appDefinition, result);
|
|
555
|
+
this.buildVpcEndpointsFromDecisions(decisions.vpcEndpoints, decisions.securityGroup, appDefinition, result);
|
|
556
556
|
|
|
557
557
|
// Set VPC_ENABLED environment variable
|
|
558
558
|
result.environment.VPC_ENABLED = 'true';
|
|
@@ -920,7 +920,8 @@ class VpcBuilder extends InfrastructureBuilder {
|
|
|
920
920
|
/**
|
|
921
921
|
* Build VPC Endpoints based on ownership decisions
|
|
922
922
|
*/
|
|
923
|
-
buildVpcEndpointsFromDecisions(
|
|
923
|
+
buildVpcEndpointsFromDecisions(endpointDecisions, securityGroupDecision, appDefinition, result) {
|
|
924
|
+
const decisions = endpointDecisions; // For backwards compatibility with existing code
|
|
924
925
|
const endpointsToCreate = [];
|
|
925
926
|
const endpointsInStack = [];
|
|
926
927
|
const externalEndpoints = [];
|
|
@@ -939,7 +940,7 @@ class VpcBuilder extends InfrastructureBuilder {
|
|
|
939
940
|
if (endpointsInStack.length > 0) {
|
|
940
941
|
console.log(` ✓ VPC Endpoints in stack: ${endpointsInStack.join(', ')}`);
|
|
941
942
|
// CRITICAL: Must add stack-managed endpoints back to template or CloudFormation will DELETE them!
|
|
942
|
-
this._addStackManagedEndpointsToTemplate(decisions, result);
|
|
943
|
+
this._addStackManagedEndpointsToTemplate(decisions, securityGroupDecision, result);
|
|
943
944
|
}
|
|
944
945
|
|
|
945
946
|
if (externalEndpoints.length > 0) {
|
|
@@ -1002,6 +1003,15 @@ class VpcBuilder extends InfrastructureBuilder {
|
|
|
1002
1003
|
// Create security group for interface endpoints if needed
|
|
1003
1004
|
const needsInterfaceEndpoints = endpointsToCreate.some(type => ['kms', 'secretsManager', 'sqs'].includes(type));
|
|
1004
1005
|
if (needsInterfaceEndpoints) {
|
|
1006
|
+
// Determine source security group for ingress rule
|
|
1007
|
+
let sourceSgId;
|
|
1008
|
+
if (securityGroupDecision.ownership === ResourceOwnership.STACK) {
|
|
1009
|
+
sourceSgId = { Ref: 'FriggLambdaSecurityGroup' };
|
|
1010
|
+
} else {
|
|
1011
|
+
// External - use the physical ID
|
|
1012
|
+
sourceSgId = securityGroupDecision.physicalIds[0];
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1005
1015
|
result.resources.FriggVPCEndpointSecurityGroup = {
|
|
1006
1016
|
Type: 'AWS::EC2::SecurityGroup',
|
|
1007
1017
|
Properties: {
|
|
@@ -1012,7 +1022,7 @@ class VpcBuilder extends InfrastructureBuilder {
|
|
|
1012
1022
|
IpProtocol: 'tcp',
|
|
1013
1023
|
FromPort: 443,
|
|
1014
1024
|
ToPort: 443,
|
|
1015
|
-
SourceSecurityGroupId:
|
|
1025
|
+
SourceSecurityGroupId: sourceSgId,
|
|
1016
1026
|
Description: 'HTTPS from Lambda',
|
|
1017
1027
|
},
|
|
1018
1028
|
],
|
|
@@ -1129,7 +1139,8 @@ class VpcBuilder extends InfrastructureBuilder {
|
|
|
1129
1139
|
*
|
|
1130
1140
|
* @private
|
|
1131
1141
|
*/
|
|
1132
|
-
_addStackManagedEndpointsToTemplate(
|
|
1142
|
+
_addStackManagedEndpointsToTemplate(endpointDecisions, securityGroupDecision, result) {
|
|
1143
|
+
const decisions = endpointDecisions; // For backwards compatibility
|
|
1133
1144
|
const vpcId = result.vpcId;
|
|
1134
1145
|
const logicalIdMap = {
|
|
1135
1146
|
s3: 'FriggS3VPCEndpoint',
|
|
@@ -1193,6 +1204,17 @@ class VpcBuilder extends InfrastructureBuilder {
|
|
|
1193
1204
|
);
|
|
1194
1205
|
|
|
1195
1206
|
if (hasInterfaceEndpoints && !result.resources.FriggVPCEndpointSecurityGroup) {
|
|
1207
|
+
// Determine source security group for ingress rule
|
|
1208
|
+
// If Lambda SG is stack-managed, use CloudFormation Ref
|
|
1209
|
+
// If Lambda SG is external, use the physical ID directly
|
|
1210
|
+
let sourceSgId;
|
|
1211
|
+
if (securityGroupDecision.ownership === ResourceOwnership.STACK) {
|
|
1212
|
+
sourceSgId = { Ref: 'FriggLambdaSecurityGroup' };
|
|
1213
|
+
} else {
|
|
1214
|
+
// External - use the physical ID
|
|
1215
|
+
sourceSgId = securityGroupDecision.physicalIds[0];
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1196
1218
|
result.resources.FriggVPCEndpointSecurityGroup = {
|
|
1197
1219
|
Type: 'AWS::EC2::SecurityGroup',
|
|
1198
1220
|
Properties: {
|
|
@@ -1203,7 +1225,7 @@ class VpcBuilder extends InfrastructureBuilder {
|
|
|
1203
1225
|
IpProtocol: 'tcp',
|
|
1204
1226
|
FromPort: 443,
|
|
1205
1227
|
ToPort: 443,
|
|
1206
|
-
SourceSecurityGroupId:
|
|
1228
|
+
SourceSecurityGroupId: sourceSgId
|
|
1207
1229
|
}
|
|
1208
1230
|
],
|
|
1209
1231
|
Tags: [
|
|
@@ -1472,6 +1472,76 @@ describe('VpcBuilder', () => {
|
|
|
1472
1472
|
});
|
|
1473
1473
|
});
|
|
1474
1474
|
|
|
1475
|
+
describe('VPC Endpoint Security Group with External Lambda SG', () => {
|
|
1476
|
+
it('should use external Lambda SG ID (not Ref) for VPC endpoint SG when Lambda SG is external', async () => {
|
|
1477
|
+
const appDefinition = {
|
|
1478
|
+
vpc: {
|
|
1479
|
+
enable: true,
|
|
1480
|
+
enableVPCEndpoints: true,
|
|
1481
|
+
ownership: {
|
|
1482
|
+
securityGroup: 'external' // External Lambda SG
|
|
1483
|
+
}
|
|
1484
|
+
},
|
|
1485
|
+
encryption: { fieldLevelEncryptionMethod: 'kms' }
|
|
1486
|
+
};
|
|
1487
|
+
const discoveredResources = {
|
|
1488
|
+
fromCloudFormationStack: true,
|
|
1489
|
+
defaultVpcId: 'vpc-123',
|
|
1490
|
+
defaultSecurityGroupId: 'sg-default-456', // Default VPC SG
|
|
1491
|
+
lambdaSecurityGroupId: 'sg-stack-789', // Stack-managed SG (will be ignored)
|
|
1492
|
+
privateSubnetId1: 'subnet-1',
|
|
1493
|
+
privateSubnetId2: 'subnet-2',
|
|
1494
|
+
natGatewayId: 'nat-123',
|
|
1495
|
+
existingLogicalIds: ['FriggS3VPCEndpoint', 'FriggKMSVPCEndpoint'],
|
|
1496
|
+
s3VpcEndpointId: 'vpce-s3-stack',
|
|
1497
|
+
kmsVpcEndpointId: 'vpce-kms-stack'
|
|
1498
|
+
};
|
|
1499
|
+
|
|
1500
|
+
const result = await vpcBuilder.build(appDefinition, discoveredResources);
|
|
1501
|
+
|
|
1502
|
+
// VPC Endpoint SG should be created
|
|
1503
|
+
expect(result.resources.FriggVPCEndpointSecurityGroup).toBeDefined();
|
|
1504
|
+
|
|
1505
|
+
// CRITICAL: Should use external Lambda SG ID directly, NOT a CloudFormation Ref
|
|
1506
|
+
const ingressRule = result.resources.FriggVPCEndpointSecurityGroup.Properties.SecurityGroupIngress[0];
|
|
1507
|
+
expect(ingressRule.SourceSecurityGroupId).toBe('sg-default-456'); // Direct ID, not { Ref: 'FriggLambdaSecurityGroup' }
|
|
1508
|
+
expect(typeof ingressRule.SourceSecurityGroupId).toBe('string');
|
|
1509
|
+
|
|
1510
|
+
// Verify FriggLambdaSecurityGroup is NOT in the template
|
|
1511
|
+
expect(result.resources.FriggLambdaSecurityGroup).toBeUndefined();
|
|
1512
|
+
});
|
|
1513
|
+
|
|
1514
|
+
it('should use CloudFormation Ref when Lambda SG is stack-managed', async () => {
|
|
1515
|
+
const appDefinition = {
|
|
1516
|
+
vpc: {
|
|
1517
|
+
enable: true,
|
|
1518
|
+
enableVPCEndpoints: true,
|
|
1519
|
+
ownership: {
|
|
1520
|
+
securityGroup: 'stack' // Stack-managed Lambda SG
|
|
1521
|
+
}
|
|
1522
|
+
},
|
|
1523
|
+
encryption: { fieldLevelEncryptionMethod: 'kms' }
|
|
1524
|
+
};
|
|
1525
|
+
const discoveredResources = {
|
|
1526
|
+
defaultVpcId: 'vpc-123',
|
|
1527
|
+
privateSubnetId1: 'subnet-1',
|
|
1528
|
+
privateSubnetId2: 'subnet-2'
|
|
1529
|
+
};
|
|
1530
|
+
|
|
1531
|
+
const result = await vpcBuilder.build(appDefinition, discoveredResources);
|
|
1532
|
+
|
|
1533
|
+
// VPC Endpoint SG should be created
|
|
1534
|
+
expect(result.resources.FriggVPCEndpointSecurityGroup).toBeDefined();
|
|
1535
|
+
|
|
1536
|
+
// Should use CloudFormation Ref when Lambda SG is in stack
|
|
1537
|
+
const ingressRule = result.resources.FriggVPCEndpointSecurityGroup.Properties.SecurityGroupIngress[0];
|
|
1538
|
+
expect(ingressRule.SourceSecurityGroupId).toEqual({ Ref: 'FriggLambdaSecurityGroup' });
|
|
1539
|
+
|
|
1540
|
+
// Verify FriggLambdaSecurityGroup IS in the template
|
|
1541
|
+
expect(result.resources.FriggLambdaSecurityGroup).toBeDefined();
|
|
1542
|
+
});
|
|
1543
|
+
});
|
|
1544
|
+
|
|
1475
1545
|
describe('convertFlatDiscoveryToStructured - VPC Endpoints from CloudFormation', () => {
|
|
1476
1546
|
it('should add VPC endpoints to stackManaged when in existingLogicalIds', () => {
|
|
1477
1547
|
const flatDiscovery = {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@friggframework/devtools",
|
|
3
3
|
"prettier": "@friggframework/prettier-config",
|
|
4
|
-
"version": "2.0.0--canary.490.
|
|
4
|
+
"version": "2.0.0--canary.490.12406f7.0",
|
|
5
5
|
"bin": {
|
|
6
6
|
"frigg": "./frigg-cli/index.js"
|
|
7
7
|
},
|
|
@@ -16,9 +16,9 @@
|
|
|
16
16
|
"@babel/eslint-parser": "^7.18.9",
|
|
17
17
|
"@babel/parser": "^7.25.3",
|
|
18
18
|
"@babel/traverse": "^7.25.3",
|
|
19
|
-
"@friggframework/core": "2.0.0--canary.490.
|
|
20
|
-
"@friggframework/schemas": "2.0.0--canary.490.
|
|
21
|
-
"@friggframework/test": "2.0.0--canary.490.
|
|
19
|
+
"@friggframework/core": "2.0.0--canary.490.12406f7.0",
|
|
20
|
+
"@friggframework/schemas": "2.0.0--canary.490.12406f7.0",
|
|
21
|
+
"@friggframework/test": "2.0.0--canary.490.12406f7.0",
|
|
22
22
|
"@hapi/boom": "^10.0.1",
|
|
23
23
|
"@inquirer/prompts": "^5.3.8",
|
|
24
24
|
"axios": "^1.7.2",
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
"validate-npm-package-name": "^5.0.0"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
|
-
"@friggframework/eslint-config": "2.0.0--canary.490.
|
|
50
|
-
"@friggframework/prettier-config": "2.0.0--canary.490.
|
|
49
|
+
"@friggframework/eslint-config": "2.0.0--canary.490.12406f7.0",
|
|
50
|
+
"@friggframework/prettier-config": "2.0.0--canary.490.12406f7.0",
|
|
51
51
|
"aws-sdk-client-mock": "^4.1.0",
|
|
52
52
|
"aws-sdk-client-mock-jest": "^4.1.0",
|
|
53
53
|
"jest": "^30.1.3",
|
|
@@ -79,5 +79,5 @@
|
|
|
79
79
|
"publishConfig": {
|
|
80
80
|
"access": "public"
|
|
81
81
|
},
|
|
82
|
-
"gitHead": "
|
|
82
|
+
"gitHead": "12406f722951a015ba310ba6c47854d7fda9dee2"
|
|
83
83
|
}
|