X-Git-Url: https://review.fuel-infra.org/gitweb?a=blobdiff_plain;f=website%2Fdeploy%2Fmiddleware%2Factivemq_keystores.md;fp=website%2Fdeploy%2Fmiddleware%2Factivemq_keystores.md;h=0d7ad05d1009c35a51f665e90bc4b1bddf60346f;hb=8fd0f35facc21b89b378ecfb253e06a66af1e422;hp=0000000000000000000000000000000000000000;hpb=327162e6e319ff38447992668e0753363b870b6e;p=packages%2Fprecise%2Fmcollective.git diff --git a/website/deploy/middleware/activemq_keystores.md b/website/deploy/middleware/activemq_keystores.md new file mode 100644 index 0000000..0d7ad05 --- /dev/null +++ b/website/deploy/middleware/activemq_keystores.md @@ -0,0 +1,273 @@ +--- +title: "MCollective » Deploy » Middleware » ActiveMQ Keystores" +subtitle: "Setting Up Keystores For ActiveMQ" +layout: default +--- + +[tls]: ./activemq.html#tls-credentials + +Since ActiveMQ runs on the JVM, [configuring it to use TLS encryption/authentication][tls] requires a pair of Java keystores; it can't just use the normal PEM format certificates and keys used by Puppet and MCollective. + +Java keystores require some non-obvious steps to set up, so this guide provides full instructions, including both a [manual method](#manually-creating-keystores) and a [Puppet method](#creating-keystores-with-puppet). + + +## Step 0: Obtain Certificates and Keys + +ActiveMQ needs the following credentials: + +* A copy of the site's CA certificate +* A certificate signed by the site's CA +* A private key to match its certificate + +These can come from anywhere, but the CA has to match the one used by MCollective. + +The easiest approach is to re-use your site's Puppet cert infrastructure, since it's already everywhere and has tools for issuing and signing arbitrary certificates. + +As ever, remember to **protect the private key.** + +### Option A: Re-Use the Node's Puppet Agent Certificate + +On your ActiveMQ server: + +* Locate the ssldir by running `sudo puppet agent --configprint ssldir`. +* Copy the following files to your working directory, making sure to give unique names to the cert and private key: + * `/certs/ca.pem` + * `/certs/.pem` + * `/private_keys/.pem` + +### Option B: Get a New Certificate from the Puppet CA + +On your CA puppet master: + +* Run `sudo puppet cert generate activemq.example.com`, substituting some name for your ActiveMQ server. Unlike with a puppet master, the cert's common name can be anything; it doesn't have to be the node's hostname or FQDN. +* Locate the ssldir by running `sudo puppet master --configprint ssldir`. +* Retrieve the following files and copy them to a working directory on your ActiveMQ server, making sure to give unique names to the cert and private key: + * `/certs/ca.pem` + * `/certs/activemq.example.com.pem` + * `/private_keys/activemq.example.com.pem` + +### Option C: Do Whatever You Want + +If you have some other CA infrastructure, you can use that instead. + +You can now: + +* [Manually create the keystores](#manually-creating-keystores) +* [Use Puppet to create the keystores](#creating-keystores-with-puppet) + +## Manually Creating Keystores + +We need a **"truststore"** and a **"keystore."** We also need a **password** for each. (You can use the same password for both stores.) + +Remember the password(s) for later, because it needs to [go in the activemq.xml file][tls]. + +### Step 1: Truststore + +> **Note:** The truststore is only required for CA-verified TLS. If you are using anonymous TLS, you may skip it. + +The truststore determines which certificates are allowed to connect to ActiveMQ. If you import a CA cert into it, ActiveMQ will trust any certificate signed by that CA. + +> You could also _not_ import a CA, and instead import every individual certificate you want to allow. If you do that, you're on your own, but the commands should be similar. + +In the working directory with your PEM-format credentials, run the following command. Replace `ca.pem` with whatever you named your copy of the CA cert, and use the password when requested. + +{% highlight console %} +$ sudo keytool -import -alias "My CA" -file ca.pem -keystore truststore.jks +Enter keystore password: +Re-enter new password: +. +. +. +Trust this certificate? [no]: y +Certificate was added to keystore +{% endhighlight %} + +The truststore is now done. + +If you want, you can compare fingerprints: + +{% highlight console %} +$ sudo keytool -list -keystore truststore.jks +Enter keystore password: + +Keystore type: JKS +Keystore provider: SUN + +Your keystore contains 1 entry + +my ca, Mar 30, 2012, trustedCertEntry, +Certificate fingerprint (MD5): 99:D3:28:6B:37:13:7A:A2:B8:73:75:4A:31:78:0B:68 + +$ sudo openssl x509 -in ca.pem -fingerprint -md5 +MD5 Fingerprint=99:D3:28:6B:37:13:7A:A2:B8:73:75:4A:31:78:0B:68 +{% endhighlight %} + + +### Step 2: Keystore + +The keystore contains the ActiveMQ broker's certificate and private key, which it uses to identify itself to the applications that connect to it. + +In the working directory with your PEM-format credentials, run the following commands. Substitute the names of your key and certificate files where necessary, and the common name of your ActiveMQ server's certificate for `activemq.example.com`. + +These commands use both an "export/source" password and a "destination" password. The export/source password is never used again after this series of commands. + +{% highlight console %} +$ sudo cat activemq_private.pem activemq_cert.pem > temp.pem +$ sudo openssl pkcs12 -export -in temp.pem -out activemq.p12 -name activemq.example.com +Enter Export Password: +Verifying - Enter Export Password: +$sudo keytool -importkeystore -destkeystore keystore.jks -srckeystore activemq.p12 -srcstoretype PKCS12 -alias activemq.example.com +Enter destination keystore password: +Re-enter new password: +Enter source keystore password: +{% endhighlight %} + +The keystore is now done. + +If you want, you can compare fingerprints: + +{% highlight console %} +$ sudo keytool -list -keystore keystore.jks +Enter keystore password: + +Keystore type: JKS +Keystore provider: SUN + +Your keystore contains 1 entry + +activemq.example.com, Mar 30, 2012, PrivateKeyEntry, +Certificate fingerprint (MD5): 7E:2A:B4:4D:1E:6D:D1:70:A9:E7:20:0D:9D:41:F3:B9 + +$ sudo openssl x509 -in activemq_cert.pem -fingerprint -md5 +MD5 Fingerprint=7E:2A:B4:4D:1E:6D:D1:70:A9:E7:20:0D:9D:41:F3:B9 +{% endhighlight %} + +### Step 3: Finish + +Move the keystore and truststore to ActiveMQ's config directory. Make sure they are owned by the ActiveMQ user and unreadable to any other users. [Configure ActiveMQ to use them in its `sslContext`.][tls] **Double-check** that you've made activemq.xml world-unreadable, since it now contains sensitive credentials. + +## Creating Keystores with Puppet + +If you're managing your ActiveMQ server with Puppet anyway, you can use the [puppetlabs/java_ks module](http://forge.puppetlabs.com/puppetlabs/java_ks) to handle the format conversion. + +This approach is more work for a single permanent ActiveMQ server, but less work if you intend to deploy multiple ActiveMQ servers or eventually change the credentials. + +### Step 1: Install the `java_ks` Module + +On your puppet master, run `sudo puppet module install puppetlabs/java_ks`. + +### Step 2: Create a Puppet Class + +The class to manage the keystores should do the following: + +* Make sure the PEM cert and key files are present and protected. +* Declare a pair of `java_ks` resources. +* Manage the mode and ownership of the keystore files. + +The code below is an example, but it will work fine if you put it in a module (example file location in the first comment) and set its parameters when you declare it. The name of the class (and its home module) can be changed as needed. + + +{% highlight ruby %} + # /etc/puppet/modules/activemq/manifests/keystores.pp + class activemq::keystores ( + $keystore_password, # required + + # User must put these files in the module, or provide other URLs + $ca = 'puppet:///modules/activemq/ca.pem', + $cert = 'puppet:///modules/activemq/cert.pem', + $private_key = 'puppet:///modules/activemq/private_key.pem', + + $activemq_confdir = '/etc/activemq', + $activemq_user = 'activemq', + ) { + + # ----- Restart ActiveMQ if the SSL credentials ever change ----- + # ----- Uncomment if you are fully managing ActiveMQ with Puppet. ----- + + # Package['activemq'] -> Class[$title] + # Java_ks['activemq_cert:keystore'] ~> Service['activemq'] + # Java_ks['activemq_ca:truststore'] ~> Service['activemq'] + + + # ----- Manage PEM files ----- + + File { + owner => root, + group => root, + mode => 0600, + } + file {"${activemq_confdir}/ssl_credentials": + ensure => directory, + mode => 0700, + } + file {"${activemq_confdir}/ssl_credentials/activemq_certificate.pem": + ensure => file, + source => $cert, + } + file {"${activemq_confdir}/ssl_credentials/activemq_private.pem": + ensure => file, + source => $private_key, + } + file {"${activemq_confdir}/ssl_credentials/ca.pem": + ensure => file, + source => $ca, + } + + + # ----- Manage Keystore Contents ----- + + # Each keystore should have a dependency on the PEM files it relies on. + + # Truststore with copy of CA cert + java_ks { 'activemq_ca:truststore': + ensure => latest, + certificate => "${activemq_confdir}/ssl_credentials/ca.pem", + target => "${activemq_confdir}/truststore.jks", + password => $keystore_password, + trustcacerts => true, + require => File["${activemq_confdir}/ssl_credentials/ca.pem"], + } + + # Keystore with ActiveMQ cert and private key + java_ks { 'activemq_cert:keystore': + ensure => latest, + certificate => "${activemq_confdir}/ssl_credentials/activemq_certificate.pem", + private_key => "${activemq_confdir}/ssl_credentials/activemq_private.pem", + target => "${activemq_confdir}/keystore.jks", + password => $keystore_password, + require => [ + File["${activemq_confdir}/ssl_credentials/activemq_private.pem"], + File["${activemq_confdir}/ssl_credentials/activemq_certificate.pem"] + ], + } + + + # ----- Manage Keystore Files ----- + + # Permissions only. + # No ensure, source, or content. + + file {"${activemq_confdir}/keystore.jks": + owner => $activemq_user, + group => $activemq_user, + mode => 0600, + require => Java_ks['activemq_cert:keystore'], + } + file {"${activemq_confdir}/truststore.jks": + owner => $activemq_user, + group => $activemq_user, + mode => 0600, + require => Java_ks['activemq_ca:truststore'], + } + + } +{% endhighlight %} + + +### Step 3: Assign the Class to the ActiveMQ Server + +...using your standard Puppet site tools. + +### Step 4: Finish + +[Configure ActiveMQ to use the keystores in its `sslContext`][tls], probably with the Puppet template you're using to manage activemq.xml. **Double-check** that you've made activemq.xml world-unreadable, since it now contains sensitive credentials.