@friggframework/devtools 2.0.0--canary.428.1c210bc.0 → 2.0.0--canary.428.4968614.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.
|
@@ -559,8 +559,23 @@ class AWSDiscovery {
|
|
|
559
559
|
const response = await this.ec2Client.send(command);
|
|
560
560
|
|
|
561
561
|
if (response.NatGateways && response.NatGateways.length > 0) {
|
|
562
|
+
// Filter out any NAT Gateways that are not truly available
|
|
563
|
+
const availableNatGateways = response.NatGateways.filter(nat => {
|
|
564
|
+
// Double-check the state is truly 'available'
|
|
565
|
+
if (nat.State !== 'available') {
|
|
566
|
+
console.warn(`Skipping NAT Gateway ${nat.NatGatewayId} with state: ${nat.State}`);
|
|
567
|
+
return false;
|
|
568
|
+
}
|
|
569
|
+
return true;
|
|
570
|
+
});
|
|
571
|
+
|
|
572
|
+
if (availableNatGateways.length === 0) {
|
|
573
|
+
console.warn('No truly available NAT Gateways found in VPC');
|
|
574
|
+
return null;
|
|
575
|
+
}
|
|
576
|
+
|
|
562
577
|
// Sort NAT Gateways to prioritize Frigg-managed ones
|
|
563
|
-
const sortedNatGateways =
|
|
578
|
+
const sortedNatGateways = availableNatGateways.sort((a, b) => {
|
|
564
579
|
const aIsFrigg =
|
|
565
580
|
a.Tags &&
|
|
566
581
|
a.Tags.some(
|
|
@@ -632,7 +647,7 @@ class AWSDiscovery {
|
|
|
632
647
|
|
|
633
648
|
if (isFriggNat) {
|
|
634
649
|
console.log(
|
|
635
|
-
`Found existing Frigg-managed NAT Gateway: ${natGateway.NatGatewayId}`
|
|
650
|
+
`Found existing Frigg-managed NAT Gateway: ${natGateway.NatGatewayId} (State: ${natGateway.State})`
|
|
636
651
|
);
|
|
637
652
|
natGateway._isInPrivateSubnet = false;
|
|
638
653
|
return natGateway;
|
|
@@ -640,7 +655,7 @@ class AWSDiscovery {
|
|
|
640
655
|
|
|
641
656
|
// Return first valid NAT Gateway that's in a public subnet
|
|
642
657
|
console.log(
|
|
643
|
-
`Found existing NAT Gateway in public subnet: ${natGateway.NatGatewayId}`
|
|
658
|
+
`Found existing NAT Gateway in public subnet: ${natGateway.NatGatewayId} (State: ${natGateway.State})`
|
|
644
659
|
);
|
|
645
660
|
natGateway._isInPrivateSubnet = false;
|
|
646
661
|
return natGateway;
|
|
@@ -1252,6 +1267,7 @@ class AWSDiscovery {
|
|
|
1252
1267
|
|
|
1253
1268
|
return {
|
|
1254
1269
|
defaultVpcId: vpc.VpcId,
|
|
1270
|
+
vpcCidr: vpc.CidrBlock, // Add VPC CIDR for security group configuration
|
|
1255
1271
|
defaultSecurityGroupId: securityGroup.GroupId,
|
|
1256
1272
|
privateSubnetId1: privateSubnets[0]?.SubnetId,
|
|
1257
1273
|
privateSubnetId2:
|
|
@@ -56,6 +56,7 @@ describe('BuildTimeDiscovery', () => {
|
|
|
56
56
|
describe('discoverAndCreateConfig', () => {
|
|
57
57
|
const mockResources = {
|
|
58
58
|
defaultVpcId: 'vpc-12345678',
|
|
59
|
+
vpcCidr: '172.31.0.0/16',
|
|
59
60
|
defaultSecurityGroupId: 'sg-12345678',
|
|
60
61
|
privateSubnetId1: 'subnet-1',
|
|
61
62
|
privateSubnetId2: 'subnet-2',
|
|
@@ -100,6 +101,7 @@ describe('BuildTimeDiscovery', () => {
|
|
|
100
101
|
describe('replaceTemplateVariables', () => {
|
|
101
102
|
const mockResources = {
|
|
102
103
|
defaultVpcId: 'vpc-12345678',
|
|
104
|
+
vpcCidr: '172.31.0.0/16',
|
|
103
105
|
defaultSecurityGroupId: 'sg-12345678',
|
|
104
106
|
privateSubnetId1: 'subnet-1',
|
|
105
107
|
privateSubnetId2: 'subnet-2',
|
|
@@ -225,6 +227,7 @@ describe('BuildTimeDiscovery', () => {
|
|
|
225
227
|
describe('preBuildHook', () => {
|
|
226
228
|
const mockResources = {
|
|
227
229
|
defaultVpcId: 'vpc-12345678',
|
|
230
|
+
vpcCidr: '172.31.0.0/16',
|
|
228
231
|
defaultSecurityGroupId: 'sg-12345678',
|
|
229
232
|
privateSubnetId1: 'subnet-1',
|
|
230
233
|
privateSubnetId2: 'subnet-2',
|
|
@@ -1893,6 +1893,8 @@ const composeServerlessDefinition = async (AppDefinition) => {
|
|
|
1893
1893
|
}
|
|
1894
1894
|
|
|
1895
1895
|
// Always add route table and routes (referencing the NAT, whether new or existing)
|
|
1896
|
+
// IMPORTANT: Create a new route table to ensure clean routing configuration
|
|
1897
|
+
// This avoids issues with stale routes pointing to deleted NAT Gateways
|
|
1896
1898
|
definition.resources.Resources.FriggLambdaRouteTable = {
|
|
1897
1899
|
Type: 'AWS::EC2::RouteTable',
|
|
1898
1900
|
Properties: {
|
|
@@ -1904,6 +1906,10 @@ const composeServerlessDefinition = async (AppDefinition) => {
|
|
|
1904
1906
|
Key: 'Name',
|
|
1905
1907
|
Value: '${self:service}-${self:provider.stage}-lambda-rt',
|
|
1906
1908
|
},
|
|
1909
|
+
{
|
|
1910
|
+
Key: 'ManagedBy',
|
|
1911
|
+
Value: 'Frigg',
|
|
1912
|
+
},
|
|
1907
1913
|
],
|
|
1908
1914
|
},
|
|
1909
1915
|
};
|
|
@@ -1914,18 +1920,23 @@ const composeServerlessDefinition = async (AppDefinition) => {
|
|
|
1914
1920
|
if (reuseExistingNatGateway) {
|
|
1915
1921
|
// Use the existing NAT Gateway that we're reusing
|
|
1916
1922
|
natGatewayIdForRoute = discoveredResources.existingNatGatewayId;
|
|
1923
|
+
console.log(`Using discovered NAT Gateway for routing: ${natGatewayIdForRoute}`);
|
|
1917
1924
|
} else if (needsNewNatGateway && !reuseExistingNatGateway) {
|
|
1918
1925
|
// Reference the new NAT Gateway being created
|
|
1919
1926
|
natGatewayIdForRoute = { Ref: 'FriggNATGateway' };
|
|
1927
|
+
console.log('Using newly created NAT Gateway for routing');
|
|
1920
1928
|
} else if (discoveredResources.existingNatGatewayId) {
|
|
1921
1929
|
// Use the existing NAT Gateway ID
|
|
1922
1930
|
natGatewayIdForRoute = discoveredResources.existingNatGatewayId;
|
|
1931
|
+
console.log(`Using discovered NAT Gateway for routing: ${natGatewayIdForRoute}`);
|
|
1923
1932
|
} else if (AppDefinition.vpc.natGateway?.id) {
|
|
1924
1933
|
// Use explicitly provided NAT Gateway ID
|
|
1925
1934
|
natGatewayIdForRoute = AppDefinition.vpc.natGateway.id;
|
|
1935
|
+
console.log(`Using explicitly provided NAT Gateway for routing: ${natGatewayIdForRoute}`);
|
|
1926
1936
|
} else if (AppDefinition.vpc.selfHeal === true) {
|
|
1927
1937
|
// Self-healing enabled but no NAT Gateway - skip NAT route
|
|
1928
1938
|
natGatewayIdForRoute = null;
|
|
1939
|
+
console.log('No NAT Gateway available - skipping NAT route creation');
|
|
1929
1940
|
} else {
|
|
1930
1941
|
throw new Error(
|
|
1931
1942
|
'Unable to determine NAT Gateway ID for routing. ' +
|
|
@@ -1935,7 +1946,8 @@ const composeServerlessDefinition = async (AppDefinition) => {
|
|
|
1935
1946
|
|
|
1936
1947
|
// Only create NAT route if we have a NAT Gateway
|
|
1937
1948
|
if (natGatewayIdForRoute) {
|
|
1938
|
-
|
|
1949
|
+
console.log(`Creating NAT route: 0.0.0.0/0 → ${natGatewayIdForRoute}`);
|
|
1950
|
+
definition.resources.Resources.FriggNATRoute = {
|
|
1939
1951
|
Type: 'AWS::EC2::Route',
|
|
1940
1952
|
Properties: {
|
|
1941
1953
|
RouteTableId: { Ref: 'FriggLambdaRouteTable' },
|
|
@@ -1943,6 +1955,8 @@ const composeServerlessDefinition = async (AppDefinition) => {
|
|
|
1943
1955
|
NatGatewayId: natGatewayIdForRoute,
|
|
1944
1956
|
},
|
|
1945
1957
|
};
|
|
1958
|
+
} else {
|
|
1959
|
+
console.warn('⚠️ No NAT Gateway configured - Lambda functions will not have internet access');
|
|
1946
1960
|
}
|
|
1947
1961
|
|
|
1948
1962
|
// Associate Lambda subnets with NAT Gateway route table
|
|
@@ -2028,6 +2042,13 @@ const composeServerlessDefinition = async (AppDefinition) => {
|
|
|
2028
2042
|
AppDefinition.encryption?.fieldLevelEncryptionMethod ===
|
|
2029
2043
|
'kms'
|
|
2030
2044
|
) {
|
|
2045
|
+
// Validate we have VPC CIDR for security group configuration
|
|
2046
|
+
if (!discoveredResources.vpcCidr) {
|
|
2047
|
+
console.warn(
|
|
2048
|
+
'⚠️ Warning: VPC CIDR not discovered. VPC endpoint security group may not work correctly.'
|
|
2049
|
+
);
|
|
2050
|
+
}
|
|
2051
|
+
|
|
2031
2052
|
// Create security group for VPC endpoints if it doesn't exist
|
|
2032
2053
|
if (
|
|
2033
2054
|
!definition.resources.Resources
|
|
@@ -2040,16 +2061,16 @@ const composeServerlessDefinition = async (AppDefinition) => {
|
|
|
2040
2061
|
GroupDescription:
|
|
2041
2062
|
'Security group for VPC endpoints',
|
|
2042
2063
|
VpcId: discoveredResources.defaultVpcId,
|
|
2043
|
-
SecurityGroupIngress:
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2064
|
+
SecurityGroupIngress: discoveredResources.vpcCidr
|
|
2065
|
+
? [
|
|
2066
|
+
{
|
|
2067
|
+
IpProtocol: 'tcp',
|
|
2068
|
+
FromPort: 443,
|
|
2069
|
+
ToPort: 443,
|
|
2070
|
+
CidrIp: discoveredResources.vpcCidr, // Use discovered VPC CIDR
|
|
2071
|
+
},
|
|
2072
|
+
]
|
|
2073
|
+
: [], // Empty array if no VPC CIDR discovered
|
|
2053
2074
|
Tags: [
|
|
2054
2075
|
{
|
|
2055
2076
|
Key: 'Name',
|
|
@@ -7,6 +7,7 @@ jest.mock('./aws-discovery', () => {
|
|
|
7
7
|
return {
|
|
8
8
|
discoverResources: jest.fn().mockResolvedValue({
|
|
9
9
|
defaultVpcId: 'vpc-123456',
|
|
10
|
+
vpcCidr: '172.31.0.0/16', // Add VPC CIDR for security group configuration
|
|
10
11
|
defaultSecurityGroupId: 'sg-123456',
|
|
11
12
|
privateSubnetId1: 'subnet-123456',
|
|
12
13
|
privateSubnetId2: 'subnet-789012',
|
|
@@ -484,6 +485,10 @@ describe('composeServerlessDefinition', () => {
|
|
|
484
485
|
Key: 'Name',
|
|
485
486
|
Value: '${self:service}-${self:provider.stage}-frigg-kms-key'
|
|
486
487
|
},
|
|
488
|
+
{
|
|
489
|
+
Key: 'ManagedBy',
|
|
490
|
+
Value: 'Frigg'
|
|
491
|
+
},
|
|
487
492
|
{
|
|
488
493
|
Key: 'Purpose',
|
|
489
494
|
Value: 'Field-level encryption for Frigg application'
|
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.428.
|
|
4
|
+
"version": "2.0.0--canary.428.4968614.0",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"@aws-sdk/client-ec2": "^3.835.0",
|
|
7
7
|
"@aws-sdk/client-kms": "^3.835.0",
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
"@babel/eslint-parser": "^7.18.9",
|
|
10
10
|
"@babel/parser": "^7.25.3",
|
|
11
11
|
"@babel/traverse": "^7.25.3",
|
|
12
|
-
"@friggframework/schemas": "2.0.0--canary.428.
|
|
13
|
-
"@friggframework/test": "2.0.0--canary.428.
|
|
12
|
+
"@friggframework/schemas": "2.0.0--canary.428.4968614.0",
|
|
13
|
+
"@friggframework/test": "2.0.0--canary.428.4968614.0",
|
|
14
14
|
"@hapi/boom": "^10.0.1",
|
|
15
15
|
"@inquirer/prompts": "^5.3.8",
|
|
16
16
|
"axios": "^1.7.2",
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
"serverless-http": "^2.7.0"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
|
-
"@friggframework/eslint-config": "2.0.0--canary.428.
|
|
36
|
-
"@friggframework/prettier-config": "2.0.0--canary.428.
|
|
35
|
+
"@friggframework/eslint-config": "2.0.0--canary.428.4968614.0",
|
|
36
|
+
"@friggframework/prettier-config": "2.0.0--canary.428.4968614.0",
|
|
37
37
|
"aws-sdk-client-mock": "^4.1.0",
|
|
38
38
|
"aws-sdk-client-mock-jest": "^4.1.0",
|
|
39
39
|
"jest": "^30.1.3",
|
|
@@ -68,5 +68,5 @@
|
|
|
68
68
|
"publishConfig": {
|
|
69
69
|
"access": "public"
|
|
70
70
|
},
|
|
71
|
-
"gitHead": "
|
|
71
|
+
"gitHead": "49686143bbd8303507c1824ef167465d1efeaa1e"
|
|
72
72
|
}
|