Jeff did a really good job explaining what I glossed over earlier. Assuming the 
site you are trying to reach doesn’t have a certificate that is signed by a 
known CA (for example, a company service that is only accessed from within the 
organization), you can follow these instructions to obtain the service’s 
certificate, put it in a new truststore, and configure NiFi. I concur with 
Jeff; adding custom certs to cacerts is a bad idea. 

Let’s say your NiFi instance is hosted on “nifi.vic.com” and the service you 
want to connect to is “other.service.com” and running on port 443. 

From your command-line, run the following “openssl s_client -connect 
other.service.com:443 -showcerts”. This command will attempt to make a TLS 
connection to that service, and will print the provided certificates in PEM 
format. You should see an “issuer” and “subject” for each. A subject is “who am 
I” and the issuer is “who vouches for me”. At level 0 is the actual service 
certificate. That is the one you want to copy. However, if that cert could 
change (I.e. there is a pool of application servers, each with their own cert, 
or it’s a Docker container that gets a new cert every time it’s instantiated) 
you will want to get the signing cert (unlikely to change). Either way, there 
will be a section of output that looks like:


-----BEGIN CERTIFICATE----- 
MIIDZTCCAk2gAwIBAgIKAWTeM3kDAAAAADANBgkqhkiG9w0BAQsFADAxMQ0wCwYD 
...
MDG+K3rCeieSBPOnGNrEC/PiA/CvaMXBEog+xPAw1SgYfuCz4rlM3BdRa54z3+oO lc8xbzd7w8Q3 
-----END CERTIFICATE-----
That is called the “PEM-encoded certificate”. It means it is in Base64 
encoding. Copy all of that into a file named “service.pem”. Now you will import 
that certificate into a JKS truststore file. 

Follow the instructions here [1], starting at Step 2 (you already have the PEM 
file). This will create a truststore file with that trusted cert in it, which 
you can reference in your SSLContextService. 

There are more details on certificate formats here [2], but it’s not quite 
tailored to your use case, so you’ll have to patch things together. 

[1] 
https://docs.oracle.com/cd/E35976_01/server.740/es_admin/src/tadm_ssl_convert_pem_to_jks.html
[2] 
https://nifi.apache.org/docs/nifi-docs/html/administration-guide.html#using-an-existing-intermediate-certificate-authority-ca

Andy LoPresto
[email protected]
[email protected]
PGP Fingerprint: 70EC B3E5 98A6 5A3F D3C4  BACE 3C6E F65B 2F7D EF69

