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 }