diff --git a/docs/content/https/tls.md b/docs/content/https/tls.md index c67da5d95..541495ce2 100644 --- a/docs/content/https/tls.md +++ b/docs/content/https/tls.md @@ -11,18 +11,16 @@ See the [Let's Encrypt](./acme.md) page. ### User defined -To add / remove TLS certificates, even when Traefik is already running, their definition can be added to the [dynamic configuration](../getting-started/configuration-overview.md), in the `[[tls]]` section: +To add / remove TLS certificates, even when Traefik is already running, their definition can be added to the [dynamic configuration](../getting-started/configuration-overview.md), in the `[[tls.certificates]]` section: ```toml -[[tls]] - [tls.certificate] - certFile = "/path/to/domain.cert" - keyFile = "/path/to/domain.key" +[[tls.certificates]] + certFile = "/path/to/domain.cert" + keyFile = "/path/to/domain.key" -[[tls]] - [tls.certificate] - certFile = "/path/to/other-domain.cert" - keyFile = "/path/to/other-domain.key" +[[tls.certificates]] + certFile = "/path/to/other-domain.cert" + keyFile = "/path/to/other-domain.key" ``` !!! important "File Provider Only" @@ -35,8 +33,8 @@ To add / remove TLS certificates, even when Traefik is already running, their de In Traefik, certificates are grouped together in certificates stores, which are defined as such: ```toml -[tlsStores] - [tlsStores.default] +[tls.stores] + [tls.stores.default] ``` !!! important "Alpha restriction" @@ -44,21 +42,19 @@ In Traefik, certificates are grouped together in certificates stores, which are During the alpha version, any store definition other than the default one (named `default`) will be ignored, and there is thefore only one globally available TLS store. -In the `[[tls]]` section, a list of stores can then be specified to indicate where the certificates should be stored: +In the `[[tls.certificates]]` section, a list of stores can then be specified to indicate where the certificates should be stored: ```toml -[[tls]] +[[tls.certificates]] stores = ["default"] - [tls.certificate] - certFile = "/path/to/domain.cert" - keyFile = "/path/to/domain.key" + certFile = "/path/to/domain.cert" + keyFile = "/path/to/domain.key" -[[tls]] +[[tls.certificates]] # Note that since no store is defined, # the certificate below will be stored in the `default` store. - [tls.certificate] - certFile = "/path/to/other-domain.cert" - keyFile = "/path/to/other-domain.key" + certFile = "/path/to/other-domain.cert" + keyFile = "/path/to/other-domain.key" ``` !!! important "Alpha restriction" @@ -71,9 +67,9 @@ Traefik can use a default certificate for connections without a SNI, or without This default certificate should be defined in a TLS store: ```toml -[tlsStores] - [tlsStores.default] - [tlsStores.default.defaultCertificate] +[tls.stores] + [tls.stores.default] + [tls.stores.default.defaultCertificate] certFile = "path/to/cert.crt" keyFile = "path/to/cert.key" ``` @@ -87,12 +83,12 @@ The TLS options allow one to configure some parameters of the TLS connection. ### Minimum TLS Version ```toml -[tlsOptions] +[tls.options] - [tlsOptions.default] + [tls.options.default] minVersion = "VersionTLS12" - [tlsOptions.mintls13] + [tls.options.mintls13] minVersion = "VersionTLS13" ``` @@ -107,9 +103,9 @@ For clients with a certificate, the `optional` option governs the behaviour as f - When `optional = true`, Traefik authorizes connections from clients presenting a certificate signed by an unknown CA. ```toml -[tlsOptions] - [tlsOptions.default] - [tlsOptions.default.ClientCA] +[tls.options] + [tls.options.default] + [tls.options.default.ClientCA] # in PEM format. each file can contain multiple CAs. files = ["tests/clientca1.crt", "tests/clientca2.crt"] optional = false @@ -120,8 +116,8 @@ For clients with a certificate, the `optional` option governs the behaviour as f See [cipherSuites](https://godoc.org/crypto/tls#pkg-constants) for more information. ```toml -[tlsOptions] - [tlsOptions.default] +[tls.options] + [tls.options.default] cipherSuites = [ "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_RSA_WITH_AES_256_GCM_SHA384" @@ -134,7 +130,7 @@ With strict SNI checking, Traefik won't allow connections from clients connectio that do not specify a server_name extension. ```toml -[tlsOptions] - [tlsOptions.default] +[tls.options] + [tls.options.default] sniStrict = true ``` diff --git a/docs/content/providers/file.md b/docs/content/providers/file.md index 8c2033568..8a940b943 100644 --- a/docs/content/providers/file.md +++ b/docs/content/providers/file.md @@ -192,16 +192,15 @@ Thus, it's possible to define easily lot of routers, services and TLS certificat {{ end }} {{ range $i, $e := until 10 }} - [[TLS]] + [[tls.certificates]] + CertFile = "/etc/traefik/cert-{{ $e }}.pem" + KeyFile = "/etc/traefik/cert-{{ $e }}.key" Store = ["my-store-foo-{{ $e }}", "my-store-bar-{{ $e }}"] - [TLS.Certificate] - CertFile = "/etc/traefik/cert-{{ $e }}.pem" - KeyFile = "/etc/traefik/cert-{{ $e }}.key" {{ end }} - [TLSConfig] + [tls.config] {{ range $i, $e := until 10 }} - [TLSConfig.TLS{{ $e }}] + [tls.config.TLS{{ $e }}] # ... {{ end }} ``` @@ -237,11 +236,11 @@ Thus, it's possible to define easily lot of routers, services and TLS certificat {{ range $i, $e := until 10 }} tls: - store: - - "my-store-foo-{{ $e }}" - - "my-store-bar-{{ $e }}" - certificate: - certfile: "/etc/traefik/cert-{{ $e }}.pem" + certificates: + - certfile: "/etc/traefik/cert-{{ $e }}.pem" keyfile: "/etc/traefik/cert-{{ $e }}.key" + store: + - "my-store-foo-{{ $e }}" + - "my-store-bar-{{ $e }}" {{end}} ``` diff --git a/docs/content/reference/dynamic-configuration/file.toml b/docs/content/reference/dynamic-configuration/file.toml index 3f5b20af5..1879364b9 100644 --- a/docs/content/reference/dynamic-configuration/file.toml +++ b/docs/content/reference/dynamic-configuration/file.toml @@ -220,42 +220,40 @@ [[TCP.Services.TCPService0.LoadBalancer.Servers]] Address = "foobar" -[[TLS]] - Stores = ["foobar", "foobar"] - [TLS.Certificate] +[TLS] + + [[TLS.Certificates]] + Stores = ["foobar", "foobar"] CertFile = "foobar" KeyFile = "foobar" -[[TLS]] - Stores = ["foobar", "foobar"] - [TLS.Certificate] + [[TLS.Certificates]] + Stores = ["foobar", "foobar"] CertFile = "foobar" KeyFile = "foobar" -[TLSOptions] + [TLS.Options] + [TLS.Options.TLS0] + MinVersion = "foobar" + CipherSuites = ["foobar", "foobar"] + SniStrict = true + [TLS.Options.TLS0.ClientCA] + Files = ["foobar", "foobar"] + Optional = true + [TLS.Options.TLS1] + MinVersion = "foobar" + CipherSuites = ["foobar", "foobar"] + SniStrict = true + [TLS.Options.TLS1.ClientCA] + Files = ["foobar", "foobar"] + Optional = true - [TLSOptions.TLS0] - MinVersion = "foobar" - CipherSuites = ["foobar", "foobar"] - SniStrict = true - [TLSOptions.TLS0.ClientCA] - Files = ["foobar", "foobar"] - Optional = true - [TLSOptions.TLS1] - MinVersion = "foobar" - CipherSuites = ["foobar", "foobar"] - SniStrict = true - [TLSOptions.TLS1.ClientCA] - Files = ["foobar", "foobar"] - Optional = true - -[TLSStores] - - [TLSStores.Store0] - [TLSStores.Store0.DefaultCertificate] - CertFile = "foobar" - KeyFile = "foobar" - [TLSStores.Store1] - [TLSStores.Store1.DefaultCertificate] - CertFile = "foobar" - KeyFile = "foobar" + [TLS.Stores] + [TLS.Stores.Store0] + [TLS.Stores.Store0.DefaultCertificate] + CertFile = "foobar" + KeyFile = "foobar" + [TLS.Stores.Store1] + [TLS.Stores.Store1.DefaultCertificate] + CertFile = "foobar" + KeyFile = "foobar" diff --git a/docs/content/routing/routers/index.md b/docs/content/routing/routers/index.md index ac8990d32..b59513e75 100644 --- a/docs/content/routing/routers/index.md +++ b/docs/content/routing/routers/index.md @@ -207,7 +207,7 @@ Traefik will terminate the SSL connections (meaning that it will send decrypted #### `Options` The `Options` field enables fine-grained control of the TLS parameters. -It refers to a [tlsOptions](../../https/tls.md#tls-options) and will be applied only if a `Host` rule is defined. +It refers to a [TLS Options](../../https/tls.md#tls-options) and will be applied only if a `Host` rule is defined. ??? example "Configuring the tls options" @@ -219,8 +219,8 @@ It refers to a [tlsOptions](../../https/tls.md#tls-options) and will be applied [http.routers.Router-1.tls] # will terminate the TLS request options = "foo" - [tlsOptions] - [tlsOptions.foo] + [tls.options] + [tls.options.foo] minVersion = "VersionTLS12" cipherSuites = [ "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", @@ -338,7 +338,7 @@ Services are the target for the router. #### `Options` The `Options` field enables fine-grained control of the TLS parameters. -It refers to a [tlsOptions](../../https/tls.md#tls-options) and will be applied only if a `HostSNI` rule is defined. +It refers to a [TLS Options](../../https/tls.md#tls-options) and will be applied only if a `HostSNI` rule is defined. ??? example "Configuring the tls options" @@ -350,8 +350,8 @@ It refers to a [tlsOptions](../../https/tls.md#tls-options) and will be applied [tcp.routers.Router-1.tls] # will terminate the TLS request options = "foo" - [tlsOptions] - [tlsOptions.foo] + [tls.options] + [tls.options.foo] minVersion = "VersionTLS12" cipherSuites = [ "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", diff --git a/integration/fixtures/acme/acme_tls.toml b/integration/fixtures/acme/acme_tls.toml index 27280bd74..b7ffe5477 100644 --- a/integration/fixtures/acme/acme_tls.toml +++ b/integration/fixtures/acme/acme_tls.toml @@ -54,6 +54,7 @@ level = "DEBUG" service = "test" [http.routers.test.tls] -[tlsStores.default.defaultCertificate] - certFile = "fixtures/acme/ssl/wildcard.crt" - keyFile = "fixtures/acme/ssl/wildcard.key" +[tls.stores] + [tls.stores.default.defaultCertificate] + certFile = "fixtures/acme/ssl/wildcard.crt" + keyFile = "fixtures/acme/ssl/wildcard.key" diff --git a/integration/fixtures/acme/certificates.toml b/integration/fixtures/acme/certificates.toml index ff1653bfd..f0a2c8412 100644 --- a/integration/fixtures/acme/certificates.toml +++ b/integration/fixtures/acme/certificates.toml @@ -1,17 +1,16 @@ [http.services] [http.services.test.loadbalancer] - [[http.services.test.loadbalancer.servers]] - url = "http://127.0.0.1:9010" + [[http.services.test.loadbalancer.servers]] + url = "http://127.0.0.1:9010" [http.routers] [http.routers.test] - entryPoints = ["web-secure"] - rule = "Host(`traefik.acme.wtf`)" - service = "test" - [http.routers.test.tls] + entryPoints = ["web-secure"] + rule = "Host(`traefik.acme.wtf`)" + service = "test" + [http.routers.test.tls] -[[tls]] +[[tls.certificates]] store = ["default"] - [tls.certificate] certFile = "fixtures/acme/ssl/wildcard.crt" keyFile = "fixtures/acme/ssl/wildcard.key" diff --git a/integration/fixtures/grpc/config.toml b/integration/fixtures/grpc/config.toml index 2aa10f1c9..b38ab2ffa 100644 --- a/integration/fixtures/grpc/config.toml +++ b/integration/fixtures/grpc/config.toml @@ -28,6 +28,7 @@ rootCAs = [ """{{ .CertContent }}""" ] [[http.services.service1.loadbalancer.servers]] url = "https://127.0.0.1:{{ .GRPCServerPort }}" -[tlsStores.default.DefaultCertificate] +[tls.stores] + [tls.stores.default.DefaultCertificate] certFile = """{{ .CertContent }}""" keyFile = """{{ .KeyContent }}""" diff --git a/integration/fixtures/grpc/config_h2c_termination.toml b/integration/fixtures/grpc/config_h2c_termination.toml index 2042816b5..71d3aec6b 100644 --- a/integration/fixtures/grpc/config_h2c_termination.toml +++ b/integration/fixtures/grpc/config_h2c_termination.toml @@ -26,6 +26,7 @@ level = "DEBUG" [[http.services.service1.loadbalancer.servers]] url = "h2c://127.0.0.1:{{ .GRPCServerPort }}" -[tlsStores.default.DefaultCertificate] +[tls.stores] + [tls.stores.default.DefaultCertificate] certFile = """{{ .CertContent }}""" keyFile = """{{ .KeyContent }}""" diff --git a/integration/fixtures/grpc/config_insecure.toml b/integration/fixtures/grpc/config_insecure.toml index 406f4286a..ce4c7fb4b 100644 --- a/integration/fixtures/grpc/config_insecure.toml +++ b/integration/fixtures/grpc/config_insecure.toml @@ -28,6 +28,7 @@ insecureSkipVerify = true [[http.services.service1.loadbalancer.servers]] url = "https://127.0.0.1:{{ .GRPCServerPort }}" -[tlsStores.default.DefaultCertificate] +[tls.stores] + [tls.stores.default.DefaultCertificate] certFile = """{{ .CertContent }}""" keyFile = """{{ .KeyContent }}""" diff --git a/integration/fixtures/grpc/config_retry.toml b/integration/fixtures/grpc/config_retry.toml index 0073ca393..f88706400 100644 --- a/integration/fixtures/grpc/config_retry.toml +++ b/integration/fixtures/grpc/config_retry.toml @@ -35,6 +35,7 @@ rootCAs = [ """{{ .CertContent }}""" ] [[http.services.service1.loadbalancer.servers]] url = "https://127.0.0.1:{{ .GRPCServerPort }}" -[tlsStores.default.DefaultCertificate] +[tls.stores] + [tls.stores.default.DefaultCertificate] certFile = """{{ .CertContent }}""" keyFile = """{{ .KeyContent }}""" diff --git a/integration/fixtures/https/clientca/https_1ca1config.toml b/integration/fixtures/https/clientca/https_1ca1config.toml index 3ee74c690..063b4f22d 100644 --- a/integration/fixtures/https/clientca/https_1ca1config.toml +++ b/integration/fixtures/https/clientca/https_1ca1config.toml @@ -36,16 +36,15 @@ level = "DEBUG" [[http.services.service2.LoadBalancer.Servers]] URL = "http://127.0.0.1:9020" -[[tls]] - [tls.certificate] - certFile = "fixtures/https/snitest.com.cert" - keyFile = "fixtures/https/snitest.com.key" +[[tls.certificates]] + certFile = "fixtures/https/snitest.com.cert" + keyFile = "fixtures/https/snitest.com.key" -[[tls]] - [tls.certificate] - certFile = "fixtures/https/snitest.org.cert" - keyFile = "fixtures/https/snitest.org.key" +[[tls.certificates]] + certFile = "fixtures/https/snitest.org.cert" + keyFile = "fixtures/https/snitest.org.key" -[tlsOptions.default.ClientCA] +[tls.options] + [tls.options.default.ClientCA] files = ["fixtures/https/clientca/ca1.crt"] optional = true diff --git a/integration/fixtures/https/clientca/https_2ca1config.toml b/integration/fixtures/https/clientca/https_2ca1config.toml index 5497da6cd..e09d2c006 100644 --- a/integration/fixtures/https/clientca/https_2ca1config.toml +++ b/integration/fixtures/https/clientca/https_2ca1config.toml @@ -36,14 +36,14 @@ level = "DEBUG" [[http.services.service2.LoadBalancer.Servers]] URL = "http://127.0.0.1:9020" -[[tls]] - [tls.certificate] - certFile = "fixtures/https/snitest.com.cert" - keyFile = "fixtures/https/snitest.com.key" -[[tls]] - [tls.certificate] - certFile = "fixtures/https/snitest.org.cert" - keyFile = "fixtures/https/snitest.org.key" +[[tls.certificates]] + certFile = "fixtures/https/snitest.com.cert" + keyFile = "fixtures/https/snitest.com.key" -[tlsOptions.default.ClientCA] +[[tls.certificates]] + certFile = "fixtures/https/snitest.org.cert" + keyFile = "fixtures/https/snitest.org.key" + +[tls.options] + [tls.options.default.ClientCA] files = ["fixtures/https/clientca/ca1and2.crt"] \ No newline at end of file diff --git a/integration/fixtures/https/clientca/https_2ca2config.toml b/integration/fixtures/https/clientca/https_2ca2config.toml index 2b518170d..138ac2a18 100644 --- a/integration/fixtures/https/clientca/https_2ca2config.toml +++ b/integration/fixtures/https/clientca/https_2ca2config.toml @@ -35,16 +35,15 @@ level = "DEBUG" [[http.services.service2.LoadBalancer.Servers]] URL = "http://127.0.0.1:9020" -[[tls]] - [tls.certificate] - certFile = "fixtures/https/snitest.com.cert" - keyFile = "fixtures/https/snitest.com.key" +[[tls.certificates]] + certFile = "fixtures/https/snitest.com.cert" + keyFile = "fixtures/https/snitest.com.key" -[[tls]] - [tls.certificate] - certFile = "fixtures/https/snitest.org.cert" - keyFile = "fixtures/https/snitest.org.key" +[[tls.certificates]] + certFile = "fixtures/https/snitest.org.cert" + keyFile = "fixtures/https/snitest.org.key" -[tlsOptions.default.ClientCA] +[tls.options] + [tls.options.default.ClientCA] files = ["fixtures/https/clientca/ca1.crt", "fixtures/https/clientca/ca2.crt"] optional = false diff --git a/integration/fixtures/https/dynamic_https.toml b/integration/fixtures/https/dynamic_https.toml index 949b3c4ed..65bfe163f 100644 --- a/integration/fixtures/https/dynamic_https.toml +++ b/integration/fixtures/https/dynamic_https.toml @@ -20,9 +20,8 @@ [[http.services.service2.LoadBalancer.Servers]] url = "http://127.0.0.1:9020" -[[tls]] - # bad certificates to validate the loop on the certificate appending - [tls.certificate] +# bad certificates to validate the loop on the certificate appending +[[tls.certificates]] # bad content certFile = """-----BEGIN CERTIFICATE----- MIIC/zCCAeegAwIBAgIJALAYHG/vGqWEMA0GCSqGSIb3DQEBBQUAMBYxFDASBgNV @@ -34,8 +33,7 @@ eRG3DaVpez4DQVupZDHMgxJUYqqKynUj6GD1YiaxGROj3TYCu6e7OxyhalhCllSu w/X5M802XqzLjeec5zHoZDfknnAkgR9MsxZYmZPFaDyL6GOKUB8= -----END RSA PRIVATE KEY-----""" -[[tls]] - [tls.certificate] +[[tls.certificates]] certFile = """-----BEGIN CERTIFICATE----- MIIC/zCCAeegAwIBAgIJALAYHG/vGqWEMA0GCSqGSIb3DQEBBQUAMBYxFDASBgNV BAMMC3NuaXRlc3Qub3JnMB4XDTE1MTEyMzIyMDU0NFoXDTI1MTEyMDIyMDU0NFow diff --git a/integration/fixtures/https/dynamic_https_sni_default_cert.toml b/integration/fixtures/https/dynamic_https_sni_default_cert.toml index cb0bd446a..50efab1f4 100644 --- a/integration/fixtures/https/dynamic_https_sni_default_cert.toml +++ b/integration/fixtures/https/dynamic_https_sni_default_cert.toml @@ -31,16 +31,15 @@ level = "DEBUG" [[http.services.service1.LoadBalancer.Servers]] url = "http://127.0.0.1:9010" -[[tls]] - [tls.certificate] +[[tls.certificates]] certFile = "fixtures/https/wildcard.snitest.com.cert" keyFile = "fixtures/https/wildcard.snitest.com.key" -[[tls]] - [tls.certificate] - certFile = "fixtures/https/www.snitest.com.cert" - keyFile = "fixtures/https/www.snitest.com.key" +[[tls.certificates]] + certFile = "fixtures/https/www.snitest.com.cert" + keyFile = "fixtures/https/www.snitest.com.key" -[tlsStores.default.DefaultCertificate] +[tls.stores] + [tls.stores.default.DefaultCertificate] certFile = "fixtures/https/snitest.com.cert" keyFile = "fixtures/https/snitest.com.key" diff --git a/integration/fixtures/https/https_sni.toml b/integration/fixtures/https/https_sni.toml index 944f11e24..3c184436c 100644 --- a/integration/fixtures/https/https_sni.toml +++ b/integration/fixtures/https/https_sni.toml @@ -36,12 +36,10 @@ level = "DEBUG" [[http.services.service2.LoadBalancer.Servers]] URL = "http://127.0.0.1:9020" -[[tls]] - [tls.certificate] - certFile = "fixtures/https/snitest.com.cert" - keyFile = "fixtures/https/snitest.com.key" +[[tls.certificates]] + certFile = "fixtures/https/snitest.com.cert" + keyFile = "fixtures/https/snitest.com.key" -[[tls]] - [tls.certificate] - certFile = "fixtures/https/snitest.org.cert" - keyFile = "fixtures/https/snitest.org.key" +[[tls.certificates]] + certFile = "fixtures/https/snitest.org.cert" + keyFile = "fixtures/https/snitest.org.key" diff --git a/integration/fixtures/https/https_sni_case_insensitive_dynamic.toml b/integration/fixtures/https/https_sni_case_insensitive_dynamic.toml index d6501c9cc..364d77816 100644 --- a/integration/fixtures/https/https_sni_case_insensitive_dynamic.toml +++ b/integration/fixtures/https/https_sni_case_insensitive_dynamic.toml @@ -31,11 +31,11 @@ level = "DEBUG" [[http.services.service1.LoadBalancer.Servers]] url = "http://127.0.0.1:9010" -[[tls]] - [tls.certificate] - certFile = "fixtures/https/uppercase_wildcard.www.snitest.com.cert" - keyFile = "fixtures/https/uppercase_wildcard.www.snitest.com.key" +[[tls.certificates]] + certFile = "fixtures/https/uppercase_wildcard.www.snitest.com.cert" + keyFile = "fixtures/https/uppercase_wildcard.www.snitest.com.key" -[tlsStores.default.DefaultCertificate] +[tls.stores] + [tls.stores.default.DefaultCertificate] certFile = "fixtures/https/wildcard.snitest.com.cert" keyFile = "fixtures/https/wildcard.snitest.com.key" diff --git a/integration/fixtures/https/https_sni_default_cert.toml b/integration/fixtures/https/https_sni_default_cert.toml index b5034dcea..50efab1f4 100644 --- a/integration/fixtures/https/https_sni_default_cert.toml +++ b/integration/fixtures/https/https_sni_default_cert.toml @@ -31,16 +31,15 @@ level = "DEBUG" [[http.services.service1.LoadBalancer.Servers]] url = "http://127.0.0.1:9010" -[[tls]] - [tls.certificate] - certFile = "fixtures/https/wildcard.snitest.com.cert" - keyFile = "fixtures/https/wildcard.snitest.com.key" +[[tls.certificates]] + certFile = "fixtures/https/wildcard.snitest.com.cert" + keyFile = "fixtures/https/wildcard.snitest.com.key" -[[tls]] - [tls.certificate] - certFile = "fixtures/https/www.snitest.com.cert" - keyFile = "fixtures/https/www.snitest.com.key" +[[tls.certificates]] + certFile = "fixtures/https/www.snitest.com.cert" + keyFile = "fixtures/https/www.snitest.com.key" -[tlsStores.default.DefaultCertificate] +[tls.stores] + [tls.stores.default.DefaultCertificate] certFile = "fixtures/https/snitest.com.cert" keyFile = "fixtures/https/snitest.com.key" diff --git a/integration/fixtures/https/https_sni_strict.toml b/integration/fixtures/https/https_sni_strict.toml index 6cca5d576..dce7c13a2 100644 --- a/integration/fixtures/https/https_sni_strict.toml +++ b/integration/fixtures/https/https_sni_strict.toml @@ -1,9 +1,9 @@ [global] -checkNewVersion = false -sendAnonymousUsage = false + checkNewVersion = false + sendAnonymousUsage = false [log] -level = "DEBUG" + level = "DEBUG" [entryPoints] [entryPoints.web-secure] @@ -26,11 +26,13 @@ level = "DEBUG" [[http.services.service1.LoadBalancer.Servers]] url = "http://127.0.0.1:9010" -[tlsOptions.default] +[tls.options] + [tls.options.default] sniStrict = true -[tlsStores.default] - [tlsStores.default.DefaultCertificate] - certFile = "fixtures/https/snitest.com.cert" - keyFile = "fixtures/https/snitest.com.key" +[tls.stores] + [tls.stores.default] + [tls.stores.default.DefaultCertificate] + certFile = "fixtures/https/snitest.com.cert" + keyFile = "fixtures/https/snitest.com.key" diff --git a/integration/fixtures/https/https_tls_options.toml b/integration/fixtures/https/https_tls_options.toml index 680db609c..aad21a2c4 100644 --- a/integration/fixtures/https/https_tls_options.toml +++ b/integration/fixtures/https/https_tls_options.toml @@ -44,18 +44,18 @@ level = "DEBUG" [[http.services.service2.LoadBalancer.Servers]] URL = "http://127.0.0.1:9020" -[[tls]] - [tls.certificate] - certFile = "fixtures/https/snitest.com.cert" - keyFile = "fixtures/https/snitest.com.key" +[[tls.certificates]] + certFile = "fixtures/https/snitest.com.cert" + keyFile = "fixtures/https/snitest.com.key" -[[tls]] - [tls.certificate] - certFile = "fixtures/https/snitest.org.cert" - keyFile = "fixtures/https/snitest.org.key" +[[tls.certificates]] + certFile = "fixtures/https/snitest.org.cert" + keyFile = "fixtures/https/snitest.org.key" -[tlsoptions.foo] +[tls.options] + + [tls.options.foo] minversion = "VersionTLS11" -[tlsoptions.bar] + [tls.options.bar] minversion = "VersionTLS12" diff --git a/integration/fixtures/tcp/mixed.toml b/integration/fixtures/tcp/mixed.toml index 8a73f837c..a94b7c640 100644 --- a/integration/fixtures/tcp/mixed.toml +++ b/integration/fixtures/tcp/mixed.toml @@ -64,7 +64,6 @@ level = "DEBUG" [[tcp.services.whoami-no-cert.loadbalancer.servers]] address = "localhost:8083" -[[tls]] - [tls.certificate] +[[tls.certificates]] certFile = "fixtures/tcp/whoami-c.crt" keyFile = "fixtures/tcp/whoami-c.key" diff --git a/integration/fixtures/tcp/multi-tls-options.toml b/integration/fixtures/tcp/multi-tls-options.toml index 36b75fc67..5551a4088 100644 --- a/integration/fixtures/tcp/multi-tls-options.toml +++ b/integration/fixtures/tcp/multi-tls-options.toml @@ -35,8 +35,10 @@ level = "DEBUG" [[tcp.services.whoami-no-cert.loadbalancer.servers]] address = "localhost:8083" -[tlsoptions.foo] +[tls.options] + + [tls.options.foo] minversion = "VersionTLS11" -[tlsoptions.bar] + [tls.options.bar] minversion = "VersionTLS12" diff --git a/integration/fixtures/tlsclientheaders/simple.toml b/integration/fixtures/tlsclientheaders/simple.toml index 609c4ef5f..26c2cbe7b 100644 --- a/integration/fixtures/tlsclientheaders/simple.toml +++ b/integration/fixtures/tlsclientheaders/simple.toml @@ -1,12 +1,12 @@ [global] -checkNewVersion = false -sendAnonymousUsage = false + checkNewVersion = false + sendAnonymousUsage = false [log] -level = "DEBUG" + level = "DEBUG" [serversTransport] -rootCAs = [ """{{ .RootCertContent }}""" ] + rootCAs = [ """{{ .RootCertContent }}""" ] [entryPoints] [entryPoints.web-secure] @@ -15,16 +15,18 @@ rootCAs = [ """{{ .RootCertContent }}""" ] [api] [providers] - [providers.docker] - endpoint = "unix:///var/run/docker.sock" - watch = true + [providers.docker] + endpoint = "unix:///var/run/docker.sock" + watch = true - [providers.file] + [providers.file] -[tlsOptions.default.ClientCA] +[tls.options] + [tls.options.default.ClientCA] files = [ """{{ .RootCertContent }}""" ] optional = false -[tlsStores.default.DefaultCertificate] +[tls.stores] + [tls.stores.default.DefaultCertificate] certFile = """{{ .ServerCertContent }}""" keyFile = """{{ .ServerKeyContent }}""" diff --git a/integration/fixtures/websocket/config_https.toml b/integration/fixtures/websocket/config_https.toml index a1e672c20..a1fa2f43a 100644 --- a/integration/fixtures/websocket/config_https.toml +++ b/integration/fixtures/websocket/config_https.toml @@ -30,6 +30,7 @@ insecureSkipVerify=true [[http.services.service1.LoadBalancer.Servers]] URL = "{{ .WebsocketServer }}" -[tlsStores.default.DefaultCertificate] +[tls.stores] + [tls.stores.default.DefaultCertificate] certFile = "resources/tls/local.cert" keyFile = "resources/tls/local.key" diff --git a/integration/https_test.go b/integration/https_test.go index 6923f076d..cdbc58489 100644 --- a/integration/https_test.go +++ b/integration/https_test.go @@ -799,12 +799,14 @@ func modifyCertificateConfFileContent(c *check.C, certFileName, confFileName, en // If certificate file is not provided, just truncate the configuration file if len(certFileName) > 0 { tlsConf := config.Configuration{ - TLS: []*traefiktls.Configuration{{ - Certificate: &traefiktls.Certificate{ - CertFile: traefiktls.FileOrContent("fixtures/https/" + certFileName + ".cert"), - KeyFile: traefiktls.FileOrContent("fixtures/https/" + certFileName + ".key"), + TLS: &config.TLSConfiguration{ + Certificates: []*traefiktls.CertAndStores{{ + Certificate: traefiktls.Certificate{ + CertFile: traefiktls.FileOrContent("fixtures/https/" + certFileName + ".cert"), + KeyFile: traefiktls.FileOrContent("fixtures/https/" + certFileName + ".key"), + }}, }, - }}, + }, } var confBuffer bytes.Buffer diff --git a/pkg/config/dyn_config.go b/pkg/config/dyn_config.go index 6b7577945..032cff288 100644 --- a/pkg/config/dyn_config.go +++ b/pkg/config/dyn_config.go @@ -213,24 +213,29 @@ type Message struct { // Configuration is the root of the dynamic configuration type Configuration struct { - HTTP *HTTPConfiguration - TCP *TCPConfiguration - TLS []*traefiktls.Configuration `json:"-" label:"-" yaml:"tls"` - TLSOptions map[string]traefiktls.TLS - TLSStores map[string]traefiktls.Store + HTTP *HTTPConfiguration + TCP *TCPConfiguration + TLS *TLSConfiguration +} + +// TLSConfiguration contains all the configuration parameters of a TLS connection. +type TLSConfiguration struct { + Certificates []*traefiktls.CertAndStores `json:"-" label:"-" yaml:"certificates"` + Options map[string]traefiktls.Options + Stores map[string]traefiktls.Store } // Configurations is for currentConfigurations Map. type Configurations map[string]*Configuration -// HTTPConfiguration FIXME better name? +// HTTPConfiguration contains all the HTTP configuration parameters. type HTTPConfiguration struct { Routers map[string]*Router `json:"routers,omitempty" toml:",omitempty"` Middlewares map[string]*Middleware `json:"middlewares,omitempty" toml:",omitempty"` Services map[string]*Service `json:"services,omitempty" toml:",omitempty"` } -// TCPConfiguration FIXME better name? +// TCPConfiguration contains all the TCP configuration parameters. type TCPConfiguration struct { Routers map[string]*TCPRouter `json:"routers,omitempty" toml:",omitempty"` Services map[string]*TCPService `json:"services,omitempty" toml:",omitempty"` diff --git a/pkg/config/file/fixtures/sample.toml b/pkg/config/file/fixtures/sample.toml index 04d8bc9c5..8ef1d61b8 100644 --- a/pkg/config/file/fixtures/sample.toml +++ b/pkg/config/file/fixtures/sample.toml @@ -497,42 +497,40 @@ [[TCP.Services.TCPService0.LoadBalancer.Servers]] Address = "foobar" -[[TLS]] +[[TLS.Certificates]] Stores = ["foobar", "foobar"] - [TLS.Certificate] - CertFile = "foobar" - KeyFile = "foobar" + CertFile = "foobar" + KeyFile = "foobar" -[[TLS]] +[[TLS.Certificates]] Stores = ["foobar", "foobar"] - [TLS.Certificate] - CertFile = "foobar" - KeyFile = "foobar" + CertFile = "foobar" + KeyFile = "foobar" -[TLSOptions] +[TLS.Options] - [TLSOptions.TLS0] + [TLS.Options.TLS0] MinVersion = "foobar" CipherSuites = ["foobar", "foobar"] SniStrict = true - [TLSOptions.TLS0.ClientCA] + [TLS.Options.TLS0.ClientCA] Files = ["foobar", "foobar"] Optional = true - [TLSOptions.TLS1] + [TLS.Options.TLS1] MinVersion = "foobar" CipherSuites = ["foobar", "foobar"] SniStrict = true - [TLSOptions.TLS1.ClientCA] + [TLS.Options.TLS1.ClientCA] Files = ["foobar", "foobar"] Optional = true -[TLSStores] +[TLS.Stores] - [TLSStores.Store0] - [TLSStores.Store0.DefaultCertificate] + [TLS.Stores.Store0] + [TLS.Stores.Store0.DefaultCertificate] CertFile = "foobar" KeyFile = "foobar" - [TLSStores.Store1] - [TLSStores.Store1.DefaultCertificate] + [TLS.Stores.Store1] + [TLS.Stores.Store1.DefaultCertificate] CertFile = "foobar" KeyFile = "foobar" diff --git a/pkg/provider/acme/provider.go b/pkg/provider/acme/provider.go index 8cdfd58b9..39e2ba072 100644 --- a/pkg/provider/acme/provider.go +++ b/pkg/provider/acme/provider.go @@ -589,14 +589,20 @@ func (p *Provider) refreshCertificates() { Middlewares: map[string]*config.Middleware{}, Services: map[string]*config.Service{}, }, - TLS: []*traefiktls.Configuration{}, + TLS: &config.TLSConfiguration{}, }, } for _, cert := range p.certificates { - cert := &traefiktls.Certificate{CertFile: traefiktls.FileOrContent(cert.Certificate), KeyFile: traefiktls.FileOrContent(cert.Key)} - conf.Configuration.TLS = append(conf.Configuration.TLS, &traefiktls.Configuration{Certificate: cert}) + certConf := &traefiktls.CertAndStores{ + Certificate: traefiktls.Certificate{ + CertFile: traefiktls.FileOrContent(cert.Certificate), + KeyFile: traefiktls.FileOrContent(cert.Key), + }, + } + conf.Configuration.TLS.Certificates = append(conf.Configuration.TLS.Certificates, certConf) } + p.configurationChan <- conf } diff --git a/pkg/provider/file/file.go b/pkg/provider/file/file.go index 57903ec3d..cceb93fbb 100644 --- a/pkg/provider/file/file.go +++ b/pkg/provider/file/file.go @@ -182,28 +182,36 @@ func (p *Provider) loadFileConfig(filename string, parseTemplate bool) (*config. return nil, err } - var tlsConfigs []*tls.Configuration - for _, conf := range configuration.TLS { - bytes, err := conf.Certificate.CertFile.Read() - if err != nil { - log.Error(err) - continue - } - conf.Certificate.CertFile = tls.FileOrContent(string(bytes)) - - bytes, err = conf.Certificate.KeyFile.Read() - if err != nil { - log.Error(err) - continue - } - conf.Certificate.KeyFile = tls.FileOrContent(string(bytes)) - tlsConfigs = append(tlsConfigs, conf) + if configuration.TLS != nil { + configuration.TLS.Certificates = flattenCertificates(configuration.TLS) } - configuration.TLS = tlsConfigs return configuration, nil } +func flattenCertificates(tlsConfig *config.TLSConfiguration) []*tls.CertAndStores { + var certs []*tls.CertAndStores + for _, cert := range tlsConfig.Certificates { + content, err := cert.Certificate.CertFile.Read() + if err != nil { + log.Error(err) + continue + } + cert.Certificate.CertFile = tls.FileOrContent(string(content)) + + content, err = cert.Certificate.KeyFile.Read() + if err != nil { + log.Error(err) + continue + } + cert.Certificate.KeyFile = tls.FileOrContent(string(content)) + + certs = append(certs, cert) + } + + return certs +} + func (p *Provider) loadFileConfigFromDirectory(ctx context.Context, directory string, configuration *config.Configuration) (*config.Configuration, error) { logger := log.FromContext(ctx) @@ -223,13 +231,16 @@ func (p *Provider) loadFileConfigFromDirectory(ctx context.Context, directory st Routers: make(map[string]*config.TCPRouter), Services: make(map[string]*config.TCPService), }, + TLS: &config.TLSConfiguration{ + Stores: make(map[string]tls.Store), + Options: make(map[string]tls.Options), + }, } } - configTLSMaps := make(map[*tls.Configuration]struct{}) + configTLSMaps := make(map[*tls.CertAndStores]struct{}) for _, item := range fileList { - if item.IsDir() { configuration, err = p.loadFileConfigFromDirectory(ctx, filepath.Join(directory, item.Name()), configuration) if err != nil { @@ -291,7 +302,7 @@ func (p *Provider) loadFileConfigFromDirectory(ctx context.Context, directory st } } - for _, conf := range c.TLS { + for _, conf := range c.TLS.Certificates { if _, exists := configTLSMaps[conf]; exists { logger.Warnf("TLS configuration %v already configured, skipping", conf) } else { @@ -300,9 +311,14 @@ func (p *Provider) loadFileConfigFromDirectory(ctx context.Context, directory st } } - for conf := range configTLSMaps { - configuration.TLS = append(configuration.TLS, conf) + if len(configTLSMaps) > 0 { + configuration.TLS = &config.TLSConfiguration{} } + + for conf := range configTLSMaps { + configuration.TLS.Certificates = append(configuration.TLS.Certificates, conf) + } + return configuration, nil } @@ -364,9 +380,10 @@ func (p *Provider) decodeConfiguration(filePath string, content string) (*config Routers: make(map[string]*config.TCPRouter), Services: make(map[string]*config.TCPService), }, - TLS: make([]*tls.Configuration, 0), - TLSStores: make(map[string]tls.Store), - TLSOptions: make(map[string]tls.TLS), + TLS: &config.TLSConfiguration{ + Stores: make(map[string]tls.Store), + Options: make(map[string]tls.Options), + }, } switch strings.ToLower(filepath.Ext(filePath)) { diff --git a/pkg/provider/file/file_test.go b/pkg/provider/file/file_test.go index 46f28354b..019e74036 100644 --- a/pkg/provider/file/file_test.go +++ b/pkg/provider/file/file_test.go @@ -37,10 +37,9 @@ func TestTLSContent(t *testing.T) { require.NoError(t, err) content := ` -[[tls]] - [tls.certificate] - certFile = "` + fileTLS.Name() + `" - keyFile = "` + fileTLS.Name() + `" +[[tls.certificates]] + certFile = "` + fileTLS.Name() + `" + keyFile = "` + fileTLS.Name() + `" ` _, err = fileConfig.Write([]byte(content)) @@ -50,8 +49,8 @@ func TestTLSContent(t *testing.T) { configuration, err := provider.loadFileConfig(fileConfig.Name(), true) require.NoError(t, err) - require.Equal(t, "CONTENT", configuration.TLS[0].Certificate.CertFile.String()) - require.Equal(t, "CONTENT", configuration.TLS[0].Certificate.KeyFile.String()) + require.Equal(t, "CONTENT", configuration.TLS.Certificates[0].Certificate.CertFile.String()) + require.Equal(t, "CONTENT", configuration.TLS.Certificates[0].Certificate.KeyFile.String()) } func TestErrorWhenEmptyConfig(t *testing.T) { @@ -91,9 +90,11 @@ func TestProvideWithoutWatch(t *testing.T) { timeout := time.After(time.Second) select { case conf := <-configChan: + require.NotNil(t, conf.Configuration.HTTP) assert.Len(t, conf.Configuration.HTTP.Services, test.expectedNumService) assert.Len(t, conf.Configuration.HTTP.Routers, test.expectedNumRouter) - assert.Len(t, conf.Configuration.TLS, test.expectedNumTLSConf) + require.NotNil(t, conf.Configuration.TLS) + assert.Len(t, conf.Configuration.TLS.Certificates, test.expectedNumTLSConf) case <-timeout: t.Errorf("timeout while waiting for config") } @@ -116,9 +117,11 @@ func TestProvideWithWatch(t *testing.T) { timeout := time.After(time.Second) select { case conf := <-configChan: + require.NotNil(t, conf.Configuration.HTTP) assert.Len(t, conf.Configuration.HTTP.Services, 0) assert.Len(t, conf.Configuration.HTTP.Routers, 0) - assert.Len(t, conf.Configuration.TLS, 0) + require.NotNil(t, conf.Configuration.TLS) + assert.Len(t, conf.Configuration.TLS.Certificates, 0) case <-timeout: t.Errorf("timeout while waiting for config") } @@ -148,7 +151,7 @@ func TestProvideWithWatch(t *testing.T) { numUpdates++ numServices = len(conf.Configuration.HTTP.Services) numRouters = len(conf.Configuration.HTTP.Routers) - numTLSConfs = len(conf.Configuration.TLS) + numTLSConfs = len(conf.Configuration.TLS.Certificates) t.Logf("received update #%d: services %d/%d, routers %d/%d, TLS configs %d/%d", numUpdates, numServices, test.expectedNumService, numRouters, test.expectedNumRouter, numTLSConfs, test.expectedNumTLSConf) if numServices == test.expectedNumService && numRouters == test.expectedNumRouter && numTLSConfs == test.expectedNumTLSConf { diff --git a/pkg/provider/file/fixtures/toml/dir01_file03.toml b/pkg/provider/file/fixtures/toml/dir01_file03.toml index 498a19b91..7d5a35e0d 100644 --- a/pkg/provider/file/fixtures/toml/dir01_file03.toml +++ b/pkg/provider/file/fixtures/toml/dir01_file03.toml @@ -1,16 +1,17 @@ -[[TLS]] - [TLS.Certificate] - CertFile = "integration/fixtures/https/snitest1.com.cert" - KeyFile = "integration/fixtures/https/snitest1.com.key" -[[TLS]] - [TLS.Certificate] - CertFile = "integration/fixtures/https/snitest2.com.cert" - KeyFile = "integration/fixtures/https/snitest2.com.key" -[[TLS]] - [TLS.Certificate] - CertFile = "integration/fixtures/https/snitest3.com.cert" - KeyFile = "integration/fixtures/https/snitest3.com.key" -[[TLS]] - [TLS.Certificate] - CertFile = "integration/fixtures/https/snitest4.com.cert" - KeyFile = "integration/fixtures/https/snitest4.com.key" +[TLS] + +[[TLS.Certificates]] + CertFile = "integration/fixtures/https/snitest1.com.cert" + KeyFile = "integration/fixtures/https/snitest1.com.key" + +[[TLS.Certificates]] + CertFile = "integration/fixtures/https/snitest2.com.cert" + KeyFile = "integration/fixtures/https/snitest2.com.key" + +[[TLS.Certificates]] + CertFile = "integration/fixtures/https/snitest3.com.cert" + KeyFile = "integration/fixtures/https/snitest3.com.key" + +[[TLS.Certificates]] + CertFile = "integration/fixtures/https/snitest4.com.cert" + KeyFile = "integration/fixtures/https/snitest4.com.key" diff --git a/pkg/provider/file/fixtures/toml/simple_file_01.toml b/pkg/provider/file/fixtures/toml/simple_file_01.toml index e3af6f686..287597951 100644 --- a/pkg/provider/file/fixtures/toml/simple_file_01.toml +++ b/pkg/provider/file/fixtures/toml/simple_file_01.toml @@ -33,23 +33,25 @@ [http.services.application-6.loadbalancer] [[http.services.application-6.loadbalancer.servers]] url = "http://172.17.0.6:80" -[[TLS]] - [TLS.Certificate] - CertFile = "integration/fixtures/https/snitest1.com.cert" - KeyFile = "integration/fixtures/https/snitest1.com.key" -[[TLS]] - [TLS.Certificate] - CertFile = "integration/fixtures/https/snitest2.com.cert" - KeyFile = "integration/fixtures/https/snitest2.com.key" -[[TLS]] - [TLS.Certificate] - CertFile = "integration/fixtures/https/snitest3.com.cert" - KeyFile = "integration/fixtures/https/snitest3.com.key" -[[TLS]] - [TLS.Certificate] - CertFile = "integration/fixtures/https/snitest4.com.cert" - KeyFile = "integration/fixtures/https/snitest4.com.key" -[[TLS]] - [TLS.Certificate] - CertFile = "integration/fixtures/https/snitest5.com.cert" - KeyFile = "integration/fixtures/https/snitest5.com.key" + +[TLS] + +[[TLS.Certificates]] + CertFile = "integration/fixtures/https/snitest1.com.cert" + KeyFile = "integration/fixtures/https/snitest1.com.key" + +[[TLS.Certificates]] + CertFile = "integration/fixtures/https/snitest2.com.cert" + KeyFile = "integration/fixtures/https/snitest2.com.key" + +[[TLS.Certificates]] + CertFile = "integration/fixtures/https/snitest3.com.cert" + KeyFile = "integration/fixtures/https/snitest3.com.key" + +[[TLS.Certificates]] + CertFile = "integration/fixtures/https/snitest4.com.cert" + KeyFile = "integration/fixtures/https/snitest4.com.key" + +[[TLS.Certificates]] + CertFile = "integration/fixtures/https/snitest5.com.cert" + KeyFile = "integration/fixtures/https/snitest5.com.key" diff --git a/pkg/provider/file/fixtures/toml/simple_file_02.toml b/pkg/provider/file/fixtures/toml/simple_file_02.toml index e614160d3..2b4feb4a4 100644 --- a/pkg/provider/file/fixtures/toml/simple_file_02.toml +++ b/pkg/provider/file/fixtures/toml/simple_file_02.toml @@ -44,19 +44,21 @@ [http.services.application-8.loadbalancer] [[http.services.application-8.loadbalancer.servers]] url = "http://172.17.0.8:80" -[[TLS]] - [TLS.Certificate] - CertFile = "integration/fixtures/https/snitest1.com.cert" - KeyFile = "integration/fixtures/https/snitest1.com.key" -[[TLS]] - [TLS.Certificate] - CertFile = "integration/fixtures/https/snitest2.com.cert" - KeyFile = "integration/fixtures/https/snitest2.com.key" -[[TLS]] - [TLS.Certificate] - CertFile = "integration/fixtures/https/snitest3.com.cert" - KeyFile = "integration/fixtures/https/snitest3.com.key" -[[TLS]] - [TLS.Certificate] - CertFile = "integration/fixtures/https/snitest4.com.cert" - KeyFile = "integration/fixtures/https/snitest4.com.key" + +[TLS] + +[[TLS.Certificates]] + CertFile = "integration/fixtures/https/snitest1.com.cert" + KeyFile = "integration/fixtures/https/snitest1.com.key" + +[[TLS.Certificates]] + CertFile = "integration/fixtures/https/snitest2.com.cert" + KeyFile = "integration/fixtures/https/snitest2.com.key" + +[[TLS.Certificates]] + CertFile = "integration/fixtures/https/snitest3.com.cert" + KeyFile = "integration/fixtures/https/snitest3.com.key" + +[[TLS.Certificates]] + CertFile = "integration/fixtures/https/snitest4.com.cert" + KeyFile = "integration/fixtures/https/snitest4.com.key" diff --git a/pkg/provider/file/fixtures/toml/simple_traefik_file_01.toml b/pkg/provider/file/fixtures/toml/simple_traefik_file_01.toml index 2aa73ad54..db2d68bfc 100644 --- a/pkg/provider/file/fixtures/toml/simple_traefik_file_01.toml +++ b/pkg/provider/file/fixtures/toml/simple_traefik_file_01.toml @@ -1,3 +1,2 @@ - [log] - level = "DEBUG" + level = "DEBUG" diff --git a/pkg/provider/file/fixtures/toml/simple_traefik_file_02.toml b/pkg/provider/file/fixtures/toml/simple_traefik_file_02.toml index 4d9e472f5..dcc1c678d 100644 --- a/pkg/provider/file/fixtures/toml/simple_traefik_file_02.toml +++ b/pkg/provider/file/fixtures/toml/simple_traefik_file_02.toml @@ -20,19 +20,21 @@ [http.services.application-3.loadbalancer] [[http.services.application-3.loadbalancer.servers]] url = "http://172.17.0.3:80" -[[TLS]] - [TLS.Certificate] - CertFile = "integration/fixtures/https/snitest1.com.cert" - KeyFile = "integration/fixtures/https/snitest1.com.key" -[[TLS]] - [TLS.Certificate] - CertFile = "integration/fixtures/https/snitest2.com.cert" - KeyFile = "integration/fixtures/https/snitest2.com.key" -[[TLS]] - [TLS.Certificate] - CertFile = "integration/fixtures/https/snitest3.com.cert" - KeyFile = "integration/fixtures/https/snitest3.com.key" -[[TLS]] - [TLS.Certificate] - CertFile = "integration/fixtures/https/snitest4.com.cert" - KeyFile = "integration/fixtures/https/snitest4.com.key" + +[TLS] + +[[TLS.Certificates]] + CertFile = "integration/fixtures/https/snitest1.com.cert" + KeyFile = "integration/fixtures/https/snitest1.com.key" + +[[TLS.Certificates]] + CertFile = "integration/fixtures/https/snitest2.com.cert" + KeyFile = "integration/fixtures/https/snitest2.com.key" + +[[TLS.Certificates]] + CertFile = "integration/fixtures/https/snitest3.com.cert" + KeyFile = "integration/fixtures/https/snitest3.com.key" + +[[TLS.Certificates]] + CertFile = "integration/fixtures/https/snitest4.com.cert" + KeyFile = "integration/fixtures/https/snitest4.com.key" diff --git a/pkg/provider/file/fixtures/toml/simple_traefik_file_with_templating.toml b/pkg/provider/file/fixtures/toml/simple_traefik_file_with_templating.toml index 99bb1bc14..c07e8601c 100644 --- a/pkg/provider/file/fixtures/toml/simple_traefik_file_with_templating.toml +++ b/pkg/provider/file/fixtures/toml/simple_traefik_file_with_templating.toml @@ -1,7 +1,8 @@ +temp="{{ getTag \"test\" }}" - temp="{{ getTag \"test\" }}" - [providers.file] - [http.routers] +[providers.file] + +[http.routers] [http.routers."router1"] service = "application-1" @@ -21,19 +22,21 @@ [http.services.application-3.loadbalancer] [[http.services.application-3.loadbalancer.servers]] url = "http://172.17.0.3:80" -[[TLS]] - [TLS.Certificate] - CertFile = "integration/fixtures/https/snitest1.com.cert" - KeyFile = "integration/fixtures/https/snitest1.com.key" -[[TLS]] - [TLS.Certificate] - CertFile = "integration/fixtures/https/snitest2.com.cert" - KeyFile = "integration/fixtures/https/snitest2.com.key" -[[TLS]] - [TLS.Certificate] - CertFile = "integration/fixtures/https/snitest3.com.cert" - KeyFile = "integration/fixtures/https/snitest3.com.key" -[[TLS]] - [TLS.Certificate] - CertFile = "integration/fixtures/https/snitest4.com.cert" - KeyFile = "integration/fixtures/https/snitest4.com.key" + +[TLS] + +[[TLS.Certificates]] + CertFile = "integration/fixtures/https/snitest1.com.cert" + KeyFile = "integration/fixtures/https/snitest1.com.key" + +[[TLS.Certificates]] + CertFile = "integration/fixtures/https/snitest2.com.cert" + KeyFile = "integration/fixtures/https/snitest2.com.key" + +[[TLS.Certificates]] + CertFile = "integration/fixtures/https/snitest3.com.cert" + KeyFile = "integration/fixtures/https/snitest3.com.key" + +[[TLS.Certificates]] + CertFile = "integration/fixtures/https/snitest4.com.cert" + KeyFile = "integration/fixtures/https/snitest4.com.key" diff --git a/pkg/provider/file/fixtures/toml/template_file.toml b/pkg/provider/file/fixtures/toml/template_file.toml index 1958d6387..062788f9d 100644 --- a/pkg/provider/file/fixtures/toml/template_file.toml +++ b/pkg/provider/file/fixtures/toml/template_file.toml @@ -1,4 +1,3 @@ - [http.routers] {{ range $i, $e := until 20 }} [http.routers.router{{ $e }}] diff --git a/pkg/provider/file/fixtures/yaml/dir01_file03.yml b/pkg/provider/file/fixtures/yaml/dir01_file03.yml index e243d4fa8..3bd36db08 100644 --- a/pkg/provider/file/fixtures/yaml/dir01_file03.yml +++ b/pkg/provider/file/fixtures/yaml/dir01_file03.yml @@ -1,13 +1,10 @@ tls: - - certificate: - certfile: integration/fixtures/https/snitest1.com.cert - keyfile: integration/fixtures/https/snitest1.com.key - - certificate: - certfile: integration/fixtures/https/snitest2.com.cert - keyfile: integration/fixtures/https/snitest2.com.key - - certificate: - certfile: integration/fixtures/https/snitest3.com.cert - keyfile: integration/fixtures/https/snitest3.com.key - - certificate: - certfile: integration/fixtures/https/snitest4.com.cert - keyfile: integration/fixtures/https/snitest4.com.key + certificates: + - certfile: integration/fixtures/https/snitest1.com.cert + keyfile: integration/fixtures/https/snitest1.com.key + - certfile: integration/fixtures/https/snitest2.com.cert + keyfile: integration/fixtures/https/snitest2.com.key + - certfile: integration/fixtures/https/snitest3.com.cert + keyfile: integration/fixtures/https/snitest3.com.key + - certfile: integration/fixtures/https/snitest4.com.cert + keyfile: integration/fixtures/https/snitest4.com.key diff --git a/pkg/provider/file/fixtures/yaml/simple_file_01.yml b/pkg/provider/file/fixtures/yaml/simple_file_01.yml index b2fc6e191..e1cd1cb5b 100644 --- a/pkg/provider/file/fixtures/yaml/simple_file_01.yml +++ b/pkg/provider/file/fixtures/yaml/simple_file_01.yml @@ -33,18 +33,14 @@ http: - url: 'http://172.17.0.6:80' tls: - - certificate: - certfile: integration/fixtures/https/snitest1.com.cert - keyfile: integration/fixtures/https/snitest1.com.key - - certificate: - certfile: integration/fixtures/https/snitest2.com.cert - keyfile: integration/fixtures/https/snitest2.com.key - - certificate: - certfile: integration/fixtures/https/snitest3.com.cert - keyfile: integration/fixtures/https/snitest3.com.key - - certificate: - certfile: integration/fixtures/https/snitest4.com.cert - keyfile: integration/fixtures/https/snitest4.com.key - - certificate: - certfile: integration/fixtures/https/snitest5.com.cert - keyfile: integration/fixtures/https/snitest5.com.key + certificates: + - certfile: integration/fixtures/https/snitest1.com.cert + keyfile: integration/fixtures/https/snitest1.com.key + - certfile: integration/fixtures/https/snitest2.com.cert + keyfile: integration/fixtures/https/snitest2.com.key + - certfile: integration/fixtures/https/snitest3.com.cert + keyfile: integration/fixtures/https/snitest3.com.key + - certfile: integration/fixtures/https/snitest4.com.cert + keyfile: integration/fixtures/https/snitest4.com.key + - certfile: integration/fixtures/https/snitest5.com.cert + keyfile: integration/fixtures/https/snitest5.com.key diff --git a/pkg/provider/file/fixtures/yaml/simple_file_02.yml b/pkg/provider/file/fixtures/yaml/simple_file_02.yml index ae40b8789..6066f9a57 100644 --- a/pkg/provider/file/fixtures/yaml/simple_file_02.yml +++ b/pkg/provider/file/fixtures/yaml/simple_file_02.yml @@ -43,16 +43,12 @@ http: - url: 'http://172.17.0.8:80' tls: - - certificate: - certfile: integration/fixtures/https/snitest1.com.cert + certificates: + - certfile: integration/fixtures/https/snitest1.com.cert keyfile: integration/fixtures/https/snitest1.com.key - - certificate: - certfile: integration/fixtures/https/snitest2.com.cert + - certfile: integration/fixtures/https/snitest2.com.cert keyfile: integration/fixtures/https/snitest2.com.key - - certificate: - certfile: integration/fixtures/https/snitest3.com.cert + - certfile: integration/fixtures/https/snitest3.com.cert keyfile: integration/fixtures/https/snitest3.com.key - - certificate: - certfile: integration/fixtures/https/snitest4.com.cert - keyfile: integration/fixtures/https/snitest4.com.key - + - certfile: integration/fixtures/https/snitest4.com.cert + keyfile: integration/fixtures/https/snitest4.com.key \ No newline at end of file diff --git a/pkg/provider/file/fixtures/yaml/simple_traefik_file_02.yml b/pkg/provider/file/fixtures/yaml/simple_traefik_file_02.yml index f8733b514..4d6f87160 100644 --- a/pkg/provider/file/fixtures/yaml/simple_traefik_file_02.yml +++ b/pkg/provider/file/fixtures/yaml/simple_traefik_file_02.yml @@ -21,15 +21,12 @@ http: - url: 'http://172.17.0.3:80' tls: - - certificate: - certfile: integration/fixtures/https/snitest1.com.cert + certificates: + - certfile: integration/fixtures/https/snitest1.com.cert keyfile: integration/fixtures/https/snitest1.com.key - - certificate: - certfile: integration/fixtures/https/snitest2.com.cert + - certfile: integration/fixtures/https/snitest2.com.cert keyfile: integration/fixtures/https/snitest2.com.key - - certificate: - certfile: integration/fixtures/https/snitest3.com.cert + - certfile: integration/fixtures/https/snitest3.com.cert keyfile: integration/fixtures/https/snitest3.com.key - - certificate: - certfile: integration/fixtures/https/snitest4.com.cert - keyfile: integration/fixtures/https/snitest4.com.key + - certfile: integration/fixtures/https/snitest4.com.cert + keyfile: integration/fixtures/https/snitest4.com.key \ No newline at end of file diff --git a/pkg/provider/kubernetes/crd/kubernetes.go b/pkg/provider/kubernetes/crd/kubernetes.go index a18781d69..07c3e7610 100644 --- a/pkg/provider/kubernetes/crd/kubernetes.go +++ b/pkg/provider/kubernetes/crd/kubernetes.go @@ -293,14 +293,14 @@ func loadServers(client Client, namespace string, svc v1alpha1.Service) ([]confi return servers, nil } -func buildTLSOptions(ctx context.Context, client Client) map[string]tls.TLS { +func buildTLSOptions(ctx context.Context, client Client) map[string]tls.Options { tlsOptionsCRD := client.GetTLSOptions() - var tlsOptions map[string]tls.TLS + var tlsOptions map[string]tls.Options if len(tlsOptionsCRD) == 0 { return tlsOptions } - tlsOptions = make(map[string]tls.TLS) + tlsOptions = make(map[string]tls.Options) for _, tlsOption := range tlsOptionsCRD { logger := log.FromContext(log.With(ctx, log.Str("tlsOption", tlsOption.Name), log.Str("namespace", tlsOption.Namespace))) @@ -327,7 +327,7 @@ func buildTLSOptions(ctx context.Context, client Client) map[string]tls.TLS { clientCAs = append(clientCAs, tls.FileOrContent(cert)) } - tlsOptions[makeID(tlsOption.Namespace, tlsOption.Name)] = tls.TLS{ + tlsOptions[makeID(tlsOption.Namespace, tlsOption.Name)] = tls.Options{ MinVersion: tlsOption.Spec.MinVersion, CipherSuites: tlsOption.Spec.CipherSuites, ClientCA: tls.ClientCA{ @@ -340,7 +340,7 @@ func buildTLSOptions(ctx context.Context, client Client) map[string]tls.TLS { return tlsOptions } -func (p *Provider) loadIngressRouteConfiguration(ctx context.Context, client Client, tlsConfigs map[string]*tls.Configuration) *config.HTTPConfiguration { +func (p *Provider) loadIngressRouteConfiguration(ctx context.Context, client Client, tlsConfigs map[string]*tls.CertAndStores) *config.HTTPConfiguration { conf := &config.HTTPConfiguration{ Routers: map[string]*config.Router{}, Middlewares: map[string]*config.Middleware{}, @@ -465,7 +465,7 @@ func (p *Provider) loadIngressRouteConfiguration(ctx context.Context, client Cli return conf } -func (p *Provider) loadIngressRouteTCPConfiguration(ctx context.Context, client Client, tlsConfigs map[string]*tls.Configuration) *config.TCPConfiguration { +func (p *Provider) loadIngressRouteTCPConfiguration(ctx context.Context, client Client, tlsConfigs map[string]*tls.CertAndStores) *config.TCPConfiguration { conf := &config.TCPConfiguration{ Routers: map[string]*config.TCPRouter{}, Services: map[string]*config.TCPService{}, @@ -565,12 +565,14 @@ func (p *Provider) loadIngressRouteTCPConfiguration(ctx context.Context, client } func (p *Provider) loadConfigurationFromCRD(ctx context.Context, client Client) *config.Configuration { - tlsConfigs := make(map[string]*tls.Configuration) + tlsConfigs := make(map[string]*tls.CertAndStores) conf := &config.Configuration{ - HTTP: p.loadIngressRouteConfiguration(ctx, client, tlsConfigs), - TCP: p.loadIngressRouteTCPConfiguration(ctx, client, tlsConfigs), - TLSOptions: buildTLSOptions(ctx, client), - TLS: getTLSConfig(tlsConfigs), + HTTP: p.loadIngressRouteConfiguration(ctx, client, tlsConfigs), + TCP: p.loadIngressRouteTCPConfiguration(ctx, client, tlsConfigs), + TLS: &config.TLSConfiguration{ + Certificates: getTLSConfig(tlsConfigs), + Options: buildTLSOptions(ctx, client), + }, } for _, middleware := range client.GetMiddlewares() { @@ -604,7 +606,7 @@ func shouldProcessIngress(ingressClass string, ingressClassAnnotation string) bo (len(ingressClass) == 0 && ingressClassAnnotation == traefikDefaultIngressClass) } -func getTLSHTTP(ctx context.Context, ingressRoute *v1alpha1.IngressRoute, k8sClient Client, tlsConfigs map[string]*tls.Configuration) error { +func getTLSHTTP(ctx context.Context, ingressRoute *v1alpha1.IngressRoute, k8sClient Client, tlsConfigs map[string]*tls.CertAndStores) error { if ingressRoute.Spec.TLS == nil { return nil } @@ -626,7 +628,7 @@ func getTLSHTTP(ctx context.Context, ingressRoute *v1alpha1.IngressRoute, k8sCli return nil } -func getTLSTCP(ctx context.Context, ingressRoute *v1alpha1.IngressRouteTCP, k8sClient Client, tlsConfigs map[string]*tls.Configuration) error { +func getTLSTCP(ctx context.Context, ingressRoute *v1alpha1.IngressRouteTCP, k8sClient Client, tlsConfigs map[string]*tls.CertAndStores) error { if ingressRoute.Spec.TLS == nil { return nil } @@ -648,7 +650,7 @@ func getTLSTCP(ctx context.Context, ingressRoute *v1alpha1.IngressRouteTCP, k8sC return nil } -func getTLS(k8sClient Client, secretName, namespace string) (*tls.Configuration, error) { +func getTLS(k8sClient Client, secretName, namespace string) (*tls.CertAndStores, error) { secret, exists, err := k8sClient.GetSecret(namespace, secretName) if err != nil { return nil, fmt.Errorf("failed to fetch secret %s/%s: %v", namespace, secretName, err) @@ -662,22 +664,22 @@ func getTLS(k8sClient Client, secretName, namespace string) (*tls.Configuration, return nil, err } - return &tls.Configuration{ - Certificate: &tls.Certificate{ + return &tls.CertAndStores{ + Certificate: tls.Certificate{ CertFile: tls.FileOrContent(cert), KeyFile: tls.FileOrContent(key), }, }, nil } -func getTLSConfig(tlsConfigs map[string]*tls.Configuration) []*tls.Configuration { +func getTLSConfig(tlsConfigs map[string]*tls.CertAndStores) []*tls.CertAndStores { var secretNames []string for secretName := range tlsConfigs { secretNames = append(secretNames, secretName) } sort.Strings(secretNames) - var configs []*tls.Configuration + var configs []*tls.CertAndStores for _, secretName := range secretNames { configs = append(configs, tlsConfigs[secretName]) } diff --git a/pkg/provider/kubernetes/crd/kubernetes_test.go b/pkg/provider/kubernetes/crd/kubernetes_test.go index c8df41c86..8e48e71d3 100644 --- a/pkg/provider/kubernetes/crd/kubernetes_test.go +++ b/pkg/provider/kubernetes/crd/kubernetes_test.go @@ -31,6 +31,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { Middlewares: map[string]*config.Middleware{}, Services: map[string]*config.Service{}, }, + TLS: &config.TLSConfiguration{}, }, }, { @@ -67,6 +68,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { }, }, }, + TLS: &config.TLSConfiguration{}, }, }, { @@ -122,6 +124,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { Middlewares: map[string]*config.Middleware{}, Services: map[string]*config.Service{}, }, + TLS: &config.TLSConfiguration{}, }, }, { @@ -165,6 +168,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { Middlewares: map[string]*config.Middleware{}, Services: map[string]*config.Service{}, }, + TLS: &config.TLSConfiguration{}, }, }, { @@ -181,6 +185,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { Middlewares: map[string]*config.Middleware{}, Services: map[string]*config.Service{}, }, + TLS: &config.TLSConfiguration{}, }, }, { @@ -196,6 +201,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { Middlewares: map[string]*config.Middleware{}, Services: map[string]*config.Service{}, }, + TLS: &config.TLSConfiguration{}, }, }, { @@ -211,17 +217,20 @@ func TestLoadIngressRouteTCPs(t *testing.T) { Middlewares: map[string]*config.Middleware{}, Services: map[string]*config.Service{}, }, + TLS: &config.TLSConfiguration{}, }, }, { desc: "TLS", paths: []string{"tcp/services.yml", "tcp/with_tls.yml"}, expected: &config.Configuration{ - TLS: []*tls.Configuration{ - { - Certificate: &tls.Certificate{ - CertFile: tls.FileOrContent("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----"), - KeyFile: tls.FileOrContent("-----BEGIN PRIVATE KEY-----\n-----END PRIVATE KEY-----"), + TLS: &config.TLSConfiguration{ + Certificates: []*tls.CertAndStores{ + { + Certificate: tls.Certificate{ + CertFile: tls.FileOrContent("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----"), + KeyFile: tls.FileOrContent("-----BEGIN PRIVATE KEY-----\n-----END PRIVATE KEY-----"), + }, }, }, }, @@ -295,27 +304,30 @@ func TestLoadIngressRouteTCPs(t *testing.T) { Middlewares: map[string]*config.Middleware{}, Services: map[string]*config.Service{}, }, + TLS: &config.TLSConfiguration{}, }, }, { desc: "TLS with tls options", paths: []string{"tcp/services.yml", "tcp/with_tls_options.yml"}, expected: &config.Configuration{ - TLSOptions: map[string]tls.TLS{ - "default/foo": { - MinVersion: "VersionTLS12", - CipherSuites: []string{ - "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", - "TLS_RSA_WITH_AES_256_GCM_SHA384", - }, - ClientCA: tls.ClientCA{ - Files: []tls.FileOrContent{ - tls.FileOrContent("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----"), - tls.FileOrContent("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----"), + TLS: &config.TLSConfiguration{ + Options: map[string]tls.Options{ + "default/foo": { + MinVersion: "VersionTLS12", + CipherSuites: []string{ + "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", + "TLS_RSA_WITH_AES_256_GCM_SHA384", }, - Optional: true, + ClientCA: tls.ClientCA{ + Files: []tls.FileOrContent{ + tls.FileOrContent("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----"), + tls.FileOrContent("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----"), + }, + Optional: true, + }, + SniStrict: true, }, - SniStrict: true, }, }, TCP: &config.TCPConfiguration{ @@ -357,21 +369,23 @@ func TestLoadIngressRouteTCPs(t *testing.T) { desc: "TLS with tls options and specific namespace", paths: []string{"tcp/services.yml", "tcp/with_tls_options_and_specific_namespace.yml"}, expected: &config.Configuration{ - TLSOptions: map[string]tls.TLS{ - "myns/foo": { - MinVersion: "VersionTLS12", - CipherSuites: []string{ - "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", - "TLS_RSA_WITH_AES_256_GCM_SHA384", - }, - ClientCA: tls.ClientCA{ - Files: []tls.FileOrContent{ - tls.FileOrContent("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----"), - tls.FileOrContent("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----"), + TLS: &config.TLSConfiguration{ + Options: map[string]tls.Options{ + "myns/foo": { + MinVersion: "VersionTLS12", + CipherSuites: []string{ + "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", + "TLS_RSA_WITH_AES_256_GCM_SHA384", }, - Optional: true, + ClientCA: tls.ClientCA{ + Files: []tls.FileOrContent{ + tls.FileOrContent("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----"), + tls.FileOrContent("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----"), + }, + Optional: true, + }, + SniStrict: true, }, - SniStrict: true, }, }, TCP: &config.TCPConfiguration{ @@ -413,20 +427,22 @@ func TestLoadIngressRouteTCPs(t *testing.T) { desc: "TLS with bad tls options", paths: []string{"tcp/services.yml", "tcp/with_bad_tls_options.yml"}, expected: &config.Configuration{ - TLSOptions: map[string]tls.TLS{ - "default/foo": { - MinVersion: "VersionTLS12", - CipherSuites: []string{ - "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", - "TLS_RSA_WITH_AES_256_GCM_SHA384", - }, - ClientCA: tls.ClientCA{ - Files: []tls.FileOrContent{ - tls.FileOrContent("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----"), + TLS: &config.TLSConfiguration{ + Options: map[string]tls.Options{ + "default/foo": { + MinVersion: "VersionTLS12", + CipherSuites: []string{ + "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", + "TLS_RSA_WITH_AES_256_GCM_SHA384", }, - Optional: true, + ClientCA: tls.ClientCA{ + Files: []tls.FileOrContent{ + tls.FileOrContent("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----"), + }, + Optional: true, + }, + SniStrict: true, }, - SniStrict: true, }, }, TCP: &config.TCPConfiguration{ @@ -468,9 +484,11 @@ func TestLoadIngressRouteTCPs(t *testing.T) { desc: "TLS with unknown tls options", paths: []string{"tcp/services.yml", "tcp/with_unknown_tls_options.yml"}, expected: &config.Configuration{ - TLSOptions: map[string]tls.TLS{ - "default/foo": { - MinVersion: "VersionTLS12", + TLS: &config.TLSConfiguration{ + Options: map[string]tls.Options{ + "default/foo": { + MinVersion: "VersionTLS12", + }, }, }, TCP: &config.TCPConfiguration{ @@ -512,9 +530,11 @@ func TestLoadIngressRouteTCPs(t *testing.T) { desc: "TLS with unknown tls options namespace", paths: []string{"tcp/services.yml", "tcp/with_unknown_tls_options_namespace.yml"}, expected: &config.Configuration{ - TLSOptions: map[string]tls.TLS{ - "default/foo": { - MinVersion: "VersionTLS12", + TLS: &config.TLSConfiguration{ + Options: map[string]tls.Options{ + "default/foo": { + MinVersion: "VersionTLS12", + }, }, }, TCP: &config.TCPConfiguration{ @@ -587,6 +607,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) { Middlewares: map[string]*config.Middleware{}, Services: map[string]*config.Service{}, }, + TLS: &config.TLSConfiguration{}, }, }, } @@ -627,6 +648,7 @@ func TestLoadIngressRoutes(t *testing.T) { Middlewares: map[string]*config.Middleware{}, Services: map[string]*config.Service{}, }, + TLS: &config.TLSConfiguration{}, }, }, { @@ -663,6 +685,7 @@ func TestLoadIngressRoutes(t *testing.T) { }, }, }, + TLS: &config.TLSConfiguration{}, }, }, { @@ -711,12 +734,14 @@ func TestLoadIngressRoutes(t *testing.T) { }, }, }, + TLS: &config.TLSConfiguration{}, }, }, { desc: "Simple Ingress Route with middleware crossprovider", paths: []string{"services.yml", "with_middleware_crossprovider.yml"}, expected: &config.Configuration{ + TLS: &config.TLSConfiguration{}, TCP: &config.TCPConfiguration{ Routers: map[string]*config.TCPRouter{}, Services: map[string]*config.TCPService{}, @@ -814,12 +839,14 @@ func TestLoadIngressRoutes(t *testing.T) { }, }, }, + TLS: &config.TLSConfiguration{}, }, }, { desc: "One ingress Route with two different services, their servers will merge", paths: []string{"services.yml", "with_two_services.yml"}, expected: &config.Configuration{ + TLS: &config.TLSConfiguration{}, TCP: &config.TCPConfiguration{ Routers: map[string]*config.TCPRouter{}, Services: map[string]*config.TCPService{}, @@ -863,6 +890,7 @@ func TestLoadIngressRoutes(t *testing.T) { paths: []string{"services.yml", "simple.yml"}, ingressClass: "tchouk", expected: &config.Configuration{ + TLS: &config.TLSConfiguration{}, TCP: &config.TCPConfiguration{ Routers: map[string]*config.TCPRouter{}, Services: map[string]*config.TCPService{}, @@ -878,6 +906,7 @@ func TestLoadIngressRoutes(t *testing.T) { desc: "Route with empty rule value is ignored", paths: []string{"services.yml", "with_no_rule_value.yml"}, expected: &config.Configuration{ + TLS: &config.TLSConfiguration{}, TCP: &config.TCPConfiguration{ Routers: map[string]*config.TCPRouter{}, Services: map[string]*config.TCPService{}, @@ -893,6 +922,7 @@ func TestLoadIngressRoutes(t *testing.T) { desc: "Route with kind not of a rule type (empty kind) is ignored", paths: []string{"services.yml", "with_wrong_rule_kind.yml"}, expected: &config.Configuration{ + TLS: &config.TLSConfiguration{}, TCP: &config.TCPConfiguration{ Routers: map[string]*config.TCPRouter{}, Services: map[string]*config.TCPService{}, @@ -908,6 +938,7 @@ func TestLoadIngressRoutes(t *testing.T) { desc: "check rule quoting validity", paths: []string{"services.yml", "with_bad_host_rule.yml"}, expected: &config.Configuration{ + TLS: &config.TLSConfiguration{}, TCP: &config.TCPConfiguration{ Routers: map[string]*config.TCPRouter{}, Services: map[string]*config.TCPService{}, @@ -923,11 +954,13 @@ func TestLoadIngressRoutes(t *testing.T) { desc: "TLS", paths: []string{"services.yml", "with_tls.yml"}, expected: &config.Configuration{ - TLS: []*tls.Configuration{ - { - Certificate: &tls.Certificate{ - CertFile: tls.FileOrContent("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----"), - KeyFile: tls.FileOrContent("-----BEGIN PRIVATE KEY-----\n-----END PRIVATE KEY-----"), + TLS: &config.TLSConfiguration{ + Certificates: []*tls.CertAndStores{ + { + Certificate: tls.Certificate{ + CertFile: tls.FileOrContent("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----"), + KeyFile: tls.FileOrContent("-----BEGIN PRIVATE KEY-----\n-----END PRIVATE KEY-----"), + }, }, }, }, @@ -968,21 +1001,23 @@ func TestLoadIngressRoutes(t *testing.T) { desc: "TLS with tls options", paths: []string{"services.yml", "with_tls_options.yml"}, expected: &config.Configuration{ - TLSOptions: map[string]tls.TLS{ - "default/foo": { - MinVersion: "VersionTLS12", - CipherSuites: []string{ - "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", - "TLS_RSA_WITH_AES_256_GCM_SHA384", - }, - ClientCA: tls.ClientCA{ - Files: []tls.FileOrContent{ - tls.FileOrContent("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----"), - tls.FileOrContent("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----"), + TLS: &config.TLSConfiguration{ + Options: map[string]tls.Options{ + "default/foo": { + MinVersion: "VersionTLS12", + CipherSuites: []string{ + "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", + "TLS_RSA_WITH_AES_256_GCM_SHA384", }, - Optional: true, + ClientCA: tls.ClientCA{ + Files: []tls.FileOrContent{ + tls.FileOrContent("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----"), + tls.FileOrContent("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----"), + }, + Optional: true, + }, + SniStrict: true, }, - SniStrict: true, }, }, TCP: &config.TCPConfiguration{ @@ -1024,21 +1059,23 @@ func TestLoadIngressRoutes(t *testing.T) { desc: "TLS with tls options and specific namespace", paths: []string{"services.yml", "with_tls_options_and_specific_namespace.yml"}, expected: &config.Configuration{ - TLSOptions: map[string]tls.TLS{ - "myns/foo": { - MinVersion: "VersionTLS12", - CipherSuites: []string{ - "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", - "TLS_RSA_WITH_AES_256_GCM_SHA384", - }, - ClientCA: tls.ClientCA{ - Files: []tls.FileOrContent{ - tls.FileOrContent("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----"), - tls.FileOrContent("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----"), + TLS: &config.TLSConfiguration{ + Options: map[string]tls.Options{ + "myns/foo": { + MinVersion: "VersionTLS12", + CipherSuites: []string{ + "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", + "TLS_RSA_WITH_AES_256_GCM_SHA384", }, - Optional: true, + ClientCA: tls.ClientCA{ + Files: []tls.FileOrContent{ + tls.FileOrContent("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----"), + tls.FileOrContent("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----"), + }, + Optional: true, + }, + SniStrict: true, }, - SniStrict: true, }, }, TCP: &config.TCPConfiguration{ @@ -1080,20 +1117,22 @@ func TestLoadIngressRoutes(t *testing.T) { desc: "TLS with bad tls options", paths: []string{"services.yml", "with_bad_tls_options.yml"}, expected: &config.Configuration{ - TLSOptions: map[string]tls.TLS{ - "default/foo": { - MinVersion: "VersionTLS12", - CipherSuites: []string{ - "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", - "TLS_RSA_WITH_AES_256_GCM_SHA384", - }, - ClientCA: tls.ClientCA{ - Files: []tls.FileOrContent{ - tls.FileOrContent("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----"), + TLS: &config.TLSConfiguration{ + Options: map[string]tls.Options{ + "default/foo": { + MinVersion: "VersionTLS12", + CipherSuites: []string{ + "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", + "TLS_RSA_WITH_AES_256_GCM_SHA384", }, - Optional: true, + ClientCA: tls.ClientCA{ + Files: []tls.FileOrContent{ + tls.FileOrContent("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----"), + }, + Optional: true, + }, + SniStrict: true, }, - SniStrict: true, }, }, TCP: &config.TCPConfiguration{ @@ -1135,9 +1174,11 @@ func TestLoadIngressRoutes(t *testing.T) { desc: "TLS with unknown tls options", paths: []string{"services.yml", "with_unknown_tls_options.yml"}, expected: &config.Configuration{ - TLSOptions: map[string]tls.TLS{ - "default/foo": { - MinVersion: "VersionTLS12", + TLS: &config.TLSConfiguration{ + Options: map[string]tls.Options{ + "default/foo": { + MinVersion: "VersionTLS12", + }, }, }, TCP: &config.TCPConfiguration{ @@ -1179,9 +1220,11 @@ func TestLoadIngressRoutes(t *testing.T) { desc: "TLS with unknown tls options namespace", paths: []string{"services.yml", "with_unknown_tls_options_namespace.yml"}, expected: &config.Configuration{ - TLSOptions: map[string]tls.TLS{ - "default/foo": { - MinVersion: "VersionTLS12", + TLS: &config.TLSConfiguration{ + Options: map[string]tls.Options{ + "default/foo": { + MinVersion: "VersionTLS12", + }, }, }, TCP: &config.TCPConfiguration{ @@ -1223,6 +1266,7 @@ func TestLoadIngressRoutes(t *testing.T) { desc: "TLS with ACME", paths: []string{"services.yml", "with_tls_acme.yml"}, expected: &config.Configuration{ + TLS: &config.TLSConfiguration{}, TCP: &config.TCPConfiguration{ Routers: map[string]*config.TCPRouter{}, Services: map[string]*config.TCPService{}, @@ -1260,6 +1304,7 @@ func TestLoadIngressRoutes(t *testing.T) { desc: "Simple Ingress Route, defaulting to https for servers", paths: []string{"services.yml", "with_https_default.yml"}, expected: &config.Configuration{ + TLS: &config.TLSConfiguration{}, TCP: &config.TCPConfiguration{ Routers: map[string]*config.TCPRouter{}, Services: map[string]*config.TCPService{}, diff --git a/pkg/provider/kubernetes/ingress/kubernetes.go b/pkg/provider/kubernetes/ingress/kubernetes.go index b2a0095ba..7f4b24c08 100644 --- a/pkg/provider/kubernetes/ingress/kubernetes.go +++ b/pkg/provider/kubernetes/ingress/kubernetes.go @@ -257,7 +257,7 @@ func (p *Provider) loadConfigurationFromIngresses(ctx context.Context, client Cl ingresses := client.GetIngresses() - tlsConfigs := make(map[string]*tls.Configuration) + tlsConfigs := make(map[string]*tls.CertAndStores) for _, ingress := range ingresses { ctx = log.With(ctx, log.Str("ingress", ingress.Name), log.Str("namespace", ingress.Namespace)) @@ -341,7 +341,13 @@ func (p *Provider) loadConfigurationFromIngresses(ctx context.Context, client Cl } } - conf.TLS = getTLSConfig(tlsConfigs) + certs := getTLSConfig(tlsConfigs) + if len(certs) > 0 { + conf.TLS = &config.TLSConfiguration{ + Certificates: certs, + } + } + return conf } @@ -350,7 +356,7 @@ func shouldProcessIngress(ingressClass string, ingressClassAnnotation string) bo (len(ingressClass) == 0 && ingressClassAnnotation == traefikDefaultIngressClass) } -func getTLS(ctx context.Context, ingress *v1beta1.Ingress, k8sClient Client, tlsConfigs map[string]*tls.Configuration) error { +func getTLS(ctx context.Context, ingress *v1beta1.Ingress, k8sClient Client, tlsConfigs map[string]*tls.CertAndStores) error { for _, t := range ingress.Spec.TLS { if t.SecretName == "" { log.FromContext(ctx).Debugf("Skipping TLS sub-section: No secret name provided") @@ -372,8 +378,8 @@ func getTLS(ctx context.Context, ingress *v1beta1.Ingress, k8sClient Client, tls return err } - tlsConfigs[configKey] = &tls.Configuration{ - Certificate: &tls.Certificate{ + tlsConfigs[configKey] = &tls.CertAndStores{ + Certificate: tls.Certificate{ CertFile: tls.FileOrContent(cert), KeyFile: tls.FileOrContent(key), }, @@ -384,14 +390,14 @@ func getTLS(ctx context.Context, ingress *v1beta1.Ingress, k8sClient Client, tls return nil } -func getTLSConfig(tlsConfigs map[string]*tls.Configuration) []*tls.Configuration { +func getTLSConfig(tlsConfigs map[string]*tls.CertAndStores) []*tls.CertAndStores { var secretNames []string for secretName := range tlsConfigs { secretNames = append(secretNames, secretName) } sort.Strings(secretNames) - var configs []*tls.Configuration + var configs []*tls.CertAndStores for _, secretName := range secretNames { configs = append(configs, tlsConfigs[secretName]) } diff --git a/pkg/provider/kubernetes/ingress/kubernetes_test.go b/pkg/provider/kubernetes/ingress/kubernetes_test.go index 388ed7ce7..ffb0e273f 100644 --- a/pkg/provider/kubernetes/ingress/kubernetes_test.go +++ b/pkg/provider/kubernetes/ingress/kubernetes_test.go @@ -702,11 +702,13 @@ func TestLoadConfigurationFromIngresses(t *testing.T) { }, }, }, - TLS: []*tls.Configuration{ - { - Certificate: &tls.Certificate{ - CertFile: tls.FileOrContent("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----"), - KeyFile: tls.FileOrContent("-----BEGIN PRIVATE KEY-----\n-----END PRIVATE KEY-----"), + TLS: &config.TLSConfiguration{ + Certificates: []*tls.CertAndStores{ + { + Certificate: tls.Certificate{ + CertFile: tls.FileOrContent("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----"), + KeyFile: tls.FileOrContent("-----BEGIN PRIVATE KEY-----\n-----END PRIVATE KEY-----"), + }, }, }, }, @@ -973,7 +975,7 @@ func TestGetTLS(t *testing.T) { desc string ingress *v1beta1.Ingress client Client - result map[string]*tls.Configuration + result map[string]*tls.CertAndStores errResult string }{ { @@ -1080,15 +1082,15 @@ func TestGetTLS(t *testing.T) { }, }, }, - result: map[string]*tls.Configuration{ + result: map[string]*tls.CertAndStores{ "testing/test-secret": { - Certificate: &tls.Certificate{ + Certificate: tls.Certificate{ CertFile: tls.FileOrContent("tls-crt"), KeyFile: tls.FileOrContent("tls-key"), }, }, "testing/test-secret2": { - Certificate: &tls.Certificate{ + Certificate: tls.Certificate{ CertFile: tls.FileOrContent("tls-crt"), KeyFile: tls.FileOrContent("tls-key"), }, @@ -1099,7 +1101,7 @@ func TestGetTLS(t *testing.T) { desc: "return nil when no secret is defined", ingress: testIngressWithoutSecret, client: clientMock{}, - result: map[string]*tls.Configuration{}, + result: map[string]*tls.CertAndStores{}, }, } @@ -1108,7 +1110,7 @@ func TestGetTLS(t *testing.T) { t.Run(test.desc, func(t *testing.T) { t.Parallel() - tlsConfigs := map[string]*tls.Configuration{} + tlsConfigs := map[string]*tls.CertAndStores{} err := getTLS(context.Background(), test.ingress, test.client, tlsConfigs) if test.errResult != "" { diff --git a/pkg/server/aggregator.go b/pkg/server/aggregator.go index 60db24001..5d2c25cc9 100644 --- a/pkg/server/aggregator.go +++ b/pkg/server/aggregator.go @@ -18,8 +18,10 @@ func mergeConfiguration(configurations config.Configurations) config.Configurati Routers: make(map[string]*config.TCPRouter), Services: make(map[string]*config.TCPService), }, - TLSOptions: make(map[string]tls.TLS), - TLSStores: make(map[string]tls.Store), + TLS: &config.TLSConfiguration{ + Stores: make(map[string]tls.Store), + Options: make(map[string]tls.Options), + }, } var defaultTLSOptionProviders []string @@ -44,30 +46,33 @@ func mergeConfiguration(configurations config.Configurations) config.Configurati conf.TCP.Services[internal.MakeQualifiedName(provider, serviceName)] = service } } - conf.TLS = append(conf.TLS, configuration.TLS...) - for key, store := range configuration.TLSStores { - conf.TLSStores[key] = store - } + if configuration.TLS != nil { + conf.TLS.Certificates = append(conf.TLS.Certificates, configuration.TLS.Certificates...) - for tlsOptionsName, config := range configuration.TLSOptions { - if tlsOptionsName != "default" { - tlsOptionsName = internal.MakeQualifiedName(provider, tlsOptionsName) - } else { - defaultTLSOptionProviders = append(defaultTLSOptionProviders, provider) + for key, store := range configuration.TLS.Stores { + conf.TLS.Stores[key] = store } - conf.TLSOptions[tlsOptionsName] = config + for tlsOptionsName, options := range configuration.TLS.Options { + if tlsOptionsName != "default" { + tlsOptionsName = internal.MakeQualifiedName(provider, tlsOptionsName) + } else { + defaultTLSOptionProviders = append(defaultTLSOptionProviders, provider) + } + + conf.TLS.Options[tlsOptionsName] = options + } } } if len(defaultTLSOptionProviders) == 0 { - conf.TLSOptions["default"] = tls.TLS{} + conf.TLS.Options["default"] = tls.Options{} } else if len(defaultTLSOptionProviders) > 1 { log.WithoutContext().Errorf("Default TLS Options defined multiple times in %v", defaultTLSOptionProviders) // We do not set an empty tls.TLS{} as above so that we actually get a "cascading failure" later on, // i.e. routers depending on this missing TLS option will fail to initialize as well. - delete(conf.TLSOptions, "default") + delete(conf.TLS.Options, "default") } return conf diff --git a/pkg/server/aggregator_test.go b/pkg/server/aggregator_test.go index 6267b819a..92733f3e0 100644 --- a/pkg/server/aggregator_test.go +++ b/pkg/server/aggregator_test.go @@ -114,12 +114,12 @@ func TestAggregator_tlsoptions(t *testing.T) { testCases := []struct { desc string given config.Configurations - expected map[string]tls.TLS + expected map[string]tls.Options }{ { desc: "Nil returns an empty configuration", given: nil, - expected: map[string]tls.TLS{ + expected: map[string]tls.Options{ "default": {}, }, }, @@ -127,14 +127,16 @@ func TestAggregator_tlsoptions(t *testing.T) { desc: "Returns fully qualified elements from a mono-provider configuration map", given: config.Configurations{ "provider-1": &config.Configuration{ - TLSOptions: map[string]tls.TLS{ - "foo": { - MinVersion: "VersionTLS12", + TLS: &config.TLSConfiguration{ + Options: map[string]tls.Options{ + "foo": { + MinVersion: "VersionTLS12", + }, }, }, }, }, - expected: map[string]tls.TLS{ + expected: map[string]tls.Options{ "default": {}, "foo@provider-1": { MinVersion: "VersionTLS12", @@ -145,21 +147,25 @@ func TestAggregator_tlsoptions(t *testing.T) { desc: "Returns fully qualified elements from a multi-provider configuration map", given: config.Configurations{ "provider-1": &config.Configuration{ - TLSOptions: map[string]tls.TLS{ - "foo": { - MinVersion: "VersionTLS13", + TLS: &config.TLSConfiguration{ + Options: map[string]tls.Options{ + "foo": { + MinVersion: "VersionTLS13", + }, }, }, }, "provider-2": &config.Configuration{ - TLSOptions: map[string]tls.TLS{ - "foo": { - MinVersion: "VersionTLS12", + TLS: &config.TLSConfiguration{ + Options: map[string]tls.Options{ + "foo": { + MinVersion: "VersionTLS12", + }, }, }, }, }, - expected: map[string]tls.TLS{ + expected: map[string]tls.Options{ "default": {}, "foo@provider-1": { MinVersion: "VersionTLS13", @@ -173,24 +179,28 @@ func TestAggregator_tlsoptions(t *testing.T) { desc: "Create a valid default tls option when appears only in one provider", given: config.Configurations{ "provider-1": &config.Configuration{ - TLSOptions: map[string]tls.TLS{ - "foo": { - MinVersion: "VersionTLS13", - }, - "default": { - MinVersion: "VersionTLS11", + TLS: &config.TLSConfiguration{ + Options: map[string]tls.Options{ + "foo": { + MinVersion: "VersionTLS13", + }, + "default": { + MinVersion: "VersionTLS11", + }, }, }, }, "provider-2": &config.Configuration{ - TLSOptions: map[string]tls.TLS{ - "foo": { - MinVersion: "VersionTLS12", + TLS: &config.TLSConfiguration{ + Options: map[string]tls.Options{ + "foo": { + MinVersion: "VersionTLS12", + }, }, }, }, }, - expected: map[string]tls.TLS{ + expected: map[string]tls.Options{ "default": { MinVersion: "VersionTLS11", }, @@ -206,27 +216,31 @@ func TestAggregator_tlsoptions(t *testing.T) { desc: "No default tls option if it is defined in multiple providers", given: config.Configurations{ "provider-1": &config.Configuration{ - TLSOptions: map[string]tls.TLS{ - "foo": { - MinVersion: "VersionTLS12", - }, - "default": { - MinVersion: "VersionTLS11", + TLS: &config.TLSConfiguration{ + Options: map[string]tls.Options{ + "foo": { + MinVersion: "VersionTLS12", + }, + "default": { + MinVersion: "VersionTLS11", + }, }, }, }, "provider-2": &config.Configuration{ - TLSOptions: map[string]tls.TLS{ - "foo": { - MinVersion: "VersionTLS13", - }, - "default": { - MinVersion: "VersionTLS12", + TLS: &config.TLSConfiguration{ + Options: map[string]tls.Options{ + "foo": { + MinVersion: "VersionTLS13", + }, + "default": { + MinVersion: "VersionTLS12", + }, }, }, }, }, - expected: map[string]tls.TLS{ + expected: map[string]tls.Options{ "foo@provider-1": { MinVersion: "VersionTLS12", }, @@ -239,21 +253,25 @@ func TestAggregator_tlsoptions(t *testing.T) { desc: "Create a default TLS Options configuration if none was provided", given: config.Configurations{ "provider-1": &config.Configuration{ - TLSOptions: map[string]tls.TLS{ - "foo": { - MinVersion: "VersionTLS12", + TLS: &config.TLSConfiguration{ + Options: map[string]tls.Options{ + "foo": { + MinVersion: "VersionTLS12", + }, }, }, }, "provider-2": &config.Configuration{ - TLSOptions: map[string]tls.TLS{ - "foo": { - MinVersion: "VersionTLS13", + TLS: &config.TLSConfiguration{ + Options: map[string]tls.Options{ + "foo": { + MinVersion: "VersionTLS13", + }, }, }, }, }, - expected: map[string]tls.TLS{ + expected: map[string]tls.Options{ "default": {}, "foo@provider-1": { MinVersion: "VersionTLS12", @@ -272,7 +290,7 @@ func TestAggregator_tlsoptions(t *testing.T) { t.Parallel() actual := mergeConfiguration(test.given) - assert.Equal(t, test.expected, actual.TLSOptions) + assert.Equal(t, test.expected, actual.TLS.Options) }) } } diff --git a/pkg/server/router/tcp/router_test.go b/pkg/server/router/tcp/router_test.go index 1050e7938..e65e549e2 100644 --- a/pkg/server/router/tcp/router_test.go +++ b/pkg/server/router/tcp/router_test.go @@ -203,7 +203,7 @@ func TestRuntimeConfiguration(t *testing.T) { tlsManager := tls.NewManager() tlsManager.UpdateConfigs( map[string]tls.Store{}, - map[string]tls.TLS{ + map[string]tls.Options{ "default": { MinVersion: "VersionTLS10", }, @@ -214,7 +214,7 @@ func TestRuntimeConfiguration(t *testing.T) { MinVersion: "VersionTLS11", }, }, - []*tls.Configuration{}) + []*tls.CertAndStores{}) routerManager := NewManager(conf, serviceManager, nil, nil, tlsManager) diff --git a/pkg/server/server_configuration.go b/pkg/server/server_configuration.go index de9f2bb4c..dd397f82b 100644 --- a/pkg/server/server_configuration.go +++ b/pkg/server/server_configuration.go @@ -66,7 +66,7 @@ func (s *Server) loadConfigurationTCP(configurations config.Configurations) map[ conf := mergeConfiguration(configurations) - s.tlsManager.UpdateConfigs(conf.TLSStores, conf.TLSOptions, conf.TLS) + s.tlsManager.UpdateConfigs(conf.TLS.Stores, conf.TLS.Options, conf.TLS.Certificates) rtConf := config.NewRuntimeConfig(conf) handlersNonTLS, handlersTLS := s.createHTTPHandlers(ctx, rtConf, entryPoints) @@ -167,7 +167,7 @@ func isEmptyConfiguration(conf *config.Configuration) bool { return conf.HTTP.Routers == nil && conf.HTTP.Services == nil && conf.HTTP.Middlewares == nil && - conf.TLS == nil && + (conf.TLS == nil || conf.TLS.Certificates == nil && conf.TLS.Stores == nil && conf.TLS.Options == nil) && conf.TCP.Routers == nil && conf.TCP.Services == nil } diff --git a/pkg/tls/tls.go b/pkg/tls/tls.go index c2d09a5bb..e509e4b10 100644 --- a/pkg/tls/tls.go +++ b/pkg/tls/tls.go @@ -9,8 +9,8 @@ type ClientCA struct { Optional bool } -// TLS configures TLS for an entry point -type TLS struct { +// Options configures TLS for an entry point +type Options struct { MinVersion string `export:"true"` CipherSuites []string ClientCA ClientCA @@ -22,8 +22,8 @@ type Store struct { DefaultCertificate *Certificate } -// Configuration allows mapping a TLS certificate to a list of entry points. -type Configuration struct { +// CertAndStores allows mapping a TLS certificate to a list of entry points. +type CertAndStores struct { + Certificate `yaml:",inline"` Stores []string - Certificate *Certificate } diff --git a/pkg/tls/tlsmanager.go b/pkg/tls/tlsmanager.go index 60791ace0..c1599b7d8 100644 --- a/pkg/tls/tlsmanager.go +++ b/pkg/tls/tlsmanager.go @@ -17,8 +17,8 @@ import ( type Manager struct { storesConfig map[string]Store stores map[string]*CertificateStore - configs map[string]TLS - certs []*Configuration + configs map[string]Options + certs []*CertAndStores TLSAlpnGetter func(string) (*tls.Certificate, error) lock sync.RWMutex } @@ -29,7 +29,7 @@ func NewManager() *Manager { } // UpdateConfigs updates the TLS* configuration options -func (m *Manager) UpdateConfigs(stores map[string]Store, configs map[string]TLS, certs []*Configuration) { +func (m *Manager) UpdateConfigs(stores map[string]Store, configs map[string]Options, certs []*CertAndStores) { m.lock.Lock() defer m.lock.Unlock() @@ -153,7 +153,7 @@ func buildCertificateStore(tlsStore Store) (*CertificateStore, error) { } // creates a TLS config that allows terminating HTTPS for multiple domains using SNI -func buildTLSConfig(tlsOption TLS) (*tls.Config, error) { +func buildTLSConfig(tlsOption Options) (*tls.Config, error) { conf := &tls.Config{} // ensure http2 enabled diff --git a/pkg/tls/tlsmanager_test.go b/pkg/tls/tlsmanager_test.go index 848d55389..963f548ee 100644 --- a/pkg/tls/tlsmanager_test.go +++ b/pkg/tls/tlsmanager_test.go @@ -46,15 +46,12 @@ f9Oeos0UUothgiDktdQHxdNEwLjQf7lJJBzV+5OtwswCWA== ) func TestTLSInStore(t *testing.T) { - dynamicConfigs := - []*Configuration{ - { - Certificate: &Certificate{ - CertFile: localhostCert, - KeyFile: localhostKey, - }, - }, - } + dynamicConfigs := []*CertAndStores{{ + Certificate: Certificate{ + CertFile: localhostCert, + KeyFile: localhostKey, + }, + }} tlsManager := NewManager() tlsManager.UpdateConfigs(nil, nil, dynamicConfigs) @@ -66,15 +63,12 @@ func TestTLSInStore(t *testing.T) { } func TestTLSInvalidStore(t *testing.T) { - dynamicConfigs := - []*Configuration{ - { - Certificate: &Certificate{ - CertFile: localhostCert, - KeyFile: localhostKey, - }, - }, - } + dynamicConfigs := []*CertAndStores{{ + Certificate: Certificate{ + CertFile: localhostCert, + KeyFile: localhostKey, + }, + }} tlsManager := NewManager() tlsManager.UpdateConfigs(map[string]Store{ @@ -93,16 +87,14 @@ func TestTLSInvalidStore(t *testing.T) { } func TestManager_Get(t *testing.T) { - dynamicConfigs := - []*Configuration{ - { - Certificate: &Certificate{ - CertFile: localhostCert, - KeyFile: localhostKey, - }, - }, - } - tlsConfigs := map[string]TLS{ + dynamicConfigs := []*CertAndStores{{ + Certificate: Certificate{ + CertFile: localhostCert, + KeyFile: localhostKey, + }, + }} + + tlsConfigs := map[string]Options{ "foo": {MinVersion: "VersionTLS12"}, "bar": {MinVersion: "VersionTLS11"}, } @@ -153,5 +145,4 @@ func TestManager_Get(t *testing.T) { assert.Equal(t, config.MinVersion, test.expectedMinVersion) }) } - }