Skip to content

Commit 23bb1df

Browse files
authored
manage-security-groups: Only add SGs to LB members (#2455) (#2466)
Previous code for manage-security-groups were adding the SGs to all the ports attached to the Node. That doesn't make a lot of sense, we only need this traffic opened to the LB members and we only add one port of the Node as the LB member. Moreover we've even tried to add SGs to the ports that had `port_security_enabled=false` which obviously failed. This patch makes sure that we only add the SG opening NodePort traffic to the port that is actually plugged into the LB. Moreover it adds a check for `port_security_enabled` to make sure that ports with it disabled are ignored.
1 parent b447f67 commit 23bb1df

File tree

3 files changed

+43
-9
lines changed

3 files changed

+43
-9
lines changed

pkg/openstack/loadbalancer.go

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -717,25 +717,52 @@ func getSubnetIDForLB(network *gophercloud.ServiceClient, node corev1.Node, pref
717717
return "", cpoerrors.ErrNotFound
718718
}
719719

720-
// applyNodeSecurityGroupIDForLB associates the security group with all the ports on the nodes.
721-
func applyNodeSecurityGroupIDForLB(network *gophercloud.ServiceClient, nodes []*corev1.Node, sg string) error {
720+
// isPortMember returns true if IP and subnetID are one of the FixedIPs on the port
721+
func isPortMember(port PortWithPortSecurity, IP string, subnetID string) bool {
722+
for _, fixedIP := range port.FixedIPs {
723+
if (subnetID == "" || subnetID == fixedIP.SubnetID) && IP == fixedIP.IPAddress {
724+
return true
725+
}
726+
}
727+
return false
728+
}
729+
730+
// applyNodeSecurityGroupIDForLB associates the security group with the ports being members of the LB on the nodes.
731+
func applyNodeSecurityGroupIDForLB(network *gophercloud.ServiceClient, svcConf *serviceConfig, nodes []*corev1.Node, sg string) error {
722732
for _, node := range nodes {
723733
serverID, _, err := instanceIDFromProviderID(node.Spec.ProviderID)
724734
if err != nil {
725735
return fmt.Errorf("error getting server ID from the node: %w", err)
726736
}
737+
738+
addr, _ := nodeAddressForLB(node, svcConf.preferredIPFamily)
739+
if addr == "" {
740+
// If node has no viable address let's ignore it.
741+
continue
742+
}
743+
727744
listOpts := neutronports.ListOpts{DeviceID: serverID}
728-
allPorts, err := openstackutil.GetPorts(network, listOpts)
745+
allPorts, err := openstackutil.GetPorts[PortWithPortSecurity](network, listOpts)
729746
if err != nil {
730747
return err
731748
}
732749

733750
for _, port := range allPorts {
751+
// You can't assign an SG to a port with port_security_enabled=false, skip them.
752+
if !port.PortSecurityEnabled {
753+
continue
754+
}
755+
734756
// If the Security Group is already present on the port, skip it.
735757
if slices.Contains(port.SecurityGroups, sg) {
736758
continue
737759
}
738760

761+
// Only add SGs to the port actually attached to the LB
762+
if !isPortMember(port, addr, svcConf.lbMemberSubnetID) {
763+
continue
764+
}
765+
739766
// Add the security group ID as a tag to the port in order to find all these ports when removing the security group.
740767
// We're doing that before actually applying the SG as if tagging would fail we wouldn't be able to find the port
741768
// when deleting the SG and operation would be stuck forever. It's better to find more ports than not all of them.
@@ -766,7 +793,7 @@ func applyNodeSecurityGroupIDForLB(network *gophercloud.ServiceClient, nodes []*
766793
func disassociateSecurityGroupForLB(network *gophercloud.ServiceClient, sg string) error {
767794
// Find all the ports that have the security group associated.
768795
listOpts := neutronports.ListOpts{TagsAny: sg}
769-
allPorts, err := openstackutil.GetPorts(network, listOpts)
796+
allPorts, err := openstackutil.GetPorts[neutronports.Port](network, listOpts)
770797
if err != nil {
771798
return err
772799
}
@@ -2353,7 +2380,7 @@ func (lbaas *LbaasV2) ensureAndUpdateOctaviaSecurityGroup(clusterName string, ap
23532380
}
23542381
}
23552382

2356-
if err := applyNodeSecurityGroupIDForLB(lbaas.network, nodes, lbSecGroupID); err != nil {
2383+
if err := applyNodeSecurityGroupIDForLB(lbaas.network, svcConf, nodes, lbSecGroupID); err != nil {
23572384
return err
23582385
}
23592386
return nil

pkg/openstack/openstack.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"github.com/gophercloud/gophercloud"
2828
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/availabilityzones"
2929
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
30+
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/portsecurity"
3031
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/trunk_details"
3132
neutronports "github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
3233
"github.com/spf13/pflag"
@@ -74,6 +75,11 @@ type PortWithTrunkDetails struct {
7475
trunk_details.TrunkDetailsExt
7576
}
7677

78+
type PortWithPortSecurity struct {
79+
neutronports.Port
80+
portsecurity.PortSecurityExt
81+
}
82+
7783
// LoadBalancer is used for creating and maintaining load balancers
7884
type LoadBalancer struct {
7985
secret *gophercloud.ServiceClient

pkg/util/openstack/network.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -140,15 +140,16 @@ func getSubnet(networkSubnet string, subnetList []subnets.Subnet) *subnets.Subne
140140
}
141141

142142
// GetPorts gets all the filtered ports.
143-
func GetPorts(client *gophercloud.ServiceClient, listOpts neutronports.ListOpts) ([]neutronports.Port, error) {
143+
func GetPorts[PortType interface{}](client *gophercloud.ServiceClient, listOpts neutronports.ListOpts) ([]PortType, error) {
144144
mc := metrics.NewMetricContext("port", "list")
145145
allPages, err := neutronports.List(client, listOpts).AllPages()
146146
if mc.ObserveRequest(err) != nil {
147-
return []neutronports.Port{}, err
147+
return []PortType{}, err
148148
}
149-
allPorts, err := neutronports.ExtractPorts(allPages)
149+
var allPorts []PortType
150+
err = neutronports.ExtractPortsInto(allPages, &allPorts)
150151
if err != nil {
151-
return []neutronports.Port{}, err
152+
return []PortType{}, err
152153
}
153154

154155
return allPorts, nil

0 commit comments

Comments
 (0)