Spring Gateway Question on reverse proxying to TLS micro-services - spring

I am currently working on a project where each micro-service has it's own tls certificate.
I am thinking of using spring gateway to address a cross concerns like csrf (using the double submit pattern).
I would like the gateway to validate the csrf before proxying to micro-services and to create a new csrf value after each response of micro-service and mutate the response to include new csrf values.
Since each micro-service (that the gateway is proxying to) has it's own tls certificate is it possible to read and mutate the request before and after sending it to the micro-services?
I guess I am a little confused on how the gateway would work if it does not have the certificate to read the request.

The gateway will establish it's own tls connection. After which the gateway will then apply it's filters then proxy to a micro-service establishing another tls connection. In this senario we will have 2 different tls connections (from client browser to gateway, from gateway to service).
In my senario, I had micro-services with self signed certificates. The gateway settings will need to include the public keys for each service to establish a tls connection (since it will not be able to validate the certificate from a certificate authority). Spring gateway allows us to do this within the application properties file
spring:
cloud:
gateway:
httpclient:
ssl:
trustedX509Certificates:
- cert1.pem
- cert2.pem
Lastly, I was able to validate csrf value within the gateway before proxying to micro-services by creating a filter to do this. I have decided against changing the csrf value every request. For my use case I only needed to generate the csrf once for the user's session (I generated the csrf once after the user signs in).

Related

Secure API JAX-RS API with ssl certificate over Jetty Server

I have Jax-RS REST API with Jetty Server in my Java 8 application. I am new to securing the REST API.
I have .pem file (certificate) in some path.
I want to use this certificate to validate the incoming request API.
Can someone point me a working example that how to validate APIs with ssl certificate?
Is there any way that I can validate only single API and not all.
SSL/TLS based authentication of a client certificate occurs very early in the connections/conversation with an HTTP server.
In java it happens entirely within the JVMs SSLEngine layer.
Basically like this (simplified)
Client connects to port 443
Jetty accepts the connection
Jetty tests to see what kind of traffic it is
Jetty sees that it's encrypted and sends the traffic through the JVM SSLEngine layer.
TLS negotiates encryption (JVM code)
TLS negotiates client certificate (JVM code)
Connection is established (JVM code)
Jetty reads the decrypted traffic on the connection and starts to parse the request
Jetty creates the request object and dispatches to the web app.
Web app (your REST layer) now handles the request and produces a response.
By the time the request reaches your API the client certificate has already been verified / validated by the TLS layer.
You will only ever receive requests that satisfy that layer.
You have the optional feature SecureRequestCustomizer that will include Request attributes that contains information from TLS layer, by way of the JVM's post-negotiated TLS layer.

Spring cloud oauth 2 with ingress kubernetes

Is it possible to use spring cloud oauth 2 server with kubernetes api gateway ingress.
I have used it with zuul to authenticate user before making a call. Can I do similar with ingress?
Edit 1:
To explain it more clearly, what I am trying to achieve
I am using token based oAuth2 implementation given by the spring cloud.
oauth is running as one of the service behind the zuul.
zuul has routes mapped for the oauth server and resource server
client call the auth server via zuul and gets the token.
client call resource server via zuul with token passed
zuul is configured to validate the token before making a call to resource server.
In this way we can stop any downstream traffic to go without a valid token.
can we do token validation in ingress with auth server running with in a cluster?
I have not used Spring Cloud OAuth 2 but as OAuth is a standard I believe you can set it up if you are using Nginx Ingress as the ingress controller, you can specify and external Oauth Provider (As OAuth generally has the same flow) like this on your ingress:
...
metadata:
name: application
annotations:
nginx.ingress.kubernetes.io/auth-url: "https://$host/oauth2/auth"
nginx.ingress.kubernetes.io/auth-signin: "https://$host/oauth2/start?rd=$escaped_request_uri"
...
You can find more information here with an example of using GitHub as an OAuth provider
There are currently three different nginx-ingress-controllers (see here), which differ in functionality. I believe that none of these ingress controllers themselves can perform an oauth token introspection. However, requests can be routed to the authorization server's introspection interface using the auth_request module.
Specifically for your case, you can use the auth-url annotation (see) in the ingress controller to direct the requests to the introspection interface of the spring cloud oauth2 server (see). The introspection interface is available under /oaut/check_token by default when #EnableAuthorizationServer is used. If the introspection interface returns a 2XX, the ingress will forward the request. This functionality is based on the auth_request module, which expects a 2xx response code from the external service if the access is allowed and 401 or 403 if denied.
If you use JWTs and want to validate the request by only checking the signature, this can in some cases actually be done by the ingress itself. To my knowledge, only the nginx plus ingress controller (paid) can validate JWTs. But there is also the nginx-based kong-ingress controller, which you can equip with pulgins (see here). There is e.g. promoted with oauth2 integration and JWT validation.
Did you find out more than me?

