GKE ingress answers in HTTP even my service uses HTTPS only

2/26/2019

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;
}
-- Vitaly
google-kubernetes-engine
kubernetes

1 Answer

2/26/2019

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
Source: StackOverflow