sigs.k8s.io/cluster-api-provider-aws@v1.5.5/api/v1beta1/network_types.go (about)

     1  /*
     2  Copyright 2021 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  	http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package v1beta1
    18  
    19  import (
    20  	"fmt"
    21  	"sort"
    22  	"time"
    23  )
    24  
    25  // NetworkStatus encapsulates AWS networking resources.
    26  type NetworkStatus struct {
    27  	// SecurityGroups is a map from the role/kind of the security group to its unique name, if any.
    28  	SecurityGroups map[SecurityGroupRole]SecurityGroup `json:"securityGroups,omitempty"`
    29  
    30  	// APIServerELB is the Kubernetes api server classic load balancer.
    31  	APIServerELB ClassicELB `json:"apiServerElb,omitempty"`
    32  }
    33  
    34  // ClassicELBScheme defines the scheme of a classic load balancer.
    35  type ClassicELBScheme string
    36  
    37  var (
    38  	// ClassicELBSchemeInternetFacing defines an internet-facing, publicly
    39  	// accessible AWS Classic ELB scheme.
    40  	ClassicELBSchemeInternetFacing = ClassicELBScheme("internet-facing")
    41  
    42  	// ClassicELBSchemeInternal defines an internal-only facing
    43  	// load balancer internal to an ELB.
    44  	ClassicELBSchemeInternal = ClassicELBScheme("internal")
    45  
    46  	// ClassicELBSchemeIncorrectInternetFacing was inaccurately used to define an internet-facing LB in v0.6 releases > v0.6.6 and v0.7.0 release.
    47  	ClassicELBSchemeIncorrectInternetFacing = ClassicELBScheme("Internet-facing")
    48  )
    49  
    50  func (e ClassicELBScheme) String() string {
    51  	return string(e)
    52  }
    53  
    54  // ClassicELBProtocol defines listener protocols for a classic load balancer.
    55  type ClassicELBProtocol string
    56  
    57  func (e ClassicELBProtocol) String() string {
    58  	return string(e)
    59  }
    60  
    61  var (
    62  	// ClassicELBProtocolTCP defines the ELB API string representing the TCP protocol.
    63  	ClassicELBProtocolTCP = ClassicELBProtocol("TCP")
    64  
    65  	// ClassicELBProtocolSSL defines the ELB API string representing the TLS protocol.
    66  	ClassicELBProtocolSSL = ClassicELBProtocol("SSL")
    67  
    68  	// ClassicELBProtocolHTTP defines the ELB API string representing the HTTP protocol at L7.
    69  	ClassicELBProtocolHTTP = ClassicELBProtocol("HTTP")
    70  
    71  	// ClassicELBProtocolHTTPS defines the ELB API string representing the HTTP protocol at L7.
    72  	ClassicELBProtocolHTTPS = ClassicELBProtocol("HTTPS")
    73  )
    74  
    75  // ClassicELB defines an AWS classic load balancer.
    76  type ClassicELB struct {
    77  	// The name of the load balancer. It must be unique within the set of load balancers
    78  	// defined in the region. It also serves as identifier.
    79  	// +optional
    80  	Name string `json:"name,omitempty"`
    81  
    82  	// DNSName is the dns name of the load balancer.
    83  	DNSName string `json:"dnsName,omitempty"`
    84  
    85  	// Scheme is the load balancer scheme, either internet-facing or private.
    86  	Scheme ClassicELBScheme `json:"scheme,omitempty"`
    87  
    88  	// AvailabilityZones is an array of availability zones in the VPC attached to the load balancer.
    89  	AvailabilityZones []string `json:"availabilityZones,omitempty"`
    90  
    91  	// SubnetIDs is an array of subnets in the VPC attached to the load balancer.
    92  	SubnetIDs []string `json:"subnetIds,omitempty"`
    93  
    94  	// SecurityGroupIDs is an array of security groups assigned to the load balancer.
    95  	SecurityGroupIDs []string `json:"securityGroupIds,omitempty"`
    96  
    97  	// Listeners is an array of classic elb listeners associated with the load balancer. There must be at least one.
    98  	Listeners []ClassicELBListener `json:"listeners,omitempty"`
    99  
   100  	// HealthCheck is the classic elb health check associated with the load balancer.
   101  	HealthCheck *ClassicELBHealthCheck `json:"healthChecks,omitempty"`
   102  
   103  	// Attributes defines extra attributes associated with the load balancer.
   104  	Attributes ClassicELBAttributes `json:"attributes,omitempty"`
   105  
   106  	// Tags is a map of tags associated with the load balancer.
   107  	Tags map[string]string `json:"tags,omitempty"`
   108  }
   109  
   110  // IsUnmanaged returns true if the Classic ELB is unmanaged.
   111  func (b *ClassicELB) IsUnmanaged(clusterName string) bool {
   112  	return b.Name != "" && !Tags(b.Tags).HasOwned(clusterName)
   113  }
   114  
   115  // IsManaged returns true if Classic ELB is managed.
   116  func (b *ClassicELB) IsManaged(clusterName string) bool {
   117  	return !b.IsUnmanaged(clusterName)
   118  }
   119  
   120  // ClassicELBAttributes defines extra attributes associated with a classic load balancer.
   121  type ClassicELBAttributes struct {
   122  	// IdleTimeout is time that the connection is allowed to be idle (no data
   123  	// has been sent over the connection) before it is closed by the load balancer.
   124  	IdleTimeout time.Duration `json:"idleTimeout,omitempty"`
   125  
   126  	// CrossZoneLoadBalancing enables the classic load balancer load balancing.
   127  	// +optional
   128  	CrossZoneLoadBalancing bool `json:"crossZoneLoadBalancing,omitempty"`
   129  }
   130  
   131  // ClassicELBListener defines an AWS classic load balancer listener.
   132  type ClassicELBListener struct {
   133  	Protocol         ClassicELBProtocol `json:"protocol"`
   134  	Port             int64              `json:"port"`
   135  	InstanceProtocol ClassicELBProtocol `json:"instanceProtocol"`
   136  	InstancePort     int64              `json:"instancePort"`
   137  }
   138  
   139  // ClassicELBHealthCheck defines an AWS classic load balancer health check.
   140  type ClassicELBHealthCheck struct {
   141  	Target             string        `json:"target"`
   142  	Interval           time.Duration `json:"interval"`
   143  	Timeout            time.Duration `json:"timeout"`
   144  	HealthyThreshold   int64         `json:"healthyThreshold"`
   145  	UnhealthyThreshold int64         `json:"unhealthyThreshold"`
   146  }
   147  
   148  // NetworkSpec encapsulates all things related to AWS network.
   149  type NetworkSpec struct {
   150  	// VPC configuration.
   151  	// +optional
   152  	VPC VPCSpec `json:"vpc,omitempty"`
   153  
   154  	// Subnets configuration.
   155  	// +optional
   156  	Subnets Subnets `json:"subnets,omitempty"`
   157  
   158  	// CNI configuration
   159  	// +optional
   160  	CNI *CNISpec `json:"cni,omitempty"`
   161  
   162  	// SecurityGroupOverrides is an optional set of security groups to use for cluster instances
   163  	// This is optional - if not provided new security groups will be created for the cluster
   164  	// +optional
   165  	SecurityGroupOverrides map[SecurityGroupRole]string `json:"securityGroupOverrides,omitempty"`
   166  }
   167  
   168  // VPCSpec configures an AWS VPC.
   169  type VPCSpec struct {
   170  	// ID is the vpc-id of the VPC this provider should use to create resources.
   171  	ID string `json:"id,omitempty"`
   172  
   173  	// CidrBlock is the CIDR block to be used when the provider creates a managed VPC.
   174  	// Defaults to 10.0.0.0/16.
   175  	CidrBlock string `json:"cidrBlock,omitempty"`
   176  
   177  	// InternetGatewayID is the id of the internet gateway associated with the VPC.
   178  	// +optional
   179  	InternetGatewayID *string `json:"internetGatewayId,omitempty"`
   180  
   181  	// Tags is a collection of tags describing the resource.
   182  	Tags Tags `json:"tags,omitempty"`
   183  
   184  	// AvailabilityZoneUsageLimit specifies the maximum number of availability zones (AZ) that
   185  	// should be used in a region when automatically creating subnets. If a region has more
   186  	// than this number of AZs then this number of AZs will be picked randomly when creating
   187  	// default subnets. Defaults to 3
   188  	// +kubebuilder:default=3
   189  	// +kubebuilder:validation:Minimum=1
   190  	AvailabilityZoneUsageLimit *int `json:"availabilityZoneUsageLimit,omitempty"`
   191  
   192  	// AvailabilityZoneSelection specifies how AZs should be selected if there are more AZs
   193  	// in a region than specified by AvailabilityZoneUsageLimit. There are 2 selection schemes:
   194  	// Ordered - selects based on alphabetical order
   195  	// Random - selects AZs randomly in a region
   196  	// Defaults to Ordered
   197  	// +kubebuilder:default=Ordered
   198  	// +kubebuilder:validation:Enum=Ordered;Random
   199  	AvailabilityZoneSelection *AZSelectionScheme `json:"availabilityZoneSelection,omitempty"`
   200  }
   201  
   202  // String returns a string representation of the VPC.
   203  func (v *VPCSpec) String() string {
   204  	return fmt.Sprintf("id=%s", v.ID)
   205  }
   206  
   207  // IsUnmanaged returns true if the VPC is unmanaged.
   208  func (v *VPCSpec) IsUnmanaged(clusterName string) bool {
   209  	return v.ID != "" && !v.Tags.HasOwned(clusterName)
   210  }
   211  
   212  // IsManaged returns true if VPC is managed.
   213  func (v *VPCSpec) IsManaged(clusterName string) bool {
   214  	return !v.IsUnmanaged(clusterName)
   215  }
   216  
   217  // SubnetSpec configures an AWS Subnet.
   218  type SubnetSpec struct {
   219  	// ID defines a unique identifier to reference this resource.
   220  	ID string `json:"id,omitempty"`
   221  
   222  	// CidrBlock is the CIDR block to be used when the provider creates a managed VPC.
   223  	CidrBlock string `json:"cidrBlock,omitempty"`
   224  
   225  	// AvailabilityZone defines the availability zone to use for this subnet in the cluster's region.
   226  	AvailabilityZone string `json:"availabilityZone,omitempty"`
   227  
   228  	// IsPublic defines the subnet as a public subnet. A subnet is public when it is associated with a route table that has a route to an internet gateway.
   229  	// +optional
   230  	IsPublic bool `json:"isPublic"`
   231  
   232  	// RouteTableID is the routing table id associated with the subnet.
   233  	// +optional
   234  	RouteTableID *string `json:"routeTableId,omitempty"`
   235  
   236  	// NatGatewayID is the NAT gateway id associated with the subnet.
   237  	// Ignored unless the subnet is managed by the provider, in which case this is set on the public subnet where the NAT gateway resides. It is then used to determine routes for private subnets in the same AZ as the public subnet.
   238  	// +optional
   239  	NatGatewayID *string `json:"natGatewayId,omitempty"`
   240  
   241  	// Tags is a collection of tags describing the resource.
   242  	Tags Tags `json:"tags,omitempty"`
   243  }
   244  
   245  // String returns a string representation of the subnet.
   246  func (s *SubnetSpec) String() string {
   247  	return fmt.Sprintf("id=%s/az=%s/public=%v", s.ID, s.AvailabilityZone, s.IsPublic)
   248  }
   249  
   250  // Subnets is a slice of Subnet.
   251  type Subnets []SubnetSpec
   252  
   253  // ToMap returns a map from id to subnet.
   254  func (s Subnets) ToMap() map[string]*SubnetSpec {
   255  	res := make(map[string]*SubnetSpec)
   256  	for i := range s {
   257  		x := s[i]
   258  		res[x.ID] = &x
   259  	}
   260  	return res
   261  }
   262  
   263  // IDs returns a slice of the subnet ids.
   264  func (s Subnets) IDs() []string {
   265  	res := []string{}
   266  	for _, subnet := range s {
   267  		res = append(res, subnet.ID)
   268  	}
   269  	return res
   270  }
   271  
   272  // FindByID returns a single subnet matching the given id or nil.
   273  func (s Subnets) FindByID(id string) *SubnetSpec {
   274  	for _, x := range s {
   275  		if x.ID == id {
   276  			return &x
   277  		}
   278  	}
   279  
   280  	return nil
   281  }
   282  
   283  // FindEqual returns a subnet spec that is equal to the one passed in.
   284  // Two subnets are defined equal to each other if their id is equal
   285  // or if they are in the same vpc and the cidr block is the same.
   286  func (s Subnets) FindEqual(spec *SubnetSpec) *SubnetSpec {
   287  	for _, x := range s {
   288  		if (spec.ID != "" && x.ID == spec.ID) || (spec.CidrBlock == x.CidrBlock) {
   289  			return &x
   290  		}
   291  	}
   292  	return nil
   293  }
   294  
   295  // FilterPrivate returns a slice containing all subnets marked as private.
   296  func (s Subnets) FilterPrivate() (res Subnets) {
   297  	for _, x := range s {
   298  		if !x.IsPublic {
   299  			res = append(res, x)
   300  		}
   301  	}
   302  	return
   303  }
   304  
   305  // FilterPublic returns a slice containing all subnets marked as public.
   306  func (s Subnets) FilterPublic() (res Subnets) {
   307  	for _, x := range s {
   308  		if x.IsPublic {
   309  			res = append(res, x)
   310  		}
   311  	}
   312  	return
   313  }
   314  
   315  // FilterByZone returns a slice containing all subnets that live in the availability zone specified.
   316  func (s Subnets) FilterByZone(zone string) (res Subnets) {
   317  	for _, x := range s {
   318  		if x.AvailabilityZone == zone {
   319  			res = append(res, x)
   320  		}
   321  	}
   322  	return
   323  }
   324  
   325  // GetUniqueZones returns a slice containing the unique zones of the subnets.
   326  func (s Subnets) GetUniqueZones() []string {
   327  	keys := make(map[string]bool)
   328  	zones := []string{}
   329  	for _, x := range s {
   330  		if _, value := keys[x.AvailabilityZone]; !value {
   331  			keys[x.AvailabilityZone] = true
   332  			zones = append(zones, x.AvailabilityZone)
   333  		}
   334  	}
   335  	return zones
   336  }
   337  
   338  // CNISpec defines configuration for CNI.
   339  type CNISpec struct {
   340  	// CNIIngressRules specify rules to apply to control plane and worker node security groups.
   341  	// The source for the rule will be set to control plane and worker security group IDs.
   342  	CNIIngressRules CNIIngressRules `json:"cniIngressRules,omitempty"`
   343  }
   344  
   345  // CNIIngressRules is a slice of CNIIngressRule.
   346  type CNIIngressRules []CNIIngressRule
   347  
   348  // CNIIngressRule defines an AWS ingress rule for CNI requirements.
   349  type CNIIngressRule struct {
   350  	Description string                `json:"description"`
   351  	Protocol    SecurityGroupProtocol `json:"protocol"`
   352  	FromPort    int64                 `json:"fromPort"`
   353  	ToPort      int64                 `json:"toPort"`
   354  }
   355  
   356  // RouteTable defines an AWS routing table.
   357  type RouteTable struct {
   358  	ID string `json:"id"`
   359  }
   360  
   361  // SecurityGroupRole defines the unique role of a security group.
   362  type SecurityGroupRole string
   363  
   364  var (
   365  	// SecurityGroupBastion defines an SSH bastion role.
   366  	SecurityGroupBastion = SecurityGroupRole("bastion")
   367  
   368  	// SecurityGroupNode defines a Kubernetes workload node role.
   369  	SecurityGroupNode = SecurityGroupRole("node")
   370  
   371  	// SecurityGroupEKSNodeAdditional defines an extra node group from eks nodes.
   372  	SecurityGroupEKSNodeAdditional = SecurityGroupRole("node-eks-additional")
   373  
   374  	// SecurityGroupControlPlane defines a Kubernetes control plane node role.
   375  	SecurityGroupControlPlane = SecurityGroupRole("controlplane")
   376  
   377  	// SecurityGroupAPIServerLB defines a Kubernetes API Server Load Balancer role.
   378  	SecurityGroupAPIServerLB = SecurityGroupRole("apiserver-lb")
   379  
   380  	// SecurityGroupLB defines a container for the cloud provider to inject its load balancer ingress rules.
   381  	SecurityGroupLB = SecurityGroupRole("lb")
   382  )
   383  
   384  // SecurityGroup defines an AWS security group.
   385  type SecurityGroup struct {
   386  	// ID is a unique identifier.
   387  	ID string `json:"id"`
   388  
   389  	// Name is the security group name.
   390  	Name string `json:"name"`
   391  
   392  	// IngressRules is the inbound rules associated with the security group.
   393  	// +optional
   394  	IngressRules IngressRules `json:"ingressRule,omitempty"`
   395  
   396  	// Tags is a map of tags associated with the security group.
   397  	Tags Tags `json:"tags,omitempty"`
   398  }
   399  
   400  // String returns a string representation of the security group.
   401  func (s *SecurityGroup) String() string {
   402  	return fmt.Sprintf("id=%s/name=%s", s.ID, s.Name)
   403  }
   404  
   405  // SecurityGroupProtocol defines the protocol type for a security group rule.
   406  type SecurityGroupProtocol string
   407  
   408  var (
   409  	// SecurityGroupProtocolAll is a wildcard for all IP protocols.
   410  	SecurityGroupProtocolAll = SecurityGroupProtocol("-1")
   411  
   412  	// SecurityGroupProtocolIPinIP represents the IP in IP protocol in ingress rules.
   413  	SecurityGroupProtocolIPinIP = SecurityGroupProtocol("4")
   414  
   415  	// SecurityGroupProtocolTCP represents the TCP protocol in ingress rules.
   416  	SecurityGroupProtocolTCP = SecurityGroupProtocol("tcp")
   417  
   418  	// SecurityGroupProtocolUDP represents the UDP protocol in ingress rules.
   419  	SecurityGroupProtocolUDP = SecurityGroupProtocol("udp")
   420  
   421  	// SecurityGroupProtocolICMP represents the ICMP protocol in ingress rules.
   422  	SecurityGroupProtocolICMP = SecurityGroupProtocol("icmp")
   423  
   424  	// SecurityGroupProtocolICMPv6 represents the ICMPv6 protocol in ingress rules.
   425  	SecurityGroupProtocolICMPv6 = SecurityGroupProtocol("58")
   426  )
   427  
   428  // IngressRule defines an AWS ingress rule for security groups.
   429  type IngressRule struct {
   430  	Description string                `json:"description"`
   431  	Protocol    SecurityGroupProtocol `json:"protocol"`
   432  	FromPort    int64                 `json:"fromPort"`
   433  	ToPort      int64                 `json:"toPort"`
   434  
   435  	// List of CIDR blocks to allow access from. Cannot be specified with SourceSecurityGroupID.
   436  	// +optional
   437  	CidrBlocks []string `json:"cidrBlocks,omitempty"`
   438  
   439  	// The security group id to allow access from. Cannot be specified with CidrBlocks.
   440  	// +optional
   441  	SourceSecurityGroupIDs []string `json:"sourceSecurityGroupIds,omitempty"`
   442  }
   443  
   444  // String returns a string representation of the ingress rule.
   445  func (i *IngressRule) String() string {
   446  	return fmt.Sprintf("protocol=%s/range=[%d-%d]/description=%s", i.Protocol, i.FromPort, i.ToPort, i.Description)
   447  }
   448  
   449  // IngressRules is a slice of AWS ingress rules for security groups.
   450  type IngressRules []IngressRule
   451  
   452  // Difference returns the difference between this slice and the other slice.
   453  func (i IngressRules) Difference(o IngressRules) (out IngressRules) {
   454  	for index := range i {
   455  		x := i[index]
   456  		found := false
   457  		for oIndex := range o {
   458  			y := o[oIndex]
   459  			if x.Equals(&y) {
   460  				found = true
   461  				break
   462  			}
   463  		}
   464  
   465  		if !found {
   466  			out = append(out, x)
   467  		}
   468  	}
   469  
   470  	return
   471  }
   472  
   473  // Equals returns true if two IngressRule are equal.
   474  func (i *IngressRule) Equals(o *IngressRule) bool {
   475  	if len(i.CidrBlocks) != len(o.CidrBlocks) {
   476  		return false
   477  	}
   478  
   479  	sort.Strings(i.CidrBlocks)
   480  	sort.Strings(o.CidrBlocks)
   481  
   482  	for i, v := range i.CidrBlocks {
   483  		if v != o.CidrBlocks[i] {
   484  			return false
   485  		}
   486  	}
   487  
   488  	if len(i.SourceSecurityGroupIDs) != len(o.SourceSecurityGroupIDs) {
   489  		return false
   490  	}
   491  
   492  	sort.Strings(i.SourceSecurityGroupIDs)
   493  	sort.Strings(o.SourceSecurityGroupIDs)
   494  
   495  	for i, v := range i.SourceSecurityGroupIDs {
   496  		if v != o.SourceSecurityGroupIDs[i] {
   497  			return false
   498  		}
   499  	}
   500  
   501  	if i.Description != o.Description || i.Protocol != o.Protocol {
   502  		return false
   503  	}
   504  
   505  	// AWS seems to ignore the From/To port when set on protocols where it doesn't apply, but
   506  	// we avoid serializing it out for clarity's sake.
   507  	// See: https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_IpPermission.html
   508  	switch i.Protocol {
   509  	case SecurityGroupProtocolTCP,
   510  		SecurityGroupProtocolUDP,
   511  		SecurityGroupProtocolICMP,
   512  		SecurityGroupProtocolICMPv6:
   513  		return i.FromPort == o.FromPort && i.ToPort == o.ToPort
   514  	case SecurityGroupProtocolAll, SecurityGroupProtocolIPinIP:
   515  		// FromPort / ToPort are not applicable
   516  	}
   517  
   518  	return true
   519  }