Skip to content

Commit 9582e18

Browse files
committed
eigw: use cluster tag key to list managed egress-only internet gateway
The API for DescribeEgressOnlyInternetGateways does not support attachment.vpc-id filter. Thus, the call will return all available eigw. Consequences: - CAPA incorrectly selects an unintended eigw for use. Leading to route creation failure since the eigw belongs to a different VPC. - CAPA incorrectly destroys all eigw of all VPCs. This is very catastrophic as it can break other workloads. This commit changes the filter to use cluster tag instead. Additional safeguard is also included to check if the eigw is truly attached the VPC.
1 parent dab54f9 commit 9582e18

File tree

2 files changed

+19
-5
lines changed

2 files changed

+19
-5
lines changed

pkg/cloud/services/network/egress_only_gateways.go

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,21 +136,35 @@ func (s *Service) createEgressOnlyInternetGateway() (*types.EgressOnlyInternetGa
136136
}
137137

138138
func (s *Service) describeEgressOnlyVpcInternetGateways() ([]types.EgressOnlyInternetGateway, error) {
139+
// The API for DescribeEgressOnlyInternetGateways does not support filtering by VPC ID attachment.
140+
// More details: https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeEgressOnlyInternetGateways.html
141+
// Since the eigw is managed by CAPA, we can filter by the kubernetes cluster tag.
139142
out, err := s.EC2Client.DescribeEgressOnlyInternetGateways(context.TODO(), &ec2.DescribeEgressOnlyInternetGatewaysInput{
140143
Filters: []types.Filter{
141-
filter.EC2.VPCAttachment(s.scope.VPC().ID),
144+
filter.EC2.Cluster(s.scope.Name()),
142145
},
143146
})
144147
if err != nil {
145148
record.Eventf(s.scope.InfraCluster(), "FailedDescribeEgressOnlyInternetGateway", "Failed to describe egress only internet gateway in vpc %q: %v", s.scope.VPC().ID, err)
146149
return nil, errors.Wrapf(err, "failed to describe egress only internet gateways in vpc %q", s.scope.VPC().ID)
147150
}
148151

149-
if len(out.EgressOnlyInternetGateways) == 0 {
152+
// For safeguarding, we collect only egress-only internet gateways
153+
// that are attached to the VPC.
154+
eigws := make([]types.EgressOnlyInternetGateway, 0)
155+
for _, eigw := range out.EgressOnlyInternetGateways {
156+
for _, attachment := range eigw.Attachments {
157+
if aws.StringValue(attachment.VpcId) == s.scope.VPC().ID {
158+
eigws = append(eigws, eigw)
159+
}
160+
}
161+
}
162+
163+
if len(eigws) == 0 {
150164
return nil, awserrors.NewNotFound(fmt.Sprintf("no egress only internet gateways found in vpc %q", s.scope.VPC().ID))
151165
}
152166

153-
return out.EgressOnlyInternetGateways, nil
167+
return eigws, nil
154168
}
155169

156170
func (s *Service) getEgressOnlyGatewayTagParams(id string) infrav1.BuildParams {

pkg/cloud/services/network/egress_only_gateways_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,8 +199,8 @@ func TestDeleteEgressOnlyInternetGateways(t *testing.T) {
199199
m.DescribeEgressOnlyInternetGateways(context.TODO(), gomock.Eq(&ec2.DescribeEgressOnlyInternetGatewaysInput{
200200
Filters: []types.Filter{
201201
{
202-
Name: aws.String("attachment.vpc-id"),
203-
Values: []string{"vpc-gateways"},
202+
Name: aws.String("tag-key"),
203+
Values: []string{infrav1.ClusterTagKey("test-cluster")},
204204
},
205205
},
206206
})).Return(&ec2.DescribeEgressOnlyInternetGatewaysOutput{}, nil)

0 commit comments

Comments
 (0)