> On Dec 26, 2018, at 11:14, Jeff <[email protected]> wrote:
> 
> There was a bit of a grammar issue with my previous message...  InvokeHTTP 
> should be *presented* with a cert that's signed by one of the CAs in cacerts. 
>  You can use your browser to go to the website/URL that you've configured in 
> InvokeHTTP, and take a look at the certificate for the site.
> 
> For example, going to www.google.com using Google Chrome, you can click on 
> the padlock icon next to the URL, and click on "Certificate", which should 
> show you information about the cert that was presented for www.google.com, 
> and you can see that the root CA is from "GlobalSign".  The owner/issuer of 
> that "GlobalSign" root CA is:
> CN=GlobalSign, O=GlobalSign, OU=GlobalSign Root CA - R2
> Then, you can look in your JDK's cacerts to see if that CA is included:
> keytool -storepass changeit -keystore 
> /Library/Java/JavaVirtualMachines/jdk1.8.0_192.jdk/Contents/Home/jre/lib/security/cacerts
>  -list -v | grep -i "GlobalSign"
> You should see output similar to the following:
> 
> Alias name: globalsignr2ca [jdk]
> Owner: CN=GlobalSign, O=GlobalSign, OU=GlobalSign Root CA - R2
> Issuer: CN=GlobalSign, O=GlobalSign, OU=GlobalSign Root CA - R2
>      [URIName: http://crl.globalsign.net/root-r2.crl]
> Alias name: globalsigneccrootcar4 [jdk]
> Owner: CN=GlobalSign, O=GlobalSign, OU=GlobalSign ECC Root CA - R4
> Issuer: CN=GlobalSign, O=GlobalSign, OU=GlobalSign ECC Root CA - R4
> Alias name: globalsignca [jdk]
> Owner: CN=GlobalSign Root CA, OU=Root CA, O=GlobalSign nv-sa, C=BE
> Issuer: CN=GlobalSign Root CA, OU=Root CA, O=GlobalSign nv-sa, C=BE
> Alias name: globalsignr3ca [jdk]
> Owner: CN=GlobalSign, O=GlobalSign, OU=GlobalSign Root CA - R3
> Issuer: CN=GlobalSign, O=GlobalSign, OU=GlobalSign Root CA - R3
> Alias name: globalsigneccrootcar5 [jdk]
> Owner: CN=GlobalSign, O=GlobalSign, OU=GlobalSign ECC Root CA - R5
> Issuer: CN=GlobalSign, O=GlobalSign, OU=GlobalSign ECC Root CA - R5
> 
> You can see that the cert with an owner/issuer of "CN=GlobalSign, 
> O=GlobalSign, OU=GlobalSign Root CA - R2" is in the alias "globalsignr2ca 
> [jdk]" in the output, which should match the root CA with which 
> www.google.com's cert is signed.  You can look at more details of that cert 
> with keytool:
> 
> keytool -storepass changeit -keystore 
> /Library/Java/JavaVirtualMachines/jdk1.8.0_192.jdk/Contents/Home/jre/lib/security/cacerts
>  -list -v -alias "globalsignr2ca [jdk]"
> 
> I won't list that output here, but you can compare it with the detailed view 
> provided by your browser if you click on the root certificate.
> 
> If the issuer of the cert presented by a website cannot be found in the 
> truststore of the SSLContextService that InvokeHTTP is using, you'll see that 
> "PKIX path" exception.  This can happen with self-signed certs, if the 
> issuer's cert has not been added to the truststore.  Not all public CAs are 
> present in the JDK's cacerts by default, and like self-signed certs, the CA 
> cert will need to be added to a truststore.  I don't recommend adding certs 
> to cacerts, but Andy may have a different view on this.  If you need to 
> access sites with certs that are not part of cacerts, and you trust the 
> issuer of the cert for the site being accessed, you should create a custom 
> truststore that contains the issuer's cert, and configure an 
> SSLContextService that uses the custom truststore.
> 
> This isn't a comprehensive guide on CA certs, but I hope it helps you to work 
> through the issue.  Please let us know if we can help further!
> 
> - Jeff
> 
> 
>> On Mon, Dec 24, 2018 at 9:34 AM l vic <[email protected]> wrote:
>> Could you try using an explicit path to the cacerts provided by your 
>> JDK/JRE, instead of referring to $JAVA_HOME? 
>> Tried without success...
>> Were you able to successfully start the SSLContextService after configuring 
>> it?
>> Yes
>> InvokeHTTP needs to present a certificate that is signed by a CA that is in 
>> the default cacerts
>> Not sure how to identify one that is supposed to be presented
>> 
>> 
>>> On Sun, Dec 23, 2018 at 1:32 PM Jeff <[email protected]> wrote:
>>> Could you try using an explicit path to the cacerts provided by your 
>>> JDK/JRE, instead of referring to $JAVA_HOME?  Andy gave an example of 
>>> "/Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home/jre/lib/security/cacerts",
>>>  which you would update with the path to the JDK you are using.  
>>> Referencing an environment variable (without using EL) will not work for a 
>>> NiFi property.  It does not appear that EL is supported for the keystore 
>>> and truststore properties, as that could lead to security issues.  Those 
>>> properties have validators that should also verify that the 
>>> keystore/truststore exists and is readable.  Were you able to successfully 
>>> start the SSLContextService after configuring it?
>>> 
>>> Also, as Andy mentioned, the URL you are using in InvokeHTTP needs to 
>>> present a certificate that is signed by a CA that is in the default 
>>> cacerts.  Can you please verify this?  You can get a list of what is 
>>> contained in cacerts by using keytool, and specifying the path to cacerts, 
>>> the password, and the list command.  For example:
>>> 
>>> keytool -storepass changeit -keystore 
>>> /Library/Java/JavaVirtualMachines/jdk1.8.0_192.jdk/Contents/Home/jre/lib/security/cacerts
>>>  -list
>>> 
>>> - Jeff
>>> 
>>>> On Fri, Dec 21, 2018 at 2:55 PM l vic <[email protected]> wrote:
>>>> I put "default" parameters for trust-store:
>>>> Path: $JAVA_HOME/jre/lib/security/cacerts 
>>>> Password: changeit (default)
>>>> Type: JKS
>>>>  and got "invalid path" exception ( see below)
>>>> How does that missing cert file should look like?
>>>> Thanks again...
>>>> 
>>>> 2018-12-21 14:46:00,021 ERROR [Timer-Driven Process Thread-1] 
>>>> o.a.nifi.processors.standard.InvokeHTTP 
>>>> InvokeHTTP[id=0929346d-d742-1fd9-e41a-8e4324b73349] Yielding processor due 
>>>> to exception encountered as a source processor: 
>>>> javax.net.ssl.SSLHandshakeException: 
>>>> sun.security.validator.ValidatorException: PKIX path building failed: 
>>>> sun.security.provider.certpath.SunCertPathBuilderException: unable to find 
>>>> valid certification path to requested target: {}
>>>> javax.net.ssl.SSLHandshakeException: 
>>>> sun.security.validator.ValidatorException: PKIX path building failed: 
>>>> sun.security.provider.certpath.SunCertPathBuilderException: unable to find 
>>>> valid certification path to requested target
>>>>        at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
>>>>        at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1964)
>>>>        at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:328)
>>>>        at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:322)
>>>>        at 
>>>> sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1614)
>>>>        at 
>>>> sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
>>>>        at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1052)
>>>>        at sun.security.ssl.Handshaker.process_record(Handshaker.java:987)
>>>>        at 
>>>> sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1072)
>>>>        at 
>>>> sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1385)
>>>>        at 
>>>> sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1413)
>>>>        at 
>>>> sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1397)
>>>>        at 
>>>> okhttp3.internal.connection.RealConnection.connectTls(RealConnection.java:267)
>>>>        at 
>>>> okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.java:237)
>>>>        at 
>>>> okhttp3.internal.connection.RealConnection.connect(RealConnection.java:148)
>>>>        at 
>>>> okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:186)
>>>>        at 
>>>> okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:121)
>>>>        at 
>>>> okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:100)
>>>>        at 
>>>> okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42)
>>>>        at 
>>>> okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
>>>>        at 
>>>> okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
>>>>        at 
>>>> okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
>>>>        at 
>>>> okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
>>>>        at 
>>>> okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
>>>>        at 
>>>> okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
>>>>        at 
>>>> okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
>>>>        at 
>>>> okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:120)
>>>>        at 
>>>> okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
>>>>        at 
>>>> okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
>>>>        at 
>>>> okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:179)
>>>>        at okhttp3.RealCall.execute(RealCall.java:63)
>>>>        at 
>>>> org.apache.nifi.processors.standard.InvokeHTTP.onTrigger(InvokeHTTP.java:709)
>>>>        at 
>>>> org.apache.nifi.processor.AbstractProcessor.onTrigger(AbstractProcessor.java:27)
>>>>        at 
>>>> org.apache.nifi.controller.StandardProcessorNode.onTrigger(StandardProcessorNode.java:1122)
>>>>        at 
>>>> org.apache.nifi.controller.tasks.ContinuallyRunProcessorTask.call(ContinuallyRunProcessorTask.java:147)
>>>>        at 
>>>> org.apache.nifi.controller.tasks.ContinuallyRunProcessorTask.call(ContinuallyRunProcessorTask.java:47)
>>>>        at 
>>>> org.apache.nifi.controller.scheduling.QuartzSchedulingAgent$2.run(QuartzSchedulingAgent.java:161)
>>>>        at 
>>>> java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
>>>>        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
>>>>        at 
>>>> java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
>>>>        at 
>>>> java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
>>>>        at 
>>>> java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
>>>>        at 
>>>> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
>>>>        at java.lang.Thread.run(Thread.java:748)
>>>> Caused by: sun.security.validator.ValidatorException: PKIX path building 
>>>> failed: sun.security.provider.certpath.SunCertPathBuilderException: unable 
>>>> to find valid certification path to requested target
>>>>        at 
>>>> sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:397)
>>>>        at 
>>>> sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:302)
>>>>        at sun.security.validator.Validator.validate(Validator.java:260)
>>>>        at 
>>>> sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
>>>>        at 
>>>> sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229)
>>>>        at 
>>>> sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
>>>>        at 
>>>> sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1596)
>>>>        ... 39 common frames omitted
>>>> Caused by: sun.security.provider.certpath.SunCertPathBuilderException: 
>>>> unable to find valid certification path to requested target
>>>>        at 
>>>> sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
>>>>        at 
>>>> sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
>>>>        at 
>>>> java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
>>>>        at 
>>>> sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:392)
>>>>        ... 45 common frames omitted
>>>>  
>>>>  
>>>> 
>>>> 
>>>>> On Thu, Dec 20, 2018 at 4:14 PM Andy LoPresto <[email protected]> 
>>>>> wrote:
>>>>> You need to configure the truststore properties in the SSLContextService 
>>>>> — the keystore contains the private key and public certificate the 
>>>>> service (NiFi) uses to identify itself, but the truststore contains the 
>>>>> public certificate(s) of external services NiFi should trust. In this 
>>>>> case, in order to connect to another service at 
>>>>> https://service.external.com, you will need to have the public 
>>>>> certificate (pub1) of the External Service or one of the public 
>>>>> certificates in the chain that signed that pub1. If this is a site on the 
>>>>> public internet, you can probably use the JVM defaults, as it will likely 
>>>>> be signed by a known certificate authority. If not, you must obtain that 
>>>>> public certificate independently, put it in a JKS truststore, and 
>>>>> populate the controller service properties for it. 
>>>>> 
>>>>> JVM truststore:
>>>>> 
>>>>> Path: $JAVA_HOME/jre/lib/security/cacerts (i.e. 
>>>>> /Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home/jre/lib/security/cacerts)
>>>>> Password: changeit (default)
>>>>> Type: JKS
>>>>> 
>>>>> 
>>>>> Andy LoPresto
>>>>> [email protected]
>>>>> [email protected]
>>>>> PGP Fingerprint: 70EC B3E5 98A6 5A3F D3C4  BACE 3C6E F65B 2F7D EF69
>>>>> 
>>>>>> On Dec 20, 2018, at 2:31 PM, l vic <[email protected]> wrote:
>>>>>> 
>>>>>> Hello,
>>>>>> I am trying to perform "get" request over SSL from InvokeHTTP 
>>>>>> nifi-1.5.0-RC1;
>>>>>> I configured SSL by the means of a StandardSSLContextService with jks 
>>>>>> certificate (see attached)
>>>>>> When I try to execute processor, i see the following problem:
>>>>>> Caused by: java.lang.IllegalStateException: TrustManagerFactoryImpl is 
>>>>>> not initialized
>>>>>>         at 
>>>>>> sun.security.ssl.TrustManagerFactoryImpl.engineGetTrustManagers(TrustManagerFactoryImpl.java:100)
>>>>>> Do I have an error in my configuration, or is this bug? keystore 
>>>>>> file/password combination is valid - i can do that request from cli.... 
>>>>>> Can I do "insecure" SSL request ( like curl -k) with InvokeHTTP?
>>>>>> Below is full stack trace
>>>>>> 
>>>>>> 2018-12-20 14:53:41,116 ERROR [StandardProcessScheduler Thread-3] 
>>>>>> o.a.n.controller.StandardProcessorNode Failed to invoke @OnScheduled 
>>>>>> method due to java.lang.RuntimeException: Failed while executing one of 
>>>>>> processor's OnScheduled task.
>>>>>> java.lang.RuntimeException: Failed while executing one of processor's 
>>>>>> OnScheduled task.
>>>>>>         at 
>>>>>> org.apache.nifi.controller.StandardProcessorNode.invokeTaskAsCancelableFuture(StandardProcessorNode.java:1504)
>>>>>>         at 
>>>>>> org.apache.nifi.controller.StandardProcessorNode.initiateStart(StandardProcessorNode.java:1330)
>>>>>>         at 
>>>>>> org.apache.nifi.controller.StandardProcessorNode.lambda$start$0(StandardProcessorNode.java:1315)
>>>>>>         at 
>>>>>> java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
>>>>>>         at java.util.concurrent.FutureTask.run(FutureTask.java:266)
>>>>>>         at 
>>>>>> java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
>>>>>>         at 
>>>>>> java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
>>>>>>         at 
>>>>>> java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
>>>>>>         at 
>>>>>> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
>>>>>>         at java.lang.Thread.run(Thread.java:748)
>>>>>> Caused by: java.util.concurrent.ExecutionException: 
>>>>>> java.lang.reflect.InvocationTargetException
>>>>>>         at java.util.concurrent.FutureTask.report(FutureTask.java:122)
>>>>>>         at java.util.concurrent.FutureTask.get(FutureTask.java:206)
>>>>>>         at 
>>>>>> org.apache.nifi.controller.StandardProcessorNode.invokeTaskAsCancelableFuture(StandardProcessorNode.java:1487)
>>>>>>         ... 9 common frames omitted
>>>>>> Caused by: java.lang.reflect.InvocationTargetException: null
>>>>>>         at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>>>>>>         at 
>>>>>> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
>>>>>>         at 
>>>>>> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>>>>>>         at java.lang.reflect.Method.invoke(Method.java:498)
>>>>>>         at 
>>>>>> org.apache.nifi.util.ReflectionUtils.invokeMethodsWithAnnotations(ReflectionUtils.java:137)
>>>>>>         at 
>>>>>> org.apache.nifi.util.ReflectionUtils.invokeMethodsWithAnnotations(ReflectionUtils.java:125)
>>>>>>         at 
>>>>>> org.apache.nifi.util.ReflectionUtils.invokeMethodsWithAnnotations(ReflectionUtils.java:70)
>>>>>>         at 
>>>>>> org.apache.nifi.util.ReflectionUtils.invokeMethodsWithAnnotation(ReflectionUtils.java:47)
>>>>>>         at 
>>>>>> org.apache.nifi.controller.StandardProcessorNode$1.call(StandardProcessorNode.java:1334)
>>>>>>         at 
>>>>>> org.apache.nifi.controller.StandardProcessorNode$1.call(StandardProcessorNode.java:1330)
>>>>>>         ... 6 common frames omitted
>>>>>> Caused by: java.lang.IllegalStateException: TrustManagerFactoryImpl is 
>>>>>> not initialized
>>>>>>         at 
>>>>>> sun.security.ssl.TrustManagerFactoryImpl.engineGetTrustManagers(TrustManagerFactoryImpl.java:100)
>>>>>>         at 
>>>>>> javax.net.ssl.TrustManagerFactory.getTrustManagers(TrustManagerFactory.java:285)
>>>>>>         at 
>>>>>> org.apache.nifi.processors.standard.InvokeHTTP.setSslSocketFactory(InvokeHTTP.java:613)
>>>>>>         at 
>>>>>> org.apache.nifi.processors.standard.InvokeHTTP.setUpClient(InvokeHTTP.java:545)
>>>>>>         ... 16 common frames omitted
>>>>>> <Screen Shot 2018-12-20 at 3.21.08 PM.png>

Reply via email to