Define a TLS section to group TLS, TLSOptions, and TLSStores.

Co-authored-by: Jean-Baptiste Doumenjou <jb.doumenjou@gmail.com>
This commit is contained in:
Ludovic Fernandez 2019-06-27 23:58:03 +02:00 committed by Traefiker Bot
parent c9b2a07bc7
commit 4245096be4
52 changed files with 717 additions and 628 deletions

View file

@ -11,18 +11,16 @@ See the [Let's Encrypt](./acme.md) page.
### User defined ### 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 ```toml
[[tls]] [[tls.certificates]]
[tls.certificate] certFile = "/path/to/domain.cert"
certFile = "/path/to/domain.cert" keyFile = "/path/to/domain.key"
keyFile = "/path/to/domain.key"
[[tls]] [[tls.certificates]]
[tls.certificate] certFile = "/path/to/other-domain.cert"
certFile = "/path/to/other-domain.cert" keyFile = "/path/to/other-domain.key"
keyFile = "/path/to/other-domain.key"
``` ```
!!! important "File Provider Only" !!! 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: In Traefik, certificates are grouped together in certificates stores, which are defined as such:
```toml ```toml
[tlsStores] [tls.stores]
[tlsStores.default] [tls.stores.default]
``` ```
!!! important "Alpha restriction" !!! 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, 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. 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 ```toml
[[tls]] [[tls.certificates]]
stores = ["default"] stores = ["default"]
[tls.certificate] certFile = "/path/to/domain.cert"
certFile = "/path/to/domain.cert" keyFile = "/path/to/domain.key"
keyFile = "/path/to/domain.key"
[[tls]] [[tls.certificates]]
# Note that since no store is defined, # Note that since no store is defined,
# the certificate below will be stored in the `default` store. # the certificate below will be stored in the `default` store.
[tls.certificate] certFile = "/path/to/other-domain.cert"
certFile = "/path/to/other-domain.cert" keyFile = "/path/to/other-domain.key"
keyFile = "/path/to/other-domain.key"
``` ```
!!! important "Alpha restriction" !!! 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: This default certificate should be defined in a TLS store:
```toml ```toml
[tlsStores] [tls.stores]
[tlsStores.default] [tls.stores.default]
[tlsStores.default.defaultCertificate] [tls.stores.default.defaultCertificate]
certFile = "path/to/cert.crt" certFile = "path/to/cert.crt"
keyFile = "path/to/cert.key" 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 ### Minimum TLS Version
```toml ```toml
[tlsOptions] [tls.options]
[tlsOptions.default] [tls.options.default]
minVersion = "VersionTLS12" minVersion = "VersionTLS12"
[tlsOptions.mintls13] [tls.options.mintls13]
minVersion = "VersionTLS13" 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. - When `optional = true`, Traefik authorizes connections from clients presenting a certificate signed by an unknown CA.
```toml ```toml
[tlsOptions] [tls.options]
[tlsOptions.default] [tls.options.default]
[tlsOptions.default.ClientCA] [tls.options.default.ClientCA]
# in PEM format. each file can contain multiple CAs. # in PEM format. each file can contain multiple CAs.
files = ["tests/clientca1.crt", "tests/clientca2.crt"] files = ["tests/clientca1.crt", "tests/clientca2.crt"]
optional = false 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. See [cipherSuites](https://godoc.org/crypto/tls#pkg-constants) for more information.
```toml ```toml
[tlsOptions] [tls.options]
[tlsOptions.default] [tls.options.default]
cipherSuites = [ cipherSuites = [
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_RSA_WITH_AES_256_GCM_SHA384" "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. that do not specify a server_name extension.
```toml ```toml
[tlsOptions] [tls.options]
[tlsOptions.default] [tls.options.default]
sniStrict = true sniStrict = true
``` ```

View file

@ -192,16 +192,15 @@ Thus, it's possible to define easily lot of routers, services and TLS certificat
{{ end }} {{ end }}
{{ range $i, $e := until 10 }} {{ 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 }}"] Store = ["my-store-foo-{{ $e }}", "my-store-bar-{{ $e }}"]
[TLS.Certificate]
CertFile = "/etc/traefik/cert-{{ $e }}.pem"
KeyFile = "/etc/traefik/cert-{{ $e }}.key"
{{ end }} {{ end }}
[TLSConfig] [tls.config]
{{ range $i, $e := until 10 }} {{ range $i, $e := until 10 }}
[TLSConfig.TLS{{ $e }}] [tls.config.TLS{{ $e }}]
# ... # ...
{{ end }} {{ end }}
``` ```
@ -237,11 +236,11 @@ Thus, it's possible to define easily lot of routers, services and TLS certificat
{{ range $i, $e := until 10 }} {{ range $i, $e := until 10 }}
tls: tls:
store: certificates:
- "my-store-foo-{{ $e }}" - certfile: "/etc/traefik/cert-{{ $e }}.pem"
- "my-store-bar-{{ $e }}"
certificate:
certfile: "/etc/traefik/cert-{{ $e }}.pem"
keyfile: "/etc/traefik/cert-{{ $e }}.key" keyfile: "/etc/traefik/cert-{{ $e }}.key"
store:
- "my-store-foo-{{ $e }}"
- "my-store-bar-{{ $e }}"
{{end}} {{end}}
``` ```

View file

@ -220,42 +220,40 @@
[[TCP.Services.TCPService0.LoadBalancer.Servers]] [[TCP.Services.TCPService0.LoadBalancer.Servers]]
Address = "foobar" Address = "foobar"
[[TLS]] [TLS]
Stores = ["foobar", "foobar"]
[TLS.Certificate] [[TLS.Certificates]]
Stores = ["foobar", "foobar"]
CertFile = "foobar" CertFile = "foobar"
KeyFile = "foobar" KeyFile = "foobar"
[[TLS]] [[TLS.Certificates]]
Stores = ["foobar", "foobar"] Stores = ["foobar", "foobar"]
[TLS.Certificate]
CertFile = "foobar" CertFile = "foobar"
KeyFile = "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] [TLS.Stores]
MinVersion = "foobar" [TLS.Stores.Store0]
CipherSuites = ["foobar", "foobar"] [TLS.Stores.Store0.DefaultCertificate]
SniStrict = true CertFile = "foobar"
[TLSOptions.TLS0.ClientCA] KeyFile = "foobar"
Files = ["foobar", "foobar"] [TLS.Stores.Store1]
Optional = true [TLS.Stores.Store1.DefaultCertificate]
[TLSOptions.TLS1] CertFile = "foobar"
MinVersion = "foobar" KeyFile = "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"

View file

@ -207,7 +207,7 @@ Traefik will terminate the SSL connections (meaning that it will send decrypted
#### `Options` #### `Options`
The `Options` field enables fine-grained control of the TLS parameters. 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" ??? 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 [http.routers.Router-1.tls] # will terminate the TLS request
options = "foo" options = "foo"
[tlsOptions] [tls.options]
[tlsOptions.foo] [tls.options.foo]
minVersion = "VersionTLS12" minVersion = "VersionTLS12"
cipherSuites = [ cipherSuites = [
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
@ -338,7 +338,7 @@ Services are the target for the router.
#### `Options` #### `Options`
The `Options` field enables fine-grained control of the TLS parameters. 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" ??? 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 [tcp.routers.Router-1.tls] # will terminate the TLS request
options = "foo" options = "foo"
[tlsOptions] [tls.options]
[tlsOptions.foo] [tls.options.foo]
minVersion = "VersionTLS12" minVersion = "VersionTLS12"
cipherSuites = [ cipherSuites = [
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",

View file

@ -54,6 +54,7 @@ level = "DEBUG"
service = "test" service = "test"
[http.routers.test.tls] [http.routers.test.tls]
[tlsStores.default.defaultCertificate] [tls.stores]
certFile = "fixtures/acme/ssl/wildcard.crt" [tls.stores.default.defaultCertificate]
keyFile = "fixtures/acme/ssl/wildcard.key" certFile = "fixtures/acme/ssl/wildcard.crt"
keyFile = "fixtures/acme/ssl/wildcard.key"

View file

@ -1,17 +1,16 @@
[http.services] [http.services]
[http.services.test.loadbalancer] [http.services.test.loadbalancer]
[[http.services.test.loadbalancer.servers]] [[http.services.test.loadbalancer.servers]]
url = "http://127.0.0.1:9010" url = "http://127.0.0.1:9010"
[http.routers] [http.routers]
[http.routers.test] [http.routers.test]
entryPoints = ["web-secure"] entryPoints = ["web-secure"]
rule = "Host(`traefik.acme.wtf`)" rule = "Host(`traefik.acme.wtf`)"
service = "test" service = "test"
[http.routers.test.tls] [http.routers.test.tls]
[[tls]] [[tls.certificates]]
store = ["default"] store = ["default"]
[tls.certificate]
certFile = "fixtures/acme/ssl/wildcard.crt" certFile = "fixtures/acme/ssl/wildcard.crt"
keyFile = "fixtures/acme/ssl/wildcard.key" keyFile = "fixtures/acme/ssl/wildcard.key"

View file

@ -28,6 +28,7 @@ rootCAs = [ """{{ .CertContent }}""" ]
[[http.services.service1.loadbalancer.servers]] [[http.services.service1.loadbalancer.servers]]
url = "https://127.0.0.1:{{ .GRPCServerPort }}" url = "https://127.0.0.1:{{ .GRPCServerPort }}"
[tlsStores.default.DefaultCertificate] [tls.stores]
[tls.stores.default.DefaultCertificate]
certFile = """{{ .CertContent }}""" certFile = """{{ .CertContent }}"""
keyFile = """{{ .KeyContent }}""" keyFile = """{{ .KeyContent }}"""

View file

@ -26,6 +26,7 @@ level = "DEBUG"
[[http.services.service1.loadbalancer.servers]] [[http.services.service1.loadbalancer.servers]]
url = "h2c://127.0.0.1:{{ .GRPCServerPort }}" url = "h2c://127.0.0.1:{{ .GRPCServerPort }}"
[tlsStores.default.DefaultCertificate] [tls.stores]
[tls.stores.default.DefaultCertificate]
certFile = """{{ .CertContent }}""" certFile = """{{ .CertContent }}"""
keyFile = """{{ .KeyContent }}""" keyFile = """{{ .KeyContent }}"""

View file

@ -28,6 +28,7 @@ insecureSkipVerify = true
[[http.services.service1.loadbalancer.servers]] [[http.services.service1.loadbalancer.servers]]
url = "https://127.0.0.1:{{ .GRPCServerPort }}" url = "https://127.0.0.1:{{ .GRPCServerPort }}"
[tlsStores.default.DefaultCertificate] [tls.stores]
[tls.stores.default.DefaultCertificate]
certFile = """{{ .CertContent }}""" certFile = """{{ .CertContent }}"""
keyFile = """{{ .KeyContent }}""" keyFile = """{{ .KeyContent }}"""

View file

@ -35,6 +35,7 @@ rootCAs = [ """{{ .CertContent }}""" ]
[[http.services.service1.loadbalancer.servers]] [[http.services.service1.loadbalancer.servers]]
url = "https://127.0.0.1:{{ .GRPCServerPort }}" url = "https://127.0.0.1:{{ .GRPCServerPort }}"
[tlsStores.default.DefaultCertificate] [tls.stores]
[tls.stores.default.DefaultCertificate]
certFile = """{{ .CertContent }}""" certFile = """{{ .CertContent }}"""
keyFile = """{{ .KeyContent }}""" keyFile = """{{ .KeyContent }}"""

View file

@ -36,16 +36,15 @@ level = "DEBUG"
[[http.services.service2.LoadBalancer.Servers]] [[http.services.service2.LoadBalancer.Servers]]
URL = "http://127.0.0.1:9020" URL = "http://127.0.0.1:9020"
[[tls]] [[tls.certificates]]
[tls.certificate] certFile = "fixtures/https/snitest.com.cert"
certFile = "fixtures/https/snitest.com.cert" keyFile = "fixtures/https/snitest.com.key"
keyFile = "fixtures/https/snitest.com.key"
[[tls]] [[tls.certificates]]
[tls.certificate] certFile = "fixtures/https/snitest.org.cert"
certFile = "fixtures/https/snitest.org.cert" keyFile = "fixtures/https/snitest.org.key"
keyFile = "fixtures/https/snitest.org.key"
[tlsOptions.default.ClientCA] [tls.options]
[tls.options.default.ClientCA]
files = ["fixtures/https/clientca/ca1.crt"] files = ["fixtures/https/clientca/ca1.crt"]
optional = true optional = true

View file

@ -36,14 +36,14 @@ level = "DEBUG"
[[http.services.service2.LoadBalancer.Servers]] [[http.services.service2.LoadBalancer.Servers]]
URL = "http://127.0.0.1:9020" URL = "http://127.0.0.1:9020"
[[tls]] [[tls.certificates]]
[tls.certificate] certFile = "fixtures/https/snitest.com.cert"
certFile = "fixtures/https/snitest.com.cert" keyFile = "fixtures/https/snitest.com.key"
keyFile = "fixtures/https/snitest.com.key"
[[tls]]
[tls.certificate]
certFile = "fixtures/https/snitest.org.cert"
keyFile = "fixtures/https/snitest.org.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"] files = ["fixtures/https/clientca/ca1and2.crt"]

View file

@ -35,16 +35,15 @@ level = "DEBUG"
[[http.services.service2.LoadBalancer.Servers]] [[http.services.service2.LoadBalancer.Servers]]
URL = "http://127.0.0.1:9020" URL = "http://127.0.0.1:9020"
[[tls]] [[tls.certificates]]
[tls.certificate] certFile = "fixtures/https/snitest.com.cert"
certFile = "fixtures/https/snitest.com.cert" keyFile = "fixtures/https/snitest.com.key"
keyFile = "fixtures/https/snitest.com.key"
[[tls]] [[tls.certificates]]
[tls.certificate] certFile = "fixtures/https/snitest.org.cert"
certFile = "fixtures/https/snitest.org.cert" keyFile = "fixtures/https/snitest.org.key"
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"] files = ["fixtures/https/clientca/ca1.crt", "fixtures/https/clientca/ca2.crt"]
optional = false optional = false

View file

@ -20,9 +20,8 @@
[[http.services.service2.LoadBalancer.Servers]] [[http.services.service2.LoadBalancer.Servers]]
url = "http://127.0.0.1:9020" url = "http://127.0.0.1:9020"
[[tls]] # bad certificates to validate the loop on the certificate appending
# bad certificates to validate the loop on the certificate appending [[tls.certificates]]
[tls.certificate]
# bad content # bad content
certFile = """-----BEGIN CERTIFICATE----- certFile = """-----BEGIN CERTIFICATE-----
MIIC/zCCAeegAwIBAgIJALAYHG/vGqWEMA0GCSqGSIb3DQEBBQUAMBYxFDASBgNV MIIC/zCCAeegAwIBAgIJALAYHG/vGqWEMA0GCSqGSIb3DQEBBQUAMBYxFDASBgNV
@ -34,8 +33,7 @@ eRG3DaVpez4DQVupZDHMgxJUYqqKynUj6GD1YiaxGROj3TYCu6e7OxyhalhCllSu
w/X5M802XqzLjeec5zHoZDfknnAkgR9MsxZYmZPFaDyL6GOKUB8= w/X5M802XqzLjeec5zHoZDfknnAkgR9MsxZYmZPFaDyL6GOKUB8=
-----END RSA PRIVATE KEY-----""" -----END RSA PRIVATE KEY-----"""
[[tls]] [[tls.certificates]]
[tls.certificate]
certFile = """-----BEGIN CERTIFICATE----- certFile = """-----BEGIN CERTIFICATE-----
MIIC/zCCAeegAwIBAgIJALAYHG/vGqWEMA0GCSqGSIb3DQEBBQUAMBYxFDASBgNV MIIC/zCCAeegAwIBAgIJALAYHG/vGqWEMA0GCSqGSIb3DQEBBQUAMBYxFDASBgNV
BAMMC3NuaXRlc3Qub3JnMB4XDTE1MTEyMzIyMDU0NFoXDTI1MTEyMDIyMDU0NFow BAMMC3NuaXRlc3Qub3JnMB4XDTE1MTEyMzIyMDU0NFoXDTI1MTEyMDIyMDU0NFow

View file

@ -31,16 +31,15 @@ level = "DEBUG"
[[http.services.service1.LoadBalancer.Servers]] [[http.services.service1.LoadBalancer.Servers]]
url = "http://127.0.0.1:9010" url = "http://127.0.0.1:9010"
[[tls]] [[tls.certificates]]
[tls.certificate]
certFile = "fixtures/https/wildcard.snitest.com.cert" certFile = "fixtures/https/wildcard.snitest.com.cert"
keyFile = "fixtures/https/wildcard.snitest.com.key" keyFile = "fixtures/https/wildcard.snitest.com.key"
[[tls]] [[tls.certificates]]
[tls.certificate] certFile = "fixtures/https/www.snitest.com.cert"
certFile = "fixtures/https/www.snitest.com.cert" keyFile = "fixtures/https/www.snitest.com.key"
keyFile = "fixtures/https/www.snitest.com.key"
[tlsStores.default.DefaultCertificate] [tls.stores]
[tls.stores.default.DefaultCertificate]
certFile = "fixtures/https/snitest.com.cert" certFile = "fixtures/https/snitest.com.cert"
keyFile = "fixtures/https/snitest.com.key" keyFile = "fixtures/https/snitest.com.key"

View file

@ -36,12 +36,10 @@ level = "DEBUG"
[[http.services.service2.LoadBalancer.Servers]] [[http.services.service2.LoadBalancer.Servers]]
URL = "http://127.0.0.1:9020" URL = "http://127.0.0.1:9020"
[[tls]] [[tls.certificates]]
[tls.certificate] certFile = "fixtures/https/snitest.com.cert"
certFile = "fixtures/https/snitest.com.cert" keyFile = "fixtures/https/snitest.com.key"
keyFile = "fixtures/https/snitest.com.key"
[[tls]] [[tls.certificates]]
[tls.certificate] certFile = "fixtures/https/snitest.org.cert"
certFile = "fixtures/https/snitest.org.cert" keyFile = "fixtures/https/snitest.org.key"
keyFile = "fixtures/https/snitest.org.key"

View file

@ -31,11 +31,11 @@ level = "DEBUG"
[[http.services.service1.LoadBalancer.Servers]] [[http.services.service1.LoadBalancer.Servers]]
url = "http://127.0.0.1:9010" url = "http://127.0.0.1:9010"
[[tls]] [[tls.certificates]]
[tls.certificate] certFile = "fixtures/https/uppercase_wildcard.www.snitest.com.cert"
certFile = "fixtures/https/uppercase_wildcard.www.snitest.com.cert" keyFile = "fixtures/https/uppercase_wildcard.www.snitest.com.key"
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" certFile = "fixtures/https/wildcard.snitest.com.cert"
keyFile = "fixtures/https/wildcard.snitest.com.key" keyFile = "fixtures/https/wildcard.snitest.com.key"

View file

@ -31,16 +31,15 @@ level = "DEBUG"
[[http.services.service1.LoadBalancer.Servers]] [[http.services.service1.LoadBalancer.Servers]]
url = "http://127.0.0.1:9010" url = "http://127.0.0.1:9010"
[[tls]] [[tls.certificates]]
[tls.certificate] certFile = "fixtures/https/wildcard.snitest.com.cert"
certFile = "fixtures/https/wildcard.snitest.com.cert" keyFile = "fixtures/https/wildcard.snitest.com.key"
keyFile = "fixtures/https/wildcard.snitest.com.key"
[[tls]] [[tls.certificates]]
[tls.certificate] certFile = "fixtures/https/www.snitest.com.cert"
certFile = "fixtures/https/www.snitest.com.cert" keyFile = "fixtures/https/www.snitest.com.key"
keyFile = "fixtures/https/www.snitest.com.key"
[tlsStores.default.DefaultCertificate] [tls.stores]
[tls.stores.default.DefaultCertificate]
certFile = "fixtures/https/snitest.com.cert" certFile = "fixtures/https/snitest.com.cert"
keyFile = "fixtures/https/snitest.com.key" keyFile = "fixtures/https/snitest.com.key"

View file

@ -1,9 +1,9 @@
[global] [global]
checkNewVersion = false checkNewVersion = false
sendAnonymousUsage = false sendAnonymousUsage = false
[log] [log]
level = "DEBUG" level = "DEBUG"
[entryPoints] [entryPoints]
[entryPoints.web-secure] [entryPoints.web-secure]
@ -26,11 +26,13 @@ level = "DEBUG"
[[http.services.service1.LoadBalancer.Servers]] [[http.services.service1.LoadBalancer.Servers]]
url = "http://127.0.0.1:9010" url = "http://127.0.0.1:9010"
[tlsOptions.default] [tls.options]
[tls.options.default]
sniStrict = true sniStrict = true
[tlsStores.default] [tls.stores]
[tlsStores.default.DefaultCertificate] [tls.stores.default]
certFile = "fixtures/https/snitest.com.cert" [tls.stores.default.DefaultCertificate]
keyFile = "fixtures/https/snitest.com.key" certFile = "fixtures/https/snitest.com.cert"
keyFile = "fixtures/https/snitest.com.key"

View file

@ -44,18 +44,18 @@ level = "DEBUG"
[[http.services.service2.LoadBalancer.Servers]] [[http.services.service2.LoadBalancer.Servers]]
URL = "http://127.0.0.1:9020" URL = "http://127.0.0.1:9020"
[[tls]] [[tls.certificates]]
[tls.certificate] certFile = "fixtures/https/snitest.com.cert"
certFile = "fixtures/https/snitest.com.cert" keyFile = "fixtures/https/snitest.com.key"
keyFile = "fixtures/https/snitest.com.key"
[[tls]] [[tls.certificates]]
[tls.certificate] certFile = "fixtures/https/snitest.org.cert"
certFile = "fixtures/https/snitest.org.cert" keyFile = "fixtures/https/snitest.org.key"
keyFile = "fixtures/https/snitest.org.key"
[tlsoptions.foo] [tls.options]
[tls.options.foo]
minversion = "VersionTLS11" minversion = "VersionTLS11"
[tlsoptions.bar] [tls.options.bar]
minversion = "VersionTLS12" minversion = "VersionTLS12"

View file

@ -64,7 +64,6 @@ level = "DEBUG"
[[tcp.services.whoami-no-cert.loadbalancer.servers]] [[tcp.services.whoami-no-cert.loadbalancer.servers]]
address = "localhost:8083" address = "localhost:8083"
[[tls]] [[tls.certificates]]
[tls.certificate]
certFile = "fixtures/tcp/whoami-c.crt" certFile = "fixtures/tcp/whoami-c.crt"
keyFile = "fixtures/tcp/whoami-c.key" keyFile = "fixtures/tcp/whoami-c.key"

View file

@ -35,8 +35,10 @@ level = "DEBUG"
[[tcp.services.whoami-no-cert.loadbalancer.servers]] [[tcp.services.whoami-no-cert.loadbalancer.servers]]
address = "localhost:8083" address = "localhost:8083"
[tlsoptions.foo] [tls.options]
[tls.options.foo]
minversion = "VersionTLS11" minversion = "VersionTLS11"
[tlsoptions.bar] [tls.options.bar]
minversion = "VersionTLS12" minversion = "VersionTLS12"

View file

@ -1,12 +1,12 @@
[global] [global]
checkNewVersion = false checkNewVersion = false
sendAnonymousUsage = false sendAnonymousUsage = false
[log] [log]
level = "DEBUG" level = "DEBUG"
[serversTransport] [serversTransport]
rootCAs = [ """{{ .RootCertContent }}""" ] rootCAs = [ """{{ .RootCertContent }}""" ]
[entryPoints] [entryPoints]
[entryPoints.web-secure] [entryPoints.web-secure]
@ -15,16 +15,18 @@ rootCAs = [ """{{ .RootCertContent }}""" ]
[api] [api]
[providers] [providers]
[providers.docker] [providers.docker]
endpoint = "unix:///var/run/docker.sock" endpoint = "unix:///var/run/docker.sock"
watch = true watch = true
[providers.file] [providers.file]
[tlsOptions.default.ClientCA] [tls.options]
[tls.options.default.ClientCA]
files = [ """{{ .RootCertContent }}""" ] files = [ """{{ .RootCertContent }}""" ]
optional = false optional = false
[tlsStores.default.DefaultCertificate] [tls.stores]
[tls.stores.default.DefaultCertificate]
certFile = """{{ .ServerCertContent }}""" certFile = """{{ .ServerCertContent }}"""
keyFile = """{{ .ServerKeyContent }}""" keyFile = """{{ .ServerKeyContent }}"""

View file

@ -30,6 +30,7 @@ insecureSkipVerify=true
[[http.services.service1.LoadBalancer.Servers]] [[http.services.service1.LoadBalancer.Servers]]
URL = "{{ .WebsocketServer }}" URL = "{{ .WebsocketServer }}"
[tlsStores.default.DefaultCertificate] [tls.stores]
[tls.stores.default.DefaultCertificate]
certFile = "resources/tls/local.cert" certFile = "resources/tls/local.cert"
keyFile = "resources/tls/local.key" keyFile = "resources/tls/local.key"

View file

@ -799,12 +799,14 @@ func modifyCertificateConfFileContent(c *check.C, certFileName, confFileName, en
// If certificate file is not provided, just truncate the configuration file // If certificate file is not provided, just truncate the configuration file
if len(certFileName) > 0 { if len(certFileName) > 0 {
tlsConf := config.Configuration{ tlsConf := config.Configuration{
TLS: []*traefiktls.Configuration{{ TLS: &config.TLSConfiguration{
Certificate: &traefiktls.Certificate{ Certificates: []*traefiktls.CertAndStores{{
CertFile: traefiktls.FileOrContent("fixtures/https/" + certFileName + ".cert"), Certificate: traefiktls.Certificate{
KeyFile: traefiktls.FileOrContent("fixtures/https/" + certFileName + ".key"), CertFile: traefiktls.FileOrContent("fixtures/https/" + certFileName + ".cert"),
KeyFile: traefiktls.FileOrContent("fixtures/https/" + certFileName + ".key"),
}},
}, },
}}, },
} }
var confBuffer bytes.Buffer var confBuffer bytes.Buffer

View file

@ -213,24 +213,29 @@ type Message struct {
// Configuration is the root of the dynamic configuration // Configuration is the root of the dynamic configuration
type Configuration struct { type Configuration struct {
HTTP *HTTPConfiguration HTTP *HTTPConfiguration
TCP *TCPConfiguration TCP *TCPConfiguration
TLS []*traefiktls.Configuration `json:"-" label:"-" yaml:"tls"` TLS *TLSConfiguration
TLSOptions map[string]traefiktls.TLS }
TLSStores map[string]traefiktls.Store
// 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. // Configurations is for currentConfigurations Map.
type Configurations map[string]*Configuration type Configurations map[string]*Configuration
// HTTPConfiguration FIXME better name? // HTTPConfiguration contains all the HTTP configuration parameters.
type HTTPConfiguration struct { type HTTPConfiguration struct {
Routers map[string]*Router `json:"routers,omitempty" toml:",omitempty"` Routers map[string]*Router `json:"routers,omitempty" toml:",omitempty"`
Middlewares map[string]*Middleware `json:"middlewares,omitempty" toml:",omitempty"` Middlewares map[string]*Middleware `json:"middlewares,omitempty" toml:",omitempty"`
Services map[string]*Service `json:"services,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 { type TCPConfiguration struct {
Routers map[string]*TCPRouter `json:"routers,omitempty" toml:",omitempty"` Routers map[string]*TCPRouter `json:"routers,omitempty" toml:",omitempty"`
Services map[string]*TCPService `json:"services,omitempty" toml:",omitempty"` Services map[string]*TCPService `json:"services,omitempty" toml:",omitempty"`

View file

@ -497,42 +497,40 @@
[[TCP.Services.TCPService0.LoadBalancer.Servers]] [[TCP.Services.TCPService0.LoadBalancer.Servers]]
Address = "foobar" Address = "foobar"
[[TLS]] [[TLS.Certificates]]
Stores = ["foobar", "foobar"] Stores = ["foobar", "foobar"]
[TLS.Certificate] CertFile = "foobar"
CertFile = "foobar" KeyFile = "foobar"
KeyFile = "foobar"
[[TLS]] [[TLS.Certificates]]
Stores = ["foobar", "foobar"] Stores = ["foobar", "foobar"]
[TLS.Certificate] CertFile = "foobar"
CertFile = "foobar" KeyFile = "foobar"
KeyFile = "foobar"
[TLSOptions] [TLS.Options]
[TLSOptions.TLS0] [TLS.Options.TLS0]
MinVersion = "foobar" MinVersion = "foobar"
CipherSuites = ["foobar", "foobar"] CipherSuites = ["foobar", "foobar"]
SniStrict = true SniStrict = true
[TLSOptions.TLS0.ClientCA] [TLS.Options.TLS0.ClientCA]
Files = ["foobar", "foobar"] Files = ["foobar", "foobar"]
Optional = true Optional = true
[TLSOptions.TLS1] [TLS.Options.TLS1]
MinVersion = "foobar" MinVersion = "foobar"
CipherSuites = ["foobar", "foobar"] CipherSuites = ["foobar", "foobar"]
SniStrict = true SniStrict = true
[TLSOptions.TLS1.ClientCA] [TLS.Options.TLS1.ClientCA]
Files = ["foobar", "foobar"] Files = ["foobar", "foobar"]
Optional = true Optional = true
[TLSStores] [TLS.Stores]
[TLSStores.Store0] [TLS.Stores.Store0]
[TLSStores.Store0.DefaultCertificate] [TLS.Stores.Store0.DefaultCertificate]
CertFile = "foobar" CertFile = "foobar"
KeyFile = "foobar" KeyFile = "foobar"
[TLSStores.Store1] [TLS.Stores.Store1]
[TLSStores.Store1.DefaultCertificate] [TLS.Stores.Store1.DefaultCertificate]
CertFile = "foobar" CertFile = "foobar"
KeyFile = "foobar" KeyFile = "foobar"

View file

@ -589,14 +589,20 @@ func (p *Provider) refreshCertificates() {
Middlewares: map[string]*config.Middleware{}, Middlewares: map[string]*config.Middleware{},
Services: map[string]*config.Service{}, Services: map[string]*config.Service{},
}, },
TLS: []*traefiktls.Configuration{}, TLS: &config.TLSConfiguration{},
}, },
} }
for _, cert := range p.certificates { for _, cert := range p.certificates {
cert := &traefiktls.Certificate{CertFile: traefiktls.FileOrContent(cert.Certificate), KeyFile: traefiktls.FileOrContent(cert.Key)} certConf := &traefiktls.CertAndStores{
conf.Configuration.TLS = append(conf.Configuration.TLS, &traefiktls.Configuration{Certificate: cert}) 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 p.configurationChan <- conf
} }

View file

@ -182,28 +182,36 @@ func (p *Provider) loadFileConfig(filename string, parseTemplate bool) (*config.
return nil, err return nil, err
} }
var tlsConfigs []*tls.Configuration if configuration.TLS != nil {
for _, conf := range configuration.TLS { configuration.TLS.Certificates = flattenCertificates(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)
} }
configuration.TLS = tlsConfigs
return configuration, nil 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) { func (p *Provider) loadFileConfigFromDirectory(ctx context.Context, directory string, configuration *config.Configuration) (*config.Configuration, error) {
logger := log.FromContext(ctx) logger := log.FromContext(ctx)
@ -223,13 +231,16 @@ func (p *Provider) loadFileConfigFromDirectory(ctx context.Context, directory st
Routers: make(map[string]*config.TCPRouter), Routers: make(map[string]*config.TCPRouter),
Services: make(map[string]*config.TCPService), 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 { for _, item := range fileList {
if item.IsDir() { if item.IsDir() {
configuration, err = p.loadFileConfigFromDirectory(ctx, filepath.Join(directory, item.Name()), configuration) configuration, err = p.loadFileConfigFromDirectory(ctx, filepath.Join(directory, item.Name()), configuration)
if err != nil { 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 { if _, exists := configTLSMaps[conf]; exists {
logger.Warnf("TLS configuration %v already configured, skipping", conf) logger.Warnf("TLS configuration %v already configured, skipping", conf)
} else { } else {
@ -300,9 +311,14 @@ func (p *Provider) loadFileConfigFromDirectory(ctx context.Context, directory st
} }
} }
for conf := range configTLSMaps { if len(configTLSMaps) > 0 {
configuration.TLS = append(configuration.TLS, conf) configuration.TLS = &config.TLSConfiguration{}
} }
for conf := range configTLSMaps {
configuration.TLS.Certificates = append(configuration.TLS.Certificates, conf)
}
return configuration, nil return configuration, nil
} }
@ -364,9 +380,10 @@ func (p *Provider) decodeConfiguration(filePath string, content string) (*config
Routers: make(map[string]*config.TCPRouter), Routers: make(map[string]*config.TCPRouter),
Services: make(map[string]*config.TCPService), Services: make(map[string]*config.TCPService),
}, },
TLS: make([]*tls.Configuration, 0), TLS: &config.TLSConfiguration{
TLSStores: make(map[string]tls.Store), Stores: make(map[string]tls.Store),
TLSOptions: make(map[string]tls.TLS), Options: make(map[string]tls.Options),
},
} }
switch strings.ToLower(filepath.Ext(filePath)) { switch strings.ToLower(filepath.Ext(filePath)) {

View file

@ -37,10 +37,9 @@ func TestTLSContent(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
content := ` content := `
[[tls]] [[tls.certificates]]
[tls.certificate] certFile = "` + fileTLS.Name() + `"
certFile = "` + fileTLS.Name() + `" keyFile = "` + fileTLS.Name() + `"
keyFile = "` + fileTLS.Name() + `"
` `
_, err = fileConfig.Write([]byte(content)) _, err = fileConfig.Write([]byte(content))
@ -50,8 +49,8 @@ func TestTLSContent(t *testing.T) {
configuration, err := provider.loadFileConfig(fileConfig.Name(), true) configuration, err := provider.loadFileConfig(fileConfig.Name(), true)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, "CONTENT", configuration.TLS[0].Certificate.CertFile.String()) require.Equal(t, "CONTENT", configuration.TLS.Certificates[0].Certificate.CertFile.String())
require.Equal(t, "CONTENT", configuration.TLS[0].Certificate.KeyFile.String()) require.Equal(t, "CONTENT", configuration.TLS.Certificates[0].Certificate.KeyFile.String())
} }
func TestErrorWhenEmptyConfig(t *testing.T) { func TestErrorWhenEmptyConfig(t *testing.T) {
@ -91,9 +90,11 @@ func TestProvideWithoutWatch(t *testing.T) {
timeout := time.After(time.Second) timeout := time.After(time.Second)
select { select {
case conf := <-configChan: case conf := <-configChan:
require.NotNil(t, conf.Configuration.HTTP)
assert.Len(t, conf.Configuration.HTTP.Services, test.expectedNumService) assert.Len(t, conf.Configuration.HTTP.Services, test.expectedNumService)
assert.Len(t, conf.Configuration.HTTP.Routers, test.expectedNumRouter) 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: case <-timeout:
t.Errorf("timeout while waiting for config") t.Errorf("timeout while waiting for config")
} }
@ -116,9 +117,11 @@ func TestProvideWithWatch(t *testing.T) {
timeout := time.After(time.Second) timeout := time.After(time.Second)
select { select {
case conf := <-configChan: case conf := <-configChan:
require.NotNil(t, conf.Configuration.HTTP)
assert.Len(t, conf.Configuration.HTTP.Services, 0) assert.Len(t, conf.Configuration.HTTP.Services, 0)
assert.Len(t, conf.Configuration.HTTP.Routers, 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: case <-timeout:
t.Errorf("timeout while waiting for config") t.Errorf("timeout while waiting for config")
} }
@ -148,7 +151,7 @@ func TestProvideWithWatch(t *testing.T) {
numUpdates++ numUpdates++
numServices = len(conf.Configuration.HTTP.Services) numServices = len(conf.Configuration.HTTP.Services)
numRouters = len(conf.Configuration.HTTP.Routers) 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) 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 { if numServices == test.expectedNumService && numRouters == test.expectedNumRouter && numTLSConfs == test.expectedNumTLSConf {

View file

@ -1,16 +1,17 @@
[[TLS]] [TLS]
[TLS.Certificate]
CertFile = "integration/fixtures/https/snitest1.com.cert" [[TLS.Certificates]]
KeyFile = "integration/fixtures/https/snitest1.com.key" CertFile = "integration/fixtures/https/snitest1.com.cert"
[[TLS]] KeyFile = "integration/fixtures/https/snitest1.com.key"
[TLS.Certificate]
CertFile = "integration/fixtures/https/snitest2.com.cert" [[TLS.Certificates]]
KeyFile = "integration/fixtures/https/snitest2.com.key" CertFile = "integration/fixtures/https/snitest2.com.cert"
[[TLS]] KeyFile = "integration/fixtures/https/snitest2.com.key"
[TLS.Certificate]
CertFile = "integration/fixtures/https/snitest3.com.cert" [[TLS.Certificates]]
KeyFile = "integration/fixtures/https/snitest3.com.key" CertFile = "integration/fixtures/https/snitest3.com.cert"
[[TLS]] KeyFile = "integration/fixtures/https/snitest3.com.key"
[TLS.Certificate]
CertFile = "integration/fixtures/https/snitest4.com.cert" [[TLS.Certificates]]
KeyFile = "integration/fixtures/https/snitest4.com.key" CertFile = "integration/fixtures/https/snitest4.com.cert"
KeyFile = "integration/fixtures/https/snitest4.com.key"

View file

@ -33,23 +33,25 @@
[http.services.application-6.loadbalancer] [http.services.application-6.loadbalancer]
[[http.services.application-6.loadbalancer.servers]] [[http.services.application-6.loadbalancer.servers]]
url = "http://172.17.0.6:80" url = "http://172.17.0.6:80"
[[TLS]]
[TLS.Certificate] [TLS]
CertFile = "integration/fixtures/https/snitest1.com.cert"
KeyFile = "integration/fixtures/https/snitest1.com.key" [[TLS.Certificates]]
[[TLS]] CertFile = "integration/fixtures/https/snitest1.com.cert"
[TLS.Certificate] KeyFile = "integration/fixtures/https/snitest1.com.key"
CertFile = "integration/fixtures/https/snitest2.com.cert"
KeyFile = "integration/fixtures/https/snitest2.com.key" [[TLS.Certificates]]
[[TLS]] CertFile = "integration/fixtures/https/snitest2.com.cert"
[TLS.Certificate] KeyFile = "integration/fixtures/https/snitest2.com.key"
CertFile = "integration/fixtures/https/snitest3.com.cert"
KeyFile = "integration/fixtures/https/snitest3.com.key" [[TLS.Certificates]]
[[TLS]] CertFile = "integration/fixtures/https/snitest3.com.cert"
[TLS.Certificate] KeyFile = "integration/fixtures/https/snitest3.com.key"
CertFile = "integration/fixtures/https/snitest4.com.cert"
KeyFile = "integration/fixtures/https/snitest4.com.key" [[TLS.Certificates]]
[[TLS]] CertFile = "integration/fixtures/https/snitest4.com.cert"
[TLS.Certificate] KeyFile = "integration/fixtures/https/snitest4.com.key"
CertFile = "integration/fixtures/https/snitest5.com.cert"
KeyFile = "integration/fixtures/https/snitest5.com.key" [[TLS.Certificates]]
CertFile = "integration/fixtures/https/snitest5.com.cert"
KeyFile = "integration/fixtures/https/snitest5.com.key"

View file

@ -44,19 +44,21 @@
[http.services.application-8.loadbalancer] [http.services.application-8.loadbalancer]
[[http.services.application-8.loadbalancer.servers]] [[http.services.application-8.loadbalancer.servers]]
url = "http://172.17.0.8:80" url = "http://172.17.0.8:80"
[[TLS]]
[TLS.Certificate] [TLS]
CertFile = "integration/fixtures/https/snitest1.com.cert"
KeyFile = "integration/fixtures/https/snitest1.com.key" [[TLS.Certificates]]
[[TLS]] CertFile = "integration/fixtures/https/snitest1.com.cert"
[TLS.Certificate] KeyFile = "integration/fixtures/https/snitest1.com.key"
CertFile = "integration/fixtures/https/snitest2.com.cert"
KeyFile = "integration/fixtures/https/snitest2.com.key" [[TLS.Certificates]]
[[TLS]] CertFile = "integration/fixtures/https/snitest2.com.cert"
[TLS.Certificate] KeyFile = "integration/fixtures/https/snitest2.com.key"
CertFile = "integration/fixtures/https/snitest3.com.cert"
KeyFile = "integration/fixtures/https/snitest3.com.key" [[TLS.Certificates]]
[[TLS]] CertFile = "integration/fixtures/https/snitest3.com.cert"
[TLS.Certificate] KeyFile = "integration/fixtures/https/snitest3.com.key"
CertFile = "integration/fixtures/https/snitest4.com.cert"
KeyFile = "integration/fixtures/https/snitest4.com.key" [[TLS.Certificates]]
CertFile = "integration/fixtures/https/snitest4.com.cert"
KeyFile = "integration/fixtures/https/snitest4.com.key"

View file

@ -1,3 +1,2 @@
[log] [log]
level = "DEBUG" level = "DEBUG"

View file

@ -20,19 +20,21 @@
[http.services.application-3.loadbalancer] [http.services.application-3.loadbalancer]
[[http.services.application-3.loadbalancer.servers]] [[http.services.application-3.loadbalancer.servers]]
url = "http://172.17.0.3:80" url = "http://172.17.0.3:80"
[[TLS]]
[TLS.Certificate] [TLS]
CertFile = "integration/fixtures/https/snitest1.com.cert"
KeyFile = "integration/fixtures/https/snitest1.com.key" [[TLS.Certificates]]
[[TLS]] CertFile = "integration/fixtures/https/snitest1.com.cert"
[TLS.Certificate] KeyFile = "integration/fixtures/https/snitest1.com.key"
CertFile = "integration/fixtures/https/snitest2.com.cert"
KeyFile = "integration/fixtures/https/snitest2.com.key" [[TLS.Certificates]]
[[TLS]] CertFile = "integration/fixtures/https/snitest2.com.cert"
[TLS.Certificate] KeyFile = "integration/fixtures/https/snitest2.com.key"
CertFile = "integration/fixtures/https/snitest3.com.cert"
KeyFile = "integration/fixtures/https/snitest3.com.key" [[TLS.Certificates]]
[[TLS]] CertFile = "integration/fixtures/https/snitest3.com.cert"
[TLS.Certificate] KeyFile = "integration/fixtures/https/snitest3.com.key"
CertFile = "integration/fixtures/https/snitest4.com.cert"
KeyFile = "integration/fixtures/https/snitest4.com.key" [[TLS.Certificates]]
CertFile = "integration/fixtures/https/snitest4.com.cert"
KeyFile = "integration/fixtures/https/snitest4.com.key"

View file

@ -1,7 +1,8 @@
temp="{{ getTag \"test\" }}"
temp="{{ getTag \"test\" }}" [providers.file]
[providers.file]
[http.routers] [http.routers]
[http.routers."router1"] [http.routers."router1"]
service = "application-1" service = "application-1"
@ -21,19 +22,21 @@
[http.services.application-3.loadbalancer] [http.services.application-3.loadbalancer]
[[http.services.application-3.loadbalancer.servers]] [[http.services.application-3.loadbalancer.servers]]
url = "http://172.17.0.3:80" url = "http://172.17.0.3:80"
[[TLS]]
[TLS.Certificate] [TLS]
CertFile = "integration/fixtures/https/snitest1.com.cert"
KeyFile = "integration/fixtures/https/snitest1.com.key" [[TLS.Certificates]]
[[TLS]] CertFile = "integration/fixtures/https/snitest1.com.cert"
[TLS.Certificate] KeyFile = "integration/fixtures/https/snitest1.com.key"
CertFile = "integration/fixtures/https/snitest2.com.cert"
KeyFile = "integration/fixtures/https/snitest2.com.key" [[TLS.Certificates]]
[[TLS]] CertFile = "integration/fixtures/https/snitest2.com.cert"
[TLS.Certificate] KeyFile = "integration/fixtures/https/snitest2.com.key"
CertFile = "integration/fixtures/https/snitest3.com.cert"
KeyFile = "integration/fixtures/https/snitest3.com.key" [[TLS.Certificates]]
[[TLS]] CertFile = "integration/fixtures/https/snitest3.com.cert"
[TLS.Certificate] KeyFile = "integration/fixtures/https/snitest3.com.key"
CertFile = "integration/fixtures/https/snitest4.com.cert"
KeyFile = "integration/fixtures/https/snitest4.com.key" [[TLS.Certificates]]
CertFile = "integration/fixtures/https/snitest4.com.cert"
KeyFile = "integration/fixtures/https/snitest4.com.key"

View file

@ -1,4 +1,3 @@
[http.routers] [http.routers]
{{ range $i, $e := until 20 }} {{ range $i, $e := until 20 }}
[http.routers.router{{ $e }}] [http.routers.router{{ $e }}]

View file

@ -1,13 +1,10 @@
tls: tls:
- certificate: certificates:
certfile: integration/fixtures/https/snitest1.com.cert - certfile: integration/fixtures/https/snitest1.com.cert
keyfile: integration/fixtures/https/snitest1.com.key 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
keyfile: integration/fixtures/https/snitest2.com.key - certfile: integration/fixtures/https/snitest3.com.cert
- certificate: keyfile: integration/fixtures/https/snitest3.com.key
certfile: integration/fixtures/https/snitest3.com.cert - certfile: integration/fixtures/https/snitest4.com.cert
keyfile: integration/fixtures/https/snitest3.com.key keyfile: integration/fixtures/https/snitest4.com.key
- certificate:
certfile: integration/fixtures/https/snitest4.com.cert
keyfile: integration/fixtures/https/snitest4.com.key

View file

@ -33,18 +33,14 @@ http:
- url: 'http://172.17.0.6:80' - url: 'http://172.17.0.6:80'
tls: tls:
- certificate: certificates:
certfile: integration/fixtures/https/snitest1.com.cert - certfile: integration/fixtures/https/snitest1.com.cert
keyfile: integration/fixtures/https/snitest1.com.key 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
keyfile: integration/fixtures/https/snitest2.com.key - certfile: integration/fixtures/https/snitest3.com.cert
- certificate: keyfile: integration/fixtures/https/snitest3.com.key
certfile: integration/fixtures/https/snitest3.com.cert - certfile: integration/fixtures/https/snitest4.com.cert
keyfile: integration/fixtures/https/snitest3.com.key keyfile: integration/fixtures/https/snitest4.com.key
- certificate: - certfile: integration/fixtures/https/snitest5.com.cert
certfile: integration/fixtures/https/snitest4.com.cert keyfile: integration/fixtures/https/snitest5.com.key
keyfile: integration/fixtures/https/snitest4.com.key
- certificate:
certfile: integration/fixtures/https/snitest5.com.cert
keyfile: integration/fixtures/https/snitest5.com.key

View file

@ -43,16 +43,12 @@ http:
- url: 'http://172.17.0.8:80' - url: 'http://172.17.0.8:80'
tls: tls:
- certificate: certificates:
certfile: integration/fixtures/https/snitest1.com.cert - certfile: integration/fixtures/https/snitest1.com.cert
keyfile: integration/fixtures/https/snitest1.com.key 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 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 keyfile: integration/fixtures/https/snitest3.com.key
- certificate: - certfile: integration/fixtures/https/snitest4.com.cert
certfile: integration/fixtures/https/snitest4.com.cert
keyfile: integration/fixtures/https/snitest4.com.key keyfile: integration/fixtures/https/snitest4.com.key

View file

@ -21,15 +21,12 @@ http:
- url: 'http://172.17.0.3:80' - url: 'http://172.17.0.3:80'
tls: tls:
- certificate: certificates:
certfile: integration/fixtures/https/snitest1.com.cert - certfile: integration/fixtures/https/snitest1.com.cert
keyfile: integration/fixtures/https/snitest1.com.key 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 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 keyfile: integration/fixtures/https/snitest3.com.key
- certificate: - certfile: integration/fixtures/https/snitest4.com.cert
certfile: integration/fixtures/https/snitest4.com.cert
keyfile: integration/fixtures/https/snitest4.com.key keyfile: integration/fixtures/https/snitest4.com.key

View file

@ -293,14 +293,14 @@ func loadServers(client Client, namespace string, svc v1alpha1.Service) ([]confi
return servers, nil 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() tlsOptionsCRD := client.GetTLSOptions()
var tlsOptions map[string]tls.TLS var tlsOptions map[string]tls.Options
if len(tlsOptionsCRD) == 0 { if len(tlsOptionsCRD) == 0 {
return tlsOptions return tlsOptions
} }
tlsOptions = make(map[string]tls.TLS) tlsOptions = make(map[string]tls.Options)
for _, tlsOption := range tlsOptionsCRD { for _, tlsOption := range tlsOptionsCRD {
logger := log.FromContext(log.With(ctx, log.Str("tlsOption", tlsOption.Name), log.Str("namespace", tlsOption.Namespace))) 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)) 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, MinVersion: tlsOption.Spec.MinVersion,
CipherSuites: tlsOption.Spec.CipherSuites, CipherSuites: tlsOption.Spec.CipherSuites,
ClientCA: tls.ClientCA{ ClientCA: tls.ClientCA{
@ -340,7 +340,7 @@ func buildTLSOptions(ctx context.Context, client Client) map[string]tls.TLS {
return tlsOptions 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{ conf := &config.HTTPConfiguration{
Routers: map[string]*config.Router{}, Routers: map[string]*config.Router{},
Middlewares: map[string]*config.Middleware{}, Middlewares: map[string]*config.Middleware{},
@ -465,7 +465,7 @@ func (p *Provider) loadIngressRouteConfiguration(ctx context.Context, client Cli
return conf 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{ conf := &config.TCPConfiguration{
Routers: map[string]*config.TCPRouter{}, Routers: map[string]*config.TCPRouter{},
Services: map[string]*config.TCPService{}, 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 { 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{ conf := &config.Configuration{
HTTP: p.loadIngressRouteConfiguration(ctx, client, tlsConfigs), HTTP: p.loadIngressRouteConfiguration(ctx, client, tlsConfigs),
TCP: p.loadIngressRouteTCPConfiguration(ctx, client, tlsConfigs), TCP: p.loadIngressRouteTCPConfiguration(ctx, client, tlsConfigs),
TLSOptions: buildTLSOptions(ctx, client), TLS: &config.TLSConfiguration{
TLS: getTLSConfig(tlsConfigs), Certificates: getTLSConfig(tlsConfigs),
Options: buildTLSOptions(ctx, client),
},
} }
for _, middleware := range client.GetMiddlewares() { for _, middleware := range client.GetMiddlewares() {
@ -604,7 +606,7 @@ func shouldProcessIngress(ingressClass string, ingressClassAnnotation string) bo
(len(ingressClass) == 0 && ingressClassAnnotation == traefikDefaultIngressClass) (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 { if ingressRoute.Spec.TLS == nil {
return nil return nil
} }
@ -626,7 +628,7 @@ func getTLSHTTP(ctx context.Context, ingressRoute *v1alpha1.IngressRoute, k8sCli
return nil 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 { if ingressRoute.Spec.TLS == nil {
return nil return nil
} }
@ -648,7 +650,7 @@ func getTLSTCP(ctx context.Context, ingressRoute *v1alpha1.IngressRouteTCP, k8sC
return nil 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) secret, exists, err := k8sClient.GetSecret(namespace, secretName)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to fetch secret %s/%s: %v", namespace, secretName, err) 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 nil, err
} }
return &tls.Configuration{ return &tls.CertAndStores{
Certificate: &tls.Certificate{ Certificate: tls.Certificate{
CertFile: tls.FileOrContent(cert), CertFile: tls.FileOrContent(cert),
KeyFile: tls.FileOrContent(key), KeyFile: tls.FileOrContent(key),
}, },
}, nil }, nil
} }
func getTLSConfig(tlsConfigs map[string]*tls.Configuration) []*tls.Configuration { func getTLSConfig(tlsConfigs map[string]*tls.CertAndStores) []*tls.CertAndStores {
var secretNames []string var secretNames []string
for secretName := range tlsConfigs { for secretName := range tlsConfigs {
secretNames = append(secretNames, secretName) secretNames = append(secretNames, secretName)
} }
sort.Strings(secretNames) sort.Strings(secretNames)
var configs []*tls.Configuration var configs []*tls.CertAndStores
for _, secretName := range secretNames { for _, secretName := range secretNames {
configs = append(configs, tlsConfigs[secretName]) configs = append(configs, tlsConfigs[secretName])
} }

View file

@ -31,6 +31,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) {
Middlewares: map[string]*config.Middleware{}, Middlewares: map[string]*config.Middleware{},
Services: map[string]*config.Service{}, 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{}, Middlewares: map[string]*config.Middleware{},
Services: map[string]*config.Service{}, Services: map[string]*config.Service{},
}, },
TLS: &config.TLSConfiguration{},
}, },
}, },
{ {
@ -165,6 +168,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) {
Middlewares: map[string]*config.Middleware{}, Middlewares: map[string]*config.Middleware{},
Services: map[string]*config.Service{}, Services: map[string]*config.Service{},
}, },
TLS: &config.TLSConfiguration{},
}, },
}, },
{ {
@ -181,6 +185,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) {
Middlewares: map[string]*config.Middleware{}, Middlewares: map[string]*config.Middleware{},
Services: map[string]*config.Service{}, Services: map[string]*config.Service{},
}, },
TLS: &config.TLSConfiguration{},
}, },
}, },
{ {
@ -196,6 +201,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) {
Middlewares: map[string]*config.Middleware{}, Middlewares: map[string]*config.Middleware{},
Services: map[string]*config.Service{}, Services: map[string]*config.Service{},
}, },
TLS: &config.TLSConfiguration{},
}, },
}, },
{ {
@ -211,17 +217,20 @@ func TestLoadIngressRouteTCPs(t *testing.T) {
Middlewares: map[string]*config.Middleware{}, Middlewares: map[string]*config.Middleware{},
Services: map[string]*config.Service{}, Services: map[string]*config.Service{},
}, },
TLS: &config.TLSConfiguration{},
}, },
}, },
{ {
desc: "TLS", desc: "TLS",
paths: []string{"tcp/services.yml", "tcp/with_tls.yml"}, paths: []string{"tcp/services.yml", "tcp/with_tls.yml"},
expected: &config.Configuration{ expected: &config.Configuration{
TLS: []*tls.Configuration{ TLS: &config.TLSConfiguration{
{ Certificates: []*tls.CertAndStores{
Certificate: &tls.Certificate{ {
CertFile: tls.FileOrContent("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----"), Certificate: tls.Certificate{
KeyFile: tls.FileOrContent("-----BEGIN PRIVATE KEY-----\n-----END PRIVATE KEY-----"), 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{}, Middlewares: map[string]*config.Middleware{},
Services: map[string]*config.Service{}, Services: map[string]*config.Service{},
}, },
TLS: &config.TLSConfiguration{},
}, },
}, },
{ {
desc: "TLS with tls options", desc: "TLS with tls options",
paths: []string{"tcp/services.yml", "tcp/with_tls_options.yml"}, paths: []string{"tcp/services.yml", "tcp/with_tls_options.yml"},
expected: &config.Configuration{ expected: &config.Configuration{
TLSOptions: map[string]tls.TLS{ TLS: &config.TLSConfiguration{
"default/foo": { Options: map[string]tls.Options{
MinVersion: "VersionTLS12", "default/foo": {
CipherSuites: []string{ MinVersion: "VersionTLS12",
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", CipherSuites: []string{
"TLS_RSA_WITH_AES_256_GCM_SHA384", "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-----"),
}, },
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{ TCP: &config.TCPConfiguration{
@ -357,21 +369,23 @@ func TestLoadIngressRouteTCPs(t *testing.T) {
desc: "TLS with tls options and specific namespace", desc: "TLS with tls options and specific namespace",
paths: []string{"tcp/services.yml", "tcp/with_tls_options_and_specific_namespace.yml"}, paths: []string{"tcp/services.yml", "tcp/with_tls_options_and_specific_namespace.yml"},
expected: &config.Configuration{ expected: &config.Configuration{
TLSOptions: map[string]tls.TLS{ TLS: &config.TLSConfiguration{
"myns/foo": { Options: map[string]tls.Options{
MinVersion: "VersionTLS12", "myns/foo": {
CipherSuites: []string{ MinVersion: "VersionTLS12",
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", CipherSuites: []string{
"TLS_RSA_WITH_AES_256_GCM_SHA384", "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-----"),
}, },
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{ TCP: &config.TCPConfiguration{
@ -413,20 +427,22 @@ func TestLoadIngressRouteTCPs(t *testing.T) {
desc: "TLS with bad tls options", desc: "TLS with bad tls options",
paths: []string{"tcp/services.yml", "tcp/with_bad_tls_options.yml"}, paths: []string{"tcp/services.yml", "tcp/with_bad_tls_options.yml"},
expected: &config.Configuration{ expected: &config.Configuration{
TLSOptions: map[string]tls.TLS{ TLS: &config.TLSConfiguration{
"default/foo": { Options: map[string]tls.Options{
MinVersion: "VersionTLS12", "default/foo": {
CipherSuites: []string{ MinVersion: "VersionTLS12",
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", CipherSuites: []string{
"TLS_RSA_WITH_AES_256_GCM_SHA384", "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-----"),
}, },
Optional: true, ClientCA: tls.ClientCA{
Files: []tls.FileOrContent{
tls.FileOrContent("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----"),
},
Optional: true,
},
SniStrict: true,
}, },
SniStrict: true,
}, },
}, },
TCP: &config.TCPConfiguration{ TCP: &config.TCPConfiguration{
@ -468,9 +484,11 @@ func TestLoadIngressRouteTCPs(t *testing.T) {
desc: "TLS with unknown tls options", desc: "TLS with unknown tls options",
paths: []string{"tcp/services.yml", "tcp/with_unknown_tls_options.yml"}, paths: []string{"tcp/services.yml", "tcp/with_unknown_tls_options.yml"},
expected: &config.Configuration{ expected: &config.Configuration{
TLSOptions: map[string]tls.TLS{ TLS: &config.TLSConfiguration{
"default/foo": { Options: map[string]tls.Options{
MinVersion: "VersionTLS12", "default/foo": {
MinVersion: "VersionTLS12",
},
}, },
}, },
TCP: &config.TCPConfiguration{ TCP: &config.TCPConfiguration{
@ -512,9 +530,11 @@ func TestLoadIngressRouteTCPs(t *testing.T) {
desc: "TLS with unknown tls options namespace", desc: "TLS with unknown tls options namespace",
paths: []string{"tcp/services.yml", "tcp/with_unknown_tls_options_namespace.yml"}, paths: []string{"tcp/services.yml", "tcp/with_unknown_tls_options_namespace.yml"},
expected: &config.Configuration{ expected: &config.Configuration{
TLSOptions: map[string]tls.TLS{ TLS: &config.TLSConfiguration{
"default/foo": { Options: map[string]tls.Options{
MinVersion: "VersionTLS12", "default/foo": {
MinVersion: "VersionTLS12",
},
}, },
}, },
TCP: &config.TCPConfiguration{ TCP: &config.TCPConfiguration{
@ -587,6 +607,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) {
Middlewares: map[string]*config.Middleware{}, Middlewares: map[string]*config.Middleware{},
Services: map[string]*config.Service{}, Services: map[string]*config.Service{},
}, },
TLS: &config.TLSConfiguration{},
}, },
}, },
} }
@ -627,6 +648,7 @@ func TestLoadIngressRoutes(t *testing.T) {
Middlewares: map[string]*config.Middleware{}, Middlewares: map[string]*config.Middleware{},
Services: map[string]*config.Service{}, 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", desc: "Simple Ingress Route with middleware crossprovider",
paths: []string{"services.yml", "with_middleware_crossprovider.yml"}, paths: []string{"services.yml", "with_middleware_crossprovider.yml"},
expected: &config.Configuration{ expected: &config.Configuration{
TLS: &config.TLSConfiguration{},
TCP: &config.TCPConfiguration{ TCP: &config.TCPConfiguration{
Routers: map[string]*config.TCPRouter{}, Routers: map[string]*config.TCPRouter{},
Services: map[string]*config.TCPService{}, 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", desc: "One ingress Route with two different services, their servers will merge",
paths: []string{"services.yml", "with_two_services.yml"}, paths: []string{"services.yml", "with_two_services.yml"},
expected: &config.Configuration{ expected: &config.Configuration{
TLS: &config.TLSConfiguration{},
TCP: &config.TCPConfiguration{ TCP: &config.TCPConfiguration{
Routers: map[string]*config.TCPRouter{}, Routers: map[string]*config.TCPRouter{},
Services: map[string]*config.TCPService{}, Services: map[string]*config.TCPService{},
@ -863,6 +890,7 @@ func TestLoadIngressRoutes(t *testing.T) {
paths: []string{"services.yml", "simple.yml"}, paths: []string{"services.yml", "simple.yml"},
ingressClass: "tchouk", ingressClass: "tchouk",
expected: &config.Configuration{ expected: &config.Configuration{
TLS: &config.TLSConfiguration{},
TCP: &config.TCPConfiguration{ TCP: &config.TCPConfiguration{
Routers: map[string]*config.TCPRouter{}, Routers: map[string]*config.TCPRouter{},
Services: map[string]*config.TCPService{}, Services: map[string]*config.TCPService{},
@ -878,6 +906,7 @@ func TestLoadIngressRoutes(t *testing.T) {
desc: "Route with empty rule value is ignored", desc: "Route with empty rule value is ignored",
paths: []string{"services.yml", "with_no_rule_value.yml"}, paths: []string{"services.yml", "with_no_rule_value.yml"},
expected: &config.Configuration{ expected: &config.Configuration{
TLS: &config.TLSConfiguration{},
TCP: &config.TCPConfiguration{ TCP: &config.TCPConfiguration{
Routers: map[string]*config.TCPRouter{}, Routers: map[string]*config.TCPRouter{},
Services: map[string]*config.TCPService{}, 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", desc: "Route with kind not of a rule type (empty kind) is ignored",
paths: []string{"services.yml", "with_wrong_rule_kind.yml"}, paths: []string{"services.yml", "with_wrong_rule_kind.yml"},
expected: &config.Configuration{ expected: &config.Configuration{
TLS: &config.TLSConfiguration{},
TCP: &config.TCPConfiguration{ TCP: &config.TCPConfiguration{
Routers: map[string]*config.TCPRouter{}, Routers: map[string]*config.TCPRouter{},
Services: map[string]*config.TCPService{}, Services: map[string]*config.TCPService{},
@ -908,6 +938,7 @@ func TestLoadIngressRoutes(t *testing.T) {
desc: "check rule quoting validity", desc: "check rule quoting validity",
paths: []string{"services.yml", "with_bad_host_rule.yml"}, paths: []string{"services.yml", "with_bad_host_rule.yml"},
expected: &config.Configuration{ expected: &config.Configuration{
TLS: &config.TLSConfiguration{},
TCP: &config.TCPConfiguration{ TCP: &config.TCPConfiguration{
Routers: map[string]*config.TCPRouter{}, Routers: map[string]*config.TCPRouter{},
Services: map[string]*config.TCPService{}, Services: map[string]*config.TCPService{},
@ -923,11 +954,13 @@ func TestLoadIngressRoutes(t *testing.T) {
desc: "TLS", desc: "TLS",
paths: []string{"services.yml", "with_tls.yml"}, paths: []string{"services.yml", "with_tls.yml"},
expected: &config.Configuration{ expected: &config.Configuration{
TLS: []*tls.Configuration{ TLS: &config.TLSConfiguration{
{ Certificates: []*tls.CertAndStores{
Certificate: &tls.Certificate{ {
CertFile: tls.FileOrContent("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----"), Certificate: tls.Certificate{
KeyFile: tls.FileOrContent("-----BEGIN PRIVATE KEY-----\n-----END PRIVATE KEY-----"), 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", desc: "TLS with tls options",
paths: []string{"services.yml", "with_tls_options.yml"}, paths: []string{"services.yml", "with_tls_options.yml"},
expected: &config.Configuration{ expected: &config.Configuration{
TLSOptions: map[string]tls.TLS{ TLS: &config.TLSConfiguration{
"default/foo": { Options: map[string]tls.Options{
MinVersion: "VersionTLS12", "default/foo": {
CipherSuites: []string{ MinVersion: "VersionTLS12",
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", CipherSuites: []string{
"TLS_RSA_WITH_AES_256_GCM_SHA384", "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-----"),
}, },
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{ TCP: &config.TCPConfiguration{
@ -1024,21 +1059,23 @@ func TestLoadIngressRoutes(t *testing.T) {
desc: "TLS with tls options and specific namespace", desc: "TLS with tls options and specific namespace",
paths: []string{"services.yml", "with_tls_options_and_specific_namespace.yml"}, paths: []string{"services.yml", "with_tls_options_and_specific_namespace.yml"},
expected: &config.Configuration{ expected: &config.Configuration{
TLSOptions: map[string]tls.TLS{ TLS: &config.TLSConfiguration{
"myns/foo": { Options: map[string]tls.Options{
MinVersion: "VersionTLS12", "myns/foo": {
CipherSuites: []string{ MinVersion: "VersionTLS12",
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", CipherSuites: []string{
"TLS_RSA_WITH_AES_256_GCM_SHA384", "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-----"),
}, },
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{ TCP: &config.TCPConfiguration{
@ -1080,20 +1117,22 @@ func TestLoadIngressRoutes(t *testing.T) {
desc: "TLS with bad tls options", desc: "TLS with bad tls options",
paths: []string{"services.yml", "with_bad_tls_options.yml"}, paths: []string{"services.yml", "with_bad_tls_options.yml"},
expected: &config.Configuration{ expected: &config.Configuration{
TLSOptions: map[string]tls.TLS{ TLS: &config.TLSConfiguration{
"default/foo": { Options: map[string]tls.Options{
MinVersion: "VersionTLS12", "default/foo": {
CipherSuites: []string{ MinVersion: "VersionTLS12",
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", CipherSuites: []string{
"TLS_RSA_WITH_AES_256_GCM_SHA384", "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-----"),
}, },
Optional: true, ClientCA: tls.ClientCA{
Files: []tls.FileOrContent{
tls.FileOrContent("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----"),
},
Optional: true,
},
SniStrict: true,
}, },
SniStrict: true,
}, },
}, },
TCP: &config.TCPConfiguration{ TCP: &config.TCPConfiguration{
@ -1135,9 +1174,11 @@ func TestLoadIngressRoutes(t *testing.T) {
desc: "TLS with unknown tls options", desc: "TLS with unknown tls options",
paths: []string{"services.yml", "with_unknown_tls_options.yml"}, paths: []string{"services.yml", "with_unknown_tls_options.yml"},
expected: &config.Configuration{ expected: &config.Configuration{
TLSOptions: map[string]tls.TLS{ TLS: &config.TLSConfiguration{
"default/foo": { Options: map[string]tls.Options{
MinVersion: "VersionTLS12", "default/foo": {
MinVersion: "VersionTLS12",
},
}, },
}, },
TCP: &config.TCPConfiguration{ TCP: &config.TCPConfiguration{
@ -1179,9 +1220,11 @@ func TestLoadIngressRoutes(t *testing.T) {
desc: "TLS with unknown tls options namespace", desc: "TLS with unknown tls options namespace",
paths: []string{"services.yml", "with_unknown_tls_options_namespace.yml"}, paths: []string{"services.yml", "with_unknown_tls_options_namespace.yml"},
expected: &config.Configuration{ expected: &config.Configuration{
TLSOptions: map[string]tls.TLS{ TLS: &config.TLSConfiguration{
"default/foo": { Options: map[string]tls.Options{
MinVersion: "VersionTLS12", "default/foo": {
MinVersion: "VersionTLS12",
},
}, },
}, },
TCP: &config.TCPConfiguration{ TCP: &config.TCPConfiguration{
@ -1223,6 +1266,7 @@ func TestLoadIngressRoutes(t *testing.T) {
desc: "TLS with ACME", desc: "TLS with ACME",
paths: []string{"services.yml", "with_tls_acme.yml"}, paths: []string{"services.yml", "with_tls_acme.yml"},
expected: &config.Configuration{ expected: &config.Configuration{
TLS: &config.TLSConfiguration{},
TCP: &config.TCPConfiguration{ TCP: &config.TCPConfiguration{
Routers: map[string]*config.TCPRouter{}, Routers: map[string]*config.TCPRouter{},
Services: map[string]*config.TCPService{}, Services: map[string]*config.TCPService{},
@ -1260,6 +1304,7 @@ func TestLoadIngressRoutes(t *testing.T) {
desc: "Simple Ingress Route, defaulting to https for servers", desc: "Simple Ingress Route, defaulting to https for servers",
paths: []string{"services.yml", "with_https_default.yml"}, paths: []string{"services.yml", "with_https_default.yml"},
expected: &config.Configuration{ expected: &config.Configuration{
TLS: &config.TLSConfiguration{},
TCP: &config.TCPConfiguration{ TCP: &config.TCPConfiguration{
Routers: map[string]*config.TCPRouter{}, Routers: map[string]*config.TCPRouter{},
Services: map[string]*config.TCPService{}, Services: map[string]*config.TCPService{},

View file

@ -257,7 +257,7 @@ func (p *Provider) loadConfigurationFromIngresses(ctx context.Context, client Cl
ingresses := client.GetIngresses() ingresses := client.GetIngresses()
tlsConfigs := make(map[string]*tls.Configuration) tlsConfigs := make(map[string]*tls.CertAndStores)
for _, ingress := range ingresses { for _, ingress := range ingresses {
ctx = log.With(ctx, log.Str("ingress", ingress.Name), log.Str("namespace", ingress.Namespace)) 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 return conf
} }
@ -350,7 +356,7 @@ func shouldProcessIngress(ingressClass string, ingressClassAnnotation string) bo
(len(ingressClass) == 0 && ingressClassAnnotation == traefikDefaultIngressClass) (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 { for _, t := range ingress.Spec.TLS {
if t.SecretName == "" { if t.SecretName == "" {
log.FromContext(ctx).Debugf("Skipping TLS sub-section: No secret name provided") 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 return err
} }
tlsConfigs[configKey] = &tls.Configuration{ tlsConfigs[configKey] = &tls.CertAndStores{
Certificate: &tls.Certificate{ Certificate: tls.Certificate{
CertFile: tls.FileOrContent(cert), CertFile: tls.FileOrContent(cert),
KeyFile: tls.FileOrContent(key), KeyFile: tls.FileOrContent(key),
}, },
@ -384,14 +390,14 @@ func getTLS(ctx context.Context, ingress *v1beta1.Ingress, k8sClient Client, tls
return nil return nil
} }
func getTLSConfig(tlsConfigs map[string]*tls.Configuration) []*tls.Configuration { func getTLSConfig(tlsConfigs map[string]*tls.CertAndStores) []*tls.CertAndStores {
var secretNames []string var secretNames []string
for secretName := range tlsConfigs { for secretName := range tlsConfigs {
secretNames = append(secretNames, secretName) secretNames = append(secretNames, secretName)
} }
sort.Strings(secretNames) sort.Strings(secretNames)
var configs []*tls.Configuration var configs []*tls.CertAndStores
for _, secretName := range secretNames { for _, secretName := range secretNames {
configs = append(configs, tlsConfigs[secretName]) configs = append(configs, tlsConfigs[secretName])
} }

View file

@ -702,11 +702,13 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
}, },
}, },
}, },
TLS: []*tls.Configuration{ TLS: &config.TLSConfiguration{
{ Certificates: []*tls.CertAndStores{
Certificate: &tls.Certificate{ {
CertFile: tls.FileOrContent("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----"), Certificate: tls.Certificate{
KeyFile: tls.FileOrContent("-----BEGIN PRIVATE KEY-----\n-----END PRIVATE KEY-----"), 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 desc string
ingress *v1beta1.Ingress ingress *v1beta1.Ingress
client Client client Client
result map[string]*tls.Configuration result map[string]*tls.CertAndStores
errResult string errResult string
}{ }{
{ {
@ -1080,15 +1082,15 @@ func TestGetTLS(t *testing.T) {
}, },
}, },
}, },
result: map[string]*tls.Configuration{ result: map[string]*tls.CertAndStores{
"testing/test-secret": { "testing/test-secret": {
Certificate: &tls.Certificate{ Certificate: tls.Certificate{
CertFile: tls.FileOrContent("tls-crt"), CertFile: tls.FileOrContent("tls-crt"),
KeyFile: tls.FileOrContent("tls-key"), KeyFile: tls.FileOrContent("tls-key"),
}, },
}, },
"testing/test-secret2": { "testing/test-secret2": {
Certificate: &tls.Certificate{ Certificate: tls.Certificate{
CertFile: tls.FileOrContent("tls-crt"), CertFile: tls.FileOrContent("tls-crt"),
KeyFile: tls.FileOrContent("tls-key"), KeyFile: tls.FileOrContent("tls-key"),
}, },
@ -1099,7 +1101,7 @@ func TestGetTLS(t *testing.T) {
desc: "return nil when no secret is defined", desc: "return nil when no secret is defined",
ingress: testIngressWithoutSecret, ingress: testIngressWithoutSecret,
client: clientMock{}, 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.Run(test.desc, func(t *testing.T) {
t.Parallel() t.Parallel()
tlsConfigs := map[string]*tls.Configuration{} tlsConfigs := map[string]*tls.CertAndStores{}
err := getTLS(context.Background(), test.ingress, test.client, tlsConfigs) err := getTLS(context.Background(), test.ingress, test.client, tlsConfigs)
if test.errResult != "" { if test.errResult != "" {

View file

@ -18,8 +18,10 @@ func mergeConfiguration(configurations config.Configurations) config.Configurati
Routers: make(map[string]*config.TCPRouter), Routers: make(map[string]*config.TCPRouter),
Services: make(map[string]*config.TCPService), Services: make(map[string]*config.TCPService),
}, },
TLSOptions: make(map[string]tls.TLS), TLS: &config.TLSConfiguration{
TLSStores: make(map[string]tls.Store), Stores: make(map[string]tls.Store),
Options: make(map[string]tls.Options),
},
} }
var defaultTLSOptionProviders []string var defaultTLSOptionProviders []string
@ -44,30 +46,33 @@ func mergeConfiguration(configurations config.Configurations) config.Configurati
conf.TCP.Services[internal.MakeQualifiedName(provider, serviceName)] = service conf.TCP.Services[internal.MakeQualifiedName(provider, serviceName)] = service
} }
} }
conf.TLS = append(conf.TLS, configuration.TLS...)
for key, store := range configuration.TLSStores { if configuration.TLS != nil {
conf.TLSStores[key] = store conf.TLS.Certificates = append(conf.TLS.Certificates, configuration.TLS.Certificates...)
}
for tlsOptionsName, config := range configuration.TLSOptions { for key, store := range configuration.TLS.Stores {
if tlsOptionsName != "default" { conf.TLS.Stores[key] = store
tlsOptionsName = internal.MakeQualifiedName(provider, tlsOptionsName)
} else {
defaultTLSOptionProviders = append(defaultTLSOptionProviders, provider)
} }
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 { if len(defaultTLSOptionProviders) == 0 {
conf.TLSOptions["default"] = tls.TLS{} conf.TLS.Options["default"] = tls.Options{}
} else if len(defaultTLSOptionProviders) > 1 { } else if len(defaultTLSOptionProviders) > 1 {
log.WithoutContext().Errorf("Default TLS Options defined multiple times in %v", defaultTLSOptionProviders) 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, // 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. // 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 return conf

View file

@ -114,12 +114,12 @@ func TestAggregator_tlsoptions(t *testing.T) {
testCases := []struct { testCases := []struct {
desc string desc string
given config.Configurations given config.Configurations
expected map[string]tls.TLS expected map[string]tls.Options
}{ }{
{ {
desc: "Nil returns an empty configuration", desc: "Nil returns an empty configuration",
given: nil, given: nil,
expected: map[string]tls.TLS{ expected: map[string]tls.Options{
"default": {}, "default": {},
}, },
}, },
@ -127,14 +127,16 @@ func TestAggregator_tlsoptions(t *testing.T) {
desc: "Returns fully qualified elements from a mono-provider configuration map", desc: "Returns fully qualified elements from a mono-provider configuration map",
given: config.Configurations{ given: config.Configurations{
"provider-1": &config.Configuration{ "provider-1": &config.Configuration{
TLSOptions: map[string]tls.TLS{ TLS: &config.TLSConfiguration{
"foo": { Options: map[string]tls.Options{
MinVersion: "VersionTLS12", "foo": {
MinVersion: "VersionTLS12",
},
}, },
}, },
}, },
}, },
expected: map[string]tls.TLS{ expected: map[string]tls.Options{
"default": {}, "default": {},
"foo@provider-1": { "foo@provider-1": {
MinVersion: "VersionTLS12", MinVersion: "VersionTLS12",
@ -145,21 +147,25 @@ func TestAggregator_tlsoptions(t *testing.T) {
desc: "Returns fully qualified elements from a multi-provider configuration map", desc: "Returns fully qualified elements from a multi-provider configuration map",
given: config.Configurations{ given: config.Configurations{
"provider-1": &config.Configuration{ "provider-1": &config.Configuration{
TLSOptions: map[string]tls.TLS{ TLS: &config.TLSConfiguration{
"foo": { Options: map[string]tls.Options{
MinVersion: "VersionTLS13", "foo": {
MinVersion: "VersionTLS13",
},
}, },
}, },
}, },
"provider-2": &config.Configuration{ "provider-2": &config.Configuration{
TLSOptions: map[string]tls.TLS{ TLS: &config.TLSConfiguration{
"foo": { Options: map[string]tls.Options{
MinVersion: "VersionTLS12", "foo": {
MinVersion: "VersionTLS12",
},
}, },
}, },
}, },
}, },
expected: map[string]tls.TLS{ expected: map[string]tls.Options{
"default": {}, "default": {},
"foo@provider-1": { "foo@provider-1": {
MinVersion: "VersionTLS13", 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", desc: "Create a valid default tls option when appears only in one provider",
given: config.Configurations{ given: config.Configurations{
"provider-1": &config.Configuration{ "provider-1": &config.Configuration{
TLSOptions: map[string]tls.TLS{ TLS: &config.TLSConfiguration{
"foo": { Options: map[string]tls.Options{
MinVersion: "VersionTLS13", "foo": {
}, MinVersion: "VersionTLS13",
"default": { },
MinVersion: "VersionTLS11", "default": {
MinVersion: "VersionTLS11",
},
}, },
}, },
}, },
"provider-2": &config.Configuration{ "provider-2": &config.Configuration{
TLSOptions: map[string]tls.TLS{ TLS: &config.TLSConfiguration{
"foo": { Options: map[string]tls.Options{
MinVersion: "VersionTLS12", "foo": {
MinVersion: "VersionTLS12",
},
}, },
}, },
}, },
}, },
expected: map[string]tls.TLS{ expected: map[string]tls.Options{
"default": { "default": {
MinVersion: "VersionTLS11", MinVersion: "VersionTLS11",
}, },
@ -206,27 +216,31 @@ func TestAggregator_tlsoptions(t *testing.T) {
desc: "No default tls option if it is defined in multiple providers", desc: "No default tls option if it is defined in multiple providers",
given: config.Configurations{ given: config.Configurations{
"provider-1": &config.Configuration{ "provider-1": &config.Configuration{
TLSOptions: map[string]tls.TLS{ TLS: &config.TLSConfiguration{
"foo": { Options: map[string]tls.Options{
MinVersion: "VersionTLS12", "foo": {
}, MinVersion: "VersionTLS12",
"default": { },
MinVersion: "VersionTLS11", "default": {
MinVersion: "VersionTLS11",
},
}, },
}, },
}, },
"provider-2": &config.Configuration{ "provider-2": &config.Configuration{
TLSOptions: map[string]tls.TLS{ TLS: &config.TLSConfiguration{
"foo": { Options: map[string]tls.Options{
MinVersion: "VersionTLS13", "foo": {
}, MinVersion: "VersionTLS13",
"default": { },
MinVersion: "VersionTLS12", "default": {
MinVersion: "VersionTLS12",
},
}, },
}, },
}, },
}, },
expected: map[string]tls.TLS{ expected: map[string]tls.Options{
"foo@provider-1": { "foo@provider-1": {
MinVersion: "VersionTLS12", MinVersion: "VersionTLS12",
}, },
@ -239,21 +253,25 @@ func TestAggregator_tlsoptions(t *testing.T) {
desc: "Create a default TLS Options configuration if none was provided", desc: "Create a default TLS Options configuration if none was provided",
given: config.Configurations{ given: config.Configurations{
"provider-1": &config.Configuration{ "provider-1": &config.Configuration{
TLSOptions: map[string]tls.TLS{ TLS: &config.TLSConfiguration{
"foo": { Options: map[string]tls.Options{
MinVersion: "VersionTLS12", "foo": {
MinVersion: "VersionTLS12",
},
}, },
}, },
}, },
"provider-2": &config.Configuration{ "provider-2": &config.Configuration{
TLSOptions: map[string]tls.TLS{ TLS: &config.TLSConfiguration{
"foo": { Options: map[string]tls.Options{
MinVersion: "VersionTLS13", "foo": {
MinVersion: "VersionTLS13",
},
}, },
}, },
}, },
}, },
expected: map[string]tls.TLS{ expected: map[string]tls.Options{
"default": {}, "default": {},
"foo@provider-1": { "foo@provider-1": {
MinVersion: "VersionTLS12", MinVersion: "VersionTLS12",
@ -272,7 +290,7 @@ func TestAggregator_tlsoptions(t *testing.T) {
t.Parallel() t.Parallel()
actual := mergeConfiguration(test.given) actual := mergeConfiguration(test.given)
assert.Equal(t, test.expected, actual.TLSOptions) assert.Equal(t, test.expected, actual.TLS.Options)
}) })
} }
} }

View file

@ -203,7 +203,7 @@ func TestRuntimeConfiguration(t *testing.T) {
tlsManager := tls.NewManager() tlsManager := tls.NewManager()
tlsManager.UpdateConfigs( tlsManager.UpdateConfigs(
map[string]tls.Store{}, map[string]tls.Store{},
map[string]tls.TLS{ map[string]tls.Options{
"default": { "default": {
MinVersion: "VersionTLS10", MinVersion: "VersionTLS10",
}, },
@ -214,7 +214,7 @@ func TestRuntimeConfiguration(t *testing.T) {
MinVersion: "VersionTLS11", MinVersion: "VersionTLS11",
}, },
}, },
[]*tls.Configuration{}) []*tls.CertAndStores{})
routerManager := NewManager(conf, serviceManager, routerManager := NewManager(conf, serviceManager,
nil, nil, tlsManager) nil, nil, tlsManager)

View file

@ -66,7 +66,7 @@ func (s *Server) loadConfigurationTCP(configurations config.Configurations) map[
conf := mergeConfiguration(configurations) 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) rtConf := config.NewRuntimeConfig(conf)
handlersNonTLS, handlersTLS := s.createHTTPHandlers(ctx, rtConf, entryPoints) handlersNonTLS, handlersTLS := s.createHTTPHandlers(ctx, rtConf, entryPoints)
@ -167,7 +167,7 @@ func isEmptyConfiguration(conf *config.Configuration) bool {
return conf.HTTP.Routers == nil && return conf.HTTP.Routers == nil &&
conf.HTTP.Services == nil && conf.HTTP.Services == nil &&
conf.HTTP.Middlewares == 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.Routers == nil &&
conf.TCP.Services == nil conf.TCP.Services == nil
} }

View file

@ -9,8 +9,8 @@ type ClientCA struct {
Optional bool Optional bool
} }
// TLS configures TLS for an entry point // Options configures TLS for an entry point
type TLS struct { type Options struct {
MinVersion string `export:"true"` MinVersion string `export:"true"`
CipherSuites []string CipherSuites []string
ClientCA ClientCA ClientCA ClientCA
@ -22,8 +22,8 @@ type Store struct {
DefaultCertificate *Certificate DefaultCertificate *Certificate
} }
// Configuration allows mapping a TLS certificate to a list of entry points. // CertAndStores allows mapping a TLS certificate to a list of entry points.
type Configuration struct { type CertAndStores struct {
Certificate `yaml:",inline"`
Stores []string Stores []string
Certificate *Certificate
} }

View file

@ -17,8 +17,8 @@ import (
type Manager struct { type Manager struct {
storesConfig map[string]Store storesConfig map[string]Store
stores map[string]*CertificateStore stores map[string]*CertificateStore
configs map[string]TLS configs map[string]Options
certs []*Configuration certs []*CertAndStores
TLSAlpnGetter func(string) (*tls.Certificate, error) TLSAlpnGetter func(string) (*tls.Certificate, error)
lock sync.RWMutex lock sync.RWMutex
} }
@ -29,7 +29,7 @@ func NewManager() *Manager {
} }
// UpdateConfigs updates the TLS* configuration options // 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() m.lock.Lock()
defer m.lock.Unlock() 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 // 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{} conf := &tls.Config{}
// ensure http2 enabled // ensure http2 enabled

View file

@ -46,15 +46,12 @@ f9Oeos0UUothgiDktdQHxdNEwLjQf7lJJBzV+5OtwswCWA==
) )
func TestTLSInStore(t *testing.T) { func TestTLSInStore(t *testing.T) {
dynamicConfigs := dynamicConfigs := []*CertAndStores{{
[]*Configuration{ Certificate: Certificate{
{ CertFile: localhostCert,
Certificate: &Certificate{ KeyFile: localhostKey,
CertFile: localhostCert, },
KeyFile: localhostKey, }}
},
},
}
tlsManager := NewManager() tlsManager := NewManager()
tlsManager.UpdateConfigs(nil, nil, dynamicConfigs) tlsManager.UpdateConfigs(nil, nil, dynamicConfigs)
@ -66,15 +63,12 @@ func TestTLSInStore(t *testing.T) {
} }
func TestTLSInvalidStore(t *testing.T) { func TestTLSInvalidStore(t *testing.T) {
dynamicConfigs := dynamicConfigs := []*CertAndStores{{
[]*Configuration{ Certificate: Certificate{
{ CertFile: localhostCert,
Certificate: &Certificate{ KeyFile: localhostKey,
CertFile: localhostCert, },
KeyFile: localhostKey, }}
},
},
}
tlsManager := NewManager() tlsManager := NewManager()
tlsManager.UpdateConfigs(map[string]Store{ tlsManager.UpdateConfigs(map[string]Store{
@ -93,16 +87,14 @@ func TestTLSInvalidStore(t *testing.T) {
} }
func TestManager_Get(t *testing.T) { func TestManager_Get(t *testing.T) {
dynamicConfigs := dynamicConfigs := []*CertAndStores{{
[]*Configuration{ Certificate: Certificate{
{ CertFile: localhostCert,
Certificate: &Certificate{ KeyFile: localhostKey,
CertFile: localhostCert, },
KeyFile: localhostKey, }}
},
}, tlsConfigs := map[string]Options{
}
tlsConfigs := map[string]TLS{
"foo": {MinVersion: "VersionTLS12"}, "foo": {MinVersion: "VersionTLS12"},
"bar": {MinVersion: "VersionTLS11"}, "bar": {MinVersion: "VersionTLS11"},
} }
@ -153,5 +145,4 @@ func TestManager_Get(t *testing.T) {
assert.Equal(t, config.MinVersion, test.expectedMinVersion) assert.Equal(t, config.MinVersion, test.expectedMinVersion)
}) })
} }
} }