github.com/openshift/installer@v1.4.17/pkg/infrastructure/openstack/preprovision/securitygroups.go (about)

     1  package preprovision
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  
     7  	"github.com/gophercloud/gophercloud/v2/openstack/networking/v2/extensions/attributestags"
     8  	"github.com/gophercloud/gophercloud/v2/openstack/networking/v2/extensions/security/groups"
     9  	"github.com/gophercloud/gophercloud/v2/openstack/networking/v2/extensions/security/rules"
    10  	"github.com/sirupsen/logrus"
    11  
    12  	"github.com/openshift/installer/pkg/asset/installconfig"
    13  	openstackdefaults "github.com/openshift/installer/pkg/types/openstack/defaults"
    14  )
    15  
    16  const description = "Created By OpenShift Installer"
    17  
    18  type protocol uint8
    19  
    20  const (
    21  	_ protocol = 1 << iota
    22  	tcp
    23  	udp
    24  	icmp
    25  	esp
    26  	vrrp
    27  )
    28  
    29  func (p protocol) Protocols() []rules.RuleProtocol {
    30  	protocols := make([]rules.RuleProtocol, 0, 2)
    31  	if p&tcp == tcp {
    32  		protocols = append(protocols, rules.ProtocolTCP)
    33  	}
    34  	if p&udp == udp {
    35  		protocols = append(protocols, rules.ProtocolUDP)
    36  	}
    37  	if p&icmp == icmp {
    38  		protocols = append(protocols, rules.ProtocolICMP)
    39  	}
    40  	if p&esp == esp {
    41  		protocols = append(protocols, rules.ProtocolESP)
    42  	}
    43  	if p&vrrp == vrrp {
    44  		protocols = append(protocols, rules.RuleProtocol("112"))
    45  	}
    46  	return protocols
    47  }
    48  
    49  // SecurityGroups creates the master and worker security groups with the security group rules.
    50  func SecurityGroups(ctx context.Context, installConfig *installconfig.InstallConfig, infraID string, mastersSchedulable bool) error {
    51  	networkClient, err := openstackdefaults.NewServiceClient(ctx, "network", openstackdefaults.DefaultClientOpts(installConfig.Config.Platform.OpenStack.Cloud))
    52  	if err != nil {
    53  		return err
    54  	}
    55  
    56  	logrus.Debugf("Creating the security groups")
    57  	var masterGroup, workerGroup *groups.SecGroup
    58  	{
    59  		masterGroup, err = groups.Create(ctx, networkClient, groups.CreateOpts{
    60  			Name:        infraID + "-master",
    61  			Description: description,
    62  		}).Extract()
    63  		if err != nil {
    64  			return fmt.Errorf("failed to create the Control plane security group: %w", err)
    65  		}
    66  
    67  		// The Neutron call to add a tag
    68  		// (https://docs.openstack.org/api-ref/network/v2/#add-a-tag)
    69  		// doesn't accept all special characters. Here we use the
    70  		// "replace-all-tags" call instead, because it accepts a more
    71  		// robust JSON body.
    72  		//
    73  		// see: https://bugzilla.redhat.com/show_bug.cgi?id=2299208
    74  		if _, err := attributestags.ReplaceAll(ctx, networkClient, "security-groups", masterGroup.ID, attributestags.ReplaceAllOpts{
    75  			Tags: []string{"openshiftClusterID=" + infraID},
    76  		}).Extract(); err != nil {
    77  			return fmt.Errorf("failed to tag the Control plane security group: %w", err)
    78  		}
    79  
    80  		workerGroup, err = groups.Create(ctx, networkClient, groups.CreateOpts{
    81  			Name:        infraID + "-worker",
    82  			Description: description,
    83  		}).Extract()
    84  		if err != nil {
    85  			return fmt.Errorf("failed to create the Compute security group: %w", err)
    86  		}
    87  
    88  		// See comment above
    89  		if _, err := attributestags.ReplaceAll(ctx, networkClient, "security-groups", workerGroup.ID, attributestags.ReplaceAllOpts{
    90  			Tags: []string{"openshiftClusterID=" + infraID},
    91  		}).Extract(); err != nil {
    92  			return fmt.Errorf("failed to tag the Compute security group: %w", err)
    93  		}
    94  	}
    95  
    96  	logrus.Debugf("Creating the security group rules")
    97  	var (
    98  		machineV4CIDRs = make([]string, 0, len(installConfig.Config.Networking.MachineNetwork))
    99  		machineV6CIDRs = make([]string, 0, len(installConfig.Config.Networking.MachineNetwork))
   100  	)
   101  	for _, network := range installConfig.Config.Networking.MachineNetwork {
   102  		if network.CIDR.IPNet.IP.To4() != nil {
   103  			machineV4CIDRs = append(machineV4CIDRs, network.CIDR.IPNet.String())
   104  		} else {
   105  			machineV6CIDRs = append(machineV6CIDRs, network.CIDR.IPNet.String())
   106  		}
   107  	}
   108  
   109  	type service struct {
   110  		protocol
   111  		minPort int
   112  		maxPort int
   113  	}
   114  
   115  	var (
   116  		serviceAPI           = service{tcp | udp, 6443, 6443}
   117  		serviceDNS           = service{tcp | udp, 53, 53}
   118  		serviceESP           = service{protocol: esp}
   119  		serviceETCD          = service{tcp, 2379, 2380}
   120  		serviceGeneve        = service{udp, 6081, 6081}
   121  		serviceHTTP          = service{tcp, 80, 80}
   122  		serviceHTTPS         = service{tcp, 443, 443}
   123  		serviceICMP          = service{protocol: icmp}
   124  		serviceIKE           = service{udp, 500, 500}
   125  		serviceIKENat        = service{udp, 4500, 4500}
   126  		serviceInternal      = service{tcp | udp, 9000, 9999}
   127  		serviceKCM           = service{tcp, 10257, 10257}
   128  		serviceKubeScheduler = service{tcp, 10259, 10259}
   129  		serviceKubelet       = service{tcp, 10250, 10250}
   130  		serviceMCS           = service{tcp, 22623, 22623}
   131  		serviceNodeport      = service{tcp | udp, 30000, 32767}
   132  		serviceOVNDB         = service{tcp, 6641, 6642}
   133  		serviceRouter        = service{tcp, 1936, 1936}
   134  		serviceSSH           = service{tcp, 22, 22}
   135  		serviceVRRP          = service{protocol: vrrp}
   136  		serviceVXLAN         = service{udp, 4789, 4789}
   137  	)
   138  
   139  	addRules := func(ctx context.Context, ch chan<- rules.CreateOpts, securityGroupID string, s service, ipVersion rules.RuleEtherType, remoteCIDRs []string) {
   140  		for _, proto := range s.Protocols() {
   141  			for _, remoteCIDR := range remoteCIDRs {
   142  				select {
   143  				case ch <- rules.CreateOpts{
   144  					Direction:      rules.DirIngress,
   145  					Description:    description,
   146  					EtherType:      ipVersion,
   147  					SecGroupID:     securityGroupID,
   148  					PortRangeMax:   s.maxPort,
   149  					PortRangeMin:   s.minPort,
   150  					Protocol:       proto,
   151  					RemoteIPPrefix: remoteCIDR,
   152  				}:
   153  				case <-ctx.Done():
   154  					return
   155  				}
   156  			}
   157  		}
   158  	}
   159  
   160  	ctx, cancel := context.WithCancel(ctx)
   161  	defer cancel()
   162  
   163  	// TODO(mandre) Explicitly enable egress
   164  
   165  	r := make(chan rules.CreateOpts)
   166  	go func() {
   167  		defer close(r)
   168  
   169  		// In this loop: security groups with a catch-all remote IP
   170  		for ipVersion, anyIP := range map[rules.RuleEtherType][]string{
   171  			rules.EtherType4: {"0.0.0.0/0"},
   172  			rules.EtherType6: func() []string {
   173  				switch len(machineV6CIDRs) {
   174  				case 0:
   175  					return []string{}
   176  				default:
   177  					return []string{"::/0"}
   178  				}
   179  			}(),
   180  		} {
   181  			addRules(ctx, r, masterGroup.ID, serviceAPI, ipVersion, anyIP)
   182  			addRules(ctx, r, masterGroup.ID, serviceICMP, ipVersion, anyIP)
   183  			addRules(ctx, r, workerGroup.ID, serviceHTTP, ipVersion, anyIP)
   184  			addRules(ctx, r, workerGroup.ID, serviceHTTPS, ipVersion, anyIP)
   185  			addRules(ctx, r, workerGroup.ID, serviceICMP, ipVersion, anyIP)
   186  			if mastersSchedulable {
   187  				addRules(ctx, r, masterGroup.ID, serviceHTTP, ipVersion, anyIP)
   188  				addRules(ctx, r, masterGroup.ID, serviceHTTPS, ipVersion, anyIP)
   189  			}
   190  		}
   191  
   192  		// In this loop: security groups with the machine CIDR as remote IPs
   193  		for ipVersion, CIDRs := range map[rules.RuleEtherType][]string{
   194  			rules.EtherType4: machineV4CIDRs,
   195  			rules.EtherType6: machineV6CIDRs,
   196  		} {
   197  			// In this loop: rules that equally apply to masters and workers
   198  			for _, groupID := range [...]string{masterGroup.ID, workerGroup.ID} {
   199  				addRules(ctx, r, groupID, serviceESP, ipVersion, CIDRs)
   200  				addRules(ctx, r, groupID, serviceGeneve, ipVersion, CIDRs)
   201  				addRules(ctx, r, groupID, serviceIKE, ipVersion, CIDRs)
   202  				addRules(ctx, r, groupID, serviceInternal, ipVersion, CIDRs)
   203  				addRules(ctx, r, groupID, serviceKubelet, ipVersion, CIDRs)
   204  				addRules(ctx, r, groupID, serviceNodeport, ipVersion, CIDRs)
   205  				addRules(ctx, r, groupID, serviceSSH, ipVersion, CIDRs)
   206  				addRules(ctx, r, groupID, serviceVRRP, ipVersion, CIDRs)
   207  				addRules(ctx, r, groupID, serviceVXLAN, ipVersion, CIDRs)
   208  			}
   209  
   210  			addRules(ctx, r, masterGroup.ID, serviceDNS, ipVersion, CIDRs)
   211  			addRules(ctx, r, masterGroup.ID, serviceETCD, ipVersion, CIDRs)
   212  			addRules(ctx, r, masterGroup.ID, serviceKCM, ipVersion, CIDRs)
   213  			addRules(ctx, r, masterGroup.ID, serviceKubeScheduler, ipVersion, CIDRs)
   214  			addRules(ctx, r, masterGroup.ID, serviceMCS, ipVersion, CIDRs)
   215  			addRules(ctx, r, masterGroup.ID, serviceOVNDB, ipVersion, CIDRs)
   216  			addRules(ctx, r, workerGroup.ID, serviceRouter, ipVersion, CIDRs)
   217  			if mastersSchedulable {
   218  				addRules(ctx, r, masterGroup.ID, serviceRouter, ipVersion, CIDRs)
   219  			}
   220  		}
   221  
   222  		// IPv4-only rules
   223  		addRules(ctx, r, masterGroup.ID, serviceIKENat, rules.EtherType4, machineV4CIDRs)
   224  		addRules(ctx, r, workerGroup.ID, serviceIKENat, rules.EtherType4, machineV4CIDRs)
   225  	}()
   226  
   227  	for ruleCreateOpts := range r {
   228  		if _, err := rules.Create(ctx, networkClient, ruleCreateOpts).Extract(); err != nil {
   229  			return fmt.Errorf("failed to create the security group rule on group %q for %s %s on ports %d-%d: %w", ruleCreateOpts.SecGroupID, ruleCreateOpts.EtherType, ruleCreateOpts.Protocol, ruleCreateOpts.PortRangeMin, ruleCreateOpts.PortRangeMax, err)
   230  		}
   231  	}
   232  	return nil
   233  }