mirror of
https://github.com/alibaba/higress.git
synced 2026-06-24 09:45:16 +08:00
fix: add full push when higress-https configmap updated and fix certmagic storage (#1105)
This commit is contained in:
4
go.mod
4
go.mod
@@ -255,7 +255,6 @@ require (
|
|||||||
go.opentelemetry.io/proto/otlp v0.12.0 // indirect
|
go.opentelemetry.io/proto/otlp v0.12.0 // indirect
|
||||||
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect
|
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
go.uber.org/zap v1.24.0 // indirect
|
|
||||||
golang.org/x/crypto v0.17.0 // indirect
|
golang.org/x/crypto v0.17.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect
|
golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect
|
||||||
golang.org/x/mod v0.11.0 // indirect
|
golang.org/x/mod v0.11.0 // indirect
|
||||||
@@ -304,7 +303,7 @@ replace istio.io/client-go => ./external/client-go
|
|||||||
|
|
||||||
replace istio.io/istio => ./external/istio
|
replace istio.io/istio => ./external/istio
|
||||||
|
|
||||||
replace github.com/caddyserver/certmagic => github.com/2456868764/certmagic v1.0.1
|
replace github.com/caddyserver/certmagic => github.com/2456868764/certmagic v1.0.2
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/caddyserver/certmagic v0.20.0
|
github.com/caddyserver/certmagic v0.20.0
|
||||||
@@ -313,6 +312,7 @@ require (
|
|||||||
github.com/kylelemons/godebug v1.1.0
|
github.com/kylelemons/godebug v1.1.0
|
||||||
github.com/mholt/acmez v1.2.0
|
github.com/mholt/acmez v1.2.0
|
||||||
github.com/tidwall/gjson v1.17.0
|
github.com/tidwall/gjson v1.17.0
|
||||||
|
go.uber.org/zap v1.24.0
|
||||||
golang.org/x/net v0.17.0
|
golang.org/x/net v0.17.0
|
||||||
helm.sh/helm/v3 v3.7.1
|
helm.sh/helm/v3 v3.7.1
|
||||||
k8s.io/apiextensions-apiserver v0.25.4
|
k8s.io/apiextensions-apiserver v0.25.4
|
||||||
|
|||||||
4
go.sum
4
go.sum
@@ -61,8 +61,8 @@ dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBr
|
|||||||
dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4=
|
dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4=
|
||||||
dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
|
dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
|
||||||
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
|
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
|
||||||
github.com/2456868764/certmagic v1.0.1 h1:dRzow2Npe9llFTBhNVl0fVe8Yi/Q14ygNonlaZUyDZQ=
|
github.com/2456868764/certmagic v1.0.2 h1:xYoN4z6seONwT85llWXZcASvQME8TOSiSWQvLJsGGsE=
|
||||||
github.com/2456868764/certmagic v1.0.1/go.mod h1:LOn81EQYMPajdew6Ln6SVdHPxPqPv6jwsUg92kiNlcQ=
|
github.com/2456868764/certmagic v1.0.2/go.mod h1:LOn81EQYMPajdew6Ln6SVdHPxPqPv6jwsUg92kiNlcQ=
|
||||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20210929163055-e81b3f25be97/go.mod h1:WpB7kf89yJUETZxQnP1kgYPNwlT2jjdDYUCoxVggM3g=
|
github.com/AdaLogics/go-fuzz-headers v0.0.0-20210929163055-e81b3f25be97/go.mod h1:WpB7kf89yJUETZxQnP1kgYPNwlT2jjdDYUCoxVggM3g=
|
||||||
github.com/AlecAivazis/survey/v2 v2.3.6 h1:NvTuVHISgTHEHeBFqt6BHOe4Ny/NwGZr7w+F8S9ziyw=
|
github.com/AlecAivazis/survey/v2 v2.3.6 h1:NvTuVHISgTHEHeBFqt6BHOe4Ny/NwGZr7w+F8S9ziyw=
|
||||||
github.com/AlecAivazis/survey/v2 v2.3.6/go.mod h1:4AuI9b7RjAR+G7v9+C4YSlX/YL3K3cWNXgWXOhllqvI=
|
github.com/AlecAivazis/survey/v2 v2.3.6/go.mod h1:4AuI9b7RjAR+G7v9+C4YSlX/YL3K3cWNXgWXOhllqvI=
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ rules:
|
|||||||
# ingress controller
|
# ingress controller
|
||||||
- apiGroups: ["extensions", "networking.k8s.io"]
|
- apiGroups: ["extensions", "networking.k8s.io"]
|
||||||
resources: ["ingresses"]
|
resources: ["ingresses"]
|
||||||
verbs: ["get", "list", "watch"]
|
verbs: ["create", "get", "list", "watch", "update", "delete", "patch"]
|
||||||
- apiGroups: ["extensions", "networking.k8s.io"]
|
- apiGroups: ["extensions", "networking.k8s.io"]
|
||||||
resources: ["ingresses/status"]
|
resources: ["ingresses/status"]
|
||||||
verbs: ["*"]
|
verbs: ["*"]
|
||||||
|
|||||||
@@ -391,7 +391,7 @@ func (s *Server) initAutomaticHttps() error {
|
|||||||
ServerAddress: s.CertHttpAddress,
|
ServerAddress: s.CertHttpAddress,
|
||||||
Email: s.AutomaticHttpsEmail,
|
Email: s.AutomaticHttpsEmail,
|
||||||
}
|
}
|
||||||
certServer, err := cert.NewServer(s.kubeClient.Kube(), certOption)
|
certServer, err := cert.NewServer(s.kubeClient.Kube(), s.xdsServer, certOption)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,10 +17,15 @@ package cert
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"reflect"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/caddyserver/certmagic"
|
"github.com/caddyserver/certmagic"
|
||||||
"github.com/mholt/acmez"
|
"github.com/mholt/acmez"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
"go.uber.org/zap/zapcore"
|
||||||
|
"istio.io/istio/pilot/pkg/model"
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -28,6 +33,10 @@ const (
|
|||||||
EventCertObtained = "cert_obtained"
|
EventCertObtained = "cert_obtained"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
cfg *certmagic.Config
|
||||||
|
)
|
||||||
|
|
||||||
type CertMgr struct {
|
type CertMgr struct {
|
||||||
cfg *certmagic.Config
|
cfg *certmagic.Config
|
||||||
client kubernetes.Interface
|
client kubernetes.Interface
|
||||||
@@ -39,9 +48,10 @@ type CertMgr struct {
|
|||||||
ingressSolver acmez.Solver
|
ingressSolver acmez.Solver
|
||||||
configMgr *ConfigMgr
|
configMgr *ConfigMgr
|
||||||
secretMgr *SecretMgr
|
secretMgr *SecretMgr
|
||||||
|
XDSUpdater model.XDSUpdater
|
||||||
}
|
}
|
||||||
|
|
||||||
func InitCertMgr(opts *Option, clientSet kubernetes.Interface, config *Config) (*CertMgr, error) {
|
func InitCertMgr(opts *Option, clientSet kubernetes.Interface, config *Config, XDSUpdater model.XDSUpdater, configMgr *ConfigMgr) (*CertMgr, error) {
|
||||||
CertLog.Infof("certmgr init config: %+v", config)
|
CertLog.Infof("certmgr init config: %+v", config)
|
||||||
// Init certmagic config
|
// Init certmagic config
|
||||||
// First make a pointer to a Cache as we need to reference the same Cache in
|
// First make a pointer to a Cache as we need to reference the same Cache in
|
||||||
@@ -49,21 +59,29 @@ func InitCertMgr(opts *Option, clientSet kubernetes.Interface, config *Config) (
|
|||||||
var cache *certmagic.Cache
|
var cache *certmagic.Cache
|
||||||
var storage certmagic.Storage
|
var storage certmagic.Storage
|
||||||
storage, _ = NewConfigmapStorage(opts.Namespace, clientSet)
|
storage, _ = NewConfigmapStorage(opts.Namespace, clientSet)
|
||||||
renewalWindowRatio := float64(config.RenewBeforeDays / RenewMaxDays)
|
renewalWindowRatio := float64(config.RenewBeforeDays) / float64(RenewMaxDays)
|
||||||
|
logger := zap.New(zapcore.NewCore(
|
||||||
|
zapcore.NewConsoleEncoder(zap.NewProductionEncoderConfig()),
|
||||||
|
os.Stderr,
|
||||||
|
zap.DebugLevel,
|
||||||
|
))
|
||||||
magicConfig := certmagic.Config{
|
magicConfig := certmagic.Config{
|
||||||
RenewalWindowRatio: renewalWindowRatio,
|
RenewalWindowRatio: renewalWindowRatio,
|
||||||
Storage: storage,
|
Storage: storage,
|
||||||
|
Logger: logger,
|
||||||
}
|
}
|
||||||
cache = certmagic.NewCache(certmagic.CacheOptions{
|
cache = certmagic.NewCache(certmagic.CacheOptions{
|
||||||
GetConfigForCert: func(cert certmagic.Certificate) (*certmagic.Config, error) {
|
GetConfigForCert: func(cert certmagic.Certificate) (*certmagic.Config, error) {
|
||||||
// Here we use New to get a valid Config associated with the same cache.
|
// Here we use New to get a valid Config associated with the same cache.
|
||||||
// The provided Config is used as a template and will be completed with
|
// The provided Config is used as a template and will be completed with
|
||||||
// any defaults that are set in the Default config.
|
// any defaults that are set in the Default config.
|
||||||
return certmagic.New(cache, magicConfig), nil
|
return cfg, nil
|
||||||
},
|
},
|
||||||
|
Logger: logger,
|
||||||
})
|
})
|
||||||
// init certmagic
|
// init certmagic
|
||||||
cfg := certmagic.New(cache, magicConfig)
|
cfg = certmagic.New(cache, magicConfig)
|
||||||
|
|
||||||
// Init certmagic acme
|
// Init certmagic acme
|
||||||
issuer := config.GetIssuer(IssuerTypeLetsencrypt)
|
issuer := config.GetIssuer(IssuerTypeLetsencrypt)
|
||||||
if issuer == nil {
|
if issuer == nil {
|
||||||
@@ -85,7 +103,6 @@ func InitCertMgr(opts *Option, clientSet kubernetes.Interface, config *Config) (
|
|||||||
// init issuers
|
// init issuers
|
||||||
cfg.Issuers = []certmagic.Issuer{myACME}
|
cfg.Issuers = []certmagic.Issuer{myACME}
|
||||||
|
|
||||||
configMgr, _ := NewConfigMgr(opts.Namespace, clientSet)
|
|
||||||
secretMgr, _ := NewSecretMgr(opts.Namespace, clientSet)
|
secretMgr, _ := NewSecretMgr(opts.Namespace, clientSet)
|
||||||
|
|
||||||
certMgr := &CertMgr{
|
certMgr := &CertMgr{
|
||||||
@@ -97,6 +114,7 @@ func InitCertMgr(opts *Option, clientSet kubernetes.Interface, config *Config) (
|
|||||||
configMgr: configMgr,
|
configMgr: configMgr,
|
||||||
secretMgr: secretMgr,
|
secretMgr: secretMgr,
|
||||||
cache: cache,
|
cache: cache,
|
||||||
|
XDSUpdater: XDSUpdater,
|
||||||
}
|
}
|
||||||
certMgr.cfg.OnEvent = certMgr.OnEvent
|
certMgr.cfg.OnEvent = certMgr.OnEvent
|
||||||
return certMgr, nil
|
return certMgr, nil
|
||||||
@@ -149,18 +167,31 @@ func (s *CertMgr) Reconcile(ctx context.Context, oldConfig *Config, newConfig *C
|
|||||||
// sync email
|
// sync email
|
||||||
s.myACME.Email = newIssuer.Email
|
s.myACME.Email = newIssuer.Email
|
||||||
// sync RenewalWindowRatio
|
// sync RenewalWindowRatio
|
||||||
s.cfg.RenewalWindowRatio = float64(newConfig.RenewBeforeDays / RenewMaxDays)
|
renewalWindowRatio := float64(newConfig.RenewBeforeDays) / float64(RenewMaxDays)
|
||||||
|
s.cfg.RenewalWindowRatio = renewalWindowRatio
|
||||||
// start cache
|
// start cache
|
||||||
s.cache.Start()
|
s.cache.Start()
|
||||||
// sync domains
|
// sync domains
|
||||||
s.manageSync(context.Background(), newDomains)
|
|
||||||
s.configMgr.SetConfig(newConfig)
|
s.configMgr.SetConfig(newConfig)
|
||||||
|
CertLog.Infof("certMgr start to manageSync domains:+v%", newDomains)
|
||||||
|
s.manageSync(context.Background(), newDomains)
|
||||||
|
CertLog.Infof("certMgr manageSync domains done")
|
||||||
} else {
|
} else {
|
||||||
// stop cache maintainAssets
|
// stop cache maintainAssets
|
||||||
s.cache.Stop()
|
s.cache.Stop()
|
||||||
s.configMgr.SetConfig(newConfig)
|
s.configMgr.SetConfig(newConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if oldConfig != nil && newConfig != nil {
|
||||||
|
if oldConfig.FallbackForInvalidSecret != newConfig.FallbackForInvalidSecret || !reflect.DeepEqual(oldConfig.CredentialConfig, newConfig.CredentialConfig) {
|
||||||
|
CertLog.Infof("ingress need to full push")
|
||||||
|
s.XDSUpdater.ConfigUpdate(&model.PushRequest{
|
||||||
|
Full: true,
|
||||||
|
Reason: []model.TriggerReason{"higress-https-updated"},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -99,8 +99,9 @@ func ParseTLSSecret(tlsSecret string) (string, string) {
|
|||||||
|
|
||||||
func (c *Config) Validate() error {
|
func (c *Config) Validate() error {
|
||||||
// check acmeIssuer
|
// check acmeIssuer
|
||||||
|
if c.AutomaticHttps {
|
||||||
if len(c.ACMEIssuer) == 0 {
|
if len(c.ACMEIssuer) == 0 {
|
||||||
return fmt.Errorf("acmeIssuer is empty")
|
return fmt.Errorf("no acmeIssuer configuration found when automaticHttps is enable")
|
||||||
}
|
}
|
||||||
for _, issuer := range c.ACMEIssuer {
|
for _, issuer := range c.ACMEIssuer {
|
||||||
switch issuer.Name {
|
switch issuer.Name {
|
||||||
@@ -115,6 +116,7 @@ func (c *Config) Validate() error {
|
|||||||
return fmt.Errorf("acmeIssuer name %s is not supported", issuer.Name)
|
return fmt.Errorf("acmeIssuer name %s is not supported", issuer.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// check credentialConfig
|
// check credentialConfig
|
||||||
for _, credential := range c.CredentialConfig {
|
for _, credential := range c.CredentialConfig {
|
||||||
if len(credential.Domains) == 0 {
|
if len(credential.Domains) == 0 {
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ func NewSecretMgr(namespace string, client kubernetes.Interface) (*SecretMgr, er
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *SecretMgr) Update(domain string, secretName string, privateKey []byte, certificate []byte, notBefore time.Time, notAfter time.Time, isRenew bool) error {
|
func (s *SecretMgr) Update(domain string, secretName string, privateKey []byte, certificate []byte, notBefore time.Time, notAfter time.Time, isRenew bool) error {
|
||||||
|
CertLog.Infof("update secret, domain:%s, secretName:%s, notBefore:%v, notAfter:%v, isRenew:%t", domain, secretName, notBefore, notAfter, isRenew)
|
||||||
name := secretName
|
name := secretName
|
||||||
namespace := s.namespace
|
namespace := s.namespace
|
||||||
namespaceP, secretP := ParseTLSSecret(secretName)
|
namespaceP, secretP := ParseTLSSecret(secretName)
|
||||||
@@ -77,6 +78,7 @@ func (s *SecretMgr) constructSecret(domain string, name string, namespace string
|
|||||||
annotationMap["higress.io/cert-notAfter"] = notAfter.Format("2006-01-02 15:04:05")
|
annotationMap["higress.io/cert-notAfter"] = notAfter.Format("2006-01-02 15:04:05")
|
||||||
annotationMap["higress.io/cert-notBefore"] = notBefore.Format("2006-01-02 15:04:05")
|
annotationMap["higress.io/cert-notBefore"] = notBefore.Format("2006-01-02 15:04:05")
|
||||||
annotationMap["higress.io/cert-renew"] = strconv.FormatBool(isRenew)
|
annotationMap["higress.io/cert-renew"] = strconv.FormatBool(isRenew)
|
||||||
|
annotationMap["higress.io/cert-source"] = string(IssuerTypeLetsencrypt)
|
||||||
if isRenew {
|
if isRenew {
|
||||||
annotationMap["higress.io/cert-renew-time"] = time.Now().Format("2006-01-02 15:04:05")
|
annotationMap["higress.io/cert-renew-time"] = time.Now().Format("2006-01-02 15:04:05")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/caddyserver/certmagic"
|
"github.com/caddyserver/certmagic"
|
||||||
|
"istio.io/istio/pilot/pkg/model"
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -37,12 +38,14 @@ type Server struct {
|
|||||||
clientSet kubernetes.Interface
|
clientSet kubernetes.Interface
|
||||||
controller *Controller
|
controller *Controller
|
||||||
certMgr *CertMgr
|
certMgr *CertMgr
|
||||||
|
XDSUpdater model.XDSUpdater
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServer(clientSet kubernetes.Interface, opts *Option) (*Server, error) {
|
func NewServer(clientSet kubernetes.Interface, XDSUpdater model.XDSUpdater, opts *Option) (*Server, error) {
|
||||||
server := &Server{
|
server := &Server{
|
||||||
clientSet: clientSet,
|
clientSet: clientSet,
|
||||||
opts: opts,
|
opts: opts,
|
||||||
|
XDSUpdater: XDSUpdater,
|
||||||
}
|
}
|
||||||
return server, nil
|
return server, nil
|
||||||
}
|
}
|
||||||
@@ -65,7 +68,7 @@ func (s *Server) InitServer() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// init certmgr
|
// init certmgr
|
||||||
certMgr, err := InitCertMgr(s.opts, s.clientSet, defaultConfig) // config and start
|
certMgr, err := InitCertMgr(s.opts, s.clientSet, defaultConfig, s.XDSUpdater, configMgr) // config and start
|
||||||
s.certMgr = certMgr
|
s.certMgr = certMgr
|
||||||
// init controller
|
// init controller
|
||||||
controller, err := NewController(s.clientSet, s.opts.Namespace, certMgr, configMgr)
|
controller, err := NewController(s.clientSet, s.opts.Namespace, certMgr, configMgr)
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
CertificatesPrefix = "/certificates"
|
CertificatesPrefix = "certificates"
|
||||||
ConfigmapStoreCertficatesPrefix = "higress-cert-store-certificates-"
|
ConfigmapStoreCertficatesPrefix = "higress-cert-store-certificates-"
|
||||||
ConfigmapStoreDefaultName = "higress-cert-store-default"
|
ConfigmapStoreDefaultName = "higress-cert-store-default"
|
||||||
)
|
)
|
||||||
@@ -155,7 +155,7 @@ func (s *ConfigmapStorage) List(ctx context.Context, prefix string, recursive bo
|
|||||||
// Check if the prefix corresponds to a specific key
|
// Check if the prefix corresponds to a specific key
|
||||||
hashPrefix := fastHash([]byte(prefix))
|
hashPrefix := fastHash([]byte(prefix))
|
||||||
if strings.HasPrefix(prefix, CertificatesPrefix) {
|
if strings.HasPrefix(prefix, CertificatesPrefix) {
|
||||||
// If the prefix is "/certificates", get all ConfigMaps and traverse each one
|
// If the prefix is "certificates/", get all ConfigMaps and traverse each one
|
||||||
// List all ConfigMaps in the namespace with label higress.io/cert-https=true
|
// List all ConfigMaps in the namespace with label higress.io/cert-https=true
|
||||||
configmaps, err := s.client.CoreV1().ConfigMaps(s.namespace).List(ctx, metav1.ListOptions{FieldSelector: "metadata.annotations['higress.io/cert-https'] == 'true'"})
|
configmaps, err := s.client.CoreV1().ConfigMaps(s.namespace).List(ctx, metav1.ListOptions{FieldSelector: "metadata.annotations['higress.io/cert-https'] == 'true'"})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -289,15 +289,30 @@ func (s *ConfigmapStorage) String() string {
|
|||||||
return "ConfigmapStorage"
|
return "ConfigmapStorage"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getConfigmapStoreNameByKey determines the storage name for a given key.
|
||||||
|
// It checks if the key starts with 'certificates/' and if so, the key pattern should match one of the following:
|
||||||
|
// 'certificates/<issuerKey>/<domain>/<domain>.json',
|
||||||
|
// 'certificates/<issuerKey>/<domain>/<domain>.crt',
|
||||||
|
// or 'certificates/<issuerKey>/<domain>/<domain>.key'.
|
||||||
|
// It then returns the corresponding ConfigMap name.
|
||||||
|
// If the key does not start with 'certificates/', it returns the default store name.
|
||||||
|
//
|
||||||
|
// Parameters:
|
||||||
|
//
|
||||||
|
// key - The configuration map key that needs to be mapped to a storage name.
|
||||||
|
//
|
||||||
|
// Returns:
|
||||||
|
//
|
||||||
|
// string - The calculated or default storage name based on the key.
|
||||||
func (s *ConfigmapStorage) getConfigmapStoreNameByKey(key string) string {
|
func (s *ConfigmapStorage) getConfigmapStoreNameByKey(key string) string {
|
||||||
parts := strings.SplitN(key, "/", 10)
|
if strings.HasPrefix(key, "certificates/") {
|
||||||
if len(parts) >= 4 && parts[1] == "certificates" {
|
parts := strings.Split(key, "/")
|
||||||
domain := strings.TrimSuffix(parts[3], ".crt")
|
if len(parts) >= 4 && parts[0] == "certificates" {
|
||||||
domain = strings.TrimSuffix(domain, ".key")
|
domain := parts[2]
|
||||||
domain = strings.TrimSuffix(domain, ".json")
|
issuerKey := parts[1]
|
||||||
issuerKey := parts[2]
|
|
||||||
return ConfigmapStoreCertficatesPrefix + fastHash([]byte(issuerKey+domain))
|
return ConfigmapStoreCertficatesPrefix + fastHash([]byte(issuerKey+domain))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return ConfigmapStoreDefaultName
|
return ConfigmapStoreDefaultName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,22 +39,29 @@ func TestGetConfigmapStoreNameByKey(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "certificate crt",
|
name: "certificate crt",
|
||||||
key: "/certificates/issuerKey/domain.crt",
|
key: "certificates/issuerKey/domain/domain.crt",
|
||||||
expected: "higress-cert-store-certificates-" + fastHash([]byte("issuerKey"+"domain")),
|
expected: "higress-cert-store-certificates-" + fastHash([]byte("issuerKey"+"domain")),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
name: "47.237.14.136.sslip.io crt",
|
||||||
|
key: "certificates/acme-v02.api.letsencrypt.org-directory/47.237.14.136.sslip.io/47.237.14.136.sslip.io.crt",
|
||||||
|
expected: "higress-cert-store-certificates-" + fastHash([]byte("acme-v02.api.letsencrypt.org-directory"+"47.237.14.136.sslip.io")),
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
name: "certificate meta",
|
name: "certificate meta",
|
||||||
key: "/certificates/issuerKey/domain.json",
|
key: "certificates/issuerKey/domain/domain.json",
|
||||||
expected: "higress-cert-store-certificates-" + fastHash([]byte("issuerKey"+"domain")),
|
expected: "higress-cert-store-certificates-" + fastHash([]byte("issuerKey"+"domain")),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "certificate key",
|
name: "certificate key",
|
||||||
key: "/certificates/issuerKey/domain.key",
|
key: "certificates/issuerKey/domain/domain.key",
|
||||||
expected: "higress-cert-store-certificates-" + fastHash([]byte("issuerKey"+"domain")),
|
expected: "higress-cert-store-certificates-" + fastHash([]byte("issuerKey"+"domain")),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "user key",
|
name: "user key",
|
||||||
key: "/users/hello/2",
|
key: "users/hello/2",
|
||||||
expected: "higress-cert-store-default",
|
expected: "higress-cert-store-default",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -82,7 +89,7 @@ func TestExists(t *testing.T) {
|
|||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
// Store a test key
|
// Store a test key
|
||||||
testKey := "/certificates/issuer1/domain1.crt"
|
testKey := "certificates/issuer1/domain1/domain1.crt"
|
||||||
err = storage.Store(context.Background(), testKey, []byte("test-data"))
|
err = storage.Store(context.Background(), testKey, []byte("test-data"))
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
@@ -94,17 +101,17 @@ func TestExists(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "Existing Key",
|
name: "Existing Key",
|
||||||
key: "/certificates/issuer1/domain1.crt",
|
key: "certificates/issuer1/domain1/domain1.crt",
|
||||||
shouldExist: true,
|
shouldExist: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Non-Existent Key1",
|
name: "Non-Existent Key1",
|
||||||
key: "/certificates/issuer2/domain2.crt",
|
key: "certificates/issuer2/domain2/domain2.crt",
|
||||||
shouldExist: false,
|
shouldExist: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Non-Existent Key2",
|
name: "Non-Existent Key2",
|
||||||
key: "/users/hello/a",
|
key: "users/hello/a",
|
||||||
shouldExist: false,
|
shouldExist: false,
|
||||||
},
|
},
|
||||||
// Add more test cases as needed
|
// Add more test cases as needed
|
||||||
@@ -129,7 +136,7 @@ func TestLoad(t *testing.T) {
|
|||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
// Store a test key
|
// Store a test key
|
||||||
testKey := "/certificates/issuer1/domain1.crt"
|
testKey := "certificates/issuer1/domain1/domain1.crt"
|
||||||
testValue := []byte("test-data")
|
testValue := []byte("test-data")
|
||||||
err = storage.Store(context.Background(), testKey, testValue)
|
err = storage.Store(context.Background(), testKey, testValue)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
@@ -143,13 +150,13 @@ func TestLoad(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "Existing Key",
|
name: "Existing Key",
|
||||||
key: "/certificates/issuer1/domain1.crt",
|
key: "certificates/issuer1/domain1/domain1.crt",
|
||||||
expected: testValue,
|
expected: testValue,
|
||||||
shouldError: false,
|
shouldError: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Non-Existent Key",
|
name: "Non-Existent Key",
|
||||||
key: "/certificates/issuer2/domain2.crt",
|
key: "certificates/issuer2/domain2/domain2.crt",
|
||||||
expected: nil,
|
expected: nil,
|
||||||
shouldError: true,
|
shouldError: true,
|
||||||
},
|
},
|
||||||
@@ -192,28 +199,28 @@ func TestStore(t *testing.T) {
|
|||||||
shouldError bool
|
shouldError bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "Store Key with /certificates prefix",
|
name: "Store Key with certificates prefix",
|
||||||
key: "/certificates/issuer1/domain1.crt",
|
key: "certificates/issuer1/domain1/domain1.crt",
|
||||||
value: []byte("test-data1"),
|
value: []byte("test-data1"),
|
||||||
expected: map[string]string{fastHash([]byte("/certificates/issuer1/domain1.crt")): `{"k":"/certificates/issuer1/domain1.crt","v":"dGVzdC1kYXRhMQ=="}`},
|
expected: map[string]string{fastHash([]byte("certificates/issuer1/domain1/domain1.crt")): `{"k":"certificates/issuer1/domain1/domain1.crt","v":"dGVzdC1kYXRhMQ=="}`},
|
||||||
expectedConfigmapName: "higress-cert-store-certificates-" + fastHash([]byte("issuer1"+"domain1")),
|
expectedConfigmapName: "higress-cert-store-certificates-" + fastHash([]byte("issuer1"+"domain1")),
|
||||||
shouldError: false,
|
shouldError: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Store Key with /certificates prefix (additional data)",
|
name: "Store Key with certificates prefix (additional data)",
|
||||||
key: "/certificates/issuer2/domain2.crt",
|
key: "certificates/issuer2/domain2/domain2.crt",
|
||||||
value: []byte("test-data2"),
|
value: []byte("test-data2"),
|
||||||
expected: map[string]string{
|
expected: map[string]string{
|
||||||
fastHash([]byte("/certificates/issuer2/domain2.crt")): `{"k":"/certificates/issuer2/domain2.crt","v":"dGVzdC1kYXRhMg=="}`,
|
fastHash([]byte("certificates/issuer2/domain2/domain2.crt")): `{"k":"certificates/issuer2/domain2/domain2.crt","v":"dGVzdC1kYXRhMg=="}`,
|
||||||
},
|
},
|
||||||
expectedConfigmapName: "higress-cert-store-certificates-" + fastHash([]byte("issuer2"+"domain2")),
|
expectedConfigmapName: "higress-cert-store-certificates-" + fastHash([]byte("issuer2"+"domain2")),
|
||||||
shouldError: false,
|
shouldError: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Store Key without /certificates prefix",
|
name: "Store Key without certificates prefix",
|
||||||
key: "/other/path/data.txt",
|
key: "other/path/data.txt",
|
||||||
value: []byte("test-data3"),
|
value: []byte("test-data3"),
|
||||||
expected: map[string]string{fastHash([]byte("/other/path/data.txt")): `{"k":"/other/path/data.txt","v":"dGVzdC1kYXRhMw=="}`},
|
expected: map[string]string{fastHash([]byte("other/path/data.txt")): `{"k":"other/path/data.txt","v":"dGVzdC1kYXRhMw=="}`},
|
||||||
expectedConfigmapName: "higress-cert-store-default",
|
expectedConfigmapName: "higress-cert-store-default",
|
||||||
shouldError: false,
|
shouldError: false,
|
||||||
},
|
},
|
||||||
@@ -256,17 +263,17 @@ func TestList(t *testing.T) {
|
|||||||
// Store some test data
|
// Store some test data
|
||||||
// Store some test data
|
// Store some test data
|
||||||
testKeys := []string{
|
testKeys := []string{
|
||||||
"/certificates/issuer1/domain1.crt",
|
"certificates/issuer1/domain1/domain1.crt",
|
||||||
"/certificates/issuer1/domain2.crt",
|
"certificates/issuer1/domain2/domain2.crt",
|
||||||
"/certificates/issuer1/domain3.crt", // Added another domain for issuer1
|
"certificates/issuer1/domain3/domain3.crt", // Added another domain for issuer1
|
||||||
"/certificates/issuer2/domain4.crt",
|
"certificates/issuer2/domain4/domain4.crt",
|
||||||
"/certificates/issuer2/domain5.crt",
|
"certificates/issuer2/domain5/domain5.crt",
|
||||||
"/certificates/issuer3/subdomain1/domain6.crt", // Two-level subdirectory under issuer3
|
"certificates/issuer3/domain6/domain6.crt", // Two-level subdirectory under issuer3
|
||||||
"/certificates/issuer3/subdomain1/subdomain2/domain7.crt", // Two more levels under issuer3
|
"certificates/issuer3/subdomain1/subdomain2/domain7.crt", // Two more levels under issuer3
|
||||||
"/other-prefix/key1/file1",
|
"other-prefix/key1/file1",
|
||||||
"/other-prefix/key1/file2",
|
"other-prefix/key1/file2",
|
||||||
"/other-prefix/key2/file3",
|
"other-prefix/key2/file3",
|
||||||
"/other-prefix/key2/file4",
|
"other-prefix/key2/file4",
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, key := range testKeys {
|
for _, key := range testKeys {
|
||||||
@@ -283,34 +290,34 @@ func TestList(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "List Certificates (Non-Recursive)",
|
name: "List Certificates (Non-Recursive)",
|
||||||
prefix: "/certificates",
|
prefix: "certificates",
|
||||||
recursive: false,
|
recursive: false,
|
||||||
expected: []string{"/certificates/issuer1", "/certificates/issuer2", "/certificates/issuer3"},
|
expected: []string{"certificates/issuer1", "certificates/issuer2", "certificates/issuer3"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "List Certificates (Recursive)",
|
name: "List Certificates (Recursive)",
|
||||||
prefix: "/certificates",
|
prefix: "certificates",
|
||||||
recursive: true,
|
recursive: true,
|
||||||
expected: []string{"/certificates/issuer1/domain1.crt", "/certificates/issuer1/domain2.crt", "/certificates/issuer1/domain3.crt", "/certificates/issuer2/domain4.crt", "/certificates/issuer2/domain5.crt", "/certificates/issuer3/subdomain1/domain6.crt", "/certificates/issuer3/subdomain1/subdomain2/domain7.crt"},
|
expected: []string{"certificates/issuer1/domain1/domain1.crt", "certificates/issuer1/domain2/domain2.crt", "certificates/issuer1/domain3/domain3.crt", "certificates/issuer2/domain4/domain4.crt", "certificates/issuer2/domain5/domain5.crt", "certificates/issuer3/domain6/domain6.crt", "certificates/issuer3/subdomain1/subdomain2/domain7.crt"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "List Other Prefix (Non-Recursive)",
|
name: "List Other Prefix (Non-Recursive)",
|
||||||
prefix: "/other-prefix",
|
prefix: "other-prefix",
|
||||||
recursive: false,
|
recursive: false,
|
||||||
expected: []string{"/other-prefix/key1", "/other-prefix/key2"},
|
expected: []string{"other-prefix/key1", "other-prefix/key2"},
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
name: "List Other Prefix (Non-Recursive)",
|
name: "List Other Prefix (Non-Recursive)",
|
||||||
prefix: "/other-prefix/key1",
|
prefix: "other-prefix/key1",
|
||||||
recursive: false,
|
recursive: false,
|
||||||
expected: []string{"/other-prefix/key1/file1", "/other-prefix/key1/file2"},
|
expected: []string{"other-prefix/key1/file1", "other-prefix/key1/file2"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "List Other Prefix (Recursive)",
|
name: "List Other Prefix (Recursive)",
|
||||||
prefix: "/other-prefix",
|
prefix: "other-prefix",
|
||||||
recursive: true,
|
recursive: true,
|
||||||
expected: []string{"/other-prefix/key1/file1", "/other-prefix/key1/file2", "/other-prefix/key2/file3", "/other-prefix/key2/file4"},
|
expected: []string{"other-prefix/key1/file1", "other-prefix/key1/file2", "other-prefix/key2/file3", "other-prefix/key2/file4"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user