I am invoking a REST API from Nifi using InvokeHTTP processor and wanted to enable mutual certificate authentication between client (nifi) and server.
I enabled StandardRestrictedSSLContextService (controller service) as mentioned in the below screenshot and getting below exception:
InvokeHTTP[id=4a29f282-3665-3703-aab8-9e106c4aa9a4] Failed to properly initialize Processor. If still scheduled to run, NiFi will attempt to initialize and run the Processor again after the 'Administrative Yield Duration' has elapsed. Failure is due to java.lang.reflect.InvocationTargetException: java.lang.reflect.InvocationTargetException
Am I missing anything, kindly please explain how to enable mutual certificate based authentication?
@VijaySankar In a recent Use Case, I had to connect invokeHttp to an API (https) to get an S3 bucket URL and then to Amazon S3 (https) to download the file. Each InvokeHTTP required its own SSL Context Service and for each I complete the following:
Obtain the public SSL certificate from the end point. I use curl, or standard browser to download the cert.
Use the cert to make a truststore (JKS) file.
Put this truststore on all my NiFi nodes, owned nifi:nifi
Put the trustore path, type, and password in the SSL Context Service.
If it worked and you got the expected response, you can be sure the cert was used... i don’t think the cert will actually be “sent” but it is used on the Nifi side (client) to communicate “securely”... just make sure you get the expected response and not, for example, an http (not https) error page...
Whether a client certificate is required in the TLS connection is controlled by the server side of teh connection and not by the client.
Your SSL context service must include a truststore. The truststore is required whether the TLS secured connection is using mutual authentication or 1-way TLS authentication.
The client initiates a connection to the https server. The server responds with a TLS server hello response. Among other things, the server will include its server certificate, whether a client certificate is required (client certificate must be returned), wanted (client certificate is wanted but connection will proceed even if one is not provided), or none (no client certificate requested), and a list of server side trusted CAs. If the server does require or want a client certificate, the client can only pass a certificate that is signed (issuer) is one of the trusted CAs returned in the Server Hello. If your server endpoint requires a client certificate and non is provided, the server would just close the connection since the TLS handshake failed.
The truststore used in your SSL context service on the client side must be able to trust the server certificate presented (true for mutual auth TLS or 1-way TLS). This means the truststore you use must contain the complete trust chain for the issuer of the server certificate sent by the server.
If you want to see the server hello, you can use openssl as follows:
As mentioned in the below screenshot, I have added client cert (.jks) in keystore and server cert (.jks) in truststore. Server is expecting a client cert as part of request but when I make a rest call, client certificate is going in the request.
Here is the command that I used to generate a .jks file on top of client certificate:
The target server is what decides if connection is going to use mutual auth or not. The invokeHTTP is the client side of this connection and only provides what the server asks for in the server hello response. It is possible also in that server hello response that the server wants a client certificate; however, the list of CAs sent in that server hello response does not contain a CA capable of trusting your clientAuth PrivateKeyEntry in your nifi.com.jks. In that case client would not send the client certificate since server is incapable of trusting it.