Spring Cloud Gateway with SSL cannot route to service by name - spring-boot

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.

Related

Spring cloud gateway does not forward HTTPS correctly

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>

Spring Cloud gateway on kubernetes timeout

My first question on stackoverflow, hope to get some help 🙂
I have a spring cloud gateway (using webflux) on kubernetes. My all other microservices is also sit on kubernetes on same cluster with ingress allowed only from api gateway so that all request can only go through gateway.
Problem I am facing is when I give any other service kubernetes path e.g http://myappservice.namespace.svc.clustor.local as route uri in gateway property and try to hit it gives upstream timeout, but if with in gateway I write a rest controller and call the same service with same kubernetes uri path through a simple rest template it works fine. So for sure it had access and there is no ingress and egress issue but why it could not call other services as proxy is mystery
Anyone have any clue?
Thanks
Ravi

Spring Cloud Gateway on App engine is not routing the requests to downstream services

I am trying to deploy a simple microservice application (Spring boot) in GAE. The application has 3 services -
1. Discovery Service
2. Spring Cloud Gateway
3. Customer service
I am trying to call an API through API gateway. This works fine in local machine but getting 404 in GAE hosted application.
The URL I am using is - https://Gateway-url/customer-service/version
And corresponding YAML config is :
spring:
cloud:
gateway:
routes:
-id: customer-service
uri: https://XXXXXX.customer-service.appspot.com/
predicates:
- Path=/customer-service/**
filters:
- StripPrefix=1
The URI configured in above code snippet is - target URL of GAE service.
So When I hit the https://Gateway-url/customer-service/version url in browser, I am getting 404 error but it works if I hit the direct url https://customer-service-url/version
When I changed the API Gateway configuration in the local environment, (change uri to cloud based service uri), the issue is reproducible. So I am thinking that Gateway is not able to route the requests to App Engine Service target URL.
How can I fix this problem?
I think the problem is the url that you are using in the configuration file to route your requests.
According to google cloud documentation, to call from one service to another you should use a endpoint like this
https://VERSION_ID-dot-SERVICE_ID-dot-PROJECT_ID.REGION_ID.r.appspot.com
As yo can see here
https://cloud.google.com/appengine/docs/standard/java/communicating-between-services
And it seems that the url that you are using doesn't fit int this.
Anyway I think that in a serverless environment such as app engine the best option to perform service discovery and to route requests via gateway is using the services provided by google. In case of service discovery it is done automatically and if you want a gateway you can use google cloud endpoints that have a greate integration with app engine. Because this is the gateway intended to use with these applications

Zuul proxy and ssl

I have a Spring boot project that is setup as a zuul proxy that is functioning as a api gateway for my rest services. I am now having problems with https which makes sense because I haven't configured https yet. One solution is to run nginx on port 443 and then forward all requests to the zuul proxy however that is extra overhead. So that is no solution.
Do I have to configure the zuul proxy to use the certificates or do I have to configure all the individual rest services?
What does the zuul proxy do with incoming requests? Does it forward the request or create a new one?
Possible duplicated, if this answer helps you please someone marks as duplicated this questions else let me know what is the difference? . Error when Zuul routing to a HTTPS url

Spring Cloud Zuul: how to add route without restart

I am writing microservices with Spring Cloud.
I'm also using Zuul as the API Gateway which routes some URLs to destination services which are not registered into Eureka.
When a new route needed to be added to Zuul, we often edit the application.yml file and then restart the Zuul server.
I was wondering is there a way to add new route into Zuul without restarting the Zuul server?
I found this link useful but it only works for services registed in Erueka.

Resources