Skip to content
This repository was archived by the owner on Nov 27, 2023. It is now read-only.

Commit b9a3025

Browse files
committed
Only consider public subnets
Signed-off-by: Nicolas De Loof <[email protected]>
1 parent 99de963 commit b9a3025

File tree

5 files changed

+66
-4
lines changed

5 files changed

+66
-4
lines changed

ecs/aws.go

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ type API interface {
4040
CheckVPC(ctx context.Context, vpcID string) error
4141
GetDefaultVPC(ctx context.Context) (string, error)
4242
GetSubNets(ctx context.Context, vpcID string) ([]awsResource, error)
43+
IsPublicSubnet(ctx context.Context, vpcID string, subNetID string) (bool, error)
4344
GetRoleArn(ctx context.Context, name string) (string, error)
4445
StackExists(ctx context.Context, name string) (bool, error)
4546
CreateStack(ctx context.Context, name string, region string, template []byte) error

ecs/awsResources.go

+15-3
Original file line numberDiff line numberDiff line change
@@ -185,10 +185,22 @@ func (b *ecsAPIService) parseVPCExtension(ctx context.Context, project *types.Pr
185185
if err != nil {
186186
return "", nil, err
187187
}
188-
if len(subNets) < 2 {
189-
return "", nil, fmt.Errorf("VPC %s should have at least 2 associated subnets in different availability zones", vpc)
188+
189+
var publicSubNets []awsResource
190+
for _, subNet := range subNets {
191+
isPublic, err := b.aws.IsPublicSubnet(ctx, vpc, subNet.ID())
192+
if err != nil {
193+
return "", nil, err
194+
}
195+
if isPublic {
196+
publicSubNets = append(publicSubNets, subNet)
197+
}
198+
}
199+
200+
if len(publicSubNets) < 2 {
201+
return "", nil, fmt.Errorf("VPC %s should have at least 2 associated public subnets in different availability zones", vpc)
190202
}
191-
return vpc, subNets, nil
203+
return vpc, publicSubNets, nil
192204
}
193205

194206
func (b *ecsAPIService) parseLoadBalancerExtension(ctx context.Context, project *types.Project) (awsResource, string, error) {

ecs/aws_mock.go

+17-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ecs/cloudformation_test.go

+2
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,8 @@ func useDefaultVPC(m *MockAPIMockRecorder) {
591591
existingAWSResource{id: "subnet1"},
592592
existingAWSResource{id: "subnet2"},
593593
}, nil)
594+
m.IsPublicSubnet(gomock.Any(), "subnet1").Return(true, nil)
595+
m.IsPublicSubnet(gomock.Any(), "subnet2").Return(true, nil)
594596
}
595597

596598
func useGPU(m *MockAPIMockRecorder) {

ecs/sdk.go

+31
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,37 @@ func (s sdk) GetSubNets(ctx context.Context, vpcID string) ([]awsResource, error
211211
return ids, nil
212212
}
213213

214+
func (s sdk) IsPublicSubnet(ctx context.Context, vpcID string, subNetID string) (bool, error) {
215+
tables, err := s.EC2.DescribeRouteTablesWithContext(ctx, &ec2.DescribeRouteTablesInput{
216+
Filters: []*ec2.Filter{
217+
{
218+
Name: aws.String("association.subnet-id"),
219+
Values: []*string{aws.String(subNetID)},
220+
},
221+
},
222+
})
223+
if err != nil {
224+
return false, err
225+
}
226+
if len(tables.RouteTables) == 0 {
227+
// If a subnet is not explicitly associated with any route table, it is implicitly associated with the main route table.
228+
// https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-route-tables.html
229+
return true, nil
230+
}
231+
for _, routeTable := range tables.RouteTables {
232+
for _, route := range routeTable.Routes {
233+
if aws.StringValue(route.State) != "active" {
234+
continue
235+
}
236+
if strings.HasPrefix(aws.StringValue(route.GatewayId), "igw-") {
237+
// Connected to an internet Gateway
238+
return true, nil
239+
}
240+
}
241+
}
242+
return false, nil
243+
}
244+
214245
func (s sdk) GetRoleArn(ctx context.Context, name string) (string, error) {
215246
role, err := s.IAM.GetRoleWithContext(ctx, &iam.GetRoleInput{
216247
RoleName: aws.String(name),

0 commit comments

Comments
 (0)