Define TLS options on the Router configuration for Kubernetes
Co-authored-by: juliens <julien@containo.us>
This commit is contained in:
parent
69cf05df9a
commit
80b35575df
48 changed files with 2374 additions and 53 deletions
|
@ -118,7 +118,7 @@ func (p *Provider) Provide(configurationChan chan<- config.Message, pool *safe.P
|
|||
case <-stop:
|
||||
return nil
|
||||
case event := <-eventsChan:
|
||||
conf := p.loadConfigurationFromIngresses(ctxLog, k8sClient)
|
||||
conf := p.loadConfigurationFromCRD(ctxLog, k8sClient)
|
||||
|
||||
if reflect.DeepEqual(p.lastConfiguration.Get(), conf) {
|
||||
logger.Debugf("Skipping Kubernetes event kind %T", event)
|
||||
|
@ -293,19 +293,59 @@ func loadServers(client Client, namespace string, svc v1alpha1.Service) ([]confi
|
|||
return servers, nil
|
||||
}
|
||||
|
||||
func (p *Provider) loadConfigurationFromIngresses(ctx context.Context, client Client) *config.Configuration {
|
||||
conf := &config.Configuration{
|
||||
HTTP: &config.HTTPConfiguration{
|
||||
Routers: map[string]*config.Router{},
|
||||
Middlewares: map[string]*config.Middleware{},
|
||||
Services: map[string]*config.Service{},
|
||||
},
|
||||
TCP: &config.TCPConfiguration{
|
||||
Routers: map[string]*config.TCPRouter{},
|
||||
Services: map[string]*config.TCPService{},
|
||||
},
|
||||
func buildTLSOptions(ctx context.Context, client Client) map[string]tls.TLS {
|
||||
tlsOptionsCRD := client.GetTLSOptions()
|
||||
var tlsOptions map[string]tls.TLS
|
||||
|
||||
if len(tlsOptionsCRD) == 0 {
|
||||
return tlsOptions
|
||||
}
|
||||
tlsOptions = make(map[string]tls.TLS)
|
||||
|
||||
for _, tlsOption := range tlsOptionsCRD {
|
||||
logger := log.FromContext(log.With(ctx, log.Str("tlsOption", tlsOption.Name), log.Str("namespace", tlsOption.Namespace)))
|
||||
var clientCAs []tls.FileOrContent
|
||||
|
||||
for _, secretName := range tlsOption.Spec.ClientCA.SecretNames {
|
||||
secret, exists, err := client.GetSecret(tlsOption.Namespace, secretName)
|
||||
if err != nil {
|
||||
logger.Errorf("Failed to fetch secret %s/%s: %v", tlsOption.Namespace, secretName, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if !exists {
|
||||
logger.Warnf("Secret %s/%s does not exist", tlsOption.Namespace, secretName)
|
||||
continue
|
||||
}
|
||||
|
||||
cert, err := getCABlocks(secret, tlsOption.Namespace, secretName)
|
||||
if err != nil {
|
||||
logger.Errorf("Failed to extract CA from secret %s/%s: %v", tlsOption.Namespace, secretName, err)
|
||||
continue
|
||||
}
|
||||
|
||||
clientCAs = append(clientCAs, tls.FileOrContent(cert))
|
||||
}
|
||||
|
||||
tlsOptions[makeID(tlsOption.Namespace, tlsOption.Name)] = tls.TLS{
|
||||
MinVersion: tlsOption.Spec.MinVersion,
|
||||
CipherSuites: tlsOption.Spec.CipherSuites,
|
||||
ClientCA: tls.ClientCA{
|
||||
Files: clientCAs,
|
||||
Optional: tlsOption.Spec.ClientCA.Optional,
|
||||
},
|
||||
SniStrict: tlsOption.Spec.SniStrict,
|
||||
}
|
||||
}
|
||||
return tlsOptions
|
||||
}
|
||||
|
||||
func (p *Provider) loadIngressRouteConfiguration(ctx context.Context, client Client, tlsConfigs map[string]*tls.Configuration) *config.HTTPConfiguration {
|
||||
conf := &config.HTTPConfiguration{
|
||||
Routers: map[string]*config.Router{},
|
||||
Middlewares: map[string]*config.Middleware{},
|
||||
Services: map[string]*config.Service{},
|
||||
}
|
||||
tlsConfigs := make(map[string]*tls.Configuration)
|
||||
|
||||
for _, ingressRoute := range client.GetIngressRoutes() {
|
||||
logger := log.FromContext(log.With(ctx, log.Str("ingress", ingressRoute.Name), log.Str("namespace", ingressRoute.Namespace)))
|
||||
|
@ -377,17 +417,33 @@ func (p *Provider) loadConfigurationFromIngresses(ctx context.Context, client Cl
|
|||
|
||||
serviceName := makeID(ingressRoute.Namespace, key)
|
||||
|
||||
conf.HTTP.Routers[serviceName] = &config.Router{
|
||||
conf.Routers[serviceName] = &config.Router{
|
||||
Middlewares: mds,
|
||||
Priority: route.Priority,
|
||||
EntryPoints: ingressRoute.Spec.EntryPoints,
|
||||
Rule: route.Match,
|
||||
Service: serviceName,
|
||||
}
|
||||
|
||||
if ingressRoute.Spec.TLS != nil {
|
||||
conf.HTTP.Routers[serviceName].TLS = &config.RouterTLSConfig{}
|
||||
tlsConf := &config.RouterTLSConfig{}
|
||||
if ingressRoute.Spec.TLS.Options != nil && len(ingressRoute.Spec.TLS.Options.Name) > 0 {
|
||||
tlsOptionsName := ingressRoute.Spec.TLS.Options.Name
|
||||
// Is a Kubernetes CRD reference, (i.e. not a cross-provider default)
|
||||
if !strings.Contains(tlsOptionsName, "@") {
|
||||
ns := ingressRoute.Spec.TLS.Options.Namespace
|
||||
if len(ns) == 0 {
|
||||
ns = ingressRoute.Namespace
|
||||
}
|
||||
tlsOptionsName = makeID(ns, tlsOptionsName)
|
||||
}
|
||||
|
||||
tlsConf.Options = tlsOptionsName
|
||||
}
|
||||
conf.Routers[serviceName].TLS = tlsConf
|
||||
}
|
||||
conf.HTTP.Services[serviceName] = &config.Service{
|
||||
|
||||
conf.Services[serviceName] = &config.Service{
|
||||
LoadBalancer: &config.LoadBalancerService{
|
||||
Servers: allServers,
|
||||
// TODO: support other strategies.
|
||||
|
@ -397,8 +453,13 @@ func (p *Provider) loadConfigurationFromIngresses(ctx context.Context, client Cl
|
|||
}
|
||||
}
|
||||
|
||||
for _, middleware := range client.GetMiddlewares() {
|
||||
conf.HTTP.Middlewares[makeID(middleware.Namespace, middleware.Name)] = &middleware.Spec
|
||||
return conf
|
||||
}
|
||||
|
||||
func (p *Provider) loadIngressRouteTCPConfiguration(ctx context.Context, client Client, tlsConfigs map[string]*tls.Configuration) *config.TCPConfiguration {
|
||||
conf := &config.TCPConfiguration{
|
||||
Routers: map[string]*config.TCPRouter{},
|
||||
Services: map[string]*config.TCPService{},
|
||||
}
|
||||
|
||||
for _, ingressRouteTCP := range client.GetIngressRouteTCPs() {
|
||||
|
@ -452,19 +513,34 @@ func (p *Provider) loadConfigurationFromIngresses(ctx context.Context, client Cl
|
|||
}
|
||||
|
||||
serviceName := makeID(ingressRouteTCP.Namespace, key)
|
||||
conf.TCP.Routers[serviceName] = &config.TCPRouter{
|
||||
conf.Routers[serviceName] = &config.TCPRouter{
|
||||
EntryPoints: ingressRouteTCP.Spec.EntryPoints,
|
||||
Rule: route.Match,
|
||||
Service: serviceName,
|
||||
}
|
||||
|
||||
if ingressRouteTCP.Spec.TLS != nil {
|
||||
conf.TCP.Routers[serviceName].TLS = &config.RouterTCPTLSConfig{
|
||||
conf.Routers[serviceName].TLS = &config.RouterTCPTLSConfig{
|
||||
Passthrough: ingressRouteTCP.Spec.TLS.Passthrough,
|
||||
}
|
||||
|
||||
if ingressRouteTCP.Spec.TLS.Options != nil && len(ingressRouteTCP.Spec.TLS.Options.Name) > 0 {
|
||||
tlsOptionsName := ingressRouteTCP.Spec.TLS.Options.Name
|
||||
// Is a Kubernetes CRD reference (i.e. not a cross-provider reference)
|
||||
if !strings.Contains(tlsOptionsName, "@") {
|
||||
ns := ingressRouteTCP.Spec.TLS.Options.Namespace
|
||||
if len(ns) == 0 {
|
||||
ns = ingressRouteTCP.Namespace
|
||||
}
|
||||
tlsOptionsName = makeID(ns, tlsOptionsName)
|
||||
}
|
||||
|
||||
conf.Routers[serviceName].TLS.Options = tlsOptionsName
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
conf.TCP.Services[serviceName] = &config.TCPService{
|
||||
conf.Services[serviceName] = &config.TCPService{
|
||||
LoadBalancer: &config.TCPLoadBalancerService{
|
||||
Servers: allServers,
|
||||
},
|
||||
|
@ -472,7 +548,21 @@ func (p *Provider) loadConfigurationFromIngresses(ctx context.Context, client Cl
|
|||
}
|
||||
}
|
||||
|
||||
conf.TLS = getTLSConfig(tlsConfigs)
|
||||
return conf
|
||||
}
|
||||
|
||||
func (p *Provider) loadConfigurationFromCRD(ctx context.Context, client Client) *config.Configuration {
|
||||
tlsConfigs := make(map[string]*tls.Configuration)
|
||||
conf := &config.Configuration{
|
||||
HTTP: p.loadIngressRouteConfiguration(ctx, client, tlsConfigs),
|
||||
TCP: p.loadIngressRouteTCPConfiguration(ctx, client, tlsConfigs),
|
||||
TLSOptions: buildTLSOptions(ctx, client),
|
||||
TLS: getTLSConfig(tlsConfigs),
|
||||
}
|
||||
|
||||
for _, middleware := range client.GetMiddlewares() {
|
||||
conf.HTTP.Middlewares[makeID(middleware.Namespace, middleware.Name)] = &middleware.Spec
|
||||
}
|
||||
|
||||
return conf
|
||||
}
|
||||
|
@ -618,3 +708,19 @@ func getCertificateBlocks(secret *corev1.Secret, namespace, secretName string) (
|
|||
|
||||
return cert, key, nil
|
||||
}
|
||||
|
||||
func getCABlocks(secret *corev1.Secret, namespace, secretName string) (string, error) {
|
||||
tlsCrtData, tlsCrtExists := secret.Data["tls.ca"]
|
||||
if !tlsCrtExists {
|
||||
return "", fmt.Errorf("the tls.ca entry is missing from secret %s/%s",
|
||||
namespace, secretName)
|
||||
}
|
||||
|
||||
cert := string(tlsCrtData)
|
||||
if cert == "" {
|
||||
return "", fmt.Errorf("the tls.ca entry in secret %s/%s is empty",
|
||||
namespace, secretName)
|
||||
}
|
||||
|
||||
return cert, nil
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue