Skip to content

Commit 2807ddf

Browse files
authored
Feat https fallback (#1020)
1 parent 6e4ade0 commit 2807ddf

File tree

9 files changed

+215
-56
lines changed

9 files changed

+215
-56
lines changed

go.mod

+3-3
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,6 @@ require (
259259
golang.org/x/crypto v0.17.0 // indirect
260260
golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect
261261
golang.org/x/mod v0.11.0 // indirect
262-
golang.org/x/net v0.17.0 // indirect
263262
golang.org/x/oauth2 v0.6.0 // indirect
264263
golang.org/x/sync v0.3.0 // indirect
265264
golang.org/x/sys v0.15.0 // indirect
@@ -281,6 +280,8 @@ require (
281280
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
282281
gopkg.in/warnings.v0 v0.1.2 // indirect
283282
k8s.io/apiserver v0.22.5 // indirect
283+
k8s.io/component-base v0.22.5 // indirect
284+
k8s.io/klog/v2 v2.60.1 // indirect
284285
k8s.io/kube-openapi v0.0.0-20211109043538-20434351676c // indirect
285286
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed // indirect
286287
oras.land/oras-go v0.4.0 // indirect
@@ -312,10 +313,9 @@ require (
312313
github.com/kylelemons/godebug v1.1.0
313314
github.com/mholt/acmez v1.2.0
314315
github.com/tidwall/gjson v1.17.0
316+
golang.org/x/net v0.17.0
315317
helm.sh/helm/v3 v3.7.1
316318
k8s.io/apiextensions-apiserver v0.25.4
317-
k8s.io/component-base v0.22.5
318-
k8s.io/klog/v2 v2.60.1
319319
knative.dev/networking v0.0.0-20220302134042-e8b2eb995165
320320
knative.dev/pkg v0.0.0-20220301181942-2fdd5f232e77
321321
)

pkg/cert/config.go

+12-10
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,12 @@ const (
4545

4646
// Config is the configuration of automatic https.
4747
type Config struct {
48-
AutomaticHttps bool `json:"automaticHttps"`
49-
RenewBeforeDays int `json:"renewBeforeDays"`
50-
CredentialConfig []CredentialEntry `json:"credentialConfig"`
51-
ACMEIssuer []ACMEIssuerEntry `json:"acmeIssuer"`
52-
Version string `json:"version"`
48+
AutomaticHttps bool `json:"automaticHttps"`
49+
FallbackForInvalidSecret bool `json:"fallbackForInvalidSecret"`
50+
RenewBeforeDays int `json:"renewBeforeDays"`
51+
CredentialConfig []CredentialEntry `json:"credentialConfig"`
52+
ACMEIssuer []ACMEIssuerEntry `json:"acmeIssuer"`
53+
Version string `json:"version"`
5354
}
5455

5556
func (c *Config) GetIssuer(issuerName IssuerName) *ACMEIssuerEntry {
@@ -274,11 +275,12 @@ func newDefaultConfig(email string) *Config {
274275
}
275276
defaultCredentialConfig := make([]CredentialEntry, 0)
276277
config := &Config{
277-
AutomaticHttps: true,
278-
RenewBeforeDays: DefaultRenewBeforeDays,
279-
ACMEIssuer: defaultIssuer,
280-
CredentialConfig: defaultCredentialConfig,
281-
Version: time.Now().Format("20060102030405"),
278+
AutomaticHttps: true,
279+
FallbackForInvalidSecret: false,
280+
RenewBeforeDays: DefaultRenewBeforeDays,
281+
ACMEIssuer: defaultIssuer,
282+
CredentialConfig: defaultCredentialConfig,
283+
Version: time.Now().Format("20060102030405"),
282284
}
283285
return config
284286
}

pkg/ingress/config/ingress_config.go

+11-1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ import (
5151
higressv1 "github.com/alibaba/higress/api/networking/v1"
5252
extlisterv1 "github.com/alibaba/higress/client/pkg/listers/extensions/v1alpha1"
5353
netlisterv1 "github.com/alibaba/higress/client/pkg/listers/networking/v1"
54+
"github.com/alibaba/higress/pkg/cert"
5455
"github.com/alibaba/higress/pkg/ingress/kube/annotations"
5556
"github.com/alibaba/higress/pkg/ingress/kube/common"
5657
"github.com/alibaba/higress/pkg/ingress/kube/configmap"
@@ -144,6 +145,8 @@ type IngressConfig struct {
144145
namespace string
145146

146147
clusterId string
148+
149+
httpsConfigMgr *cert.ConfigMgr
147150
}
148151

149152
func NewIngressConfig(localKubeClient kube.Client, XDSUpdater model.XDSUpdater, namespace, clusterId string) *IngressConfig {
@@ -180,6 +183,9 @@ func NewIngressConfig(localKubeClient kube.Client, XDSUpdater model.XDSUpdater,
180183
higressConfigController := configmap.NewController(localKubeClient, clusterId, namespace)
181184
config.configmapMgr = configmap.NewConfigmapMgr(XDSUpdater, namespace, higressConfigController, higressConfigController.Lister())
182185

186+
httpsConfigMgr, _ := cert.NewConfigMgr(namespace, localKubeClient)
187+
config.httpsConfigMgr = httpsConfigMgr
188+
183189
return config
184190
}
185191

@@ -347,6 +353,10 @@ func (m *IngressConfig) convertGateways(configs []common.WrapperConfig) []config
347353
Gateways: map[string]*common.WrapperGateway{},
348354
}
349355

356+
httpsCredentialConfig, err := m.httpsConfigMgr.GetConfigFromConfigmap()
357+
if err != nil {
358+
IngressLog.Errorf("Get higress https configmap err %v", err)
359+
}
350360
for idx := range configs {
351361
cfg := configs[idx]
352362
clusterId := common.GetClusterId(cfg.Config.Annotations)
@@ -356,7 +366,7 @@ func (m *IngressConfig) convertGateways(configs []common.WrapperConfig) []config
356366
if ingressController == nil {
357367
continue
358368
}
359-
if err := ingressController.ConvertGateway(&convertOptions, &cfg); err != nil {
369+
if err := ingressController.ConvertGateway(&convertOptions, &cfg, httpsCredentialConfig); err != nil {
360370
IngressLog.Errorf("Convert ingress %s/%s to gateway fail in cluster %s, err %v", cfg.Config.Namespace, cfg.Config.Name, clusterId, err)
361371
}
362372
}

pkg/ingress/kube/common/controller.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@ package common
1717
import (
1818
"strings"
1919

20+
"github.com/alibaba/higress/pkg/cert"
21+
"github.com/alibaba/higress/pkg/ingress/kube/annotations"
2022
networking "istio.io/api/networking/v1alpha3"
2123
"istio.io/istio/pilot/pkg/model"
2224
"istio.io/istio/pkg/config"
2325
gatewaytool "istio.io/istio/pkg/config/gateway"
2426
listerv1 "k8s.io/client-go/listers/core/v1"
2527
"k8s.io/client-go/tools/cache"
26-
27-
"github.com/alibaba/higress/pkg/ingress/kube/annotations"
2828
)
2929

3030
type ServiceKey struct {
@@ -121,7 +121,7 @@ type IngressController interface {
121121

122122
SecretLister() listerv1.SecretLister
123123

124-
ConvertGateway(convertOptions *ConvertOptions, wrapper *WrapperConfig) error
124+
ConvertGateway(convertOptions *ConvertOptions, wrapper *WrapperConfig, httpsCredentialConfig *cert.Config) error
125125

126126
ConvertHTTPRoute(convertOptions *ConvertOptions, wrapper *WrapperConfig) error
127127

pkg/ingress/kube/ingress/controller.go

+19-10
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ import (
5555
"github.com/alibaba/higress/pkg/ingress/kube/secret"
5656
"github.com/alibaba/higress/pkg/ingress/kube/util"
5757
. "github.com/alibaba/higress/pkg/ingress/log"
58+
k8serrors "k8s.io/apimachinery/pkg/api/errors"
5859
)
5960

6061
var (
@@ -87,8 +88,6 @@ type controller struct {
8788
secretController secret.SecretController
8889

8990
statusSyncer *statusSyncer
90-
91-
configMgr *cert.ConfigMgr
9291
}
9392

9493
// NewController creates a new Kubernetes controller
@@ -107,7 +106,6 @@ func NewController(localKubeClient, client kubeclient.Client, options common.Opt
107106
IngressLog.Infof("Skipping IngressClass, resource not supported for cluster %s", options.ClusterId)
108107
}
109108

110-
configMgr, _ := cert.NewConfigMgr(options.SystemNamespace, client.Kube())
111109
c := &controller{
112110
options: options,
113111
queue: q,
@@ -118,7 +116,6 @@ func NewController(localKubeClient, client kubeclient.Client, options common.Opt
118116
serviceInformer: serviceInformer.Informer(),
119117
serviceLister: serviceInformer.Lister(),
120118
secretController: secretController,
121-
configMgr: configMgr,
122119
}
123120

124121
handler := controllers.LatestVersionHandlerFuncs(controllers.EnqueueForSelf(q))
@@ -354,7 +351,7 @@ func extractTLSSecretName(host string, tls []ingress.IngressTLS) string {
354351
return ""
355352
}
356353

357-
func (c *controller) ConvertGateway(convertOptions *common.ConvertOptions, wrapper *common.WrapperConfig) error {
354+
func (c *controller) ConvertGateway(convertOptions *common.ConvertOptions, wrapper *common.WrapperConfig, httpsCredentialConfig *cert.Config) error {
358355
if convertOptions == nil {
359356
return fmt.Errorf("convertOptions is nil")
360357
}
@@ -377,7 +374,6 @@ func (c *controller) ConvertGateway(convertOptions *common.ConvertOptions, wrapp
377374
common.IncrementInvalidIngress(c.options.ClusterId, common.EmptyRule)
378375
return fmt.Errorf("invalid ingress rule %s:%s in cluster %s, either `defaultBackend` or `rules` must be specified", cfg.Namespace, cfg.Name, c.options.ClusterId)
379376
}
380-
httpsCredentialConfig, _ := c.configMgr.GetConfigFromConfigmap()
381377
for _, rule := range ingressV1Beta.Rules {
382378
// Need create builder for every rule.
383379
domainBuilder := &common.IngressDomainBuilder{
@@ -429,10 +425,23 @@ func (c *controller) ConvertGateway(convertOptions *common.ConvertOptions, wrapp
429425
// Get tls secret matching the rule host
430426
secretName := extractTLSSecretName(rule.Host, ingressV1Beta.TLS)
431427
secretNamespace := cfg.Namespace
432-
// If there is no matching secret, try to get it from configmap.
433-
if secretName == "" && httpsCredentialConfig != nil {
434-
secretName = httpsCredentialConfig.MatchSecretNameByDomain(rule.Host)
435-
secretNamespace = c.options.SystemNamespace
428+
if secretName != "" {
429+
if httpsCredentialConfig != nil && httpsCredentialConfig.FallbackForInvalidSecret {
430+
_, err := c.secretController.Lister().Secrets(secretNamespace).Get(secretName)
431+
if err != nil {
432+
if k8serrors.IsNotFound(err) {
433+
// If there is no matching secret, try to get it from configmap.
434+
secretName = httpsCredentialConfig.MatchSecretNameByDomain(rule.Host)
435+
secretNamespace = c.options.SystemNamespace
436+
}
437+
}
438+
}
439+
} else {
440+
// If there is no matching secret, try to get it from configmap.
441+
if httpsCredentialConfig != nil {
442+
secretName = httpsCredentialConfig.MatchSecretNameByDomain(rule.Host)
443+
secretNamespace = c.options.SystemNamespace
444+
}
436445
}
437446
if secretName == "" {
438447
// There no matching secret, so just skip.

pkg/ingress/kube/ingress/controller_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ func testConvertGateway(t *testing.T, c common.IngressController) {
334334
}
335335

336336
for _, testcase := range testcases {
337-
err := c.ConvertGateway(testcase.input.options, testcase.input.wrapperConfig)
337+
err := c.ConvertGateway(testcase.input.options, testcase.input.wrapperConfig, nil)
338338
if err != nil {
339339
require.Equal(t, testcase.expectNoError, false)
340340
} else {

pkg/ingress/kube/ingressv1/controller.go

+20-10
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ import (
5454
"github.com/alibaba/higress/pkg/ingress/kube/secret"
5555
"github.com/alibaba/higress/pkg/ingress/kube/util"
5656
. "github.com/alibaba/higress/pkg/ingress/log"
57+
k8serrors "k8s.io/apimachinery/pkg/api/errors"
5758
)
5859

5960
var (
@@ -85,8 +86,6 @@ type controller struct {
8586
secretController secret.SecretController
8687

8788
statusSyncer *statusSyncer
88-
89-
configMgr *cert.ConfigMgr
9089
}
9190

9291
// NewController creates a new Kubernetes controller
@@ -99,7 +98,6 @@ func NewController(localKubeClient, client kubeclient.Client, options common.Opt
9998
classes := client.KubeInformer().Networking().V1().IngressClasses()
10099
classes.Informer()
101100

102-
configMgr, _ := cert.NewConfigMgr(options.SystemNamespace, client.Kube())
103101
c := &controller{
104102
options: options,
105103
queue: q,
@@ -110,7 +108,6 @@ func NewController(localKubeClient, client kubeclient.Client, options common.Opt
110108
serviceInformer: serviceInformer.Informer(),
111109
serviceLister: serviceInformer.Lister(),
112110
secretController: secretController,
113-
configMgr: configMgr,
114111
}
115112

116113
handler := controllers.LatestVersionHandlerFuncs(controllers.EnqueueForSelf(q))
@@ -346,7 +343,7 @@ func extractTLSSecretName(host string, tls []ingress.IngressTLS) string {
346343
return ""
347344
}
348345

349-
func (c *controller) ConvertGateway(convertOptions *common.ConvertOptions, wrapper *common.WrapperConfig) error {
346+
func (c *controller) ConvertGateway(convertOptions *common.ConvertOptions, wrapper *common.WrapperConfig, httpsCredentialConfig *cert.Config) error {
350347
// Ignore canary config.
351348
if wrapper.AnnotationsConfig.IsCanary() {
352349
return nil
@@ -363,7 +360,6 @@ func (c *controller) ConvertGateway(convertOptions *common.ConvertOptions, wrapp
363360
return fmt.Errorf("invalid ingress rule %s:%s in cluster %s, either `defaultBackend` or `rules` must be specified", cfg.Namespace, cfg.Name, c.options.ClusterId)
364361
}
365362

366-
httpsCredentialConfig, _ := c.configMgr.GetConfigFromConfigmap()
367363
for _, rule := range ingressV1.Rules {
368364
// Need create builder for every rule.
369365
domainBuilder := &common.IngressDomainBuilder{
@@ -415,11 +411,25 @@ func (c *controller) ConvertGateway(convertOptions *common.ConvertOptions, wrapp
415411
// Get tls secret matching the rule host
416412
secretName := extractTLSSecretName(rule.Host, ingressV1.TLS)
417413
secretNamespace := cfg.Namespace
418-
// If there is no matching secret, try to get it from configmap.
419-
if secretName == "" && httpsCredentialConfig != nil {
420-
secretName = httpsCredentialConfig.MatchSecretNameByDomain(rule.Host)
421-
secretNamespace = c.options.SystemNamespace
414+
if secretName != "" {
415+
if httpsCredentialConfig != nil && httpsCredentialConfig.FallbackForInvalidSecret {
416+
_, err := c.secretController.Lister().Secrets(secretNamespace).Get(secretName)
417+
if err != nil {
418+
if k8serrors.IsNotFound(err) {
419+
// If there is no matching secret, try to get it from configmap.
420+
secretName = httpsCredentialConfig.MatchSecretNameByDomain(rule.Host)
421+
secretNamespace = c.options.SystemNamespace
422+
}
423+
}
424+
}
425+
} else {
426+
// If there is no matching secret, try to get it from configmap.
427+
if httpsCredentialConfig != nil {
428+
secretName = httpsCredentialConfig.MatchSecretNameByDomain(rule.Host)
429+
secretNamespace = c.options.SystemNamespace
430+
}
422431
}
432+
423433
if secretName == "" {
424434
// There no matching secret, so just skip.
425435
continue

0 commit comments

Comments
 (0)