Skip to content

Commit

Permalink
kubernetes: document the TLS with ACME case
Browse files Browse the repository at this point in the history
When we did the kubernetes crd implementation, we forgot to test the
case for when one wants TLS, but handled with Let's Encrypt, i.e.
without having to provide a Kubernetes Secret. We assumed it would be
enough to provide (in YAML) a tls object with no field set, which would
get us a non-nil IngressRouteSpec.TLS, allowing us to use
IngressRouteSpec.TLS as the sentinel for whether TLS should be enabled.

However, as IngressRouteSpec.TLS is a pointer, a tls object with no
fields set will actually result in IngressRouteSpec.TLS being nil. This
means at least one of the fields of the YAML tls object must exist.
Therefore, we now use the secretName field value (for now, as it is
the only field anyway) as the sentinel for whether Let's Encrypt should
be used.

This PR documents the above behavior, and adds a unit test for it.

In addition, this PR fixes a related bug in the ACME provider: when a
router is not configured with TLS enabled, the ACME provider does not
try anymore to generate a (useless) certificate for the corresponding
domain.
  • Loading branch information
mpl authored and traefiker committed Mar 26, 2019
1 parent a0e2f47 commit b036a94
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 1 deletion.
6 changes: 6 additions & 0 deletions pkg/provider/acme/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,9 @@ func (p *Provider) watchNewDomains(ctx context.Context) {
case config := <-p.configFromListenerChan:
if config.TCP != nil {
for routerName, route := range config.TCP.Routers {
if route.TLS == nil {
continue
}
ctxRouter := log.With(ctx, log.Str(log.RouterName, routerName), log.Str(log.Rule, route.Rule))

domains, err := rules.ParseHostSNI(route.Rule)
Expand All @@ -395,6 +398,9 @@ func (p *Provider) watchNewDomains(ctx context.Context) {
}

for routerName, route := range config.HTTP.Routers {
if route.TLS == nil {
continue
}
ctxRouter := log.With(ctx, log.Str(log.RouterName, routerName), log.Str(log.Rule, route.Rule))

domains, err := rules.ParseDomains(route.Rule)
Expand Down
20 changes: 20 additions & 0 deletions pkg/provider/kubernetes/crd/fixtures/with_tls_acme.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: test.crd
namespace: default

spec:
entryPoints:
- web

routes:
- match: Host(`foo.com`) && PathPrefix(`/bar`)
kind: Rule
priority: 12
services:
- name: whoami
port: 80

tls:
secretName:
37 changes: 37 additions & 0 deletions pkg/provider/kubernetes/crd/kubernetes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,43 @@ func TestLoadIngressRoutes(t *testing.T) {
},
},
},
{
desc: "TLS with ACME",
paths: []string{"services.yml", "with_tls_acme.yml"},
expected: &config.Configuration{
TCP: &config.TCPConfiguration{},
HTTP: &config.HTTPConfiguration{
Routers: map[string]*config.Router{
"default/test.crd-6b204d94623b3df4370c": {
EntryPoints: []string{"web"},
Service: "default/test.crd-6b204d94623b3df4370c",
Rule: "Host(`foo.com`) && PathPrefix(`/bar`)",
Priority: 12,
TLS: &config.RouterTLSConfig{},
},
},
Middlewares: map[string]*config.Middleware{},
Services: map[string]*config.Service{
"default/test.crd-6b204d94623b3df4370c": {
LoadBalancer: &config.LoadBalancerService{
Servers: []config.Server{
{
URL: "http://10.10.0.1:80",
Weight: 1,
},
{
URL: "http://10.10.0.2:80",
Weight: 1,
},
},
Method: "wrr",
PassHostHeader: true,
},
},
},
},
},
},
{
desc: "Simple Ingress Route, defaulting to https for servers",
paths: []string{"services.yml", "with_https_default.yml"},
Expand Down
5 changes: 4 additions & 1 deletion pkg/provider/kubernetes/crd/traefik/v1alpha1/ingressroute.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,11 @@ type Route struct {
Middlewares []MiddlewareRef `json:"middlewares"`
}

// TLS contains the TLS certificates configuration of the routes.
// TLS contains the TLS certificates configuration of the routes. To enable
// Let's Encrypt, set a SecretName with an empty value.
type TLS struct {
// SecretName is the name of the referenced Kubernetes Secret to specify the
// certificate details.
SecretName string `json:"secretName"`
// TODO MinimumProtocolVersion string `json:"minimumProtocolVersion,omitempty"`
}
Expand Down

0 comments on commit b036a94

Please sign in to comment.