API Gateway using Spring Cloud + Zuul + Consul : dynamic routing not working when using HTTPS - netflix-zuul

I'm currently working on an API Gateway to centralize calls to REST APIs. We are using Spring Cloud (Edgware.SR3 version), with Zuul (1.3.0) to handle service discovery and Consul as service registry.
In a first version, routes to each service was registered in the gateway configuration using zuul.routes.myApiName.url and it was working fine.
Then, we wanted to use dynamic routing to allow having multiple instances of each API.
I've removed the zuul.routes.myApiName.url for that purpose.
Problem is that my calls to the API through the gateway are returning and error :
Bad Request This combination of host and port requires TLS.
Here is the configuration of the API registering in Consul :
spring.cloud.discovery.enabled=true
spring.cloud.consul.host=#consul_host_ip#
spring.cloud.consul.port=#consul_host_port#
spring.cloud.consul.discovery.scheme=https
And here is the configuration of Zuul route in the gateway :
zuul.host.socket-timeout-millis=60000
zuul.add-proxy-headers=false
zuul.ignored-services=*
zuul.routes.myApiName.path=/myApiName/**
zuul.routes.myApiName.serviceId=myApiName
API is correctly registered in Consul and health check is using HTTPS successfully :
HTTP GET https://hostname:port/health: 200 Output: {"description":"Composite Discovery Client","status":"UP"}
Certificates are also well configured since I am able to call my API directly using HTTPS.
But it seems that Zuul redirection is using HTTP instead of HTTPS (I have the same error if I call my API in direct mode (no gateway) using HTTP).
I've been struggling with this for a while, so I'd like to know if there is a configuration missing to force Zuul to use HTTPS in the routed call to API ?
Thanks in advance !

Just configure
zuul.addProxyHeaders = false
As the proxy headers are added by Zuul while forwarding any request to backend.

I've finally found the solution : I had to add this property :
ribbon.IsSecure=true

Related

spring oauth2 resourceserver jwt.jwk-set-uri from eureka server

Currently i have configured set-uri like below in resource server & spring cloud gateway,
spring.security.oauth2.resourceserver.jwt.jwk-set-uri: http://dev.auth.server:9999/.well-known/jwks.json
However to achieve high availability, I would like to resolve this end point from eureka server, I have successfully registered my auth server in eureka but below configuration fails,
spring.security.oauth2.resourceserver.jwt.jwk-set-uri: **lb://auth-server**/.well-known/jwks.json
could anyone please suggest?
currently there no way to achieve high availability by directly setting auth-server in jwt.jwk-set-uri instead you can achieve this by routing through spring cloud gateway
spring.security.oauth2.resourceserver.jwt.jwk-set-uri: GATEWAY_SERVER_URL/.well-known/jwks.json
in gateway config, you would have a config like this, which will load balance for you automatically.
- id: oauth-server
uri: lb://auth-server
predicates:
- Path=/.well-known/jwks.json

How to set up redirect uri for Facebook oauth authorization using dotnet core on docker when running behind IIS reverse proxy

