github.com/cilium/cilium@v1.16.2/operator/pkg/model/translation/ingress/dedicated_ingress_fixture_test.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package ingress 5 6 import ( 7 "fmt" 8 "syscall" 9 10 envoy_config_cluster_v3 "github.com/cilium/proxy/go/envoy/config/cluster/v3" 11 envoy_config_core_v3 "github.com/cilium/proxy/go/envoy/config/core/v3" 12 envoy_config_listener "github.com/cilium/proxy/go/envoy/config/listener/v3" 13 envoy_config_route_v3 "github.com/cilium/proxy/go/envoy/config/route/v3" 14 grpc_stats_v3 "github.com/cilium/proxy/go/envoy/extensions/filters/http/grpc_stats/v3" 15 grpc_web_v3 "github.com/cilium/proxy/go/envoy/extensions/filters/http/grpc_web/v3" 16 envoy_extensions_filters_http_router_v3 "github.com/cilium/proxy/go/envoy/extensions/filters/http/router/v3" 17 envoy_extensions_listener_proxy_protocol_v3 "github.com/cilium/proxy/go/envoy/extensions/filters/listener/proxy_protocol/v3" 18 envoy_extensions_listener_tls_inspector_v3 "github.com/cilium/proxy/go/envoy/extensions/filters/listener/tls_inspector/v3" 19 http_connection_manager_v3 "github.com/cilium/proxy/go/envoy/extensions/filters/network/http_connection_manager/v3" 20 envoy_extensions_transport_sockets_tls_v3 "github.com/cilium/proxy/go/envoy/extensions/transport_sockets/tls/v3" 21 envoy_upstreams_http_v3 "github.com/cilium/proxy/go/envoy/extensions/upstreams/http/v3" 22 envoy_type_matcher_v3 "github.com/cilium/proxy/go/envoy/type/matcher/v3" 23 "google.golang.org/protobuf/proto" 24 "google.golang.org/protobuf/types/known/anypb" 25 "google.golang.org/protobuf/types/known/durationpb" 26 "google.golang.org/protobuf/types/known/wrapperspb" 27 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 28 29 "github.com/cilium/cilium/operator/pkg/model" 30 ciliumv2 "github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2" 31 slim_metav1 "github.com/cilium/cilium/pkg/k8s/slim/k8s/apis/meta/v1" 32 ) 33 34 var socketOptions = []*envoy_config_core_v3.SocketOption{ 35 { 36 Description: "Enable TCP keep-alive (default to enabled)", 37 Level: syscall.SOL_SOCKET, 38 Name: syscall.SO_KEEPALIVE, 39 Value: &envoy_config_core_v3.SocketOption_IntValue{ 40 IntValue: 1, 41 }, 42 State: envoy_config_core_v3.SocketOption_STATE_PREBIND, 43 }, 44 { 45 Description: "TCP keep-alive idle time (in seconds) (defaults to 10s)", 46 Level: syscall.IPPROTO_TCP, 47 Name: syscall.TCP_KEEPIDLE, 48 Value: &envoy_config_core_v3.SocketOption_IntValue{ 49 IntValue: 10, 50 }, 51 State: envoy_config_core_v3.SocketOption_STATE_PREBIND, 52 }, 53 { 54 Description: "TCP keep-alive probe intervals (in seconds) (defaults to 5s)", 55 Level: syscall.IPPROTO_TCP, 56 Name: syscall.TCP_KEEPINTVL, 57 Value: &envoy_config_core_v3.SocketOption_IntValue{ 58 IntValue: 5, 59 }, 60 State: envoy_config_core_v3.SocketOption_STATE_PREBIND, 61 }, 62 { 63 Description: "TCP keep-alive probe max failures.", 64 Level: syscall.IPPROTO_TCP, 65 Name: syscall.TCP_KEEPCNT, 66 Value: &envoy_config_core_v3.SocketOption_IntValue{ 67 IntValue: 10, 68 }, 69 State: envoy_config_core_v3.SocketOption_STATE_PREBIND, 70 }, 71 } 72 73 func toEnvoyCluster(namespace, name, port string) *envoy_config_cluster_v3.Cluster { 74 return &envoy_config_cluster_v3.Cluster{ 75 Name: fmt.Sprintf("%s:%s:%s", namespace, name, port), 76 EdsClusterConfig: &envoy_config_cluster_v3.Cluster_EdsClusterConfig{ 77 ServiceName: fmt.Sprintf("%s/%s:%s", namespace, name, port), 78 }, 79 TypedExtensionProtocolOptions: map[string]*anypb.Any{ 80 "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": toAny(&envoy_upstreams_http_v3.HttpProtocolOptions{ 81 CommonHttpProtocolOptions: &envoy_config_core_v3.HttpProtocolOptions{ 82 IdleTimeout: &durationpb.Duration{Seconds: int64(60)}, 83 }, 84 UpstreamProtocolOptions: &envoy_upstreams_http_v3.HttpProtocolOptions_UseDownstreamProtocolConfig{ 85 UseDownstreamProtocolConfig: &envoy_upstreams_http_v3.HttpProtocolOptions_UseDownstreamHttpConfig{ 86 Http2ProtocolOptions: &envoy_config_core_v3.Http2ProtocolOptions{}, 87 }, 88 }, 89 }), 90 }, 91 ClusterDiscoveryType: &envoy_config_cluster_v3.Cluster_Type{ 92 Type: envoy_config_cluster_v3.Cluster_EDS, 93 }, 94 ConnectTimeout: &durationpb.Duration{Seconds: int64(5)}, 95 LbPolicy: envoy_config_cluster_v3.Cluster_ROUND_ROBIN, 96 OutlierDetection: &envoy_config_cluster_v3.OutlierDetection{ 97 SplitExternalLocalOriginErrors: true, 98 }, 99 } 100 } 101 102 func toRouteAction(namespace, name, port string) *envoy_config_route_v3.Route_Route { 103 return &envoy_config_route_v3.Route_Route{ 104 Route: &envoy_config_route_v3.RouteAction{ 105 ClusterSpecifier: &envoy_config_route_v3.RouteAction_Cluster{ 106 Cluster: fmt.Sprintf("%s:%s:%s", namespace, name, port), 107 }, 108 MaxStreamDuration: &envoy_config_route_v3.RouteAction_MaxStreamDuration{ 109 MaxStreamDuration: &durationpb.Duration{Seconds: 0}, 110 }, 111 }, 112 } 113 } 114 115 func toHTTPSRedirectAction() *envoy_config_route_v3.Route_Redirect { 116 return &envoy_config_route_v3.Route_Redirect{ 117 Redirect: &envoy_config_route_v3.RedirectAction{ 118 SchemeRewriteSpecifier: &envoy_config_route_v3.RedirectAction_HttpsRedirect{ 119 HttpsRedirect: true, 120 }, 121 }, 122 } 123 } 124 125 func toListenerFilter(name string) *envoy_config_listener.Filter { 126 return &envoy_config_listener.Filter{ 127 Name: "envoy.filters.network.http_connection_manager", 128 ConfigType: &envoy_config_listener.Filter_TypedConfig{ 129 TypedConfig: toAny(&http_connection_manager_v3.HttpConnectionManager{ 130 StatPrefix: name, 131 RouteSpecifier: &http_connection_manager_v3.HttpConnectionManager_Rds{ 132 Rds: &http_connection_manager_v3.Rds{RouteConfigName: name}, 133 }, 134 UpgradeConfigs: []*http_connection_manager_v3.HttpConnectionManager_UpgradeConfig{ 135 {UpgradeType: "websocket"}, 136 }, 137 UseRemoteAddress: &wrapperspb.BoolValue{Value: true}, 138 SkipXffAppend: false, 139 HttpFilters: []*http_connection_manager_v3.HttpFilter{ 140 { 141 Name: "envoy.filters.http.grpc_web", 142 ConfigType: &http_connection_manager_v3.HttpFilter_TypedConfig{ 143 TypedConfig: toAny(&grpc_web_v3.GrpcWeb{}), 144 }, 145 }, 146 { 147 Name: "envoy.filters.http.grpc_stats", 148 ConfigType: &http_connection_manager_v3.HttpFilter_TypedConfig{ 149 TypedConfig: toAny(&grpc_stats_v3.FilterConfig{ 150 EmitFilterState: true, 151 EnableUpstreamStats: true, 152 }), 153 }, 154 }, 155 { 156 Name: "envoy.filters.http.router", 157 ConfigType: &http_connection_manager_v3.HttpFilter_TypedConfig{ 158 TypedConfig: toAny(&envoy_extensions_filters_http_router_v3.Router{}), 159 }, 160 }, 161 }, 162 CommonHttpProtocolOptions: &envoy_config_core_v3.HttpProtocolOptions{ 163 MaxStreamDuration: &durationpb.Duration{ 164 Seconds: 0, 165 }, 166 }, 167 }), 168 }, 169 } 170 } 171 172 func toSecureListenerFilterChain(serverNames []string, certName string) *envoy_config_listener.FilterChain { 173 return &envoy_config_listener.FilterChain{ 174 FilterChainMatch: &envoy_config_listener.FilterChainMatch{ 175 ServerNames: serverNames, 176 TransportProtocol: "tls", 177 }, 178 Filters: []*envoy_config_listener.Filter{ 179 toListenerFilter("listener-secure"), 180 }, 181 TransportSocket: &envoy_config_core_v3.TransportSocket{ 182 Name: "envoy.transport_sockets.tls", 183 ConfigType: &envoy_config_core_v3.TransportSocket_TypedConfig{ 184 TypedConfig: toAny(&envoy_extensions_transport_sockets_tls_v3.DownstreamTlsContext{ 185 CommonTlsContext: &envoy_extensions_transport_sockets_tls_v3.CommonTlsContext{ 186 TlsCertificateSdsSecretConfigs: []*envoy_extensions_transport_sockets_tls_v3.SdsSecretConfig{ 187 { 188 Name: certName, 189 }, 190 }, 191 }, 192 }), 193 }, 194 }, 195 } 196 } 197 198 func toInsecureListenerFilterChain() *envoy_config_listener.FilterChain { 199 return &envoy_config_listener.FilterChain{ 200 FilterChainMatch: &envoy_config_listener.FilterChainMatch{ 201 TransportProtocol: "raw_buffer", 202 }, 203 Filters: []*envoy_config_listener.Filter{ 204 toListenerFilter("listener-insecure"), 205 }, 206 } 207 } 208 209 func toHTTPListenerXDSResource(proxyProtocol bool, address *string, port *uint32) *anypb.Any { 210 listenerFilters := []*envoy_config_listener.ListenerFilter{ 211 { 212 Name: "envoy.filters.listener.tls_inspector", 213 ConfigType: &envoy_config_listener.ListenerFilter_TypedConfig{ 214 TypedConfig: toAny(&envoy_extensions_listener_tls_inspector_v3.TlsInspector{}), 215 }, 216 }, 217 } 218 if proxyProtocol { 219 proxyListener := &envoy_config_listener.ListenerFilter{ 220 Name: "envoy.filters.listener.proxy_protocol", 221 ConfigType: &envoy_config_listener.ListenerFilter_TypedConfig{ 222 TypedConfig: toAny(&envoy_extensions_listener_proxy_protocol_v3.ProxyProtocol{}), 223 }, 224 } 225 listenerFilters = append([]*envoy_config_listener.ListenerFilter{proxyListener}, listenerFilters...) 226 } 227 l := &envoy_config_listener.Listener{ 228 Name: "listener", 229 FilterChains: []*envoy_config_listener.FilterChain{ 230 toInsecureListenerFilterChain(), 231 }, 232 ListenerFilters: listenerFilters, 233 SocketOptions: socketOptions, 234 } 235 236 if address != nil && port != nil { 237 l.Address = &envoy_config_core_v3.Address{ 238 Address: &envoy_config_core_v3.Address_SocketAddress{ 239 SocketAddress: &envoy_config_core_v3.SocketAddress{ 240 Protocol: envoy_config_core_v3.SocketAddress_TCP, 241 Address: *address, 242 PortSpecifier: &envoy_config_core_v3.SocketAddress_PortValue{ 243 PortValue: *port, 244 }, 245 }, 246 }, 247 } 248 } 249 250 return toAny(l) 251 } 252 253 func toBothListenersXDSResource(serverNames []string, certName string) *anypb.Any { 254 return toAny(&envoy_config_listener.Listener{ 255 Name: "listener", 256 FilterChains: []*envoy_config_listener.FilterChain{ 257 toInsecureListenerFilterChain(), 258 toSecureListenerFilterChain(serverNames, certName), 259 }, 260 ListenerFilters: []*envoy_config_listener.ListenerFilter{ 261 { 262 Name: "envoy.filters.listener.tls_inspector", 263 ConfigType: &envoy_config_listener.ListenerFilter_TypedConfig{ 264 TypedConfig: toAny(&envoy_extensions_listener_tls_inspector_v3.TlsInspector{}), 265 }, 266 }, 267 }, 268 SocketOptions: socketOptions, 269 }) 270 } 271 272 // Ingress Conformance test resources 273 274 // Conformance/DefaultBackend test 275 var defaultBackendListeners = []model.HTTPListener{ 276 { 277 Sources: []model.FullyQualifiedResource{ 278 { 279 Name: "load-balancing", 280 Namespace: "random-namespace", 281 Version: "networking.k8s.io/v1", 282 Kind: "Ingress", 283 }, 284 }, 285 Port: 80, 286 Hostname: "*", 287 Routes: []model.HTTPRoute{ 288 { 289 Backends: []model.Backend{ 290 { 291 Name: "default-backend", 292 Namespace: "random-namespace", 293 Port: &model.BackendPort{ 294 Port: 8080, 295 }, 296 }, 297 }, 298 }, 299 }, 300 }, 301 } 302 303 var defaultBackendListenersCiliumEnvoyConfig = &ciliumv2.CiliumEnvoyConfig{ 304 ObjectMeta: metav1.ObjectMeta{ 305 Name: "cilium-ingress-random-namespace-load-balancing", 306 Namespace: "random-namespace", 307 Labels: map[string]string{ 308 "cilium.io/use-original-source-address": "false", 309 }, 310 }, 311 Spec: ciliumv2.CiliumEnvoyConfigSpec{ 312 Services: []*ciliumv2.ServiceListener{ 313 { 314 Name: "cilium-ingress-load-balancing", 315 Namespace: "random-namespace", 316 Ports: []uint16{ 317 80, 318 }, 319 }, 320 }, 321 BackendServices: []*ciliumv2.Service{ 322 { 323 Name: "default-backend", 324 Namespace: "random-namespace", 325 Ports: []string{"8080"}, 326 }, 327 }, 328 Resources: []ciliumv2.XDSResource{ 329 {Any: toHTTPListenerXDSResource(false, nil, nil)}, 330 { 331 Any: toAny(&envoy_config_route_v3.RouteConfiguration{ 332 Name: "listener-insecure", 333 VirtualHosts: []*envoy_config_route_v3.VirtualHost{ 334 { 335 Name: "*", 336 Domains: []string{"*"}, 337 Routes: []*envoy_config_route_v3.Route{ 338 { 339 Match: &envoy_config_route_v3.RouteMatch{ 340 PathSpecifier: &envoy_config_route_v3.RouteMatch_Prefix{ 341 Prefix: "/", 342 }, 343 }, 344 Action: toRouteAction("random-namespace", "default-backend", "8080"), 345 }, 346 }, 347 }, 348 }, 349 }), 350 }, 351 {Any: toAny(toEnvoyCluster("random-namespace", "default-backend", "8080"))}, 352 }, 353 }, 354 } 355 356 // Conformance/HostRules test, enforce HTTPS is enabled 357 var hostRulesListenersEnforceHTTPS = []model.HTTPListener{ 358 { 359 Name: "ing-host-rules-random-namespace-*.foo.com", 360 Sources: []model.FullyQualifiedResource{ 361 { 362 Name: "host-rules", 363 Namespace: "random-namespace", 364 Version: "networking.k8s.io/v1", 365 Kind: "Ingress", 366 }, 367 }, 368 Port: 80, 369 Hostname: "*.foo.com", 370 Routes: []model.HTTPRoute{ 371 { 372 PathMatch: model.StringMatch{ 373 Prefix: "/", 374 }, 375 Backends: []model.Backend{ 376 { 377 Name: "wildcard-foo-com", 378 Namespace: "random-namespace", 379 Port: &model.BackendPort{ 380 Port: 8080, 381 }, 382 }, 383 }, 384 }, 385 }, 386 }, 387 { 388 Name: "ing-host-rules-random-namespace-foo.bar.com", 389 Sources: []model.FullyQualifiedResource{ 390 { 391 Name: "host-rules", 392 Namespace: "random-namespace", 393 Version: "networking.k8s.io/v1", 394 Kind: "Ingress", 395 }, 396 }, 397 Port: 80, 398 Hostname: "foo.bar.com", 399 Routes: []model.HTTPRoute{ 400 { 401 PathMatch: model.StringMatch{ 402 Prefix: "/", 403 }, 404 Backends: []model.Backend{ 405 { 406 Name: "foo-bar-com", 407 Namespace: "random-namespace", 408 Port: &model.BackendPort{ 409 Name: "http", 410 }, 411 }, 412 }, 413 }, 414 }, 415 }, 416 { 417 Name: "ing-host-rules-random-namespace-foo.bar.com", 418 Sources: []model.FullyQualifiedResource{ 419 { 420 Name: "host-rules", 421 Namespace: "random-namespace", 422 Version: "networking.k8s.io/v1", 423 Kind: "Ingress", 424 }, 425 }, 426 Port: 443, 427 Hostname: "foo.bar.com", 428 TLS: []model.TLSSecret{ 429 { 430 Name: "conformance-tls", 431 Namespace: "random-namespace", 432 }, 433 }, 434 ForceHTTPtoHTTPSRedirect: true, 435 Routes: []model.HTTPRoute{ 436 { 437 PathMatch: model.StringMatch{ 438 Prefix: "/", 439 }, 440 Backends: []model.Backend{ 441 { 442 Name: "foo-bar-com", 443 Namespace: "random-namespace", 444 Port: &model.BackendPort{ 445 Name: "http", 446 }, 447 }, 448 }, 449 }, 450 }, 451 }, 452 } 453 454 var hostRulesListenersEnforceHTTPSCiliumEnvoyConfig = &ciliumv2.CiliumEnvoyConfig{ 455 ObjectMeta: metav1.ObjectMeta{ 456 Name: "cilium-ingress-random-namespace-host-rules", 457 Namespace: "random-namespace", 458 Labels: map[string]string{ 459 "cilium.io/use-original-source-address": "false", 460 }, 461 }, 462 Spec: ciliumv2.CiliumEnvoyConfigSpec{ 463 Services: []*ciliumv2.ServiceListener{ 464 { 465 Name: "cilium-ingress-host-rules", 466 Namespace: "random-namespace", 467 Ports: []uint16{ 468 80, 469 443, 470 }, 471 }, 472 }, 473 BackendServices: []*ciliumv2.Service{ 474 { 475 Name: "foo-bar-com", 476 Namespace: "random-namespace", 477 Ports: []string{"http"}, 478 }, 479 { 480 Name: "wildcard-foo-com", 481 Namespace: "random-namespace", 482 Ports: []string{"8080"}, 483 }, 484 }, 485 Resources: []ciliumv2.XDSResource{ 486 {Any: toBothListenersXDSResource([]string{"foo.bar.com"}, "cilium-secrets/random-namespace-conformance-tls")}, 487 { 488 Any: toAny(&envoy_config_route_v3.RouteConfiguration{ 489 Name: "listener-insecure", 490 VirtualHosts: []*envoy_config_route_v3.VirtualHost{ 491 { 492 Name: "*.foo.com", 493 Domains: []string{"*.foo.com", "*.foo.com:*"}, 494 Routes: []*envoy_config_route_v3.Route{ 495 { 496 Match: &envoy_config_route_v3.RouteMatch{ 497 PathSpecifier: &envoy_config_route_v3.RouteMatch_Prefix{ 498 Prefix: "/", 499 }, 500 Headers: []*envoy_config_route_v3.HeaderMatcher{ 501 { 502 Name: ":authority", 503 HeaderMatchSpecifier: &envoy_config_route_v3.HeaderMatcher_StringMatch{ 504 StringMatch: &envoy_type_matcher_v3.StringMatcher{ 505 MatchPattern: &envoy_type_matcher_v3.StringMatcher_SafeRegex{ 506 SafeRegex: &envoy_type_matcher_v3.RegexMatcher{ 507 Regex: "^[^.]+[.]foo[.]com$", 508 }, 509 }, 510 }, 511 }, 512 }, 513 }, 514 QueryParameters: []*envoy_config_route_v3.QueryParameterMatcher{}, 515 }, 516 Action: toRouteAction("random-namespace", "wildcard-foo-com", "8080"), 517 }, 518 }, 519 }, 520 { 521 Name: "foo.bar.com", 522 Domains: []string{"foo.bar.com", "foo.bar.com:*"}, 523 Routes: []*envoy_config_route_v3.Route{ 524 { 525 Match: &envoy_config_route_v3.RouteMatch{ 526 PathSpecifier: &envoy_config_route_v3.RouteMatch_Prefix{ 527 Prefix: "/", 528 }, 529 }, 530 Action: toHTTPSRedirectAction(), 531 }, 532 }, 533 }, 534 }, 535 }), 536 }, 537 { 538 Any: toAny(&envoy_config_route_v3.RouteConfiguration{ 539 Name: "listener-secure", 540 VirtualHosts: []*envoy_config_route_v3.VirtualHost{ 541 { 542 Name: "foo.bar.com", 543 Domains: []string{"foo.bar.com", "foo.bar.com:*"}, 544 Routes: []*envoy_config_route_v3.Route{ 545 { 546 Match: &envoy_config_route_v3.RouteMatch{ 547 PathSpecifier: &envoy_config_route_v3.RouteMatch_Prefix{ 548 Prefix: "/", 549 }, 550 }, 551 Action: toRouteAction("random-namespace", "foo-bar-com", "http"), 552 }, 553 }, 554 }, 555 }, 556 }), 557 }, 558 {Any: toAny(toEnvoyCluster("random-namespace", "foo-bar-com", "http"))}, 559 {Any: toAny(toEnvoyCluster("random-namespace", "wildcard-foo-com", "8080"))}, 560 }, 561 }, 562 } 563 564 var hostRulesListeners = []model.HTTPListener{ 565 { 566 Name: "ing-host-rules-random-namespace-*.foo.com", 567 Sources: []model.FullyQualifiedResource{ 568 { 569 Name: "host-rules", 570 Namespace: "random-namespace", 571 Version: "networking.k8s.io/v1", 572 Kind: "Ingress", 573 }, 574 }, 575 Port: 80, 576 Hostname: "*.foo.com", 577 Routes: []model.HTTPRoute{ 578 { 579 PathMatch: model.StringMatch{ 580 Prefix: "/", 581 }, 582 Backends: []model.Backend{ 583 { 584 Name: "wildcard-foo-com", 585 Namespace: "random-namespace", 586 Port: &model.BackendPort{ 587 Port: 8080, 588 }, 589 }, 590 }, 591 }, 592 }, 593 }, 594 { 595 Name: "ing-host-rules-random-namespace-foo.bar.com", 596 Sources: []model.FullyQualifiedResource{ 597 { 598 Name: "host-rules", 599 Namespace: "random-namespace", 600 Version: "networking.k8s.io/v1", 601 Kind: "Ingress", 602 }, 603 }, 604 Port: 80, 605 Hostname: "foo.bar.com", 606 Routes: []model.HTTPRoute{ 607 { 608 PathMatch: model.StringMatch{ 609 Prefix: "/", 610 }, 611 Backends: []model.Backend{ 612 { 613 Name: "foo-bar-com", 614 Namespace: "random-namespace", 615 Port: &model.BackendPort{ 616 Name: "http", 617 }, 618 }, 619 }, 620 }, 621 }, 622 }, 623 { 624 Name: "ing-host-rules-random-namespace-foo.bar.com", 625 Sources: []model.FullyQualifiedResource{ 626 { 627 Name: "host-rules", 628 Namespace: "random-namespace", 629 Version: "networking.k8s.io/v1", 630 Kind: "Ingress", 631 }, 632 }, 633 Port: 443, 634 Hostname: "foo.bar.com", 635 TLS: []model.TLSSecret{ 636 { 637 Name: "conformance-tls", 638 Namespace: "random-namespace", 639 }, 640 }, 641 Routes: []model.HTTPRoute{ 642 { 643 PathMatch: model.StringMatch{ 644 Prefix: "/", 645 }, 646 Backends: []model.Backend{ 647 { 648 Name: "foo-bar-com", 649 Namespace: "random-namespace", 650 Port: &model.BackendPort{ 651 Name: "http", 652 }, 653 }, 654 }, 655 }, 656 }, 657 }, 658 } 659 660 var hostRulesListenersCiliumEnvoyConfig = &ciliumv2.CiliumEnvoyConfig{ 661 ObjectMeta: metav1.ObjectMeta{ 662 Name: "cilium-ingress-random-namespace-host-rules", 663 Namespace: "random-namespace", 664 Labels: map[string]string{ 665 "cilium.io/use-original-source-address": "false", 666 }, 667 }, 668 Spec: ciliumv2.CiliumEnvoyConfigSpec{ 669 Services: []*ciliumv2.ServiceListener{ 670 { 671 Name: "cilium-ingress-host-rules", 672 Namespace: "random-namespace", 673 Ports: []uint16{ 674 80, 675 443, 676 }, 677 }, 678 }, 679 BackendServices: []*ciliumv2.Service{ 680 { 681 Name: "foo-bar-com", 682 Namespace: "random-namespace", 683 Ports: []string{"http"}, 684 }, 685 { 686 Name: "wildcard-foo-com", 687 Namespace: "random-namespace", 688 Ports: []string{"8080"}, 689 }, 690 }, 691 Resources: []ciliumv2.XDSResource{ 692 {Any: toBothListenersXDSResource([]string{"foo.bar.com"}, "cilium-secrets/random-namespace-conformance-tls")}, 693 { 694 Any: toAny(&envoy_config_route_v3.RouteConfiguration{ 695 Name: "listener-insecure", 696 VirtualHosts: []*envoy_config_route_v3.VirtualHost{ 697 { 698 Name: "*.foo.com", 699 Domains: []string{"*.foo.com", "*.foo.com:*"}, 700 Routes: []*envoy_config_route_v3.Route{ 701 { 702 Match: &envoy_config_route_v3.RouteMatch{ 703 PathSpecifier: &envoy_config_route_v3.RouteMatch_Prefix{ 704 Prefix: "/", 705 }, 706 Headers: []*envoy_config_route_v3.HeaderMatcher{ 707 { 708 Name: ":authority", 709 HeaderMatchSpecifier: &envoy_config_route_v3.HeaderMatcher_StringMatch{ 710 StringMatch: &envoy_type_matcher_v3.StringMatcher{ 711 MatchPattern: &envoy_type_matcher_v3.StringMatcher_SafeRegex{ 712 SafeRegex: &envoy_type_matcher_v3.RegexMatcher{ 713 Regex: "^[^.]+[.]foo[.]com$", 714 }, 715 }, 716 }, 717 }, 718 }, 719 }, 720 QueryParameters: []*envoy_config_route_v3.QueryParameterMatcher{}, 721 }, 722 Action: toRouteAction("random-namespace", "wildcard-foo-com", "8080"), 723 }, 724 }, 725 }, 726 { 727 Name: "foo.bar.com", 728 Domains: []string{"foo.bar.com", "foo.bar.com:*"}, 729 Routes: []*envoy_config_route_v3.Route{ 730 { 731 Match: &envoy_config_route_v3.RouteMatch{ 732 PathSpecifier: &envoy_config_route_v3.RouteMatch_Prefix{ 733 Prefix: "/", 734 }, 735 }, 736 Action: toRouteAction("random-namespace", "foo-bar-com", "http"), 737 }, 738 }, 739 }, 740 }, 741 }), 742 }, 743 { 744 Any: toAny(&envoy_config_route_v3.RouteConfiguration{ 745 Name: "listener-secure", 746 VirtualHosts: []*envoy_config_route_v3.VirtualHost{ 747 { 748 Name: "foo.bar.com", 749 Domains: []string{"foo.bar.com", "foo.bar.com:*"}, 750 Routes: []*envoy_config_route_v3.Route{ 751 { 752 Match: &envoy_config_route_v3.RouteMatch{ 753 PathSpecifier: &envoy_config_route_v3.RouteMatch_Prefix{ 754 Prefix: "/", 755 }, 756 }, 757 Action: toRouteAction("random-namespace", "foo-bar-com", "http"), 758 }, 759 }, 760 }, 761 }, 762 }), 763 }, 764 {Any: toAny(toEnvoyCluster("random-namespace", "foo-bar-com", "http"))}, 765 {Any: toAny(toEnvoyCluster("random-namespace", "wildcard-foo-com", "8080"))}, 766 }, 767 }, 768 } 769 770 // Conformance/PathRules test 771 var pathRulesListeners = []model.HTTPListener{ 772 { 773 Name: "ing-path-rules-random-namespace-exact-path-rules", 774 Sources: []model.FullyQualifiedResource{ 775 { 776 Name: "path-rules", 777 Namespace: "random-namespace", 778 Version: "networking.k8s.io/v1", 779 Kind: "Ingress", 780 }, 781 }, 782 Port: 80, 783 Hostname: "exact-path-rules", 784 Routes: []model.HTTPRoute{ 785 { 786 PathMatch: model.StringMatch{ 787 Exact: "/foo", 788 }, 789 Backends: []model.Backend{ 790 { 791 Name: "foo-exact", 792 Namespace: "random-namespace", 793 Port: &model.BackendPort{ 794 Port: 8080, 795 }, 796 }, 797 }, 798 }, 799 }, 800 }, 801 { 802 Name: "ing-path-rules-random-namespace-mixed-path-rules", 803 Sources: []model.FullyQualifiedResource{ 804 { 805 Name: "path-rules", 806 Namespace: "random-namespace", 807 Version: "networking.k8s.io/v1", 808 Kind: "Ingress", 809 }, 810 }, 811 Port: 80, 812 Hostname: "mixed-path-rules", 813 Routes: []model.HTTPRoute{ 814 { 815 PathMatch: model.StringMatch{ 816 Prefix: "/foo", 817 }, 818 Backends: []model.Backend{ 819 { 820 Name: "foo-prefix", 821 Namespace: "random-namespace", 822 Port: &model.BackendPort{ 823 Port: 8080, 824 }, 825 }, 826 }, 827 }, 828 { 829 PathMatch: model.StringMatch{ 830 Exact: "/foo", 831 }, 832 Backends: []model.Backend{ 833 { 834 Name: "foo-exact", 835 Namespace: "random-namespace", 836 Port: &model.BackendPort{ 837 Port: 8080, 838 }, 839 }, 840 }, 841 }, 842 }, 843 }, 844 { 845 Name: "ing-path-rules-random-namespace-prefix-path-rules", 846 Sources: []model.FullyQualifiedResource{ 847 { 848 Name: "path-rules", 849 Namespace: "random-namespace", 850 Version: "networking.k8s.io/v1", 851 Kind: "Ingress", 852 }, 853 }, 854 Port: 80, 855 Hostname: "prefix-path-rules", 856 Routes: []model.HTTPRoute{ 857 { 858 PathMatch: model.StringMatch{ 859 Prefix: "/foo", 860 }, 861 Backends: []model.Backend{ 862 { 863 Name: "foo-prefix", 864 Namespace: "random-namespace", 865 Port: &model.BackendPort{ 866 Port: 8080, 867 }, 868 }, 869 }, 870 }, 871 { 872 PathMatch: model.StringMatch{ 873 Prefix: "/aaa/bbb", 874 }, 875 Backends: []model.Backend{ 876 { 877 Name: "aaa-slash-bbb-prefix", 878 Namespace: "random-namespace", 879 Port: &model.BackendPort{ 880 Port: 8080, 881 }, 882 }, 883 }, 884 }, 885 { 886 PathMatch: model.StringMatch{ 887 Prefix: "/aaa", 888 }, 889 Backends: []model.Backend{ 890 { 891 Name: "aaa-prefix", 892 Namespace: "random-namespace", 893 Port: &model.BackendPort{ 894 Port: 8080, 895 }, 896 }, 897 }, 898 }, 899 }, 900 }, 901 { 902 Name: "ing-path-rules-random-namespace-trailing-slash-path-rules", 903 Sources: []model.FullyQualifiedResource{ 904 { 905 Name: "path-rules", 906 Namespace: "random-namespace", 907 Version: "networking.k8s.io/v1", 908 Kind: "Ingress", 909 }, 910 }, 911 Port: 80, 912 Hostname: "trailing-slash-path-rules", 913 Routes: []model.HTTPRoute{ 914 { 915 PathMatch: model.StringMatch{ 916 Prefix: "/aaa/bbb/", 917 }, 918 Backends: []model.Backend{ 919 { 920 Name: "aaa-slash-bbb-slash-prefix", 921 Namespace: "random-namespace", 922 Port: &model.BackendPort{ 923 Port: 8080, 924 }, 925 }, 926 }, 927 }, 928 { 929 PathMatch: model.StringMatch{ 930 Exact: "/foo/", 931 }, 932 Backends: []model.Backend{ 933 { 934 Name: "foo-slash-exact", 935 Namespace: "random-namespace", 936 Port: &model.BackendPort{ 937 Port: 8080, 938 }, 939 }, 940 }, 941 }, 942 }, 943 }, 944 } 945 946 var pathRulesListenersCiliumEnvoyConfig = &ciliumv2.CiliumEnvoyConfig{ 947 ObjectMeta: metav1.ObjectMeta{ 948 Name: "cilium-ingress-random-namespace-path-rules", 949 Namespace: "random-namespace", 950 Labels: map[string]string{ 951 "cilium.io/use-original-source-address": "false", 952 }, 953 }, 954 Spec: ciliumv2.CiliumEnvoyConfigSpec{ 955 Services: []*ciliumv2.ServiceListener{ 956 { 957 Name: "cilium-ingress-path-rules", 958 Namespace: "random-namespace", 959 Ports: []uint16{ 960 80, 961 }, 962 }, 963 }, 964 BackendServices: []*ciliumv2.Service{ 965 { 966 Name: "aaa-prefix", 967 Namespace: "random-namespace", 968 Ports: []string{"8080"}, 969 }, 970 { 971 Name: "aaa-slash-bbb-prefix", 972 Namespace: "random-namespace", 973 Ports: []string{"8080"}, 974 }, 975 { 976 Name: "aaa-slash-bbb-slash-prefix", 977 Namespace: "random-namespace", 978 Ports: []string{"8080"}, 979 }, 980 { 981 Name: "foo-exact", 982 Namespace: "random-namespace", 983 Ports: []string{"8080"}, 984 }, 985 { 986 Name: "foo-prefix", 987 Namespace: "random-namespace", 988 Ports: []string{"8080"}, 989 }, 990 { 991 Name: "foo-slash-exact", 992 Namespace: "random-namespace", 993 Ports: []string{"8080"}, 994 }, 995 }, 996 Resources: []ciliumv2.XDSResource{ 997 {Any: toHTTPListenerXDSResource(false, nil, nil)}, 998 { 999 Any: toAny(&envoy_config_route_v3.RouteConfiguration{ 1000 Name: "listener-insecure", 1001 VirtualHosts: []*envoy_config_route_v3.VirtualHost{ 1002 { 1003 Name: "exact-path-rules", 1004 Domains: []string{"exact-path-rules", "exact-path-rules:*"}, 1005 Routes: []*envoy_config_route_v3.Route{ 1006 { 1007 Match: &envoy_config_route_v3.RouteMatch{ 1008 PathSpecifier: &envoy_config_route_v3.RouteMatch_Path{ 1009 Path: "/foo", 1010 }, 1011 }, 1012 Action: toRouteAction("random-namespace", "foo-exact", "8080"), 1013 }, 1014 }, 1015 }, 1016 { 1017 Name: "mixed-path-rules", 1018 Domains: []string{"mixed-path-rules", "mixed-path-rules:*"}, 1019 Routes: []*envoy_config_route_v3.Route{ 1020 { 1021 Match: &envoy_config_route_v3.RouteMatch{ 1022 PathSpecifier: &envoy_config_route_v3.RouteMatch_Path{ 1023 Path: "/foo", 1024 }, 1025 }, 1026 Action: toRouteAction("random-namespace", "foo-exact", "8080"), 1027 }, 1028 { 1029 Match: &envoy_config_route_v3.RouteMatch{ 1030 PathSpecifier: &envoy_config_route_v3.RouteMatch_PathSeparatedPrefix{ 1031 PathSeparatedPrefix: "/foo", 1032 }, 1033 }, 1034 Action: toRouteAction("random-namespace", "foo-prefix", "8080"), 1035 }, 1036 }, 1037 }, 1038 { 1039 Name: "prefix-path-rules", 1040 Domains: []string{"prefix-path-rules", "prefix-path-rules:*"}, 1041 Routes: []*envoy_config_route_v3.Route{ 1042 { 1043 Match: &envoy_config_route_v3.RouteMatch{ 1044 PathSpecifier: &envoy_config_route_v3.RouteMatch_PathSeparatedPrefix{ 1045 PathSeparatedPrefix: "/aaa/bbb", 1046 }, 1047 }, 1048 Action: toRouteAction("random-namespace", "aaa-slash-bbb-prefix", "8080"), 1049 }, 1050 { 1051 Match: &envoy_config_route_v3.RouteMatch{ 1052 PathSpecifier: &envoy_config_route_v3.RouteMatch_PathSeparatedPrefix{ 1053 PathSeparatedPrefix: "/foo", 1054 }, 1055 }, 1056 Action: toRouteAction("random-namespace", "foo-prefix", "8080"), 1057 }, 1058 { 1059 Match: &envoy_config_route_v3.RouteMatch{ 1060 PathSpecifier: &envoy_config_route_v3.RouteMatch_PathSeparatedPrefix{ 1061 PathSeparatedPrefix: "/aaa", 1062 }, 1063 }, 1064 Action: toRouteAction("random-namespace", "aaa-prefix", "8080"), 1065 }, 1066 }, 1067 }, 1068 { 1069 Name: "trailing-slash-path-rules", 1070 Domains: []string{"trailing-slash-path-rules", "trailing-slash-path-rules:*"}, 1071 Routes: []*envoy_config_route_v3.Route{ 1072 { 1073 Match: &envoy_config_route_v3.RouteMatch{ 1074 PathSpecifier: &envoy_config_route_v3.RouteMatch_Path{ 1075 Path: "/foo/", 1076 }, 1077 }, 1078 Action: toRouteAction("random-namespace", "foo-slash-exact", "8080"), 1079 }, 1080 { 1081 Match: &envoy_config_route_v3.RouteMatch{ 1082 PathSpecifier: &envoy_config_route_v3.RouteMatch_PathSeparatedPrefix{ 1083 PathSeparatedPrefix: "/aaa/bbb", 1084 }, 1085 }, 1086 Action: toRouteAction("random-namespace", "aaa-slash-bbb-slash-prefix", "8080"), 1087 }, 1088 }, 1089 }, 1090 }, 1091 }), 1092 }, 1093 {Any: toAny(toEnvoyCluster("random-namespace", "aaa-prefix", "8080"))}, 1094 {Any: toAny(toEnvoyCluster("random-namespace", "aaa-slash-bbb-prefix", "8080"))}, 1095 {Any: toAny(toEnvoyCluster("random-namespace", "aaa-slash-bbb-slash-prefix", "8080"))}, 1096 {Any: toAny(toEnvoyCluster("random-namespace", "foo-exact", "8080"))}, 1097 {Any: toAny(toEnvoyCluster("random-namespace", "foo-prefix", "8080"))}, 1098 {Any: toAny(toEnvoyCluster("random-namespace", "foo-slash-exact", "8080"))}, 1099 }, 1100 }, 1101 } 1102 1103 // Conformance/ProxyProtocol test 1104 var proxyProtocolListeners = []model.HTTPListener{ 1105 { 1106 Sources: []model.FullyQualifiedResource{ 1107 { 1108 Name: "load-balancing", 1109 Namespace: "random-namespace", 1110 Version: "networking.k8s.io/v1", 1111 Kind: "Ingress", 1112 }, 1113 }, 1114 Port: 80, 1115 Hostname: "*", 1116 Routes: []model.HTTPRoute{ 1117 { 1118 Backends: []model.Backend{ 1119 { 1120 Name: "default-backend", 1121 Namespace: "random-namespace", 1122 Port: &model.BackendPort{ 1123 Port: 8080, 1124 }, 1125 }, 1126 }, 1127 }, 1128 }, 1129 }, 1130 } 1131 1132 func hostNetworkListeners(port uint32) []model.HTTPListener { 1133 return []model.HTTPListener{ 1134 { 1135 Sources: []model.FullyQualifiedResource{ 1136 { 1137 Name: "load-balancing", 1138 Namespace: "random-namespace", 1139 Version: "networking.k8s.io/v1", 1140 Kind: "Ingress", 1141 }, 1142 }, 1143 Port: port, 1144 Hostname: "*", 1145 Routes: []model.HTTPRoute{ 1146 { 1147 Backends: []model.Backend{ 1148 { 1149 Name: "default-backend", 1150 Namespace: "random-namespace", 1151 Port: &model.BackendPort{ 1152 Port: 8080, 1153 }, 1154 }, 1155 }, 1156 }, 1157 }, 1158 }, 1159 } 1160 } 1161 1162 var proxyProtoListenersCiliumEnvoyConfig = &ciliumv2.CiliumEnvoyConfig{ 1163 ObjectMeta: metav1.ObjectMeta{ 1164 Name: "cilium-ingress-random-namespace-load-balancing", 1165 Namespace: "random-namespace", 1166 Labels: map[string]string{ 1167 "cilium.io/use-original-source-address": "false", 1168 }, 1169 }, 1170 Spec: ciliumv2.CiliumEnvoyConfigSpec{ 1171 Services: []*ciliumv2.ServiceListener{ 1172 { 1173 Name: "cilium-ingress-load-balancing", 1174 Namespace: "random-namespace", 1175 Ports: []uint16{ 1176 80, 1177 }, 1178 }, 1179 }, 1180 BackendServices: []*ciliumv2.Service{ 1181 { 1182 Name: "default-backend", 1183 Namespace: "random-namespace", 1184 Ports: []string{"8080"}, 1185 }, 1186 }, 1187 Resources: []ciliumv2.XDSResource{ 1188 {Any: toHTTPListenerXDSResource(true, nil, nil)}, 1189 { 1190 Any: toAny(&envoy_config_route_v3.RouteConfiguration{ 1191 Name: "listener-insecure", 1192 VirtualHosts: []*envoy_config_route_v3.VirtualHost{ 1193 { 1194 Name: "*", 1195 Domains: []string{"*"}, 1196 Routes: []*envoy_config_route_v3.Route{ 1197 { 1198 Match: &envoy_config_route_v3.RouteMatch{ 1199 PathSpecifier: &envoy_config_route_v3.RouteMatch_Prefix{ 1200 Prefix: "/", 1201 }, 1202 }, 1203 Action: toRouteAction("random-namespace", "default-backend", "8080"), 1204 }, 1205 }, 1206 }, 1207 }, 1208 }), 1209 }, 1210 {Any: toAny(toEnvoyCluster("random-namespace", "default-backend", "8080"))}, 1211 }, 1212 }, 1213 } 1214 1215 func hostNetworkListenersCiliumEnvoyConfig(address string, port uint32, nodeLabelSelector *slim_metav1.LabelSelector) *ciliumv2.CiliumEnvoyConfig { 1216 return &ciliumv2.CiliumEnvoyConfig{ 1217 ObjectMeta: metav1.ObjectMeta{ 1218 Name: "cilium-ingress-random-namespace-load-balancing", 1219 Namespace: "random-namespace", 1220 Labels: map[string]string{ 1221 "cilium.io/use-original-source-address": "false", 1222 }, 1223 }, 1224 Spec: ciliumv2.CiliumEnvoyConfigSpec{ 1225 NodeSelector: nodeLabelSelector, 1226 Services: []*ciliumv2.ServiceListener{ 1227 { 1228 Name: "cilium-ingress-load-balancing", 1229 Namespace: "random-namespace", 1230 Ports: []uint16{ 1231 uint16(port), 1232 }, 1233 }, 1234 }, 1235 BackendServices: []*ciliumv2.Service{ 1236 { 1237 Name: "default-backend", 1238 Namespace: "random-namespace", 1239 Ports: []string{"8080"}, 1240 }, 1241 }, 1242 Resources: []ciliumv2.XDSResource{ 1243 {Any: toHTTPListenerXDSResource(false, model.AddressOf(address), model.AddressOf(port))}, 1244 { 1245 Any: toAny(&envoy_config_route_v3.RouteConfiguration{ 1246 Name: "listener-insecure", 1247 VirtualHosts: []*envoy_config_route_v3.VirtualHost{ 1248 { 1249 Name: "*", 1250 Domains: []string{"*"}, 1251 Routes: []*envoy_config_route_v3.Route{ 1252 { 1253 Match: &envoy_config_route_v3.RouteMatch{ 1254 PathSpecifier: &envoy_config_route_v3.RouteMatch_Prefix{ 1255 Prefix: "/", 1256 }, 1257 }, 1258 Action: toRouteAction("random-namespace", "default-backend", "8080"), 1259 }, 1260 }, 1261 }, 1262 }, 1263 }), 1264 }, 1265 {Any: toAny(toEnvoyCluster("random-namespace", "default-backend", "8080"))}, 1266 }, 1267 }, 1268 } 1269 } 1270 1271 func toAny(message proto.Message) *anypb.Any { 1272 a, err := anypb.New(message) 1273 if err != nil { 1274 return nil 1275 } 1276 return a 1277 } 1278 1279 // default timeout for the ingress conformance tests 1280 var listenerDefaultTimeout = model.Timeout{ 1281 Request: nil, 1282 } 1283 1284 func uint32p(in uint32) *uint32 { 1285 return &in 1286 } 1287 1288 var complexNodePortIngressListeners = []model.HTTPListener{ 1289 { 1290 Sources: []model.FullyQualifiedResource{ 1291 { 1292 Name: "dummy-ingress", 1293 Namespace: "dummy-namespace", 1294 Version: "v1", 1295 Kind: "Ingress", 1296 UID: "d4bd3dc3-2ac5-4ab4-9dca-89c62c60177e", 1297 }, 1298 }, 1299 Port: 80, 1300 Hostname: "*", 1301 Routes: []model.HTTPRoute{ 1302 { 1303 Backends: []model.Backend{ 1304 { 1305 Name: "default-backend", 1306 Namespace: "dummy-namespace", 1307 Port: &model.BackendPort{ 1308 Port: 8080, 1309 }, 1310 }, 1311 }, 1312 Timeout: listenerDefaultTimeout, 1313 }, 1314 { 1315 PathMatch: model.StringMatch{ 1316 Exact: "/dummy-path", 1317 }, 1318 Backends: []model.Backend{ 1319 { 1320 Name: "dummy-backend", 1321 Namespace: "dummy-namespace", 1322 Port: &model.BackendPort{ 1323 Port: 8080, 1324 }, 1325 }, 1326 }, 1327 Timeout: listenerDefaultTimeout, 1328 }, 1329 { 1330 PathMatch: model.StringMatch{ 1331 Prefix: "/another-dummy-path", 1332 }, 1333 Backends: []model.Backend{ 1334 { 1335 Name: "another-dummy-backend", 1336 Namespace: "dummy-namespace", 1337 Port: &model.BackendPort{ 1338 Port: 8081, 1339 }, 1340 }, 1341 }, 1342 Timeout: listenerDefaultTimeout, 1343 }, 1344 }, 1345 Service: &model.Service{ 1346 Type: "NodePort", 1347 InsecureNodePort: uint32p(30000), 1348 SecureNodePort: uint32p(30001), 1349 }, 1350 }, 1351 { 1352 Sources: []model.FullyQualifiedResource{ 1353 { 1354 Name: "dummy-ingress", 1355 Namespace: "dummy-namespace", 1356 Version: "v1", 1357 Kind: "Ingress", 1358 UID: "d4bd3dc3-2ac5-4ab4-9dca-89c62c60177e", 1359 }, 1360 }, 1361 Port: 443, 1362 Hostname: "another-very-secure.server.com", 1363 TLS: []model.TLSSecret{ 1364 { 1365 Name: "tls-another-very-secure-server-com", 1366 Namespace: "dummy-namespace", 1367 }, 1368 }, 1369 Routes: []model.HTTPRoute{ 1370 { 1371 Backends: []model.Backend{ 1372 { 1373 Name: "default-backend", 1374 Namespace: "dummy-namespace", 1375 Port: &model.BackendPort{ 1376 Port: 8080, 1377 }, 1378 }, 1379 }, 1380 Timeout: listenerDefaultTimeout, 1381 }, 1382 { 1383 PathMatch: model.StringMatch{ 1384 Exact: "/dummy-path", 1385 }, 1386 Backends: []model.Backend{ 1387 { 1388 Name: "dummy-backend", 1389 Namespace: "dummy-namespace", 1390 Port: &model.BackendPort{ 1391 Port: 8080, 1392 }, 1393 }, 1394 }, 1395 Timeout: listenerDefaultTimeout, 1396 }, 1397 { 1398 PathMatch: model.StringMatch{ 1399 Prefix: "/another-dummy-path", 1400 }, 1401 Backends: []model.Backend{ 1402 { 1403 Name: "another-dummy-backend", 1404 Namespace: "dummy-namespace", 1405 Port: &model.BackendPort{ 1406 Port: 8081, 1407 }, 1408 }, 1409 }, 1410 Timeout: listenerDefaultTimeout, 1411 }, 1412 }, 1413 Service: &model.Service{ 1414 Type: "NodePort", 1415 InsecureNodePort: uint32p(30000), 1416 SecureNodePort: uint32p(30001), 1417 }, 1418 }, 1419 { 1420 Sources: []model.FullyQualifiedResource{ 1421 { 1422 Name: "dummy-ingress", 1423 Namespace: "dummy-namespace", 1424 Version: "v1", 1425 Kind: "Ingress", 1426 UID: "d4bd3dc3-2ac5-4ab4-9dca-89c62c60177e", 1427 }, 1428 }, 1429 Port: 443, 1430 Hostname: "not-in-use.another-very-secure.server.com", 1431 TLS: []model.TLSSecret{ 1432 { 1433 Name: "tls-another-very-secure-server-com", 1434 Namespace: "dummy-namespace", 1435 }, 1436 }, 1437 Routes: []model.HTTPRoute{ 1438 { 1439 Backends: []model.Backend{ 1440 { 1441 Name: "default-backend", 1442 Namespace: "dummy-namespace", 1443 Port: &model.BackendPort{ 1444 Port: 8080, 1445 }, 1446 }, 1447 }, 1448 Timeout: listenerDefaultTimeout, 1449 }, 1450 { 1451 PathMatch: model.StringMatch{ 1452 Exact: "/dummy-path", 1453 }, 1454 Backends: []model.Backend{ 1455 { 1456 Name: "dummy-backend", 1457 Namespace: "dummy-namespace", 1458 Port: &model.BackendPort{ 1459 Port: 8080, 1460 }, 1461 }, 1462 }, 1463 Timeout: listenerDefaultTimeout, 1464 }, 1465 { 1466 PathMatch: model.StringMatch{ 1467 Prefix: "/another-dummy-path", 1468 }, 1469 Backends: []model.Backend{ 1470 { 1471 Name: "another-dummy-backend", 1472 Namespace: "dummy-namespace", 1473 Port: &model.BackendPort{ 1474 Port: 8081, 1475 }, 1476 }, 1477 }, 1478 Timeout: listenerDefaultTimeout, 1479 }, 1480 }, 1481 Service: &model.Service{ 1482 Type: "NodePort", 1483 InsecureNodePort: uint32p(30000), 1484 SecureNodePort: uint32p(30001), 1485 }, 1486 }, 1487 { 1488 Sources: []model.FullyQualifiedResource{ 1489 { 1490 Name: "dummy-ingress", 1491 Namespace: "dummy-namespace", 1492 Version: "v1", 1493 Kind: "Ingress", 1494 UID: "d4bd3dc3-2ac5-4ab4-9dca-89c62c60177e", 1495 }, 1496 }, 1497 Port: 443, 1498 Hostname: "very-secure.server.com", 1499 TLS: []model.TLSSecret{ 1500 { 1501 Name: "tls-very-secure-server-com", 1502 Namespace: "dummy-namespace", 1503 }, 1504 }, 1505 Routes: []model.HTTPRoute{ 1506 { 1507 Backends: []model.Backend{ 1508 { 1509 Name: "default-backend", 1510 Namespace: "dummy-namespace", 1511 Port: &model.BackendPort{ 1512 Port: 8080, 1513 }, 1514 }, 1515 }, 1516 Timeout: listenerDefaultTimeout, 1517 }, 1518 { 1519 PathMatch: model.StringMatch{ 1520 Exact: "/dummy-path", 1521 }, 1522 Backends: []model.Backend{ 1523 { 1524 Name: "dummy-backend", 1525 Namespace: "dummy-namespace", 1526 Port: &model.BackendPort{ 1527 Port: 8080, 1528 }, 1529 }, 1530 }, 1531 Timeout: listenerDefaultTimeout, 1532 }, 1533 { 1534 PathMatch: model.StringMatch{ 1535 Prefix: "/another-dummy-path", 1536 }, 1537 Backends: []model.Backend{ 1538 { 1539 Name: "another-dummy-backend", 1540 Namespace: "dummy-namespace", 1541 Port: &model.BackendPort{ 1542 Port: 8081, 1543 }, 1544 }, 1545 }, 1546 Timeout: listenerDefaultTimeout, 1547 }, 1548 }, 1549 Service: &model.Service{ 1550 Type: "NodePort", 1551 InsecureNodePort: uint32p(30000), 1552 SecureNodePort: uint32p(30001), 1553 }, 1554 }, 1555 } 1556 1557 var complexNodePortIngressCiliumEnvoyConfig = &ciliumv2.CiliumEnvoyConfig{ 1558 ObjectMeta: metav1.ObjectMeta{ 1559 Name: "cilium-ingress-dummy-namespace-dummy-ingress", 1560 Namespace: "dummy-namespace", 1561 Labels: map[string]string{ 1562 "cilium.io/use-original-source-address": "false", 1563 }, 1564 }, 1565 Spec: ciliumv2.CiliumEnvoyConfigSpec{ 1566 NodeSelector: &slim_metav1.LabelSelector{MatchLabels: map[string]slim_metav1.MatchLabelsValue{"a": "b"}}, 1567 Services: []*ciliumv2.ServiceListener{ 1568 { 1569 Name: "cilium-ingress-dummy-ingress", 1570 Namespace: "dummy-namespace", 1571 Ports: []uint16{80, 443}, 1572 }, 1573 }, 1574 BackendServices: []*ciliumv2.Service{ 1575 { 1576 Name: "another-dummy-backend", 1577 Namespace: "dummy-namespace", 1578 Ports: []string{"8081"}, 1579 }, 1580 { 1581 Name: "default-backend", 1582 Namespace: "dummy-namespace", 1583 Ports: []string{"8080"}, 1584 }, 1585 { 1586 Name: "dummy-backend", 1587 Namespace: "dummy-namespace", 1588 Ports: []string{"8080"}, 1589 }, 1590 }, 1591 Resources: []ciliumv2.XDSResource{ 1592 {Any: toAny( 1593 &envoy_config_listener.Listener{ 1594 Name: "listener", 1595 FilterChains: []*envoy_config_listener.FilterChain{ 1596 toInsecureListenerFilterChain(), 1597 toSecureListenerFilterChain([]string{"another-very-secure.server.com", "not-in-use.another-very-secure.server.com"}, "cilium-secrets/dummy-namespace-tls-another-very-secure-server-com"), 1598 toSecureListenerFilterChain([]string{"very-secure.server.com"}, "cilium-secrets/dummy-namespace-tls-very-secure-server-com"), 1599 }, 1600 AdditionalAddresses: []*envoy_config_listener.AdditionalAddress{ 1601 { 1602 Address: &envoy_config_core_v3.Address{ 1603 Address: &envoy_config_core_v3.Address_SocketAddress{ 1604 SocketAddress: &envoy_config_core_v3.SocketAddress{ 1605 Address: "0.0.0.0", 1606 PortSpecifier: &envoy_config_core_v3.SocketAddress_PortValue{ 1607 PortValue: 443, 1608 }, 1609 }, 1610 }, 1611 }, 1612 }, 1613 }, 1614 Address: &envoy_config_core_v3.Address{ 1615 Address: &envoy_config_core_v3.Address_SocketAddress{ 1616 SocketAddress: &envoy_config_core_v3.SocketAddress{ 1617 Address: "0.0.0.0", 1618 PortSpecifier: &envoy_config_core_v3.SocketAddress_PortValue{ 1619 PortValue: 80, 1620 }, 1621 }, 1622 }, 1623 }, 1624 ListenerFilters: []*envoy_config_listener.ListenerFilter{ 1625 { 1626 Name: "envoy.filters.listener.tls_inspector", 1627 ConfigType: &envoy_config_listener.ListenerFilter_TypedConfig{ 1628 TypedConfig: toAny(&envoy_extensions_listener_tls_inspector_v3.TlsInspector{}), 1629 }, 1630 }, 1631 }, 1632 SocketOptions: socketOptions, 1633 })}, 1634 { 1635 Any: toAny(&envoy_config_route_v3.RouteConfiguration{ 1636 Name: "listener-insecure", 1637 VirtualHosts: []*envoy_config_route_v3.VirtualHost{ 1638 { 1639 Name: "*", 1640 Domains: domainsHelper("*"), 1641 Routes: []*envoy_config_route_v3.Route{ 1642 { 1643 Match: envoyRouteMatchExactPath("/dummy-path"), 1644 Action: envoyRouteAction("dummy-namespace", "dummy-backend", "8080"), 1645 }, 1646 { 1647 Match: envoyRouteMatchPrefixPath("/another-dummy-path"), 1648 Action: envoyRouteAction("dummy-namespace", "another-dummy-backend", "8081"), 1649 }, 1650 { 1651 Match: envoyRouteMatchRootPath(), 1652 Action: envoyRouteAction("dummy-namespace", "default-backend", "8080"), 1653 }, 1654 }, 1655 }, 1656 }, 1657 }), 1658 }, 1659 { 1660 Any: toAny(&envoy_config_route_v3.RouteConfiguration{ 1661 Name: "listener-secure", 1662 VirtualHosts: []*envoy_config_route_v3.VirtualHost{ 1663 { 1664 Name: "another-very-secure.server.com", 1665 Domains: domainsHelper("another-very-secure.server.com"), 1666 Routes: []*envoy_config_route_v3.Route{ 1667 { 1668 Match: envoyRouteMatchExactPath("/dummy-path"), 1669 Action: envoyRouteAction("dummy-namespace", "dummy-backend", "8080"), 1670 }, 1671 { 1672 Match: envoyRouteMatchPrefixPath("/another-dummy-path"), 1673 Action: envoyRouteAction("dummy-namespace", "another-dummy-backend", "8081"), 1674 }, 1675 { 1676 Match: envoyRouteMatchRootPath(), 1677 Action: envoyRouteAction("dummy-namespace", "default-backend", "8080"), 1678 }, 1679 }, 1680 }, 1681 { 1682 Name: "not-in-use.another-very-secure.server.com", 1683 Domains: domainsHelper("not-in-use.another-very-secure.server.com"), 1684 Routes: []*envoy_config_route_v3.Route{ 1685 { 1686 Match: envoyRouteMatchExactPath("/dummy-path"), 1687 Action: envoyRouteAction("dummy-namespace", "dummy-backend", "8080"), 1688 }, 1689 { 1690 Match: envoyRouteMatchPrefixPath("/another-dummy-path"), 1691 Action: envoyRouteAction("dummy-namespace", "another-dummy-backend", "8081"), 1692 }, 1693 { 1694 Match: envoyRouteMatchRootPath(), 1695 Action: envoyRouteAction("dummy-namespace", "default-backend", "8080"), 1696 }, 1697 }, 1698 }, 1699 { 1700 Name: "very-secure.server.com", 1701 Domains: domainsHelper("very-secure.server.com"), 1702 Routes: []*envoy_config_route_v3.Route{ 1703 { 1704 Match: envoyRouteMatchExactPath("/dummy-path"), 1705 Action: envoyRouteAction("dummy-namespace", "dummy-backend", "8080"), 1706 }, 1707 { 1708 Match: envoyRouteMatchPrefixPath("/another-dummy-path"), 1709 Action: envoyRouteAction("dummy-namespace", "another-dummy-backend", "8081"), 1710 }, 1711 { 1712 Match: envoyRouteMatchRootPath(), 1713 Action: envoyRouteAction("dummy-namespace", "default-backend", "8080"), 1714 }, 1715 }, 1716 }, 1717 }, 1718 }), 1719 }, 1720 {Any: toAny(toEnvoyCluster("dummy-namespace", "another-dummy-backend", "8081"))}, 1721 {Any: toAny(toEnvoyCluster("dummy-namespace", "default-backend", "8080"))}, 1722 {Any: toAny(toEnvoyCluster("dummy-namespace", "dummy-backend", "8080"))}, 1723 }, 1724 }, 1725 } 1726 1727 func domainsHelper(domain string) []string { 1728 if domain == "*" { 1729 return []string{domain} 1730 } 1731 1732 return []string{domain, fmt.Sprintf("%s:*", domain)} 1733 } 1734 1735 func envoyRouteMatchExactPath(path string) *envoy_config_route_v3.RouteMatch { 1736 return &envoy_config_route_v3.RouteMatch{ 1737 PathSpecifier: &envoy_config_route_v3.RouteMatch_Path{ 1738 Path: path, 1739 }, 1740 } 1741 } 1742 1743 func envoyRouteMatchRootPath() *envoy_config_route_v3.RouteMatch { 1744 return &envoy_config_route_v3.RouteMatch{ 1745 PathSpecifier: &envoy_config_route_v3.RouteMatch_Prefix{ 1746 Prefix: "/", 1747 }, 1748 } 1749 } 1750 1751 func envoyRouteMatchPrefixPath(path string) *envoy_config_route_v3.RouteMatch { 1752 return &envoy_config_route_v3.RouteMatch{ 1753 PathSpecifier: &envoy_config_route_v3.RouteMatch_PathSeparatedPrefix{ 1754 PathSeparatedPrefix: path, 1755 }, 1756 } 1757 } 1758 1759 func envoyRouteAction(namespace, backend, port string) *envoy_config_route_v3.Route_Route { 1760 return &envoy_config_route_v3.Route_Route{ 1761 Route: &envoy_config_route_v3.RouteAction{ 1762 ClusterSpecifier: &envoy_config_route_v3.RouteAction_Cluster{ 1763 Cluster: fmt.Sprintf("%s:%s:%s", namespace, backend, port), 1764 }, 1765 MaxStreamDuration: &envoy_config_route_v3.RouteAction_MaxStreamDuration{ 1766 MaxStreamDuration: &durationpb.Duration{Seconds: 0}, 1767 }, 1768 }, 1769 } 1770 }