mirror of
https://github.com/alibaba/higress.git
synced 2026-06-26 02:35:02 +08:00
feat: Enhance SSL passthrough support (#3943)
Signed-off-by: zijiren233 <pyh1670605849@gmail.com>
This commit is contained in:
@@ -46,6 +46,8 @@ import (
|
||||
"istio.io/istio/pkg/log"
|
||||
"istio.io/istio/pkg/util/sets"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
networkingv1 "k8s.io/api/networking/v1"
|
||||
networkingv1beta1 "k8s.io/api/networking/v1beta1"
|
||||
listersv1 "k8s.io/client-go/listers/core/v1"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
|
||||
@@ -438,6 +440,7 @@ func (m *IngressConfig) convertGateways(configs []common.WrapperConfig) []config
|
||||
if err != nil {
|
||||
IngressLog.Errorf("Get higress https configmap err %v", err)
|
||||
}
|
||||
m.preparePassthroughTLSHostOwners(&convertOptions, configs)
|
||||
for idx := range configs {
|
||||
cfg := configs[idx]
|
||||
clusterId := common.GetClusterId(cfg.Config.Annotations)
|
||||
@@ -504,6 +507,8 @@ func (m *IngressConfig) convertVirtualService(configs []common.WrapperConfig) []
|
||||
}
|
||||
}
|
||||
|
||||
m.preparePassthroughTLSHostOwners(&convertOptions, configs)
|
||||
|
||||
// convert http route
|
||||
for idx := range configs {
|
||||
cfg := configs[idx]
|
||||
@@ -570,13 +575,8 @@ func (m *IngressConfig) convertVirtualService(configs []common.WrapperConfig) []
|
||||
m.ingressRouteCache = convertOptions.IngressRouteCache.Extract()
|
||||
m.mutex.Unlock()
|
||||
|
||||
// Convert http route to virtual service
|
||||
out := make([]config.Config, 0, len(convertOptions.HTTPRoutes))
|
||||
for host, routes := range convertOptions.HTTPRoutes {
|
||||
if len(routes) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
out := make([]config.Config, 0, len(convertOptions.VirtualServices))
|
||||
for host, wrapperVS := range convertOptions.VirtualServices {
|
||||
cleanHost := common.CleanHost(host)
|
||||
// namespace/name, name format: (istio cluster id)-host
|
||||
gateways := []string{
|
||||
@@ -585,13 +585,10 @@ func (m *IngressConfig) convertVirtualService(configs []common.WrapperConfig) []
|
||||
common.CreateConvertedName(constants.IstioIngressGatewayName, cleanHost),
|
||||
}
|
||||
|
||||
wrapperVS, exist := convertOptions.VirtualServices[host]
|
||||
if !exist {
|
||||
IngressLog.Warnf("virtual service for host %s does not exist.", host)
|
||||
}
|
||||
vs := wrapperVS.VirtualService
|
||||
vs.Gateways = gateways
|
||||
|
||||
routes := convertOptions.HTTPRoutes[host]
|
||||
// Sort, exact -> prefix -> regex
|
||||
common.SortHTTPRoutes(routes)
|
||||
|
||||
@@ -599,14 +596,18 @@ func (m *IngressConfig) convertVirtualService(configs []common.WrapperConfig) []
|
||||
vs.Http = append(vs.Http, route.HTTPRoute)
|
||||
}
|
||||
|
||||
firstRoute := routes[0]
|
||||
if len(vs.Http) == 0 && len(vs.Tls) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
vsName, clusterId := virtualServiceNameAndClusterID(cleanHost, wrapperVS, routes)
|
||||
out = append(out, config.Config{
|
||||
Meta: config.Meta{
|
||||
GroupVersionKind: gvk.VirtualService,
|
||||
Name: common.CreateConvertedName(constants.IstioIngressGatewayName, firstRoute.WrapperConfig.Config.Namespace, firstRoute.WrapperConfig.Config.Name, cleanHost),
|
||||
Name: vsName,
|
||||
Namespace: m.namespace,
|
||||
Annotations: map[string]string{
|
||||
common.ClusterIdAnnotation: firstRoute.ClusterId.String(),
|
||||
common.ClusterIdAnnotation: clusterId.String(),
|
||||
},
|
||||
},
|
||||
Spec: vs,
|
||||
@@ -625,6 +626,129 @@ func (m *IngressConfig) convertVirtualService(configs []common.WrapperConfig) []
|
||||
return out
|
||||
}
|
||||
|
||||
func virtualServiceNameAndClusterID(cleanHost string, wrapperVS *common.WrapperVirtualService, routes []*common.WrapperHTTPRoute) (string, cluster.ID) {
|
||||
if len(routes) > 0 {
|
||||
firstRoute := routes[0]
|
||||
return common.CreateConvertedName(constants.IstioIngressGatewayName, firstRoute.WrapperConfig.Config.Namespace, firstRoute.WrapperConfig.Config.Name, cleanHost), firstRoute.ClusterId
|
||||
}
|
||||
|
||||
cfg := wrapperVS.WrapperConfig.Config
|
||||
return common.CreateConvertedName(constants.IstioIngressGatewayName, cfg.Namespace, cfg.Name, cleanHost), common.GetClusterId(cfg.Annotations)
|
||||
}
|
||||
|
||||
func (m *IngressConfig) preparePassthroughTLSHostOwners(convertOptions *common.ConvertOptions, configs []common.WrapperConfig) {
|
||||
if convertOptions.PassthroughTLSHostOwners == nil {
|
||||
convertOptions.PassthroughTLSHostOwners = map[string]*config.Config{}
|
||||
}
|
||||
|
||||
// ingress-nginx enables SSL passthrough at host level when any ingress for the host has the
|
||||
// annotation, then uses the first root path as the passthrough backend.
|
||||
passthroughHosts := map[string]struct{}{}
|
||||
firstRootPathHostOwners := map[string]*config.Config{}
|
||||
for idx := range configs {
|
||||
cfg := configs[idx]
|
||||
if cfg.AnnotationsConfig.IsCanary() {
|
||||
continue
|
||||
}
|
||||
|
||||
if cfg.AnnotationsConfig.IsSSLPassthrough() {
|
||||
for _, host := range ingressRuleHosts(cfg.Config.Spec) {
|
||||
passthroughHosts[host] = struct{}{}
|
||||
}
|
||||
}
|
||||
for _, host := range ingressRootPathHosts(cfg.Config.Spec) {
|
||||
if _, exist := firstRootPathHostOwners[host]; exist {
|
||||
continue
|
||||
}
|
||||
firstRootPathHostOwners[host] = cfg.Config
|
||||
}
|
||||
}
|
||||
|
||||
for host := range passthroughHosts {
|
||||
if owner := firstRootPathHostOwners[host]; owner != nil {
|
||||
convertOptions.PassthroughTLSHostOwners[host] = owner
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func ingressRuleHosts(spec config.Spec) []string {
|
||||
switch ingressSpec := spec.(type) {
|
||||
case networkingv1.IngressSpec:
|
||||
return ingressV1RuleHosts(ingressSpec.Rules)
|
||||
case networkingv1beta1.IngressSpec:
|
||||
return ingressV1Beta1RuleHosts(ingressSpec.Rules)
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func ingressRootPathHosts(spec config.Spec) []string {
|
||||
switch ingressSpec := spec.(type) {
|
||||
case networkingv1.IngressSpec:
|
||||
return ingressV1RootPathHosts(ingressSpec.Rules)
|
||||
case networkingv1beta1.IngressSpec:
|
||||
return ingressV1Beta1RootPathHosts(ingressSpec.Rules)
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func ingressV1RuleHosts(rules []networkingv1.IngressRule) []string {
|
||||
out := make([]string, 0, len(rules))
|
||||
for _, rule := range rules {
|
||||
out = append(out, rule.Host)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func ingressV1Beta1RuleHosts(rules []networkingv1beta1.IngressRule) []string {
|
||||
out := make([]string, 0, len(rules))
|
||||
for _, rule := range rules {
|
||||
out = append(out, rule.Host)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func ingressV1RootPathHosts(rules []networkingv1.IngressRule) []string {
|
||||
out := make([]string, 0, len(rules))
|
||||
for _, rule := range rules {
|
||||
if rule.HTTP == nil || !hasV1RootHTTPIngressPath(rule.HTTP.Paths) {
|
||||
continue
|
||||
}
|
||||
out = append(out, rule.Host)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func ingressV1Beta1RootPathHosts(rules []networkingv1beta1.IngressRule) []string {
|
||||
out := make([]string, 0, len(rules))
|
||||
for _, rule := range rules {
|
||||
if rule.HTTP == nil || !hasV1Beta1RootHTTPIngressPath(rule.HTTP.Paths) {
|
||||
continue
|
||||
}
|
||||
out = append(out, rule.Host)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func hasV1RootHTTPIngressPath(paths []networkingv1.HTTPIngressPath) bool {
|
||||
for _, path := range paths {
|
||||
if path.Path == "" || path.Path == "/" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func hasV1Beta1RootHTTPIngressPath(paths []networkingv1beta1.HTTPIngressPath) bool {
|
||||
for _, path := range paths {
|
||||
if path.Path == "" || path.Path == "/" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (m *IngressConfig) convertEnvoyFilter(convertOptions *common.ConvertOptions) {
|
||||
var envoyFilters []config.Config
|
||||
mappings := map[string]*common.Rule{}
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
networking "istio.io/api/networking/v1alpha3"
|
||||
"istio.io/istio/pkg/cluster"
|
||||
"istio.io/istio/pkg/config"
|
||||
"istio.io/istio/pkg/config/constants"
|
||||
"istio.io/istio/pkg/config/schema/gvk"
|
||||
"istio.io/istio/pkg/config/xds"
|
||||
ingress "k8s.io/api/networking/v1"
|
||||
@@ -109,6 +110,405 @@ func TestNormalizeWeightedCluster(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestVirtualServiceNameAndClusterID(t *testing.T) {
|
||||
cleanHost := common.CleanHost("example.com")
|
||||
wrapperVS := &common.WrapperVirtualService{
|
||||
WrapperConfig: &common.WrapperConfig{
|
||||
Config: &config.Config{
|
||||
Meta: config.Meta{
|
||||
Namespace: "tls-ns",
|
||||
Name: "tls-ingress",
|
||||
Annotations: map[string]string{
|
||||
common.ClusterIdAnnotation: "tls-cluster",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
routes := []*common.WrapperHTTPRoute{
|
||||
{
|
||||
WrapperConfig: &common.WrapperConfig{
|
||||
Config: &config.Config{
|
||||
Meta: config.Meta{
|
||||
Namespace: "http-ns",
|
||||
Name: "http-ingress",
|
||||
},
|
||||
},
|
||||
},
|
||||
ClusterId: "http-cluster",
|
||||
},
|
||||
}
|
||||
|
||||
name, clusterID := virtualServiceNameAndClusterID(cleanHost, wrapperVS, routes)
|
||||
if name != common.CreateConvertedName(constants.IstioIngressGatewayName, "http-ns", "http-ingress", cleanHost) {
|
||||
t.Fatalf("http-backed virtual service name mismatch: %s", name)
|
||||
}
|
||||
if clusterID != "http-cluster" {
|
||||
t.Fatalf("http-backed cluster id mismatch: %s", clusterID)
|
||||
}
|
||||
|
||||
name, clusterID = virtualServiceNameAndClusterID(cleanHost, wrapperVS, nil)
|
||||
if name != common.CreateConvertedName(constants.IstioIngressGatewayName, "tls-ns", "tls-ingress", cleanHost) {
|
||||
t.Fatalf("tls-only virtual service name mismatch: %s", name)
|
||||
}
|
||||
if clusterID != "tls-cluster" {
|
||||
t.Fatalf("tls-only cluster id mismatch: %s", clusterID)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPreparePassthroughTLSHostOwnersRequiresPassthroughHost(t *testing.T) {
|
||||
m := &IngressConfig{}
|
||||
configs := []common.WrapperConfig{
|
||||
{
|
||||
Config: &config.Config{
|
||||
Meta: config.Meta{
|
||||
Namespace: "default",
|
||||
Name: "plain-root",
|
||||
},
|
||||
Spec: ingress.IngressSpec{
|
||||
Rules: []ingress.IngressRule{
|
||||
{
|
||||
Host: "example.com",
|
||||
IngressRuleValue: ingress.IngressRuleValue{
|
||||
HTTP: &ingress.HTTPIngressRuleValue{
|
||||
Paths: []ingress.HTTPIngressPath{
|
||||
{Path: "/"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
AnnotationsConfig: &annotations.Ingress{},
|
||||
},
|
||||
{
|
||||
Config: &config.Config{
|
||||
Meta: config.Meta{
|
||||
Namespace: "default",
|
||||
Name: "plain-root-duplicate",
|
||||
},
|
||||
Spec: ingress.IngressSpec{
|
||||
Rules: []ingress.IngressRule{
|
||||
{
|
||||
Host: "example.com",
|
||||
IngressRuleValue: ingress.IngressRuleValue{
|
||||
HTTP: &ingress.HTTPIngressRuleValue{
|
||||
Paths: []ingress.HTTPIngressPath{
|
||||
{Path: "/"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
AnnotationsConfig: &annotations.Ingress{},
|
||||
},
|
||||
}
|
||||
|
||||
options := &common.ConvertOptions{}
|
||||
m.preparePassthroughTLSHostOwners(options, configs)
|
||||
|
||||
if len(options.PassthroughTLSHostOwners) != 0 {
|
||||
t.Fatalf("unexpected ssl passthrough owners: %+v", options.PassthroughTLSHostOwners)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPreparePassthroughTLSHostOwnersUsesFirstRootPathOwner(t *testing.T) {
|
||||
m := &IngressConfig{}
|
||||
configs := []common.WrapperConfig{
|
||||
{
|
||||
Config: &config.Config{
|
||||
Meta: config.Meta{
|
||||
Namespace: "default",
|
||||
Name: "plain-root",
|
||||
},
|
||||
Spec: ingress.IngressSpec{
|
||||
Rules: []ingress.IngressRule{
|
||||
{
|
||||
Host: "example.com",
|
||||
IngressRuleValue: ingress.IngressRuleValue{
|
||||
HTTP: &ingress.HTTPIngressRuleValue{
|
||||
Paths: []ingress.HTTPIngressPath{
|
||||
{Path: "/"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
AnnotationsConfig: &annotations.Ingress{},
|
||||
},
|
||||
{
|
||||
Config: &config.Config{
|
||||
Meta: config.Meta{
|
||||
Namespace: "default",
|
||||
Name: "passthrough-non-root",
|
||||
},
|
||||
Spec: ingress.IngressSpec{
|
||||
Rules: []ingress.IngressRule{
|
||||
{
|
||||
Host: "example.com",
|
||||
IngressRuleValue: ingress.IngressRuleValue{
|
||||
HTTP: &ingress.HTTPIngressRuleValue{
|
||||
Paths: []ingress.HTTPIngressPath{
|
||||
{Path: "/api"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
AnnotationsConfig: &annotations.Ingress{
|
||||
SSLPassthrough: &annotations.SSLPassthroughConfig{Enabled: true},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
options := &common.ConvertOptions{}
|
||||
m.preparePassthroughTLSHostOwners(options, configs)
|
||||
|
||||
if !common.IsPassthroughTLSHostOwner(options, configs[0].Config, "example.com") {
|
||||
t.Fatal("first root ingress was not recorded as passthrough owner")
|
||||
}
|
||||
if !common.HasPassthroughTLSHostOwner(options, configs[0].Config) {
|
||||
t.Fatal("first root ingress was not found as passthrough owner")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPreparePassthroughTLSHostOwnersIgnoresHTTPOnlyIngressForHTTPSFallback(t *testing.T) {
|
||||
m := &IngressConfig{}
|
||||
configs := []common.WrapperConfig{
|
||||
{
|
||||
Config: &config.Config{
|
||||
Meta: config.Meta{
|
||||
Namespace: "default",
|
||||
Name: "http-only",
|
||||
},
|
||||
Spec: ingress.IngressSpec{
|
||||
Rules: []ingress.IngressRule{
|
||||
{
|
||||
Host: "example.com",
|
||||
IngressRuleValue: ingress.IngressRuleValue{
|
||||
HTTP: &ingress.HTTPIngressRuleValue{
|
||||
Paths: []ingress.HTTPIngressPath{
|
||||
{Path: "/api"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
AnnotationsConfig: &annotations.Ingress{},
|
||||
},
|
||||
{
|
||||
Config: &config.Config{
|
||||
Meta: config.Meta{
|
||||
Namespace: "default",
|
||||
Name: "tls-ingress",
|
||||
},
|
||||
Spec: ingress.IngressSpec{
|
||||
TLS: []ingress.IngressTLS{
|
||||
{
|
||||
Hosts: []string{"example.com"},
|
||||
SecretName: "example-com",
|
||||
},
|
||||
},
|
||||
Rules: []ingress.IngressRule{
|
||||
{
|
||||
Host: "example.com",
|
||||
IngressRuleValue: ingress.IngressRuleValue{
|
||||
HTTP: &ingress.HTTPIngressRuleValue{
|
||||
Paths: []ingress.HTTPIngressPath{
|
||||
{Path: "/app"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
AnnotationsConfig: &annotations.Ingress{},
|
||||
},
|
||||
}
|
||||
|
||||
options := &common.ConvertOptions{}
|
||||
m.preparePassthroughTLSHostOwners(options, configs)
|
||||
|
||||
if len(options.PassthroughTLSHostOwners) != 0 {
|
||||
t.Fatalf("unexpected ssl passthrough owners: %+v", options.PassthroughTLSHostOwners)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConvertGatewaysHonorsFirstRootPathSSLPassthroughOwner(t *testing.T) {
|
||||
fake := kube.NewFakeClient()
|
||||
options := common.Options{
|
||||
Enable: true,
|
||||
ClusterId: "ingress-v1",
|
||||
RawClusterId: "ingress-v1__",
|
||||
GatewayHttpPort: 80,
|
||||
GatewayHttpsPort: 443,
|
||||
}
|
||||
ingressController := controllerv1.NewController(fake, fake, options, nil)
|
||||
m := NewIngressConfig(fake, nil, "wakanda", options)
|
||||
m.remoteIngressControllers = map[cluster.ID]common.IngressController{
|
||||
"ingress-v1": ingressController,
|
||||
}
|
||||
|
||||
configs := []common.WrapperConfig{
|
||||
{
|
||||
Config: &config.Config{
|
||||
Meta: config.Meta{
|
||||
Namespace: "default",
|
||||
Name: "tls-non-root",
|
||||
Annotations: map[string]string{
|
||||
common.ClusterIdAnnotation: "ingress-v1",
|
||||
},
|
||||
},
|
||||
Spec: ingress.IngressSpec{
|
||||
TLS: []ingress.IngressTLS{
|
||||
{
|
||||
Hosts: []string{"example.com"},
|
||||
SecretName: "example-com",
|
||||
},
|
||||
},
|
||||
Rules: []ingress.IngressRule{
|
||||
{
|
||||
Host: "example.com",
|
||||
IngressRuleValue: ingress.IngressRuleValue{
|
||||
HTTP: &ingress.HTTPIngressRuleValue{
|
||||
Paths: []ingress.HTTPIngressPath{
|
||||
{Path: "/api"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
AnnotationsConfig: &annotations.Ingress{},
|
||||
},
|
||||
{
|
||||
Config: &config.Config{
|
||||
Meta: config.Meta{
|
||||
Namespace: "default",
|
||||
Name: "passthrough-root",
|
||||
Annotations: map[string]string{
|
||||
common.ClusterIdAnnotation: "ingress-v1",
|
||||
},
|
||||
},
|
||||
Spec: ingress.IngressSpec{
|
||||
Rules: []ingress.IngressRule{
|
||||
{
|
||||
Host: "example.com",
|
||||
IngressRuleValue: ingress.IngressRuleValue{
|
||||
HTTP: &ingress.HTTPIngressRuleValue{
|
||||
Paths: []ingress.HTTPIngressPath{
|
||||
{Path: "/"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
AnnotationsConfig: &annotations.Ingress{
|
||||
SSLPassthrough: &annotations.SSLPassthroughConfig{Enabled: true},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
result := m.convertGateways(configs)
|
||||
if len(result) != 1 {
|
||||
t.Fatalf("gateway count mismatch, want 1, got %d", len(result))
|
||||
}
|
||||
gateway := result[0].Spec.(*networking.Gateway)
|
||||
if len(gateway.Servers) != 2 {
|
||||
t.Fatalf("server count mismatch, want 2, got %d", len(gateway.Servers))
|
||||
}
|
||||
tlsServer := gateway.Servers[1]
|
||||
if tlsServer.Port.Protocol != "TLS" {
|
||||
t.Fatalf("tls server protocol mismatch, want TLS, got %s", tlsServer.Port.Protocol)
|
||||
}
|
||||
if tlsServer.Tls.GetMode() != networking.ServerTLSSettings_PASSTHROUGH {
|
||||
t.Fatalf("tls mode mismatch, want PASSTHROUGH, got %s", tlsServer.Tls.GetMode())
|
||||
}
|
||||
}
|
||||
|
||||
func TestConvertGatewaysUsesFirstRootOwnerWhenLaterIngressEnablesSSLPassthrough(t *testing.T) {
|
||||
fake := kube.NewFakeClient()
|
||||
options := common.Options{
|
||||
Enable: true,
|
||||
ClusterId: "ingress-v1",
|
||||
RawClusterId: "ingress-v1__",
|
||||
GatewayHttpPort: 80,
|
||||
GatewayHttpsPort: 443,
|
||||
}
|
||||
ingressController := controllerv1.NewController(fake, fake, options, nil)
|
||||
m := NewIngressConfig(fake, nil, "wakanda", options)
|
||||
m.remoteIngressControllers = map[cluster.ID]common.IngressController{
|
||||
"ingress-v1": ingressController,
|
||||
}
|
||||
|
||||
configs := []common.WrapperConfig{
|
||||
ingressV1Wrapper("root", "example.com", "/", false),
|
||||
ingressV1Wrapper("passthrough", "example.com", "/passthrough", true),
|
||||
}
|
||||
|
||||
result := m.convertGateways(configs)
|
||||
if len(result) != 1 {
|
||||
t.Fatalf("gateway count mismatch, want 1, got %d", len(result))
|
||||
}
|
||||
gateway := result[0].Spec.(*networking.Gateway)
|
||||
if len(gateway.Servers) != 2 {
|
||||
t.Fatalf("server count mismatch, want 2, got %d", len(gateway.Servers))
|
||||
}
|
||||
tlsServer := gateway.Servers[1]
|
||||
if tlsServer.Port.Protocol != "TLS" {
|
||||
t.Fatalf("tls server protocol mismatch, want TLS, got %s", tlsServer.Port.Protocol)
|
||||
}
|
||||
if tlsServer.Tls.GetMode() != networking.ServerTLSSettings_PASSTHROUGH {
|
||||
t.Fatalf("tls mode mismatch, want PASSTHROUGH, got %s", tlsServer.Tls.GetMode())
|
||||
}
|
||||
}
|
||||
|
||||
func TestConvertVirtualServiceUsesFirstRootOwnerWhenLaterIngressEnablesSSLPassthrough(t *testing.T) {
|
||||
fake := kube.NewFakeClient()
|
||||
options := common.Options{
|
||||
Enable: true,
|
||||
ClusterId: "ingress-v1",
|
||||
RawClusterId: "ingress-v1__",
|
||||
GatewayHttpPort: 80,
|
||||
GatewayHttpsPort: 443,
|
||||
}
|
||||
ingressController := controllerv1.NewController(fake, fake, options, nil)
|
||||
m := NewIngressConfig(fake, nil, "wakanda", options)
|
||||
m.remoteIngressControllers = map[cluster.ID]common.IngressController{
|
||||
"ingress-v1": ingressController,
|
||||
}
|
||||
|
||||
configs := []common.WrapperConfig{
|
||||
ingressV1Wrapper("root", "example.com", "/", false),
|
||||
ingressV1Wrapper("passthrough", "example.com", "/passthrough", true),
|
||||
}
|
||||
|
||||
result := m.convertVirtualService(configs)
|
||||
if len(result) != 1 {
|
||||
t.Fatalf("virtual service count mismatch, want 1, got %d", len(result))
|
||||
}
|
||||
vs := result[0].Spec.(*networking.VirtualService)
|
||||
if len(vs.Tls) != 1 {
|
||||
t.Fatalf("tls route count mismatch, want 1, got %d", len(vs.Tls))
|
||||
}
|
||||
if got := vs.Tls[0].Route[0].Destination.Host; got != "root.default.svc.cluster.local" {
|
||||
t.Fatalf("destination host mismatch, want root.default.svc.cluster.local, got %s", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConvertGatewaysForIngress(t *testing.T) {
|
||||
fake := kube.NewFakeClient()
|
||||
v1Beta1Options := common.Options{
|
||||
@@ -616,3 +1016,46 @@ func TestConstructBasicAuthEnvoyFilter(t *testing.T) {
|
||||
target := proto.Clone(pb).(*httppb.HttpFilter)
|
||||
t.Log(target)
|
||||
}
|
||||
|
||||
func ingressV1Wrapper(name, host, path string, sslPassthrough bool) common.WrapperConfig {
|
||||
wrapper := common.WrapperConfig{
|
||||
Config: &config.Config{
|
||||
Meta: config.Meta{
|
||||
Namespace: "default",
|
||||
Name: name,
|
||||
Annotations: map[string]string{
|
||||
common.ClusterIdAnnotation: "ingress-v1",
|
||||
},
|
||||
},
|
||||
Spec: ingress.IngressSpec{
|
||||
Rules: []ingress.IngressRule{
|
||||
{
|
||||
Host: host,
|
||||
IngressRuleValue: ingress.IngressRuleValue{
|
||||
HTTP: &ingress.HTTPIngressRuleValue{
|
||||
Paths: []ingress.HTTPIngressPath{
|
||||
{
|
||||
Path: path,
|
||||
Backend: ingress.IngressBackend{
|
||||
Service: &ingress.IngressServiceBackend{
|
||||
Name: name,
|
||||
Port: ingress.ServiceBackendPort{Number: 443},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
AnnotationsConfig: &annotations.Ingress{
|
||||
Match: &annotations.MatchConfig{},
|
||||
},
|
||||
}
|
||||
if sslPassthrough {
|
||||
wrapper.AnnotationsConfig.SSLPassthrough = &annotations.SSLPassthroughConfig{Enabled: true}
|
||||
}
|
||||
return wrapper
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user