mirror of
https://github.com/alibaba/higress.git
synced 2026-06-26 10:45:25 +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{}
|
||||
|
||||
Reference in New Issue
Block a user