diff --git a/docs/content/reference/dynamic-configuration/file.toml b/docs/content/reference/dynamic-configuration/file.toml
index b7f30c649..da700b25f 100644
--- a/docs/content/reference/dynamic-configuration/file.toml
+++ b/docs/content/reference/dynamic-configuration/file.toml
@@ -364,6 +364,9 @@
serverName = "foobar"
insecureSkipVerify = true
rootCAs = ["foobar", "foobar"]
+ cipherSuites = ["foobar", "foobar"]
+ minVersion = "foobar"
+ maxVersion = "foobar"
maxIdleConnsPerHost = 42
disableHTTP2 = true
peerCertURI = "foobar"
@@ -388,6 +391,9 @@
serverName = "foobar"
insecureSkipVerify = true
rootCAs = ["foobar", "foobar"]
+ cipherSuites = ["foobar", "foobar"]
+ minVersion = "foobar"
+ maxVersion = "foobar"
maxIdleConnsPerHost = 42
disableHTTP2 = true
peerCertURI = "foobar"
diff --git a/docs/content/reference/dynamic-configuration/file.yaml b/docs/content/reference/dynamic-configuration/file.yaml
index 2ac73fd85..578423252 100644
--- a/docs/content/reference/dynamic-configuration/file.yaml
+++ b/docs/content/reference/dynamic-configuration/file.yaml
@@ -426,6 +426,11 @@ http:
keyFile: foobar
- certFile: foobar
keyFile: foobar
+ cipherSuites:
+ - foobar
+ - foobar
+ minVersion: foobar
+ maxVersion: foobar
maxIdleConnsPerHost: 42
forwardingTimeouts:
dialTimeout: 42s
@@ -451,6 +456,11 @@ http:
keyFile: foobar
- certFile: foobar
keyFile: foobar
+ cipherSuites:
+ - foobar
+ - foobar
+ minVersion: foobar
+ maxVersion: foobar
maxIdleConnsPerHost: 42
forwardingTimeouts:
dialTimeout: 42s
diff --git a/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml b/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml
index c4f6dc076..f5e68381b 100644
--- a/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml
+++ b/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml
@@ -2217,6 +2217,12 @@ spec:
items:
type: string
type: array
+ cipherSuites:
+ description: CipherSuites defines a list of cipher to use to contact
+ the backend servers.
+ items:
+ type: string
+ type: array
disableHTTP2:
description: DisableHTTP2 disables HTTP/2 for connections with backend
servers.
@@ -2277,6 +2283,14 @@ spec:
to keep per-host.
minimum: 0
type: integer
+ maxVersion:
+ description: MaxVersion defines TLS maximum version to use to contact
+ the backend servers.
+ type: string
+ minVersion:
+ description: MinVersion defines TLS minimum version to use to contact
+ the backend servers.
+ type: string
peerCertURI:
description: PeerCertURI defines the peer cert URI used to match against
SAN URI during the peer certificate verification.
diff --git a/docs/content/reference/dynamic-configuration/kv-ref.md b/docs/content/reference/dynamic-configuration/kv-ref.md
index a7c1b217f..c579be286 100644
--- a/docs/content/reference/dynamic-configuration/kv-ref.md
+++ b/docs/content/reference/dynamic-configuration/kv-ref.md
@@ -237,6 +237,8 @@ THIS FILE MUST NOT BE EDITED BY HAND
| `traefik/http/serversTransports/ServersTransport0/certificates/0/keyFile` | `foobar` |
| `traefik/http/serversTransports/ServersTransport0/certificates/1/certFile` | `foobar` |
| `traefik/http/serversTransports/ServersTransport0/certificates/1/keyFile` | `foobar` |
+| `traefik/http/serversTransports/ServersTransport0/cipherSuites/0` | `foobar` |
+| `traefik/http/serversTransports/ServersTransport0/cipherSuites/1` | `foobar` |
| `traefik/http/serversTransports/ServersTransport0/disableHTTP2` | `true` |
| `traefik/http/serversTransports/ServersTransport0/forwardingTimeouts/dialTimeout` | `42s` |
| `traefik/http/serversTransports/ServersTransport0/forwardingTimeouts/idleConnTimeout` | `42s` |
@@ -245,6 +247,8 @@ THIS FILE MUST NOT BE EDITED BY HAND
| `traefik/http/serversTransports/ServersTransport0/forwardingTimeouts/responseHeaderTimeout` | `42s` |
| `traefik/http/serversTransports/ServersTransport0/insecureSkipVerify` | `true` |
| `traefik/http/serversTransports/ServersTransport0/maxIdleConnsPerHost` | `42` |
+| `traefik/http/serversTransports/ServersTransport0/maxVersion` | `foobar` |
+| `traefik/http/serversTransports/ServersTransport0/minVersion` | `foobar` |
| `traefik/http/serversTransports/ServersTransport0/peerCertURI` | `foobar` |
| `traefik/http/serversTransports/ServersTransport0/rootCAs/0` | `foobar` |
| `traefik/http/serversTransports/ServersTransport0/rootCAs/1` | `foobar` |
@@ -256,6 +260,8 @@ THIS FILE MUST NOT BE EDITED BY HAND
| `traefik/http/serversTransports/ServersTransport1/certificates/0/keyFile` | `foobar` |
| `traefik/http/serversTransports/ServersTransport1/certificates/1/certFile` | `foobar` |
| `traefik/http/serversTransports/ServersTransport1/certificates/1/keyFile` | `foobar` |
+| `traefik/http/serversTransports/ServersTransport1/cipherSuites/0` | `foobar` |
+| `traefik/http/serversTransports/ServersTransport1/cipherSuites/1` | `foobar` |
| `traefik/http/serversTransports/ServersTransport1/disableHTTP2` | `true` |
| `traefik/http/serversTransports/ServersTransport1/forwardingTimeouts/dialTimeout` | `42s` |
| `traefik/http/serversTransports/ServersTransport1/forwardingTimeouts/idleConnTimeout` | `42s` |
@@ -264,6 +270,8 @@ THIS FILE MUST NOT BE EDITED BY HAND
| `traefik/http/serversTransports/ServersTransport1/forwardingTimeouts/responseHeaderTimeout` | `42s` |
| `traefik/http/serversTransports/ServersTransport1/insecureSkipVerify` | `true` |
| `traefik/http/serversTransports/ServersTransport1/maxIdleConnsPerHost` | `42` |
+| `traefik/http/serversTransports/ServersTransport1/maxVersion` | `foobar` |
+| `traefik/http/serversTransports/ServersTransport1/minVersion` | `foobar` |
| `traefik/http/serversTransports/ServersTransport1/peerCertURI` | `foobar` |
| `traefik/http/serversTransports/ServersTransport1/rootCAs/0` | `foobar` |
| `traefik/http/serversTransports/ServersTransport1/rootCAs/1` | `foobar` |
diff --git a/docs/content/reference/dynamic-configuration/traefik.io_serverstransports.yaml b/docs/content/reference/dynamic-configuration/traefik.io_serverstransports.yaml
index 132f71685..7a2eceedd 100644
--- a/docs/content/reference/dynamic-configuration/traefik.io_serverstransports.yaml
+++ b/docs/content/reference/dynamic-configuration/traefik.io_serverstransports.yaml
@@ -49,6 +49,12 @@ spec:
items:
type: string
type: array
+ cipherSuites:
+ description: CipherSuites defines a list of cipher to use to contact
+ the backend servers.
+ items:
+ type: string
+ type: array
disableHTTP2:
description: DisableHTTP2 disables HTTP/2 for connections with backend
servers.
@@ -109,6 +115,14 @@ spec:
to keep per-host.
minimum: 0
type: integer
+ maxVersion:
+ description: MaxVersion defines TLS maximum version to use to contact
+ the backend servers.
+ type: string
+ minVersion:
+ description: MinVersion defines TLS minimum version to use to contact
+ the backend servers.
+ type: string
peerCertURI:
description: PeerCertURI defines the peer cert URI used to match against
SAN URI during the peer certificate verification.
diff --git a/docs/content/reference/routing-configuration/http/load-balancing/serverstransport.md b/docs/content/reference/routing-configuration/http/load-balancing/serverstransport.md
index 89d7b31c4..451f23be3 100644
--- a/docs/content/reference/routing-configuration/http/load-balancing/serverstransport.md
+++ b/docs/content/reference/routing-configuration/http/load-balancing/serverstransport.md
@@ -35,6 +35,11 @@ http:
- "spiffe://example.org/id1"
- "spiffe://example.org/id2"
trustDomain: "example.org"
+ cipherSuites:
+ - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
+ - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
+ minVersion: VersionTLS12
+ maxVersion: VersionTLS12
```
```toml tab="Structured (TOML)"
@@ -46,6 +51,9 @@ http:
maxIdleConnsPerHost = 100
disableHTTP2 = true
peerCertURI = "spiffe://example.org/peer"
+ cipherSuites = ["TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256","TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"]
+ minVersion = "VersionTLS12"
+ maxVersion = "VersionTLS12"
[http.serversTransports.mytransport.forwardingTimeouts]
dialTimeout = "30s"
@@ -100,6 +108,9 @@ labels:
| `certificates` | Defines the list of certificates (as file paths, or data bytes) that will be set as client certificates for mTLS. | [] | No |
| `insecureSkipVerify` | Controls whether the server's certificate chain and host name is verified. | false | No |
| `rootcas` | Set of root certificate authorities to use when verifying server certificates. (for mTLS connections). | [] | No |
+| `cipherSuites` | Defines a list of cipher to use to contact the backend servers. | [] | No |
+| `minVersion` | Defines a TLS minimum version to use to contact the backend servers. | "" | No |
+| `maxVersion` | Defines a TLS maximum version to use to contact the backend servers. | "" | No |
| `maxIdleConnsPerHost` | Maximum idle (keep-alive) connections to keep per-host. | 200 | No |
| `disableHTTP2` | Disables HTTP/2 for connections with servers. | false | No |
| `peerCertURI` | Defines the URI used to match against SAN URIs during the server's certificate verification. | "" | No |
diff --git a/docs/content/reference/routing-configuration/kubernetes/crd/http/serverstransport.md b/docs/content/reference/routing-configuration/kubernetes/crd/http/serverstransport.md
index 7c364f685..5d697d9fc 100644
--- a/docs/content/reference/routing-configuration/kubernetes/crd/http/serverstransport.md
+++ b/docs/content/reference/routing-configuration/kubernetes/crd/http/serverstransport.md
@@ -59,6 +59,9 @@ spec:
| `serverstransport.`
`insecureSkipVerify` | Controls whether the server's certificate chain and host name is verified. | false | No |
| `serverstransport.`
`rootcas` | Set of root certificate authorities to use when verifying server certificates. (for mTLS connections). | | No |
| `serverstransport.`
`certificatesSecrets` | Certificates to present to the server for mTLS. | | No |
+| `serverstransport.`
`cipherSuites` | Defines a list of cipher to use to contact the backend servers. | [] | No |
+| `serverstransport.`
`minVersion` | Defines a TLS minimum version to use to contact the backend servers. | "" | No |
+| `serverstransport.`
`maxVersion` | Defines a TLS maximum version to use to contact the backend servers. | "" | No |
| `serverstransport.`
`maxIdleConnsPerHost` | Maximum idle (keep-alive) connections to keep per-host. | 200 | No |
| `serverstransport.`
`disableHTTP2` | Disables HTTP/2 for connections with servers. | false | No |
| `serverstransport.`
`peerCertURI` | Defines the URI used to match against SAN URIs during the server's certificate verification. | "" | No |
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..6d0fed286 100644
--- a/docs/content/routing/services/index.md
+++ b/docs/content/routing/services/index.md
@@ -771,6 +771,100 @@ 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/integration/fixtures/k8s/01-traefik-crd.yml b/integration/fixtures/k8s/01-traefik-crd.yml
index c4f6dc076..f5e68381b 100644
--- a/integration/fixtures/k8s/01-traefik-crd.yml
+++ b/integration/fixtures/k8s/01-traefik-crd.yml
@@ -2217,6 +2217,12 @@ spec:
items:
type: string
type: array
+ cipherSuites:
+ description: CipherSuites defines a list of cipher to use to contact
+ the backend servers.
+ items:
+ type: string
+ type: array
disableHTTP2:
description: DisableHTTP2 disables HTTP/2 for connections with backend
servers.
@@ -2277,6 +2283,14 @@ spec:
to keep per-host.
minimum: 0
type: integer
+ maxVersion:
+ description: MaxVersion defines TLS maximum version to use to contact
+ the backend servers.
+ type: string
+ minVersion:
+ description: MinVersion defines TLS minimum version to use to contact
+ the backend servers.
+ type: string
peerCertURI:
description: PeerCertURI defines the peer cert URI used to match against
SAN URI during the peer certificate verification.
diff --git a/pkg/config/dynamic/http_config.go b/pkg/config/dynamic/http_config.go
index ef6a896f1..447ffd524 100644
--- a/pkg/config/dynamic/http_config.go
+++ b/pkg/config/dynamic/http_config.go
@@ -347,6 +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 `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/config/dynamic/zz_generated.deepcopy.go b/pkg/config/dynamic/zz_generated.deepcopy.go
index 97f8907e0..59a47804d 100644
--- a/pkg/config/dynamic/zz_generated.deepcopy.go
+++ b/pkg/config/dynamic/zz_generated.deepcopy.go
@@ -1514,6 +1514,11 @@ func (in *ServersTransport) DeepCopyInto(out *ServersTransport) {
*out = make(tls.Certificates, len(*in))
copy(*out, *in)
}
+ if in.CipherSuites != nil {
+ in, out := &in.CipherSuites, &out.CipherSuites
+ *out = make([]string, len(*in))
+ copy(*out, *in)
+ }
if in.ForwardingTimeouts != nil {
in, out := &in.ForwardingTimeouts, &out.ForwardingTimeouts
*out = new(ForwardingTimeouts)
diff --git a/pkg/provider/kubernetes/crd/fixtures/with_servers_transport.yml b/pkg/provider/kubernetes/crd/fixtures/with_servers_transport.yml
index 496c5af30..5b1fee8f0 100644
--- a/pkg/provider/kubernetes/crd/fixtures/with_servers_transport.yml
+++ b/pkg/provider/kubernetes/crd/fixtures/with_servers_transport.yml
@@ -169,6 +169,11 @@ spec:
- spiffe://foo/buz
- spiffe://bar/biz
trustDomain: spiffe://lol
+ cipherSuites:
+ - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
+ - TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
+ minVersion: VersionTLS11
+ maxVersion: VersionTLS12
---
apiVersion: traefik.io/v1alpha1
diff --git a/pkg/provider/kubernetes/crd/kubernetes.go b/pkg/provider/kubernetes/crd/kubernetes.go
index 2b374eeba..36720e899 100644
--- a/pkg/provider/kubernetes/crd/kubernetes.go
+++ b/pkg/provider/kubernetes/crd/kubernetes.go
@@ -409,6 +409,39 @@ 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
+ }
+ }
+ }
+
+ if serversTransport.Spec.MinVersion != "" {
+ if _, exists := tls.MinVersion[serversTransport.Spec.MinVersion]; exists {
+ sTransport.MinVersion = serversTransport.Spec.MinVersion
+ } else {
+ // Min TLS version does not exist
+ logger.Error().Msgf("invalid TLS minimal version: %s", serversTransport.Spec.MinVersion)
+ continue
+ }
+ }
+
+ if serversTransport.Spec.MaxVersion != "" {
+ if _, exists := tls.MaxVersion[serversTransport.Spec.MaxVersion]; exists {
+ sTransport.MaxVersion = serversTransport.Spec.MaxVersion
+ } else {
+ // Min TLS version does not exist
+ logger.Error().Msgf("invalid TLS maximal version: %s", serversTransport.Spec.MaxVersion)
+ continue
+ }
+ }
+
forwardingTimeout := &dynamic.ForwardingTimeouts{}
forwardingTimeout.SetDefaults()
@@ -455,6 +488,9 @@ func (p *Provider) loadConfigurationFromCRD(ctx context.Context, client Client)
InsecureSkipVerify: serversTransport.Spec.InsecureSkipVerify,
RootCAs: rootCAs,
Certificates: certs,
+ CipherSuites: sTransport.CipherSuites,
+ MinVersion: sTransport.MinVersion,
+ MaxVersion: sTransport.MaxVersion,
DisableHTTP2: serversTransport.Spec.DisableHTTP2,
MaxIdleConnsPerHost: serversTransport.Spec.MaxIdleConnsPerHost,
ForwardingTimeouts: forwardingTimeout,
diff --git a/pkg/provider/kubernetes/crd/kubernetes_test.go b/pkg/provider/kubernetes/crd/kubernetes_test.go
index ec6651091..b53474f66 100644
--- a/pkg/provider/kubernetes/crd/kubernetes_test.go
+++ b/pkg/provider/kubernetes/crd/kubernetes_test.go
@@ -4745,6 +4745,9 @@ func TestLoadIngressRoutes(t *testing.T) {
{CertFile: "TESTCERT2", KeyFile: "TESTKEY2"},
{CertFile: "TESTCERT3", KeyFile: "TESTKEY3"},
},
+ CipherSuites: []string{"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"},
+ MinVersion: "VersionTLS11",
+ MaxVersion: "VersionTLS12",
MaxIdleConnsPerHost: 42,
DisableHTTP2: true,
ForwardingTimeouts: &dynamic.ForwardingTimeouts{
diff --git a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/serverstransport.go b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/serverstransport.go
index 08143ed45..818d7c4ca 100644
--- a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/serverstransport.go
+++ b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/serverstransport.go
@@ -38,6 +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 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/provider/kubernetes/crd/traefikio/v1alpha1/zz_generated.deepcopy.go b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/zz_generated.deepcopy.go
index 3e53cfae5..4ae91375f 100644
--- a/pkg/provider/kubernetes/crd/traefikio/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/provider/kubernetes/crd/traefikio/v1alpha1/zz_generated.deepcopy.go
@@ -1395,6 +1395,11 @@ func (in *ServersTransportSpec) DeepCopyInto(out *ServersTransportSpec) {
*out = make([]string, len(*in))
copy(*out, *in)
}
+ if in.CipherSuites != nil {
+ in, out := &in.CipherSuites, &out.CipherSuites
+ *out = make([]string, len(*in))
+ copy(*out, *in)
+ }
if in.ForwardingTimeouts != nil {
in, out := &in.ForwardingTimeouts, &out.ForwardingTimeouts
*out = new(ForwardingTimeouts)
diff --git a/pkg/server/service/transport.go b/pkg/server/service/transport.go
index ecce54010..f7a526fe1 100644
--- a/pkg/server/service/transport.go
+++ b/pkg/server/service/transport.go
@@ -169,16 +169,54 @@ 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 {
+ for _, cipher := range cfg.CipherSuites {
+ if cipherID, exists := traefiktls.CipherSuites[cipher]; exists {
+ ciphersList = append(ciphersList, cipherID)
+ } else {
+ // CipherSuite listed in the configuration does not exist in our list
+ return nil, fmt.Errorf("invalid CipherSuite: %s", cipher)
+ }
+ }
+ }
+
+ // Set the min TLS version if set in the config
+ var minVer uint16
+ if cfg.MinVersion != "" {
+ if minConst, exists := traefiktls.MinVersion[cfg.MinVersion]; exists {
+ minVer = minConst
+ } else {
+ // Min TLS version does not exist
+ return nil, fmt.Errorf("invalid TLS minimal version: %v", minVer)
+ }
+ }
+
+ // Set the min TLS version if set in the config
+ var maxVer uint16
+ if cfg.MinVersion != "" {
+ if maxConst, exists := traefiktls.MaxVersion[cfg.MaxVersion]; exists {
+ maxVer = maxConst
+ } else {
+ // Max TLS version does not exist
+ return nil, fmt.Errorf("invalid TLS maximal version: %v", maxVer)
+ }
+ }
+
config = &tls.Config{
ServerName: cfg.ServerName,
InsecureSkipVerify: cfg.InsecureSkipVerify,
RootCAs: createRootCACertPool(cfg.RootCAs),
Certificates: cfg.Certificates.GetCertificates(),
+ CipherSuites: ciphersList,
+ MinVersion: minVer,
+ MaxVersion: maxVer,
}
if cfg.PeerCertURI != "" {
diff --git a/pkg/server/service/transport_test.go b/pkg/server/service/transport_test.go
index 0fd3a8ab8..89dbd9384 100644
--- a/pkg/server/service/transport_test.go
+++ b/pkg/server/service/transport_test.go
@@ -183,6 +183,47 @@ func TestKeepConnectionWhenSameConfiguration(t *testing.T) {
assert.EqualValues(t, 2, count)
}
+func TestCipherSuites(t *testing.T) {
+ srv := httptest.NewUnstartedServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
+ rw.WriteHeader(http.StatusOK)
+ }))
+
+ cert, err := tls.X509KeyPair(LocalhostCert, LocalhostKey)
+ require.NoError(t, err)
+
+ srv.TLS = &tls.Config{
+ Certificates: []tls.Certificate{cert},
+ MaxVersion: tls.VersionTLS12,
+ CipherSuites: []uint16{
+ tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+ },
+ }
+ srv.StartTLS()
+
+ transportManager := NewTransportManager(nil)
+
+ dynamicConf := map[string]*dynamic.ServersTransport{
+ "test": {
+ ServerName: "example.com",
+ RootCAs: []types.FileOrContent{types.FileOrContent(LocalhostCert)},
+ CipherSuites: []string{"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"},
+ MaxVersion: "VersionTLS12",
+ },
+ }
+
+ transportManager.Update(dynamicConf)
+
+ tr, err := transportManager.GetRoundTripper("test")
+ require.NoError(t, err)
+
+ client := http.Client{Transport: tr}
+
+ resp, err := client.Get(srv.URL)
+ require.NoError(t, err)
+
+ assert.Equal(t, http.StatusOK, resp.StatusCode)
+}
+
func TestMTLS(t *testing.T) {
srv := httptest.NewUnstartedServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
rw.WriteHeader(http.StatusOK)