Paul Collingwood
Paul Collingwood

Reputation: 33

Google Cloud Run for Anthos (Knative) not setting X-Forwarded-Proto header correctly on https requests

I have a django application running in Google cloud run (in a Kube cluster), via Docker served by uwsgi (but I've tried manage.py runserver and it's the same). By default cloud run accepts connections on both http and https.

I would like to redirect the user to the https version but cloud run does not seen to be setting the headers correctly.

I have a handler that returns the headers via: json.dumps(request.headers.__dict__['_store'])

And the relevant headers returned are:

"x-forwarded-proto": ["X-Forwarded-Proto", "http"]

But the value http never changes even when I visit the https version of the site.

How should django correctly detect http requests on cloud run? I am unable to use

SECURE_PROXY_SSL_HEADER

to detect and redirect http requests to https as they all appear to be http requests, so you end up in a redirect loop.

However if I follow the links in this post: https://www.jhanley.com/google-cloud-run-https-part-2/

to their "show me the headers" link the value does indeed change from http to https. Is it a django thing? Or a "cloud run on kube" thing?

Hosting the app in question on pure cloud run and visiting the http version does an internal redirect to the HTTPS version and gives the reason: Non-Authoritative-Reason: HSTS

Which is exactly what I'm trying to achieve. It seems the headers I am getting are from the internal routing, not the original request itself when running in Anthos mode.

Upvotes: 3

Views: 588

Answers (2)

Igor Gassmann
Igor Gassmann

Reputation: 182

The issue is known and I have reported it a couple of months ago. You can track it here on Google Cloud Run for Anthos issue tracker.

A workaround I found for this issue is to do the redirection on your frontend with JavaScript by checking if the value of window.location.protocol is http and rewriting the location as such:

window.location = "https://" + window.location.hostname + window.location.pathname + window.location.search;

Upvotes: 1

ahmet alp balkan
ahmet alp balkan

Reputation: 45214

The article you linked seems to be about "Cloud Run (fully managed)" but you aren't using that. Cloud Run for Anthos (Knative) has a fairly different stack for handling the requests and HTTPS termination. So please ignore that.


Here's how to create a domain with a TLS certificate managed by Knative (issued from Let's Encrypt) and do a HTTP→ HTTPS redirect.

This procedure is explained in official Cloud Run documentation: https://cloud.google.com/run/docs/gke/managed-tls

  1. Ensure your cluster is 1.17.7-gke.15 and newer versions. With these versions "managed certificates" feature is enabled by default.

  2. Create a domain mapping for your service. (You can do this on Cloud Console)

  3. Point your domain’s DNS records to the IP address given to you (the gateway IP service that can be found in gke-system Kubernetes namespace)

  4. A TLS certificate will be automatically provisioned for your domain in the background (and will be renewed every 80 days or so)

  5. To set up HTTP→HTTPS redirect, follow these instructions which requires you to run:

    kubectl annotate domainmappings [YOUR_DOMAIN] domains.cloudrun.com/httpsRedirect=Enabled
    

    which is basically adding an annotation to the DomainMapping object in Kubernetes.

    This configures the ingress gateway in your cluster to do the redirect for you. You don't need to read the x-forwarded-proto header and take action.

Upvotes: 1

Related Questions