istrupin
istrupin

Reputation: 1533

How to configure nginx reverse proxy in Google Cloud Run to point to a different Google Cloud Run app

I have a web application fronted by nginx set up in GCP Cloud Run, which works great. I am trying to use nginx to proxy requests to a certain route to another GCP Cloud Run service. For example -- I want requests to https://my-cloud-run-frontend.app.run to resolve to https://my-cloud-run-frontend.run.app, however I want requests to https://my-cloud-run-frontend.run.run/api/* to be proxied to https://my-cloud-run-backend.run.app.

Both cloud run services do use IAM Auth.

When I run my services in docker containers locally, the proxying works great. Likewise, if I remove IAM auth from the frontend app in my Cloud Run settings, things seem to work.

However, with IAM auth enabled, requests to https://my-cloud-run-frontend.run.app succeed, but requests to https://my-cloud-run-frontend.run.app/api/ fail as unauthorized (specifically, the error is thrown from the frontend cloud run app).

I've confirmed that the auth works by using the same auth token and making a request to https://my-cloud-run-backend.run.app as well as to https://my-cloud-run-frontend.run.app directly, and it works fine.

Doing some research, I saw that I may need to set a Host header, so I tried setting the header Host to my destination (the https://my-cloud-run-backend.run.app url). This had the effect of making calls to https://my-cloud-run-frontend.run.app/api return a 400 error.

My nginx.conf.template file:

server {

  access_log /dev/stdout;
  listen 8080;

  location / {

    root   /usr/share/nginx/html;
    index  index.html index.htm;
    try_files $uri $uri/ /index.html;
    proxy_set_header Authorization $http_authorization;
    proxy_pass_header Authorization;
    proxy_pass_request_headers on;

  }

  location /api/ {
    proxy_pass https://my-cloud-run-backend.run.app/;
    proxy_set_header Authorization $http_authorization;
    proxy_pass_header Authorization;
    proxy_set_header Host https://my-cloud-run-backend.run.app;
    proxy_pass_request_headers on;
    rewrite ^/api(.*)$ $1 break;
  }

  error_page   500 502 503 504  /50x.html;

  location = /50x.html {
    root   /usr/share/nginx/html;
  }

}

Upvotes: 3

Views: 6058

Answers (1)

guillaume blaquiere
guillaume blaquiere

Reputation: 75715

You can achieve your use case without authentication on your backend. In fact, you can deploy the API Cloud Run unauthenticated but with ingress set to internal only

Then, on your reverse proxy Cloud Run, you have to add a Serverless VPC connector and set the egress to all

That design accepts only authenticated and authorized request on the reverse proxy and makes the API backend only reachable by the reverse proxy (or other internal resource in your VPC).


This design will work but there is several tradeoff:

  • You can't define who has access to your API backend. It's "internal": any internal resource in your project can access it. In addition, if you have access to the reverse proxy you also have access to the backend, not different level of authorization possible here (at least with Google Cloud services. You can add homemade authorization check in your code)
  • The Serverless VPC connector cost is higher than a Load Balancer
  • The design is complex for only a redirect

Upvotes: 7

Related Questions