Update code from https://github.com/dmi-try/marionette-collective
[packages/precise/mcollective.git] / website / reference / integration / activemq_ssl.md
index 4e21b72fc7e84285f8178a5f751c53035c77c024..ea9a90d00f45f9dbcd3d058b4955ab38a9693899 100644 (file)
@@ -3,159 +3,81 @@ layout: default
 title: ActiveMQ TLS
 toc: false
 ---
-[Security]: http://activemq.apache.org/security.html
-[Registration]: /mcollective/reference/plugins/registration.html
-[Wildcard]: http://activemq.apache.org/wildcards.html
 
-In order to achieve end to end encryption we use TLS encryption between
-ActiveMQ, the nodes and the client.
+[keystores]: /mcollective/deploy/middleware/activemq_keystores.html
+[sslcontext]: /mcollective/deploy/middleware/activemq.html#tls-credentials
+[transport]: /mcollective/deploy/middleware/activemq.html#transport-connectors
 
-To set this up you need to Java Keystore, the instructions here work for Java
-1.6 either Sun or OpenJDK based.
+[activemq_connector]: /mcollective/reference/plugins/connector_activemq.html
+[ssl_security]: /mcollective/reference/plugins/security_ssl.html
+[aes_security]: /mcollective/reference/plugins/security_aes.html
 
-## Full CA verified TLS between Stomp >= 1.2.2 and ActiveMQ
-As of MCollective 2.0.0 and Stomp 1.2.2 it's possible to setup a TLS setup
-that will only accept clients with certificates signed by a CA shared with
-your clients and your ActiveMQ server like the one provided by Puppet.
+You can configure MCollective and ActiveMQ to do end-to-end encryption over TLS. This allows you to use MCollective's fast and efficient [SSL security plugin][ssl_security] instead of the slow and hard to configure [AES security plugin][aes_security]. 
 
-You can only use this setup using the ActiveMQ specific connector plugin, not using
-the generic Stomp one.
+There are two main approaches:
 
