1

I have Nginx-based service which configured to accept HTTPS-only. However GKE ingress answers HTTP requests in HTTP. I know that GKE Ingress doesn't know to enforce HTTP -> HTTPS redirect, but is it possible to learn it at least return HTTPS from service?

rules:
  - http:
  paths:
  - path: /*
    backend:
      serviceName: dashboard-ui
      servicePort: 8443

UPDATE: I do have TSL configured on GKE ingress and my K8S service. When request comes in HTTPS everything works nice. But HTTP requests gets HTTP response. I implemented HTTP->HTTPS redirect in my service, but it didn't help. In fact, for now all communication between ingress and my service is HTTTPS because service exposes only HTTPS port

SOLUTION - thanks to Paul Annetts: Nginx should check original protocol inside HTTPS block and redirect, like this

if ($http_x_forwarded_proto = "http") {
   return 301 https://$host$request_uri;
}
  • Hi nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/nginx-configuration/annotations.md#backend-protocol this Annotation might be helpful – Suresh Vishnoi Feb 26 '19 at 14:24
  • Suresh, I use GKE ingress, not Nginx-based – Vitaly Karasik DevOps Feb 26 '19 at 18:25
  • There will be a similar annotation, as these functionalities are enabled using annotations. I will look into GKE Ingress – Suresh Vishnoi Feb 26 '19 at 18:47
  • Thank you for your answers! I'm not sure that "backend-protocol" is relevant for my issue. My "dashboard-ui" listens on 8080 (http) and 8443 (https), with HTTP->HTTPS redirect. As you can see in my ingress config, it uses only HTTPS service port for access my service. – Vitaly Karasik DevOps Feb 26 '19 at 19:59
  • Hi @Vitaly I'm having same issue as you but not sure how to set that configuration, would you mind to share your configuration please? `nginx.ingress.kubernetes.io/configuration-snippet: | if ($http_x_forwarded_proto = "http") { return 301 https://$host$request_uri; }` – user2669657 Jul 17 '19 at 22:37
  • @user2669657, I used almost the same config: under HTTP nginx server I have if ($http_x_forwarded_proto = "http") { return 301 https://$host$request_uri; } It's not nginx ingres, just 'my' nginx in frontend of my services. – Vitaly Karasik DevOps Jul 18 '19 at 06:21

1 Answers1

2

Yes, you can configure the GKE Kubernetes Ingress to both terminate HTTPS for external traffic, and also to use HTTPS internally between Google HTTP(S) Load Balancer and your service inside the GKE cluster.

This is documented here, but it is fairly complex.

For HTTPS to work you will need a TLS certificate and key.

If you have your own TLS certificate and key in the cluster as a secret, you can provide it using the tls section of Ingress:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-ingress-2
spec:
  tls:
  - secretName: my-secret
  rules:
  - http:
      paths:
      - path: /*
        backend:
          serviceName: my-metrics
          servicePort: 60000

You can also upload your TLS certificate and key directly to Google Cloud and provide a ingress.gcp.kubernetes.io/pre-shared-cert annotation that tells GKE Ingress to use it.

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-psc-ingress
  annotations:
    ingress.gcp.kubernetes.io/pre-shared-cert: "my-domain-tls-cert"
...

To use HTTPS for traffic inside Google Cloud, from the Load Balancer to your GKE cluster, you need the cloud.google.com/app-protocols: '{"my-https-port":"HTTPS","my-http-port":"HTTP"}' annotation on your NodePort service. Note that your ports must be named for the HTTPS to work.

apiVersion: v1
kind: Service
metadata:
  name: my-service-3
  annotations:
    cloud.google.com/app-protocols: '{"my-https-port":"HTTPS","my-http-port":"HTTP"}'
spec:
  type: NodePort
  selector:
    app: metrics
    department: sales
  ports:
  - name: my-https-port
    port: 443
    targetPort: 8443
  - name: my-http-port
    port: 80
    targetPort: 50001

The load balancer itself doesn’t support redirection from HTTP->HTTPS, you need to find another way for that.

As you have NGINX as entry-point into your cluster, you can detect the protocol used to connect to the load-balancer with the X-forwarded-Proto HTTP header and do a redirect, something like this.

if ($http_x_forwarded_proto = "http") {
   return 301 https://$host$request_uri;
}
Paul Annetts
  • 9,554
  • 1
  • 27
  • 43
  • Paul, thank you! I guess I didn't explain myself well: I do have TSL configured on GKE ingress and my K8S service. When request comes in HTTPS everything works nice. But HTTP requests gets HTTP response. I implemented HTTP->HTTPS redirect in my service, but it didn't help. In fact, for now *all* communication between ingress and my service is HTTTPS because service exposes only HTTPS port. – Vitaly Karasik DevOps Feb 27 '19 at 05:03
  • Yeah, so the Load Balancer and Ingress on GKE itself doesn’t support HTTP->HTTPS redirect (yet?). That’s something you need to do in your service. Luckily it looks like you have NGINX as your entry point, you can get that to do the redirect quite easily. – Paul Annetts Feb 27 '19 at 06:49
  • I’ve added a snippet of NGINX redirect you can use into the answer. – Paul Annetts Feb 27 '19 at 06:58
  • Another alternative is to consider NGINX ingress controller as per this answer on a related question https://stackoverflow.com/a/42923210/694641. – Paul Annetts Feb 27 '19 at 07:01
  • Paul, many thanks! Checking http_x_forwarded_proto inside *https* block fixed my issue – Vitaly Karasik DevOps Feb 27 '19 at 11:38
  • Yes, that makes sense if the traffic is over HTTPS from the LB. – Paul Annetts Feb 27 '19 at 12:03
  • 1
    There is now an option to redirect http to https. in FrontendConfig: `redirectToHttps: enabled: true responseCodeName: PERMANENT_REDIRECT` – Ajax Aug 09 '21 at 21:50