We are building a web application with dotnet core running inside docker containers. We have put the app behind IIS on WS2016 which is used as reverse proxy. The requests incoming to our URL (www.myurl.com) are forwarded to the related docker container using the container name as the hostname with the help of url rewrite module(in our case, let's call it "web"). This setup works up to here.
However, a few days ago we needed to add Facebook oauth authorization support to register to the system and a problem appeared. We setup our authorization as the following:
...
services.AddAuthentication().AddFacebook(o =>
{
o.CallbackPath = new PathString("/account/facebookreturn");
o.AppId = appSettings.FacebookLogin.AppId;
o.AppSecret = appSettings.FacebookLogin.AppSecret;
})
...
Our facebook authentication challenge then redirects user to facebook oauth page with the following redirect uri:
https://www.facebook.com/v2.12/dialog/oauth......redirect_uri=http%3A%2F%2Fweb%2Faccount%2Ffacebookreturn&state=....
As you see the redirect_uri has the container name / hostname of the docker container whereas it should actually be "www.myurl.com".
We tried several solutions such as using x-forwarded headers. Using UseIISIntegration() and UseUrls did not seem to work either. What are we missing here? I am not much experienced with IIS and web headers, so it could be fairly obvious, and I appreciate the help.

Internal working of Netlfix Zuul with Netflix Eureka

How does Netflix Zuul Exactly work along with Eureka for routing & service discovery? From my understanding, a service instance registers/deregisters itself with Eureka with its IP and port. When a request arrives at Zuul (which is the gateway for end user requests), it checks with its filters if the request has to be routed (pre/post/route filters). If the filter for a particular request is present, does it send a request to Eureka asking it for a list of all IP Addresses and Ports for a service instance which serves that filter?
If that is how it works, what kind of requests reach Zuul ? If my filter name is “example”, would it be HTTP GET ipAddr:port/example ? (IP add:port is that of the Zuul instance)
I haven’t been able to find any article which describes the exact flow of messages between the 2 services in terms of the kind of messages to be passed. It would be great if someone could share some resources as well for me to get a better understanding.

Swagger proxied by haproxy can't execute requests

I have a swagger working with a haproxy. I use built in swagger in Websphere Liberty Profile (apiDiscovery feature):
Browser -swagger.mydomain.com-> haproxy -swagger.intranet-> IBM Liberty server with Swagger
The first swagger page is generated and shown correctly in the browser, but as Liberty server gets the request from haproxy, not my browser, and gets them to the intranet name/ip (swagger.intranet), Swagger code to execute GETs, POSTs, etc. is generated with that intranet IP name (swagger.intranet), so when I try any of the methods they won't work as reference this internal ip name from in a browser outside that zone.
Can I configure haproxy with some header to inform haproxy that he should generate code with the original server name (swagger.mydomain.com) request used in the request? (That is the one to be used in the generated HTML/Javascript code)
Thanks.
Liberty trusts the Host: header and uses it to assemble self-referential links.
Where you define the backend, try setting http-request set-header Host swagger.mydomain.com to what the client will be using or removing a similar stanza if you are setting it to some swagger.intranet already.
(sorry, I'm not an HAProxy user. This is based on searching for 'HAProxy equivalent of ProxyPreserveHost')

Spring Webapp behind Apache Web Server - Secured by CAS

I have a Webapp that is secured using Spring Security CAS. The CAS Server and the Webapp sit behind a web server for reverse proxy (named url). The webapp uses ServiceAuthenticationDetailsSource to authenticate dynamic service urls. The problem I have is that Service Ticket validations are failing because the url supplied during validation does not match the url provided when the ticket was created. The set up works without the webserver when systems are connected using https://:/.
The issue seems to be that the web server modifies the HttpServletRequest when redirecting to the webapp where in it looses the "named url" information and is substituted with the and . The service ticket is obtained using the named url via "?service=" during login.
Any possible solution? Can apache reroute request without modifying it, especially for applications that are self identifying or for security reasons where CAS is trying to record the client IP address?
I have outlined a few options below:
Setup the Reverse Proxy
According to the Javadoc of ServletRequest: the HttpServletRequest.getServerName() will be:
the value of the part before ':' in the Host header value, if any, or
the resolved server name, or the server IP address.
This means you can configure your proxy to ensure the Host Header is set properly (Note Some containers like WebSphere do not honor the specification though).
Override using the Container Configuration
Many servers have a setup that can override this value in the event you are using a reverse proxy. There is a pretty decent thread on the Spring forums with a bit more information on it that I have summarized below.
If you are using Tomcat, I'd refer to the Reverse Proxy setup page. One method of configuration would be to configure the Http Connector to have the proxyName attribute to override the value returned by HttpServletRequest.getServerName() and proxyPort to override the value returned by HttpServletRequest.getServerPort(). An example configuration might look like:
server.xml
<Connector scheme="https" secure="true"
proxyPort="443" proxyName="example.com"
port="8009" protocol="AJP/1.3"
redirectPort="8443" maxThreads="750"
connectionTimeout="20000" />
Websphere has a few custom properties that do the same thing.
com.ibm.ws.webcontainer.extractHostHeaderPort = true
trusthostheaderport = true
httpsIndicatorHeader = com.ibm.ws.httpsIndicatorHeader
If you are not using either of these containers or need to support multiple domains, you will need to consult your containers documentation.
Custom AuthenticationDetailsSource
Of course Spring Security is pretty flexible, so you can always provide a custom implementation of AuthenticationDetailsSource that returns an instance of ServiceAuthenticationDetails that looks up the service URL in any way you wish.

Resources