From 1f39083555cb9a73896a972e26e388f116abeb97 Mon Sep 17 00:00:00 2001 From: kmeekva Date: Tue, 29 Oct 2019 07:58:05 -0400 Subject: [PATCH] Add support for MaxVersion in tls.Options --- docs/content/https/tls.md | 51 +++++++++++++++++++ .../reference/dynamic-configuration/file.toml | 2 + .../reference/dynamic-configuration/file.yaml | 2 + pkg/provider/kubernetes/crd/kubernetes.go | 1 + .../crd/traefik/v1alpha1/tlsoption.go | 1 + pkg/tls/certificate.go | 8 +++ pkg/tls/tls.go | 1 + pkg/tls/tlsmanager.go | 6 +++ 8 files changed, 72 insertions(+) diff --git a/docs/content/https/tls.md b/docs/content/https/tls.md index 7a53cce1e..b06a4b22c 100644 --- a/docs/content/https/tls.md +++ b/docs/content/https/tls.md @@ -181,6 +181,57 @@ spec: minVersion: VersionTLS13 ``` +### Maximum TLS Version + +We discourages the use of this setting to disable TLS1.3. + +The right approach is to update the clients to support TLS1.3. + +```toml tab="File (TOML)" +# Dynamic configuration + +[tls.options] + + [tls.options.default] + maxVersion = "VersionTLS13" + + [tls.options.maxtls12] + maxVersion = "VersionTLS12" +``` + +```yaml tab="File (YAML)" +# Dynamic configuration + +tls: + options: + default: + maxVersion: VersionTLS13 + + maxtls12: + maxVersion: VersionTLS12 +``` + +```yaml tab="Kubernetes" +apiVersion: traefik.containo.us/v1alpha1 +kind: TLSOption +metadata: + name: default + namespace: default + +spec: + maxVersion: VersionTLS13 + +--- +apiVersion: traefik.containo.us/v1alpha1 +kind: TLSOption +metadata: + name: maxtls12 + namespace: default + +spec: + maxVersion: VersionTLS12 +``` + ### Cipher Suites See [cipherSuites](https://godoc.org/crypto/tls#pkg-constants) for more information. diff --git a/docs/content/reference/dynamic-configuration/file.toml b/docs/content/reference/dynamic-configuration/file.toml index 8027a082b..934b5f695 100644 --- a/docs/content/reference/dynamic-configuration/file.toml +++ b/docs/content/reference/dynamic-configuration/file.toml @@ -318,6 +318,7 @@ [tls.options] [tls.options.Options0] minVersion = "foobar" + maxVersion = "foobar" cipherSuites = ["foobar", "foobar"] sniStrict = true [tls.options.Options0.clientAuth] @@ -325,6 +326,7 @@ clientAuthType = "foobar" [tls.options.Options1] minVersion = "foobar" + maxVersion = "foobar" cipherSuites = ["foobar", "foobar"] sniStrict = true [tls.options.Options1.clientAuth] diff --git a/docs/content/reference/dynamic-configuration/file.yaml b/docs/content/reference/dynamic-configuration/file.yaml index e8ab878b7..c2eca8db9 100644 --- a/docs/content/reference/dynamic-configuration/file.yaml +++ b/docs/content/reference/dynamic-configuration/file.yaml @@ -349,6 +349,7 @@ tls: options: Options0: minVersion: foobar + maxVersion: foobar cipherSuites: - foobar - foobar @@ -360,6 +361,7 @@ tls: sniStrict: true Options1: minVersion: foobar + maxVersion: foobar cipherSuites: - foobar - foobar diff --git a/pkg/provider/kubernetes/crd/kubernetes.go b/pkg/provider/kubernetes/crd/kubernetes.go index 73f9062fe..e9164f2f0 100644 --- a/pkg/provider/kubernetes/crd/kubernetes.go +++ b/pkg/provider/kubernetes/crd/kubernetes.go @@ -482,6 +482,7 @@ func buildTLSOptions(ctx context.Context, client Client) map[string]tls.Options tlsOptions[makeID(tlsOption.Namespace, tlsOption.Name)] = tls.Options{ MinVersion: tlsOption.Spec.MinVersion, + MaxVersion: tlsOption.Spec.MaxVersion, CipherSuites: tlsOption.Spec.CipherSuites, ClientAuth: tls.ClientAuth{ CAFiles: clientCAs, diff --git a/pkg/provider/kubernetes/crd/traefik/v1alpha1/tlsoption.go b/pkg/provider/kubernetes/crd/traefik/v1alpha1/tlsoption.go index e06fdeead..a63165e80 100644 --- a/pkg/provider/kubernetes/crd/traefik/v1alpha1/tlsoption.go +++ b/pkg/provider/kubernetes/crd/traefik/v1alpha1/tlsoption.go @@ -20,6 +20,7 @@ type TLSOption struct { // TLSOptionSpec configures TLS for an entry point type TLSOptionSpec struct { MinVersion string `json:"minVersion,omitempty"` + MaxVersion string `json:"maxVersion,omitempty"` CipherSuites []string `json:"cipherSuites,omitempty"` ClientAuth ClientAuth `json:"clientAuth,omitempty"` SniStrict bool `json:"sniStrict,omitempty"` diff --git a/pkg/tls/certificate.go b/pkg/tls/certificate.go index 1e700f111..a2b27d26c 100644 --- a/pkg/tls/certificate.go +++ b/pkg/tls/certificate.go @@ -22,6 +22,14 @@ var ( `VersionTLS13`: tls.VersionTLS13, } + // MaxVersion Map of allowed TLS minimum versions + MaxVersion = map[string]uint16{ + `VersionTLS10`: tls.VersionTLS10, + `VersionTLS11`: tls.VersionTLS11, + `VersionTLS12`: tls.VersionTLS12, + `VersionTLS13`: tls.VersionTLS13, + } + // CipherSuites Map of TLS CipherSuites from crypto/tls // Available CipherSuites defined at https://golang.org/pkg/crypto/tls/#pkg-constants CipherSuites = map[string]uint16{ diff --git a/pkg/tls/tls.go b/pkg/tls/tls.go index 49d18176f..476277a8e 100644 --- a/pkg/tls/tls.go +++ b/pkg/tls/tls.go @@ -17,6 +17,7 @@ type ClientAuth struct { // Options configures TLS for an entry point type Options struct { MinVersion string `json:"minVersion,omitempty" toml:"minVersion,omitempty" yaml:"minVersion,omitempty" export:"true"` + MaxVersion string `json:"maxVersion,omitempty" toml:"maxVersion,omitempty" yaml:"maxVersion,omitempty" export:"true"` CipherSuites []string `json:"cipherSuites,omitempty" toml:"cipherSuites,omitempty" yaml:"cipherSuites,omitempty"` ClientAuth ClientAuth `json:"clientAuth,omitempty" toml:"clientAuth,omitempty" yaml:"clientAuth,omitempty"` SniStrict bool `json:"sniStrict,omitempty" toml:"sniStrict,omitempty" yaml:"sniStrict,omitempty" export:"true"` diff --git a/pkg/tls/tlsmanager.go b/pkg/tls/tlsmanager.go index ebdeb9e22..d71145c2e 100644 --- a/pkg/tls/tlsmanager.go +++ b/pkg/tls/tlsmanager.go @@ -217,6 +217,12 @@ func buildTLSConfig(tlsOption Options) (*tls.Config, error) { conf.MinVersion = minConst } + // Set the maximum TLS version if set in the config TOML + if maxConst, exists := MaxVersion[tlsOption.MaxVersion]; exists { + conf.PreferServerCipherSuites = true + conf.MaxVersion = maxConst + } + // Set the list of CipherSuites if set in the config TOML if tlsOption.CipherSuites != nil { // if our list of CipherSuites is defined in the entryPoint config, we can re-initialize the suites list as empty