6 [Security]: http://activemq.apache.org/security.html
7 [Registration]: /mcollective/reference/plugins/registration.html
8 [Wildcard]: http://activemq.apache.org/wildcards.html
10 In order to achieve end to end encryption we use TLS encryption between
11 ActiveMQ, the nodes and the client.
13 To set this up you need to Java Keystore, the instructions here work for Java
14 1.6 either Sun or OpenJDK based.
16 ## Full CA verified TLS between Stomp >= 1.2.2 and ActiveMQ
17 As of MCollective 2.0.0 and Stomp 1.2.2 it's possible to setup a TLS setup
18 that will only accept clients with certificates signed by a CA shared with
19 your clients and your ActiveMQ server like the one provided by Puppet.
21 You can only use this setup using the ActiveMQ specific connector plugin, not using
22 the generic Stomp one.
24 These examples will use the Puppet CA to generate the certificates but you can
25 use any CA as long as you have PEM format keys and certificates.
27 ### Create ActiveMQ certificates and keystores
28 With this setup we need the following:
30 * A certificate and keys for the ActiveMQ - we will call the ActiveMQ instance stomp.my.net
31 * A Certificate Authority certificate
32 * A key store for the ActiveMQ certificates
33 * A trust store instructing ActiveMQ what connections to trust
35 First we create the trust store, we load in our CA file which will instruct ActiveMQ
36 to trust any certificate signed by the Puppet CA. You could also load in each individual
37 certificate for every client if you wanted to be really strict about it.
40 # keytool -import -alias "My CA" -file /var/lib/puppet/ssl/ca/ca_crt.pem -keystore truststore.jks
41 Enter keystore password:
42 Re-enter new password:
46 Trust this certificate? [no]: y
47 Certificate was added to keystore
50 You can view your certificate:
53 # keytool -list -keystore truststore.jks
54 Enter keystore password:
57 Keystore provider: SUN
59 Your keystore contains 1 entry
61 my ca, Mar 30, 2012, trustedCertEntry,
62 Certificate fingerprint (MD5): 99:D3:28:6B:37:13:7A:A2:B8:73:75:4A:31:78:0B:68
65 Note the MD5 fingerprint, you can verify this is the one from your CA:
68 # openssl x509 -in /var/lib/puppet/ssl/ca/ca_crt.pem -fingerprint -md5
69 MD5 Fingerprint=99:D3:28:6B:37:13:7A:A2:B8:73:75:4A:31:78:0B:68
72 Now we create the certificate for our ActiveMQ machine and store that in the key store
75 # puppet cert generate stomp.my.net
76 notice: stomp.my.net has a waiting certificate request
77 notice: Signed certificate request for stomp.my.net
78 notice: Removing file Puppet::SSL::CertificateRequest stomp.my.net at '/var/lib/puppet/ssl/ca/requests/stomp.my.net.pem'
79 notice: Removing file Puppet::SSL::CertificateRequest stomp.my.net at '/var/lib/puppet/ssl/certificate_requests/stomp.my.net.pem'
82 And then we convert it into a format keytool can understand and import it:
85 # cat /var/lib/puppet/ssl/private_keys/stomp.my.net.pem /var/lib/puppet/ssl/certs/stomp.my.net.pem > temp.pem
86 # openssl pkcs12 -export -in temp.pem -out activemq.p12 -name stomp.my.net
87 Enter Export Password:
88 Verifying - Enter Export Password:
89 # keytool -importkeystore -destkeystore keystore.jks -srckeystore activemq.p12 -srcstoretype PKCS12 -alias stomp.my.net
90 Enter destination keystore password:
91 Re-enter new password:
92 Enter source keystore password:
95 You can validate this was correct:
98 # keytool -list -keystore keystore.jks
99 Enter keystore password:
102 Keystore provider: SUN
104 Your keystore contains 1 entry
106 stomp.my.net, Mar 30, 2012, PrivateKeyEntry,
107 Certificate fingerprint (MD5): 7E:2A:B4:4D:1E:6D:D1:70:A9:E7:20:0D:9D:41:F3:B9
109 # puppet cert fingerprint stomp.my.net --digest=md5
110 MD5 Fingerprint=7E:2A:B4:4D:1E:6D:D1:70:A9:E7:20:0D:9D:41:F3:B9
113 ### Configure ActiveMQ
114 We need to tell ActiveMQ to read the stores we made:
119 keyStore="keystore.jks" keyStorePassword="secret"
120 trustStore="truststore.jks" trustStorePassword="secret"
125 And we need to tell ActiveMQ to only accept fully verified connections:
128 <transportConnectors>
129 <transportConnector name="openwire" uri="tcp://0.0.0.0:6166"/>
130 <transportConnector name="stompssl" uri="stomp+ssl://0.0.0.0:6164?needClientAuth=true"/>
131 </transportConnectors>
134 If you were to attempt to connect a mcollectived or client using the anonymous setup
135 detailed above that should fail as we have not yet setup credentials for the mcollectived
136 or mcollective client to use.
138 ### Setting up mcollectived
140 For the MCollective daemon you can use your existing Puppet certificates by editing the _server.cfg_
144 plugin.activemq.base64 = yes
145 plugin.activemq.pool.size = 2
146 plugin.activemq.pool.1.host = stomp.my.net
147 plugin.activemq.pool.1.port = 6164
148 plugin.activemq.pool.1.user = mcollective
149 plugin.activemq.pool.1.password = secret
150 plugin.activemq.pool.1.ssl = 1
151 plugin.activemq.pool.1.ssl.ca = /var/lib/puppet/ssl/ca/ca_crt.pem
152 plugin.activemq.pool.1.ssl.key = /var/lib/puppet/ssl/private_keys/fqdn.pem
153 plugin.activemq.pool.1.ssl.cert = /var/lib/puppet/ssl/certs/fqdn.pem
156 Fix the paths to the private key and certificate, they will be named after your machines FQDN.
158 ### Setting up mcollective clients
160 Each client will now need a TLS certificate issued by the Puppet CA in order to be able to
161 connect to the ActiveMQ:
164 # puppet cert generate ripienaar
165 notice: ripienaar has a waiting certificate request
166 notice: Signed certificate request for ripienaar
167 notice: Removing file Puppet::SSL::CertificateRequest ripienaar at '/var/lib/puppet/ssl/ca/requests/ripienaar.pem'
168 notice: Removing file Puppet::SSL::CertificateRequest ripienaar at '/var/lib/puppet/ssl/certificate_requests/ripienaar.pem'
171 Copy the certificates to your user:
174 # mkdir /home/rip/.mcollective.d
175 # cp /var/lib/puppet/ssl/ca/ca_crt.pem /home/rip/.mcollective.d/
176 # cp /var/lib/puppet/ssl/private_keys/ripienaar.pem /home/rip/.mcollective.d/ripienaar-private.pem
177 # cp /var/lib/puppet/ssl/public_keys/ripienaar.pem /home/rip/.mcollective.d/ripienaar.pem
178 # cp /var/lib/puppet/ssl/certs/ripienaar.pem /home/rip/.mcollective.d/ripienaar-cert.pem
179 # chown -R rip:rip /home/rip/.mcollective.d
182 You can now configure the mcollective client config in _/home/rip/.mcollective_ to use these:
186 plugin.activemq.base64 = yes
187 plugin.activemq.pool.size = 2
188 plugin.activemq.pool.1.host = stomp.my.net
189 plugin.activemq.pool.1.port = 6164
190 plugin.activemq.pool.1.user = ripienaar
191 plugin.activemq.pool.1.password = secret
192 plugin.activemq.pool.1.ssl = 1
193 plugin.activemq.pool.1.ssl.ca = /home/rip/.mcollective.d/ca_crt.pem
194 plugin.activemq.pool.1.ssl.key = /home/rip/.mcollective.d/ripienaar-private.pem
195 plugin.activemq.pool.1.ssl.cert = /home/rip/.mcollective.d/ripienaar-cert.pem
198 If you are using the SSL or AES security plugins you can use these same files using the _/home/rip/.mcollective.d/ripienaar.pem_
199 as the public key for those plugins.
203 You will get some obvious errors from this code if any files are missing, but the errors fro SSL validation will be pretty
206 There are only 2 scenarios here:
208 #### ActiveMQ rejects the client
209 When the client connects using a CA set in _plugin.activemq.pool.1.ssl.ca_ that does not match the one
210 in the ActiveMQ _truststore.jks_:
212 {% highlight console %}
213 failed: SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed
216 And in the ActiveMQ log:
218 {% highlight console %}
219 Transport failed: javax.net.ssl.SSLHandshakeException: Received fatal alert: unknown_ca
222 When your client has the correct CA but his certificates are not signed by that CA:
224 {% highlight console %}
225 failed: SSL_connect returned=1 errno=0 state=SSLv3 read finished A: sslv3 alert certificate unknown
228 And in the ActiveMQ log:
230 {% highlight console %}
231 sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
234 ## Basic anonymous TLS between Stomp and ActiveMQ
235 ### Create a keystore with existing certs
236 If you have an exiting PKI deployment, you can probably reuse Puppet ones too the main
237 point is that you already have a key and signed cert signed by some CA and you
238 now want to create a Java Keystore follow these steps:
241 # cat /etc/pki/host.key /etc/pki/ca.pem /etc/pki/host.cert >cert.pem
242 # openssl pkcs12 -export -in cert.pem -out activemq.p12 -name `hostname`
243 # keytool -importkeystore -deststorepass secret -destkeypass secret -destkeystore keystore.jks -srckeystore activemq.p12 -srcstoretype PKCS12 -alias `hostname`
246 The above steps will create a standard Java keystore in _keystore.jks_ which you
247 should store in your ActiveMQ config directory. It will have a password
248 _secret_ you should change this.
250 ### Configure ActiveMQ
252 To let ActiveMQ load your keystore you should add the following to the
257 <sslContext keyStore="keystore.jks" keyStorePassword="secret" />
261 And you should add a SSL stomp listener, you should get port 6164 opened:
264 <transportConnectors>
265 <transportConnector name="openwire" uri="tcp://0.0.0.0:6166"/>
266 <transportConnector name="stomp" uri="stomp://0.0.0.0:6163"/>
267 <transportConnector name="stompssl" uri="stomp+ssl://0.0.0.0:6164"/>
268 </transportConnectors>
271 ### Configure MCollective
273 The last step is to tell MCollective to use the SSL connection, to do this you
274 need to use the new pool based configuration, even if you just have 1 ActiveMQ
278 plugin.stomp.pool.size = 1
279 plugin.stomp.pool.host1 = stomp.your.com
280 plugin.stomp.pool.port1 = 6164
281 plugin.stomp.pool.user1 = mcollective
282 plugin.stomp.pool.password1 = secret
283 plugin.stomp.pool.ssl1 = true
286 You should now verify with tcpdump or wireshark that the connection and traffic
287 really is all encrypted.