Common Errors

1. Common Errors

This page exists to help people resolve errors that may arise in certain configurations of CleanSpeak.

1.1. SSL Validation Errors

If you find SSL validation errors in the logs when connecting to a database or Elasticsearch then it means that whatever certificate your service is using is not explicitly shipped with Java or that certificate is not signed by a known certificate authority (at least not one that is shipped with Java by default). In order to fix this, you will need to add either that certificate or the root certificate it was signed with to the cacerts file in the CleanSpeak installation.

You can obtain the root certificate from the certificate authority of the service in most cases. Ex: GoDaddy certificates.

All of the following assume that CleanSpeak was installed on a 'nix type system via package manager. If you used zip files then modify all of the paths provided to suit your installation location.

1.1.1. General Solution

Run the following on the machine that is running CleanSpeak and replace the variable values with your cert location and a name for that certificate.

# Replace the values of these variables
CERT=/location/of/the/cert/you/want/to/add
ALIAS=a_name_for_this_cert

# Add the keytool to the path
PATH=/usr/local/cleanspeak/java/current/bin:$PATH

# This command adds the given cert under the name provided in alias to the cacerts that CleanSpeak uses
keytool -import -file ${CERT} -alias "${ALIAS}" -storepass changeit -keystore /usr/local/cleanspeak/java/current/lib/security/cacerts -noprompt

# Repeat for webservice (if on CleanSpeak 3.x)
keytool -import -file ${CERT} -alias "${ALIAS}" -storepass changeit -keystore /usr/local/cleanspeak/java/current/lib/security/cacerts -noprompt

1.1.2. Workaround (MySQL only)

An alternative solution is to use the parameter string: &useSSL=true&verifyServerCertificate=false&allowPublicKeyRetrieval=true which will allow you to use encrypted connections without needing to have the cert explicitly in the truststore. This is the default behavior for enabling TLS via maintenance mode.

1.1.3. Docker (Solution 1)

One solution for docker is to create a cacerts file similar to that of the general solution and mount it without the need to modify the provided images.

  1. First obtain a copy of cacerts

    1. You can do this via docker cp from a running CleanSpeak container. (Emphasis on running container. You cannot copy from an image) Ex: docker cp <containerId>:/usr/local/cleanspeak/java/current/lib/security/cacerts cacerts

  2. Add your cert to the copy of cacerts using keytool -import -file ${CERT} -alias "${ALIAS}" -storepass changeit -keystore cacerts -noprompt

  3. When starting the images, mount the cacerts to the containers (these are 3.x container images, 4.x is a single image of cleanspeak/cleanspeak-app)

    1. docker run -p 8011:8011 -v $(pwd)/cacerts:/usr/local/cleanspeak/java/current/lib/security/cacerts cleanspeak/cleanspeak-management-interface:latest

    2. docker run -p 8001:8001 -v $(pwd)/cacerts:/usr/local/cleanspeak/java/current/lib/security/cacerts cleanspeak/cleanspeak-webservice:latest

1.1.4. Docker (Solution 2) - 3.x

An alternative solution is to create a dockerfile like the following that allows you to have an image with the modified cacerts file and no need to mount a volume/file.

FROM cleanspeak/cleanspeak-management-interface:latest

COPY ./cert.pem /cert.pem

## Patch the truststore in the java shipped with CleanSpeak
RUN /usr/local/cleanspeak/java/current/bin/keytool -import -file /cert.pem -alias "some_name_for_a_cert" -storepass changeit -keystore /usr/local/cleanspeak/java/current/lib/security/cacerts -noprompt

# Allows docker to simply call run on the image
USER cleanspeak
CMD /usr/local/cleanspeak/cleanspeak-management-interface/apache-tomcat/bin/catalina.sh run

Repeat this for webservice:

FROM cleanspeak/cleanspeak-webservice:latest

COPY ./cert.pem /cert.pem

## Patch the truststore in the java shipped with CleanSpeak
RUN /usr/local/cleanspeak/java/current/bin/keytool -import -file /cert.pem -alias "some_name_for_a_cert" -storepass changeit -keystore /usr/local/cleanspeak/java/current/lib/security/cacerts -noprompt

# Allows docker to simply call run on the image
USER cleanspeak
CMD /usr/local/cleanspeak/cleanspeak-webservice/apache-tomcat/bin/catalina.sh run

Build and use these new images in place of the ones we ship. To update CleanSpeak, simply pull the CleanSpeak images and build these dockerfiles again.

1.1.5. Docker (Solution 2) - 4.x

An alternative solution is to create a dockerfile like the following that allows you to have an image with the modified cacerts file and no need to mount a volume/file.

FROM cleanspeak/cleanspeak-app:latest

COPY ./cert.pem /cert.pem

## Patch the truststore in the java shipped with CleanSpeak
RUN /usr/local/cleanspeak/java/current/bin/keytool -import -file /cert.pem -alias "some_name_for_a_cert" -storepass changeit -keystore /usr/local/cleanspeak/java/current/lib/security/cacerts -noprompt

# Allows docker to simply call run on the image
USER cleanspeak
CMD /usr/local/cleanspeak/cleanspeak-app/bin/start.sh

Build and use this new image in place of the ones we ship. To update CleanSpeak, simply pull the CleanSpeak images and build these dockerfiles again.

1.1.6. Many certs (advanced)

In some cases you may need to add more than one certificate to the cacerts. In this case, using the rds example as a base, the following script will add all of the rds certificates to a new cacerts file which can then be merged with the cacerts provided with CleanSpeak. Modify the script as necessary if you want to add a different set of certificates but keep in mind that this script expects a chained pem file.

This script requires a system with keytool in the path, split with a -p parameter, and openssl installed.

mydir=/tmp/certs
truststore=${mydir}/rds.jks
storepassword=changeit

mkdir -p $mydir
curl -sS "https://s3.amazonaws.com/rds-downloads/rds-combined-ca-bundle.pem" > ${mydir}/rds-combined-ca-bundle.pem
split -p "-----BEGIN CERTIFICATE-----" ${mydir}/rds-combined-ca-bundle.pem rds-ca-

for CERT in rds-ca-*; do
  alias=$(openssl x509 -noout -text -in $CERT | perl -ne 'next unless /Subject:/; s/.*CN=//; print')
  echo "Importing $alias"
  keytool -import -file ${CERT} -alias "${alias}" -storepass ${storepassword} -keystore ${truststore} -noprompt
  rm $CERT
done

rm ${mydir}/rds-combined-ca-bundle.pem

echo "Trust store content is: "

keytool -list -v -keystore "$truststore" -storepass ${storepassword} | grep Alias | cut -d " " -f3- | while read alias
do
   expiry=`keytool -list -v -keystore "$truststore" -storepass ${storepassword} -alias "${alias}" | grep Valid | perl -ne 'if(/until: (.*?)\n/) { print "$1\n"; }'`
   echo " Certificate ${alias} expires in '$expiry'"
done

And finally, merge the new cacerts into the ones shipped in CleanSpeak with the following:

keytool -importkeystore -srckeystore /usr/local/cleanspeak/java/current/rds.jks -destkeystore /usr/local/cleanspeak/java/current/lib/security/cacerts \
-deststorepass changeit -srcstorepass changeit -noprompt