Skip to content

Commit 60fe9aa

Browse files
committed
Sorting LB security groups should prefer tagged security group
1 parent 806ed2c commit 60fe9aa

File tree

3 files changed

+77
-15
lines changed

3 files changed

+77
-15
lines changed

pkg/providers/v1/aws.go

+28-9
Original file line numberDiff line numberDiff line change
@@ -3869,12 +3869,16 @@ func (c *Cloud) buildELBSecurityGroupList(serviceName types.NamespacedName, load
38693869
// from buildELBSecurityGroupList. The logic is:
38703870
// - securityGroups specified by ServiceAnnotationLoadBalancerSecurityGroups appears first in order
38713871
// - securityGroups specified by ServiceAnnotationLoadBalancerExtraSecurityGroups appears last in order
3872-
func (c *Cloud) sortELBSecurityGroupList(securityGroupIDs []string, annotations map[string]string) {
3872+
func (c *Cloud) sortELBSecurityGroupList(securityGroupIDs []string, annotations map[string]string, taggedLBSecurityGroups map[string]struct{}) {
38733873
annotatedSGList := getSGListFromAnnotation(annotations[ServiceAnnotationLoadBalancerSecurityGroups])
38743874
annotatedExtraSGList := getSGListFromAnnotation(annotations[ServiceAnnotationLoadBalancerExtraSecurityGroups])
38753875
annotatedSGIndex := make(map[string]int, len(annotatedSGList))
38763876
annotatedExtraSGIndex := make(map[string]int, len(annotatedExtraSGList))
38773877

3878+
if taggedLBSecurityGroups == nil {
3879+
taggedLBSecurityGroups = make(map[string]struct{})
3880+
}
3881+
38783882
for i, sgID := range annotatedSGList {
38793883
annotatedSGIndex[sgID] = i
38803884
}
@@ -3892,7 +3896,11 @@ func (c *Cloud) sortELBSecurityGroupList(securityGroupIDs []string, annotations
38923896
}
38933897
}
38943898
sort.Slice(securityGroupIDs, func(i, j int) bool {
3895-
return sgOrderMapping[securityGroupIDs[i]] < sgOrderMapping[securityGroupIDs[j]]
3899+
// If i is tagged but j is not, then i should be before j.
3900+
_, iTagged := taggedLBSecurityGroups[securityGroupIDs[i]]
3901+
_, jTagged := taggedLBSecurityGroups[securityGroupIDs[j]]
3902+
3903+
return sgOrderMapping[securityGroupIDs[i]] < sgOrderMapping[securityGroupIDs[j]] || iTagged && !jTagged
38963904
})
38973905
}
38983906

@@ -4583,7 +4591,20 @@ func (c *Cloud) updateInstanceSecurityGroupsForLoadBalancer(lb *elb.LoadBalancer
45834591
if len(lbSecurityGroupIDs) == 0 {
45844592
return fmt.Errorf("could not determine security group for load balancer: %s", aws.StringValue(lb.LoadBalancerName))
45854593
}
4586-
c.sortELBSecurityGroupList(lbSecurityGroupIDs, annotations)
4594+
4595+
taggedSecurityGroups, err := c.getTaggedSecurityGroups()
4596+
if err != nil {
4597+
return fmt.Errorf("error querying for tagged security groups: %q", err)
4598+
}
4599+
4600+
taggedLBSecurityGroups := make(map[string]struct{})
4601+
for _, sg := range lbSecurityGroupIDs {
4602+
if _, ok := taggedSecurityGroups[sg]; ok {
4603+
taggedLBSecurityGroups[sg] = struct{}{}
4604+
}
4605+
}
4606+
4607+
c.sortELBSecurityGroupList(lbSecurityGroupIDs, annotations, taggedLBSecurityGroups)
45874608
loadBalancerSecurityGroupID := lbSecurityGroupIDs[0]
45884609

45894610
// Get the actual list of groups that allow ingress from the load-balancer
@@ -4602,11 +4623,6 @@ func (c *Cloud) updateInstanceSecurityGroupsForLoadBalancer(lb *elb.LoadBalancer
46024623
}
46034624
}
46044625

4605-
taggedSecurityGroups, err := c.getTaggedSecurityGroups()
4606-
if err != nil {
4607-
return fmt.Errorf("error querying for tagged security groups: %q", err)
4608-
}
4609-
46104626
// Open the firewall from the load balancer to the instance
46114627
// We don't actually have a trivial way to know in advance which security group the instance is in
46124628
// (it is probably the node security group, but we don't easily have that).
@@ -4766,6 +4782,7 @@ func (c *Cloud) EnsureLoadBalancerDeleted(ctx context.Context, clusterName strin
47664782
// We need to know this ahead of time so that we can check
47674783
// if the load balancer security group is being deleted.
47684784
securityGroupIDs := map[string]struct{}{}
4785+
taggedLBSecurityGroups := map[string]struct{}{}
47694786
{
47704787
// Delete the security group(s) for the load balancer
47714788
// Note that this is annoying: the load balancer disappears from the API immediately, but it is still
@@ -4805,6 +4822,8 @@ func (c *Cloud) EnsureLoadBalancerDeleted(ctx context.Context, clusterName strin
48054822
if !c.tagging.hasClusterTag(sg.Tags) {
48064823
klog.Warningf("Ignoring security group with no cluster tag in %s", service.Name)
48074824
continue
4825+
} else {
4826+
taggedLBSecurityGroups[sgID] = struct{}{}
48084827
}
48094828

48104829
// This is an extra protection of deletion of non provisioned Security Group which is annotated with `service.beta.kubernetes.io/aws-load-balancer-security-groups`.
@@ -4823,7 +4842,7 @@ func (c *Cloud) EnsureLoadBalancerDeleted(ctx context.Context, clusterName strin
48234842
if len(lbSecurityGroupIDs) == 0 {
48244843
return fmt.Errorf("could not determine security group for load balancer: %s", aws.StringValue(lb.LoadBalancerName))
48254844
}
4826-
c.sortELBSecurityGroupList(lbSecurityGroupIDs, service.Annotations)
4845+
c.sortELBSecurityGroupList(lbSecurityGroupIDs, service.Annotations, taggedLBSecurityGroups)
48274846
loadBalancerSecurityGroupID := lbSecurityGroupIDs[0]
48284847

48294848
_, isDeleteingLBSecurityGroup := securityGroupIDs[loadBalancerSecurityGroupID]

pkg/providers/v1/aws_fakes.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -450,8 +450,8 @@ func (elb *FakeELB) CreateLoadBalancer(*elb.CreateLoadBalancerInput) (*elb.Creat
450450

451451
// DeleteLoadBalancer is not implemented but is required for interface
452452
// conformance
453-
func (elb *FakeELB) DeleteLoadBalancer(input *elb.DeleteLoadBalancerInput) (*elb.DeleteLoadBalancerOutput, error) {
454-
panic("Not implemented")
453+
func (e *FakeELB) DeleteLoadBalancer(input *elb.DeleteLoadBalancerInput) (*elb.DeleteLoadBalancerOutput, error) {
454+
return &elb.DeleteLoadBalancerOutput{}, nil
455455
}
456456

457457
// DescribeLoadBalancers is not implemented but is required for interface

pkg/providers/v1/aws_test.go

+47-4
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,29 @@ func (m *MockedFakeEC2) expectDescribeSecurityGroups(clusterID, groupName string
6666
}}).Return([]*ec2.SecurityGroup{{Tags: tags}})
6767
}
6868

69+
func (m *MockedFakeEC2) expectDescribeSecurityGroupsAll(clusterID string) {
70+
tags := []*ec2.Tag{
71+
{Key: aws.String(TagNameKubernetesClusterLegacy), Value: aws.String(clusterID)},
72+
{Key: aws.String(fmt.Sprintf("%s%s", TagNameKubernetesClusterPrefix, clusterID)), Value: aws.String(ResourceLifecycleOwned)},
73+
}
74+
75+
m.On("DescribeSecurityGroups", &ec2.DescribeSecurityGroupsInput{}).Return([]*ec2.SecurityGroup{{
76+
GroupId: aws.String("sg-123456"),
77+
Tags: tags,
78+
}})
79+
}
80+
81+
func (m *MockedFakeEC2) expectDescribeSecurityGroupsByFilter(clusterID, filterName string, filterValues ...string) {
82+
tags := []*ec2.Tag{
83+
{Key: aws.String(TagNameKubernetesClusterLegacy), Value: aws.String(clusterID)},
84+
{Key: aws.String(fmt.Sprintf("%s%s", TagNameKubernetesClusterPrefix, clusterID)), Value: aws.String(ResourceLifecycleOwned)},
85+
}
86+
87+
m.On("DescribeSecurityGroups", &ec2.DescribeSecurityGroupsInput{Filters: []*ec2.Filter{
88+
newEc2Filter(filterName, filterValues...),
89+
}}).Return([]*ec2.SecurityGroup{{Tags: tags}})
90+
}
91+
6992
func (m *MockedFakeEC2) DescribeVolumes(request *ec2.DescribeVolumesInput) ([]*ec2.Volume, error) {
7093
args := m.Called(request)
7194
return args.Get(0).([]*ec2.Volume), nil
@@ -117,7 +140,11 @@ func (m *MockedFakeELB) DescribeLoadBalancers(input *elb.DescribeLoadBalancersIn
117140

118141
func (m *MockedFakeELB) expectDescribeLoadBalancers(loadBalancerName string) {
119142
m.On("DescribeLoadBalancers", &elb.DescribeLoadBalancersInput{LoadBalancerNames: []*string{aws.String(loadBalancerName)}}).Return(&elb.DescribeLoadBalancersOutput{
120-
LoadBalancerDescriptions: []*elb.LoadBalancerDescription{{}},
143+
LoadBalancerDescriptions: []*elb.LoadBalancerDescription{
144+
{
145+
SecurityGroups: []*string{aws.String("sg-123456")},
146+
},
147+
},
121148
})
122149
}
123150

@@ -1790,6 +1817,9 @@ func TestDescribeLoadBalancerOnDelete(t *testing.T) {
17901817
awsServices := newMockedFakeAWSServices(TestClusterID)
17911818
c, _ := newAWSCloud(CloudConfig{}, awsServices)
17921819
awsServices.elb.(*MockedFakeELB).expectDescribeLoadBalancers("aid")
1820+
awsServices.ec2.(*MockedFakeEC2).expectDescribeSecurityGroupsByFilter(TestClusterID, "group-id", "sg-123456")
1821+
awsServices.ec2.(*MockedFakeEC2).expectDescribeSecurityGroupsAll(TestClusterID)
1822+
awsServices.ec2.(*MockedFakeEC2).expectDescribeSecurityGroupsByFilter(TestClusterID, "ip-permission.group-id", "sg-123456")
17931823

17941824
c.EnsureLoadBalancerDeleted(context.TODO(), TestClusterName, &v1.Service{ObjectMeta: metav1.ObjectMeta{Name: "myservice", UID: "id"}})
17951825
}
@@ -1798,6 +1828,8 @@ func TestDescribeLoadBalancerOnUpdate(t *testing.T) {
17981828
awsServices := newMockedFakeAWSServices(TestClusterID)
17991829
c, _ := newAWSCloud(CloudConfig{}, awsServices)
18001830
awsServices.elb.(*MockedFakeELB).expectDescribeLoadBalancers("aid")
1831+
awsServices.ec2.(*MockedFakeEC2).expectDescribeSecurityGroupsAll(TestClusterID)
1832+
awsServices.ec2.(*MockedFakeEC2).expectDescribeSecurityGroupsByFilter(TestClusterID, "ip-permission.group-id", "sg-123456")
18011833

18021834
c.UpdateLoadBalancer(context.TODO(), TestClusterName, &v1.Service{ObjectMeta: metav1.ObjectMeta{Name: "myservice", UID: "id"}}, []*v1.Node{})
18031835
}
@@ -3344,8 +3376,9 @@ func TestAzToRegion(t *testing.T) {
33443376

33453377
func TestCloud_sortELBSecurityGroupList(t *testing.T) {
33463378
type args struct {
3347-
securityGroupIDs []string
3348-
annotations map[string]string
3379+
securityGroupIDs []string
3380+
annotations map[string]string
3381+
taggedLBSecurityGroups map[string]struct{}
33493382
}
33503383
tests := []struct {
33513384
name string
@@ -3391,11 +3424,21 @@ func TestCloud_sortELBSecurityGroupList(t *testing.T) {
33913424
},
33923425
wantSecurityGroupIDs: []string{"sg-3", "sg-2", "sg-1", "sg-4", "sg-6", "sg-5"},
33933426
},
3427+
{
3428+
name: "with an untagged, and unknown security group",
3429+
args: args{
3430+
securityGroupIDs: []string{"sg-2", "sg-1"},
3431+
taggedLBSecurityGroups: map[string]struct{}{
3432+
"sg-1": {},
3433+
},
3434+
},
3435+
wantSecurityGroupIDs: []string{"sg-1", "sg-2"},
3436+
},
33943437
}
33953438
for _, tt := range tests {
33963439
t.Run(tt.name, func(t *testing.T) {
33973440
c := &Cloud{}
3398-
c.sortELBSecurityGroupList(tt.args.securityGroupIDs, tt.args.annotations)
3441+
c.sortELBSecurityGroupList(tt.args.securityGroupIDs, tt.args.annotations, tt.args.taggedLBSecurityGroups)
33993442
assert.Equal(t, tt.wantSecurityGroupIDs, tt.args.securityGroupIDs)
34003443
})
34013444
}

0 commit comments

Comments
 (0)