Advanced headers don't work in Spring Boot + Kubernetes

Background

I recently migrated my Spring application to Spring Boot (w / embedded Tomcat), and now I'm porting it to Kubernetes. As part of the transition to Kubernetes, I separate the Apache configuration in my own service and deployment in Kubernetes to act as a proxy for my Spring application to load.

My current setup is Apache with the LoadBalancer service, which accepts requests from the world. This executes these requests and redirects them to my Spring Boot application, which has the ClusterIP service.

It's also important to note: my Apache redirects all http to https.

Problem

Whenever my Spring Boot application returns a redirect to the client, the location header in the response is http instead of https (only requests made through https will go through the Apache proxy to my application).

Example:

Not registered user:

https://example.com/admin 

If authentication is not completed, the administrator page will redirect the user to the login page. This MUST be redirected to:

 https://example.com/login 

However, like my application, it redirects the user to:

 http://example.com/login 

And then the user is redirected again by Apache to:

 https://example.com/login 

What i tried

I checked my logs to make sure that the requests my application receives include the X-Forwarded-Proto: https header, which, from what I understand, should make the location header in the response to the https redirect.

As mentioned in several posts, I tried to add server.use-forward-headers=true to my application.properties file, but it did nothing. I also tried adding server.tomcat.protocol-header=X-Forwarded-Proto , but it didn’t do anything (and from what I read, it’s all the same by default).

Other notes

  • My networkCIDR cluster networkCIDR included in the Tomcat list of internal proxies for RemoteIPValve
  • X-Forwarded-For doesn't seem to be affected either, so I think the problem is with all header forwards
+5
source share
1 answer

I get it. My mistake assumed that networkCIDR was the IP address returned by request.getRemoteAddr() when it was actually my k8s cluster IP address. This makes sense, given that the request comes from Apache, which is also inside the cluster. The cluster's internal IP address was NOT on the list of internal proxies, and thus RemoteIPValve did not use advanced headers.

By adding the server.tomcat.internal-proxies property to my application.properties with the default values ​​specified in RemoteIPValve and my cluster internal IP address, everything worked as it should.

See https://docs.spring.io/spring-boot/docs/current/reference/html/howto-embedded-servlet-containers.html#howto-customize-tomcat-behind-a-proxy-server

+2
source

Source: https://habr.com/ru/post/1272541/


All Articles