Does anyone have a simple example of implementing x509 mutual authentication in Spring Cloud Gateway/Spring WebFlux? - x509certificate

I am trying to implement mutual authentication (authentication with x509 client certificates) in Spring Cloud Gateway, but throughout my research, I haven't been able to figure out where to start.
From what I can see, authentication is not handled through Spring Cloud Gateway itself but instead should be done through Spring WebFlux -- please correct me if this is an incorrect assumption. I have found examples of implementing certification authentication through Spring Security, but I have not found any with WebFlux.
Can anyone offer some tips or even some code examples to get me on the right track with this?

You can configure it in src/main/resources/application.yml, e.g.
server:
# for testing or development without SSL certs (HTTP) use an "appropriate"
# non-secure port, e.g. 8080
# for HTTPS use an "appropriate" secure port, e.g. 8443
port: 8443
ssl:
# for HTTP set enabled to false, for HTTPS (with required client certs) set to true
enabled: true
# this is the spring cloud gateway _server_ cert
key-store: /etc/pki/tls/private/server.p12
key-store-password: servercertpassword
key-store-type: PKCS12
# this is the "bundle" of CA intermediate/root upon which the client cert has to
# match
trust-store: /etc/pki/ca-trust/extracted/java/cacerts
# this `client-auth` option is where you *require* mutual-TLS, it can alternatively
# be made optional
client-auth: need
trust-store-password: truststorepassword
trust-store-type: JCEKS
management:
# management port without SSL to allow monitoring/etc. without client certs
# e.g. /actuator/health
server:
port: 8080
ssl:
enabled: false
If you have a set of client certs, a server cert, and trust-store / CA bundle, this is an example of how to configure it in Spring Cloud Gateway.
An X509 PreAuthenticatedAuthenticationToken will be available in your application for successful connections made via mutual TLS, containing the principal/details of the client cert.

You are correct about gateway using webflux where there is no standard authentication mechanism such as spring mvc. The suggested way of authenticating is here:
https://docs.spring.io/spring-security/site/docs/5.2.5.RELEASE/reference/html/reactive-x509.html
I also found the code example here helpful in setting up the application.yml file.
https://github.com/spring-projects/spring-security-samples/tree/main/reactive/webflux/java/authentication/x509
This post may also be helpful:
Authentication by certificate for WebFlux?
This post is not with webflux but is helpful in understanding how to set up certificates:
https://www.baeldung.com/x-509-authentication-in-spring-security

Related

Need Certificate chain (on the incoming interface) from Nginx

