Configuring TLS/SSL certificates for a WSO2 deployment

Using Subject Alternative Names for multiple hostnames

With latest versions of WSO2 products, its recommended to have a separate Keystore for authenticating communication over SSL/TLS (for both Tomcat and Axis2 level HTTP connections).

You probably might have come across following errors in a wso2 deployment

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)

or

javax.net.ssl.SSLException: hostname in certificate didn't match: <ip address> != <localhost>

Both above are very common errors people get when the certificate configurations between the components are not right.

This happens when the public certificate of the other component is not available in the client-truststore.jks file.

eg: Suppose you get above error in the API Manager Gateway while trying to communicate with Key Manager. In that case Key Manager’s public certificate should be available in the Gateway’s client-truststore.jks

There is an in-built host-name-verifier comes with WSO2 products. If the actual hostname of the server and the hostname configured in the certificate doesnt match, then you may see above error in your carbon log. There is a way to disable this hostname verification, but its not recommended.

When you define a key pair, you specify the hostname of the servers that the certificate belongs to. If the certificate is for a single server then you might add the hostname under Common Name (CN) in the certificate. Or you can use Subject Alternative Names (SANs) to add multiple hostnames for that certificate.

Usually in a WSO2 deployment, there are more than one WSO2 component. eg: APIM,APIM-Analytics, EI-integrator, EI-Analytics, IAM(IS) etc

Some deployments have fully/partially distributed APIM setups. Which means different APIM profiles are separated out and running as different servers depending on the traffic/load and many other factors. eg: APIM-Gateway, APIM-KeyManager, APIM-TrafficManager, APIM-Publisher, APIM-Devportal etc.

  • If your deployment contains multiple products, instances of the same product must use the same keystore for SSL. Different products can use different keystores for SSL, but it is not mandatory.
  • It is recommended to use a CA-signed keystore for SSL communication; however, this is not mandatory. Even a self-signed certificate may suffice if it can be trusted by the clients.
  • If this is a non-production environment, then adding self signed certs are fine(if your company doesn’t have an internal policy to have CA signed certs in all the environments).
  • If its a production environment then its recommended to have a properly signed(from a CA authority) cert. For that we can usually generate Certificate Signing Requests(CSRs) and send to the relevant authority to Sign it for us.

For more information on Setting up Keystores can be found in below link

As per the WSO2 recommendation, we can achieve this in 3 steps.

Create single keystore containing a key for all WSO2 components. We use Subject Alternative Names (SANs) to include all hostnames. You can use any name for the file and key alias. Here im using “wso2carbon.jks” as my TLS keystore name and wso2carbon as the alias.

Here also you have two options, You can either generate a keystore using an already existing public key certificate (CA-signed), or you can create the public key certificate at the time of generating the keystore. Please read WSO2 official documentation for more details.

Here Im going to create a new keystore with new key pair. Please note how extra hostnames/ips are added.

keytool -genkey -alias wso2carbon -keyalg RSA -keysize 2048 -validity 3650 -keystore wso2carbon.jks -dname "CN=*.mycompany.com,OU=Support,O=WSO2,L=Colombo,S=Western,C=LK" -ext "SAN=IP:10.100.0.1,IP:192.168.0.1,DNS:keymanager.dev.mycompany.com,DNS:pubstore.dev.mycompany.com" -storepass wso2carbon -keypass wso2carbon -noprompt

Without SANs

keytool -genkey -alias wso2carbon -keyalg RSA -keysize 2048 -validity 3650 -keystore wso2carbon.jks -dname "CN=*.mycompany.com,OU=Support,O=WSO2,L=Colombo,S=Western,C=LK" -storepass wso2carbon -keypass wso2carbon -noprompt
keytool -export -alias wso2carbon -file pubkey.crt -keystore wso2carbon.jks -storepass wso2carbon -noprompt
keytool -import -trustcacerts -alias wso2carbon -file pubkey.crt -keystore client-truststore.jks -storepass wso2carbon -noprompt

Use same jks files in all the servers in one specific environment. Copy above client-truststore.jks and wso2carbon.jks to PRODUCT_HOME/repository/resources/security directory in all your WSO2 components.

Cheers!! :)