Spring cloud gateway does not forward HTTPS correctly - spring-boot

I've recently migrated a microservices backend to Spring boot v2.6.1 + spring cloud v2021.0.0 (old version was v2.2.1.RELEASE).
Previously, the setup included a discovery server (Eureka), a gateway (Zuul) and various microservices accessible externally via the gateway. All of these were TLS/secure port enabled so all requests (discovery, registration, gateway forwarding etc) required SSL trust store configuration.
Since Zuul is no longer supported in this version, I am switching to Spring cloud gateway, with the following application.properties setup:
server.port = 8080
eureka.instance.securePortEnabled=false
eureka.client.serviceUrl.defaultZone = http://localhost:8761/eureka/
spring.application.name= gateway-service
spring.cloud.gateway.routes[0].id=first-service
spring.cloud.gateway.routes[0].uri=lb://FIRST-SERVICE
spring.cloud.gateway.routes[0].predicates[0].name=Path
spring.cloud.gateway.routes[0].predicates[0].args.pattern=/firstService/**
spring.cloud.gateway.routes[0].filters[0]=StripPrefix=1
security.require-ssl=true
server.ssl.key-store=keystore.p12
server.ssl.key-store-password=password
server.ssl.keyStoreType=PKCS12
server.ssl.keyAlias=localhost
spring.cloud.gateway.httpclient.ssl.trustedX509Certificates[0]=cert.pem
Without ssl universally disabled, I can access a first service URL via that gateway without issue. With SSL enabled, I can access the first service directly and again no issue:
https://localhost:8100/test
{ "message": "Hello World!" }
However, the gateway is not correctly forwarding the requests either via the correct protocol or with the correct client certificate. I am getting the below error response instead of "Hello World" message:
https://localhost:8080/firstService/test
Bad Request This combination of host and port requires TLS.
(It's worth noting that the Eureka secure port is disabled, and registration/registry fetch is done via HTTP due to issues logged at Error setting custom trust store for Eureka Discovery client by overriding DiscoveryClient.DiscoveryClientOptionalArgs

Ok, this comes down to how the microservices register with Eureka.
Although FIRST-SERVICE was also setup with security.require-ssl=true for direct access it was also necessary to register with Eureka with SSL enabled.
Adding the settings below to application.properties fixed the issue without any changes needed for the gateway configuration:
eureka.client.tls.enabled=true
eureka.client.tls.key-store=file:<path-to-key-store>
eureka.client.tls.key-store-password=<password>
eureka.client.tls.keyStoreType=PKCS12
eureka.client.tls.keyPassword=<password>
eureka.client.tls.trust-store=file:<path-to-trust-store>
eureka.client.tls.trust-store-password=<password>

Related

Spring Cloud Gateway Proxy Host issue

I am running Spring Cloud Gateway with Spring Boot version 2.5.8 and Spring Cloud version 2020.0.5.
I am trying to configure Spring Cloud Gateway to validate JWT access tokens using Spring Security and thus the gateway needs to connect to the OAuth2 Authorization server external to my company's network. As per company standard, I am using a proxy host to connect to the external Authorization server and I have set the http.proxy* and https.proxy* environment variables ie
-Dhttp.proxyHost=my-proxy.com -Dhttp.proxyPort=3328 -Dhttps.proxyHost=my-proxy..com -Dhttps.proxyPort=3328 -Dhttp.proxySet=true -Dhttps.proxySet=true
and well as the properties in application.yml. ie
spring:
cloud:
httpclient:
proxy:
host: my-proxy.com
port: 3328
But I am getting timeout error when connecting to the external Authorization Server. The proxy host and port are correct and are working for other Spring Boot projects using Spring MVC. I saw this question/answer
spring-boot app as spring-cloud-gateway has to use a proxy: JVM arguments not used NOR spring.cloud.gateway.httpclient.proxy.****
But my entries in application.yml is not working. Would appreciate if someone can provide some advice on resolving the issue.
Thanks

Spring boot API endpoint does not work after setting the DNS record

I have a spring boot web service running on localhost:8000 with an embedded Apache Tomcat.
Frontend is developed using Angular and is running on nginx and port 80. Connection between front- and back-end is established with a REST API endpoint, i.e. /v1/getdata/...
We have a static IP and outside access is OK with this configuration. But after setting a DNS record, i.e. https://x.y.com for the static IP, the spring web server does not return data and ERR_TUNNEL_CONNECTION_FAILED error is occurred in Angular, although the front-end is loaded successfully on port 80.
The only server-side configurations in Spring app is server.port=8000 and CORS configs.
I have set [STATIC-IP]:8000 and https://x.y.com:8000 for the api address in Angular but neither worked. However accessing with static IP is still working.
I think there is a problem with SSL configuration.
Any Ideas?

Problems setting up Zuul proxy server with Eureka discovery

I am trying to set up a zuul proxy server which will act as a gateway service for other apis in my microservice architecture.
So far all the tutorials that I have come across have the discovery client and zuul proxy set up in different gradle modules while I am trying to set them up in the same gradle module.
I have defined the routes and can see that my services have been successfully registered in the eureka dashboard.
I have also verified that I can ping the services using a discovery client from my gatekeeper service but whenever I try to access the services from the URL, I get
"Load balancer does not have available server for client:xyz"
exception.
Can somebody please help me setting this up?

How to register non Spring Boot MicroService in Eureka discovery server

I have recently installed a micro service infrastraucture based on Spring Boot + Spring Cloud.
My Spring Boot microservices register in my Eureka server and Zuul automaticaly redirects requests to them.
I have a Drupal content manager that exposes content through REST interface and I'd like it to take part in the discovery rave party. How can I have my drupal register it self in the Eureka server so Zuul redirects the corresponding calls to it?
As an ugly workaround I wonder if I can have automatic discovery and routing running in Zuul while manually configuring some REST paths to be redirected to the drupal server? (Using zuul.routes... property files)
I found that I can add manual zuul routes in bootstrap.yaml
I have tried adding it in the application yaml property files in configuration server but for some reason they are ignored when the Eureka discovery server is working.
Anyway, bootstrap.yaml works. Example:
zuul:
routes:
mta_api:
path: /mta_api/**
url: http://my-non-springboot-rest-service.com/
stripPrefix: false
You could add sidecar to your non-springboot application. This would allow Eureka support.
Source: Dead- http://cloud.spring.io/spring-cloud-static/Edgware.SR4/single/spring-cloud.html#_polyglot_support_with_sidecar
Current: https://cloud.spring.io/spring-cloud-static/Dalston.SR5/multi/multi__polyglot_support_with_sidecar.html

Spring Cloud Gateway with SSL cannot route to service by name

I had enable SSL on Spring Cloud Gateway service, and after that routing such as
.route("instruments-ui", r -> r.path("/instruments/**")
.filters(f -> f.filter(addCredentials.apply()).preserveHostHeader())
.uri("lb://instruments-ui"))
ceased normally working. If I change uri to real address such as http://localhost:8001 routing working right. I use Gateway version 2.0.0.RC1. Can anybody explain how to setup Spring Cloud Gateway + routing with Eureka data + SSL?
If your Gateway works with SSL and downstream services works without it, then you need to specify uri as for example .uri("lb:http://instruments-ui"). I found it after viewing LoadBalancerClientFilter class.

Resources