Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Define TLS options on the Router configuration for Kubernetes #4973

Merged
merged 11 commits into from
Jun 21, 2019
32 changes: 32 additions & 0 deletions docs/content/middlewares/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,38 @@ labels:
- "traefik.http.middlewares.foo-add-prefix.addprefix.prefix=/foo"
```

```toml tab="File"
[tlsOptions]
[tlsOptions.default]
minVersion = "VersionTLS12"
```

```yaml tab="Kubernetes"
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: tlsoptions.traefik.containo.us

spec:
group: traefik.containo.us
version: v1alpha1
names:
kind: TLSOption
plural: tlsoptions
singular: tlsoption
scope: Namespaced

---
apiVersion: traefik.containo.us/v1alpha1
kind: TLSOption
metadata:
name: mytlsoption
namespace: default

spec:
minversion: VersionTLS12
```

```toml tab="File"
# As Toml Configuration File
[providers]
Expand Down
13 changes: 13 additions & 0 deletions docs/content/providers/crd_tls_option.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: tlsoptions.traefik.containo.us

spec:
group: traefik.containo.us
version: v1alpha1
names:
kind: TLSOption
plural: tlsoptions
singular: tlsoption
scope: Namespaced
45 changes: 45 additions & 0 deletions docs/content/providers/kubernetes-crd.md
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,51 @@ spec:

More information about available middlewares in the dedicated [middlewares section](../middlewares/overview.md).

### Traefik TLS Option Definition

Additionally, to allow for the use of tls options in an IngressRoute, we defined the CRD below for the TLSOption kind.
More information about TLS Options is available in the dedicated [TLS Configuration Options](../../https/tls/#tls-options).

```yaml
--8<-- "content/providers/crd_tls_option.yml"
```

Once the TLSOption kind has been registered with the Kubernetes cluster or defined in the File Provider, it can then be used in IngressRoute definitions, such as:

```yaml
apiVersion: traefik.containo.us/v1alpha1
kind: TLSOption
metadata:
name: mytlsoption
namespace: default

spec:
minversion: VersionTLS12

---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: ingressroutebar

spec:
entryPoints:
- web
routes:
- match: Host(`bar.com`) && PathPrefix(`/stripit`)
kind: Rule
services:
- name: whoami
port: 80
tls:
options:
name: mytlsoption
namespace: default
```

!!! note "TLS Option reference and namespace"
If the optional `namespace` attribute is not set, the configuration will be applied with the namespace of the IngressRoute.

### TLS

To allow for TLS, we made use of the `Secret` kind, as it was already defined, and it can be directly used in an `IngressRoute`:
Expand Down
21 changes: 21 additions & 0 deletions docs/content/reference/dynamic-configuration/kubernetes-crd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,21 @@ spec:
singular: middleware
scope: Namespaced

---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: tlsoptions.traefik.containo.us

spec:
group: traefik.containo.us
version: v1alpha1
names:
kind: TLSOption
plural: tlsoptions
singular: tlsoption
scope: Namespaced

---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
Expand Down Expand Up @@ -85,6 +100,9 @@ spec:
# use an empty tls object for TLS with Let's Encrypt
tls:
secretName: supersecret
options:
name: myTLSOption
namespace: default

---
apiVersion: traefik.containo.us/v1alpha1
Expand All @@ -104,3 +122,6 @@ spec:
tls:
secretName: foosecret
passthrough: false
options:
name: myTLSOption
namespace: default
1 change: 0 additions & 1 deletion integration/fixtures/https/https_tls_options.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ level = "DEBUG"
[[http.services.service2.LoadBalancer.Servers]]
URL = "http://127.0.0.1:9020"


[[tls]]
[tls.certificate]
certFile = "fixtures/https/snitest.com.cert"
Expand Down
15 changes: 15 additions & 0 deletions integration/fixtures/k8s/01-crd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,18 @@ spec:
plural: ingressroutetcps
singular: ingressroutetcp
scope: Namespaced

---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: tlsoptions.traefik.containo.us

spec:
group: traefik.containo.us
version: v1alpha1
names:
kind: TLSOption
plural: tlsoptions
singular: tlsoption
scope: Namespaced
4 changes: 4 additions & 0 deletions integration/fixtures/k8s/03-ingressroute.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,7 @@ spec:
services:
- name: whoami
port: 80

tls:
options:
name: mytlsoption
12 changes: 12 additions & 0 deletions integration/fixtures/k8s/03-tlsoption.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
apiVersion: traefik.containo.us/v1alpha1
kind: TLSOption
metadata:
name: mytlsoption
namespace: default

spec:
minversion: VersionTLS12
snistrict: true
ciphersuites:
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_RSA_WITH_AES_256_GCM_SHA384
3 changes: 3 additions & 0 deletions integration/fixtures/k8s/05-ingressroutetcp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,6 @@ spec:
services:
- name: whoamitcp
port: 8080
tls:
options:
name: mytlsoption
2 changes: 1 addition & 1 deletion integration/https_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ func (s *HTTPSSuite) TestWithTLSOptions(c *check.C) {
c.Assert(err.Error(), checker.Contains, "protocol version not supported")

// with unknown tls option
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1*time.Second, try.BodyContains("unknown TLS options: unknown"))
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1*time.Second, try.BodyContains("unknown TLS options: unknown@file"))
c.Assert(err, checker.IsNil)
}