-These examples will use the Puppet CA to generate the certificates but you can
-use any CA as long as you have PEM format keys and certificates.
+* [CA-verified TLS](#ca-verified-tls) encrypts traffic, and also lets you restrict middleware connections --- only nodes with valid certificates from the site's CA can connect.
+* [Anonymous TLS](#anonymous-tls) encrypts messages to prevent casual traffic sniffing, and will prevent the passwords MCollective uses to connect to ActiveMQ from being stolen. However, it doesn't check whether nodes are allowed to connect, so you have to trust your username and password security.
 
-### Create ActiveMQ certificates and keystores
-With this setup we need the following:
+This feature requires:
 
- * A certificate and keys for the ActiveMQ - we will call the ActiveMQ instance stomp.my.net
- * A Certificate Authority certificate
- * A key store for the ActiveMQ certificates
- * A trust store instructing ActiveMQ what connections to trust
+* MCollective 2.0.0 or newer
+* ActiveMQ 5.5.0 or newer
+* Stomp gem 1.2.2 or newer
+* The [activemq connector][activemq_connector] plugin (included with MCollective 2.0.0 and newer)
 
-First we create the trust store, we load in our CA file which will instruct ActiveMQ
-to trust any certificate signed by the Puppet CA. You could also load in each individual
-certificate for every client if you wanted to be really strict about it.
+## CA-Verified TLS
 
-{% highlight bash %}
-# keytool -import -alias "My CA" -file /var/lib/puppet/ssl/ca/ca_crt.pem -keystore truststore.jks
-Enter keystore password:
-Re-enter new password:
-.
-.
-.
-Trust this certificate? [no]:  y
-Certificate was added to keystore
-{% endhighlight %}
-
-You can view your certificate:
-
-{% highlight bash %}
-# 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
-{% endhighlight %}
-
-Note the MD5 fingerprint, you can verify this is the one from your CA:
-
-{% highlight bash %}
-# openssl x509 -in /var/lib/puppet/ssl/ca/ca_crt.pem -fingerprint -md5
-MD5 Fingerprint=99:D3:28:6B:37:13:7A:A2:B8:73:75:4A:31:78:0B:68
-{% endhighlight %}
+**(Recommended For Most Users)**
 
-Now we create the certificate for our ActiveMQ machine and store that in the key store
+### Summary
 
-{% highlight bash %}
-# puppet cert generate stomp.my.net
-notice: stomp.my.net has a waiting certificate request
-notice: Signed certificate request for stomp.my.net
-notice: Removing file Puppet::SSL::CertificateRequest stomp.my.net at '/var/lib/puppet/ssl/ca/requests/stomp.my.net.pem'
-notice: Removing file Puppet::SSL::CertificateRequest stomp.my.net at '/var/lib/puppet/ssl/certificate_requests/stomp.my.net.pem'
-{% endhighlight %}
+This approach configures MCollective and ActiveMQ to only accept connections when the peer has a certificate signed by the site's CA. 
 
-And then we convert it into a format keytool can understand and import it:
+**Benefits:**
 
-{% highlight bash %}
-# cat /var/lib/puppet/ssl/private_keys/stomp.my.net.pem /var/lib/puppet/ssl/certs/stomp.my.net.pem > temp.pem
-# openssl pkcs12 -export -in temp.pem -out activemq.p12 -name stomp.my.net
-Enter Export Password:
-Verifying - Enter Export Password:
-# keytool -importkeystore  -destkeystore keystore.jks -srckeystore activemq.p12 -srcstoretype PKCS12 -alias stomp.my.net
-Enter destination keystore password:
-Re-enter new password:
-Enter source keystore password:
-{% endhighlight %}
+This approach gives extra security, and your MCollective servers will generally already have the credentials they need since you can re-use Puppet certificates.
 
-You can validate this was correct:
+**Drawbacks:**
 
-{% highlight bash %}
-# keytool -list -keystore keystore.jks
-Enter keystore password:
+You will need to go out of your way to issue keys and certificates to your admin users, which is an extra step when onboarding a new admin.
 
-Keystore type: JKS
-Keystore provider: SUN
 
-Your keystore contains 1 entry
+### Step 1: Configure ActiveMQ to Use TLS
 
-stomp.my.net, Mar 30, 2012, PrivateKeyEntry,
-Certificate fingerprint (MD5): 7E:2A:B4:4D:1E:6D:D1:70:A9:E7:20:0D:9D:41:F3:B9
+Do the following steps to get ActiveMQ configured:
 
-# puppet cert fingerprint stomp.my.net --digest=md5
-MD5 Fingerprint=7E:2A:B4:4D:1E:6D:D1:70:A9:E7:20:0D:9D:41:F3:B9
-{% endhighlight %}
+* Follow [the ActiveMQ keystores guide][keystores] to create Java keystores for ActiveMQ.
+* [Configure activemq.xml's `<sslContext>` element to point at the keystores.][sslcontext]
+* [Configure the proper URIs in the broker's transport connectors.][transport]
+* Restart ActiveMQ.
 
-### Configure ActiveMQ
-We need to tell ActiveMQ to read the stores we made:
+At this point, MCollective servers and clients should be unable to connect to ActiveMQ, since they do not yet have credentials configured.
 
-{% highlight xml %}
-<sslContext>
-   <sslContext
-       keyStore="keystore.jks" keyStorePassword="secret"
-       trustStore="truststore.jks" trustStorePassword="secret"
-   />
-</sslContext>
-{% endhighlight %}
+### Step 2: Configure MCollective Servers
 
-And we need to tell ActiveMQ to only accept fully verified connections:
-
-{% highlight xml %}
-<transportConnectors>
-    <transportConnector name="openwire" uri="tcp://0.0.0.0:6166"/>
-    <transportConnector name="stompssl" uri="stomp+ssl://0.0.0.0:6164?needClientAuth=true"/>
-</transportConnectors>
-{% endhighlight %}
-
-If you were to attempt to connect a mcollectived or client using the anonymous setup
-detailed above that should fail as we have not yet setup credentials for the mcollectived
-or mcollective client to use.
-
-### Setting up mcollectived
-
-For the MCollective daemon you can use your existing Puppet certificates by editing the _server.cfg_
+For the MCollective daemon you can use your existing Puppet certificates by editing the _server.cfg_ file:
 
 {% highlight ini %}
 connector = activemq
-plugin.activemq.base64 = yes
-plugin.activemq.pool.size = 2
-plugin.activemq.pool.1.host = stomp.my.net
-plugin.activemq.pool.1.port = 6164
+# Optional:
+# plugin.activemq.base64 = yes
+plugin.activemq.pool.size = 1
+plugin.activemq.pool.1.host = stomp.example.com
+plugin.activemq.pool.1.port = 61614
 plugin.activemq.pool.1.user = mcollective
 plugin.activemq.pool.1.password = secret
-plugin.activemq.pool.1.ssl = 1
+plugin.activemq.pool.1.ssl = true
 plugin.activemq.pool.1.ssl.ca = /var/lib/puppet/ssl/ca/ca_crt.pem
-plugin.activemq.pool.1.ssl.key = /var/lib/puppet/ssl/private_keys/fqdn.pem
-plugin.activemq.pool.1.ssl.cert = /var/lib/puppet/ssl/certs/fqdn.pem
+plugin.activemq.pool.1.ssl.key = /var/lib/puppet/ssl/private_keys/<NAME>.pem
+plugin.activemq.pool.1.ssl.cert = /var/lib/puppet/ssl/certs/<NAME>.pem
 {% endhighlight %}
 
-Fix the paths to the private key and certificate, they will be named after your machines FQDN.
+* Set the correct paths to each node's private key and certificate; they will be named after the node's Puppet certname and located in the ssldir.
+    * You can locate a node's private key by running `sudo puppet agent --configprint hostprivkey`, the certificate with `sudo puppet agent --configprint hostcert`, and the CA certificate with `sudo puppet agent --configprint localcacert`.
+* Set the correct username and password.
 
-### Setting up mcollective clients
+### Step 3: Configure MCollective Clients
 
 Each client will now need a TLS certificate issued by the Puppet CA in order to be able to
 connect to the ActiveMQ:
@@ -183,29 +105,35 @@ You can now configure the mcollective client config in _/home/rip/.mcollective_
 
 {% highlight ini %}
 connector = activemq
-plugin.activemq.base64 = yes
-plugin.activemq.pool.size = 2
-plugin.activemq.pool.1.host = stomp.my.net
-plugin.activemq.pool.1.port = 6164
+# Optional:
+# plugin.activemq.base64 = yes
+plugin.activemq.pool.size = 1
+plugin.activemq.pool.1.host = stomp.example.com
+plugin.activemq.pool.1.port = 61614
 plugin.activemq.pool.1.user = ripienaar
 plugin.activemq.pool.1.password = secret
-plugin.activemq.pool.1.ssl = 1
+plugin.activemq.pool.1.ssl = true
 plugin.activemq.pool.1.ssl.ca = /home/rip/.mcollective.d/ca_crt.pem
 plugin.activemq.pool.1.ssl.key = /home/rip/.mcollective.d/ripienaar-private.pem
 plugin.activemq.pool.1.ssl.cert = /home/rip/.mcollective.d/ripienaar-cert.pem
 {% endhighlight %}
 
-If you are using the SSL or AES security plugins you can use these same files using the _/home/rip/.mcollective.d/ripienaar.pem_
-as the public key for those plugins.
+If you are using the SSL security plugin, you can use these same files by setting `/home/rip/.mcollective.d/ripienaar.pem` as the public key.
 
-### Common Errors
+### Finish: Verify Encryption
 
-You will get some obvious errors from this code if any files are missing, but the errors fro SSL validation will be pretty
+If you want to be sure of this, you should now verify with tcpdump or wireshark that the connection and traffic
+really is all encrypted.
+
+### Troubleshooting Common Errors
+
+You will get some obvious errors from this code if any files are missing, but the errors from SSL validation will be pretty
 hard to understand.
 
-There are only 2 scenarios here:
+There are two main scenarios where ActiveMQ will reject an MCollective conneciton:
+
+#### MCollective Uses Wrong CA to Verify ActiveMQ Cert
 
-#### ActiveMQ rejects the client
 When the client connects using a CA set in _plugin.activemq.pool.1.ssl.ca_ that does not match the one
 in the ActiveMQ _truststore.jks_:
 
@@ -219,6 +147,8 @@ And in the ActiveMQ log:
 Transport failed: javax.net.ssl.SSLHandshakeException: Received fatal alert: unknown_ca
 {% endhighlight %}
 
+#### MCollective Certs Aren't Signed by the Right CA
+
 When your client has the correct CA but his certificates are not signed by that CA:
 
 {% highlight console %}
@@ -231,57 +161,64 @@ And in the ActiveMQ log:
 sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
 {% endhighlight %}
 
-## Basic anonymous TLS between Stomp and ActiveMQ
-### Create a keystore with existing certs
-If you have an exiting PKI deployment, you can probably reuse Puppet ones too the main
-point is that you already have a key and signed cert signed by some CA and you
-now want to create a Java Keystore follow these steps:
 
-{% highlight bash %}
-# cat /etc/pki/host.key /etc/pki/ca.pem /etc/pki/host.cert >cert.pem
-# openssl pkcs12 -export -in cert.pem -out activemq.p12 -name `hostname`
-# keytool -importkeystore -deststorepass secret -destkeypass secret -destkeystore keystore.jks -srckeystore activemq.p12 -srcstoretype PKCS12 -alias `hostname`
-{% endhighlight %}
 
-The above steps will create a standard Java keystore in _keystore.jks_ which you
-should store in your ActiveMQ config directory.  It will have a password
-_secret_ you should change this.
 
-### Configure ActiveMQ
 
-To let ActiveMQ load your keystore you should add the following to the
-_activemq.xml_ file:
+## Anonymous TLS
 
-{% highlight xml %}
-<sslContext>
-   <sslContext keyStore="keystore.jks" keyStorePassword="secret" />
-</sslContext>
-{% endhighlight %}
+**(Less Recommended)**
 
-And you should add a SSL stomp listener, you should get port 6164 opened:
+### Summary
 
-{% highlight xml %}
-<transportConnectors>
-    <transportConnector name="openwire" uri="tcp://0.0.0.0:6166"/>
-    <transportConnector name="stomp" uri="stomp://0.0.0.0:6163"/>
-    <transportConnector name="stompssl" uri="stomp+ssl://0.0.0.0:6164"/>
-</transportConnectors>
-{% endhighlight %}
+This approach configures MCollective and ActiveMQ to encrypt traffic via TLS, but accept connections from anyone.
+
+**Benefits:**
+
+This approach requires less configuration, especially when adding new admin users.
+
+**Drawbacks:**
+
+This approach has some relative security drawbacks. Depending on your site's security needs, these may not concern you --- since MCollective's application-level security plugins will prevent an attacker from issuing agent commands and owning your servers, attacks like those below would only result in denial of service plus some leakage of inventory data via lower-level discovery protocols.
+
+* Although attackers can't sniff MCollective's ActiveMQ passwords, there's nothing to prevent them from logging in if they steal a password through some other means. (With CA-verified TLS, on the other hand, they would also require a private key and certificate, which provides some additional security depth.)
+* An attacker able to run a man-in-the-middle attack at your site could fool your MCollective servers into trusting a malicious ActiveMQ server. 
 
-### Configure MCollective
 
-The last step is to tell MCollective to use the SSL connection, to do this you
-need to use the new pool based configuration, even if you just have 1 ActiveMQ
-in your pool:
+### Step 1: Configure ActiveMQ to Use Anonymous TLS
+
+* Follow [the ActiveMQ keystores guide][keystores] to create a Java keystore for ActiveMQ. _You can skip the truststore._ 
+* [Configure activemq.xml's `<sslContext>` element to point at the keystore.][sslcontext] _You can skip the `trustStore` and `trustStorePassword` attributes._
+* [Configure the proper URIs in the broker's transport connectors][transport], but _leave off the `?needClientAuth=true` portion._
+* Restart ActiveMQ.
+
+
+### Step 2: Configure MCollective Servers and Clients
+
+Set the following settings in the `server.cfg` and `client.cfg` (or `~/.mcollective`) files:
 
 {% highlight ini %}
-plugin.stomp.pool.size = 1
-plugin.stomp.pool.host1 = stomp.your.com
-plugin.stomp.pool.port1 = 6164
-plugin.stomp.pool.user1 = mcollective
-plugin.stomp.pool.password1 = secret
-plugin.stomp.pool.ssl1 = true
+connector = activemq
+# Optional:
+# plugin.activemq.base64 = yes
+plugin.activemq.pool.size = 1
+plugin.activemq.pool.1.host = stomp.example.com
+plugin.activemq.pool.1.port = 61614
+plugin.activemq.pool.1.user = mcollective
+plugin.activemq.pool.1.password = secret
+plugin.activemq.pool.1.ssl = true
+plugin.activemq.pool.1.ssl.fallback = true
 {% endhighlight %}
 
-You should now verify with tcpdump or wireshark that the connection and traffic
+The `plugin.activemq.pool.1.ssl.fallback` setting tells the plugin that it is allowed to:
+
+* Connect to an unverified server
+* Connect without presenting its own SSL credentials
+
+...if it is missing any of the `.ca` `.cert` or `.key` settings or cannot find the files they reference. If the settings _are_ present (and point to correct files), MCollective will try to do a verified connection.
+
+
+### Finish: Verify Encryption
+
+If you want to be sure of this, you should now verify with tcpdump or wireshark that the connection and traffic
 really is all encrypted.