jetstack / kube-lego

DEPRECATED: Automatically request certificates for Kubernetes Ingress resources from Let's Encrypt
Apache License 2.0
2.16k stars 267 forks source link

Creating ingress with allow-http:false fails the reachability test #218

Closed ahmetb closed 7 years ago

ahmetb commented 7 years ago

When I create an ingress with kubernetes.io/ingress.allow-http: "false", it fails with

time="2017-06-28T05:05:44Z" level=debug msg="testing reachability of http://b.alp.im/.well-known/acme-challenge/_selftest" context=acme domain=b.alp.im
time="2017-06-28T05:05:44Z" level=debug msg="error while authorizing: reachability test failed: wrong status code '404'" context=acme domain=b.alp.im
time="2017-06-28T05:05:51Z" level=debug msg="testing reachability of http://b.alp.im/.well-known/acme-challenge/_selftest" context=acme domain=b.alp.im
time="2017-06-28T05:05:51Z" level=debug msg="error while authorizing: reachability test failed: wrong status code '404'" context=acme domain=b.alp.im
...

I am guessing simply because it's querying http:// instead of https://.

(kube-lego v0.1.4 , kubernetes 1.6.4 on GKE)

thockin commented 7 years ago

How do we expect to solve this? You are telling it to not offer HTTP, but don't have a cert yet...

ahmetb commented 7 years ago

@thockin ACME HTTP-01 challenge does not require a valid TLS certificate to validate the challenge.

See ACME spect draft 0 section 7.1 (page 38) step 3:

   3.  Dereference the URI using an HTTP or HTTPS GET request.  If using
       HTTPS, the ACME server MUST ignore the certificate provided by
       the HTTPS server.

or TLS-SNI-02 challenge can also be used to serve a self-signed certificate with a SAN containing the challenge token.

munnerz commented 7 years ago

So as the annotation in question is one that is specific to the nginx ingress controller, and as the annotation is also one that is enforced by (and only by) the nginx ingress controller, I believe it is outside the scope (and also not possible!) for kube-lego to support (without potentially comprising these security considerations).

If the user specifically disallows HTTP Ingress to your services, I think it makes sense to also disallow HTTP based challenges from letsencrypt, despite the potential UX difficulty that users may face.

I'm actually unsure off the top of my head if we support TLS based challenges. If we do, I'd recommend that is used instead here! On Fri, 30 Jun 2017 at 00:15, Ahmet Alp Balkan notifications@github.com wrote:

@thockin https://github.com/thockin ACME HTTP-01 challenge does not require a valid TLS certificate to validate the challenge.

See ACME spect draft section 7.2 https://tools.ietf.org/html/draft-ietf-acme-acme-01#section-7.2 (page 38) step 3:

  1. Dereference the URI using an HTTP or HTTPS GET request. If using HTTPS, the ACME server MUST ignore the certificate provided by the HTTPS server.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/jetstack/kube-lego/issues/218#issuecomment-312133042, or mute the thread https://github.com/notifications/unsubscribe-auth/AAMbP5PoljLAu_qBn6tEfwJCbqB0iXk8ks5sJDARgaJpZM4OHf04 .

munnerz commented 7 years ago

However, as @thockin says, if there's a potential UX/use case that fits in the general case then it's definitely something to be considered! On Fri, 30 Jun 2017 at 00:40, James Munnelly james@munnelly.eu wrote:

So as the annotation in question is one that is specific to the nginx ingress controller, and as the annotation is also one that is enforced by (and only by) the nginx ingress controller, I believe it is outside the scope (and also not possible!) for kube-lego to support (without potentially comprising these security considerations).

If the user specifically disallows HTTP Ingress to your services, I think it makes sense to also disallow HTTP based challenges from letsencrypt, despite the potential UX difficulty that users may face.

I'm actually unsure off the top of my head if we support TLS based challenges. If we do, I'd recommend that is used instead here! On Fri, 30 Jun 2017 at 00:15, Ahmet Alp Balkan notifications@github.com wrote:

@thockin https://github.com/thockin ACME HTTP-01 challenge does not require a valid TLS certificate to validate the challenge.

See ACME spect draft section 7.2 https://tools.ietf.org/html/draft-ietf-acme-acme-01#section-7.2 (page 38) step 3:

  1. Dereference the URI using an HTTP or HTTPS GET request. If using HTTPS, the ACME server MUST ignore the certificate provided by the HTTPS server.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/jetstack/kube-lego/issues/218#issuecomment-312133042, or mute the thread https://github.com/notifications/unsubscribe-auth/AAMbP5PoljLAu_qBn6tEfwJCbqB0iXk8ks5sJDARgaJpZM4OHf04 .

ahmetb commented 7 years ago

the annotation is also one that is enforced by (and only by) the nginx ingress controller

GCE ingress controller supports this annotation, too. So nginx is not the only one.

If the user specifically disallows HTTP Ingress to your services, I think it makes sense to also disallow HTTP based challenges from letsencrypt

HTTP-01 challenge still uses HTTPS with a self-signed certificate, it just does not validate the chain. Self-signed certificates still prevent attackers from intercepting the challenge/verification flow. Also, if the ACME spec does not discourage it, I tend to think they see it as secure enough.

if there's a potential UX/use case

Yes. The majority websites that serve HTTPS redirect all HTTP traffic to HTTPS. Even my personal website works like that. If I cannot use this annotation with kube-lego directly, it's a major inconvenience.

aledbf commented 7 years ago

GCE ingress controller supports this annotation, too. So nginx is not the only one.

nginx (from kubernetes/ingress) does not supports this annotation.

ahmetb commented 7 years ago

thanks for correcting @aledbf. I just checked it looks like nginx provides redirection for non-HTTPs through the ingress.kubernetes.io/ssl-redirect: "true" annotation.

munnerz commented 7 years ago

Thanks @aledbf - it's not one I've used myself so wasn't sure!

So we could potentially work something out for this - I'd see it as follows:

  1. kube-lego needs to detect and understand all these different ingress annotations

  2. kube-lego will need to generate a self-signed certificate (if one does not already exist) and place that in the specified Secret resource so that the ingress controller can detect it and begin using it.

  3. Verification happens (via HTTP-01), and kube-lego then updates that certificate resource with the new one. If this is a renewal, we shouldn't need step 2 as there is already a (potentially invalid) certificate in place.

What other annotations are other ingress controllers using here? I'm reluctant to keep on adding in controller-specific workarounds. As part of the move to cert-manager, we're hoping to reduce the number of these so that there's a consistent experience regardless of controller, and to ensure that all features work irrespective of controller! Some standardisation of Ingress spec would be great at some point!

munnerz commented 7 years ago

I'm going to close this in favour of #173 - there's been some good conversation here around a solution, but I'd like to consolidate all the issues we have springing up.