diff --git a/docs/content/routing/providers/kubernetes-crd.md b/docs/content/routing/providers/kubernetes-crd.md index 66da0fae3..df509be3f 100644 --- a/docs/content/routing/providers/kubernetes-crd.md +++ b/docs/content/routing/providers/kubernetes-crd.md @@ -1869,6 +1869,11 @@ Register the `TLSStore` kind in the Kubernetes cluster before creating `TLSStore - spiffe://trust-domain/id1 - spiffe://trust-domain/id2 trustDomain: "spiffe://trust-domain" # [14] + cipherSuites: # [15] + - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + minVersion: VersionTLS11 # [16] + maxVersion: VersionTLS12 # [17] ``` | Ref | Attribute | Purpose | @@ -1887,6 +1892,9 @@ Register the `TLSStore` kind in the Kubernetes cluster before creating `TLSStore | [12] | `spiffe` | The spiffe configuration. | | [13] | `ids` | Defines the allowed SPIFFE IDs (takes precedence over the SPIFFE TrustDomain). | | [14] | `trustDomain` | Defines the allowed SPIFFE trust domain. | +| [15] | `cipherSuites` | Defines a list of cipher to use to contact the backend servers. | +| [16] | `minVersion` | Defines TLS minimum version to use to contact the backend servers. | +| [17] | `maxVersion` | Defines TLS maximum version to use to contact the backend servers. | !!! info "CA Secret" diff --git a/docs/content/routing/services/index.md b/docs/content/routing/services/index.md index fddf2c953..c7a56f891 100644 --- a/docs/content/routing/services/index.md +++ b/docs/content/routing/services/index.md @@ -771,6 +771,103 @@ data: ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0= ``` +#### `cipherSuites` + +_Optional_ + +`cipherSuites` defines a list of cipher to use to contact the backend servers. + +```yaml tab="File (YAML)" +## Dynamic configuration +http: + serversTransports: + mytransport: + cipherSuites: + - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 +``` + +```toml tab="File (TOML)" +## Dynamic configuration +[http.serversTransports.mytransport] + cipherSuites = ["TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256","TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"] +``` + +```yaml tab="Kubernetes" +apiVersion: traefik.io/v1alpha1 +kind: ServersTransport +metadata: + name: mytransport + namespace: default + +spec: + cipherSuites: + - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 +``` + +#### `minVersion` + +_Optional_ + +`minVersion` defines TLS minimum version to use to contact the backend servers. + +```yaml tab="File (YAML)" +## Dynamic configuration +http: + serversTransports: + mytransport: + minVersion: VersionTLS12 +``` + +```toml tab="File (TOML)" +## Dynamic configuration +[http.serversTransports.mytransport] + minVersion = "VersionTLS12" +``` + +```yaml tab="Kubernetes" +apiVersion: traefik.io/v1alpha1 +kind: ServersTransport +metadata: + name: mytransport + namespace: default + +spec: + minVersion: VersionTLS12 +``` + +#### `maxVersion` + +_Optional_ + +`maxVersion` defines TLS maximum version to use to contact the backend servers. + +```yaml tab="File (YAML)" +## Dynamic configuration +http: + serversTransports: + mytransport: + maxVersion: VersionTLS12 +``` + +```toml tab="File (TOML)" +## Dynamic configuration +[http.serversTransports.mytransport] + maxVersion = "VersionTLS12" +``` + +```yaml tab="Kubernetes" +apiVersion: traefik.io/v1alpha1 +kind: ServersTransport +metadata: + name: mytransport + namespace: default + +spec: + maxVersion: VersionTLS12 +``` + #### `maxIdleConnsPerHost` _Optional, Default=2_ diff --git a/pkg/config/dynamic/http_config.go b/pkg/config/dynamic/http_config.go index 1ee393d1e..447ffd524 100644 --- a/pkg/config/dynamic/http_config.go +++ b/pkg/config/dynamic/http_config.go @@ -347,7 +347,9 @@ type ServersTransport struct { InsecureSkipVerify bool `description:"Disables SSL certificate verification." json:"insecureSkipVerify,omitempty" toml:"insecureSkipVerify,omitempty" yaml:"insecureSkipVerify,omitempty" export:"true"` RootCAs []types.FileOrContent `description:"Defines a list of CA certificates used to validate server certificates." json:"rootCAs,omitempty" toml:"rootCAs,omitempty" yaml:"rootCAs,omitempty"` Certificates traefiktls.Certificates `description:"Defines a list of client certificates for mTLS." json:"certificates,omitempty" toml:"certificates,omitempty" yaml:"certificates,omitempty" export:"true"` - CipherSuites []string `json:"cipherSuites,omitempty" toml:"cipherSuites,omitempty" yaml:"cipherSuites,omitempty" export:"true"` + CipherSuites []string `description:"Defines a list of cipher to use to contact the backend servers." json:"cipherSuites,omitempty" toml:"cipherSuites,omitempty" yaml:"cipherSuites,omitempty" export:"true"` + MinVersion string `description:"Defines a TLS minimum version to use to contact the backend servers." json:"minVersion,omitempty" toml:"minVersion,omitempty" yaml:"minVersion,omitempty" export:"true"` + MaxVersion string `description:"Defines a TLS maximum version to use to contact the backend servers." json:"maxVersion,omitempty" toml:"maxVersion,omitempty" yaml:"maxVersion,omitempty" export:"true"` MaxIdleConnsPerHost int `description:"If non-zero, controls the maximum idle (keep-alive) to keep per-host. If zero, DefaultMaxIdleConnsPerHost is used" json:"maxIdleConnsPerHost,omitempty" toml:"maxIdleConnsPerHost,omitempty" yaml:"maxIdleConnsPerHost,omitempty" export:"true"` ForwardingTimeouts *ForwardingTimeouts `description:"Defines the timeouts for requests forwarded to the backend servers." json:"forwardingTimeouts,omitempty" toml:"forwardingTimeouts,omitempty" yaml:"forwardingTimeouts,omitempty" export:"true"` DisableHTTP2 bool `description:"Disables HTTP/2 for connections with backend servers." json:"disableHTTP2,omitempty" toml:"disableHTTP2,omitempty" yaml:"disableHTTP2,omitempty" export:"true"` diff --git a/pkg/provider/kubernetes/crd/kubernetes.go b/pkg/provider/kubernetes/crd/kubernetes.go index 2b374eeba..c4c79f2a8 100644 --- a/pkg/provider/kubernetes/crd/kubernetes.go +++ b/pkg/provider/kubernetes/crd/kubernetes.go @@ -409,6 +409,19 @@ func (p *Provider) loadConfigurationFromCRD(ctx context.Context, client Client) }) } + sTransport := &dynamic.ServersTransport{} + if serversTransport.Spec.CipherSuites != nil { + for _, cipher := range serversTransport.Spec.CipherSuites { + if _, exists := tls.CipherSuites[cipher]; exists { + sTransport.CipherSuites = append(sTransport.CipherSuites, cipher) + } else { + // CipherSuite listed in the configuration does not exist in our list + logger.Error().Msgf("invalid CipherSuite: %s", cipher) + continue + } + } + } + forwardingTimeout := &dynamic.ForwardingTimeouts{} forwardingTimeout.SetDefaults() @@ -455,6 +468,9 @@ func (p *Provider) loadConfigurationFromCRD(ctx context.Context, client Client) InsecureSkipVerify: serversTransport.Spec.InsecureSkipVerify, RootCAs: rootCAs, Certificates: certs, + CipherSuites: serversTransport.Spec.CipherSuites, + MinVersion: serversTransport.Spec.MinVersion, + MaxVersion: serversTransport.Spec.MaxVersion, DisableHTTP2: serversTransport.Spec.DisableHTTP2, MaxIdleConnsPerHost: serversTransport.Spec.MaxIdleConnsPerHost, ForwardingTimeouts: forwardingTimeout, diff --git a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/serverstransport.go b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/serverstransport.go index 85efac042..818d7c4ca 100644 --- a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/serverstransport.go +++ b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/serverstransport.go @@ -38,8 +38,12 @@ type ServersTransportSpec struct { RootCAsSecrets []string `json:"rootCAsSecrets,omitempty"` // CertificatesSecrets defines a list of secret storing client certificates for mTLS. CertificatesSecrets []string `json:"certificatesSecrets,omitempty"` - // CipherSuites defines a list of cipher to use to contact backends - CipherSuites []string `json:"cipherSuites,omitempty" toml:"cipherSuites,omitempty" yaml:"cipherSuites,omitempty" export:"true"` + // CipherSuites defines a list of cipher to use to contact the backend servers. + CipherSuites []string `json:"cipherSuites,omitempty"` + // MinVersion defines TLS minimum version to use to contact the backend servers. + MinVersion string `json:"minVersion,omitempty"` + // MaxVersion defines TLS maximum version to use to contact the backend servers. + MaxVersion string `json:"maxVersion,omitempty"` // MaxIdleConnsPerHost controls the maximum idle (keep-alive) to keep per-host. // +kubebuilder:validation:Minimum=0 MaxIdleConnsPerHost int `json:"maxIdleConnsPerHost,omitempty"` diff --git a/pkg/server/service/transport.go b/pkg/server/service/transport.go index 5166dffe6..7959f5059 100644 --- a/pkg/server/service/transport.go +++ b/pkg/server/service/transport.go @@ -169,17 +169,17 @@ func (t *TransportManager) createTLSConfig(cfg *dynamic.ServersTransport) (*tls. config = tlsconfig.MTLSClientConfig(t.spiffeX509Source, t.spiffeX509Source, spiffeAuthorizer) } - if cfg.InsecureSkipVerify || len(cfg.RootCAs) > 0 || len(cfg.ServerName) > 0 || len(cfg.Certificates) > 0 || cfg.PeerCertURI != "" { + if cfg.InsecureSkipVerify || len(cfg.RootCAs) > 0 || len(cfg.ServerName) > 0 || len(cfg.Certificates) > 0 || cfg.PeerCertURI != "" || len(cfg.CipherSuites) > 0 || cfg.MaxVersion != "" || cfg.MinVersion != "" { if config != nil { return nil, errors.New("TLS and SPIFFE configuration cannot be defined at the same time") } // map and validate the CipherSuite passed in the configuration + ciphersList := make([]uint16, 0) if cfg.CipherSuites != nil { - config.CipherSuites = make([]uint16, 0) for _, cipher := range cfg.CipherSuites { if cipherID, exists := traefiktls.CipherSuites[cipher]; exists { - config.CipherSuites = append(config.CipherSuites, cipherID) + ciphersList = append(ciphersList, cipherID) } else { // CipherSuite listed in the configuration does not exist in our list return nil, fmt.Errorf("invalid CipherSuite: %s", cipher) @@ -187,12 +187,26 @@ func (t *TransportManager) createTLSConfig(cfg *dynamic.ServersTransport) (*tls. } } + // Set the minimum TLS version if set in the config + var minVer uint16 + if minConst, exists := traefiktls.MinVersion[cfg.MinVersion]; exists { + minVer = minConst + } + + // Set the minimum TLS version if set in the config + var maxVer uint16 + if maxConst, exists := traefiktls.MaxVersion[cfg.MaxVersion]; exists { + maxVer = maxConst + } + config = &tls.Config{ ServerName: cfg.ServerName, InsecureSkipVerify: cfg.InsecureSkipVerify, RootCAs: createRootCACertPool(cfg.RootCAs), Certificates: cfg.Certificates.GetCertificates(), - CipherSuites: config.CipherSuites, + CipherSuites: ciphersList, + MinVersion: minVer, + MaxVersion: maxVer, } if cfg.PeerCertURI != "" {