I am trying to forward client certificate information from Spring Cloud Gateway to microservices behind it. I modified the Netty config and it is successfully requesting a client cert from the client, but I don't see it forwarding it to the microservice behind it. In Apache we used to use +ExportCertData which populated a handful of headers with the client certificate DN, validity time, etc. Does Spring Cloud Gateway have any out of the box functionality like this?
I found these 2 questions which seem similar, but neither had very explicit answers. spring cloud gateway forward client certificate and Does anyone have a simple example of implementing x509 mutual authentication in Spring Cloud Gateway/Spring WebFlux?
After playing with it for a while, changing something on the Netty HttpClient did not seem to be right because as far as I could tell it did not know anything about where the request came from. However I found that the filter chain had all the information I needed, so I put in a custom GlobalFilter which adds the certificate information to the header like what Apache does.
public class ClientSSLToHeaderFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest req = exchange.getRequest();
SslInfo info = req.getSslInfo();
if(info != null) {
X509Certificate[] certs = info.getPeerCertificates();
if(certs != null && certs.length > 0) {
ServerHttpRequest request = exchange.getRequest().mutate()
.headers(httpHeaders -> {
try {
certs[0].checkValidity();
String encodedCert = new String(Base64.getEncoder().encode(certs[0].getEncoded()));
httpHeaders.add("SSL_CLIENT_CERT", encodedCert);
httpHeaders.add("SSL_CLIENT_VERIFY", "success");
} catch(CertificateEncodingException | CertificateExpiredException
| CertificateNotYetValidException e) {
// TODO Auto-generated catch block
log.log(Level.ERROR, e, e);
}
}).build();
return chain.filter(exchange.mutate().request(request).build());
}
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return -1;
}
}