Authorizing requests through spring gateway with zool via oauth server

My application has microservices behind (spring) gateway with zuul proxy. There is also internal (spring) oauth2 authorization server. I want to implement client_credentials grant type for my microservices calls from outside - for M2M communication.
When I configure for the gateway client_id and client_secret in its application.yml requests come through the gateway but there is no requester check - oauth authorizes the gateway itself, as a result there is no authorization at all. I could use authorization code grant type, but then it would require web-client authorization which (web client) user might not have.
If I request authentication token from the oauth microservice, I get correct token for this app.
How can I force the gateway use the requester's client_id and client_secret to get token from oauth? - e.g. I can provide them as basic authorization via header.
Or can I provide to the gateway the token obtained by the requester from oauth?
The question is very similar to another one: Implementing authentication and authorization using Zuul Proxy, Oauth2 on REST Microservices
except the thing that there might be no web client, but an external microservice.
I have answered the question Implementing authentication and authorization using Zuul Proxy, Oauth2 on REST Microservices.
In my case the most important thing was to configure zuul proxy to forward authorization header to downstream services. Initially I thought about using zuul filters, but solution was much simpler - just configure sensitive headers for zuul:
server:
port: 8080
zuul:
sensitiveHeaders: Cookie,Set-Cookie # <--- this line
routes:
spring-security-oauth-resource:
path: /spring-security-oauth-resource/**
url: http://localhost:8081/spring-security-oauth-resource
oauth:
path: /oauth/**
url: http://localhost:8083/spring-security-oauth-server/oauth
After successful authentication of a client/user with oauth JWT token will be forwarded to downstream by the gateway.
Certainly, for this gateway must allow unathenticated access to oauth resource and require authentication for all others.
More details on the topics can be found in the article
https://www.baeldung.com/spring-security-zuul-oauth-jwt

Spring boot Oauth2 SSO with Zuul proxy and multiple clients (native, mobile, web)

I'm currently working on a project that uses Zuul to proxy requests to both API endpoints as well as client resources. There is an angular app that is being served from the same endpoint as the Zuul proxy as outlined in this guide. I have the need for additional clients, specifically a desktop application.
I'm not sure I understand how Zuul proxy handles requests and I think there are several paths to get to where I want to go, I'm just not sure what the correct one is.
Here is what I have surmised thus far:
Option 1: Extract the Zuul proxy and SSO capabilities to it's own server. Then create a new UI server which is behind the gateway server. Follow this up with creating a new client application server which handles the authentication of the desktop client.
Option 2: Extract the Zuul proxy and SSO capabilities to it's own server. Serve the current angular app from its own server NOT behind the proxy and change the authorization flow to something different (implicit). Alter Zuul proxy and SSO configuration to ignore requests that already have a bearer token in the header.
If I go with option 2 then I don't understand how to register with the Zuul gateway client that I already am providing the authorization header with my requests so all it should be doing then is proxying my requests to the correct microservices.
Final Questions:
Which option is the most optimal one?
If an access token is already acquired (directly from the auth server using implicit flow) then how does Zuul need to be configured to not try and acquire the access token using the jsessionid?

Https support for <int-http:outbound-gateway>

I need to implement https support for <int-http:outbound-gateway>.
Following is the scenario:
There is <int-http:inbound-gateway> which accepts inbound url to Spring integration. The reply-channel of <int-http:inbound-gateway> and <int-http:outbound-gateway> are same. Based on the HeaderValueRouter, the inbound request is forwarded from request-channel of <int-http:inbound-gateway> to request channel of <int-http:inbound-gateway> . Now response is received from the outbound url and put in the reply-channel.
The url-expression of <int-http:outbound-gateway> is built from the MesssageHeader "http_requestUrl" attribute.
Now if I host the external app in https. What configuration I need to make in <int-http:inbound-gateway> to get the response in reply-channel
Actually there is nothing to do with Spring Integration for SSL. It is a responsibility of the underlying HTTP engine. And, to be honest, it even doesn't depend on the ClientHttpRequestFactory implementation for the RestTemplate.
You just need to have the server SSL certificate and place it to the trustStore. That's is if your target service requires only trusting - single-way SSL.
If you need mutual SSL, you need to generate the key and store it in the keyStore for your Java and share with the server the public part - certificate.
More info you can find in the Java SSL documentation.

Resources