Update mcollective.init according to OSCI-855
[packages/precise/mcollective.git] / website / deploy / middleware / activemq_keystores.md
1 ---
2 title: "MCollective » Deploy » Middleware » ActiveMQ Keystores"
3 subtitle: "Setting Up Keystores For ActiveMQ"
4 layout: default
5 ---
6
7 [tls]: ./activemq.html#tls-credentials
8
9 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. 
10
11 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).
12
13
14 ## Step 0: Obtain Certificates and Keys
15
16 ActiveMQ needs the following credentials:
17
18 * A copy of the site's CA certificate
19 * A certificate signed by the site's CA
20 * A private key to match its certificate
21
22 These can come from anywhere, but the CA has to match the one used by MCollective. 
23
24 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.
25
26 As ever, remember to **protect the private key.**
27
28 ### Option A: Re-Use the Node's Puppet Agent Certificate
29
30 On your ActiveMQ server:
31
32 * Locate the ssldir by running `sudo puppet agent --configprint ssldir`.
33 * Copy the following files to your working directory, making sure to give unique names to the cert and private key:
34     * `<ssldir>/certs/ca.pem`
35     * `<ssldir>/certs/<node name>.pem`
36     * `<ssldir>/private_keys/<node name>.pem`
37
38 ### Option B: Get a New Certificate from the Puppet CA
39
40 On your CA puppet master:
41
42 * 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.
43 * Locate the ssldir by running `sudo puppet master --configprint ssldir`.
44 * 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:
45     * `<ssldir>/certs/ca.pem`
46     * `<ssldir>/certs/activemq.example.com.pem`
47     * `<ssldir>/private_keys/activemq.example.com.pem`
48
49 ### Option C: Do Whatever You Want
50
51 If you have some other CA infrastructure, you can use that instead.
52
53 You can now:
54
55 * [Manually create the keystores](#manually-creating-keystores)
56 * [Use Puppet to create the keystores](#creating-keystores-with-puppet)
57
58 ## Manually Creating Keystores
59
60 We need a **"truststore"** and a **"keystore."** We also need a **password** for each. (You can use the same password for both stores.)
61
62 Remember the password(s) for later, because it needs to [go in the activemq.xml file][tls]. 
63
64 ### Step 1: Truststore
65
66 > **Note:** The truststore is only required for CA-verified TLS. If you are using anonymous TLS, you may skip it.
67
68 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.
69
70 > 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.
71
72 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.
73
74 {% highlight console %}
75 $ sudo keytool -import -alias "My CA" -file ca.pem -keystore truststore.jks
76 Enter keystore password:
77 Re-enter new password:
78 .
79 .
80 .
81 Trust this certificate? [no]:  y
82 Certificate was added to keystore
83 {% endhighlight %}
84
85 The truststore is now done.
86
87 If you want, you can compare fingerprints:
88
89 {% highlight console %}
90 $ sudo keytool -list -keystore truststore.jks
91 Enter keystore password:
92
93 Keystore type: JKS
94 Keystore provider: SUN
95
96 Your keystore contains 1 entry
97
98 my ca, Mar 30, 2012, trustedCertEntry,
99 Certificate fingerprint (MD5): 99:D3:28:6B:37:13:7A:A2:B8:73:75:4A:31:78:0B:68
100
101 $ sudo openssl x509 -in ca.pem -fingerprint -md5
102 MD5 Fingerprint=99:D3:28:6B:37:13:7A:A2:B8:73:75:4A:31:78:0B:68
103 {% endhighlight %}
104
105
106 ### Step 2: Keystore
107
108 The keystore contains the ActiveMQ broker's certificate and private key, which it uses to identify itself to the applications that connect to it.
109
110 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`.
111
112 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.
113
114 {% highlight console %}
115 $ sudo cat activemq_private.pem activemq_cert.pem > temp.pem
116 $ sudo openssl pkcs12 -export -in temp.pem -out activemq.p12 -name activemq.example.com
117 Enter Export Password:
118 Verifying - Enter Export Password:
119 $sudo keytool -importkeystore  -destkeystore keystore.jks -srckeystore activemq.p12 -srcstoretype PKCS12 -alias activemq.example.com
120 Enter destination keystore password:
121 Re-enter new password:
122 Enter source keystore password:
123 {% endhighlight %}
124
125 The keystore is now done.
126
127 If you want, you can compare fingerprints:
128
129 {% highlight console %}
130 $ sudo keytool -list -keystore keystore.jks
131 Enter keystore password:
132
133 Keystore type: JKS
134 Keystore provider: SUN
135
136 Your keystore contains 1 entry
137
138 activemq.example.com, Mar 30, 2012, PrivateKeyEntry,
139 Certificate fingerprint (MD5): 7E:2A:B4:4D:1E:6D:D1:70:A9:E7:20:0D:9D:41:F3:B9
140
141 $ sudo openssl x509 -in activemq_cert.pem -fingerprint -md5
142 MD5 Fingerprint=7E:2A:B4:4D:1E:6D:D1:70:A9:E7:20:0D:9D:41:F3:B9
143 {% endhighlight %}
144
145 ### Step 3: Finish
146
147 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.
148
149 ## Creating Keystores with Puppet
150
151 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.
152
153 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.
154
155 ### Step 1: Install the `java_ks` Module
156
157 On your puppet master, run `sudo puppet module install puppetlabs/java_ks`.
158
159 ### Step 2: Create a Puppet Class
160
161 The class to manage the keystores should do the following:
162
163 * Make sure the PEM cert and key files are present and protected.
164 * Declare a pair of `java_ks` resources.
165 * Manage the mode and ownership of the keystore files.
166
167 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.
168
169
170 {% highlight ruby %}
171     # /etc/puppet/modules/activemq/manifests/keystores.pp
172     class activemq::keystores (
173       $keystore_password, # required
174
175       # User must put these files in the module, or provide other URLs
176       $ca = 'puppet:///modules/activemq/ca.pem',
177       $cert = 'puppet:///modules/activemq/cert.pem',
178       $private_key = 'puppet:///modules/activemq/private_key.pem',
179
180       $activemq_confdir = '/etc/activemq',
181       $activemq_user = 'activemq',
182     ) {
183
184       # ----- Restart ActiveMQ if the SSL credentials ever change       -----
185       # ----- Uncomment if you are fully managing ActiveMQ with Puppet. -----
186
187       # Package['activemq'] -> Class[$title]
188       # Java_ks['activemq_cert:keystore'] ~> Service['activemq']
189       # Java_ks['activemq_ca:truststore'] ~> Service['activemq']
190
191
192       # ----- Manage PEM files -----
193
194       File {
195         owner => root,
196         group => root,
197         mode  => 0600,
198       }
199       file {"${activemq_confdir}/ssl_credentials":
200         ensure => directory,
201         mode   => 0700,
202       }
203       file {"${activemq_confdir}/ssl_credentials/activemq_certificate.pem":
204         ensure => file,
205         source => $cert,
206       }
207       file {"${activemq_confdir}/ssl_credentials/activemq_private.pem":
208         ensure => file,
209         source => $private_key,
210       }
211       file {"${activemq_confdir}/ssl_credentials/ca.pem":
212         ensure => file,
213         source => $ca,
214       }
215
216
217       # ----- Manage Keystore Contents -----
218
219       # Each keystore should have a dependency on the PEM files it relies on.
220
221       # Truststore with copy of CA cert
222       java_ks { 'activemq_ca:truststore':
223         ensure       => latest,
224         certificate  => "${activemq_confdir}/ssl_credentials/ca.pem",
225         target       => "${activemq_confdir}/truststore.jks",
226         password     => $keystore_password,
227         trustcacerts => true,
228         require      => File["${activemq_confdir}/ssl_credentials/ca.pem"],
229       }
230
231       # Keystore with ActiveMQ cert and private key
232       java_ks { 'activemq_cert:keystore':
233         ensure       => latest,
234         certificate  => "${activemq_confdir}/ssl_credentials/activemq_certificate.pem",
235         private_key  => "${activemq_confdir}/ssl_credentials/activemq_private.pem",
236         target       => "${activemq_confdir}/keystore.jks",
237         password     => $keystore_password,
238         require      => [
239           File["${activemq_confdir}/ssl_credentials/activemq_private.pem"],
240           File["${activemq_confdir}/ssl_credentials/activemq_certificate.pem"]
241         ],
242       }
243
244
245       # ----- Manage Keystore Files -----
246
247       # Permissions only.
248       # No ensure, source, or content.
249
250       file {"${activemq_confdir}/keystore.jks":
251         owner   => $activemq_user,
252         group   => $activemq_user,
253         mode    => 0600,
254         require => Java_ks['activemq_cert:keystore'],
255       }
256       file {"${activemq_confdir}/truststore.jks":
257         owner   => $activemq_user,
258         group   => $activemq_user,
259         mode    => 0600,
260         require => Java_ks['activemq_ca:truststore'],
261       }
262     
263     }
264 {% endhighlight %}
265
266
267 ### Step 3: Assign the Class to the ActiveMQ Server
268
269 ...using your standard Puppet site tools.
270
271 ### Step 4: Finish
272
273 [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.