Skip to content
Matt Magoffin edited this page Dec 10, 2012 · 14 revisions

SolarNetwork Developer PKI Guide

This page describes how to set up PKI support when developing SolarNode <-> SolarNet secure communication. This guide assumes you have your Eclipse development environment set up as well as the SolarNode and SolarNet environments.

Configure a development DNS name

For TLS to work you'll need to use a DNS name, which you can make up and assign in your system's host file. For example on Unix systems, you can usually add a line to /etc/hosts like this:

127.0.0.1	solarnetworkdev.net

Whatever name you choose, it must match what we configure in the server's certificate subject later on in this guide.

Set up Certification Authority (CA)

You must create a Certification Authority that will act as the trusted root for the SolarNetwork platform. There are several ways to accomplish this, but this guide will show how using OpenSSL. There are lots of references such as this or that to help you create the CA self-signed certificate and then sign other certificates with that CA certificate. We'll describe one method here, creating a CA root certificate CN=Developer CA, O=SolarDev on a Unix platform.

OpenSSL expects a certain directory layout for its ca tool to function. Create that structure with the following command:

mkdir -m 0700 CA CA/certs CA/crl CA/newcerts CA/private

Now we'll create our CA private key and then the CA root certificate:

# Create a private key of 4096 bits
openssl genrsa -des3 -out CA/private/ca.key 4096

# Create a self-signed root "CA" certificate using our private key, that expires in 10 years
openssl req -new -x509 -extensions v3_ca -key CA/private/ca.key -out CA/certs/ca.crt \
	-days 3650 -subj '/CN=Developer CA/O=SolarDev/'
	
# Create some database files the 'ca' tool needs
touch CA/index.txt
echo '01' >CA/serial

Now create a policy file for the CA, named policy.cfg with the following contents:

[ ca ]
default_ca      = CA_solardev

[ CA_solardev ]

dir            = ./CA
database       = $dir/index.txt
new_certs_dir  = $dir/newcerts

certificate    = $dir/certs/ca.crt
serial         = $dir/serial
private_key    = $dir/private/ca.key
RANDFILE       = $dir/private/.rand

default_days   = 3650
default_crl_days= 30
default_md     = md5

policy         = policy_solardevweb
email_in_dn    = no                    # Don't add the email into cert DN

name_opt       = ca_default            # Subject name display option
cert_opt       = ca_default            # Certificate display option
copy_extensions = none                 # Don't copy extensions from request

[ policy_solardevweb ]
organizationName       = supplied
commonName             = supplied

[ policy_solardevnode ]
organizationName       = supplied
userId            	   = supplied

Notice we've declared two policy sections, one named solardevweb and the other solardevnode. The web policy is for our webserver certificate, whose subject will take the form CN=solarnetworkdev.net,O=SolarDev. The CN in the subject must match the DNS name you created earlier. The node policy is for our node certificate(s), whose subject will take the form UID=1,O=SolarDev. The UID in the subject will contain the node's unique ID.

Generate Development webserver certificate

The SolarNet server will need a server TLS certificate now to complete the secure connection to the SolarNode. First you must generate a new private key and CSR for the webserver, which must use the same DNS name you created earlier, solarnetworkdev.net:

# Create a 2048-bit webserver certificate signing request (CSR) for the domain 'solarnetworkdev.net'
openssl req -new -nodes -newkey rsa:2048 -keyout solarnetworkdev.key \
	-out solarnetworkdev.csr -days 3650 -subj '/CN=solarnetworkdev.net/O=SolarDev/'

Now sign the webserver certificate with our CA's private key, using the web policy:

openssl ca -in solarnetworkdev.csr -out CA/certs/solarnetworkdev.crt \
	-config policy.cfg -policy policy_solardevweb 

Use OpenSSL to export the certificates as a PKCS#12 file, with the webserver certificate named central and the CA certificate ca:

openssl pkcs12 -export -in CA/certs/solarnetworkdev.crt -inkey solarnetworkdev.key \
	-out solarnetworkdev.net.p12 -name central -CAfile CA/certs/ca.crt -caname ca -chain

It will ask you to assign a password. Use the same password you configured in the PKIService.manualKeyStorePassword setting, for example dev123. Now move the generated file to /solarnetwork-osgi-target/conf/tls/solarnetworkdev.net.p12.

Configure Tomcat with TLS support

If you haven't already created the /solarnetwork-osgi-target/config/tomcat-server.xml file, copy the example file from /solarnetwork-osgi-target/example/config. Then add (or uncomment the example) TLS Connector element, which should look like this:

	<Connector port="8683" protocol="HTTP/1.1" SSLEnabled="true"
		maxThreads="25" scheme="https" secure="true" sslProtocol="TLS"
		keyAlias="central" keystoreType="pkcs12"
		keystoreFile="conf/tls/solarnetworkdev.net.p12" keystorePass="dev123"
		truststoreFile="conf/tls/solarnetworkdev.net.p12" truststorePass="dev123"
		clientAuth="want"/>

