From: Dmitry Burmistrov Date: Tue, 15 Oct 2013 13:55:40 +0000 (+0400) Subject: Update code from https://github.com/dmi-try/marionette-collective X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=8fd0f35facc21b89b378ecfb253e06a66af1e422;p=packages%2Fprecise%2Fmcollective.git Update code from https://github.com/dmi-try/marionette-collective Change-Id: Iaf781af6b59d3932ffca234751ae014da2aea5af --- diff --git a/Rakefile b/Rakefile index c1020d0..4a6f8f9 100644 --- a/Rakefile +++ b/Rakefile @@ -129,21 +129,23 @@ task :rpm => [:clean, :doc, :package] do specsdir = `rpm --eval '%_specdir'`.chomp srpmsdir = `rpm --eval '%_srcrpmdir'`.chomp rpmdir = `rpm --eval '%_rpmdir'`.chomp - lsbdistrel = `lsb_release -r -s | cut -d . -f1`.chomp - lsbdistro = `lsb_release -i -s`.chomp + rpmdist = '' + + `which lsb_release` + if $?.success? + lsbdistrel = `lsb_release -r -s | cut -d . -f1`.chomp + lsbdistro = `lsb_release -i -s`.chomp + case lsbdistro + when 'CentOS' + rpmdist = ".el#{lsbdistrel}" + when 'Fedora' + rpmdist = ".fc#{lsbdistrel}" + end + end `which rpmbuild-md5` rpmcmd = $?.success? ? 'rpmbuild-md5' : 'rpmbuild' - case lsbdistro - when 'CentOS' - rpmdist = ".el#{lsbdistrel}" - when 'Fedora' - rpmdist = ".fc#{lsbdistrel}" - else - rpmdist = "" - end - safe_system %{cp build/#{PROJ_NAME}-#{CURRENT_VERSION}.tgz #{sourcedir}} safe_system %{cat ext/redhat/#{PROJ_NAME}.spec|sed -e s/%{rpm_release}/#{CURRENT_RELEASE}/g | sed -e s/%{version}/#{CURRENT_VERSION}/g > #{specsdir}/#{PROJ_NAME}.spec} @@ -153,9 +155,9 @@ task :rpm => [:clean, :doc, :package] do safe_system %{#{rpmcmd} -D 'version #{CURRENT_VERSION}' -D 'rpm_release #{CURRENT_RELEASE}' -D 'dist #{rpmdist}' -D 'use_lsb 0' -ba #{specsdir}/#{PROJ_NAME}.spec} end - safe_system %{cp #{srpmsdir}/#{PROJ_NAME}-#{CURRENT_VERSION}-#{CURRENT_RELEASE}#{rpmdist}.src.rpm build/} + safe_system %{cp #{srpmsdir}/#{PROJ_NAME}-#{CURRENT_VERSION}-#{CURRENT_RELEASE}*.src.rpm build/} - safe_system %{cp #{rpmdir}/*/#{PROJ_NAME}*-#{CURRENT_VERSION}-#{CURRENT_RELEASE}#{rpmdist}.*.rpm build/} + safe_system %{cp #{rpmdir}/*/#{PROJ_NAME}*-#{CURRENT_VERSION}-#{CURRENT_RELEASE}*.rpm build/} end desc "Create the .debs" @@ -224,9 +226,6 @@ task :update_msgweb do md.puts "toc: false" md.puts "---" md.puts - md.puts "Detail for Marionette Collective message %s" % msg_code - md.puts "===========================================" - md.puts md.puts "Example Message" md.puts "---------------" md.puts diff --git a/debian/control b/debian/control index 7fb71de..7a0ada2 100644 --- a/debian/control +++ b/debian/control @@ -31,12 +31,12 @@ Description: build server orchestration or parallel job execution systems . Common files for mcollective packages. -Package: mcollective-doc -Architecture: all -Section: doc -Description: Documentation for mcollective - The Marionette Collective aka. mcollective is a framework - to build server orchestration or parallel job execution systems. - . - Documentation package. +#Package: mcollective-doc +#Architecture: all +#Section: doc +#Description: Documentation for mcollective +# The Marionette Collective aka. mcollective is a framework +# to build server orchestration or parallel job execution systems. +# . +# Documentation package. diff --git a/debian/mcollective.init b/debian/mcollective.init index f599f4a..6fb229b 100755 --- a/debian/mcollective.init +++ b/debian/mcollective.init @@ -24,11 +24,11 @@ uid=`id -u` # PID directory -pidfile="/var/run/mcollectived.pid" +pidfile="/var/run/mcollective.pid" name="mcollective" mcollectived=/usr/sbin/mcollectived -daemonopts="--pid=${pidfile} --config=/etc/mcollective/server.cfg" +daemonopts="--config=/etc/mcollective/server.cfg" # Source function library. @@ -41,22 +41,30 @@ then exit 5 fi -# create pid file if it does not exist -[ ! -f ${pidfile} ] && { touch ${pidfile} ; } - # See how we were called. case "$1" in start) echo "Starting daemon: " $name # start the program - start-stop-daemon -S -p ${pidfile} --oknodo -q -a ${mcollectived} -- ${daemonopts} - [ $? = 0 ] && { exit 0 ; } || { exit 1 ; } + if [ -f $pidfile ]; then + if [ -f "$(cat /proc/$(cat $pidfile)/exe > /dev/null)" ] ; then + echo MCollective appears to be running + exit 1 + else + /sbin/start-stop-daemon --start -b --quiet --oknodo -m --pidfile $pidfile --exec $mcollectived -- $daemonopts + [ $? = 0 ] && { exit 0 ; } || { exit 1 ; } + fi + else + /sbin/start-stop-daemon --start -b --quiet --oknodo -m --pidfile $pidfile --exec $mcollectived -- $daemonopts + fi log_success_msg "mcollective started" - touch $lock ;; stop) echo "Stopping daemon: " $name - start-stop-daemon -K -R 5 -s "TERM" --oknodo -q -p ${pidfile} + /sbin/start-stop-daemon --stop -q --pidfile $pidfile + if [ -f $pidfile ]; then + rm -f $pidfile + fi [ $? = 0 ] && { exit 0 ; } || { exit 1 ; } log_success_msg "mcollective stopped" ;; @@ -67,14 +75,6 @@ case "$1" in $0 start [ $? = 0 ] && { echo "mcollective restarted" ; exit 0 ; } ;; - condrestart) - if [ -f $lock ]; then - $0 stop - # avoid race - sleep 2 - $0 start - fi - ;; status) status_of_proc -p ${pidfile} ${mcollectived} ${name} && exit 0 || exit $? ;; diff --git a/debian/patches/conffile.dpatch b/debian/patches/conffile.dpatch index 07ba476..499ae7c 100755 --- a/debian/patches/conffile.dpatch +++ b/debian/patches/conffile.dpatch @@ -9,7 +9,6 @@ diff -urNad mcollective-0.4.1~/etc/client.cfg mcollective-0.4.1/etc/client.cfg --- mcollective-0.4.1~/etc/client.cfg 1970-01-01 00:00:00.000000000 +0000 +++ mcollective-0.4.1/etc/client.cfg 2010-01-06 14:37:24.000000000 +0000 @@ -0,0 +1,19 @@ -+topicprefix = /topic/mcollective +libdir = /usr/share/mcollective/plugins +logger_type = console +loglevel = warn @@ -33,7 +32,6 @@ diff -urNad mcollective-0.4.1~/etc/client.cfg.dist mcollective-0.4.1/etc/client. --- mcollective-0.4.1~/etc/client.cfg.dist 2010-01-02 14:54:25.000000000 +0000 +++ mcollective-0.4.1/etc/client.cfg.dist 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ --topicprefix = /topic/mcollective -libdir = /usr/libexec/mcollective -logger_type = console -loglevel = warn @@ -68,7 +66,6 @@ diff -urNad mcollective-0.4.1~/etc/server.cfg mcollective-0.4.1/etc/server.cfg --- mcollective-0.4.1~/etc/server.cfg 1970-01-01 00:00:00.000000000 +0000 +++ mcollective-0.4.1/etc/server.cfg 2010-01-06 14:37:50.000000000 +0000 @@ -0,0 +1,20 @@ -+topicprefix = /topic/mcollective +libdir = /usr/share/mcollective/plugins +logfile = /var/log/mcollective.log +loglevel = info @@ -93,7 +90,6 @@ diff -urNad mcollective-0.4.1~/etc/server.cfg.dist mcollective-0.4.1/etc/server. --- mcollective-0.4.1~/etc/server.cfg.dist 2010-01-02 14:54:25.000000000 +0000 +++ mcollective-0.4.1/etc/server.cfg.dist 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ --topicprefix = /topic/mcollective -libdir = /usr/libexec/mcollective -logfile = /var/log/mcollective.log -loglevel = info diff --git a/debian/patches/pluginsdir.dpatch b/debian/patches/pluginsdir.dpatch index ef56927..843c716 100755 --- a/debian/patches/pluginsdir.dpatch +++ b/debian/patches/pluginsdir.dpatch @@ -8,20 +8,18 @@ diff -urNad mcollective-1.1.4~/etc/client.cfg.dist mcollective-1.1.4/etc/client.cfg.dist --- mcollective-1.1.4~/etc/client.cfg.dist 2011-04-06 14:13:08.829462165 -0700 +++ mcollective-1.1.4/etc/client.cfg.dist 2011-04-06 14:12:53.129384114 -0700 -@@ -1,7 +1,7 @@ - topicprefix = /topic/ +@@ -1,6 +1,6 @@ main_collective = mcollective collectives = mcollective -libdir = /usr/libexec/mcollective +libdir = /usr/share/mcollective/plugins logger_type = console loglevel = warn - + diff -urNad mcollective-1.1.4~/etc/server.cfg.dist mcollective-1.1.4/etc/server.cfg.dist --- mcollective-1.1.4~/etc/server.cfg.dist 2011-04-06 14:12:30.889527230 -0700 +++ mcollective-1.1.4/etc/server.cfg.dist 2011-04-06 14:12:23.779407065 -0700 -@@ -1,7 +1,7 @@ - topicprefix = /topic/ +@@ -1,6 +1,6 @@ main_collective = mcollective collectives = mcollective -libdir = /usr/libexec/mcollective diff --git a/doc/.do-not-remove b/doc/.do-not-remove new file mode 100644 index 0000000..e69de29 diff --git a/doc/mcollective/COPYING b/doc/mcollective/COPYING deleted file mode 100644 index 375d1c8..0000000 --- a/doc/mcollective/COPYING +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2010, 2011 Puppet Labs - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/doc/mcollective/README b/doc/mcollective/README deleted file mode 100644 index 8db05de..0000000 --- a/doc/mcollective/README +++ /dev/null @@ -1,6 +0,0 @@ -The Marionette Collective -========================= - -The Marionette Collective aka. mcollective is a framework to build server orchestration or parallel job execution systems. - -For full information, wikis, ticketing and downloads please see http://marionette-collective.org/ diff --git a/etc/client.cfg.dist b/etc/client.cfg.dist index 514c1a5..1acffee 100644 --- a/etc/client.cfg.dist +++ b/etc/client.cfg.dist @@ -1,4 +1,3 @@ -topicprefix = /topic/ main_collective = mcollective collectives = mcollective libdir = /usr/libexec/mcollective diff --git a/etc/server.cfg.dist b/etc/server.cfg.dist index beed021..2038324 100644 --- a/etc/server.cfg.dist +++ b/etc/server.cfg.dist @@ -1,4 +1,3 @@ -topicprefix = /topic/ main_collective = mcollective collectives = mcollective libdir = /usr/libexec/mcollective diff --git a/ext/activemq/examples/multi-broker/broker1-activemq.xml b/ext/activemq/examples/multi-broker/broker1-activemq.xml index a910b3d..bc7fe07 100755 --- a/ext/activemq/examples/multi-broker/broker1-activemq.xml +++ b/ext/activemq/examples/multi-broker/broker1-activemq.xml @@ -12,7 +12,29 @@ + + + + + + @@ -26,11 +48,20 @@ + broker3 --> + + + + + + + - + + + @@ -103,6 +166,10 @@ + @@ -110,6 +177,11 @@ + @@ -124,10 +196,25 @@ + - - + + + + diff --git a/ext/activemq/examples/multi-broker/broker2-activemq.xml b/ext/activemq/examples/multi-broker/broker2-activemq.xml index 163cf36..5f1d027 100755 --- a/ext/activemq/examples/multi-broker/broker2-activemq.xml +++ b/ext/activemq/examples/multi-broker/broker2-activemq.xml @@ -12,7 +12,29 @@ + + + + + + @@ -26,15 +48,47 @@ + + + + + + + - + + + @@ -43,6 +97,10 @@ + @@ -50,6 +108,11 @@ + @@ -64,10 +127,25 @@ + - - + + + + diff --git a/ext/activemq/examples/multi-broker/broker3-activemq.xml b/ext/activemq/examples/multi-broker/broker3-activemq.xml index d118852..b9366fc 100755 --- a/ext/activemq/examples/multi-broker/broker3-activemq.xml +++ b/ext/activemq/examples/multi-broker/broker3-activemq.xml @@ -12,7 +12,29 @@ + + + + + + @@ -26,15 +48,47 @@ + + + + + + + - + + + @@ -43,6 +97,10 @@ + @@ -50,6 +108,11 @@ + @@ -64,10 +127,25 @@ + - - + + + + diff --git a/ext/activemq/examples/single-broker/activemq.xml b/ext/activemq/examples/single-broker/activemq.xml index bb9ea1b..7f9e9f8 100644 --- a/ext/activemq/examples/single-broker/activemq.xml +++ b/ext/activemq/examples/single-broker/activemq.xml @@ -12,7 +12,27 @@ + + + + @@ -28,12 +48,30 @@ + + - + + + @@ -42,6 +80,10 @@ + @@ -49,6 +91,11 @@ + @@ -63,10 +110,25 @@ + - - + + + + diff --git a/ext/debian/patches/conffile.dpatch b/ext/debian/patches/conffile.dpatch index 07ba476..499ae7c 100755 --- a/ext/debian/patches/conffile.dpatch +++ b/ext/debian/patches/conffile.dpatch @@ -9,7 +9,6 @@ diff -urNad mcollective-0.4.1~/etc/client.cfg mcollective-0.4.1/etc/client.cfg --- mcollective-0.4.1~/etc/client.cfg 1970-01-01 00:00:00.000000000 +0000 +++ mcollective-0.4.1/etc/client.cfg 2010-01-06 14:37:24.000000000 +0000 @@ -0,0 +1,19 @@ -+topicprefix = /topic/mcollective +libdir = /usr/share/mcollective/plugins +logger_type = console +loglevel = warn @@ -33,7 +32,6 @@ diff -urNad mcollective-0.4.1~/etc/client.cfg.dist mcollective-0.4.1/etc/client. --- mcollective-0.4.1~/etc/client.cfg.dist 2010-01-02 14:54:25.000000000 +0000 +++ mcollective-0.4.1/etc/client.cfg.dist 1970-01-01 00:00:00.000000000 +0000 @@ -1,19 +0,0 @@ --topicprefix = /topic/mcollective -libdir = /usr/libexec/mcollective -logger_type = console -loglevel = warn @@ -68,7 +66,6 @@ diff -urNad mcollective-0.4.1~/etc/server.cfg mcollective-0.4.1/etc/server.cfg --- mcollective-0.4.1~/etc/server.cfg 1970-01-01 00:00:00.000000000 +0000 +++ mcollective-0.4.1/etc/server.cfg 2010-01-06 14:37:50.000000000 +0000 @@ -0,0 +1,20 @@ -+topicprefix = /topic/mcollective +libdir = /usr/share/mcollective/plugins +logfile = /var/log/mcollective.log +loglevel = info @@ -93,7 +90,6 @@ diff -urNad mcollective-0.4.1~/etc/server.cfg.dist mcollective-0.4.1/etc/server. --- mcollective-0.4.1~/etc/server.cfg.dist 2010-01-02 14:54:25.000000000 +0000 +++ mcollective-0.4.1/etc/server.cfg.dist 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ --topicprefix = /topic/mcollective -libdir = /usr/libexec/mcollective -logfile = /var/log/mcollective.log -loglevel = info diff --git a/ext/debian/patches/pluginsdir.dpatch b/ext/debian/patches/pluginsdir.dpatch index ef56927..843c716 100755 --- a/ext/debian/patches/pluginsdir.dpatch +++ b/ext/debian/patches/pluginsdir.dpatch @@ -8,20 +8,18 @@ diff -urNad mcollective-1.1.4~/etc/client.cfg.dist mcollective-1.1.4/etc/client.cfg.dist --- mcollective-1.1.4~/etc/client.cfg.dist 2011-04-06 14:13:08.829462165 -0700 +++ mcollective-1.1.4/etc/client.cfg.dist 2011-04-06 14:12:53.129384114 -0700 -@@ -1,7 +1,7 @@ - topicprefix = /topic/ +@@ -1,6 +1,6 @@ main_collective = mcollective collectives = mcollective -libdir = /usr/libexec/mcollective +libdir = /usr/share/mcollective/plugins logger_type = console loglevel = warn - + diff -urNad mcollective-1.1.4~/etc/server.cfg.dist mcollective-1.1.4/etc/server.cfg.dist --- mcollective-1.1.4~/etc/server.cfg.dist 2011-04-06 14:12:30.889527230 -0700 +++ mcollective-1.1.4/etc/server.cfg.dist 2011-04-06 14:12:23.779407065 -0700 -@@ -1,7 +1,7 @@ - topicprefix = /topic/ +@@ -1,6 +1,6 @@ main_collective = mcollective collectives = mcollective -libdir = /usr/libexec/mcollective diff --git a/ext/openbsd/port-files/mcollective/patches/patch-etc_server_cfg_dist b/ext/openbsd/port-files/mcollective/patches/patch-etc_server_cfg_dist index 61bf822..acf348b 100644 --- a/ext/openbsd/port-files/mcollective/patches/patch-etc_server_cfg_dist +++ b/ext/openbsd/port-files/mcollective/patches/patch-etc_server_cfg_dist @@ -2,9 +2,8 @@ $OpenBSD$ --- etc/server.cfg.dist.orig Thu Jun 24 15:57:17 2010 +++ etc/server.cfg.dist Thu Jun 24 15:57:25 2010 @@ -1,5 +1,5 @@ - topicprefix = /topic/mcollective -libdir = /usr/libexec/mcollective -+libdir = ${PREFIX}/share/mcollective/plugins ++libdir = ${PREFIX}/share/mcollective/plugins logfile = /var/log/mcollective.log loglevel = info daemonize = 1 diff --git a/ext/redhat/mcollective.spec b/ext/redhat/mcollective.spec index d11def7..2eb54fc 100644 --- a/ext/redhat/mcollective.spec +++ b/ext/redhat/mcollective.spec @@ -10,8 +10,6 @@ License: ASL 2.0 URL: http://puppetlabs.com/mcollective/introduction/ Source0: http://downloads.puppetlabs.com/mcollective/%{name}-%{version}.tgz BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) -BuildRequires: ruby -BuildRequires: ruby(abi) >= 1.8 Requires: mcollective-common = %{version}-%{release} Packager: R.I.Pienaar BuildArch: noarch diff --git a/ext/solaris11/README.md b/ext/solaris11/README.md index 17d70e9..cd0df71 100644 --- a/ext/solaris11/README.md +++ b/ext/solaris11/README.md @@ -74,7 +74,6 @@ Configuration There is no packaged configuration; you can use the following example: # cat > /etc/mcollective/client.cfg << "EOF" - topicprefix = /topic/ main_collective = mcollective collectives = mcollective libdir = /usr/share/mcollective/plugins diff --git a/lib/mcollective.rb b/lib/mcollective.rb index 8b376df..8b1431f 100644 --- a/lib/mcollective.rb +++ b/lib/mcollective.rb @@ -7,6 +7,7 @@ require 'singleton' require 'socket' require 'erb' require 'shellwords' +require 'stringio' require 'rbconfig' require 'tempfile' require 'tmpdir' diff --git a/lib/mcollective/application.rb b/lib/mcollective/application.rb index 66751e0..85f57eb 100644 --- a/lib/mcollective/application.rb +++ b/lib/mcollective/application.rb @@ -319,46 +319,31 @@ module MCollective exit 1 end + def halt_code(stats) + request_stats = {:discoverytime => 0, + :discovered => 0, + :okcount => 0, + :failcount => 0}.merge(stats.to_hash) + + return 4 if request_stats[:discoverytime] == 0 && request_stats[:responses] == 0 + return 3 if request_stats[:discovered] > 0 && request_stats[:responses] == 0 + return 2 if request_stats[:discovered] > 0 && request_stats[:failcount] > 0 + return 1 if request_stats[:discovered] == 0 + return 0 if request_stats[:discoverytime] == 0 && request_stats[:discovered] == request_stats[:okcount] + return 0 if request_stats[:discovered] == request_stats[:okcount] + end + # A helper that creates a consistent exit code for applications by looking at an # instance of MCollective::RPC::Stats # # Exit with 0 if nodes were discovered and all passed - # Exit with 0 if no discovery were done and > 0 responses were received + # Exit with 0 if no discovery were done and > 0 responses were received, all ok # Exit with 1 if no nodes were discovered # Exit with 2 if nodes were discovered but some RPC requests failed - # Exit with 3 if nodes were discovered, but not responses received + # Exit with 3 if nodes were discovered, but no responses received # Exit with 4 if no discovery were done and no responses were received def halt(stats) - request_stats = {:discoverytime => 0, - :discovered => 0, - :failcount => 0}.merge(stats.to_hash) - - # was discovery done? - if request_stats[:discoverytime] != 0 - # was any nodes discovered - if request_stats[:discovered] == 0 - exit 1 - - # nodes were discovered, did we get responses - elsif request_stats[:responses] == 0 - exit 3 - - else - # we got responses and discovery was done, no failures - if request_stats[:failcount] == 0 - exit 0 - else - exit 2 - end - end - else - # discovery wasnt done and we got no responses - if request_stats[:responses] == 0 - exit 4 - else - exit 0 - end - end + exit(halt_code(stats)) end # Wrapper around MC::RPC#rpcclient that forcably supplies our options hash diff --git a/lib/mcollective/config.rb b/lib/mcollective/config.rb index 8b5e409..7ce3a26 100644 --- a/lib/mcollective/config.rb +++ b/lib/mcollective/config.rb @@ -5,16 +5,16 @@ module MCollective attr_accessor :mode - attr_reader :topicprefix, :daemonize, :pluginconf, :libdir, :configured + attr_reader :daemonize, :pluginconf, :libdir, :configured attr_reader :logfile, :keeplogs, :max_log_size, :loglevel, :logfacility attr_reader :identity, :daemonize, :connector, :securityprovider, :factsource - attr_reader :registration, :registerinterval, :topicsep, :classesfile + attr_reader :registration, :registerinterval, :classesfile attr_reader :rpcauditprovider, :rpcaudit, :configdir, :rpcauthprovider attr_reader :rpcauthorization, :color, :configfile, :rpchelptemplate attr_reader :rpclimitmethod, :logger_type, :fact_cache_time, :collectives attr_reader :main_collective, :ssl_cipher, :registration_collective attr_reader :direct_addressing, :direct_addressing_threshold, :ttl, :helptemplatedir - attr_reader :queueprefix, :default_discovery_method, :default_discovery_options + attr_reader :default_discovery_method, :default_discovery_options def initialize @configured = false @@ -24,7 +24,7 @@ module MCollective set_config_defaults(configfile) if File.exists?(configfile) - File.open(configfile, "r").each do |line| + File.readlines(configfile).each do |line| # strip blank spaces, tabs etc off the end of all lines line.gsub!(/\s*$/, "") @@ -35,8 +35,6 @@ module MCollective val = $2 case key - when "topicsep" - @topicsep = val when "registration" @registration = val.capitalize when "registration_collective" @@ -47,10 +45,6 @@ module MCollective @collectives = val.split(",").map {|c| c.strip} when "main_collective" @main_collective = val - when "topicprefix" - @topicprefix = val - when "queueprefix" - @queueprefix = val when "logfile" @logfile = val when "keeplogs" @@ -74,7 +68,7 @@ module MCollective when "identity" @identity = val when "direct_addressing" - val =~ /^1|y/i ? @direct_addressing = true : @direct_addressing = false + @direct_addressing = false unless val =~ /^1|y/i when "direct_addressing_threshold" @direct_addressing_threshold = val.to_i when "color" @@ -124,6 +118,8 @@ module MCollective end end + raise('The %s config file does not specify a libdir setting, cannot continue' % configfile) if @libdir.empty? + I18n.load_path = Dir[File.expand_path(File.join(File.dirname(__FILE__), "locales", "*.yml"))] I18n.locale = :en @@ -163,9 +159,6 @@ module MCollective @registration = "Agentlist" @registerinterval = 0 @registration_collective = nil - @topicsep = "." - @topicprefix = "/topic/" - @queueprefix = "/queue/" @classesfile = "/var/lib/puppet/state/classes.txt" @rpcaudit = false @rpcauditprovider = "" @@ -185,7 +178,7 @@ module MCollective @collectives = ["mcollective"] @main_collective = @collectives.first @ssl_cipher = "aes-256-cbc" - @direct_addressing = false + @direct_addressing = true @direct_addressing_threshold = 10 @default_discovery_method = "mc" @default_discovery_options = [] diff --git a/lib/mcollective/data/base.rb b/lib/mcollective/data/base.rb index 3ff8213..fdfecee 100644 --- a/lib/mcollective/data/base.rb +++ b/lib/mcollective/data/base.rb @@ -13,7 +13,7 @@ module MCollective def initialize @name = self.class.to_s.split("::").last.downcase @ddl = DDL.new(@name, :data) - @result = Result.new + @result = Result.new(@ddl.dataquery_interface[:output]) @timeout = @ddl.meta[:timeout] || 1 startup_hook diff --git a/lib/mcollective/data/result.rb b/lib/mcollective/data/result.rb index e19a652..8ffe4d2 100644 --- a/lib/mcollective/data/result.rb +++ b/lib/mcollective/data/result.rb @@ -6,8 +6,12 @@ module MCollective # method_missing lookup strategy undef :type if method_defined?(:type) - def initialize + def initialize(outputs) @data = {} + + outputs.keys.each do |output| + @data[output] = outputs[output].fetch(:default, nil) + end end def include?(key) diff --git a/lib/mcollective/ddl/base.rb b/lib/mcollective/ddl/base.rb index d526755..b4e524d 100644 --- a/lib/mcollective/ddl/base.rb +++ b/lib/mcollective/ddl/base.rb @@ -81,7 +81,7 @@ module MCollective if ddlfile = findddlfile instance_eval(File.read(ddlfile), ddlfile, 1) else - raise_code(:PLMC18, "Can't find DDL for %{type} plugin '%{name}'", :debug, :type => @plugintype, :name => @pluginname) + raise_code(:PLMC40, "Can't find DDL for %{type} plugin '%{name}'", :debug, :type => @plugintype, :name => @pluginname) end end diff --git a/lib/mcollective/locales/en.yml b/lib/mcollective/locales/en.yml index 2ff5d7a..2bfee67 100644 --- a/lib/mcollective/locales/en.yml +++ b/lib/mcollective/locales/en.yml @@ -278,6 +278,13 @@ en: This message indicate that on first start this plugin failed to run, it will show the exception class, line and exception message to assist with debugging pattern: "Failed to start registration plugin: %{error}" + PLMC40: + example: "Can't find DDL for agent plugin 'puppet'" + expanded: |- + MCollective plugins come with DDL files that describe their behaviours, versions, capabilities and requirements. + + This error indicate that a DDL file for the plugin mentioned could not be found - it could be that you have a typing error in your command line or an installation error. + pattern: "Can't find DDL for %{type} plugin '%{name}'" PLMC5: expanded: |- In previous versions of MCollective a application called 'controller' were included that had the ability to request agent reloads and other commands that would control the runner. diff --git a/plugins/mcollective/agent/discovery.rb b/plugins/mcollective/agent/discovery.rb index ede2ec4..3d5d5d3 100644 --- a/plugins/mcollective/agent/discovery.rb +++ b/plugins/mcollective/agent/discovery.rb @@ -10,8 +10,6 @@ module MCollective config = Config.instance.pluginconf @timeout = 5 - @timeout = config["discovery.timeout"].to_i if config.include?("discovery.timeout") - @meta = {:license => "Apache License, Version 2", :author => "R.I.Pienaar ", :timeout => @timeout, diff --git a/plugins/mcollective/application/rpc.rb b/plugins/mcollective/application/rpc.rb index c69cfd1..32d59f9 100644 --- a/plugins/mcollective/application/rpc.rb +++ b/plugins/mcollective/application/rpc.rb @@ -84,6 +84,8 @@ class MCollective::Application::Rpc msg.request.headers["reply-to"], :headers => {}, :id => ""} elsif [:request, :direct_request].include?(msg.type) - target = make_target(msg.agent, msg.type, msg.collective, node) + target = make_target(msg.agent, msg.type, msg.collective, msg.reply_to, node) else raise "Don't now how to create a target for message type #{msg.type}" @@ -200,7 +200,7 @@ module MCollective return target end - def make_target(agent, type, collective, node=nil) + def make_target(agent, type, collective, reply_to=nil, node=nil) raise("Unknown target type #{type}") unless [:directed, :broadcast, :reply, :request, :direct_request].include?(type) raise("Unknown collective '#{collective}' known collectives are '#{@config.collectives.join ', '}'") unless @config.collectives.include?(collective) @@ -213,7 +213,11 @@ module MCollective when :broadcast, :request # publishing a request to all nodes with an agent target[:name] = "/exchange/%s_broadcast/%s" % [collective, agent] - target[:headers]["reply-to"] = "/temp-queue/mcollective_reply_%s" % agent + if reply_to + target[:headers]["reply-to"] = reply_to + else + target[:headers]["reply-to"] = "/temp-queue/mcollective_reply_%s" % agent + end target[:id] = "%s_broadcast_%s" % [collective, agent] when :direct_request # a request to a specific node diff --git a/spec/unit/application_spec.rb b/spec/unit/application_spec.rb index 9b1c434..d2e64eb 100755 --- a/spec/unit/application_spec.rb +++ b/spec/unit/application_spec.rb @@ -414,7 +414,7 @@ module MCollective describe "#halt" do before do - @stats = {:discoverytime => 0, :discovered => 0, :failcount => 0, :responses => 0} + @stats = {:discoverytime => 0, :discovered => 0, :failcount => 0, :responses => 0, :okcount => 0} end it "should exit with code 0 if discovery was done and all responses passed" do @@ -423,28 +423,25 @@ module MCollective @stats[:discoverytime] = 2 @stats[:discovered] = 2 @stats[:responses] = 2 + @stats[:okcount] = 2 - app.expects(:exit).with(0) - - app.halt(@stats) + app.halt_code(@stats).should == 0 end it "should exit with code 0 if no discovery were done but responses were received" do app = Application.new @stats[:responses] = 1 + @stats[:okcount] = 1 + @stats[:discovered] = 1 - app.expects(:exit).with(0) - - app.halt(@stats) + app.halt_code(@stats).should == 0 end - it "should exit with code 0 if discovery info is missing" do + it "should exit with code 1 if discovery info is missing" do app = Application.new - app.expects(:exit).with(0) - - app.halt({}) + app.halt_code({}).should == 1 end it "should exit with code 1 if no nodes were discovered and discovery was done" do @@ -452,22 +449,29 @@ module MCollective @stats[:discoverytime] = 2 - app.expects(:exit).with(1) - - app.halt(@stats) + app.halt_code(@stats).should == 1 end it "should exit with code 2 if a request failed for some nodes" do app = Application.new - @stats[:discovered] = 1 + @stats[:discovered] = 2 @stats[:failcount] = 1 @stats[:discoverytime] = 2 - @stats[:responses] = 1 + @stats[:responses] = 2 - app.expects(:exit).with(2) + app.halt_code(@stats).should == 2 + end + + it "should exit with code 2 when no discovery were done and there were failure results" do + app = Application.new - app.halt(@stats) + @stats[:discovered] = 1 + @stats[:failcount] = 1 + @stats[:discoverytime] = 0 + @stats[:responses] = 1 + + app.halt_code(@stats).should == 2 end it "should exit with code 3 if no responses were received after discovery" do @@ -476,17 +480,13 @@ module MCollective @stats[:discovered] = 1 @stats[:discoverytime] = 2 - app.expects(:exit).with(3) - - app.halt(@stats) + app.halt_code(@stats).should == 3 end it "should exit with code 4 if no discovery was done and no responses were received" do app = Application.new - app.expects(:exit).with(4) - - app.halt(@stats) + app.halt_code(@stats).should == 4 end end diff --git a/spec/unit/config_spec.rb b/spec/unit/config_spec.rb index adf71a5..f166f22 100755 --- a/spec/unit/config_spec.rb +++ b/spec/unit/config_spec.rb @@ -5,6 +5,13 @@ require 'spec_helper' module MCollective describe Config do describe "#loadconfig" do + it "should fail when no libdir is set" do + File.expects(:exists?).with("/nonexisting").returns(true) + File.expects(:readlines).with("/nonexisting").returns([]) + Config.instance.stubs(:set_config_defaults) + expect { Config.instance.loadconfig("/nonexisting") }.to raise_error("The /nonexisting config file does not specify a libdir setting, cannot continue") + end + it "should only test that libdirs are absolute paths" do Util.expects(:absolute_path?).with("/one").returns(true) Util.expects(:absolute_path?).with("/two").returns(true) @@ -15,14 +22,14 @@ module MCollective File.stubs(:exists?).with(File.join(File.dirname("/nonexisting"), "rpc-help.erb")).returns(true) ["/one:/two", "/three"].each do |path| - File.stubs(:open).with("/nonexisting", "r").returns(StringIO.new("libdir = #{path}")) + File.expects(:readlines).with("/nonexisting").returns(["libdir = #{path}"]) Config.instance.loadconfig("/nonexisting") PluginManager.clear end - File.stubs(:open).with("/nonexisting", "r").returns(StringIO.new("libdir = four")) + File.expects(:readlines).with("/nonexisting").returns(["libdir = four"]) expect { Config.instance.loadconfig("/nonexisting") }.to raise_error(/should be absolute paths/) end @@ -38,7 +45,7 @@ module MCollective "\\\\?\\c:\\foo", "//?/UNC/bar", "//foo/bar", "//?/c:/foo" ].each do |input| - File.expects(:open).with("/nonexisting", "r").returns(StringIO.new("identity = #{input}")) + File.expects(:readlines).with("/nonexisting").returns(["identity = #{input}", "libdir=/nonexistinglib"]) File.expects(:exists?).with("/nonexisting").returns(true) File.expects(:exists?).with(File.join(File.dirname("/nonexisting"), "rpc-help.erb")).returns(true) @@ -50,7 +57,7 @@ module MCollective it "should allow valid identities" do ["foo", "foo_bar", "foo-bar", "foo-bar-123", "foo.bar", "foo_bar_123"].each do |input| - File.expects(:open).with("/nonexisting", "r").returns(StringIO.new("identity = #{input}")) + File.expects(:readlines).with("/nonexisting").returns(["identity = #{input}", "libdir=/nonexistinglib"]) File.expects(:exists?).with("/nonexisting").returns(true) File.expects(:exists?).with(File.join(File.dirname("/nonexisting"), "rpc-help.erb")).returns(true) PluginManager.stubs(:loadclass) @@ -60,9 +67,31 @@ module MCollective end end + it "should set direct_addressing to true by default" do + File.expects(:readlines).with("/nonexisting").returns(["libdir=/nonexistinglib"]) + File.expects(:exists?).with("/nonexisting").returns(true) + File.expects(:exists?).with(File.join(File.dirname("/nonexisting"), "rpc-help.erb")).returns(true) + PluginManager.stubs(:loadclass) + PluginManager.stubs("<<") + + Config.instance.loadconfig("/nonexisting") + Config.instance.direct_addressing.should == true + end + + it "should allow direct_addressing to be disabled in the config file" do + File.expects(:readlines).with("/nonexisting").returns(["libdir=/nonexistinglib", "direct_addressing=n"]) + File.expects(:exists?).with("/nonexisting").returns(true) + File.expects(:exists?).with(File.join(File.dirname("/nonexisting"), "rpc-help.erb")).returns(true) + PluginManager.stubs(:loadclass) + PluginManager.stubs("<<") + + Config.instance.loadconfig("/nonexisting") + Config.instance.direct_addressing.should == false + end + it "should not allow the syslog logger type on windows" do Util.expects("windows?").returns(true).twice - File.expects(:open).with("/nonexisting", "r").returns(StringIO.new("logger_type = syslog")) + File.expects(:readlines).with("/nonexisting").returns(["libdir=/nonexistinglib", "logger_type=syslog"]) File.expects(:exists?).with("/nonexisting").returns(true) File.expects(:exists?).with(File.join(File.dirname("/nonexisting"), "rpc-help.erb")).returns(true) PluginManager.stubs(:loadclass) @@ -74,7 +103,7 @@ module MCollective it "should default to finding the help template in the same dir as the config file" do path = File.join(File.dirname("/nonexisting"), "rpc-help.erb") - File.expects(:open).with("/nonexisting", "r").returns(StringIO.new("")) + File.expects(:readlines).with("/nonexisting").returns(["libdir=/nonexistinglib"]) File.expects(:exists?).with("/nonexisting").returns(true) PluginManager.stubs(:loadclass) PluginManager.stubs("<<") @@ -88,7 +117,7 @@ module MCollective it "should fall back to old behavior if the help template file does not exist in the config dir" do path = File.join(File.dirname("/nonexisting"), "rpc-help.erb") - File.expects(:open).with("/nonexisting", "r").returns(StringIO.new("")) + File.expects(:readlines).with("/nonexisting").returns(["libdir=/nonexistinglib"]) File.expects(:exists?).with("/nonexisting").returns(true) File.expects(:exists?).with(path).returns(false) PluginManager.stubs(:loadclass) @@ -99,7 +128,7 @@ module MCollective end it "should support multiple default_discovery_options" do - File.expects(:open).with("/nonexisting", "r").returns(StringIO.new("default_discovery_options = 1\ndefault_discovery_options = 2")) + File.expects(:readlines).with("/nonexisting").returns(["default_discovery_options = 1", "default_discovery_options = 2", "libdir=/nonexistinglib"]) File.expects(:exists?).with("/nonexisting").returns(true) File.expects(:exists?).with(File.join(File.dirname("/nonexisting"), "rpc-help.erb")).returns(true) PluginManager.stubs(:loadclass) @@ -155,7 +184,8 @@ module MCollective File.stubs(:exists?).returns(true) File.stubs(:directory?).with(@plugindir).returns(true) File.stubs(:exists?).with(servercfg).returns(true) - File.expects(:open).with(servercfg, "r").returns(["plugin.rspec.key = default"]) + File.expects(:readlines).with(servercfg).returns(["plugin.rspec.key = default", "libdir=/nonexisting"]) + File.stubs(:directory?).with("/nonexisting").returns(true) Dir.expects(:new).with(@plugindir).returns(["rspec.cfg"]) File.expects(:open).with(File.join(@plugindir, "rspec.cfg"), "r").returns(["key = overridden"]) diff --git a/spec/unit/data/base_spec.rb b/spec/unit/data/base_spec.rb index 51ffa6c..80a1504 100644 --- a/spec/unit/data/base_spec.rb +++ b/spec/unit/data/base_spec.rb @@ -7,6 +7,7 @@ module MCollective describe Base do before do @ddl = mock + @ddl.stubs(:dataquery_interface).returns({:output => {'rspec' => {}}}) @ddl.stubs(:meta).returns({:timeout => 1}) end diff --git a/spec/unit/data/result_spec.rb b/spec/unit/data/result_spec.rb index 9ea22cd..4f88932 100644 --- a/spec/unit/data/result_spec.rb +++ b/spec/unit/data/result_spec.rb @@ -6,7 +6,21 @@ module MCollective module Data describe Result do before(:each) do - @result = Result.new + @result = Result.new({}) + end + + describe "#initialize" do + it "should initialize empty values for all output fields" do + result = Result.new({:rspec1 => {}, :rspec2 => {}}) + result[:rspec1].should == nil + result[:rspec2].should == nil + end + + it "should set default values for all output fields" do + result = Result.new({:rspec1 => {:default => 1}, :rspec2 => {}}) + result[:rspec1].should == 1 + result[:rspec2].should == nil + end end describe "#[]=" do diff --git a/spec/unit/data_spec.rb b/spec/unit/data_spec.rb index a117ce0..cc7dbf8 100644 --- a/spec/unit/data_spec.rb +++ b/spec/unit/data_spec.rb @@ -17,6 +17,8 @@ module MCollective ddl = mock ddl.stubs(:meta).returns({:timeout => 1}) + ddl.stubs(:dataquery_interface).returns({:rspec => nil}) + ddl.stubs(:dataquery_interface).returns({:output => {}}) DDL.stubs(:new).returns(ddl) Data::Base.expects(:activate?).returns(false) PluginManager.expects("[]").with("rspec_data").returns(Data::Base.new) @@ -30,6 +32,7 @@ module MCollective ddl = mock ddl.stubs(:meta).returns({:timeout => 1}) + ddl.stubs(:dataquery_interface).returns({:output => {}}) DDL.stubs(:new).returns(ddl) Data::Base.expects(:activate?).raises("rspec failure") Log.expects(:debug).once.with("Disabling data plugin rspec_data due to exception RuntimeError: rspec failure") diff --git a/spec/unit/plugins/mcollective/connector/rabbitmq_spec.rb b/spec/unit/plugins/mcollective/connector/rabbitmq_spec.rb index 82b9d94..bf09704 100644 --- a/spec/unit/plugins/mcollective/connector/rabbitmq_spec.rb +++ b/spec/unit/plugins/mcollective/connector/rabbitmq_spec.rb @@ -264,6 +264,7 @@ module MCollective msg.stubs(:agent).returns("agent") msg.stubs(:collective).returns("mcollective") msg.stubs(:type).returns(:direct_request) + msg.stubs(:reply_to).returns("/topic/mcollective") msg.expects(:discovered_hosts).returns(["one", "two"]) @connection.expects(:publish).with('/exchange/mcollective_directed/one', 'msg', {'reply-to' => '/temp-queue/mcollective_reply_agent'}) @@ -345,8 +346,9 @@ module MCollective message.expects(:type).returns(:request).times(3) message.expects(:agent).returns("rspecagent") message.expects(:collective).returns("mcollective") + message.expects(:reply_to).returns("/topic/rspec") - @c.expects(:make_target).with("rspecagent", :request, "mcollective", nil) + @c.expects(:make_target).with("rspecagent", :request, "mcollective", "/topic/rspec", nil) @c.target_for(message) end @@ -355,8 +357,9 @@ module MCollective message.expects(:type).returns(:direct_request).times(3) message.expects(:agent).returns("rspecagent") message.expects(:collective).returns("mcollective") + message.expects(:reply_to).returns("/topic/rspec") - @c.expects(:make_target).with("rspecagent", :direct_request, "mcollective", nil) + @c.expects(:make_target).with("rspecagent", :direct_request, "mcollective", "/topic/rspec", nil) @c.target_for(message) end @@ -383,8 +386,9 @@ module MCollective @c.make_target("test", :reply, "mcollective").should == {:name => "/temp-queue/mcollective_reply_test", :headers => {}, :id => "mcollective_test_replies"} @c.make_target("test", :broadcast, "mcollective").should == {:name => "/exchange/mcollective_broadcast/test", :headers => {"reply-to"=>"/temp-queue/mcollective_reply_test"}, :id => "mcollective_broadcast_test"} @c.make_target("test", :request, "mcollective").should == {:name => "/exchange/mcollective_broadcast/test", :headers => {"reply-to"=>"/temp-queue/mcollective_reply_test"}, :id => "mcollective_broadcast_test"} - @c.make_target("test", :direct_request, "mcollective", "rspec").should == {:headers=>{"reply-to"=>"/temp-queue/mcollective_reply_test"}, :name=>"/exchange/mcollective_directed/rspec", :id => nil} + @c.make_target("test", :direct_request, "mcollective", nil, "rspec").should == {:headers=>{"reply-to"=>"/temp-queue/mcollective_reply_test"}, :name=>"/exchange/mcollective_directed/rspec", :id => nil} @c.make_target("test", :directed, "mcollective").should == {:name => "/exchange/mcollective_directed/rspec", :headers=>{}, :id => "rspec_directed_to_identity"} + @c.make_target("test", :request, "mcollective", "/topic/rspec", "rspec").should == {:headers=>{"reply-to"=>"/topic/rspec"}, :name=>"/exchange/mcollective_broadcast/test", :id => "mcollective_broadcast_test"} end it "should raise an error for unknown collectives" do diff --git a/spec/unit/plugins/mcollective/data/agent_data_spec.rb b/spec/unit/plugins/mcollective/data/agent_data_spec.rb index 8477a63..6c8670f 100644 --- a/spec/unit/plugins/mcollective/data/agent_data_spec.rb +++ b/spec/unit/plugins/mcollective/data/agent_data_spec.rb @@ -10,6 +10,7 @@ module MCollective describe "#query_data" do before do @ddl = mock + @ddl.stubs(:dataquery_interface).returns({:output => {}}) @ddl.stubs(:meta).returns({:timeout => 1}) DDL.stubs(:new).returns(@ddl) @plugin = Agent_data.new diff --git a/spec/unit/plugins/mcollective/data/fstat_data_spec.rb b/spec/unit/plugins/mcollective/data/fstat_data_spec.rb index babca39..228c0b1 100644 --- a/spec/unit/plugins/mcollective/data/fstat_data_spec.rb +++ b/spec/unit/plugins/mcollective/data/fstat_data_spec.rb @@ -11,6 +11,7 @@ module MCollective before do @ddl = mock @ddl.stubs(:meta).returns({:timeout => 1}) + @ddl.stubs(:dataquery_interface).returns({:output => {}}) DDL.stubs(:new).returns(@ddl) @plugin = Fstat_data.new diff --git a/spec/unit/security/base_spec.rb b/spec/unit/security/base_spec.rb index d36264c..9aaacf8 100755 --- a/spec/unit/security/base_spec.rb +++ b/spec/unit/security/base_spec.rb @@ -10,7 +10,6 @@ module MCollective @config.stubs(:identity).returns("test") @config.stubs(:configured).returns(true) @config.stubs(:topicsep).returns(".") - @config.stubs(:topicprefix).returns("/topic/") @stats = mock("stats") diff --git a/website/changelog.md b/website/changelog.md index b8e678e..a7cd14f 100644 --- a/website/changelog.md +++ b/website/changelog.md @@ -8,21 +8,32 @@ toc: false |Date|Description|Ticket| |----|-----------|------| +|2013/03/22|Remove the topicprefix, queueprefix and topicsep options|19673| +|2013/03/21|Remove the plugin.discovery.timeout setting as it's not relevant anymore|19694| +|2013/03/21|Improve error reporting from the rpc application in the light of direct_addressing|19827| +|2013/03/20|Fail with a friendly error message when no libdir is set|19752| +|2013/03/14|Change default RabbitMQ and ActiveMQ ports to 61613|19734| +|2013/03/13|Set correct reply-to headers in the RabbitMQ connector|17034| +|2013/03/12|Pre-populate the data from data plugins like agent replies|19564| +|2013/03/12|Explicitly include StringIO|19367| +|2013/03/12|Enable direct addressing by default|19665| +|2013/02/20|Fix error code collision on PLMC18|19366| +|2013/02/15|Validate arguments supplied to the RPC application and raise errors sooner|19181| |*2013/02/14*|*Release 2.3.1*|19265| -|2012/02/14|Initial work towards internationalization and online help|18663| +|2013/02/14|Initial work towards internationalization and online help|18663| |2013/02/14|Update vendored JSON gem for CVE-2013-0269|19265| -|2012/02/13|Restore the ability to set a discovery timeout on a RPC client|19238| -|2012/02/12|Replace underscores in plugin names with dashes to keep Debian happy|19200| -|2012/02/12|Fix package building on certain Debian systems|19141| -|2012/02/12|Remove the stomp connector|19146| -|2012/02/07|Read the client config before trying to use any configuration options|19105| -|2012/01/22|When an argument fails to parse in the rpc application fail rather than continue with unintended consequences|18773| -|2012/01/22|The fix the *--no-response* argument to the rpc application that broke due to 18438|18513| -|2012/01/22|Set *=* dependencies on the various packages that form a plugin rather than *>=*|18758| -|2012/01/21|Improve presentation of the --help output for applications|18447| -|2012/01/21|When a request failed via *reply.fail*, only show the message and not the half built data|18434| +|2013/02/13|Restore the ability to set a discovery timeout on a RPC client|19238| +|2013/02/12|Replace underscores in plugin names with dashes to keep Debian happy|19200| +|2013/02/12|Fix package building on certain Debian systems|19141| +|2013/02/12|Remove the stomp connector|19146| +|2013/02/07|Read the client config before trying to use any configuration options|19105| +|2013/01/22|When an argument fails to parse in the rpc application fail rather than continue with unintended consequences|18773| +|2013/01/22|The fix the *--no-response* argument to the rpc application that broke due to 18438|18513| +|2013/01/22|Set *=* dependencies on the various packages that form a plugin rather than *>=*|18758| +|2013/01/21|Improve presentation of the --help output for applications|18447| +|2013/01/21|When a request failed via *reply.fail*, only show the message and not the half built data|18434| |*2013/01/10*|*Release 2.3.0*|18259| -|2012/01/10|Raise the correct exception when trying to access unknown data items in a Data results|18466| +|2013/01/10|Raise the correct exception when trying to access unknown data items in a Data results|18466| |2013/01/10|Fix failing documentation generation for data plugins|18437| |2013/01/09|Correctly support negative boolean flags declared as --[no]-foo|18438| |2013/01/03|Add the package iteration number as a dependency for the common packages|18273| @@ -53,12 +64,12 @@ toc: false |----|-----------|------| |*2013/02/14*|*Release 2.2.3*|19265| |2013/02/14|Update vendored JSON gem for CVE-2013-0269|19265| -|2012/02/13|Restore the ability to set a discovery timeout on a RPC client|19238| -|2012/02/12|Replace underscores in plugin names with dashes to keep Debian happy|19200| -|2012/02/12|Fix package building on certain Debian systems|19141| -|2012/02/12|Deprecate the stomp connector|19146| -|2012/02/07|Read the client config before trying to use any configuration options|19105| -|2012/01/22|Set *=* dependencies on the various packages that form a plugin rather than *>=*|18758| +|2013/02/13|Restore the ability to set a discovery timeout on a RPC client|19238| +|2013/02/12|Replace underscores in plugin names with dashes to keep Debian happy|19200| +|2013/02/12|Fix package building on certain Debian systems|19141| +|2013/02/12|Deprecate the stomp connector|19146| +|2013/02/07|Read the client config before trying to use any configuration options|19105| +|2013/01/22|Set *=* dependencies on the various packages that form a plugin rather than *>=*|18758| |*2013/01/17*|*Release 2.2.2*|18258| |2013/01/03|Add the package iteration number as a dependency for the common packages|18273| |2012/12/24|Restore the :any validator|18265| diff --git a/website/configure/server.md b/website/configure/server.md new file mode 100644 index 0000000..b8cba6f --- /dev/null +++ b/website/configure/server.md @@ -0,0 +1,732 @@ +--- +title: "MCollective » Configure » Servers" +layout: default +--- + + + +[middleware]: /mcollective/deploy/middleware/activemq.html +[filters]: /mcollective/reference/ui/filters.html +[plugin_directory]: http://projects.puppetlabs.com/projects/mcollective-plugins/wiki +[facter_plugin]: http://projects.puppetlabs.com/projects/mcollective-plugins/wiki/FactsFacter +[ohai_plugin]: http://projects.puppetlabs.com/projects/mcollective-plugins/wiki/FactsOhai +[chef_classfile]: /mcollective/reference/integration/chef.html#class-filters +[fact]: #facts-identity-and-classes +[connector_plugin]: #connector-settings +[subcollectives]: /mcollective/reference/basic/subcollectives.html +[registration]: /mcollective/reference/plugins/registration.html +[puppetdb]: /puppetdb/ +[security_plugin]: #security-plugin-settings +[auditing]: /mcollective/simplerpc/auditing.html +[authorization]: /mcollective/simplerpc/authorization.html +[actionpolicy]: http://projects.puppetlabs.com/projects/mcollective-plugins/wiki/AuthorizationActionPolicy +[security_aes]: /mcollective/reference/plugins/security_aes.html +[security_overview]: /mcollective/security.html +[ssl_plugin]: /mcollective/reference/plugins/security_ssl.html +[activemq_tls_verified]: /mcollective/reference/integration/activemq_ssl.html#ca-verified-tls +[activemq_connector]: /mcollective/reference/plugins/connector_activemq.html +[rabbitmq_connector]: /mcollective/reference/plugins/connector_rabbitmq.html +[stdlib]: http://forge.puppetlabs.com/puppetlabs/stdlib + +{% capture badbool %}**Note:** Use these exact values only; do not use "true" or "false."{% endcapture %} + +{% capture pluginname %}**Note:** Capitalization of plugin names doesn't matter; MCollective normalizes it before loading the plugin.{% endcapture %} + +{% capture path_separator %}system path separator (colon \[`:`\] on \*nix, semicolon \[`;`\] on Windows){% endcapture %} + + + +This document describes MCollective server configuration in MCollective 2.0.0 and higher. Older versions may lack certain fetaures. + + +Example / Index +----- + +The following is an example MCollective server config file showing all of the major groups of settings. All of the setting names styled as links can be clicked, and will take you down the page to a full description of that setting. + +[See below the example for a full description of the config file location and format.](#the-server-config-files) + +
# /etc/mcollective/server.cfg
+
+# Connector settings (required):
+# -----------------------------
+
+connector = activemq
+direct_addressing = 1
+
+# ActiveMQ connector settings:
+plugin.activemq.pool.size = 1
+plugin.activemq.pool.1.host = middleware.example.net
+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.ca = /var/lib/puppet/ssl/certs/ca.pem
+plugin.activemq.pool.1.ssl.cert = /var/lib/puppet/ssl/certs/web01.example.com.pem
+plugin.activemq.pool.1.ssl.key = /var/lib/puppet/ssl/private_keys/web01.example.com.pem
+plugin.activemq.pool.1.ssl.fallback = 0
+
+# RabbitMQ connector settings:
+plugin.rabbitmq.vhost = /mcollective
+plugin.rabbitmq.pool.size = 1
+plugin.rabbitmq.pool.1.host = middleware.example.net
+# ... etc., similar to activemq settings
+
+# Security plugin settings (required):
+# -----------------------------------
+
+securityprovider = ssl
+
+# SSL plugin settings:
+plugin.ssl_client_cert_dir = /etc/mcollective.d/clients
+plugin.ssl_server_private = /etc/mcollective.d/server_private.pem
+plugin.ssl_server_public = /etc/mcollective.d/server_public.pem
+
+# PSK plugin settings:
+plugin.psk = j9q8kx7fnuied9e
+
+# Facts, identity, and classes (recommended):
+# ------------------------------------------
+
+factsource = yaml
+plugin.yaml = /etc/mcollective/facts.yaml
+fact_cache_time = 300
+
+identity = web01.example.com
+
+classesfile = /var/lib/puppet/state/classes.txt
+
+# Subcollectives (optional):
+# -------------------------
+
+collectives = mcollective,uk_collective
+main_collective = mcollective
+
+# Registration (optional):
+# -----------------------
+
+registerinterval = 300
+registration = agentlist
+registration_collective = mcollective
+
+# Auditing (optional):
+# -------------------
+
+rpcaudit = 1
+rpcauditprovider = logfile
+plugin.rpcaudit.logfile = /var/log/mcollective-audit.log
+
+# Authorization (optional):
+# ------------------------
+
+rpcauthorization = 1
+rpcauthprovider = action_policy
+
+# Logging:
+# -------
+
+logger_type = file
+loglevel = info
+keeplogs = 5
+max_log_size = 2097152
+logfacility = user
+
+# Platform defaults:
+# -----------------
+
+daemonize = 1
+libdir = /usr/libexec/mcollective
+ssl_cipher = aes-256-cbc
+
+
+ + +([↑ Back to top](#content)) + + + + + + +The Server Config File(s) +----- + +### Main Config File + +MCollective servers are configured with the `/etc/mcollective/server.cfg` file. It contains MCollective's core settings, as well as settings for the various plugins. + +> **Warning:** This file contains sensitive credentials, and should only be readable by the root user, or whatever user the MCollective daemon runs as. + +### File Format + +Each line consists of a setting, an equals sign, and a value: + + # setting = value + connector = activemq + +The spaces on either side of the equals sign are optional. Lines starting with a `#` are comments. + +> **Note on Boolean Values:** MCollective's config code does not have consistent handling of boolean values. Many of the core settings will accept values of `1/0` and `y/n`, but will fail to handle `true/false`; additionally, each plugin can handle boolean values differently, and some of them do not properly handle the `y/n` values accepted by the core settings. +> +> Nearly all known plugins and core settings accept `1` and `0`. Until further notice, you should always use these for all boolean settings, as no other values are universally safe. + +### Plugin Config Directory (Optional) + +Many of MCollective's settings are named with the format `plugin..`. These settings can optionally be put in separate files, in the `/etc/mcollective/plugin.d/` directory. + +To move a plugin setting to an external file, put it in `/etc/mcollective/plugin.d/.cfg`, and use only the `` segment of the setting. So this: + + # /etc/mcollective/server.cfg + plugin.puppet.splay = true + +...is equivalent to: + + # /etc/mcollective/plugin.d/puppet.cfg + splay = true + +Note that this doesn't work for settings like `plugin.psk`, since they have no `` segment; a setting must have at least three segments to go in a plugin.cfg file. + +### Best Practices + +You should manage your MCollective servers' config files with config management software (such as Puppet). While most settings in a deployment are the same, several should be different for each server, and managing these differences manually is impractical. + +If your deployment is fairly simple and there is little division of responsibility (e.g. having one group in charge of MCollective core and another group in charge of several agent plugins), then you can manage the config file with a simple template. + +If your deployment is large or complex, or you expect it to become so, you should manage MCollective settings as individual resources, as this is the only practical way to divide responsibilities within a single file. + +Below is an example of how to do this using the `file_line` type from the [puppetlabs/stdlib module][stdlib]: + +{% highlight ruby %} + # /etc/puppet/modules/mcollective/manifests/setting.pp + define mcollective::setting ($setting = $title, $target = '/etc/mcollective/server.cfg', $value) { + validate_re($target, '\/(plugin\.d\/[a-z]+|server)\.cfg\Z') + $regex_escaped_setting = regsubst($setting, '\.', '\\.', 'G') # assume dots are the only regex-unsafe chars in a setting name. + + file_line {"mco_setting_${title}": + path => $target, + line => "${setting} = ${value}", + match => "^ *${regex_escaped_setting} *=.*$", + } + } + + # /etc/puppet/modules/mcollective_core/manifests/server/connector.pp + # ... + # Connector settings: + mcollective::setting { + 'connector': + value => 'activemq'; + 'direct_addressing': + value => '1'; + 'plugin.activemq.pool.size': + value => '1'; + 'plugin.activemq.pool.1.host': + value => $activemq_server; + 'plugin.activemq.pool.1.port': + value => '61614'; + 'plugin.activemq.pool.1.user': + value => $activemq_user; + 'plugin.activemq.pool.1.password': + value => $activemq_password; + 'plugin.activemq.pool.1.ssl': + value => '1'; + 'plugin.activemq.pool.1.ssl.fallback': + value => '1'; + } + # ... +{% endhighlight %} + +([↑ Back to top](#content)) + + +Required Settings +----- + +### Connector Settings + + +
connector = activemq
+direct_addressing = 1
+
+# ActiveMQ connector settings:
+plugin.activemq.pool.size = 1
+plugin.activemq.pool.1.host = middleware.example.net
+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.ca = /var/lib/puppet/ssl/certs/ca.pem
+plugin.activemq.pool.1.ssl.cert = /var/lib/puppet/ssl/certs/web01.example.com.pem
+plugin.activemq.pool.1.ssl.key = /var/lib/puppet/ssl/private_keys/web01.example.com.pem
+plugin.activemq.pool.1.ssl.fallback = 0
+
+# RabbitMQ connector settings:
+plugin.rabbitmq.vhost = /mcollective
+plugin.rabbitmq.pool.size = 1
+plugin.rabbitmq.pool.1.host = middleware.example.net
+plugin.rabbitmq.pool.1.port = 61613
+# ... etc., similar to activemq settings
+
+
+ + +MCollective always requires a connector plugin. The connector plugin is determined by the [middleware][] you chose for your deployment. Each connector plugin will have additional settings it requires. + +> #### Shared Configuration +> +> * All servers and clients must use the same connector plugin, and its settings must be configured compatibly. +> * You must use the right connector plugin for your [choice of middleware][middleware]. +> * The hostname and port must match what the middleware is using. The username and password must be valid login accounts on the middleware. If you are using [CA-verified TLS][activemq_tls_verified], the certificate must be signed by the same CA the middleware is using. + +#### `connector` + +Which connector plugin to use. This is determined by your [choice of middleware][middleware]. + +- _Default:_ `activemq` +- _Allowed values:_ `activemq`, `rabbitmq`, or the name of a third-party connector plugin. {{ pluginname }} + + +#### `direct_addressing` + +Whether your middleware supports direct point-to-point messages. **This should usually be turned on,** although it is off by default. The built-in `activemq` and `rabbitmq` connectors both support direct addressing, as does the external `redis` connector. (The older `stomp` connector, however, does not.) + +- _Default:_ `0` +- _Allowed values:_ `1`, `0`, `y`, `n` --- {{ badbool }} + +#### ActiveMQ Connector Settings + +ActiveMQ is the main middleware we recommend for MCollective. The ActiveMQ connector can use multiple servers as a failover pool; if you have only one server, just use a pool size of `1`. + +> **Note:** This is only a summary of the most commonly used ActiveMQ settings; there are about ten more settings that can be used to tune the connector's performance. [See the ActiveMQ connector documentation][activemq_connector] for more complete details. + +- **`plugin.activemq.pool.size`** --- How many ActiveMQ servers to attempt to use. _Default:_ (nothing) +- **`plugin.activemq.pool.1.host`** --- The hostname of the first ActiveMQ server. (Note that additional servers use the same settings as the first, incrementing the number.) _Default:_ (nothing) +- **`plugin.activemq.pool.1.port`** --- The Stomp port of the first ActiveMQ server. _Default:_ `61613` or `6163`, depending on the MCollective version. +- **`plugin.activemq.pool.1.user`** --- The ActiveMQ user account to connect as. If the `STOMP_USER` environment variable is set, MCollective will use its value instead of this setting. +- **`plugin.activemq.pool.1.password`** --- The password for the user account being used. If the `STOMP_PASSWORD` environment variable is set, MCollective will use its value instead of this setting. +- **`plugin.activemq.pool.1.ssl`** --- Whether to use TLS when connecting to ActiveMQ. _Default:_ `0`; _allowed:_ `1/0`, `true/false`, `yes/no` +- **`plugin.activemq.pool.1.ssl.fallback`** --- _(When `ssl == 1`)_ Whether to allow unverified TLS if the ca/cert/key settings aren't set. _Default:_ `0`; _allowed:_ `1/0`, `true/false`, `yes/no` +- **`plugin.activemq.pool.1.ssl.ca`** --- _(When `ssl == 1`)_ The CA certificate to use when verifying ActiveMQ's certificate. Must be the path to a `.pem` file. _Default:_ (nothing) +- **`plugin.activemq.pool.1.ssl.cert`** --- _(When `ssl == 1`)_ The certificate to present when connecting to ActiveMQ. Must be the path to a `.pem` file. _Default:_ (nothing) +- **`plugin.activemq.pool.1.ssl.key`** --- _(When `ssl == 1`)_ The private key corresponding to this node's certificate. Must be the path to a `.pem` file. _Default:_ (nothing) + +#### RabbitMQ Connector Settings + +The RabbitMQ connector uses very similar settings to the ActiveMQ connector, with the same `.pool.1.host` style of setting names. + +[See the RabbitMQ connector documentation][rabbitmq_connector] for more complete details. + + +([↑ Back to top](#content)) + + +### Security Plugin Settings + +
securityprovider = ssl
+
+# SSL plugin settings:
+plugin.ssl_client_cert_dir = /etc/mcollective.d/clients
+plugin.ssl_server_private = /etc/mcollective.d/server_private.pem
+plugin.ssl_server_public = /etc/mcollective.d/server_public.pem
+
+# PSK plugin settings:
+plugin.psk = j9q8kx7fnuied9e
+
+
+ +MCollective always requires a security plugin. (Although they're called security plugins, they actually handle more, including message serialization.) Each security plugin will have additional settings it requires. + +> #### Shared Configuration +> +> All servers and clients must use the same security plugin, and its settings must be configured compatibly. + +It's possible to write new security plugins, but most people use one of the three included in MCollective: + +- **SSL:** The best choice for most users. Provides very good security when combined with TLS on the connector plugin (see above). +- **PSK:** Poor security, but easy to configure; fine for proof-of-concept deployments. +- **AES:** Complex to configure, and carries a noticable performance cost in large networks. Only suitable for certain use cases, like where TLS on the middleware is impossible. + +For a full-system look at how security works in MCollective, see [Security Overview][security_overview]. + + +#### `securityprovider` + +Which security plugin to use. + +- _Default:_ `psk` +- _Allowed values:_ `ssl`, `psk`, `aes_security`, or the name of a third-party security plugin. {{ pluginname }} + +#### SSL Plugin Settings + +> **Note:** This security plugin requires you to manage and distribute SSL credentials. [See the SSL security plugin page][ssl_plugin] for full details. In summary: +> +> * All servers share **one** "server" keypair. They must all have a copy of the public key and private key. +> * Every admin user must have a copy of the server public key. +> * Every admin user has their own "client" keypair. +> * Every server must have a copy of **every** authorized client public key. + +All of these settings have **no default,** and must be set for the SSL plugin to work. + +- **`plugin.ssl_server_private`** --- The path to the server private key file, which must be in `.pem` format. +- **`plugin.ssl_server_public`** --- The path to the server public key file, which must be in `.pem` format. +- **`plugin.ssl_client_cert_dir`** --- A directory containing every authorized client public key. + + +#### PSK Plugin Settings + +> **Note:** The only credential used by this plugin is a single shared password, which all servers and admin users have a copy of. + +- **`plugin.psk`** --- The shared passphrase. If the `MCOLLECTIVE_PSK` environment variable is set, MCollective will use its value instead of this setting. + + +([↑ Back to top](#content)) + + +Facts, Identity, and Classes +----- + +
factsource = yaml
+plugin.yaml = /etc/mcollective/facts.yaml
+fact_cache_time = 300
+
+identity = web01.example.com
+
+classesfile = /var/lib/puppet/state/classes.txt
+
+
+ +MCollective clients use filters to discover nodes and limit commands. (See [Discovery Filters][filters] for more details.) These filters can use a variety of per-server metadata, including **facts, identity,** and **classes.** + +* **Facts:** A collection of key/value data about a server's hardware and software. (E.g. `memorytotal = 8.00 GB`, `kernel = Darwin`, etc.) +* **Identity:** The name of the node. +* **Classes:** The Puppet classes (or Chef cookbooks, etc.) applied to this node. Classes are useful as metadata because they describe what _roles_ a server fills at your site. + +None of these settings are mandatory, but MCollective is less useful without them. + +#### `identity` + +The node's name or identity. This **should** be unique for each node, but does not **need** to be. + +- _Default:_ The value of Ruby's `Socket.gethostname` method, which is usually the server's FQDN. +- _Sample value:_ `web01.example.com` +- _Allowed values:_ Any string containing only alphanumeric characters, hyphens, and dots --- i.e. matching the regular expression `/\A[\w\.\-]+\Z/` + +#### `classesfile` + +A file with a list of classes applied by your configuration management system. This should be a plain text file containing one class name per line. + +Puppet automatically writes a class file, which can be found by running `sudo puppet apply --configprint classfile`. [Chef can be made to write a class file][chef_classfile]. + +- _Default:_ `/var/lib/puppet/state/classes.txt` + + +#### `factsource` + +Which fact plugin to use. + +MCollective includes a fact plugin called `yaml`. Most users should use this default, set [the `plugin.yaml` setting (see below)](#pluginyaml), and arrange to fill the file it relies on. + +Other fact plugins (including [Facter][facter_plugin] and [Ohai][ohai_plugin] ones) are available in the [plugin directory][plugin_directory]. These may require settings of their own. + +- _Default:_ `yaml` +- _Allowed values:_ The name of any installed fact plugin, with the `_facts` suffix trimmed off. {{ pluginname }} + +#### `plugin.yaml` + +_When `factsource == yaml`_ + +The fact file(s) to load for [the default `yaml` fact plugin](#factsource). + +- _Default:_ (nothing) +- _Sample value:_ `/etc/mcollective/facts.yaml` +- _Valid values:_ A single path, or a list of paths separated by the {{ path_separator }}. + +**Notes:** + +The default `yaml` fact plugin reads cached facts from a file, which should be a simple YAML hash. If multiple files are specified, they will be merged. (Later files override prior ones if there are conflicting values.) + +**The user is responsible for populating the fact file;** by default it is empty, and MCollective has no facts. + +If you are using Puppet and Facter, you can populate it by putting something like the following in your puppet master's `/etc/puppet/manifests/site.pp`, outside any node definition: + +{% highlight ruby %} + # /etc/puppet/manifests/site.pp + file{"/etc/mcollective/facts.yaml": + owner => root, + group => root, + mode => 400, + loglevel => debug, # reduce noise in Puppet reports + content => inline_template("<%= scope.to_hash.reject { |k,v| k.to_s =~ /(uptime_seconds|timestamp|free)/ }.to_yaml %>"), # exclude rapidly changing facts + } +{% endhighlight %} + +#### `fact_cache_time` + +How long (in seconds) to cache fact results before refreshing from source. This can be ignored unless you're using a non-default `factsource`. + +- _Default:_ `300` + +([↑ Back to top](#content)) + + +Optional Features +----- + +### Subcollectives + +
collectives = mcollective,uk_collective
+main_collective = mcollective
+
+
+ +Subcollectives provide an alternate way of dividing up the servers in a deployment. They are mostly useful because the middleware can be made aware of them, which enables traffic flow and access restrictions. In multi-datacenter deployments, this can save bandwidth costs and give some extra security. + +* [See the Subcollectives and Partitioning page][subcollectives] for more details and an example of site partitioning. + +Subcollective membership is managed **on the server side,** by each server's config file. A given server can join any number of collectives, and will respond to commands from any of them. + +> #### Shared Configuration +> +> If you are using any additional collectives (besides the default `mcollective` collective), your middleware must be configured to permit traffic on those collectives. See the middleware deployment guide for your specific middleware to see how to do this: +> +> * ActiveMQ: [Subcollective topic/queue names](/mcollective/deploy/middleware/activemq.html#topic-and-queue-names) --- [Multi-subcollective authorization example](/mcollective/deploy/middleware/activemq.html#detailed-restrictions-with-multiple-subcollectives) + + +#### `collectives` + +A comma-separated list (spaces OK) of [subcollectives][] this server should join. + +- _Default:_ `mcollective` +- _Sample value:_ `mcollective,uk_collective` + +#### `main_collective` + +The main collective for this server. Currently, this is only used as the default value for the [`registration_collective`](#registrationcollective) setting. + +- _Default:_ (the first value of [the `collectives` setting](#collectives), usually `mcollective`) + + +([↑ Back to top](#content)) + + +### Node Registration + +
registerinterval = 300
+registration = agentlist
+registration_collective = mcollective
+
+
+ +By default, registration is disabled, due to [`registerinterval`](#registerinterval) being set to 0. + +Optionally, MCollective servers can [send periodic heartbeat messages][registration] containing some inventory information. This can provide a central inventory at sites that don't already use something like [PuppetDB][], and can also be used as a simple passive monitoring system. + +The default registration plugin, `agentlist`, sends a standard SimpleRPC command over the MCollective middleware, to be processed by some server with an agent called `registration` installed. You would need to ensure that the `registration` agent is extremely performant (due to the volume of message it will receive) and installed on a limited number of servers. If your [middleware][] supports detailed permissions, you must also ensure that it allows servers to send commands to the registration agent ([ActiveMQ instructions](/mcollective/deploy/middleware/activemq.html#detailed-restrictions)). + +Some registration plugins (e.g. `redis`) can insert data directly into the inventory instead of sending an RPC message. This is a flexible system, and the user is in charge of deciding what to build with it, if anything. If all you need is a searchable inventory, [PuppetDB][] is probably closer to your needs. + +#### `registerinterval` + +How long (in seconds) to wait between registration messages. Setting this to 0 disables registration. + +- _Default:_ `0` + +#### `registration` + +The [registration plugin][registration] to use. + +This plugin must be installed on the server sending the message, and will dictate what the message contains. The default `agentlist` plugin will only send a list of the installed agents. See [Registration Plugins][registration] for more details. + +- _Default:_ `agentlist` +- _Allowed values:_ The name of any installed registration plugin. {{ pluginname }} + +#### `registration_collective` + +Which subcollective to send registration messages to, when using a SimpleRPC-based registration plugin. + +- _Default:_ (the value of [`main_collective`](#maincollective), usually `mcollective`) + + +([↑ Back to top](#content)) + + +### Auditing + +
rpcaudit = 1
+rpcauditprovider = logfile
+plugin.rpcaudit.logfile = /var/log/mcollective-audit.log
+
+
+ +Optionally, MCollective can log the SimpleRPC agent commands it receives from admin users, recording both the command itself and some identifying information about the user who issued it. The caller ID of a command is determined by the [security plugin][security_plugin] being used. + +MCollective ships with a local logging audit plugin, called `Logfile`, which saves audit info to a local file (different from the daemon log file). Log lines look like this: + + 2010-12-28T17:09:03.889113+0000: reqid=319719cc475f57fda3f734136a31e19b: reqtime=1293556143 caller=cert=nagios@monitor1 agent=nrpe action=runcommand data={:process_results=>true, :command=>"check_mailq"} + +Tthere are central loggers available from [the plugin directory][plugin_directory], and you can also write your own audit plugins; see [Writing Auditing Plugins][auditing] for more information. + + +#### `rpcaudit` + +Whether to enable [SimpleRPC auditing][Auditing] for all SimpleRPC agent commands. + +- _Default:_ `0` +- _Allowed values:_ `1`, `0`, `y`, `n` --- {{ badbool }} + +#### `rpcauditprovider` + +The name of the audit plugin to use whenever SimpleRPC commands are received. + +- _Default:_ (nothing) +- _Sample value:_ `logfile` +- _Allowed values:_ The name of any installed audit plugin. {{ pluginname }} + + +#### `plugin.rpcaudit.logfile` + +_When `rpcauditprovider == logfile`_ + +The file to write to when using the `logfile` audit plugin. **Note:** this file is not automatically rotated. + +- _Default:_ `/var/log/mcollective-audit.log` + + +([↑ Back to top](#content)) + + +### Authorization + +
rpcauthorization = 1
+rpcauthprovider = action_policy
+
+
+ +Optionally, MCollective can refuse to execute agent commands unless they meet some requirement. The exact requirement is defined by an [authorization plugin][authorization]. + +See [SimpleRPC Authorization][authorization] for more details, including how to enable authorization for only certain agents. + +The [actionpolicy][] plugin, which is provided in the [plugin directory][plugin_directory], is fairly popular and seems to meet many users' needs, when combined with a [security plugin][security_plugin] that provides a verified caller ID (such as the SSL plugin). [See its documentation][actionpolicy] for details. + +#### `rpcauthorization` + +Whether to enable [SimpleRPC authorization][Authorization] globally. + +- _Default:_ `0` +- _Allowed values:_ `1`, `0`, `y`, `n` --- {{ badbool }} + +#### `rpcauthprovider` + +The plugin to use when globally managing authorization. See [SimpleRPC Authorization][authorization] for more details. + +- _Default:_ (nothing) +- _Sample value:_ `action_policy` +- _Allowed values:_ The name of any installed authorization plugin. This uses different capitalization/formatting rules from the other plugin settings: if the name of the plugin (in the code) has any interior capital letters (e.g. `ActionPolicy`), you should use a lowercase value for the setting but insert an underscore before the place where the interior capital letter(s) would have gone (e.g. `action_policy`). If the name contains no interior capital letters, simply use a lowercase value with no other changes. + + +([↑ Back to top](#content)) + + +Advanced Settings +----- + +### Logging + +
logger_type = file
+loglevel = info
+logfile = /var/log/mcollective.log
+keeplogs = 5
+max_log_size = 2097152
+logfacility = user
+
+
+ +The MCollective server daemon can log to its own log file (which it will automatically rotate), or to the syslog. It can also log directly to the console, if you are running it in the foreground instead of daemonized. + +Some of the settings below only apply if you are using log files, and some only apply if you are using syslog. + +#### `logger_type` + +How the MCollective server daemon should log. You generally want to use a file or syslog. + +- _Default:_ `file` +- _Allowed values:_ `file`, `syslog`, `console` + +#### `loglevel` + +How verbosely to log. + +- _Default:_ `info` +- _Allowed values:_ In increasing order of verbosity: `fatal`, `error` , `warn`, `info`, `debug` + +#### `logfile` + +_When `logger_type == file`_ + +Where the log file should be stored. + +- _Default:_ (nothing; the package's default config file usually sets a platform-appropriate value) +- _Sample value:_ `/var/log/mcollective.log` + +#### `keeplogs` + +_When `logger_type == file`_ + +The number of log files to keep when rotating. + +- _Default:_ `5` + +#### `max_log_size` + +_When `logger_type == file`_ + +Max size in bytes for log files before rotation happens. + +- _Default:_ `2097152` + +#### `logfacility` + +_When `logger_type == syslog`_ + +The syslog facility to use. + +- _Default:_ `user` + + +([↑ Back to top](#content)) + + +### Platform Defaults + +
daemonize = 1
+libdir = /usr/libexec/mcollective
+ssl_cipher = aes-256-cbc
+
+
+ +These settings generally shouldn't be changed by the user, but their values may vary by platform. The package you used to install MCollective should have created a config file with platform-appropriate values for these settings. + +#### `daemonize` + +Whether to fork and run the MCollective server daemon in the background. + +This depends on your platform's init system. For example, newer Ubuntu releases require this to be false, while RHEL-derived systems require it to be true. + +- _Default:_ `0` +- _Allowed values:_ `1`, `0`, `y`, `n` --- {{ badbool }} + +#### `libdir` + +Where to look for plugins. Should be a single path or a list of paths separated by the {{ path_separator }}. + +By default, this setting is blank, but the package you installed MCollective with should supply a default server.cfg file with a platform-appropriate value for this setting. **If server.cfg has no value for this setting, MCollective will not work.** + +- _Default:_ (nothing; the package's default config file usually sets a platform-appropriate value) +- _Sample value:_ `/usr/libexec/mcollective:/opt/mcollective` + +#### `ssl_cipher` + +The cipher to use for encryption. This is currently only relevant if you are using the [AES security plugin][security_aes]. + +This setting should be a standard OpenSSL cipher string. See `man enc` for a list. + +- _Default:_ `aes-256-cbc` diff --git a/website/deploy/middleware/activemq.md b/website/deploy/middleware/activemq.md new file mode 100644 index 0000000..1396a9a --- /dev/null +++ b/website/deploy/middleware/activemq.md @@ -0,0 +1,694 @@ +--- +title: "MCollective » Deploy » Middleware » ActiveMQ Config" +subtitle: "ActiveMQ Config Reference for MCollective Users" +layout: default +--- + +[Wildcard]: http://activemq.apache.org/wildcards.html +[minimal_example]: http://github.com/puppetlabs/marionette-collective/raw/master/ext/activemq/examples/single-broker/activemq.xml +[maximal_example]: https://github.com/puppetlabs/marionette-collective/tree/master/ext/activemq/examples/multi-broker +[template_example]: TODO +[apache_activemq_config_docs]: http://activemq.apache.org/version-5-xml-configuration.html + +[subcollectives]: /reference/basic/subcollectives.html +[activemq_connector]: /reference/plugins/connector_activemq.html +[mcollective_connector_tls]: /mcollective/reference/integration/activemq_ssl.html + + +Summary +----- + +Apache ActiveMQ is the primary middleware we recommend with MCollective. It's good software, but its XML config file is large and unwieldy, and you may need to edit many sections of it in a complex MCollective deployment. This reference guide attempts to describe every major ActiveMQ setting that matters to MCollective. + +### How to Use This Page + +* This page **doesn't** describe the complete format of the activemq.xml config file, and will sometimes use incomplete shorthand to describe elements of it. +* You should definitely refer to an example config file while reading, so you can see each element's full syntax in context. +* You don't need to read this entire page when setting up a new deployment. We recommend that you: + * Start with an example config file (see directly below). + * Make heavy use of the table of contents above. + * Skim the sections of this page you currently care about, and edit your config as needed. + * Refer back to this page later when you need to expand your broker infrastructure. +* If you are a new user, we recommend that you: + * Start with the [single-broker example config][minimal_example]. + * Change the [user account passwords](#authentication-users-and-groups). + * [Set up TLS](#tls-credentials). + +### Example Config Files + +We have several. + +* [Minimal config example][minimal_example] --- single broker +* [Maximal config example][maximal_example] --- multi-broker + + + + +> **Note:** Some config data needs to be set in both MCollective and ActiveMQ; your configuration of one will affect the other. In this page, we call out that information with headers labeled "Shared Configuration." + +### Version Limits + +This document is about the "new" MCollective/ActiveMQ interface, which means it requires the following: + +* 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) + +([↑ Back to top](#content)) + +How MCollective Uses ActiveMQ +----- + +MCollective connects to ActiveMQ over the Stomp protocol, and presents certain credentials: + +* It provides a username and password, with which ActiveMQ can do what it pleases. +* If TLS is in use, it will also present a certificate (and verify the ActiveMQ server's certificate). + +Once allowed to connect, MCollective will use the Stomp protocol to create subscriptions. It will then produce and consume a lot of traffic on queues and topics whose names begin with `mcollective`. (See "Topic and Queue Names" directly below.) + +### Absolute Minimum Requirements + +ActiveMQ defaults to believing that it is routing traffic between processes in a single JVM instance: it doesn't assume it is connected to the network, and it uses a loose-to-nonexistent security model. + +This means that if you do nothing but enable Stomp traffic, MCollective will work fine. (Albeit with terrible security and eventual out-of-control memory usage.) + +### Topic and Queue Names + +MCollective uses the following destination names. This list uses standard [ActiveMQ destination wildcards][wildcard]. "COLLECTIVE" is the name of the collective being used; by default, this is `mcollective`, but if you are using [subcollectives][], each one is implemented as an equal peer of the default collective. + +Topics: + +- `ActiveMQ.Advisory.>` (built-in topics that all ActiveMQ producers and consumers need all permissions on) +- `COLLECTIVE.*.agent` (for each agent plugin, where the `*` is the name of the plugin) + +Queues: + +- `COLLECTIVE.nodes` (used for direct addressing; this is a single destination that uses JMS selectors, rather than a group of destinations) +- `COLLECTIVE.reply.>` (where the continued portion is a request ID) + +> #### Shared Configuration +> +> Subcollectives must also be configured in the MCollective client and server config files. ActiveMQ must allow traffic on any subcollective that MCollective servers and clients expect to use. + +([↑ Back to top](#content)) + +Config File Location and Format +----- + +ActiveMQ's config is usually called activemq.xml, and is kept in ActiveMQ's configuration directory (`/etc/activemq` with Puppet Labs's Red Hat-like packages, or a subdirectory of `/etc/activemq/instances-enabled` with the standard Debian or Ubuntu packages). Any other files referenced in activemq.xml will be looked for in the same directory. + +The config file is in Java's Beans XML format. Note that all of the settings relevant to MCollective are located inside activemq.xml's `` element. + +This document won't describe the complete format of the activemq.xml config file, and will sometimes use incomplete shorthand to describe elements of it. You should definitely [refer to an example config file](#example-config-files) while reading, so you can see each element's full syntax in context. + +You can also read external documentation for a more complete understanding. + +> **Bug Warning:** In ActiveMQ 5.5, the first-level children of the `` element must be arranged in alphabetical order. There is no good reason for this behavior, and it was fixed in ActiveMQ 5.6. + +### External ActiveMQ Documentation + +The Apache ActiveMQ documentation contains important information, but it is often incomplete, badly organized, and confusing. The Fuse documentation (a commercially supported release of ActiveMQ) is significantly better written and better organized, although it requires signing up for an email newsletter, but it may be out of sync with the most recent ActiveMQ releases. + +* [Apache ActiveMQ Documentation][apache_activemq_config_docs] +* [Fuse Documentation](http://fusesource.com/documentation/fuse-message-broker-documentation/) + +### Wildcards + +You'll see a lot of [ActiveMQ destination wildcards][wildcard] below. In short: + +* Segments in a destination name are separated with dots (`.`) +* A `*` represents _one segment_ (i.e. any sequence of non-dot characters) +* A `>` represents _the whole rest of the name_ after a prefix + + +([↑ Back to top](#content)) + +Required Settings +----- + +One way or another, you must set all of the following. + +### Transport Connector(s) + +It's generally best to only enable the transport connectors you need. For example, if you're using Stomp over TLS, don't leave a bare Stomp transport open. If you're not using a network of brokers, close the OpenWire transport. + +The `name` attribute of a transport connector doesn't seem to matter as long as it's locally unique. + +#### Stomp + +ActiveMQ must listen over the network for Stomp connections; otherwise, MCollective can't reach it. Enable this with a `` element inside the `` element. We generally recommend using TLS. + +{% highlight xml %} + + + +{% endhighlight %} + +* Note that the protocol/port/arguments for Stomp URIs can differ: + * Unencrypted: `stomp+nio://0.0.0.0:61613` + * CA-verified TLS: `stomp+ssl://0.0.0.0:61614?needClientAuth=true` + * Anonymous TLS: `stomp+ssl://0.0.0.0:61614` +* You can choose to restrict the interface/hostname to use instead of listening on `0.0.0.0`. + +> **If you are using TLS,** note that you must also: +> +> * [Configure ActiveMQ's TLS credentials](#tls-credentials) (see below) +> * [Configure MCollective to use TLS credentials][mcollective_connector_tls] + +#### OpenWire + +If you are using a network of brokers instead of just one ActiveMQ server, they talk to each other over OpenWire, and will all need a transport connector for that protocol too: + +{% highlight xml %} + +{% endhighlight %} + +* Note that the protocol/port/arguments for OpenWire URIs can differ: + * Unencrypted: `tcp://0.0.0.0:61616` + * CA-verified TLS: `ssl://0.0.0.0:61617?needClientAuth=true` + * Anonymous TLS: `ssl://0.0.0.0:61617` +* You can choose to restrict the interface/hostname to use instead of listening on `0.0.0.0`. + + + +#### Standard Ports for Stomp and OpenWire + +Alas, there aren't any; just a rough consensus. + +* 61613 for unencrypted Stomp +* 61614 for Stomp with TLS +* 61616 for unencrypted OpenWire +* 61617 for OpenWire with TLS + +All of our documentation assumes these ports. + +> #### Shared Configuration +> +> MCollective needs to know the following: +> +> * The port to use for Stomp traffic +> * The hostname or IP address to reach ActiveMQ at +> * Whether to use TLS +> +> In a network of brokers, the other ActiveMQ servers need to know the following: +> +> * The port to use for OpenWire traffic +> * The hostname or IP address to reach peer ActiveMQ servers at +> * Whether to use TLS + + +### Reply Queue Pruning + +MCollective sends replies on uniquely-named, single-use queues with names like `mcollective.reply.`. These have to be deleted after about five minutes, lest they clog up ActiveMQ's available memory. By default, queues live forever, so you have to configure this. + +Use a `` element for `*.reply.>` queues, with `gcInactiveDestinations` set to true and `inactiveTimoutBeforeGC` set to 300000 ms (five minutes). + +{% highlight xml %} + + + + + + + + +{% endhighlight %} + +### Disable Producer Flow Control on Topics + +In the example above, you can also see that `producerFlowControl` is set to false for all topics. This is highly recommended; setting it to true can cause MCollective servers to appear blocked when there's heavy traffic. + + +([↑ Back to top](#content)) + +Recommended Settings +----- + +### TLS Credentials + +If you are using TLS in either your Stomp or OpenWire [transport connectors](#transport-connectors), ActiveMQ needs a keystore file, a truststore file, and a password for each: + +{% highlight xml %} + + + +{% endhighlight %} + +**Note:** This example is for CA-verified TLS. If you are using anonymous TLS, you may optionally skip the truststore attributes. + +The redundant nested `` elements are not a typo; for some reason ActiveMQ actually needs this. + +ActiveMQ will expect to find these files in the same directory as activemq.xml. + +> #### Creating a Keystore and Truststore +> +> There is a [separate guide that covers how to create keystores.][activemq_keystores] + +[activemq_keystores]: ./activemq_keystores.html + + +### Authentication (Users and Groups) + +When they connect, MCollective clients and servers provide a username, password, and optionally an SSL certificate. ActiveMQ can use any of these to authenticate them. + +By default, ActiveMQ ignores all of these and has no particular concept of "users." Enabling authentication means ActiveMQ will only allow users with proper credentials to connect. It also gives you the option of setting up per-destination authorization (see below). + +You set up authentication by adding the appropriate element to the `` element. [The Fuse documentation has a more complete description of ActiveMQ's authentication capabilities;][fuse_security] the [ActiveMQ docs version][activemq_security] is less organized and less complete. In summary: + +- `simpleAuthenticationPlugin` defines users directly in activemq.xml. It's well-tested and easy. It also requires you to edit activemq.xml and restart the broker every time you add a new user. The activemq.xml file will contain sensitive passwords and must be protected. +- `jaasAuthenticationPlugin` lets you use external text files (or even an LDAP database) to define users and groups. You need to make a `login.config` file in the ActiveMQ config directory, and possibly two more files. You can add users and groups without restarting the broker. The external users file will contain sensitive passwords and must be protected. +- `jaasCertificateAuthenticationPlugin` ignores the username and password that MCollective presents; instead, it reads the distinguished name of the certificate and maps that to a username. It requires TLS, a `login.config` file, and two other external files. It is also impractical unless your servers are all using the same SSL certificate to connect to ActiveMQ; the currently recommended approach of re-using Puppet certificates makes this problematic, but you can probably ship credentials around and figure out a way to make it work. This is not currently well-tested with MCollective. + +[fuse_security]: http://fusesource.com/docs/broker/5.5/security/front.html +[activemq_security]: http://activemq.apache.org/security.html + +The example below uses `simpleAuthenticationPlugin`. + +{% highlight xml %} + + + + + + + + + +{% endhighlight %} + +This creates two users, with the expectation that MCollective servers will log in as `mcollective` and admin users issuing commands will log in as `admin`. + +Note that unless you set up authorization (see below), these users have the exact same capabilities. + +> #### Shared Configuration +> +> MCollective servers and clients both need a username and password to use when connecting. That user **must** have appropriate permissions (see "Authorization," directly below) for that server or client's role. + + + +### Authorization (Group Permissions) + +By default, ActiveMQ allows everyone to **read** from any topic or queue, **write** to any topic or queue, and create (**admin**) any topic or queue. + +By setting rules in an `` element, you can regulate things a bit. Some notes: + +* Authorization is done **by group.** +* The exact behavior of authorization doesn't seem to be documented anywhere. Going by observation, it appears that ActiveMQ first tries the most specific rule available, then retreats to less specific rules. This means if a given group isn't allowed an action by a more specific rule but is allowed it by a more general rule, it still gets authorized to take that action. If you have any solid information about how this works, please email us at . +* MCollective creates subscriptions before it knows whether there will be any content coming. That means any role able to **read** from or **write** to a destination must also be able to **admin** that destination. Think of "admin" as a superset of both read and write. + +#### Simple Restrictions + +The following example grants all permissions on destinations beginning with `mcollective` to everyone in group `mcollective`: + +{% highlight xml %} + + + + + + + + + + + + + + + + +{% endhighlight %} + +This means admins can issue commands and MCollective servers can read those commands and reply. However, it also means that servers can issue commands, which you probably don't want. + +Note that the `everyone` group (as seen in the `ActiveMQ.Advisory.>` topics) **isn't special.** You need to manually make sure all users are members of it. ActiveMQ does not appear to have any kind of real wildcard "everyone" group, unfortunately. + +#### Detailed Restrictions + +The following example splits permissions along a simple user/server model: + +{% highlight xml %} + + + + + + + + + + + + + + + + + + + + +{% endhighlight %} + +This means admins can issue commands and MCollective servers can read those commands and reply. This time, though, servers can't issue commands. The exception is the `mcollective.registration.agent` destination, which servers DO need the ability to write to if you've turned on registration. + +Admins, of course, can also read commands and reply, since they have power over the entire `mcollective.>` destination set. This isn't considered much of an additional security risk, considering that admins can already control your entire infrastructure. + +#### Detailed Restrictions with Multiple Subcollectives + +Both of the above examples assume only a single `mcollective` collective. If you are using additional [subcollectives][] (e.g. `uk_collective`, `us_collective`, etc.), their destinations will start with their name instead of `mcollective`. If you need to separately control authorization for each collective, it's best to use a template to do so, so you can avoid repeating yourself. + +{% highlight xml %} + + + + + + + + + + + <%- @collectives.each do |collective| -%> + + + + + + + <%- end -%> + + + + + + + +{% endhighlight %} + +This example divides your users into several groups: + +* `admins` is the "super-admins" group, who can command all servers. +* `servers` is the "super-servers" group, who can receive and respond to commands on any collective they believe themselves to be members of. +* `COLLECTIVE-admins` can only command servers on their specific collective. (Since all servers are probably members of the default `mcollective` collective, the `mcollective-admins` group are sort of the "almost-super-admins.") +* `COLLECTIVE-servers` can only receive and respond to commands on their specific collective. + +Thus, when you define your users in the [authentication setup](#authentication-users-and-groups), you could allow a certain user to command both the EU and UK collectives (but not the US collective) with `groups="eu_collective-admins,uk_collective-admins"`. You would probably want most servers to be "super-servers," since each server already gets to choose which collectives to ignore. + +#### MCollective's Exact Authorization Requirements + +As described above, any user able to read OR write on a destination must also be able to admin that destination. + +Topics: + +- `ActiveMQ.Advisory.>` --- Everyone must be able to read and write. +- `COLLECTIVE.*.agent` --- Admin users must be able to write. Servers must be able to read. +- `COLLECTIVE.registration.agent` --- If you're using registration, servers must be able to read and write. Otherwise, it can be ignored. + +Queues: + +- `COLLECTIVE.nodes` --- Admin users must be able to write. Servers must be able to read. +- `COLLECTIVE.reply.>` --- Servers must be able to write. Admin users must be able to read. + + +> #### Shared Configuration +> +> Subcollectives must also be configured in the MCollective client and server config files. If you're setting up authorization per-subcollective, ActiveMQ must allow traffic on any subcollective that MCollective servers and clients expect to use. + + +([↑ Back to top](#content)) + +Settings for Networks of Brokers +----- + +You can group multiple ActiveMQ servers into networks of brokers, and they can route local MCollective traffic amongst themselves. There are a lot of reasons to do this: + +* Scale --- we recommend a maximum of about 800 MCollective servers per ActiveMQ broker, and multiple brokers let you expand past this. +* High availability --- MCollective servers and clients can attempt to connect to mupltiple brokers in a failover pool. +* Partition resilience --- if an inter-datacenter link goes down, each half's local MCollective system will still work fine. +* Network isolation and traffic limiting --- if your clients default to only sending messages to local machines, you can get better performance in the most common case while still being able to command a global collective when you need to. +* Security --- destination filtering can prevent certain users from sending requests to certain datacenters. + +This is naturally more complicated than configuring a single broker. + +Designing your broker network's topology is beyond the scope of this reference. The [ActiveMQ Clusters guide](/mcollective/reference/integration/activemq_clusters.html) has a brief description of an example network; see [the ActiveMQ docs][NetworksOfBrokers] or [the Fuse docs][fuse_cluster] for more detailed info. For our purposes, we assume you have already decided: + +* Which ActiveMQ brokers can communicate with each other. +* What kinds of traffic should be excluded from other brokers. + +[NetworksOfBrokers]: http://activemq.apache.org/networks-of-brokers.html +[fuse_cluster]: http://fusesource.com/docs/broker/5.5/clustering/index.html + + +### Broker Name + +_Required._ + +The main `` element has a `brokerName` attribute. In single-broker deployments, this can be anything and defaults to `localhost`. In a network of brokers, each broker's name must be globally unique across the deployment; duplicates can cause message loops. + +{% highlight xml %} + +{% endhighlight %} + +### OpenWire Transports + +_Required._ + +All participants in a network of brokers need OpenWire network transports enabled. [See "Transport Connectors" above](#transport-connectors) for details. + +### Network Connectors + +_Required._ + +If you are using a network of brokers, you need to configure which brokers can talk to each other. + +On **one** broker in each linked pair, set up **two** bi-directional network connectors: one for topics, and one for queues. (The only difference between them is the `conduitSubscriptions` attribute, which must be false for the queue connector.) + +This is done with a pair of `` elements inside the `` element. Note that the queues connector excludes topics and vice-versa. + +{% highlight xml %} + + + + + + + + + + + + +{% endhighlight %} + +Notes: + +* If you're using TLS for OpenWire, you'll need to change the URIs to something like `static:(ssl://stomp2.example.com:61617)` --- note the change of both protocol and port. +* You will need to adjust the TTL for your network's conditions. +* A username and password are required. The broker with the `` connects to the other broker as this user. This user should have **full rights** on **all** queues and topics, unless you really know what you're doing. (See [authentication](#authentication-users-and-groups) and [authorization](#authorization-group-permissions) above.) +* The `name` attribute on each connector must be globally unique. Easiest way to do that is to combine the pair of hostnames involved with the word "queues" or "topics." +* Alternately, you can set up two uni-directional connectors on both brokers; see the Fuse or ActiveMQ documentation linked above for more details. + + +### Destination Filtering + +[fuse_filtering]: http://fusesource.com/docs/broker/5.5/clustering/Networks-Filtering.html + +_Optional._ + +Relevant external docs: + +* [Fuse filtering guide][fuse_filtering] + +If you want to prevent certain traffic from leaving a given datacenter, you can do so with `` or `` elements **inside each `` element.** This is mostly useful for noise reduction, by blocking traffic that other datacenters don't care about, but it can also serve security purposes. Generally, you'll be filtering on [subcollectives][], which, as described above, begin their destination names with the name of the collective. + +Both types of filter element can contain `` and `` elements, with their `physicalName` attributes defining a destination name with the normal wildcards. + +**Remember to retain the all-queues/all-topics exclusions as [shown above](#network-connectors).** + +#### Examples + +Assume a star network topology. + +This topology can be achieved by either having each edge broker connect to the central broker, or having the central broker connect to each edge broker. You can achieve the same filtering in both situations, but with slightly different configuration. The two examples below have similar but not identical effects; the ramifications are subtle, and we _really_ recommend reading the external ActiveMQ and Fuse documentation if you've come this far in your deployment scale. + +If your central broker is connecting to the UK broker, and you want it to only pass on traffic for the global `mcollective` collective and the UK-specific `uk_collective` collective: + +{% highlight xml %} + + + + + + +{% endhighlight %} + +In this case, admin users connected to the central broker can command nodes on the `uk_collective`, but admin users connected to the UK broker can't command nodes on the `us_collective`, etc. + +Alternately, if your UK broker is connecting to your central broker and you want it to refrain from passing on UK-specific traffic that no one outside that datacenter cares about: + +{% highlight xml %} + + + + +{% endhighlight %} + +In this case, admin users connected to the central broker **cannot** command nodes on the `uk_collective`; it's expected that they'll be issuing commands to the main `mcollective` collective if they need to (and are authorized to) cross outside their borders. + +([↑ Back to top](#content)) + +Tuning +----- + +The minor adjustments listed below (turn off dedicated task runner, increase heap, and increase memory and temp usage in activemq.xml) will generally let you reach about 800 MCollective nodes connected to a single ActiveMQ server, depending on traffic and usage patterns, number of topics and queues, etc. Any more detailed tuning is beyond the scope of this reference, and is likely to be unnecessary for your deployment. + +### Don't Use Dedicated Task Runner + +Set `-Dorg.apache.activemq.UseDedicatedTaskRunner=false` when starting ActiveMQ. MCollective creates a lot of queues and topics, so _not_ using a thread per destination will save you a lot of memory usage. + +This setting is **not** configured in activemq.xml; it's an extra argument to the JVM, which should be provided when ActiveMQ starts up. The place to put this varies, depending on the package you installed ActiveMQ with; it usually goes in the wrapper config file. Check your init script for clues about this file's location. With the common TanukiWrapper scripts, it would look something like this: + + wrapper.java.additional.4=-Dorg.apache.activemq.UseDedicatedTaskRunner=false + +### Increase JVM Heap if Necessary + +Likewise, the max heap is usually configured in the wrapper config file (`wrapper.java.maxmemory=512`) or on the command line (`-Xmx512m`). + +### Memory and Temp Usage for Messages (`systemUsage`) + +Since ActiveMQ expects to be embedded in another JVM application, it won't automatically fill up the heap with messages; it has extra limitations on how much space to take up with message contents. + +As your deployment gets bigger, you may need to increase the `` and `` elements in the `` element. Unfortunately, we lack a lot of solid data for what to actually set these to. Most users leave the defaults for memory and temp until they have problems, then double the defaults and see whether their problems go away. This isn't perfectly effecient, but anecdotally it appears to work. + +The many redundant nested elements are not a typo; for some reason, ActiveMQ seems to require this. + +{% highlight xml %} + + + + + + + + + + + + + + +{% endhighlight %} + + +([↑ Back to top](#content)) + +Boilerplate +----- + +There's little reason to care about these settings in most conditions, but they're in the example config files anyway. + +### Persistence + +MCollective rarely uses this. It's only necessary in networks of brokers, where it is used to prevent routing loops. Leave it enabled; it has no notable performance penalty and its disk usage is limited by the `` element described above. + +{% highlight xml %} + + + +{% endhighlight %} + +### Management Context + +This is for monitoring. MCollective doesn't use this and the examples have it turned off, but you may want it for your own purposes. + +{% highlight xml %} + + + + + +{% endhighlight %} + +### Statistics Broker + +MCollective doesn't use this. + +{% highlight xml %} + + + + + +{% endhighlight %} + + +### Jetty (Web Consoles, APIs, etc.) + +The activemq.xml file will often either contain Jetty settings or import them from another file. MCollective doesn't use this. If you're not using it to manage ActiveMQ, leaving it enabled may be a security risk. Note that this configuration is **outside** the `` element. + +{% highlight xml %} + + +{% endhighlight %} + +([↑ Back to top](#content)) 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. diff --git a/website/index.md b/website/index.md index 5b83ee9..a5c747d 100644 --- a/website/index.md +++ b/website/index.md @@ -36,6 +36,7 @@ toc: false [ActiveMQ]: /mcollective/reference/integration/activemq_security.html [MessageFormat]: /mcollective/reference/basic/messageformat.html [ChangeLog]: /mcollective/changelog.html +[server_config]: /mcollective/configure/server.html The Marionette Collective AKA mcollective is a framework to build server orchestration or parallel job execution systems. @@ -93,7 +94,7 @@ MCollective is licensed under the Apache 2 license. ### Introductory and Tutorial Pages * See it in action in our [Screencasts] - * Read the [GettingStarted] and [Configuration] guides for installation instructions + * Read the [GettingStarted], [Server Configuration Reference][server_config], and [Configuration] guides for installation instructions * Read the [Terminology] page if you see any words where the meaning in the context of MCollective is not clear * Read the [ChangeLog] page to see how MCollective has developed * Learn how to write basic reports for your servers - [NodeReports] diff --git a/website/messages/PLMC1.md b/website/messages/PLMC1.md index 4fbd245..92bf9a6 100644 --- a/website/messages/PLMC1.md +++ b/website/messages/PLMC1.md @@ -4,9 +4,6 @@ title: Message detail for PLMC1 toc: false --- -Detail for Marionette Collective message PLMC1 -=========================================== - Example Message --------------- diff --git a/website/messages/PLMC10.md b/website/messages/PLMC10.md index cd818dc..a0fd7b5 100644 --- a/website/messages/PLMC10.md +++ b/website/messages/PLMC10.md @@ -4,9 +4,6 @@ title: Message detail for PLMC10 toc: false --- -Detail for Marionette Collective message PLMC10 -=========================================== - Example Message --------------- diff --git a/website/messages/PLMC11.md b/website/messages/PLMC11.md index 8ff9a60..e07cd16 100644 --- a/website/messages/PLMC11.md +++ b/website/messages/PLMC11.md @@ -4,9 +4,6 @@ title: Message detail for PLMC11 toc: false --- -Detail for Marionette Collective message PLMC11 -=========================================== - Example Message --------------- diff --git a/website/messages/PLMC12.md b/website/messages/PLMC12.md index be7cb5a..c995c7f 100644 --- a/website/messages/PLMC12.md +++ b/website/messages/PLMC12.md @@ -4,9 +4,6 @@ title: Message detail for PLMC12 toc: false --- -Detail for Marionette Collective message PLMC12 -=========================================== - Example Message --------------- diff --git a/website/messages/PLMC13.md b/website/messages/PLMC13.md index 550c8c5..5efd236 100644 --- a/website/messages/PLMC13.md +++ b/website/messages/PLMC13.md @@ -4,9 +4,6 @@ title: Message detail for PLMC13 toc: false --- -Detail for Marionette Collective message PLMC13 -=========================================== - Example Message --------------- diff --git a/website/messages/PLMC14.md b/website/messages/PLMC14.md index 149ec8f..8287488 100644 --- a/website/messages/PLMC14.md +++ b/website/messages/PLMC14.md @@ -4,9 +4,6 @@ title: Message detail for PLMC14 toc: false --- -Detail for Marionette Collective message PLMC14 -=========================================== - Example Message --------------- diff --git a/website/messages/PLMC15.md b/website/messages/PLMC15.md index c269575..74afc2d 100644 --- a/website/messages/PLMC15.md +++ b/website/messages/PLMC15.md @@ -4,9 +4,6 @@ title: Message detail for PLMC15 toc: false --- -Detail for Marionette Collective message PLMC15 -=========================================== - Example Message --------------- diff --git a/website/messages/PLMC16.md b/website/messages/PLMC16.md index 56efeca..b169953 100644 --- a/website/messages/PLMC16.md +++ b/website/messages/PLMC16.md @@ -4,9 +4,6 @@ title: Message detail for PLMC16 toc: false --- -Detail for Marionette Collective message PLMC16 -=========================================== - Example Message --------------- diff --git a/website/messages/PLMC17.md b/website/messages/PLMC17.md index f4d938d..bf3eded 100644 --- a/website/messages/PLMC17.md +++ b/website/messages/PLMC17.md @@ -4,9 +4,6 @@ title: Message detail for PLMC17 toc: false --- -Detail for Marionette Collective message PLMC17 -=========================================== - Example Message --------------- diff --git a/website/messages/PLMC18.md b/website/messages/PLMC18.md index d463e4d..f715267 100644 --- a/website/messages/PLMC18.md +++ b/website/messages/PLMC18.md @@ -4,9 +4,6 @@ title: Message detail for PLMC18 toc: false --- -Detail for Marionette Collective message PLMC18 -=========================================== - Example Message --------------- diff --git a/website/messages/PLMC19.md b/website/messages/PLMC19.md index bbcf887..f449db5 100644 --- a/website/messages/PLMC19.md +++ b/website/messages/PLMC19.md @@ -4,9 +4,6 @@ title: Message detail for PLMC19 toc: false --- -Detail for Marionette Collective message PLMC19 -=========================================== - Example Message --------------- diff --git a/website/messages/PLMC2.md b/website/messages/PLMC2.md index 675ae91..39fb476 100644 --- a/website/messages/PLMC2.md +++ b/website/messages/PLMC2.md @@ -4,9 +4,6 @@ title: Message detail for PLMC2 toc: false --- -Detail for Marionette Collective message PLMC2 -=========================================== - Example Message --------------- diff --git a/website/messages/PLMC20.md b/website/messages/PLMC20.md index 2377376..d9e0191 100644 --- a/website/messages/PLMC20.md +++ b/website/messages/PLMC20.md @@ -4,9 +4,6 @@ title: Message detail for PLMC20 toc: false --- -Detail for Marionette Collective message PLMC20 -=========================================== - Example Message --------------- diff --git a/website/messages/PLMC21.md b/website/messages/PLMC21.md index 5531687..242e7f0 100644 --- a/website/messages/PLMC21.md +++ b/website/messages/PLMC21.md @@ -4,9 +4,6 @@ title: Message detail for PLMC21 toc: false --- -Detail for Marionette Collective message PLMC21 -=========================================== - Example Message --------------- diff --git a/website/messages/PLMC22.md b/website/messages/PLMC22.md index d786a52..7d7dc62 100644 --- a/website/messages/PLMC22.md +++ b/website/messages/PLMC22.md @@ -4,9 +4,6 @@ title: Message detail for PLMC22 toc: false --- -Detail for Marionette Collective message PLMC22 -=========================================== - Example Message --------------- diff --git a/website/messages/PLMC23.md b/website/messages/PLMC23.md index 0085f0e..b782478 100644 --- a/website/messages/PLMC23.md +++ b/website/messages/PLMC23.md @@ -4,9 +4,6 @@ title: Message detail for PLMC23 toc: false --- -Detail for Marionette Collective message PLMC23 -=========================================== - Example Message --------------- diff --git a/website/messages/PLMC24.md b/website/messages/PLMC24.md index 0bfb434..423d4e9 100644 --- a/website/messages/PLMC24.md +++ b/website/messages/PLMC24.md @@ -4,9 +4,6 @@ title: Message detail for PLMC24 toc: false --- -Detail for Marionette Collective message PLMC24 -=========================================== - Example Message --------------- diff --git a/website/messages/PLMC25.md b/website/messages/PLMC25.md index 7c178af..14fb321 100644 --- a/website/messages/PLMC25.md +++ b/website/messages/PLMC25.md @@ -4,9 +4,6 @@ title: Message detail for PLMC25 toc: false --- -Detail for Marionette Collective message PLMC25 -=========================================== - Example Message --------------- diff --git a/website/messages/PLMC26.md b/website/messages/PLMC26.md index d91ed42..15f8335 100644 --- a/website/messages/PLMC26.md +++ b/website/messages/PLMC26.md @@ -4,9 +4,6 @@ title: Message detail for PLMC26 toc: false --- -Detail for Marionette Collective message PLMC26 -=========================================== - Example Message --------------- diff --git a/website/messages/PLMC27.md b/website/messages/PLMC27.md index d5c2225..77f955f 100644 --- a/website/messages/PLMC27.md +++ b/website/messages/PLMC27.md @@ -4,9 +4,6 @@ title: Message detail for PLMC27 toc: false --- -Detail for Marionette Collective message PLMC27 -=========================================== - Example Message --------------- diff --git a/website/messages/PLMC28.md b/website/messages/PLMC28.md index 49a317d..160bbe6 100644 --- a/website/messages/PLMC28.md +++ b/website/messages/PLMC28.md @@ -4,9 +4,6 @@ title: Message detail for PLMC28 toc: false --- -Detail for Marionette Collective message PLMC28 -=========================================== - Example Message --------------- diff --git a/website/messages/PLMC29.md b/website/messages/PLMC29.md index dda52e6..17abe89 100644 --- a/website/messages/PLMC29.md +++ b/website/messages/PLMC29.md @@ -4,9 +4,6 @@ title: Message detail for PLMC29 toc: false --- -Detail for Marionette Collective message PLMC29 -=========================================== - Example Message --------------- diff --git a/website/messages/PLMC3.md b/website/messages/PLMC3.md index 9136795..8e1c90a 100644 --- a/website/messages/PLMC3.md +++ b/website/messages/PLMC3.md @@ -4,9 +4,6 @@ title: Message detail for PLMC3 toc: false --- -Detail for Marionette Collective message PLMC3 -=========================================== - Example Message --------------- diff --git a/website/messages/PLMC30.md b/website/messages/PLMC30.md index cc9dfc4..95a947f 100644 --- a/website/messages/PLMC30.md +++ b/website/messages/PLMC30.md @@ -4,9 +4,6 @@ title: Message detail for PLMC30 toc: false --- -Detail for Marionette Collective message PLMC30 -=========================================== - Example Message --------------- diff --git a/website/messages/PLMC31.md b/website/messages/PLMC31.md index 97846cd..9ac14bd 100644 --- a/website/messages/PLMC31.md +++ b/website/messages/PLMC31.md @@ -4,9 +4,6 @@ title: Message detail for PLMC31 toc: false --- -Detail for Marionette Collective message PLMC31 -=========================================== - Example Message --------------- diff --git a/website/messages/PLMC32.md b/website/messages/PLMC32.md index e79f614..c432da9 100644 --- a/website/messages/PLMC32.md +++ b/website/messages/PLMC32.md @@ -4,9 +4,6 @@ title: Message detail for PLMC32 toc: false --- -Detail for Marionette Collective message PLMC32 -=========================================== - Example Message --------------- diff --git a/website/messages/PLMC33.md b/website/messages/PLMC33.md index f56c04c..2bf994d 100644 --- a/website/messages/PLMC33.md +++ b/website/messages/PLMC33.md @@ -4,9 +4,6 @@ title: Message detail for PLMC33 toc: false --- -Detail for Marionette Collective message PLMC33 -=========================================== - Example Message --------------- diff --git a/website/messages/PLMC34.md b/website/messages/PLMC34.md index 71bac1a..a14ffbe 100644 --- a/website/messages/PLMC34.md +++ b/website/messages/PLMC34.md @@ -4,9 +4,6 @@ title: Message detail for PLMC34 toc: false --- -Detail for Marionette Collective message PLMC34 -=========================================== - Example Message --------------- diff --git a/website/messages/PLMC35.md b/website/messages/PLMC35.md index 2340786..083d478 100644 --- a/website/messages/PLMC35.md +++ b/website/messages/PLMC35.md @@ -4,9 +4,6 @@ title: Message detail for PLMC35 toc: false --- -Detail for Marionette Collective message PLMC35 -=========================================== - Example Message --------------- diff --git a/website/messages/PLMC36.md b/website/messages/PLMC36.md index 494b2a5..ebfa38b 100644 --- a/website/messages/PLMC36.md +++ b/website/messages/PLMC36.md @@ -4,9 +4,6 @@ title: Message detail for PLMC36 toc: false --- -Detail for Marionette Collective message PLMC36 -=========================================== - Example Message --------------- diff --git a/website/messages/PLMC37.md b/website/messages/PLMC37.md index 638430b..a047b50 100644 --- a/website/messages/PLMC37.md +++ b/website/messages/PLMC37.md @@ -4,9 +4,6 @@ title: Message detail for PLMC37 toc: false --- -Detail for Marionette Collective message PLMC37 -=========================================== - Example Message --------------- diff --git a/website/messages/PLMC38.md b/website/messages/PLMC38.md index 0f6800a..1c98475 100644 --- a/website/messages/PLMC38.md +++ b/website/messages/PLMC38.md @@ -4,9 +4,6 @@ title: Message detail for PLMC38 toc: false --- -Detail for Marionette Collective message PLMC38 -=========================================== - Example Message --------------- diff --git a/website/messages/PLMC39.md b/website/messages/PLMC39.md index a34cbc8..728abf9 100644 --- a/website/messages/PLMC39.md +++ b/website/messages/PLMC39.md @@ -4,9 +4,6 @@ title: Message detail for PLMC39 toc: false --- -Detail for Marionette Collective message PLMC39 -=========================================== - Example Message --------------- diff --git a/website/messages/PLMC4.md b/website/messages/PLMC4.md index 3323b86..57e586c 100644 --- a/website/messages/PLMC4.md +++ b/website/messages/PLMC4.md @@ -4,9 +4,6 @@ title: Message detail for PLMC4 toc: false --- -Detail for Marionette Collective message PLMC4 -=========================================== - Example Message --------------- diff --git a/website/messages/PLMC5.md b/website/messages/PLMC5.md index 9fafa06..38f22fe 100644 --- a/website/messages/PLMC5.md +++ b/website/messages/PLMC5.md @@ -4,9 +4,6 @@ title: Message detail for PLMC5 toc: false --- -Detail for Marionette Collective message PLMC5 -=========================================== - Example Message --------------- diff --git a/website/messages/PLMC6.md b/website/messages/PLMC6.md index 8b4bf59..42e7e98 100644 --- a/website/messages/PLMC6.md +++ b/website/messages/PLMC6.md @@ -4,9 +4,6 @@ title: Message detail for PLMC6 toc: false --- -Detail for Marionette Collective message PLMC6 -=========================================== - Example Message --------------- diff --git a/website/messages/PLMC7.md b/website/messages/PLMC7.md index b695613..1a5a064 100644 --- a/website/messages/PLMC7.md +++ b/website/messages/PLMC7.md @@ -4,9 +4,6 @@ title: Message detail for PLMC7 toc: false --- -Detail for Marionette Collective message PLMC7 -=========================================== - Example Message --------------- diff --git a/website/messages/PLMC8.md b/website/messages/PLMC8.md index 244b470..53546a5 100644 --- a/website/messages/PLMC8.md +++ b/website/messages/PLMC8.md @@ -4,9 +4,6 @@ title: Message detail for PLMC8 toc: false --- -Detail for Marionette Collective message PLMC8 -=========================================== - Example Message --------------- diff --git a/website/messages/PLMC9.md b/website/messages/PLMC9.md index f0183b8..fe8818b 100644 --- a/website/messages/PLMC9.md +++ b/website/messages/PLMC9.md @@ -4,9 +4,6 @@ title: Message detail for PLMC9 toc: false --- -Detail for Marionette Collective message PLMC9 -=========================================== - Example Message --------------- diff --git a/website/reference/basic/configuration.md b/website/reference/basic/configuration.md index 7d79b1a..54a9a9b 100644 --- a/website/reference/basic/configuration.md +++ b/website/reference/basic/configuration.md @@ -9,6 +9,9 @@ title: Configuration Guide [Auditing]: /mcollective/simplerpc/auditing.html [Authorization]: /mcollective/simplerpc/authorization.html [Subcollectives]: /mcollective/reference/basic/subcollectives.html +[server_config]: /mcollective/configure/server.html + +> **Note:** There is a new [Server Configuration Reference][server_config] page with a more complete overview of MCollective's server daemon settings. A similar client configuration page is forthcoming. This guide tells you about the major configuration options in the daemon and client config files. There are options not mentioned here typically ones specific to a certain plugin. @@ -22,9 +25,6 @@ Configuration is a simple *key = val* style configuration file. |Key|Sample|Description| |---|------|-----------| -|topicprefix|/topic/|Prefix that gets used for all messages.| -|queueprefix|/queue/|Prefix that gets used for all queued messages.| -|topicsep|.|The seperator to use between parts of the topic path| |collectives|mcollective,subcollective|A list of [Subcollectives] to join - 1.1.3 and newer only| |main_collective|mcollective|The main collective to target - 1.1.3 and newer only| |logfile|/var/log/mcollective.log|Where to log| @@ -33,7 +33,7 @@ Configuration is a simple *key = val* style configuration file. |keeplogs|5|The amount of logs to keep| |max_log_size|2097152|Max size in bytes for log files before rotation happens| |libdir|/usr/libexec/mcollective:/site/mcollective|Where to look for plugins| -|connector|Stomp|Which _connector_ plugin to use for communication| +|connector|activemq|Which _connector_ plugin to use for communication| |securityprovider|Psk|Which security model to use, see [SSL Security Plugin][SSLSecurity] and [AES Security Plugin][AESSecurity] for details on others| |rpchelptemplate|/etc/mcollective/rpc-help.erb|The path to the erb template used for generating help| |helptemplatedir|/etc/mcollective|The path that contains all the erb templates for generating help| @@ -63,7 +63,6 @@ The server configuration file should be root only readable |rpcauthprovider|action_policy|Use the _MCollective::Util::ActionPolicy_ plugin to manage authorization| |rpclimitmethod|The method used for --limit-results. Can be either _first_ or _random_| |fact_cache_time|300|How long to cache fact results for before refreshing from source| -|plugin.discovery.timeout|10|Sets the timeout for the discovery agent, useful if facts are very slow| The last example sets a option for the _discovery_ plugin, you can also set this in _/etc/mcollective/plugin.d/discovery.cfg_, in that case you'd just set _timeout=10_ in the file. @@ -88,10 +87,6 @@ Common plugin options are: |Key|Sample|Description| |---|------|-----------| -|plugin.stomp.host|stomp.your.com|Host to connect too| -|plugin.stomp.port|6163|Port to connecto too| -|plugin.stomp.user|mcollective|User to connect as| -|plugin.stomp.password|password|Password to use| |plugin.yaml|/etc/mcollective/facts.yaml:/other/facts.yaml|Where the yaml fact source finds facts from, multiples get merged| |plugin.psk|123456789|The pre-shared key to use for the Psk security provider| |plugin.psk.callertype|group|What to base the callerid on for the PSK plugin, uid, gid, user, group or identity| @@ -106,7 +101,6 @@ You can set various Environment variables per user to supply these values: {% highlight bash %} export STOMP_USER=user export STOMP_PASSWORD=password -export STOMP_SERVER=stomp.your.com export MCOLLECTIVE_PSK=123456789 {% endhighlight %} diff --git a/website/reference/basic/gettingstarted.md b/website/reference/basic/gettingstarted.md index 6a36e6c..bd1755d 100644 --- a/website/reference/basic/gettingstarted.md +++ b/website/reference/basic/gettingstarted.md @@ -4,6 +4,7 @@ title: Getting Started --- [Screencasts]: /mcollective/screencasts.html [ActiveMQ]: http://activemq.apache.org/ +[RabbitMQ]: http://www.rabbitmq.com/ [EC2Demo]: /mcollective/ec2demo.html [Stomp]: http://stomp.codehaus.org/Ruby+Client [DepRPMs]: http://www.marionette-collective.org/activemq/ @@ -17,24 +18,24 @@ title: Getting Started [ControllingTheDaemon]: /mcollective/reference/basic/daemon.html [SSLSecurityPlugin]: /mcollective/reference/plugins/security_ssl.html [AESSecurityPlugin]: /mcollective/reference/plugins/security_aes.html -[ConnectorStomp]: /mcollective/reference/plugins/connector_stomp.html +[ConnectorActiveMQ]: /mcollective/reference/plugins/connector_activemq.html +[ConnectorRabbitMQ]: /mcollective/reference/plugins/connector_rabbitmq.html [MessageFlowCast]: /mcollective/screencasts.html#message_flow [Plugins]: http://projects.puppetlabs.com/projects/mcollective-plugins/wiki [RedHatGuide]: gettingstarted_redhat.html [DebianGuide]: gettingstarted_debian.html +[server_config]: /mcollective/configure/server.html -*NOTE:* We are currently improving the Getting Started documentation. Red Hat and CentOS users can refer to [our Redhat guide][RedHatGuide]. Debian users can refer to [our Debian guide][DebianGuide]. +*NOTE:* This is an older, deprecated version of the Getting Started documentation. Red Hat and CentOS users can refer to [our Redhat guide][RedHatGuide]. Debian users can refer to [our Debian guide][DebianGuide]. Users on less common platforms should adapt one of those two instead of continuing to read this page. Below find a rough guide to get you going, this assumes the client and server is on the same node, but servers don't need the client code installed. -For an even quicker intro to how it all works you can try our [EC2 based demo][EC2Demo] - Look at the [Screencasts] page, there are [some screencasts dealing with basic architecture, terminology and so forth][MessageFlowCast] that you might find helpful before getting started. ## Requirements We try to keep the requirements on external Gems to a minimum, you only need: - * A Stomp server, tested against [ActiveMQ] + * A Stomp server, tested against [ActiveMQ] and [RabbitMQ] * Ruby * Rubygems * [Ruby Stomp Client][Stomp] @@ -42,9 +43,9 @@ We try to keep the requirements on external Gems to a minimum, you only need: RPMs for these are available [here][DepRPMs]. ## ActiveMQ -I've developed this against ActiveMQ. It should work against other Stomp servers but I suspect if you choose -one without username and password support you might have problems, please let me know if that's the case -and I'll refactor the code around that. +ActiveMQ is currently the most used middleware for MCollective, it would be our recommended choice and one +that the community has most experience supporting. There is a specific connector for RabbitMQ if you wish +to go that route though - see [ConnectorRabbitMQ] for details. This guide will focus on ActiveMQ. Full details on setting up and configuring ActiveMQ is out of scope for this, but you can follow these simple setup instructions for initial testing (make sure JDK is installed, see below for Debian specific issue regarding JDK): @@ -129,8 +130,8 @@ And then you should add a user or two, to keep it simple we'll just add one user - - + + @@ -143,7 +144,7 @@ Save the above code as activemq.xml and run activemq as - if installing from a p Else your package would have a RC script: {% highlight console %} - # /etc/init.d/activemq start +# /etc/init.d/activemq start {% endhighlight %} For further info about ActiveMQ settings you might need see [SecurityWithActiveMQ] and [ActiveMQClustering]. @@ -161,7 +162,7 @@ locations. If you use the tarball you'll need to double check all the paths in You'll need to tweak some configs in */etc/mcollective/client.cfg*, a full reference of config settings can be found [here][ConfigurationReference]: -Mostly what you'll need to change is the *identity*, *plugin.stomp.`*`* and the *plugin.psk*: +Mostly what you'll need to change is the *identity*, *plugin.activemq.1.`*`* and the *plugin.psk*: {% highlight ini %} # main config @@ -171,18 +172,19 @@ Mostly what you'll need to change is the *identity*, *plugin.stomp.`*`* and the identity = fqdn # connector plugin config - connector = stomp - plugin.stomp.host = stomp.your.net - plugin.stomp.port = 6163 - plugin.stomp.user = unset - plugin.stomp.password = unset + connector = activemq + plugin.activemq.pool.size = 1 + plugin.activemq.pool.1.host = stomp.your.net + plugin.activemq.pool.1.port = 61613 + plugin.activemq.pool.1.user = unset + plugin.activemq.pool.1.password = unset # security plugin config securityprovider = psk plugin.psk = abcdefghj {% endhighlight %} -You should also create _/etc/mcollective/server.cfg_ here's a sample, , a full reference of config settings can be found here [ConfigurationReference]: +You should also create _/etc/mcollective/server.cfg_ here's a sample, a full reference of config settings can be found on the [Server Configuration Reference][server_config]: {% highlight ini %} # main config @@ -196,11 +198,12 @@ You should also create _/etc/mcollective/server.cfg_ here's a sample, , a full r registerinterval = 300 # connector plugin config - connector = stomp - plugin.stomp.host = stomp.your.net - plugin.stomp.port = 6163 - plugin.stomp.user = mcollective - plugin.stomp.password = password + connector = activemq + plugin.activemq.pool.size = 1 + plugin.activemq.pool.1.host = stomp.your.net + plugin.activemq.pool.1.port = 61613 + plugin.activemq.pool.1.user = mcollective + plugin.activemq.pool.1.password = password # facts factsource = yaml @@ -211,12 +214,12 @@ You should also create _/etc/mcollective/server.cfg_ here's a sample, , a full r plugin.psk = abcdefghj {% endhighlight %} -Replace the *plugin.stomp.host* with your server running ActiveMQ and replace the *plugin.psk* with a Pre-Shared Key of your own. +Replace the *plugin.activemq.pool.1.host* with your server running ActiveMQ and replace the *plugin.psk* with a Pre-Shared Key of your own. -The STOMP connector supports other options like failover pools, see [ConnectorStomp] for full details. +The ActiveMQ connector supports other options like failover pools, see [ConnectorActiveMQ] for full details. ### Create Facts -By default - and for this setup - we'll use a simple YAML file for a fact source, later on you can use Reductive Labs Facter or something else. +By default - and for this setup - we'll use a simple YAML file for a fact source, later on you can use Puppet Labs Facter or something else. Create */etc/mcollective/facts.yaml* along these lines: @@ -252,7 +255,7 @@ your.domain.com This searches all systems currently active for ones with a fact *country=uk*, it got the data from the yaml file you made earlier. -If you use confiuration management tools like puppet and the nodes are setup with classes with *classes.txt* in */var/lib/puppet* then you +If you use configuration management tools like puppet and the nodes are setup with classes with *classes.txt* in */var/lib/puppet* then you can search for nodes with a specific class on them - the locations will configurable soon: {% highlight console %} @@ -280,4 +283,3 @@ From here you should look at the rest of the wiki pages some key pages are: * [ControllingTheDaemon] - Controlling a running daemon * [AESSecurityPlugin] - Using AES+RSA for secure message encryption and authentication of clients * [SSLSecurityPlugin] - Using SSL for secure message signing and authentication of clients - * [ConnectorStomp] - Full details on the Stomp adapter including failover pools diff --git a/website/reference/basic/gettingstarted_debian.md b/website/reference/basic/gettingstarted_debian.md index ecab625..3539663 100644 --- a/website/reference/basic/gettingstarted_debian.md +++ b/website/reference/basic/gettingstarted_debian.md @@ -19,16 +19,16 @@ title: Getting Started [ControllingTheDaemon]: /mcollective/reference/basic/daemon.html [SSLSecurityPlugin]: /mcollective/reference/plugins/security_ssl.html [AESSecurityPlugin]: /mcollective/reference/plugins/security_aes.html -[ConnectorStomp]: /mcollective/reference/plugins/connector_stomp.html +[ConnectorActiveMQ]: /mcollective/reference/plugins/connector_activemq.html +[ConnectorRabbitMQ]: /mcollective/reference/plugins/connector_rabbitmq.html [MessageFlowCast]: /mcollective/screencasts.html#message_flow [Plugins]: http://projects.puppetlabs.com/projects/mcollective-plugins/wiki [MCDownloads]: http://www.puppetlabs.com/downloads/mcollective/ [RubyGems]: http://packages.debian.org/search?suite=default§ion=all&arch=any&searchon=names&keywords=rubygems +[server_config]: /mcollective/configure/server.html Getting started using Debian based distribution like Debian squeeze and Ubuntu is easy as DEBs are available for most the required components. This guide walks you through the process. -If you just want to experiment with the system please try our [EC2 based demo][EC2Demo]. You should be familiar with the architecture and terminology of Marionette Collective, please review the [basic architecture, terminology and message flow][MessageFlowCast] screencast first. - ## Requirements We try to keep the requirements on external Gems to a minimum, you only need: @@ -46,15 +46,16 @@ We strongly recommend you set up a local Apt repository that will host all the p * Ruby - included with your distribution * [RubyGems] * Stomp Ruby Gem - * [MCollective][MCDownloads] - mcollective-1.x.x-1_all.deb, mcollective-common-1.x.x-1_all.deb, mcollective-client-1.x.x-1_all.deb + * [MCollective][MCDownloads] - mcollective-2.2.x-1_all.deb, mcollective-common-2.2.x-1_all.deb, mcollective-client-2.2.x-1_all.deb The rest of this guide will assume you set up a Apt repository. Puppet Labs hosts a Apt repository with all these dependencies at _apt.puppetlabs.com_. ## ActiveMQ + ActiveMQ is currently the most used and tested middleware for use with MCollective. You need at least one ActiveMQ server on your network, all the nodes you wish to manage will connect to the central ActiveMQ server. -Later on your can [cluster the ActiveMQ servers for availability and scale][ActiveMQClustering]. +Later on you can [cluster the ActiveMQ servers for availability and scale][ActiveMQClustering]. ### Install @@ -68,82 +69,17 @@ ActiveMQ installation instructions can be found [here][ActiveMQ Getting Started] ### Configuring -Initially you'll just keep it simple with a single ActiveMQ broker and a basic user setup, further security information for ActiveMQ -can be found [here][SecurityWithActiveMQ] - -Place the following in your ActiveMQ configuration path as *activemq.xml*. You can download this file from [GitHub][ActiveMQSingleBrokerSample] - -Other examples are also available from [GitHub][ActiveMQSamples] - -{% highlight xml %} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -{% endhighlight %} +[The ActiveMQ config reference][activemq_config] describes all of the ActiveMQ settings that MCollective cares about. For best use, skim the sections you care about while comparing it to an example activemq.xml file. + +[activemq_config]: /mcollective/deploy/middleware/activemq.html -This creates a user *mcollective* with the password *marionette* and give it access to read/write/admin */topic/mcollective.`*`*. You should change this passsword. +We recommend that new users: + +* Start with the [single-broker example config][ActiveMQSingleBrokerSample]. +* Change the [user account passwords](/mcollective/deploy/middleware/activemq.html#authentication-users-and-groups). +* [Set up TLS](/mcollective/deploy/middleware/activemq.html#tls-credentials) and [use a TLS Stomp transport connector](/mcollective/deploy/middleware/activemq.html#transport-connectors). + +Other example config files are also available from [GitHub][ActiveMQSamples]. ### Starting @@ -156,13 +92,13 @@ Start the ActiveMQ service: You should see it running in the process list: {% highlight console %} - # ps -auxw|grep java + # ps auxw|grep java activemq 3012 0.1 14.5 1155112 152180 ? Sl Dec28 2:02 java -Dactivemq.home=/usr/share/activemq -Dactivemq.base=/usr/share/activemq -Dcom.sun.management.jmxremote -Dorg.apache.activemq.UseDedicatedTaskRunner=true -Xmx512m -Djava.library.path=/usr/lib:/usr/lib64 -classpath /usr/share/java/tanukiwrapper.jar:/usr/share/activemq/bin/run.jar -Dwrapper.key=eg4_VvENzCmvtAKg -Dwrapper.port=32000 -Dwrapper.jvm.port.min=31000 -Dwrapper.jvm.port.max=31999 -Dwrapper.pid=3000 -Dwrapper.version=3.2.3 -Dwrapper.native_library=wrapper -Dwrapper.service=TRUE -Dwrapper.cpu.timeout=10 -Dwrapper.jvmid=1 org.tanukisoftware.wrapper.WrapperSimpleApp org.apache.activemq.console.Main start {% endhighlight %} -You should also see it listening on port 61613 in your network stack +You should also see it listening on port 61613 or 61614 in your network stack, depending on whether you turned on TLS. -You should open port 61613 for all your nodes to connect to. +You should open port 61613 or 61614 for all your nodes to connect to. ## Marionette Collective @@ -185,7 +121,7 @@ A machine can be both at once, in which case you need to install all 3 packages. You'll need to tweak some configs in */etc/mcollective/client.cfg*, a full reference of config settings can be found [here][ConfigurationReference]: -We're assuming you called the machine running ActiveMQ *stomp.example.net* please change as appropriate +We're assuming you called the machine running ActiveMQ *stomp.example.net*; please change as appropriate. Also note that the port should be 61614 if you turned on TLS. {% highlight ini %} # main config @@ -194,18 +130,19 @@ We're assuming you called the machine running ActiveMQ *stomp.example.net* pleas loglevel = error # connector plugin config - connector = stomp - plugin.stomp.host = stomp.example.net - plugin.stomp.port = 61613 - plugin.stomp.user = mcollective - plugin.stomp.password = marionette + connector = activemq + plugin.activemq.pool.size = 1 + plugin.activemq.pool.1.host = stomp.example.net + plugin.activemq.pool.1.port = 61613 + plugin.activemq.pool.1.user = mcollective + plugin.activemq.pool.1.password = marionette # security plugin config securityprovider = psk plugin.psk = abcdefghj {% endhighlight %} -You should also create _/etc/mcollective/server.cfg_ here's a sample, , a full reference of config settings can be found here [ConfigurationReference]: +You should also create _/etc/mcollective/server.cfg_ here's a sample, a full reference of config settings can be found on the [Server Configuration Reference][server_config]: {% highlight ini %} # main config @@ -215,11 +152,13 @@ You should also create _/etc/mcollective/server.cfg_ here's a sample, , a full r loglevel = info # connector plugin config - connector = stomp - plugin.stomp.host = stomp.example.net - plugin.stomp.port = 61613 - plugin.stomp.user = mcollective - plugin.stomp.password = marionette + connector = activemq + plugin.activemq.pool.size = 1 + plugin.activemq.pool.1.host = stomp.example.net + plugin.activemq.pool.1.port = 61613 + plugin.activemq.pool.1.user = mcollective + plugin.activemq.pool.1.password = marionette + # facts factsource = yaml @@ -309,4 +248,3 @@ From here you should look at the rest of the wiki pages some key pages are: * [ControllingTheDaemon] - Controlling a running daemon * [AESSecurityPlugin] - Using AES+RSA for secure message encryption and authentication of clients * [SSLSecurityPlugin] - Using SSL for secure message signing and authentication of clients - * [ConnectorStomp] - Full details on the Stomp adapter including failover pools diff --git a/website/reference/basic/gettingstarted_redhat.md b/website/reference/basic/gettingstarted_redhat.md index 852e4be..59ff23c 100644 --- a/website/reference/basic/gettingstarted_redhat.md +++ b/website/reference/basic/gettingstarted_redhat.md @@ -18,16 +18,16 @@ title: Getting Started [ControllingTheDaemon]: /mcollective/reference/basic/daemon.html [SSLSecurityPlugin]: /mcollective/reference/plugins/security_ssl.html [AESSecurityPlugin]: /mcollective/reference/plugins/security_aes.html -[ConnectorStomp]: /mcollective/reference/plugins/connector_stomp.html +[ConnectorActiveMQ]: /mcollective/reference/plugins/connector_activemq.html +[ConnectorRabbitMQ]: /mcollective/reference/plugins/connector_rabbitmq.html [MessageFlowCast]: /mcollective/screencasts.html#message_flow [Plugins]: http://projects.puppetlabs.com/projects/mcollective-plugins/wiki [MCDownloads]: http://www.puppetlabs.com/downloads/mcollective/ [EPEL]: http://fedoraproject.org/wiki/EPEL +[server_config]: /mcollective/configure/server.html Getting started using Red Hat based distribution like Red Hat Enterprise Linux and CentOS is easy as RPMs are available for all the required components. This guide walks you through the process. -If you just want to experiment with the system please try our [EC2 based demo][EC2Demo]. You should be familiar with the architecture and terminology of Marionette Collective, please review the [basic architecture, terminology and message flow][MessageFlowCast] screencast first. - ## Requirements We try to keep the requirements on external Gems to a minimum, you only need: @@ -45,7 +45,7 @@ We strongly recommend you set up a local Yum repository that will host all the p * Ruby - included with your distribution * RubyGems - [EPEL] * Stomp Ruby Gem - [EPEL] - * [MCollective][MCDownloads] - mcollective-1.x.x-1.el5.noarch.rpm, mcollective-common-1.x.x-1.el5.noarch.rpm, mcollective-client-1.x.x-1.el5.noarch.rpm + * [MCollective][MCDownloads] - mcollective-2.2.x-1.el5.noarch.rpm, mcollective-common-2.2.x-1.el5.noarch.rpm, mcollective-client-2.2.x-1.el5.noarch.rpm The rest of this guide will assume you set up a Yum repository. Puppet Labs hosts a Yum repository with all these dependencies at _yum.puppetlabs.com_. @@ -65,82 +65,18 @@ On the server that you chose to configure as the ActiveMQ server: ### Configuring -Initially you'll just keep it simple with a single ActiveMQ broker and a basic user setup, further security information for ActiveMQ -can be found [here][SecurityWithActiveMQ] - -Place the following in _/etc/activemq/activemq.xml_ you can download this file from [GitHub][ActiveMQSingleBrokerSample] - -Other examples are also available from [GitHub][ActiveMQSamples] - -{% highlight xml %} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -{% endhighlight %} +[The ActiveMQ config reference][activemq_config] describes all of the ActiveMQ settings that MCollective cares about. For best use, skim the sections you care about while comparing it to an example activemq.xml file. + +[activemq_config]: /mcollective/deploy/middleware/activemq.html + +We recommend that new users: + +* Start with the [single-broker example config][ActiveMQSingleBrokerSample]. +* Change the [user account passwords](/mcollective/deploy/middleware/activemq.html#authentication-users-and-groups). +* [Set up TLS](/mcollective/deploy/middleware/activemq.html#tls-credentials) and [use a TLS Stomp transport connector](/mcollective/deploy/middleware/activemq.html#transport-connectors). + +Other example config files are also available from [GitHub][ActiveMQSamples]. -This creates a user *mcollective* with the password *marionette* and give it access to read/write/admin */topic/mcollective.`*`*. You should change this passsword. ### Starting @@ -153,7 +89,7 @@ Start the ActiveMQ service: You should see it running in the process list: {% highlight console %} - # ps -auxw|grep java + # ps auxw|grep java activemq 3012 0.1 14.5 1155112 152180 ? Sl Dec28 2:02 java -Dactivemq.home=/usr/share/activemq -Dactivemq.base=/usr/share/activemq -Dcom.sun.management.jmxremote -Dorg.apache.activemq.UseDedicatedTaskRunner=true -Xmx512m -Djava.library.path=/usr/lib:/usr/lib64 -classpath /usr/share/java/tanukiwrapper.jar:/usr/share/activemq/bin/run.jar -Dwrapper.key=eg4_VvENzCmvtAKg -Dwrapper.port=32000 -Dwrapper.jvm.port.min=31000 -Dwrapper.jvm.port.max=31999 -Dwrapper.pid=3000 -Dwrapper.version=3.2.3 -Dwrapper.native_library=wrapper -Dwrapper.service=TRUE -Dwrapper.cpu.timeout=10 -Dwrapper.jvmid=1 org.tanukisoftware.wrapper.WrapperSimpleApp org.apache.activemq.console.Main start {% endhighlight %} @@ -190,18 +126,19 @@ We're assuming you called the machine running ActiveMQ *stomp.example.net* pleas loglevel = error # connector plugin config - connector = stomp - plugin.stomp.host = stomp.example.net - plugin.stomp.port = 61613 - plugin.stomp.user = mcollective - plugin.stomp.password = marionette + connector = activemq + plugin.activemq.pool.size = 1 + plugin.activemq.pool.1.host = stomp.example.net + plugin.activemq.pool.1.port = 61613 + plugin.activemq.pool.1.user = mcollective + plugin.activemq.pool.1.password = marionette # security plugin config securityprovider = psk plugin.psk = abcdefghj {% endhighlight %} -You should also create _/etc/mcollective/server.cfg_ here's a sample, , a full reference of config settings can be found here [ConfigurationReference]: +You should also create _/etc/mcollective/server.cfg_ here's a sample, a full reference of config settings can be found on the [Server Configuration Reference][server_config]: {% highlight ini %} # main config @@ -211,11 +148,12 @@ You should also create _/etc/mcollective/server.cfg_ here's a sample, , a full r loglevel = info # connector plugin config - connector = stomp - plugin.stomp.host = stomp.example.net - plugin.stomp.port = 61613 - plugin.stomp.user = mcollective - plugin.stomp.password = marionette + connector = activemq + plugin.activemq.pool.size = 1 + plugin.activemq.pool.1.host = stomp.example.net + plugin.activemq.pool.1.port = 61613 + plugin.activemq.pool.1.user = mcollective + plugin.activemq.pool.1.password = marionette # facts factsource = yaml @@ -305,4 +243,3 @@ From here you should look at the rest of the wiki pages some key pages are: * [ControllingTheDaemon] - Controlling a running daemon * [AESSecurityPlugin] - Using AES+RSA for secure message encryption and authentication of clients * [SSLSecurityPlugin] - Using SSL for secure message signing and authentication of clients - * [ConnectorStomp] - Full details on the Stomp adapter including failover pools diff --git a/website/reference/basic/subcollectives.md b/website/reference/basic/subcollectives.md index 4240207..60e6d64 100644 --- a/website/reference/basic/subcollectives.md +++ b/website/reference/basic/subcollectives.md @@ -2,10 +2,15 @@ layout: default title: Subcollectives --- + [ActiveMQClustering]: /mcollective/reference/integration/activemq_clusters.html -[MessageFlow]: messageflow.html +[activemq_authorization]: /mcollective/deploy/middleware/activemq.html#authorization-group-permissions +[activemq_detailed]: /mcollective/deploy/middleware/activemq.html#detailed-restrictions +[activemq_subcollectives]: /mcollective/deploy/middleware/activemq.html#detailed-restrictions-with-multiple-subcollectives +[activemq_filtering]: /mcollective/deploy/middleware/activemq.html#destination-filtering +[activemq_authentication]: /mcollective/deploy/middleware/activemq.html#authentication-users-and-groups -# Overview +## Overview By default all servers are part of a single broadcast domain, if you have an agent on all machines in your network and you send a message directed to @@ -30,7 +35,7 @@ following scenarios: We've introduced the concept of sub collectives that lets you define broadcast domains and configure a mcollective server to belong to one or many of these domains. -# Partitionion Approaches +## Partitioning Approaches Determining how to partition your nework can be a very complex subject and requires an understanding of your message flow, where requestors sit and also @@ -90,7 +95,7 @@ network this can have a big impact. ![Subcollectives](../../images/subcollectives-impact.png) -# Configuring MCollective +## Configuring MCollective Configuring the partitioned collective above is fairly simple. We'll look at one of the DE nodes for reference: @@ -104,19 +109,7 @@ The _collectives_ directive tells the node all the collectives it should belong to and the _main`_`collective_ instructs Registration where to direct messages to. -# Partitioning for Security - -Another possible advantage from subcollectives is security. While the SimpleRPC -framework has a security model that is aware of the topology the core network -layer does not. Even if you only give someone access to run SimpleRPC requests -against some machines they can still use _mc ping_ to discover other nodes on -your network. - -By creating a subcollective of just their nodes and restricting them on the -middleware level to just that collective you can effectively and completely -create a secure isolated zone that overlays your exiting network. - -# Testing +## Testing Testing that it works is pretty simple, first we need a _client.cfg_ that configures your client to talk to all the sub collectives: @@ -126,10 +119,10 @@ collectives = mcollective,uk_collective,us_collective,de_collective,eu_collectiv main_collective = mcollective {% endhighlight %} -You can now test with _mc ping_: +You can now test with _mco ping_: {% highlight console %} -$ mc ping -T us_collective +$ mco ping -T us_collective host1.us.my.net time=200.67 ms host2.us.my.net time=241.30 ms host3.us.my.net time=245.24 ms @@ -153,7 +146,7 @@ You can discover the list of known collectives and how many nodes are in each using the _inventory_ application: {% highlight console %} -$ mc inventory --list-collectives +$ mco inventory --list-collectives * [ ==================================== ] 52 / 52 @@ -170,43 +163,39 @@ $ mc inventory --list-collectives {% endhighlight %} -# ActiveMQ Filters +## Partitioning for Security -The above setup should just work in most cases but you might want to go one step -further and actively prevent propagation across the network of sub collective -traffic. +Another possible advantage from subcollectives is security. While the SimpleRPC +framework has a security model that is aware of the topology the core network +layer does not. Even if you only give someone access to run SimpleRPC requests +against some machines they can still use _mco ping_ to discover other nodes on +your network. -In your ActiveMQ broker setup you will already have a section defining your -network connections, something like: +By creating a subcollective of just their nodes and restricting them on the +middleware level to just that collective you can effectively and completely +create a secure isolated zone that overlays your exiting network. -{% highlight xml %} - - - -{% endhighlight %} +These restrictions have to be configured on the middleware server, outside of MCollective itself. The method will vary based on the middleware you use; the suggestions below are for ActiveMQ, the main recommended middleware. -You can add filters here restricting traffic in this case the US<->UK connection -should never transmit _us`_`collective_ traffic, so lets restrict that: - -{% highlight xml %} - - - - - - - - - name="us-uk" - uri="static:(tcp://stomp1.uk.my.net:6166)" - userName="amq" - password="secret" - duplex="true" /> - -{% endhighlight %} +### Identifying Subcollectives on ActiveMQ + +The ActiveMQ connector plugin identifies subcollectives with the **first segment** of every destination (topic or queue) name. + +So for direct node addressing, for example, the default `mcollective` collective would use the `mcollective.nodes` queue, and `uk_collective` would use the `uk_collective.nodes` queue. For the package agent, they would use the `mcollective.package.agent` and `uk_collective.package.agent` topics, respectively. + +This makes it easy to use ActiveMQ destination wildcards to control access to a given collective. + +### Per-Subcollective Authorization + +To control subcollective access, identify the set of topics and queues that collective will use, then use ActiveMQ's authorization rules to secure them. + +* [See the "Authorization" section of the ActiveMQ config reference][activemq_authorization] for details. +* The ["Detailed Restrictions"][activemq_detailed] example shows all of the topics and queues used by the default collective; you can copy/paste/modify these for a small number of collectives. +* The ["Detailed Restrictions with Multiple Subcollectives"][activemq_subcollectives] example uses a snippet of ERB template to manage any number of collectives. + +You must then [configure multiple ActiveMQ user accounts][activemq_authentication] for your site's admins. Give each user membership in the groups they'll need to manage their collectives. + +### Destination Filters in a Network of Brokers + +In a [network of brokers][ActiveMQClustering], you can also prevent propagation across the network of sub collective +traffic. See the ["Destination Filtering"][activemq_filtering] section of the ActiveMQ config reference for details. diff --git a/website/reference/integration/activemq_clusters.md b/website/reference/integration/activemq_clusters.md index 79be05d..a4f2003 100644 --- a/website/reference/integration/activemq_clusters.md +++ b/website/reference/integration/activemq_clusters.md @@ -3,18 +3,17 @@ layout: default title: ActiveMQ Clustering toc: false --- -[MessageFormat]: /mcollective/reference/basic/messageformat.html [MessageFlow]: /mcollective/reference/basic/messageflow.html [NetworksOfBrokers]: http://activemq.apache.org/networks-of-brokers.html -[UsingSSL]: http://activemq.apache.org/how-do-i-use-ssl.html -[SecurityWithActiveMQ]: /mcollective/reference/integration/activemq_security.html [SampleConfig]: http://github.com/puppetlabs/marionette-collective/tree/master/ext/activemq/ +[fuse_cluster]: http://fusesource.com/docs/broker/5.5/clustering/index.html +[activemq_network]: /mcollective/deploy/middleware/activemq.html#settings-for-networks-of-brokers Relying on existing middleware tools and not re-inventing the transport wheel ourselves means we can take advantage of a lot of the built in features they provide. One such feature is clustering in ActiveMQ that allows for highly scalable and flexible network layouts. We'll cover here how to build a multi data center network of ActiveMQ servers with a NOC, the NOC computers would not need to send any packets direct to the nodes they manage and thanks to our meta data based approach to addressing machines they do not even need to know IPs or hostnames. -There is an example of a 3 node cluster in the [ext/activemq directory][SampleConfig]. +There is an example of a 3 node cluster in the [ext/activemq directory of the MCollective source][SampleConfig]. ## Network Design @@ -24,12 +23,12 @@ There is an example of a 3 node cluster in the [ext/activemq directory][SampleCo The diagram above shows our sample network, I am using the same techniques to put an ActiveMQ in each of 4 countries and then having local nodes communicate to in-country ActiveMQ nodes. - * These are the terminals of your NOC staff, they run the client code, these could also be isolated web servers for running admin tools etc. - * Each location has its own instance of ActiveMQ and nodes would only need to communicate to their local ActiveMQ. This greatly enhances security in a setup like this. - * The ActiveMQ instances speak to each other using a protocol called OpenWire, you can run this over IPSec or you could use the native support for SSL. - * These are the servers being managed, they run the server code. No direct communications needs to be in place between NOC and managed servers. +* These are the terminals of your NOC staff, they run the client code, these could also be isolated web servers for running admin tools etc. +* Each location has its own instance of ActiveMQ and nodes would only need to communicate to their local ActiveMQ. This greatly enhances security in a setup like this. +* The ActiveMQ instances speak to each other using a protocol called OpenWire, you can run this over IPSec or you could use the native support for SSL. +* These are the servers being managed, they run the server code. No direct communications needs to be in place between NOC and managed servers. -Refer to the [MessageFlow] document to see how messages would traverse the middleware in a setup like this. +Refer to the [MessageFlow][] document to see how messages would traverse the middleware in a setup like this. ### General Observations The main design goal here is to promote network isolation, the staff in your NOC are often high churn people, you'll get replacement staff relatively often and it's a struggle to secure what information they carry and how and when you can trust them. @@ -38,80 +37,21 @@ Our model of using middleware and off-loading authentication and authorization o Our usage of meta data to address machines rather than hostnames or ip address means you do not need to divulge this information to NOC staff, from their point of view they access machines like this: - * All machines in _datacenter=a_ - * AND all machines with puppet class _/webserver/_ - * AND all machines with Facter fact _customer=acmeinc_ +* All machines in _datacenter=a_ +* AND all machines with puppet class _/webserver/_ +* AND all machines with Facter fact _customer=acmeinc_ In the end they can target the machines they need to target for maintenance commands as above without the need for any info about hostnames, ips, or even what/where data center A is. This model works particularly well in a Cloud environment where hostnames are dynamic and not under your control, in a cloud like Amazon S3 machines are better identified by what AMI they have booted and in what availability zones they are rather than what their hostnames are. ## ActiveMQ Configuration -ActiveMQ supports many types of cluster, I think their Network of Brokers model works best for us so I'll show a sample setup of that. -There are some relevant docs on the ActiveMQ Wiki: +ActiveMQ supports many types of cluster; we think their Network of Brokers model works best for MCollective. - * [Network of Brokers][NetworksOfBrokers] - * [Using SSL for transport security][UsingSSL] +You will need to configure your ActiveMQ servers with everything from the ["Settings for Networks of Brokers" section of the ActiveMQ config reference][activemq_network]. Note the comments about the bi-directional connections: In the example network described above, you could either configure a pair of connectors on each datacenter broker to connect them to the NOC, or configure several pairs of connectors on the NOC broker to connect it to every datacenter. Do whichever makes sense for your own convenience and security needs. -## Configuring Transports +There is also a set of example config files in the [ext/activemq directory of the MCollective source][SampleConfig]; refer to these while reading the config reference. -First you should configure transport for that each ActiveMQ will listen on, this is the configuration for the NOC node, you'd just mirror this setup on each ActiveMQ node. +See [the ActiveMQ docs][NetworksOfBrokers] or [the Fuse docs][fuse_cluster] for more detailed info about networks of brokers. -{%highlight xml linenos %} - - - - - - -{% endhighlight %} - - * *The _brokerName_ attribute is important and should be unique.* (Leaving it set to localhost will cause message loops to occur) - * The _openwire_ transport is the important one here, you can make it listen on specific hosts and ports as shown. - -## Connecting to other ActiveMQs - -Next up you should configure the _networkConnectors_: - -{%highlight xml linenos %} - - - -{% endhighlight %} - -Here we're connecting the NOC to Data Center 1. - - * The _name_ on each connector should be unique, I just list the pair of hostnames involved which should be unique. - * This is a bi-directional connection it can send and receive traffic, you can make uni directional connections too if you wanted - * We're authenticating with a username and password - -There are many more options you can set on these connectors and it varies on your topology, you can make a ring of brokers or redundant meshes etc. - -### Setting up Authentication - -We have an [entire page dedicated][SecurityWithActiveMQ] to the subject of users and authentication, you should check that page out for full details but here's a simple bit of config for the authentication above. - -{%highlight xml linenos %} - - - - - - - - - - - - - - - - - - -{% endhighlight %} - -You can now duplicate this on your other nodes, the NOC will have users and NetworkConnectors for the Data Center 2 as well, you can also flip it around so the DCs connect to the NOC which might be more secure. diff --git a/website/reference/integration/activemq_security.md b/website/reference/integration/activemq_security.md index 2b5fbb3..e3ca4ed 100644 --- a/website/reference/integration/activemq_security.md +++ b/website/reference/integration/activemq_security.md @@ -3,90 +3,36 @@ layout: default title: ActiveMQ Security toc: false --- + [Security]: http://activemq.apache.org/security.html -[Registration]: /mcollective/reference/plugins/registration.html [Wildcard]: http://activemq.apache.org/wildcards.html -[ActiveMQ TLS]: activemq_ssl.html +[activemq_config]: /mcollective/deploy/middleware/activemq.html +[mcollective_username]: /mcollective/reference/plugins/connector_activemq.html#configuring-mcollective +[mcollective_tls]: ./activemq_ssl.html#configuring-mcollective-servers -As part of rolling out mcollective you need to think about security. The various examples in the quick start guide and on this blog has allowed all agents to talk to all nodes all agents. The problem with this approach is that should you have untrusted users on a node they can install the client applications and read the username/password from the server config file and thus control your entire architecture. +As part of rolling out MCollective you need to think about security. The various examples in the quick start guide and on this blog has allowed all agents to talk to all nodes all agents. The problem with this approach is that should you have untrusted users on a node they can install the client applications and read the username/password from the server config file and thus control your entire architecture. The default format for message topics is compatible with [ActiveMQ wildcard patterns][Wildcard] and so we can now do fine grained controls over who can speak to what. General information about [ActiveMQ Security can be found on their wiki][Security]. -The default message targets looks like this: - -{% highlight console %} - /topic/mcollective.agentname.command - /topic/mcollective.agentname.reply -{% endhighlight %} - -If you are using Subcollectives each subcollective will have topics like: - -{% highlight console %} - /topic/subcollective.agentname.command - /topic/subcollective.agentname.reply -{% endhighlight %} - -For a node to belong to a sub collective he also need rights to these topics. - -The nodes only need read access to the command topics and only need write access to the reply topics. The examples below also give them admin access so these topics can be created dynamically. For simplicity we'll wildcard the agent names, you could go further and limit certain nodes to only run certain agents. Adding these controls effectively means anyone who gets onto your node will not be able to write to the command topics and so will not be able to send commands to the rest of the collective. - -There's one special case and that's the registration topic, if you want to enable the [registration feature][Registration] you should give the nodes access to write on the command channel for the registration agent. Nothing should reply on the registration topic so you can limit that in the ActiveMQ config. - -We'll let mcollective log in as the mcollective user, create a group called mcollectiveusers, we'll then give the mcollectiveusers group access to run as a typical registration enabled mcollective node. - -The rip user is a mcollective admin and can create commands and receive replies. - -First we'll create users and the groups. - -{% highlight xml %} - - - - - - -{% endhighlight %} - -Now we'll create the access rights: +## Configuring Security in activemq.xml -{% highlight xml %} - - - - - - - - - - - - - - -{% endhighlight %} +[The ActiveMQ config reference][activemq_config] contains all relevant info for configuring security is activemq.xml. The most relevant sections are: -You could give just the specific node that runs the registration agent access to mcollective.registration.command to ensure the secrecy of your node registration. +* [Topic and Queue Names](/mcollective/deploy/middleware/activemq.html#topic-and-queue-names) --- Info about the destinations that MCollective uses. +* [Transport Connectors](/mcollective/deploy/middleware/activemq.html#transport-connectors) --- URL structure for insecure and TLS transports. +* [TLS Credentials](/mcollective/deploy/middleware/activemq.html#tls-credentials) --- For use with TLS transports. +* [Authentication](/mcollective/deploy/middleware/activemq.html#authentication-users-and-groups) --- Establishing user accounts and groups. +* [Authorization](/mcollective/deploy/middleware/activemq.html#authorization-group-permissions) --- Limiting access to destinations based on group membership. +* [Destination Filtering](/mcollective/deploy/middleware/activemq.html#destination-filtering) --- Preventing certain messages from crossing between datacenters. -Finally the nodes need to be configured, the server.cfg should have the following at least: -{% highlight ini %} - plugin.stomp.user = mcollective - plugin.stomp.password = pI1SkjRi - plugin.psk = aBieveenshedeineeceezaeheer -{% endhighlight %} -For my clients I can use the ability to configure the user details in my shell environment: +## Configuring Security in MCollective -{% highlight bash %} - export STOMP_USER=rip - export STOMP_PASSWORD=foobarbaz - export STOMP_SERVER=stomp1 - export MCOLLECTIVE_PSK=aBieveenshedeineeceezaeheer -{% endhighlight %} +MCollective clients and servers need security credentials that line up with ActiveMQ's expectations. Specifically: -And finally the rip user when logged into a shell with these variables have full access to the various commands. You can now give different users access to the entire collective or go further and give a certain admin user access to only run certain agents by limiting the command topics they have access to. Doing the user and password settings in shell environments means it's not kept in any config file in /etc/ for example. +* [An ActiveMQ username and password][mcollective_username] +* [TLS credentials, if necessary][mcollective_tls] -Your next step should be to setup TLS between your nodes and your middleware, to set this up follow our [ActiveMQ TLS] quide. diff --git a/website/reference/integration/activemq_ssl.md b/website/reference/integration/activemq_ssl.md index 4e21b72..ea9a90d 100644 --- a/website/reference/integration/activemq_ssl.md +++ b/website/reference/integration/activemq_ssl.md @@ -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 `` 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 %} - - - -{% endhighlight %} +### Step 2: Configure MCollective Servers -And we need to tell ActiveMQ to only accept fully verified connections: - -{% highlight xml %} - - - - -{% 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/.pem +plugin.activemq.pool.1.ssl.cert = /var/lib/puppet/ssl/certs/.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 %} - - - -{% endhighlight %} +**(Less Recommended)** -And you should add a SSL stomp listener, you should get port 6164 opened: +### Summary -{% highlight xml %} - - - - - -{% 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 `` 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. diff --git a/website/reference/plugins/connector_activemq.md b/website/reference/plugins/connector_activemq.md index f38bade..1456d18 100644 --- a/website/reference/plugins/connector_activemq.md +++ b/website/reference/plugins/connector_activemq.md @@ -3,118 +3,78 @@ layout: default title: ActiveMQ Connector toc: false --- + [STOMP]: http://stomp.codehaus.org/ +[wildcard]: http://activemq.apache.org/wildcards.html +[subcollectives]: /reference/basic/subcollectives.html +[activemq_config]: /mcollective/deploy/middleware/activemq.html + -The ActiveMQ connector uses the [STOMP] rubygem to connect to ActiveMQ servers. It is specifically optimiszed for ActiveMQ +The ActiveMQ connector uses the [STOMP][] rubygem to connect to ActiveMQ servers. It is specifically optimized for ActiveMQ and uses features in ActiveMQ 5.5.0 and later. -This code will only work with version _1.1.8_ or newer of the Stomp gem. +This plugin requires version _1.2.2_ or newer of the Stomp gem. ## Differences between ActiveMQ connector and Stomp Connector -The ActiveMQ connector requires MCollective 2.0.0 or newer and introduce a new structure to the middleware messsages. +### Topic and Queue Names - * Replies goes direct to clients using short lived queues - * Agent topics are called */topic/<collective>.<agent_name>.agent* - * Support for point to point messages are added by using _/queue/<collective>.nodes_ and using JMS selectors. +The new connector uses different destination names from the old stomp connector. -The use of short lived queues mean that replies are now going to go back only to the person who sent the request. -This has big impact on overall CPU usage by clients on busy networks but also optimize the traffic flow on -networks with many brokers. +MCollective uses the following destination names. This list uses standard [ActiveMQ destination wildcards][wildcard]. "COLLECTIVE" is the name of the collective being used; by default, this is `mcollective`, but if you are using [subcollectives][], each one is implemented as an equal peer of the default collective. + +Topics: + +- `ActiveMQ.Advisory.>` (built-in topics that all ActiveMQ producers and consumers need all permissions on) +- `COLLECTIVE.*.agent` (for each agent plugin, where the `*` is the name of the plugin) + +Queues: + +- `COLLECTIVE.nodes` (used for direct addressing; this is a single destination that uses JMS selectors, rather than a group of destinations) +- `COLLECTIVE.reply.>` (where the continued portion is a request ID) -Point to Point messages means each node has a unique subscription, the approach using JMS Selectors means -internally to ActiveMQ only a single thread will be dedicated to this rather than 1 per connected node. +Note especially that: + +* We can now do direct addressing to specific nodes. +* Replies now go directly to the instigating client instead of being brodcast on a topic. + +This has big impact on overall CPU usage by clients on busy networks, and also optimizes the traffic flow on +networks with many brokers. -Before using this plugin you will need to make appropriate adjustments to your ActiveMQ Access Control Lists. ## Configuring ActiveMQ -For best behavior there are a few settings you need in your _activemq.xml_ - -### Remove unused queues -We use uniquely named queues for replies. As queues will live forever we need to get ActiveMQ to remove -queues we are done with else they will just add up and grow forever. - -{% highlight xml %} - - - - - - - -{% endhighlight %} -The above policy will instruct ActiveMQ to remove dead queues after 5 minutes. - -### Optimize network usage for direct requests in a network of brokers -If you are using a network of brokers you will need to make a big change to how that works. -At present we tend to have 1 bi-directional connection for everything, with direct requests -we dedicate a bi-directional connection for these queues leaving the other just for topics. - -{% highlight xml %} - - - - - - - - - - - - -{% endhighlight %} +See [the ActiveMQ config reference][activemq_config] for details on configuring ActiveMQ for this connector. As recommended at the top of the reference, you should skim the sections you care about and edit an example config file while reading. -You will need to adjust the TTL for your network. Note the queue connection has a different -_conduitSubscriptions_ policy than the topic one, you have to create these different connections -and set this policy for everything to work correctly. ## Configuring MCollective -### Common Options -The most basic configuration method is supported in all versions of the gem: +MCollective clients and servers use the same connector settings, although the value of settings involving credentials will vary. ### Failover Pools + A sample configuration can be seen below. Note this plugin does not support the old style config of the Stomp connector. {% highlight ini %} connector = activemq plugin.activemq.pool.size = 2 plugin.activemq.pool.1.host = stomp1 -plugin.activemq.pool.1.port = 6163 +plugin.activemq.pool.1.port = 61613 plugin.activemq.pool.1.user = me plugin.activemq.pool.1.password = secret plugin.activemq.pool.2.host = stomp2 -plugin.activemq.pool.2.port = 6163 +plugin.activemq.pool.2.port = 61613 plugin.activemq.pool.2.user = me plugin.activemq.pool.2.password = secret {% endhighlight %} This gives it 2 servers to attempt to connect to, if the first one fails it will use the second. Usernames and passwords can be set -with the environment variables STOMP_USER, STOMP_PASSWORD. +with the environment variables `STOMP_USER`, `STOMP_PASSWORD`. If you do not specify a port it will default to _61613_ -You can also specify the following options for the Stomp gem, these are the defaults in the Stomp 1.1.6 gem: +You can also specify the following options for the Stomp gem, these are the defaults in the Stomp gem: {% highlight ini %} plugin.activemq.initial_reconnect_delay = 0.01 diff --git a/website/reference/plugins/connector_rabbitmq.md b/website/reference/plugins/connector_rabbitmq.md index 2c39169..fba83ab 100644 --- a/website/reference/plugins/connector_rabbitmq.md +++ b/website/reference/plugins/connector_rabbitmq.md @@ -56,12 +56,12 @@ connector = rabbitmq plugin.rabbitmq.vhost = /mcollective plugin.rabbitmq.pool.size = 2 plugin.rabbitmq.pool.1.host = rabbit1 -plugin.rabbitmq.pool.1.port = 6163 +plugin.rabbitmq.pool.1.port = 61613 plugin.rabbitmq.pool.1.user = mcollective plugin.rabbitmq.pool.1.password = changeme plugin.rabbitmq.pool.2.host = rabbit2 -plugin.rabbitmq.pool.2.port = 6163 +plugin.rabbitmq.pool.2.port = 61613 plugin.rabbitmq.pool.2.user = mcollective plugin.rabbitmq.pool.2.password = changeme {% endhighlight %} diff --git a/website/reference/plugins/connector_stomp.md b/website/reference/plugins/connector_stomp.md index b3ec9f7..98eaa7a 100644 --- a/website/reference/plugins/connector_stomp.md +++ b/website/reference/plugins/connector_stomp.md @@ -4,6 +4,10 @@ title: STOMP Connector toc: false --- [STOMP]: http://stomp.codehaus.org/ +[ConnectorActiveMQ]: /mcollective/reference/plugins/connector_activemq.html +[ConnectorRabbitMQ]: /mcollective/reference/plugins/connector_rabbitmq.html + +*NOTE:* This connector is being deprecated and will not be supported in versions newer than 2.2.x. Please move to one of the [ConnectorActiveMQ] or [ConnectorRabbitMQ]. The stomp connector uses the [STOMP] rubygem to connect to compatible servers. This is known to work with ActiveMQ and Stompserver. Anecdotal evidence suggests it works with RabbitMQ's Stomp plugin. @@ -30,7 +34,7 @@ The most basic configuration method is supported in all versions of the gem: connector = stomp plugin.stomp.base64 = false plugin.stomp.host = stomp.my.net -plugin.stomp.port = 6163 +plugin.stomp.port = 61613 plugin.stomp.user = me plugin.stomp.password = secret {% endhighlight %} @@ -49,12 +53,12 @@ logging about connections, failures and other significant events. connector = stomp plugin.stomp.pool.size = 2 plugin.stomp.pool.host1 = stomp1 -plugin.stomp.pool.port1 = 6163 +plugin.stomp.pool.port1 = 61613 plugin.stomp.pool.user1 = me plugin.stomp.pool.password1 = secret plugin.stomp.pool.host2 = stomp2 -plugin.stomp.pool.port2 = 6163 +plugin.stomp.pool.port2 = 61613 plugin.stomp.pool.user2 = me plugin.stomp.pool.password2 = secret {% endhighlight %} diff --git a/website/reference/plugins/data.md b/website/reference/plugins/data.md index e0e6f09..e5768e3 100644 --- a/website/reference/plugins/data.md +++ b/website/reference/plugins/data.md @@ -3,6 +3,7 @@ layout: default title: Data Plugins --- [DDL]: /mcollective/reference/plugins/ddl.html +[DiscoveryPlugins]: /mcollective/reference/plugins/discovery.html ## Overview Up to MCollective 2.0 the discovery system could only discover against @@ -36,6 +37,11 @@ action "query" do end {% endhighlight %} +*NOTE:* As opposed to the [DiscoveryPlugins] which are used by the client +to communicate to the nodes using direct addressing, data plugins on the other +hand refer to data that the nodes can provide, and hence this uses the normal +broadcast discovery paradigm. + These new data sources are plugins so you can provide via the plugin system and they require DDL documents. The DDL will be used on both the client and the server to provide strict validation and configuration. diff --git a/website/reference/ui/nodereports.md b/website/reference/ui/nodereports.md index 39adb0d..5458cda 100644 --- a/website/reference/ui/nodereports.md +++ b/website/reference/ui/nodereports.md @@ -6,7 +6,7 @@ title: Node Reports As we have all facts, classes and agents for nodes we can do some custom reporting on all of these. -The _mc inventory_ tool is a generic node and network reporting tool, it has basic scripting abilities. +The _mco inventory_ tool is a generic node and network reporting tool, it has basic scripting abilities. **Note: This is an emerging feature, the scripting language is likely to change** @@ -55,7 +55,7 @@ We have a concept of [Subcollectives] and you can use the inventory application report on all known collectives: {% highlight console %} -$ mc inventory --list-collectives +$ mco inventory --list-collectives * [ ===================================== ] 52 / 52 @@ -77,7 +77,7 @@ $ mc inventory --list-collectives You can also create a DOT format graph of your collective: {% highlight console %} -$ mc inventory --collective-graph collective.dot +$ mco inventory --collective-graph collective.dot Retrieving collective info.... Graph of 52 nodes has been written to collective.dot diff --git a/website/releasenotes.md b/website/releasenotes.md index a5cd15f..cc9f31c 100644 --- a/website/releasenotes.md +++ b/website/releasenotes.md @@ -10,7 +10,7 @@ will be highlighted here.   -## 2.3.1 - 2012/02/14 +## 2.3.1 - 2013/02/14 This is the second release in the new development series of MCollective. This release features enhancements and bug fixes. @@ -79,22 +79,22 @@ package upgrading from failing |Date|Description|Ticket| |----|-----------|------| |*2013/02/14*|*Release 2.3.1*|19265| -|2012/02/14|Initial work towards internationalization and online help|18663| +|2013/02/14|Initial work towards internationalization and online help|18663| |2013/02/14|Update vendored JSON gem for CVE-2013-0269|19265| -|2012/02/13|Restore the ability to set a discovery timeout on a RPC client|19238| -|2012/02/12|Replace underscores in plugin names with dashes to keep Debian happy|19200| -|2012/02/12|Fix package building on certain Debian systems|19141| -|2012/02/12|Remove the stomp connector|19146| -|2012/02/07|Read the client config before trying to use any configuration options|19105| -|2012/01/22|When an argument fails to parse in the rpc application fail rather than continue with unintended consequences|18773| -|2012/01/22|The fix the *--no-response* argument to the rpc application that broke due to 18438|18513| -|2012/01/22|Set *=* dependencies on the various packages that form a plugin rather than *>=*|18758| -|2012/01/21|Improve presentation of the --help output for applications|18447| -|2012/01/21|When a request failed via *reply.fail*, only show the message and not the half built data|18434| +|2013/02/13|Restore the ability to set a discovery timeout on a RPC client|19238| +|2013/02/12|Replace underscores in plugin names with dashes to keep Debian happy|19200| +|2013/02/12|Fix package building on certain Debian systems|19141| +|2013/02/12|Remove the stomp connector|19146| +|2013/02/07|Read the client config before trying to use any configuration options|19105| +|2013/01/22|When an argument fails to parse in the rpc application fail rather than continue with unintended consequences|18773| +|2013/01/22|The fix the *--no-response* argument to the rpc application that broke due to 18438|18513| +|2013/01/22|Set *=* dependencies on the various packages that form a plugin rather than *>=*|18758| +|2013/01/21|Improve presentation of the --help output for applications|18447| +|2013/01/21|When a request failed via *reply.fail*, only show the message and not the half built data|18434|   -## 2.2.3 - 2012/02/14 +## 2.2.3 - 2013/02/14 This is a maintenance release to the current production version of MCollective. This release is a bug fix only release. @@ -125,16 +125,16 @@ ActiveMQ or RabbitMQ specific ones. |----|-----------|------| |*2013/02/14*|*Release 2.2.3*|19265| |2013/02/14|Update vendored JSON gem for CVE-2013-0269|19265| -|2012/02/13|Restore the ability to set a discovery timeout on a RPC client|19238| -|2012/02/12|Replace underscores in plugin names with dashes to keep Debian happy|19200| -|2012/02/12|Fix package building on certain Debian systems|19141| -|2012/02/12|Deprecate the stomp connector|19146| -|2012/02/07|Read the client config before trying to use any configuration options|19105| -|2012/01/22|Set *=* dependencies on the various packages that form a plugin rather than *>=*|18758| +|2013/02/13|Restore the ability to set a discovery timeout on a RPC client|19238| +|2013/02/12|Replace underscores in plugin names with dashes to keep Debian happy|19200| +|2013/02/12|Fix package building on certain Debian systems|19141| +|2013/02/12|Deprecate the stomp connector|19146| +|2013/02/07|Read the client config before trying to use any configuration options|19105| +|2013/01/22|Set *=* dependencies on the various packages that form a plugin rather than *>=*|18758|   -## 2.0.1 - 2012/02/14 +## 2.0.1 - 2013/02/14 This is a maintenance release against our unsupported past production release, it brings no visible changes or bug fixes we only updated the vendored JSON gem to version 1.5.5 due to diff --git a/website/simplerpc/authorization.md b/website/simplerpc/authorization.md index b2521ed..ad1ea18 100644 --- a/website/simplerpc/authorization.md +++ b/website/simplerpc/authorization.md @@ -50,7 +50,7 @@ end The call extra _authorized`_`by :authorize`_`it_ line tells your agent to use the _MCollective::Util::AuthorizeIt_ class for authorization. -## Enabling RPC auditing globally +## Enabling RPC authorization globally You can enable a specific plugin on all RPC agents in the server config file. If you do this and an agent also specify it's own authorization the agent will take priority. {% highlight ini %}