TDIing out loud

Ramblings on the paradigm-shift that is TDI.

Monday, December 12, 2016

Importing a client certificate in order to access an https URL

When you go to make an HTTP request to a service that requires an SSL connection, you'll get an exception that your HTTP Client Connector cannot set up the secure link to the service. Unlike your browser, TDI (SDI) does not automatically import the client certificate. You have to do this yourself, and this post is about how to do this.

For this example, we'll try to access https://login.salesforce.com

If you enter this URL into an HTTP Client Connector and attempt a connection either by pressing the Connect and Next buttons in the Schema area of an Attribute Map, or by dropping the Connector into an AL and running it, then you will see this error:

ERROR - [HTTPClientConnector] CTGDIS810E handleException - cannot handle exception , callreply 
javax.net.ssl.SSLHandshakeException: com.ibm.jsse2.util.j: PKIX path building failed: java.security.cert.CertPathBuilderException: PKIXCertPathBuilderImpl could not build a valid CertPath.; internal cause is: 
java.security.cert.CertPathValidatorException: The certificate issued by CN=VeriSign Class 3 Public Primary Certification Authority - G5, OU="(c) 2006 VeriSign, Inc. - For authorized use only", OU=VeriSign Trust Network, O="VeriSign, Inc.", C=US is not trusted; internal cause is: 
java.security.cert.CertPathValidatorException: Certificate chaining error
at com.ibm.jsse2.j.a(j.java:10)
at com.ibm.jsse2.qc.a(qc.java:359)

This error is telling us that we are missing the required client certificate. An easy fix available directly in the CE is to press the Get Certificate button located to the right of the HTTP URL parameter in the Connector's Connection tab.



This handy button will request the certificate and then store it in the TDI Server's keystore (as specified in the solution.properties file by the property named javax.net.ssl.trustStore).



Once imported, the Java VM needs a restart in order for it to use this newly acquired cert. This means that you must recycle your TDI Server before a successful connection is possible.

This is all well and good, but if you're scripting your own components then it would be better if the missing certificate could be detected and then automatically imported. Fortunately, this is very simple to do with a single line of script in TDI.

msg = com.ibm.di.security.GetSSLCertificate.installCertificateFrom(baseurl, 443)

The baseurl argument is the 'https://...' address you want to access, and 443 is the default port for HTTPS. If the socket you are trying to reach includes a specific port number, then you can use this in the above call. If the request or the keystore update fail then the returned String is an error message describing this failure. If the client cert exists already in your keystore, then the message will tell you that the cert is already trusted. And if the requested certificate is successfully added to your keystore, the message will indicate this.

CTGDIS1957I Added certificate with subject: CN=login.salesforce.com, OU=Applications, O="Salesforce.com, Inc", L=San Francisco, ST=California, C=US.

Once TDI has been restarted then you can make secure connections to this service.

8 comments:

Pieter Geerts said...

cool, does this also work for ldaps://... ?

Eddie Hartman said...

It should. Away from my PC, so I'm being optimistic, Pieter :)

Ninad Tamras said...

I don't see the Get Certificate button in the Connection tab of the HTTP Client connecter..

Also, when i try to execute the script you have mentioned above, it gives exception saying com not found. I tried adding Packages.com... but it gives error as "Error calling method 'GetSSLCertificate()': 'Packages.com.ibm.di.security' is not a valid object"

I am using TDI 7.1.1

Eddie Hartman said...

Hi @Ninad. That will depend on the version your are running. If you have TDI 7.1 or 7.1.1 then I think all you need is to install the latest fixpack for that version.

Ninad Tamras said...

Thanks @Eddie.

Upgrading the TDI is not the option at this moment.

Is there an alternate way to do it in the existing TDI?

Ninad Tamras said...

I manually added the cert to the truststore jks and got it working.

Arif said...

Hi Eddie

I have click on "Get certificate" button in http client connector and got message "Connection is already trusted" and then restared the TDI.

While running the assembly line getting this error "PKIX path building failed: java.security.cert.CertPathBuilderException: PKIXCertPathBuilderImpl could not build a valid CertPath.; internal cause is: "

Eddie Hartman said...

@Arif You could try deleting the cert from your keystore and then re-importing it. See if that helps. Also, drop your question(s) into the TDI forum and give lots of sharp TDIers a chance to answer you :)
https://groups.google.com/group/ibm.software.network.directory-integrator/topics?gvc=2