2

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?

cstack
  • 395
  • 1
  • 15

1 Answers1

1

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;
}

}

cstack
  • 395
  • 1
  • 15