54

Is there a way to force an SSL upgrade for incoming connections on the ingress load-balancer? Or if that is not possible with, can I disable port :80? I haven't found a good documentation pages that outlines such an option in the YAML file. Thanks a lot in advance!

Jonas
  • 97,987
  • 90
  • 271
  • 355
Simon Heinzle
  • 925
  • 1
  • 7
  • 17
  • What do you mean by "SSL upgrade for incoming connections". Could you please elaborate? Also, could you please elaborate on what you are trying to do? – Madhusudan.C.S May 05 '16 at 19:50
  • 1
    I would like to redirect connections to http port 80 towards https port 443, ideally at the Kubernetes Ingress load balancer - if that is at all possible. If not, what would be the best strategy - load balance both 80 and 443, and put a haproxy behind the LB to do the forward? – Simon Heinzle May 07 '16 at 09:48

9 Answers9

58

https://github.com/kubernetes/ingress-gce#frontend-https

You can block HTTP through the annotation kubernetes.io/ingress.allow-http: "false" or redirect HTTP to HTTPS by specifying a custom backend. Unfortunately GCE doesn't handle redirection or rewriting at the L7 layer directly for you, yet. (see https://github.com/kubernetes/ingress-gce#ingress-cannot-redirect-http-to-https)

Update: GCP now handles redirection rules for load balancers, including HTTP to HTTPS. There doesn't appear to be a method to create these through Kubernetes YAML yet.

Cyral
  • 12,859
  • 5
  • 40
  • 78
Prashanth B
  • 3,981
  • 17
  • 13
  • Thanks a lot, also for the link! Is redirection a planned feature? – Simon Heinzle May 14 '16 at 15:57
  • 1
    Is this the reason why if I return 301 in my nginx HTTP server block to HTTPS it results in a 301 loop. – Bcf Ant Mar 15 '17 at 14:19
  • 1
    Are there any resources available that would elaborate on how to actually use a custom backend to perform the redirection? Or could extend your answer on that part? My app is not running on Apache/nginx so adding such a service means an additional piece in the puzzle, and I can't figure out how to route things correctly. – zagrimsan Apr 05 '18 at 08:13
  • @zagrimsan https://github.com/kubernetes/contrib/blob/21530358618d6122178963240139cb0e106064a4/ingress/echoheaders-redirect/nginx.conf#L20. That entire example should just work, send a request with "X-Forwarded-Proto: http" to :80 – Prashanth B Apr 06 '18 at 10:33
  • That example does work ok, I've tried it out. My point was that if the application is not based on a web server that can be nicely configured to do such a redirection, there surely is also a way to plug in a separate minimal web server Pod in the setup so that it takes care of fixing the lack of native support for the redirection. This morning I came to think of NodePorts etc (something I haven't really yet fully grasped about K8s) and it might be that I figured out how to do exactly what I need... but I couldn't test it fully yet. If I manage to solve this I'll link the answer here, too. – zagrimsan Apr 06 '18 at 13:03
  • 1
    I was able to figure out the solution for my own needs (and figure out how to plug in the extra Pod), posted it in https://stackoverflow.com/a/49750913/2745865 – zagrimsan Apr 10 '18 at 10:11
  • 1
    via this article https://www.digitalocean.com/community/questions/best-way-to-configure-nginx-ssl-force-http-to-redirect-to-https-force-www-to-non-www-on-serverpilot-free-plan-by-using-nginx-configuration-file-only I understand how to redirect HTTP to HTTPs using nginx. But nginx conf ask for ssl certificate file location. In my case I am using GCP managed certificate. I have no idea what will nginx conf file will have with GCP managed certificates. – Savaratkar Apr 26 '19 at 12:15
  • 1
    There is now a way to support redirect in k8s yaml via FrontendConfig: https://cloud.google.com/kubernetes-engine/docs/how-to/ingress-features#https_redirect – Andrej Palicka Jan 09 '21 at 17:12
16

The annotation has changed:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test
  annotations:
    kubernetes.io/ingress.allow-http: "false"
spec:
...

Here is the annotation change PR: https://github.com/kubernetes/contrib/pull/1462/files

mlazarov
  • 383
  • 2
  • 6
  • checked recently and annotation remains the same but the latest version is now {apiVersion: networking.k8s.io/v1beta1} – CarlosJ May 14 '20 at 21:39
14

If you are not bound to the GCLB Ingress Controller you could have a look at the Nginx Ingress Controller. This controller is different to the builtin one in multiple ways. First and foremost you need to deploy and manage one by yourself. But if you are willing to do so, you get the benefit of not depending on the GCE LB (20$/month) and getting support for IPv6/websockets.

The documentation states:

By default the controller redirects (301) to HTTPS if TLS is enabled for that ingress . If you want to disable that behaviour globally, you can use ssl-redirect: "false" in the NGINX config map.

The recently released 0.9.0-beta.3 comes with an additional annotation for explicitly enforcing this redirect:

Force redirect to SSL using the annotation ingress.kubernetes.io/force-ssl-redirect

Huds0nHawk
  • 1,443
  • 15
  • 25
Fabian Dörk
  • 313
  • 3
  • 9
  • for nginx ingress controller I tried `nginx.ingress.kubernetes.io/force-ssl-redirect: "true"` and its working. For complete list of annotation please visit https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/annotations.md – Balkrishna Apr 03 '18 at 05:26
  • still really feels like the best answer here – Randy L Jul 27 '18 at 19:00
  • 1
    Updated annotations documentation link: https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/nginx-configuration/annotations.md – Archonic Aug 01 '18 at 17:07
  • 1
    GCE Load Balancers support WebSockets, and have done so since May 2018 at least - can you adjust this answer? – Cameron Aug 05 '19 at 19:24
