2

I'm trying to configure websphere-liberty server to use default keystore and trustore for all outbound connections (actually REST calls) and for inbound use a custom key and trust stores. But it fails with SSLHandshakeException when try to make a call to external REST service. In logs I can see that it uses my custom truststore instead of default one.
Below is my server.xml

<?xml version="1.0" encoding="UTF-8"?>
<server description="Default server">
    <featureManager>
        <feature>appSecurity-2.0</feature>
        <feature>transportSecurity-1.0</feature>
        <feature>jaxrs-2.0</feature>
        <feature>json-1.0</feature>
        <feature>javaMail-1.5</feature>
        <!--<feature>ssl-1.0</feature>-->
    </featureManager>

    <sslDefault sslRef="saasSSLConfig" outboundSSLRef="outboundSSLConfig" />

    <ssl id="saasSSLConfig" keyStoreRef="saasKeyStore" trustStoreRef="saasTrustStore" clientAuthentication="true" sslProtocol="TLSv1" />
    <keyStore id="saasKeyStore" location="/opt/ibm/wlp/output/defaultServer/resources/security/sbs_endpoint_keystore.jks" password="pwd" />
    <keyStore id="saasTrustStore" location="/opt/ibm/wlp/output/defaultServer/resources/security/serverTruststore.jks" password="pwd" />

    <ssl id="outboundSSLConfig" keyStoreRef="defaultKeyStore" trustStoreRef="defaultTrustStore" />

    <basicRegistry id="basic" realm="BasicRealm">
        <!-- <user name="yourUserName" password="" />  -->
    </basicRegistry>

    <httpEndpoint id="defaultHttpEndpoint" host="*" httpPort="9080" httpsPort="9443" />
    <applicationManager autoExpand="true"/>
</server>

BTW if change saasSSLConfig to use defaultTrustStore instead of saasTrustStore then everything works fine.

Server version:

WebSphere Application Server 17.0.0.2 (1.0.17.cl170220170523-1818) on IBM J9 VM, version pxa6480sr4fp7-20170627_02 (SR4 FP7) (en_US)

Error:

[ERROR] CWPKI0022E: SSL HANDSHAKE FAILURE:  A signer with SubjectDN CN=*.api.ibm.com, O=International Business Machines, L=Armonk, ST=New York, C=US was sent from the target host.  The signer might need to be added to local trust store /opt/ibm/wlp/output/defaultServer/resources/security/serverTruststore.jks, located in SSL configuration alias saasSSLConfig.  The extended error message from the SSL handshake exception is: PKIX path building failed: java.security.cert.CertPathBuilderException: PKIXCertPathBuilderImpl could not build a valid CertPath.;
SSLHandshakeException invoking https://dev.api.ibm.com/scx/test/sbs/customer/222222222: java.security.cert.CertificateException: PKIXCertPathBuilderImpl could not build a valid CertPath.
Andy Guibert
  • 41,446
  • 8
  • 38
  • 61
Yuriy Bondaruk
  • 4,512
  • 2
  • 33
  • 49

2 Answers2

1

Liberty does not load cacerts automatically. You can create a keyStore element to point to it if desired. So in your case above you can create a configuration like this.

<ssl id="outboundSSLConfig" keyStoreRef="cacertKeyStore" />
<keyStore id="cacertKeyStore" location=<fill in path to your jdk cacerts file> password="changeit" />

I am assuming you do not need a key for this configuration so I simplified to just a keyStoreRef on outboundSSLConfig. It will use what is pointed to by keyStoreRef for both key and trust.

Alaine
  • 419
  • 2
  • 5
  • It works like that but then I don't understand why it also work if remove outbound SSL settings and use 'trustStoreRef="defaultTrustStore"' for 'saasSSLConfig'? I would expect some error (like 'defaultTrustStore' is undefined) or fall back to use 'saasKeyStore' as a trustStore but it succeeded instead (so used java's defaul cacerts file). – Yuriy Bondaruk Aug 11 '17 at 17:26
  • Perhaps there should be some kind of error message saying your configuration is not valid so it just ignored. But what happens in the scenario you explain is that "defaultTrustStore" is a in valid config, does not exist so "saasSSLConfig" is also an invalid config. So that is really leaving your Liberty server without a Liberty SSL configuration, your server inbound port https port is probably not starting. In this case jaxrs will just pass on to the JSSE default SSLContext. – Alaine Aug 11 '17 at 19:45
0

In your configuration I do not see keyStore elements for defaultKeyStore and defaultTrustStore. If they are missing that will cause outboundSSLConfig to be an invalid SSL configuration. Can you please add them and see if things work.

Alaine
  • 419
  • 2
  • 5
  • Well, I expected that defaultKeyStore and defaultTrustStore are defined by the liberty server for cases when there are no keyStore and trustStore defined in SSL settings. And the defaultTruststore is using java's cacerts. Isn't like that? How to configure a liberty server to use default java cacerts truststore for all outbound connections? – Yuriy Bondaruk Aug 11 '17 at 13:41
  • Liberty does not load the cacerts file, not unless you add it to the configuration. If you had scenario where the cacerts file is being used then it's because the connection is using the JSSE's default SSLContext and somehow bypassing Liberty SSL. An example of adding cacerts to the configuration is above – Alaine Aug 11 '17 at 18:27
  • I've enabled tracing logs and found that in both cases uses com.ibm.ssl.contextProvider=IBMJSSE2 (com.ibm.ws.ssl.provider.IBMJSSEProvider). So the config difference is in these two lines: [FAILS] ; [SUCCESS] – Yuriy Bondaruk Aug 11 '17 at 19:55
  • You will always see com.ibm.ssl.contextProvider=IBMJSSE2 in the properties. The question is do you see Liberty create a SSLContext? I would expect to create a SSLContext, should see it in the trace. is not valid because the truststore is not there so no SSLContext created. In that case jaxrs will pass on to the JDK/JSSE. – Alaine Aug 11 '17 at 20:13