I am using a setup wherein a chain certificate(Root CA Cert-> Intermediate CA Cert -> Client Cert) is being sent to the Nginx. I need to configure Nginx in such a way that it forwards the entire certificate chain to the middleware. Right now, it is just sending the leaf certificate i.e. client certificate.
I found the following options from the Nginx's documentation (http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_client_certificate)
1- $ssl_client_escaped_cert
2- $ssl_client_cert
None of the above returns the full certificate chain.
Is anyone aware if there is such an option available ?
This seems to be impossible by design - see https://serverfault.com/questions/576965/nginx-proxy-pass-with-a-backend-requesting-client-certificates
The usage of $ssl_client_escaped_cert (as explained in https://clairekeum.wordpress.com/2018/12/05/passing-client-cert-through-nginx-to-the-backend/) seems to be your only option.
This may not be a complete answer, but thought I'd post some resources that may give you a couple of ideas.
If you want the client cert details downstream, then one option is to avoid terminating Mutual TLS in nginx by using the stream module. Here is an example:
Mutual TLS Secured API Blog Post .
NGINX Config
In this setup there are 2 Mutual TLS connections being routed via nginx:
To authenticate with an Authorization Server - where Mutual TLS is not handled by nginx
To call an API with a certificate bound access token - where nginx terminates TLS
Note that this uses a LUA plugin and the ssl_client_raw_cert property to do the extra work of calculating a SHA256 thumbprint, which NGINX itself does not support.
Generally though it makes sense to externalise Mutual TLS plumbing from application level components, as in the above example. Eg you can forward ssl_client_eacaped_cert to your middleware, but perhaps nginx should do the more detailed work of checking issuers.

Not able to achieve end to end encryption in openshift 4.3 route

We have a AngularJS application where we have a nodejs app which creates certificates and key for service hostname only when HTTPS port is 443. Then created certificates are consumed in nginx as shown below:
<% if ENV["HTTPS__ENABLED"] == "true" %>
listen <%= ENV["HTTPS__PORT"] %> ssl;
# These files are generated by the node app
ssl_certificate /cert.csr;
ssl_certificate_key /tls_private_key.csr;
ssl_protocols TLSv1.2;
<% end %>
But when I set 443 port in route with re-encrypt termination it gives below error while accessing application
Application is not available
The application is currently not serving requests at this endpoint. It may not have been started or is still starting.
The request is not even reaching pod. If I create route with edge termination is gives error
400 Bad Request
The plain HTTP request was sent to HTTPS port
As in Edge termination there is no encryption from router to pod.
I cannot use passthrough termination policy as we have path in our route which is not supported by passthrough termination.
can someone please let me know how to achieve end to end encryption in openshift 4.3. We do not use custom domain here.
I was checking the way for creating re-encrypt route
oc create route reencrypt --service=frontend --cert=tls.crt --key=tls.key --dest-ca-cert=destca.crt --ca-cert=ca.crt --hostname=www.example.com
but as we are not using custom domain our route should use default cert and key right? So no need to provide those right? I am not getting how to create --dest-ca-cert for this route.
TLS is already enabled in our AngularJS app using a nodejs app which creates cert and key which is consumed by Nginx.Pod inside the cluster uses TLS, it’s issued by a CA, that’s the cert we should put in destinationCACert for the route.The CA cert is how the router determines if it can trust the upstream POD for the TLS communication.
We used ca.cert located at /var/run/secrets/kubernetes.io/serviceaccount/ca.crt as destination certificate while creating re-encrypt route. We selected HTTPS port while creating route.
oc create route reencrypt --service=frontend --cert=tls.crt --key=tls.key --dest-ca-cert=destca.crt --ca-cert=ca.crt --hostname=www.example.com
Here tls.cert and tls.key is not needed for us as we were using default domain of the openshift cluster.Only cert we used is --dest-ca-cert which is also found at secret service-serving-cert-signer-sa-token-l42lm of openshift-service-ca namespace
For re-encrypt route the pod needs to be configured with a TLS certificate as it has to respond to TLS request originated at Openshift router. You already have it as evident from the error you are getting when trying to use edge route.
Now this TLS certificate, must be created with same host name that you want to use in the actual route. It is not necessary that this TLS certificate is a CA signed one, but the hostname must match with the route. Only then the route can forward traffic to your pod.

Does enabling LDAP over SSL and HTTP over SSL require two certificates?

I am a novice in SSL working on a Spring web application running directly off of an Apache Tomcat server. It is currently configured to be able to use LDAP (non-SSL) for authentication (this was set up by a previous developer). It also is running over http (also not SSL).
I want to be able to use both LDAPS and HTTPS.
My question is will I be able to use the same certificate to enable SSL for both LDAPS usage and HTTPS usage?
You can use the same certificate if:
you use the same server name in both cases or
if you have a certificate covering both names, with both names listed in the certificate, or
if they have some common domain suffix and you have a relevant wildcard certificate
Remember that certificates are used to prove the identity of some remote endpoint, and it is typically based on the hostname of the endpoint, as shown in some URLs, either for HTTPS or LDAPS.
RFC 6125 describes how identity is checked with certificates. Section 6 for the generic idea, and then appendix B.2 for HTTPS case and B.3 for LDAPS. They both use the name.

How to enable https in IIS?

I have applied a free certificate for my website and successfully installed the certificate in the certificate store. And the CN is the same as my domain(issued to mydomain).
I also set up the site bindings and added an https binding using the free certificate.
The port 443 is opened for both inbound and outbound.
Windows Network Troubleshooting detected the resource(my domain) is online but isn't responding to connection attempt.
But I still get ERR_CONNECTION_TIMED_OUT error from the browser.
Did I miss any steps? How could I enable the https in IIS?
UPDATE 11/14/2018
I have run bindings diagnostics and SSL diagnostics using JexusManager suggested by #Lex Li, and got more information as below:
Binding Diagnostics:
BINDING: https *:443:whatever.com
This site can take external traffic if,
TCP port 443 must be opened on Windows Firewall (or any other equivalent products).
Requests from web browsers must be routed to following end points on this machine,
[::1]:443.
My.private.IP.address:443.
This site can take local traffic at 127.0.0.1:443.
This site can take local traffic at [::1]:443.
Web browsers should use URL https://whatever.com:443. Requests must have Host header of "whatever.com".
Start DNS query for whatever.com.
DNS Query returns 1 result(s).
127.0.0.1
Binding Diagnostics does not verify certificates and other SSL/TLS related settings.
Please run SSL Diagnostics at server level to analyze SSL/TLS configuration.
And then I ran SSL diagnostics as below:
BINDING: https *:443:whatever.com
SSLCertHash: 2962cd5b2b450403bce520169c268de1f17a6216
SSL Flags: None
Testing EndPoint: 127.0.0.1
CertName: whatever.com
Version: 3
You have a private key that corresponds to this certificate.
Signature Algorithm: sha256RSA
Key Exchange Algorithm: RSA-PKCS1-KeyEx Key Size: 2048
Subject: CN=whatever.com
Issuer: CN=TrustAsia TLS RSA CA, OU=Domain Validated SSL, O="TrustAsia
Technologies, Inc.", C=CN
Validity: From 11/11/2018 4:00:00 PM To 11/12/2019 4:00:00 AM
Serial Number: 0B365B8ABC8118CD7F818FD5B7BB485C
DS Mapper Usage: Disabled
Archived: False
Subject Alternative Name: DNS Name=whatever.com DNS Name=www.whatever.com
Key Usage: KeyEncipherment, DigitalSignature
Enhanced Key Usage: Server Authentication (1.3.6.1.5.5.7.3.1),Client
Authentication (1.3.6.1.5.5.7.3.2)
Basic Constraints: Subject Type=End Entity, Path Length Constraint=None
Certificate verified.
And, I also have run an SLL Checker and it returns:
whatever.com resolves to My.Public.IP.Address
Server Type: Microsoft-IIS/8.5
No SSL certificates were found on whatever.com. Make sure that the name resolves to the correct server and that the SSL port (default is 443) is open on your server's firewall.
The certificate passed the SSL Diagnostics but it has some problem. I didn't get it. How could I enable https protocol for my site? Many thanks!
Problem solved.
As #John Wu said, this is not a programming problem but a network gateway problem.
First, the certificate has no problem and so does the server/firewall setting.
The problem occurred in the network gateway of the cloud service provider that blocked the 443 port inbound and outbound. In my case, I am using AliCloud server and it blocked every request which went through 443 port from the public network. And this is why I could only get access to the SSL website through the browser on the server.
The solution is very simple. The only thing needs to do is to inform the cloud service provider to open the 443 port. In my case, I just added the 443/443 port authorization in the control panel of the cloud servers and then everything fixed.

Visit Kubernetes dashboard through nginx proxy

I wanted to visit my dashboard on a local Kubernetes installation (using docker for mac). I was 'blocked'. I have to provide a token or my config which is normal since the RBAC updates.
Now I don't want to kubectl proxy or enable port forwarding every time I want to visit my dashboard so I installed an nginx proxy with a ingress (tls) which redirects me to https://kubernetes-dashboard.kube-system.svc.cluster.local:443.
This works fine but now I'm a bit confused because I can see the dashboard now, without facing the RBAC issue.
I read this here:
To make Dashboard use authorization header you simply need to pass
Authorization: Bearer in every request to Dashboard. This can
be achieved i.e. by configuring reverse proxy in front of Dashboard.
Proxy will be responsible for authentication with identity provider
and will pass generated token in request header to Dashboard. Note
that Kubernetes API server needs to be configured properly to accept
these tokens.
But it's still not very clear for me. Can someone explain we why I can see the dashboard when I create a proxy in front of it?
Proxy is usually needed to transfer data between different segments of the network without connecting them directly.
Each segment of the network is "talking" to proxy host without any knowledge of the existence of the other network segment.
The Proxy Server is responsible for all negotiations and operations concerning requests and response packets. So, to enable authentication, authorization, SSL termination and many other things you need to configure your proxy server according to your needs.
If you can see the kubernetes dashboard via proxy in front of it it just means that you did not configure any security on that proxy.
For example, to learn how to configure Nginx Ingress to protect a service with basic authentication in your cluster consider to read this article.
For more complex security setup read the article about securing Kubernetes services with Ingress, TLS and LetsEncrypt.

Resources