Note the port setting, which you'll need to also configure the same value for later on. Also note the keystorePass and truststorePass values. We're using the same file as the key store and trust store, so the passwords will be the same value you used when you created the PKCS#12 file with OpenSSL.

Also in the tomcat-server.xml file, you must modify the Engine and Host elements to use the DNS name you created earlier and is the CN portion of your webserver certificate subject:

<Engine name="Catalina" defaultHost="solarnetworkdev.net">
	<Host name="solarnetworkdev.net" unpackWARs="false" autoDeploy="false"
		liveDeploy="false" deployOnStartup="false" xmlValidation="false"
		xmlNamespaceAware="false"/>
</Engine>

Notice the Engine/@defaultHost attribute and the Host/@name attribute both use our DNS name now. Most likely they would have had localhost used before you change them.

Create initial node key store

Since our Tomcat certificate is from our own CA, our node won't be able to communicate with Tomcat unless we add the CA's certificate to the node's trust store. That just means we need to create the node's key store with the CA certificate already in it. The node expects a key store in the Java jks format. We can use the open source tool Portecle to copy our Tomcat PKCS#12 trust store into a new JKS store.

Open Portecle and then open the solarnetworkdev.net.p12 file. It should contain two entries: ca and central. We don't need the central key pair, so you can delete that. Then, use the Tools > Change Keystore Type > JKS menu to convert the format. Finally, use the Tools > Save Keystore As... menu to save the store to a new file named /solarnetwork-osgi-target/conf/tls/node.jks.

Configure development settings

You need to configure some development settings in the /solarnetwork-osgi-target/configurations/services directory.

File Description
net.solarnetwork.central.in.cfg

Configure the host as the DNS name you assigned earlier, and the same port that you configured the Tomcat server to use. For example:

			<p><code>SimpleNetworkIdentityBiz.host = solarnetworkdev.net<br/>
			SimpleNetworkIdentityBiz.port = 8683<br/>
			SimpleNetworkIdentityBiz.forceTLS = true</code></p>
			<br/>
		</td>
	</tr>
	<tr>
		<td><b>net.solarnetwork.central.user.biz.cfg</b></td>
		<td>
			<p>Configure a development certificate subject DN template that matches the PKI infrastructure you want to set up. For example:</p>
			
			<p><code>RegistrationBiz.networkCertificateSubjectDNFormat = UID=%s,O=SolarDev</code></p>
			<br/>
		</td>
	</tr>
	<tr>
		<td><b>net.solarnetwork.node.setup.cfg</b></td>
		<td>
			<p>Configure a simple manual password for the node's key store. This will simplify configuring TLS in Tomcat. For example:</p>
			
			<p><code>PKIService.manualKeyStorePassword = dev123</code></p>
			<br/>
		</td>
	</tr>
</tbody>

Next you need to update the OSGi runtime in Eclipse so the node uses the node.jks file as its trust store, enabling it to "trust" your CA root certificate. Go to **Run > Run Configurations... > OSGi Framework > SolarNetwork ** and select the Arguments tab. Add the following to the VM arguments field:

-Djavax.net.ssl.trustStore=conf/tls/node.jks -Djavax.net.ssl.trustStorePassword=dev123

Associate a new node

Start up the SolarNetwork OSGi platform in Eclipse, and then use the SolarNet registration app (/solarreg) to register yourself as a new SolarNet user (if you haven't already). You can use the net.solarnetwork.central.common.mail.mock bundle to have the user registration code logged to the console rather than relying on an actual email to be sent. Once registered, invite a new SolarNode (under the My Nodes section). Copy the invitation code, then go to the SolarNode setup app (/setup). Paste in the invitation and complete the association process.

At this point, you'll have assigned the node an ID and generated a CSR for the node's certificate. Save this to a file, for example 1013.csr. Here I'm using the assigned node ID 1013 but your node ID will probably be different.

Sign the node's CSR

openssl ca -in 1013.csr -out CA/certs/1013.crt \
	-config policy.cfg -policy policy_solardevnode

Then create a PKCS#7 chain file to import into the SolarNode app:

openssl crl2pkcs7 -nocrl -certfile CA/certs/ca.crt -certfile CA/certs/1013.crt \
	-out 1013-chain.p7p

Now use the Certificates section on the SolarNode app to import the certificate chain you created. When all is finally complete, you should end up with a screen similar to the following:

Clone this wiki locally