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:
parent
c9b2a07bc7
commit
4245096be4
52 changed files with 717 additions and 628 deletions
|
@ -11,16 +11,14 @@ 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"
|
||||||
```
|
```
|
||||||
|
@ -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,19 +42,17 @@ 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"
|
||||||
```
|
```
|
||||||
|
@ -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
|
||||||
```
|
```
|
||||||
|
|
|
@ -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]]
|
||||||
Store = ["my-store-foo-{{ $e }}", "my-store-bar-{{ $e }}"]
|
|
||||||
[TLS.Certificate]
|
|
||||||
CertFile = "/etc/traefik/cert-{{ $e }}.pem"
|
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 }}
|
||||||
|
|
||||||
[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:
|
||||||
|
certificates:
|
||||||
|
- certfile: "/etc/traefik/cert-{{ $e }}.pem"
|
||||||
|
keyfile: "/etc/traefik/cert-{{ $e }}.key"
|
||||||
store:
|
store:
|
||||||
- "my-store-foo-{{ $e }}"
|
- "my-store-foo-{{ $e }}"
|
||||||
- "my-store-bar-{{ $e }}"
|
- "my-store-bar-{{ $e }}"
|
||||||
certificate:
|
|
||||||
certfile: "/etc/traefik/cert-{{ $e }}.pem"
|
|
||||||
keyfile: "/etc/traefik/cert-{{ $e }}.key"
|
|
||||||
{{end}}
|
{{end}}
|
||||||
```
|
```
|
||||||
|
|
|
@ -220,42 +220,40 @@
|
||||||
[[TCP.Services.TCPService0.LoadBalancer.Servers]]
|
[[TCP.Services.TCPService0.LoadBalancer.Servers]]
|
||||||
Address = "foobar"
|
Address = "foobar"
|
||||||
|
|
||||||
[[TLS]]
|
[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]
|
||||||
|
[TLS.Options.TLS0]
|
||||||
[TLSOptions.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]
|
||||||
|
[TLS.Stores.Store0]
|
||||||
[TLSStores.Store0]
|
[TLS.Stores.Store0.DefaultCertificate]
|
||||||
[TLSStores.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"
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -54,6 +54,7 @@ level = "DEBUG"
|
||||||
service = "test"
|
service = "test"
|
||||||
[http.routers.test.tls]
|
[http.routers.test.tls]
|
||||||
|
|
||||||
[tlsStores.default.defaultCertificate]
|
[tls.stores]
|
||||||
|
[tls.stores.default.defaultCertificate]
|
||||||
certFile = "fixtures/acme/ssl/wildcard.crt"
|
certFile = "fixtures/acme/ssl/wildcard.crt"
|
||||||
keyFile = "fixtures/acme/ssl/wildcard.key"
|
keyFile = "fixtures/acme/ssl/wildcard.key"
|
||||||
|
|
|
@ -10,8 +10,7 @@
|
||||||
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"
|
||||||
|
|
|
@ -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 }}"""
|
||||||
|
|
|
@ -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 }}"""
|
||||||
|
|
|
@ -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 }}"""
|
||||||
|
|
|
@ -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 }}"""
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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]
|
[[tls.certificates]]
|
||||||
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/ca1and2.crt"]
|
files = ["fixtures/https/clientca/ca1and2.crt"]
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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]
|
||||||
|
[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"
|
||||||
|
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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]
|
||||||
|
@ -21,10 +21,12 @@ rootCAs = [ """{{ .RootCertContent }}""" ]
|
||||||
|
|
||||||
[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 }}"""
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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{{
|
||||||
|
Certificate: traefiktls.Certificate{
|
||||||
CertFile: traefiktls.FileOrContent("fixtures/https/" + certFileName + ".cert"),
|
CertFile: traefiktls.FileOrContent("fixtures/https/" + certFileName + ".cert"),
|
||||||
KeyFile: traefiktls.FileOrContent("fixtures/https/" + certFileName + ".key"),
|
KeyFile: traefiktls.FileOrContent("fixtures/https/" + certFileName + ".key"),
|
||||||
},
|
|
||||||
}},
|
}},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var confBuffer bytes.Buffer
|
var confBuffer bytes.Buffer
|
||||||
|
|
|
@ -215,22 +215,27 @@ type Message struct {
|
||||||
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"`
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)) {
|
||||||
|
|
|
@ -37,8 +37,7 @@ 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() + `"
|
||||||
`
|
`
|
||||||
|
@ -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 {
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
[[TLS]]
|
[TLS]
|
||||||
[TLS.Certificate]
|
|
||||||
|
[[TLS.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"
|
||||||
[[TLS]]
|
|
||||||
[TLS.Certificate]
|
[[TLS.Certificates]]
|
||||||
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"
|
||||||
[[TLS]]
|
|
||||||
[TLS.Certificate]
|
[[TLS.Certificates]]
|
||||||
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"
|
||||||
[[TLS]]
|
|
||||||
[TLS.Certificate]
|
[[TLS.Certificates]]
|
||||||
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"
|
||||||
|
|
|
@ -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]
|
||||||
|
|
||||||
|
[[TLS.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"
|
||||||
[[TLS]]
|
|
||||||
[TLS.Certificate]
|
[[TLS.Certificates]]
|
||||||
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"
|
||||||
[[TLS]]
|
|
||||||
[TLS.Certificate]
|
[[TLS.Certificates]]
|
||||||
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"
|
||||||
[[TLS]]
|
|
||||||
[TLS.Certificate]
|
[[TLS.Certificates]]
|
||||||
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"
|
||||||
[[TLS]]
|
|
||||||
[TLS.Certificate]
|
[[TLS.Certificates]]
|
||||||
CertFile = "integration/fixtures/https/snitest5.com.cert"
|
CertFile = "integration/fixtures/https/snitest5.com.cert"
|
||||||
KeyFile = "integration/fixtures/https/snitest5.com.key"
|
KeyFile = "integration/fixtures/https/snitest5.com.key"
|
||||||
|
|
|
@ -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]
|
||||||
|
|
||||||
|
[[TLS.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"
|
||||||
[[TLS]]
|
|
||||||
[TLS.Certificate]
|
[[TLS.Certificates]]
|
||||||
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"
|
||||||
[[TLS]]
|
|
||||||
[TLS.Certificate]
|
[[TLS.Certificates]]
|
||||||
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"
|
||||||
[[TLS]]
|
|
||||||
[TLS.Certificate]
|
[[TLS.Certificates]]
|
||||||
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"
|
||||||
|
|
|
@ -1,3 +1,2 @@
|
||||||
|
|
||||||
[log]
|
[log]
|
||||||
level = "DEBUG"
|
level = "DEBUG"
|
||||||
|
|
|
@ -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]
|
||||||
|
|
||||||
|
[[TLS.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"
|
||||||
[[TLS]]
|
|
||||||
[TLS.Certificate]
|
[[TLS.Certificates]]
|
||||||
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"
|
||||||
[[TLS]]
|
|
||||||
[TLS.Certificate]
|
[[TLS.Certificates]]
|
||||||
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"
|
||||||
[[TLS]]
|
|
||||||
[TLS.Certificate]
|
[[TLS.Certificates]]
|
||||||
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"
|
||||||
|
|
|
@ -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]
|
||||||
|
|
||||||
|
[[TLS.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"
|
||||||
[[TLS]]
|
|
||||||
[TLS.Certificate]
|
[[TLS.Certificates]]
|
||||||
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"
|
||||||
[[TLS]]
|
|
||||||
[TLS.Certificate]
|
[[TLS.Certificates]]
|
||||||
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"
|
||||||
[[TLS]]
|
|
||||||
[TLS.Certificate]
|
[[TLS.Certificates]]
|
||||||
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"
|
||||||
|
|
|
@ -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 }}]
|
||||||
|
|
|
@ -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
|
||||||
- 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
|
||||||
|
|
|
@ -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
|
||||||
- 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
|
||||||
- certificate:
|
- certfile: integration/fixtures/https/snitest5.com.cert
|
||||||
certfile: integration/fixtures/https/snitest5.com.cert
|
|
||||||
keyfile: integration/fixtures/https/snitest5.com.key
|
keyfile: integration/fixtures/https/snitest5.com.key
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
@ -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])
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,20 +217,23 @@ 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{
|
Certificate: tls.Certificate{
|
||||||
CertFile: tls.FileOrContent("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----"),
|
CertFile: tls.FileOrContent("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----"),
|
||||||
KeyFile: tls.FileOrContent("-----BEGIN PRIVATE KEY-----\n-----END PRIVATE KEY-----"),
|
KeyFile: tls.FileOrContent("-----BEGIN PRIVATE KEY-----\n-----END PRIVATE KEY-----"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
TCP: &config.TCPConfiguration{
|
TCP: &config.TCPConfiguration{
|
||||||
Routers: map[string]*config.TCPRouter{
|
Routers: map[string]*config.TCPRouter{
|
||||||
"default/test.crd-fdd3e9338e47a45efefc": {
|
"default/test.crd-fdd3e9338e47a45efefc": {
|
||||||
|
@ -295,13 +304,15 @@ 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{
|
||||||
|
Options: map[string]tls.Options{
|
||||||
"default/foo": {
|
"default/foo": {
|
||||||
MinVersion: "VersionTLS12",
|
MinVersion: "VersionTLS12",
|
||||||
CipherSuites: []string{
|
CipherSuites: []string{
|
||||||
|
@ -318,6 +329,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) {
|
||||||
SniStrict: true,
|
SniStrict: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
TCP: &config.TCPConfiguration{
|
TCP: &config.TCPConfiguration{
|
||||||
Routers: map[string]*config.TCPRouter{
|
Routers: map[string]*config.TCPRouter{
|
||||||
"default/test.crd-fdd3e9338e47a45efefc": {
|
"default/test.crd-fdd3e9338e47a45efefc": {
|
||||||
|
@ -357,7 +369,8 @@ 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{
|
||||||
|
Options: map[string]tls.Options{
|
||||||
"myns/foo": {
|
"myns/foo": {
|
||||||
MinVersion: "VersionTLS12",
|
MinVersion: "VersionTLS12",
|
||||||
CipherSuites: []string{
|
CipherSuites: []string{
|
||||||
|
@ -374,6 +387,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) {
|
||||||
SniStrict: true,
|
SniStrict: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
TCP: &config.TCPConfiguration{
|
TCP: &config.TCPConfiguration{
|
||||||
Routers: map[string]*config.TCPRouter{
|
Routers: map[string]*config.TCPRouter{
|
||||||
"default/test.crd-fdd3e9338e47a45efefc": {
|
"default/test.crd-fdd3e9338e47a45efefc": {
|
||||||
|
@ -413,7 +427,8 @@ 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{
|
||||||
|
Options: map[string]tls.Options{
|
||||||
"default/foo": {
|
"default/foo": {
|
||||||
MinVersion: "VersionTLS12",
|
MinVersion: "VersionTLS12",
|
||||||
CipherSuites: []string{
|
CipherSuites: []string{
|
||||||
|
@ -429,6 +444,7 @@ func TestLoadIngressRouteTCPs(t *testing.T) {
|
||||||
SniStrict: true,
|
SniStrict: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
TCP: &config.TCPConfiguration{
|
TCP: &config.TCPConfiguration{
|
||||||
Routers: map[string]*config.TCPRouter{
|
Routers: map[string]*config.TCPRouter{
|
||||||
"default/test.crd-fdd3e9338e47a45efefc": {
|
"default/test.crd-fdd3e9338e47a45efefc": {
|
||||||
|
@ -468,11 +484,13 @@ 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{
|
||||||
|
Options: map[string]tls.Options{
|
||||||
"default/foo": {
|
"default/foo": {
|
||||||
MinVersion: "VersionTLS12",
|
MinVersion: "VersionTLS12",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
TCP: &config.TCPConfiguration{
|
TCP: &config.TCPConfiguration{
|
||||||
Routers: map[string]*config.TCPRouter{
|
Routers: map[string]*config.TCPRouter{
|
||||||
"default/test.crd-fdd3e9338e47a45efefc": {
|
"default/test.crd-fdd3e9338e47a45efefc": {
|
||||||
|
@ -512,11 +530,13 @@ 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{
|
||||||
|
Options: map[string]tls.Options{
|
||||||
"default/foo": {
|
"default/foo": {
|
||||||
MinVersion: "VersionTLS12",
|
MinVersion: "VersionTLS12",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
TCP: &config.TCPConfiguration{
|
TCP: &config.TCPConfiguration{
|
||||||
Routers: map[string]*config.TCPRouter{
|
Routers: map[string]*config.TCPRouter{
|
||||||
"default/test.crd-fdd3e9338e47a45efefc": {
|
"default/test.crd-fdd3e9338e47a45efefc": {
|
||||||
|
@ -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,14 +954,16 @@ 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{
|
Certificate: tls.Certificate{
|
||||||
CertFile: tls.FileOrContent("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----"),
|
CertFile: tls.FileOrContent("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----"),
|
||||||
KeyFile: tls.FileOrContent("-----BEGIN PRIVATE KEY-----\n-----END PRIVATE KEY-----"),
|
KeyFile: tls.FileOrContent("-----BEGIN PRIVATE KEY-----\n-----END PRIVATE KEY-----"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
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{},
|
||||||
|
@ -968,7 +1001,8 @@ 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{
|
||||||
|
Options: map[string]tls.Options{
|
||||||
"default/foo": {
|
"default/foo": {
|
||||||
MinVersion: "VersionTLS12",
|
MinVersion: "VersionTLS12",
|
||||||
CipherSuites: []string{
|
CipherSuites: []string{
|
||||||
|
@ -985,6 +1019,7 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
SniStrict: true,
|
SniStrict: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
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{},
|
||||||
|
@ -1024,7 +1059,8 @@ 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{
|
||||||
|
Options: map[string]tls.Options{
|
||||||
"myns/foo": {
|
"myns/foo": {
|
||||||
MinVersion: "VersionTLS12",
|
MinVersion: "VersionTLS12",
|
||||||
CipherSuites: []string{
|
CipherSuites: []string{
|
||||||
|
@ -1041,6 +1077,7 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
SniStrict: true,
|
SniStrict: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
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{},
|
||||||
|
@ -1080,7 +1117,8 @@ 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{
|
||||||
|
Options: map[string]tls.Options{
|
||||||
"default/foo": {
|
"default/foo": {
|
||||||
MinVersion: "VersionTLS12",
|
MinVersion: "VersionTLS12",
|
||||||
CipherSuites: []string{
|
CipherSuites: []string{
|
||||||
|
@ -1096,6 +1134,7 @@ func TestLoadIngressRoutes(t *testing.T) {
|
||||||
SniStrict: true,
|
SniStrict: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
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{},
|
||||||
|
@ -1135,11 +1174,13 @@ 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{
|
||||||
|
Options: map[string]tls.Options{
|
||||||
"default/foo": {
|
"default/foo": {
|
||||||
MinVersion: "VersionTLS12",
|
MinVersion: "VersionTLS12",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
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{},
|
||||||
|
@ -1179,11 +1220,13 @@ 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{
|
||||||
|
Options: map[string]tls.Options{
|
||||||
"default/foo": {
|
"default/foo": {
|
||||||
MinVersion: "VersionTLS12",
|
MinVersion: "VersionTLS12",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
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{},
|
||||||
|
@ -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{},
|
||||||
|
|
|
@ -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])
|
||||||
}
|
}
|
||||||
|
|
|
@ -702,9 +702,10 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
TLS: []*tls.Configuration{
|
TLS: &config.TLSConfiguration{
|
||||||
|
Certificates: []*tls.CertAndStores{
|
||||||
{
|
{
|
||||||
Certificate: &tls.Certificate{
|
Certificate: tls.Certificate{
|
||||||
CertFile: tls.FileOrContent("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----"),
|
CertFile: tls.FileOrContent("-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----"),
|
||||||
KeyFile: tls.FileOrContent("-----BEGIN PRIVATE KEY-----\n-----END PRIVATE KEY-----"),
|
KeyFile: tls.FileOrContent("-----BEGIN PRIVATE KEY-----\n-----END PRIVATE KEY-----"),
|
||||||
},
|
},
|
||||||
|
@ -712,6 +713,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
desc: "Ingress with a basic rule on one path with https (port == 443)",
|
desc: "Ingress with a basic rule on one path with https (port == 443)",
|
||||||
expected: &config.Configuration{
|
expected: &config.Configuration{
|
||||||
|
@ -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 != "" {
|
||||||
|
|
|
@ -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 key, store := range configuration.TLS.Stores {
|
||||||
|
conf.TLS.Stores[key] = store
|
||||||
}
|
}
|
||||||
|
|
||||||
for tlsOptionsName, config := range configuration.TLSOptions {
|
for tlsOptionsName, options := range configuration.TLS.Options {
|
||||||
if tlsOptionsName != "default" {
|
if tlsOptionsName != "default" {
|
||||||
tlsOptionsName = internal.MakeQualifiedName(provider, tlsOptionsName)
|
tlsOptionsName = internal.MakeQualifiedName(provider, tlsOptionsName)
|
||||||
} else {
|
} else {
|
||||||
defaultTLSOptionProviders = append(defaultTLSOptionProviders, provider)
|
defaultTLSOptionProviders = append(defaultTLSOptionProviders, provider)
|
||||||
}
|
}
|
||||||
|
|
||||||
conf.TLSOptions[tlsOptionsName] = config
|
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
|
||||||
|
|
|
@ -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{
|
||||||
|
Options: map[string]tls.Options{
|
||||||
"foo": {
|
"foo": {
|
||||||
MinVersion: "VersionTLS12",
|
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{
|
||||||
|
Options: map[string]tls.Options{
|
||||||
"foo": {
|
"foo": {
|
||||||
MinVersion: "VersionTLS13",
|
MinVersion: "VersionTLS13",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
"provider-2": &config.Configuration{
|
"provider-2": &config.Configuration{
|
||||||
TLSOptions: map[string]tls.TLS{
|
TLS: &config.TLSConfiguration{
|
||||||
|
Options: map[string]tls.Options{
|
||||||
"foo": {
|
"foo": {
|
||||||
MinVersion: "VersionTLS12",
|
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,7 +179,8 @@ 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{
|
||||||
|
Options: map[string]tls.Options{
|
||||||
"foo": {
|
"foo": {
|
||||||
MinVersion: "VersionTLS13",
|
MinVersion: "VersionTLS13",
|
||||||
},
|
},
|
||||||
|
@ -182,15 +189,18 @@ func TestAggregator_tlsoptions(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
"provider-2": &config.Configuration{
|
"provider-2": &config.Configuration{
|
||||||
TLSOptions: map[string]tls.TLS{
|
TLS: &config.TLSConfiguration{
|
||||||
|
Options: map[string]tls.Options{
|
||||||
"foo": {
|
"foo": {
|
||||||
MinVersion: "VersionTLS12",
|
MinVersion: "VersionTLS12",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expected: map[string]tls.TLS{
|
},
|
||||||
|
expected: map[string]tls.Options{
|
||||||
"default": {
|
"default": {
|
||||||
MinVersion: "VersionTLS11",
|
MinVersion: "VersionTLS11",
|
||||||
},
|
},
|
||||||
|
@ -206,7 +216,8 @@ 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{
|
||||||
|
Options: map[string]tls.Options{
|
||||||
"foo": {
|
"foo": {
|
||||||
MinVersion: "VersionTLS12",
|
MinVersion: "VersionTLS12",
|
||||||
},
|
},
|
||||||
|
@ -215,8 +226,10 @@ func TestAggregator_tlsoptions(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
"provider-2": &config.Configuration{
|
"provider-2": &config.Configuration{
|
||||||
TLSOptions: map[string]tls.TLS{
|
TLS: &config.TLSConfiguration{
|
||||||
|
Options: map[string]tls.Options{
|
||||||
"foo": {
|
"foo": {
|
||||||
MinVersion: "VersionTLS13",
|
MinVersion: "VersionTLS13",
|
||||||
},
|
},
|
||||||
|
@ -226,7 +239,8 @@ func TestAggregator_tlsoptions(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
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{
|
||||||
|
Options: map[string]tls.Options{
|
||||||
"foo": {
|
"foo": {
|
||||||
MinVersion: "VersionTLS12",
|
MinVersion: "VersionTLS12",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
"provider-2": &config.Configuration{
|
"provider-2": &config.Configuration{
|
||||||
TLSOptions: map[string]tls.TLS{
|
TLS: &config.TLSConfiguration{
|
||||||
|
Options: map[string]tls.Options{
|
||||||
"foo": {
|
"foo": {
|
||||||
MinVersion: "VersionTLS13",
|
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)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -46,15 +46,12 @@ f9Oeos0UUothgiDktdQHxdNEwLjQf7lJJBzV+5OtwswCWA==
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestTLSInStore(t *testing.T) {
|
func TestTLSInStore(t *testing.T) {
|
||||||
dynamicConfigs :=
|
dynamicConfigs := []*CertAndStores{{
|
||||||
[]*Configuration{
|
Certificate: Certificate{
|
||||||
{
|
|
||||||
Certificate: &Certificate{
|
|
||||||
CertFile: localhostCert,
|
CertFile: localhostCert,
|
||||||
KeyFile: localhostKey,
|
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{
|
||||||
{
|
|
||||||
Certificate: &Certificate{
|
|
||||||
CertFile: localhostCert,
|
CertFile: localhostCert,
|
||||||
KeyFile: localhostKey,
|
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{
|
||||||
{
|
|
||||||
Certificate: &Certificate{
|
|
||||||
CertFile: localhostCert,
|
CertFile: localhostCert,
|
||||||
KeyFile: localhostKey,
|
KeyFile: localhostKey,
|
||||||
},
|
},
|
||||||
},
|
}}
|
||||||
}
|
|
||||||
tlsConfigs := map[string]TLS{
|
tlsConfigs := map[string]Options{
|
||||||
"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)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue