cstack
cstack

Reputation: 405

Spring Cloud Gateway Pass Client Certificate Information

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?

Upvotes: 3

Views: 3246

Answers (1)

cstack
cstack

Reputation: 405

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

Upvotes: 1

Related Questions