9

Google has responded to our requests and is testing HTTP->HTTPS SSL redirection on their load balancers. Their latest answer said it should be in Alpha sometime before the end of January 2020.

Their comment:

Thank you for your patience on this issue. The feature is currently in testing and we expect to enter Alpha phase before the end of January. Our PM team will have an announcement with more details as we get closer to the Alpha launch.

My fingers are crossed that we'll have a straightforward solution to this very common feature in the near future.


UPDATE (April 2020):

HTTP(S) rewrites is now a Generally Available feature. It's still a bit rough around the edges and does not work out-of-the-box with the GCE Ingress Controller unfortunately. But time will tell and hopefully a native solution will appear.

Michal
  • 14,455
  • 9
  • 68
  • 97
Josh
  • 2,223
  • 1
  • 25
  • 18
  • 3
    Literally, 5 YEARS LATER. – Michal Feb 06 '20 at 14:27
  • 1
    Nevermind: `Unfortunately that will push our Alpha date out a number of weeks.` – Michal Feb 06 '20 at 14:27
  • 2
    @Michal It is finally out: https://issuetracker.google.com/issues/35904733#comment95 However, I'm sure it will be much longer before there is a config we can use in Kubernetes YAML to set this automatically... – Cyral Apr 14 '20 at 20:29
  • Thanks @Cyral I'll update Josh's answer. Feel free to roll back if unhappy. – Michal Apr 24 '20 at 10:22
  • Is it now available in GCE Ingress Controller? – Guru May 20 '20 at 09:01
  • It is available now. Search for "redirects" on [this page](https://cloud.google.com/load-balancing/docs/features#routing_and_traffic_management) – Josh May 21 '20 at 03:21
5

This was already correctly answered by a comment on the accepted answer. But since the comment is buried I missed it several times.

As of GKE version 1.18.10-gke.600 you can add a k8s frontend config to redirect from http to https.

https://cloud.google.com/kubernetes-engine/docs/how-to/ingress-features#https_redirect

apiVersion: networking.gke.io/v1beta1
kind: FrontendConfig
metadata:
  name: ssl-redirect
spec:
  redirectToHttps:
    enabled: true

# add below to ingress
# metadata:
#   annotations:
#     networking.gke.io/v1beta1.FrontendConfig: ssl-redirect
George B
  • 131
  • 2
  • 3
4

A quick update. Here

Now a FrontEndConfig can be make to configure the ingress. Hopes it helps.

Example:

apiVersion: networking.gke.io/v1beta1
kind: FrontendConfig
metadata:
  name: my-frontend-config
spec:
  redirectToHttps:
    enabled: true
    responseCodeName: 301

You'll need to make sure that your load balancer supports HTTP and HTTPS

Josh
  • 2,223
  • 1
  • 25
  • 18
  • First, thanks for you response. Please consider to include the solution directly in your answer. If the URL of this article changes, your answer will become useless. – alexzimmer96 Jan 14 '21 at 06:21
3

Worked on this for a long time. In case anyone isn't clear on the post above. You would rebuild your ingress with annotation -- kubernetes.io/ingress.allow-http: "false” -- Then delete your ingress and redeploy. The annotation will have the ingress only create a LB for 443, instead of both 443 and 80.

Then you do a compute HTTP LB, not one for GKE.

Gui directions: Create a load balancer and choose HTTP(S) Load Balancing -- Start configuration.

choose - From Internet to my VMs and continue

Choose a name for the LB

leave the backend configuration blank.

Under Host and path rules, select Advanced host and path rules with the action set to Redirect the client to different host/path. Leave the Host redirect field blank. Select Prefix Redirect and leave the Path value blank. Chose the redirect response code as 308. Tick the Enable box for HTTPS redirect.

For the Frontend configuration, leave http and port 80, for ip address select the static IP address being used for your GKE ingress.

Create this LB.

You will now have all http traffic go to this and 308 redirect to your https ingress for GKE. Super simple config setup and works well.

Note: If you just try to delete the port 80 LB that GKE makes (not doing the annotation change and rebuilding the ingress) and then adding the new redirect compute LB it does work, but you will start to see error messages on your Ingress saying error 400 invalid value for field 'resource.ipAddress " " is in use and would result in a conflict, invalid. It is trying to spin up the port 80 LB and can't because you already have an LB on port 80 using the same IP. It does work but the error is annoying and GKE keeps trying to build it (I think).

MBar
  • 31
  • 1
1

You can disable HTTP on your cluster (note that you'll need to recreate your cluster for this change to be applied on the load balancer) and then set HTTP-to-HTTPS redirect by creating an additional load balancer on the same IP address.

I spend couple of hours on the same question, and ended up doing what I've just described. It works perfectly.

0

Redirecting to HTTPS in Kubernetes is somewhat complicated. In my experience, you'll probably want to use an ingress controller such as Ambassador or ingress-nginx to control routing to your services, as opposed to having your load balancer route directly to your services.

Assuming you're using an ingress controller, then:

  • If you're terminating TLS at the external load balancer and the LB is running in L7 mode (i.e., HTTP/HTTPS), then your ingress controller needs to use X-Forwarded-Proto, and issue a redirect accordingly.
  • If you're terminating TLS at the external load balancer and the LB is running in TCP/L4 mode, then your ingress controller needs to use the PROXY protocol to do the redirect.
  • You can also terminate TLS directly in your ingress controller, in which case it has all the necessary information to do the redirect.

Here's a tutorial on how to do this in Ambassador.

Richard Li
  • 508
  • 2
  • 9