Expand Down
31 changes: 19 additions & 12 deletions integration/testdata/rawdata-crd.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
],
"service": "default/test-crd-6b204d94623b3df4370c",
"rule": "Host(`foo.com`) \u0026\u0026 PathPrefix(`/bar`)",
"priority": 12
"priority": 12,
"tls": {
"options": "default/mytlsoption"
}
},
"default/test2-crd-23c7f4c450289ee29016@kubernetescrd": {
"entryPoints": [
Expand Down Expand Up @@ -36,10 +39,10 @@
"loadbalancer": {
"servers": [
{
"url": "http://10.42.0.4:80"
"url": "http://10.42.0.2:80"
},
{
"url": "http://10.42.0.5:80"
"url": "http://10.42.0.6:80"
}
],
"passHostHeader": true
Expand All @@ -48,18 +51,18 @@
"default/test-crd-6b204d94623b3df4370c@kubernetescrd"
],
"serverStatus": {
"http://10.42.0.4:80": "UP",
"http://10.42.0.5:80": "UP"
"http://10.42.0.2:80": "UP",
"http://10.42.0.6:80": "UP"
}
},
"default/test2-crd-23c7f4c450289ee29016@kubernetescrd": {
"loadbalancer": {
"servers": [
{
"url": "http://10.42.0.4:80"
"url": "http://10.42.0.2:80"
},
{
"url": "http://10.42.0.5:80"
"url": "http://10.42.0.6:80"
}
],
"passHostHeader": true
Expand All @@ -68,8 +71,8 @@
"default/test2-crd-23c7f4c450289ee29016@kubernetescrd"
],
"serverStatus": {
"http://10.42.0.4:80": "UP",
"http://10.42.0.5:80": "UP"
"http://10.42.0.2:80": "UP",
"http://10.42.0.6:80": "UP"
}
}
},
Expand All @@ -79,18 +82,22 @@
"footcp"
],
"service": "default/test3-crd-673acf455cb2dab0b43a",
"rule": "HostSNI(`*`)"
"rule": "HostSNI(`*`)",
"tls": {
"passthrough": false,
"options": "default/mytlsoption"
}
}
},
"tcpServices": {
"default/test3-crd-673acf455cb2dab0b43a@kubernetescrd": {
"loadbalancer": {
"servers": [
{
"address": "10.42.0.2:8080"
"address": "10.42.0.3:8080"
},
{
"address": "10.42.0.3:8080"
"address": "10.42.0.4:8080"
}
]
},
Expand Down
17 changes: 17 additions & 0 deletions pkg/provider/kubernetes/crd/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ type Client interface {
GetIngressRoutes() []*v1alpha1.IngressRoute
GetIngressRouteTCPs() []*v1alpha1.IngressRouteTCP
GetMiddlewares() []*v1alpha1.Middleware
GetTLSOptions() []*v1alpha1.TLSOption

GetIngresses() []*extensionsv1beta1.Ingress
GetService(namespace, name string) (*corev1.Service, bool, error)
Expand Down Expand Up @@ -158,6 +159,7 @@ func (c *clientWrapper) WatchAll(namespaces []string, stopCh <-chan struct{}) (<
factoryCrd.Traefik().V1alpha1().IngressRoutes().Informer().AddEventHandler(eventHandler)
factoryCrd.Traefik().V1alpha1().Middlewares().Informer().AddEventHandler(eventHandler)
factoryCrd.Traefik().V1alpha1().IngressRouteTCPs().Informer().AddEventHandler(eventHandler)
factoryCrd.Traefik().V1alpha1().TLSOptions().Informer().AddEventHandler(eventHandler)

factoryKube := informers.NewFilteredSharedInformerFactory(c.csKube, resyncPeriod, ns, nil)
factoryKube.Extensions().V1beta1().Ingresses().Informer().AddEventHandler(eventHandler)
Expand Down Expand Up @@ -241,6 +243,21 @@ func (c *clientWrapper) GetMiddlewares() []*v1alpha1.Middleware {
return result
}

// GetTLSOptions
func (c *clientWrapper) GetTLSOptions() []*v1alpha1.TLSOption {
var result []*v1alpha1.TLSOption

for ns, factory := range c.factoriesCrd {
options, err := factory.Traefik().V1alpha1().TLSOptions().Lister().List(c.labelSelector)
if err != nil {
log.Errorf("Failed to list tls options in namespace %s: %s", ns, err)
}
result = append(result, options...)
}

return result
}

// GetIngresses returns all Ingresses for observed namespaces in the cluster.
func (c *clientWrapper) GetIngresses() []*extensionsv1beta1.Ingress {
var result []*extensionsv1beta1.Ingress
Expand Down
17 changes: 17 additions & 0 deletions pkg/provider/kubernetes/crd/client_mock_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ type clientMock struct {
ingressRoutes []*v1alpha1.IngressRoute
ingressRouteTCPs []*v1alpha1.IngressRouteTCP
middlewares []*v1alpha1.Middleware
tlsOptions []*v1alpha1.TLSOption

watchChan chan interface{}
}
Expand All @@ -63,6 +64,8 @@ func newClientMock(paths ...string) clientMock {
c.ingressRouteTCPs = append(c.ingressRouteTCPs, o)
case *v1alpha1.Middleware:
c.middlewares = append(c.middlewares, o)
case *v1alpha1.TLSOption:
c.tlsOptions = append(c.tlsOptions, o)
case *v1beta12.Ingress:
c.ingresses = append(c.ingresses, o)
case *corev1.Secret:
Expand All @@ -88,6 +91,20 @@ func (c clientMock) GetMiddlewares() []*v1alpha1.Middleware {
return c.middlewares
}

func (c clientMock) GetTLSOptions() []*v1alpha1.TLSOption {
return c.tlsOptions
}

func (c clientMock) GetTLSOption(namespace, name string) (*v1alpha1.TLSOption, bool, error) {
for _, option := range c.tlsOptions {
if option.Namespace == namespace && option.Name == name {
return option, true, nil
}
}

return nil, false, nil
}

func (c clientMock) GetIngresses() []*extensionsv1beta1.Ingress {
return c.ingresses
}
Expand Down