This is the third part of a ThingBerry related blog post series.
ThingBerry is ThingWorx installed on a RaspBerry Pi, which can be used for portable demonstrations without the need of utilizing e.g. customer networks. Instead the ThingBerry provides its own custom WIFI hotspot and allows Things to connect and send / receive demo data on a small scale.
In this particual blog post we'll discuss on how to setup the ThingBerry for encrypted communication and trust via certificates. We will create a custom Root and Intermediate Certificate Authority as well as a server specific certificate.
More information on the theory of Trust & Encryption can be found here: Trust & Encryption - Theory
As the ThingBerry is a highly unsupported environment for ThingWorx, please see this blog post for all related warnings.
Preparing the environment
To get started and keep all the working materials safe and secure within the scope of the pi user account, let's start creating a workspace directory and then install the openssl package
cd ~ mkdir certs chmod 700 certs cd certs
sudo apt-get install openssl
To look at a specific certificate use the keytool and specify the .crt file to look at
keytool -printcert -file rootca.crt
This will show information on the certificate's configuration, such as signing authority or validity.
It's important, that the Chain of Trust follows a timely fashion.
The Root CA has the longest expiration date. Within its validity the Intermediate CA must be valid. The server specific certificate must be valid in the timeframe of the Intermediate CA validity.
As the validity is calculated based on seconds of the current (signing) action, I'm using valid days of
- Root CA 999 days
- Intermediate CA 888 days
- Server specific certificate 777 days
Any other times, that make sense can be used, as long as the time constraints are followed.
Otherwise the certificate will not be recognized as valid and will therefore not be trusted.
Creating a Chain of Trust
For this example we'll create a Root and Intermediate Certificate Authority (CA) as well as the server specific certificate. In a first step we can create all of the required keys.
openssl genrsa -des3 -out rootca.key 4096 openssl genrsa -out intermediateca.key 4096 openssl genrsa -out server.key 4096
The -des3 option for the rootca will store a password and encrypt it within the key for more secure access.
This tightens up security, so that the key for the rootca is not easily corrupted or exposed.
Root Certificate Authority
Having the keys, we now create the Root CA itself
openssl req -new -x509 -sha256 -days 999 -key rootca.key -reqexts v3_req -extensions v3_ca -out rootca.crt
Enter the information, starting with the password for the Root CA key.
Use a easy to identify name for the Common Name (CN), e.g. "My Root CA"
Intermediate Certificate Authority
As the Intermediate CA needs to be signed / approved by the Root CA, we need a Certficiate Signing Request (CSR)
openssl req -new -key intermediateca.key -reqexts v3_req -extensions v3_ca -out intermediateca.csr
The v3_ca extension will mark this certificate as CA itself.
This means that we can use the intermediate CA to sign other certificates as well.
The CSR will be signed with the Root CA's key and certificate.
For this the CSR must be sent to the whoever own the Root CA.
In our case, we're the owner ourselves and have everything in the same directory, so no need to send it off to Let's Encrypt, Google or VeriSign.
For signing the Intermediate CA as an actual CA, the Root CA must have a specific configuration to allow the v3_ca extension. This needs to be created via
Into this new file, copy & paste the following:
basicConstraints = CA:TRUE subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always,issuer:always keyUsage = cRLSign, dataEncipherment, digitalSignature, keyCertSign, keyEncipherment, nonRepudiation
Save and exit.
Finally, the Root CA is signing the Intermediate CA, using the v3_ca extension via:
openssl x509 -req -in intermediateca.csr -CA rootca.crt -CAkey rootca.key -CAcreateserial -CAserial intermediateca.srl -extfile v3_ca.ext -days 888 -sha256 -out intermediateca.crt
Certificate Authority Chain
Having now two CAs, they need to be chained together.
This is required for later to create the keystore used in Tomcat.
Creating the Chain is probably the easiest part of this blog:
cat intermediateca.crt rootca.crt > cachain.crt
Server Specific Certificate
The server specific certificate has to be signed and obtained by the Intermediate CA; for this a CSR is required.
openssl req -new -key server.key -out server.csr
The request is then signed with the Intermediate CA's key and certificate.
For commerical certificates this signing process will be done by publicly trusted CAs, like Let's Encrypt, VeriSign or Google.
In our case, we're the Intermediate CA ourselves and can sign the CSR.
openssl x509 -req -in server.csr -CA intermediateca.crt -CAkey intermediateca.key -CAcreateserial -CAserial server.srl -days 777 -sha256 -out server.crt
For the keystore as used in Tomcat we need the CA Chain as well as the server specific certificate and the corresponding key.
To generate a keystore that can be used in Tomcat, we first need to create a PKCS12 type keystore with openssl
openssl pkcs12 -export -certfile cachain.crt -in server.crt -inkey server.key -out server.p12
keytool -importkeystore -srckeystore server.p12 -srcstoretype PKCS12 -destkeystore keystore.jks -deststoretype JKS
Important: the passwords for the PKCS12 keystore and the JKS keystore must match!
Tomcat requires those passwords to be same - in case they are different, the configuration will not work and ThingWorx cannot be accessed through a secure connection.
For ThingWorx, only the keystore is required.
It can be copied over e.g. to certificates area in the storage directory.
sudo cp keystore.jks /thingworx/storage/certificates sudo chmod 640 /thingworx/storage/certificates/keystore.jks sudo chown tomcat:tomcat /thingworx/storage/certificates/keystore.jks
To enable it, Tomcat's server.xml needs to be updated.
sudo nano $CATALINA_HOME/conf/server.xml
Find the connector for port 80 and add a new connector after the port 80 connector:
<Connector port="443" protocol="org.apache.coyote.http11.Http11NioProtocol" maxThreads="150" connectionTimeout="20000" redirectPort="8443" SSLEnabled="true" scheme="https" secure="true" clientAuth="false" sslProtocol="TLSv1.2" enableLookups="false" keystoreFile="/thingworx/storage/certificates/keystore.jks" keystorePass="<keystorePass>" />
Don't forget to update the password.
sudo service tomcat stop
Ensure Tomcat is actually down with
ps -ef | grep tomcat
If it's still running, just sudo kill it and start Tomcat again to activate the new configuration
sudo service tomcat start
ThingWorx is now running on your ThingBerry using a secure channel.
Access it via https://<thingberry>/Thingworx
As HTTPS is automatically using port 443, you will automatically connect to the port configured in the server.xml
Classic HTTP connections on port 80 can still be used.
For more information about setting up ThingWorx with (self-signed) certificates also see https://support.ptc.com/appserver/cs/view/solution.jsp?n=CS193947 - there's also a note on forwarding all HTTP traffic to HTTPS.
See also https://support.ptc.com/appserver/cs/view/solution.jsp?n=CS246292 for more information about using specific SSL protocols or cipher suites.