├── .fixtures.yml
├── .gitignore
├── CHANGELOG.md
├── Gemfile
├── LICENSE
├── README.md
├── Rakefile
├── files
├── actionpolicy-auth
│ ├── README.md
│ └── util
│ │ ├── actionpolicy.ddl
│ │ └── actionpolicy.rb
├── policies
│ ├── README.policy-format
│ ├── allow_psk_root.policy_example
│ ├── puppet.policy_example
│ └── service.policy_example
└── ssl
│ ├── clients
│ ├── fireagate.example.net.pem
│ ├── geode.netconsonance.com.pem
│ ├── heliotrope.example.net.pem
│ ├── jorhett.pem
│ └── sunstone.example.net.pem
│ └── server
│ ├── private.pem
│ └── public.pem
├── lib
└── facter
│ └── ssldir.rb
├── manifests
├── client.pp
├── facts.pp
├── facts
│ └── cronjob.pp
├── init.pp
├── middleware.pp
├── params.pp
├── plugin
│ ├── actionpolicy.pp
│ ├── agent.pp
│ └── client.pp
├── server.pp
└── userconfig.pp
├── metadata.json
├── spec
├── classes
│ ├── client_spec.rb
│ ├── facts
│ │ └── cronjob_spec.rb
│ ├── init_spec.rb
│ ├── middleware_spec.rb
│ └── server_spec.rb
└── spec_helper.rb
├── templates
├── activemq.sysconfig.erb
├── activemq.xml.erb
├── agent.policy.erb
├── client.cfg.erb
├── jetty-realm.properties.erb
├── logrotate-auditlog.erb
├── rabbitmq.config.erb
├── server.cfg.erb
└── userconfig.erb
└── tests
└── init.pp
/.fixtures.yml:
--------------------------------------------------------------------------------
1 | fixtures:
2 | symlinks:
3 | mcollective: "#{source_dir}"
4 |
5 | forge_modules:
6 | stdlib:
7 | repo: "puppetlabs/stdlib"
8 | ref: 3.2.1
9 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /pkg/
2 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## 2015-11-26 - Release 1.0.3
2 | ### Bugfix
3 | - Ensure that facts cronjob is moved into place without confirmation prompt
4 |
5 | ##2015-11-26 - Release 1.0.2
6 | ###Bugfix release
7 |
8 | ####Bugfixes
9 | - Fixed jetty password template variable reference (reported by devoncustard)
10 |
11 | ##2015-11-22 - Release 1.0.1
12 | ###Stable release
13 |
14 | This release is in use in many production sites and is stable.
15 | Only non-breaking bugfixes will be applied to 1.0.X versions going forward.
16 |
17 | Release 2.0 and above will only support Puppet 4 / future parser,
18 | and will drop support for Puppet 3 and below.
19 |
20 | ####Bugfixes
21 | - Fixed an error about referencing qualified variable in an optional class
22 | - Added/improved docs in both README and facts::cronjobs class
23 | - Fix for trailing comma on collectives (provided by Vadym Chepkov)
24 | - Fix for wrong variable name on client plugin loglevel (provided by Vadym Chepkov)
25 | - Fix for actionpolicy default name (reported by Taejon Moon)
26 |
27 | ##2015-09-08 - Release 0.1.7
28 | ###Puppet 4 Compatibility
29 |
30 | ####Features
31 | - Adjusted configuration to work with Puppet 4
32 | - Added new `mcollective::facts::cronjob::run_every` parameter to control facts updates
33 |
34 | ####Obsoletes
35 | The Hiera parameter 'mcollective::facts::cronjob::run_every' is now preferred
36 | and the only working method for Puppet 4. Use of the 'mcollective::facts' class
37 | is deprecated and will be removed in v1.0
38 |
39 | ##2015-05-27 - Release 0.1.6
40 | ###Added $logrotate_directory parameter
41 |
42 | ####Features
43 | - Added rspec tests for platform defaults
44 | - Added new $logrotate_directory variable
45 |
46 | The new variable defaults to backwards compatible changes,
47 | but allows it to be set to undef/nil to disable logrotate file installation.
48 |
49 | ##2015-05-26 - Release 0.1.5
50 | ###Added rspec tests
51 |
52 | ####Features
53 | - Added rspec tests for every class
54 |
55 | ####Bugfixes
56 | - Fix mistype in error message
57 | - Remove extra spaces that puppet-lint didn't like
58 | - Removed a set of double quotes without a variable inside
59 | - Fixed dependency resolution problem
60 |
61 | ##2015-05-25 - Release 0.1.4
62 | ###Changed to BSD 3-Clause License
63 |
64 | The module has been changed to the BSD 3-clause license.
65 |
66 | ####Features
67 | - Added CHANGELOG in Markdown format
68 |
69 | ##2015-05-19 - Release 0.1.3
70 | ###Fixed problem with ActiveMQ config file template
71 |
72 | ####Bugfixes
73 | - activemq won't replace variables inside the xml configuration without config.PropertyPlaceholderConfigurer
74 |
75 | ##2015-04-01 - Release 0.1.2
76 | ###Puppetlabs ActiveMQ 5.9 package, Improved facts.yaml generation
77 |
78 | ####Features
79 | - Use ActiveMQ 5.9 package from Puppet Labs dependency repo
80 | - Added module tests
81 | - More complete metadata
82 |
83 | ####Bugfixes
84 | - Revised facts.yaml generation to work properly regardless of Puppet stringify settings
85 |
86 | ##2014-09-10 - Release 0.1.1
87 | ###Improved documentation
88 |
89 | ##2014-07-14 - Release 0.0.1
90 | ###Original release
91 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | puppetversion = ENV.key?('PUPPET_VERSION') ? "= #{ENV['PUPPET_VERSION']}" : ['>= 3.3']
4 | gem 'puppet', puppetversion
5 | gem 'puppetlabs_spec_helper', '>= 0.1.0'
6 | gem 'puppet-lint', '>= 0.3.2'
7 | gem 'facter', '>= 1.7.0'
8 | gem 'rspec-puppet', '~> 2.1.0'
9 |
10 | # rspec must be v3.1.0 for ruby 1.8.7
11 | if RUBY_VERSION >= '1.8.7' and RUBY_VERSION < '1.9'
12 | gem 'rspec', '~> 3.1.0'
13 | end
14 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2014-2015, Jo Rhett
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 |
7 | * Redistributions of source code must retain the above copyright notice, this
8 | list of conditions and the following disclaimer.
9 |
10 | * Redistributions in binary form must reproduce the above copyright notice,
11 | this list of conditions and the following disclaimer in the documentation
12 | and/or other materials provided with the distribution.
13 |
14 | * Neither the name of jorhett-mcollective nor the names of its
15 | contributors may be used to endorse or promote products derived from
16 | this software without specific prior written permission.
17 |
18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # mcollective
2 |
3 | ## Overview
4 |
5 |
6 |

7 |
8 |
9 | This is an MCollective module for Puppet. It configures MCollective brokers,
10 | servers, and clients without any other dependency classes, as documented in
11 | [Learning MCollective](http://shop.oreilly.com/product/0636920032472.do).
12 |
13 | O'Reilly Media, Inc.
14 | http://shop.oreilly.com/product/0636920032472.do
15 | ISBN: [978-1-4919-4567-4](http://shop.oreilly.com/product/0636920032472.do)
16 |
17 |
18 | ## Deprecated
19 |
20 | This module is deprecated in favour of [choria](https://forge.puppet.com/choria/choria),
21 | which greatly simplifies what used to be the more complex bespoke Mcollective installations this module could create.
22 |
23 | ## Description
24 |
25 | This module can configure MCollective middleware brokers,
26 | servers, and clients. It can automatically configure complex configurations,
27 | such as networks of brokers, subcollectives, and TLS security options.
28 |
29 | With just a hostname and passwords it can create a fully working
30 | MCollective setup. With just a few more lines of input it can create
31 | TLS-validated, globally distributed MCollective environments.
32 |
33 | The module can also create authorization policies from Hiera input.
34 |
35 | ## Supported Operating Systems
36 |
37 | The module has been validated for full functionality on:
38 |
39 | * CentOS 6.4 and higher
40 | * Ubuntu 13.10
41 | * FreeBSD 9.2 and higher
42 |
43 | Updates for Solaris, MacOS, and Windows coming soon.
44 |
45 | ## Simple Setup
46 |
47 | The easiest setup is to put the passwords in Hiera and then simply
48 | include the modules in site or nodes manifest.
49 |
50 | ```YAML
51 | Hiera: common.yaml
52 | classes:
53 | - mcollective::server
54 |
55 | mcollective::hosts:
56 | - 'activemq.example.net'
57 | mcollective::client_password: 'Client Password'
58 | mcollective::server_password: 'Server Password'
59 | mcollective::psk_key : 'Salt Value'
60 |
61 | Hiera: fqdn/activemq.example.net.yaml
62 | classes:
63 | - mcollective::middleware
64 |
65 | Hiera: fqdn/admin.example.net.yaml
66 | classes:
67 | - mcollective::client
68 | ```
69 |
70 | Or if using in profiles with declarative style assignment:
71 |
72 | ```puppet
73 | node default {
74 | include mcollective::server
75 | }
76 | node 'activemq.example.net' {
77 | include mcollective::middleware
78 | }
79 | node 'admin.example.net' {
80 | include mcollective::client
81 | }
82 | ```
83 |
84 | This module is a companion intended for use with the Learning MCollective book.
85 |
86 | ## Facts
87 |
88 | The older version of the book refers to including the `facts` class to have facts
89 | from Facter and Puppet placed in /etc/mcollective/facts.yaml.
90 |
91 | ```
92 | include mcollective::facts
93 | ```
94 |
95 | While this still works, it is deprecated and will be removed in a future version.
96 | Instead, add this variable to define how many minutes between updates.
97 |
98 | ```YAML
99 | Hiera: common.yaml
100 | mcollective::facts::cronjob::run_every: 10
101 | ```
102 |
103 | ## Bugs
104 |
105 | If you report it, and I can replicate it I'll fix it.
106 |
107 | If you have an idea for improvement I might do it. If you create a Pull request
108 | it will happen faster. If you send me changes to support more operating systems,
109 | I'll owe you beer.
110 |
111 | I'm human and prone to overwork so response times vary. YMMV.
112 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | require 'rubygems'
2 | require 'puppetlabs_spec_helper/rake_tasks'
3 | require 'puppet-lint/tasks/puppet-lint'
4 | PuppetLint.configuration.send('disable_80chars')
5 | PuppetLint.configuration.ignore_paths = ["spec/**/*.pp", "pkg/**/*.pp"]
6 |
7 | desc "Validate manifests, templates, and ruby files"
8 | task :validate do
9 | Dir['manifests/**/*.pp'].each do |manifest|
10 | sh "puppet parser validate --noop #{manifest}"
11 | end
12 | Dir['spec/**/*.rb','lib/**/*.rb'].each do |ruby_file|
13 | sh "ruby -c #{ruby_file}" unless ruby_file =~ /spec\/fixtures/
14 | end
15 | Dir['templates/**/*.erb'].each do |template|
16 | sh "erb -P -x -T '-' #{template} | ruby -c"
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/files/actionpolicy-auth/README.md:
--------------------------------------------------------------------------------
1 | Action Policy Authorization Plugin
2 | =============================
3 |
4 | This is a plugin that provides fine grained action level authorization for agents. Any MCollective agent plugins based on SimpleRPC can be restricted with authorization plugins like this one.
5 |
6 | Installation
7 | ============
8 |
9 | * [Follow the plugin deployment guide](http://docs.puppetlabs.com/mcollective/deploy/plugins.html#method-2-copying-plugins-into-the-libdir), using the libdir copy method and placing the `actionpolicy.rb` and `actionpolicy.ddl` files in the `util` directory.
10 |
11 | Note that it is not currently possible to use the 'mco plugin package' command to package this plugin.
12 |
13 | Configuration
14 | =============
15 |
16 | There are three settings available for the actionpolicy plugin:
17 |
18 | * `allow_unconfigured` -- whether to allow requests to agents that do not have policy files configured. Boolean, with allowed values of `0`, `1`, `y`, `n`; values of `true` or `false` are not allowed. Defaults to `0`.
19 | * `enable_default` -- whether to use a default policy file. Boolean, with allowed values of `0`, `1`, `y`, `n`; values of `true` or `false` are not allowed. Defaults to `0`.
20 | * `default_name` -- the name of the default policy file, if `enable_default` is set to `1` or `y`.
21 |
22 | General authentication configuration options can be set in the server config file.
23 |
24 | # Enables system wide rpc authorization
25 | rpcauthorization = 1
26 | # Sets the authorization provider to use the actionpolicy plugin
27 | rpcauthprovider = action_policy
28 | # Allow requests to agents without policies
29 | plugin.actionpolicy.allow_unconfigured = 1
30 |
31 | ## Default Policy Files
32 |
33 | You can optionally have a default policy file that applies in the absence of an agent-specific policy file.
34 |
35 | plugin.actionpolicy.enable_default = 1
36 | plugin.actionpolicy.default_name = default
37 |
38 | This allows you to create a policy file called default.policy which will be used unless a specific policy file exists. Note that if both
39 | `allow_unconfigured` and `enable_default` are configured, all requests will go through the default policy, as `enable_default` takes precedence
40 | over `allow_unconfigured`.
41 |
42 | Usage
43 | =====
44 |
45 | Policies are defined in files like `/policies/.policy`
46 |
47 | Example: Puppet agent policy file
48 |
49 | # /etc/mcollective/policies/puppet.policy
50 | policy default deny
51 | allow cert=admin * * *
52 | allow cert=acme-devs * customer=acme acme::devserver
53 | allow cert=acme-devs enable disable status customer=acme *
54 |
55 | # /etc/mcollective/policies/service.policy
56 | policy default deny
57 | allow cert=puppet-admins restart (puppet().enabled=false and environment=production) or environment=development
58 |
59 | The above policy can be described as:
60 |
61 | * Allow the `admin` user to invoke all Puppet actions on all servers.
62 | * Allow the `acme-devs` user to invoke _all_ Puppet actions on machines with the fact _customer=acme_ and the config class _acme::devserver_
63 | * Allow the `acme-devs` user to invoke the _enable, disable and status_ actions on all other machines with fact _customer=acme_
64 | * Allow the `puppet-admins` user to restart services at any time in development but in production only when Puppet has been disabled
65 | * All other commands get denied
66 |
67 | Policy File Format
68 | -----
69 |
70 | Policy files must have the following format:
71 |
72 | * Any lines starting with `#` are comments.
73 | * A single `policy default deny` or `policy default allow` line is permitted; it can go anywhere in the file. This default policy will apply to any commands that don't match a specific rule. If you don't specify a default policy, the value of the `plugin.actionpolicy.allow_unconfigured` setting will be used as the default.
74 | * Any number of _policy lines_ are permitted. These must be **tab delimited** lines with either four or five fields (the final field is optional) in the following order:
75 | 1. `allow` or `deny`
76 | 2. Caller ID --- must be either `*` (always matches) or **one** caller ID string (see below)
77 | 3. Actions --- must be either `*` (always matches) or a space-separated list of actions
78 | 4. Facts --- may be either `*` (always matches), a space-separated list of `fact=value` pairs (matches if _every_ listed fact matches), or any valid [compound filter string][compound]
79 | 5. Classes --- may be completely absent (always matches), `*` (always matches), a space-separated list of class names (matches if _every_ listed class is present), or any valid [compound filter string][compound]
80 |
81 | ### Notes
82 |
83 | * Like firewall rules, policy lines are processed **in order** --- ActionPolicy will allow or deny each request using the _first_ rule that matches it. A policy line matches a request if **every** field after the allow/deny field matches.
84 | * Policy lines **must** use hard tabs; editor features that convert tabs to spaces (like Vim's `expandtab`) will result in non-functional policy lines.
85 | * Compound filter strings may match on facts, classes, and data plugins (MCollective 2.2.x or later). When using data plugins in action policies, you should avoid using slow ones, as this will impact the response times of agents, the client waiting time, etc.
86 |
87 | [compound]: http://docs.puppetlabs.com/mcollective/reference/basic/basic_cli_usage.html#complex-compound-or-select-queries
88 |
89 |
90 | ### Caller ID
91 |
92 | Caller ID strings are always of the form `=`, but both the kind and the value of the ID will depend on your security plugin. See your security plugin's documentation or code for details.
93 |
94 | * The recommended SSL security plugin sets caller IDs of `cert=`, where `` is the filename of the client's public key file (minus the `.pem` extension). So a request validated with the `puppet-admins.pem` public key file would be given a caller ID of `cert=puppet-admins`. This kind of caller ID is cryptographically authenticated.
95 | * The PSK security plugin defaults to caller IDs of `uid=`, where `` is the local UID of the client process. [There are several other options available](https://github.com/puppetlabs/marionette-collective/blob/master/plugins/mcollective/security/psk.rb#L79), which can be configured with the `plugin.psk.callertype` setting. **None of PSK's caller IDs are authenticated,** and you should generally not be relying on authorization at all if you are using the PSK security plugin.
96 |
97 |
98 | Hardcoding ActionPolicy Into a Specific Agent
99 | ============================
100 |
101 | Instead of using the site-wide authorization settings (as described above), you can also hardcode authorization plugins in your agents:
102 |
103 | module MCollective::Agent
104 | class Service "actionpolicy",
2 | :description => "Action Policy simplerpc authorization plugin",
3 | :author => "P.Loubser ",
4 | :license => "ASL 2.0",
5 | :version => "2.0.0",
6 | :url => "https://github.com/puppetlabs/mcollective-actionpolicy-authorization",
7 | :timeout => 1
8 |
9 | requires :mcollective => "2.2.1"
10 |
--------------------------------------------------------------------------------
/files/actionpolicy-auth/util/actionpolicy.rb:
--------------------------------------------------------------------------------
1 | module MCollective
2 | module Util
3 | class ActionPolicy
4 | attr_accessor :config, :allow_unconfigured, :configdir, :agent, :caller, :action
5 |
6 | def self.authorize(request)
7 | ActionPolicy.new(request).authorize_request
8 | end
9 |
10 | def initialize(request)
11 | @config = Config.instance
12 | @agent = request.agent
13 | @caller = request.caller
14 | @action = request.action
15 | @allow_unconfigured = !!(config.pluginconf.fetch('actionpolicy.allow_unconfigured', 'n') =~ /^1|y/i)
16 | @configdir = @config.configdir
17 | end
18 |
19 | def authorize_request
20 | # Lookup the policy file. If none exists and @allow_unconfigured
21 | # is false the request gets denied.
22 | policy_file = lookup_policy_file
23 |
24 | # No policy file exists and allow_unconfigured is false
25 | if !policy_file && !@allow_unconfigured
26 | deny('Could not load any valid policy files. Denying based on allow_unconfigured: %s' % @allow_unconfigured)
27 | # No policy exists but allow_unconfigured is true
28 | elsif !(policy_file) && @allow_unconfigured
29 | Log.debug('Could not load any valid policy files. Allowing based on allow_unconfigured: %s' % @allow_unconfigured)
30 | return true
31 | end
32 |
33 | # A policy file exists
34 | parse_policy_file(policy_file)
35 | end
36 |
37 | def parse_policy_file(policy_file)
38 | Log.debug('Parsing policyfile for %s: %s' % [@agent, policy_file])
39 | allow = @allow_unconfigured
40 |
41 | File.read(policy_file).each_line do |line|
42 | next if line =~ /^(#.*|\s*)$/
43 |
44 | if line =~ /^policy\s+default\s+(\w+)/
45 | if $1 == 'allow'
46 | allow = true
47 | else
48 | allow = false
49 | end
50 | elsif line =~ /^(allow|deny)\t+(.+?)\t+(.+?)\t+(.+?)(\t+(.+?))*$/
51 | if check_policy($2, $3, $4, $6)
52 | if $1 == 'allow'
53 | return true
54 | else
55 | deny("Denying based on explicit 'deny' policy rule in policyfile: %s" % File.basename(policy_file))
56 | end
57 | end
58 | else
59 | Log.debug("Cannot parse policy line: %s" % line)
60 | end
61 | end
62 |
63 | allow || deny("Denying based on default policy in %s" % File.basename(policy_file))
64 | end
65 |
66 | # Check if a request made by a caller matches the state defined in the policy
67 | def check_policy(rpccaller, actions, facts, classes)
68 | # If we have a wildcard caller or the caller matches our policy line
69 | # then continue else skip this policy line\
70 | if (rpccaller != '*') && (rpccaller != @caller)
71 | return false
72 | end
73 |
74 | # If we have a wildcard actions list or the request action is in the list
75 | # of actions in the policy line continue, else skip this policy line
76 | if (actions != '*') && !(actions.split.include?(@action))
77 | return false
78 | end
79 |
80 | unless classes
81 | return parse_compound(facts)
82 | else
83 | return parse_facts(facts) && parse_classes(classes)
84 | end
85 | end
86 |
87 | def parse_facts(facts)
88 | return true if facts == '*'
89 |
90 | if is_compound?(facts)
91 | return parse_compound(facts)
92 | else
93 | facts.split.each do |fact|
94 | return false unless lookup_fact(fact)
95 | end
96 | end
97 |
98 | true
99 | end
100 |
101 | def parse_classes(classes)
102 | return true if classes == '*'
103 |
104 | if is_compound?(classes)
105 | return parse_compound(classes)
106 | else
107 | classes.split.each do |klass|
108 | return false unless lookup_class(klass)
109 | end
110 | end
111 |
112 | true
113 | end
114 |
115 | def lookup_fact(fact)
116 | if fact =~ /(.+)(<|>|=|<=|>=)(.+)/
117 | lv = $1
118 | sym = $2
119 | rv = $3
120 |
121 | sym = '==' if sym == '='
122 | return eval("'#{Util.get_fact(lv)}'#{sym}'#{rv}'")
123 | else
124 | Log.warn("Class found where fact was expected")
125 | return false
126 | end
127 | end
128 |
129 | def lookup_class(klass)
130 | if klass =~ /(.+)(<|>|=|<=|>=)(.+)/
131 | Log.warn("Fact found where class was expected")
132 | return false
133 | else
134 | return Util.has_cf_class?(klass)
135 | end
136 | end
137 |
138 | def lookup(token)
139 | if token =~ /(.+)(<|>|=|<=|>=)(.+)/
140 | return lookup_fact(token)
141 | else
142 | return lookup_class(token)
143 | end
144 | end
145 |
146 | # Here we lookup the full path of the policy file. If the policyfile
147 | # does not exist, we check to see if a default file was set and
148 | # determine its full path. If no default file exists, or default was
149 | # not specified, we return false.
150 | def lookup_policy_file
151 | policy_file = File.join(@configdir, "policies", "#{@agent}.policy")
152 |
153 | Log.debug("Looking for policy in #{policy_file}")
154 |
155 | return policy_file if File.exist?(policy_file)
156 |
157 | if @config.pluginconf.fetch('actionpolicy.enable_default', 'n') =~ /^1|y/i
158 | defaultname = @config.pluginconf.fetch('actionpolicy.default_name', 'default')
159 | default_file = File.join(@configdir, "policies", "#{defaultname}.policy")
160 |
161 | Log.debug("Initial lookup failed: looking for policy in #{default_file}")
162 |
163 | return default_file if File.exist?(default_file)
164 | end
165 |
166 | Log.debug('Could not find any policy files.')
167 | nil
168 | end
169 |
170 | # Evalute a compound statement and return its truth value
171 | def eval_statement(statement)
172 | token_type = statement.keys.first
173 | token_value = statement.values.first
174 |
175 | return token_value if (token_type != 'statement' && token_type != 'fstatement')
176 |
177 | if token_type == 'statement'
178 | return lookup(token_value)
179 | elsif token_type == 'fstatement'
180 | begin
181 | return Matcher.eval_compound_fstatement(token_value)
182 | rescue => e
183 | Log.warn("Could not call Data function in policy file: #{e}")
184 | return false
185 | end
186 | end
187 | end
188 |
189 | def is_compound?(list)
190 | list.split.each do |token|
191 | if token =~ /^!|^not$|^or$|^and$|\(.+\)/
192 | return true
193 | end
194 | end
195 |
196 | false
197 | end
198 |
199 | def parse_compound(list)
200 | stack = Matcher.create_compound_callstack(list)
201 |
202 | begin
203 | stack.map!{ |item| eval_statement(item) }
204 | rescue => e
205 | Log.debug(e.to_s)
206 | return false
207 | end
208 |
209 | eval(stack.join(' '))
210 | end
211 |
212 | def deny(logline)
213 | Log.debug(logline)
214 |
215 | raise(RPCAborted, 'You are not authorized to call this agent or action.')
216 | end
217 | end
218 | end
219 | end
220 |
--------------------------------------------------------------------------------
/files/policies/README.policy-format:
--------------------------------------------------------------------------------
1 | All of this content is derrived from the plug's github page at
2 | https://github.com/puppetlabs/mcollective-actionpolicy-auth
3 |
4 | Policies are defined in files like /policies/.policy
5 |
6 | Any lines starting with # are comments.
7 |
8 | A single policy default deny or policy default allow line is permitted;
9 | it can go anywhere in the file. This default policy will apply to any
10 | commands that don't match a specific rule. If you don't specify a
11 | default policy, the value of the plugin.actionpolicy.allow_unconfigured
12 | setting will be used as the default.
13 |
14 | Any number of policy lines are permitted. These must be tab delimited
15 | lines with either four or five fields (the final field is optional)
16 | in the following order:
17 |
18 | allow or deny
19 |
20 | Caller ID --- must be either * (always matches) or one caller ID string
21 |
22 | Actions --- must be either * (always matches) or a space-separated list
23 |
24 | Facts --- may be either * (always matches),
25 | a space-separated list of fact=value pairs (matches if every fact matches),
26 | or any valid compound filter string
27 |
28 | Classes --- may be completely absent (always matches),
29 | * (always matches),
30 | a space-separated list of class names (matches if every class is present),
31 | or any valid compound filter string
32 |
--------------------------------------------------------------------------------
/files/policies/allow_psk_root.policy_example:
--------------------------------------------------------------------------------
1 | # /etc/mcollective/policies/allow_psk_root.policy
2 | # This is insecure unless we can trust root on every client machine
3 | policy default deny
4 | allow uid=0 * * *
5 | allow gid=0 * * *
6 |
--------------------------------------------------------------------------------
/files/policies/puppet.policy_example:
--------------------------------------------------------------------------------
1 | # /etc/mcollective/policies/puppet.policy
2 | policy default deny
3 |
4 | # Get out of jail free if you push out a policy that breaks authorization
5 | allow * runonce runall * *
6 |
7 | # Admins can do anything
8 | #allow cert=admin * * *
9 |
10 | # if Wile E Coyote had a dev team...
11 |
12 | # acme-devs can run puppet once or get puppet summary on any server
13 | #allow cert=acme-devs runonce summary customer=acme *
14 |
15 | # acme-devs can enable/disable puppet or run puppet on all devservers
16 | #allow cert=acme-devs enable disable runall customer=acme acme::devserver
17 |
--------------------------------------------------------------------------------
/files/policies/service.policy_example:
--------------------------------------------------------------------------------
1 | # /etc/mcollective/policies/service.policy
2 | # Admins can do anything
3 | # acme-devs can do anything to acme devservers
4 | # acme-devs can do status and restart on any acme box
5 | policy default deny
6 | allow cert=admin * * *
7 | allow cert=acme-devs * customer=acme acme::devserver
8 | allow cert=acme-devs restart status customer=acme *
9 |
--------------------------------------------------------------------------------
/files/ssl/clients/fireagate.example.net.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN PUBLIC KEY-----
2 | MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAv6VEev1VADrSCgyebIut
3 | lV4FKZ9nOSwUgU/nVauisLdLcKcT9uWThVNd8sbyebqOt+fm6qaO5VuPP4rNGuuu
4 | nKhS7Cnl6oMSdkX+Fk6D/xVvIcNUljJjaR/87gy04ZwBK0UjH8/KRbC1dg9Dn/tC
5 | YHCJ2LszAzU5fSi32C9bmFqIfQg7RwxEqOODkjP/+TemVBoYa8GhxQzoWuVViW7G
6 | pSvA4FO0pjaCWBPh7OAGFyHKazyyM3zGc5VBRCYece+0YqzQUBBBgwkx7tUxlGQN
7 | BW/D85Zgwm1F5zIJe+qhCMgb0sgeSA71QTiCQtIb3/5k/pQA+kQ+seDgkp4FrTOt
8 | 2DI8SCSMH9px/SrjfAYL3vYalFHa1GvF7t85Z7CcyvfXgZ3wHHRmN473PrDsmxk1
9 | h3qzOFxstebgaEEi0Y9TF2fpYY9q0BS9DWEsKiaL3yhPmya7vhw4tgHSYX4KAkdV
10 | ZsqACcI3+yaiwzdQdrG5XuERYbNfcRT+PZgdMGkhQILlqm4iZOBXQw0/tp9C2gxu
11 | /UMeNrfaXLyuTHE30LTrN8D0WHtBJRIFETmmGoIP63+EicOr9PWW/yEyWEKz7Wyh
12 | zw1/JfSiGGGFcLv4lOUdvJjbm9Ukr3gD2LAXGcCQNz24bvVI/NG9rkaxy2TgZ/Fo
13 | F4tiTn8AgO+Xv/cRFjWKy0UCAwEAAQ==
14 | -----END PUBLIC KEY-----
15 |
--------------------------------------------------------------------------------
/files/ssl/clients/geode.netconsonance.com.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PUBLIC KEY-----
2 | MIICCgKCAgEAru8dpnUg69FVIMXrXjPrfHb8XoYlhMda05ceuOKQlG667veoQHHO
3 | K3rWtwjEhtW/kQsZGtxqiKjADJoZQ2jZ5QRHFsG1gmY8LsKhwM3oinBqyLbdav4J
4 | qTSm/z7SHOgZd6k2b+ATDpC73gbu3iFKJu5klLqJkBakvXDHchgu2YDqFnsf5Ivy
5 | Cc8yWPNxSLnJIf+9QMh+FtfkNOcFbn5SLuBTgikIEnVCWwKmxeyN5KLY8s1EhsHm
6 | ahcoPbygdmnG2n7mNeU7pTQe5PlGxu9y/ImLwypmVc6CJ0UpDupyLvIcbBkUtXE3
7 | nKkbf7109N2VxeRR/4XAjVKaGT0fpzqAzbBs02JhETuStsR2kPYRffhwz1tv4IsN
8 | TMR8BnJ6R1/POIQYfdTOmU2SeT0PCYJS/6NMXO4l5BxXmaLKGAiXJKgTXqawLS+k
9 | 8xj2Xoomr5zDAG9tVegJvCerN3KYQDvec0jRbisE16ZytwqKQJEH80Ywuv4rjDkK
10 | nKAbg8PYr48n7+l+Tj8g7vnyHSkXaRRYl2XvlIR+52mtXZrd4YWTXrp2+EIv0CWm
11 | PyzKFVJSLBwuC0dHSiZw7qOnbrthX8eVttdiVresb1AE6i+KkazAj/rb6zSYVZuH
12 | n+mLymdCGNVLmMtInQHqi42+MtkqkR/QSk1/xJk4KiXEybiVpS0K1BECAwEAAQ==
13 | -----END RSA PUBLIC KEY-----
14 |
--------------------------------------------------------------------------------
/files/ssl/clients/heliotrope.example.net.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PUBLIC KEY-----
2 | MIICCgKCAgEAvwNw9s+mxC1eo1guOvlpyzPpnFUwfkCYhw8HFDBlaRHcmSZOq0jC
3 | bKbLekCG0FaTC8HuPc5cURBBsMsjx1d7Ct1F3QyGwtvWESGjwZoi2C4QUwTXaXUP
4 | +z/ILLs0pCUfsl+LQqXbc9xACjhmU+sr0JOeJE87IUQbTQxQ/HGh91LobhyJ+/32
5 | 8nI4wxjAuAtv1lxiyLTxdNca6qO4jPvkRZTyCb0L0NPOdim16MnxDUniakI0CXE5
6 | tAe6Bc4cu04ujp2m1TEiZS4foAf3QqkCiyfh2O17N58tq6Dua6oX4x4qpo+kCnXc
7 | IqyPa8pwycI9UpCqZ7KhOUQcQjpGXqE8/tZ6YkEkuc5/IMBhlfyQF+NMcv2GLFMJ
8 | 6Zdkjf8C24+uZKW0M2K5/XvjPoNUXiEx37v7LR8x4ioFs8Ei39bbTuVl9BfIHfCt
9 | fsQCKQ6kDLWfdSHP5aPYN+WnqK1ehPbekZ8ORo3y5B0zZ1VnBry2aWGN1bcjPV87
10 | RmhkcMTBS3LxtkXSZIY+zTm1D5J9WI27FRQt0+H/MpeqjbCc/44y6fwPuto8dZha
11 | PfQGRjdBOAKRVNUgoghWgwe7HO90p7TrfBjWHNs9JypUoIGnN/K5umdmbNQ7BLdm
12 | ycctTDAiyuYzZc4x0BFahHIuHXf6j4ht/hwv6LelcSt6m7KFvNHxZVUCAwEAAQ==
13 | -----END RSA PUBLIC KEY-----
14 |
--------------------------------------------------------------------------------
/files/ssl/clients/jorhett.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PUBLIC KEY-----
2 | MIICCgKCAgEA5qNcK2CIiE9JVCYbv2PCYTEsQB1SgtAOIK75jXwHwtuxyWE7K5Yb
3 | NaB7TF3Ji5K+tY1Qo+GI+HgrHdX/WQiFYUjWyHYHf1MFoCDPUtIPIdtH8fgof7Tq
4 | NAHsp/+RD3YT9gVGLzutA4GBIax6ruqP4Eixttyppkf3hLs5+rlXu0XD2+nU3LMc
5 | Tlv32vAoGBTCK7eIOwJUtux5EYrPqL8HgrVehaIhtD+lL48odgtvRmZJ/wz3UZ8R
6 | 7kch6g3CPA/MoYK249SslJDK08ljW7d5lhIfjnUeYfJo043rwpgBD8Qu9dQ6jAQ6
7 | JjI4ioM+2RRe5bCo9TiB1PQQdbl7F8YGm6hLB72QZvF4k8KVtEku6teJGkkzNniV
8 | XNqyclxwTvGnMJ8PxSdX9//8sOwauMMdZ60NOpeB/izIQjXjDV6krecErQWdEhAf
9 | pZHv2jGTUjDtp5FOhsjbvRwbidVfY/6847vMeX7UVOuA6YwOFN4NS7h8bTDCLDLn
10 | r63oFspIMMDk1L4cdJseSB61m4HItkk08jO/+bpuxE2b93VjSYaz1Yd1G1VOvU7f
11 | VV+wBNgNjCubpHoVzG5atUPmCCQuf8c/GNmEcKCNX4xYYNkyfkq0B5pY1QnoRRA6
12 | 7zdNN8xoQLgQIsBabX5ek/CtjB3OdYMvFiYP60E9JKbtk9hC3RI5qFUCAwEAAQ==
13 | -----END RSA PUBLIC KEY-----
14 |
--------------------------------------------------------------------------------
/files/ssl/clients/sunstone.example.net.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN PUBLIC KEY-----
2 | MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAoUM6EhGzuua/x0ibTcNi
3 | zIXRKQHZXDWjFZyqX0wEeWSt2tWiEo99768GnxcNyOLPb/tKMCZzobgYB82XlVxm
4 | EWjjTBpmCZpBF/FkJ1rv4nIldT1ur2ScWy6sin9umMuXTldPNJweHWB+27p3gxwq
5 | dwB+uvZuUmsjGD331wsR0fgg/VGfFY9d2/eyIit6URcBENxc2ROgKQvRBZ7lNnJI
6 | i530hMAaiRCkOs8QlXmcq52TOU+yXOduzfeviBR7FRiM+1Yx88OZkCGXYvMenamv
7 | fxyR2WDMviH4t3Ie9CJTfRiJT3q282nzRraeovuxpbUHIC9deQH5pHz/orSa9xbQ
8 | 9YNKB8yXU+BdAGaOEbuYdDYC+EEvIAHdi1xBsl01//Z/yTpoH/+daC1+x06cvF5E
9 | z2Y26Eeeb/O2ofYAknSPQDU2lrSrVweSV1JD1N7yAgtmQRa4NbzhVHYNjPOBa1g1
10 | aycA7LSi+U/7W3RINkvLoNfAFBb3A3ZFvsapo2hrEclQmjdoMuEcdafbqohIoRkh
11 | ThjbhHeDmB19cnVCLGA1SMTwYcHt1hp5uJoRlxPh8RO6yTmChGuqDxk9CtK7mu0B
12 | P7DV7QEFKQCipffeYdxOQBAJjNh6L0l1Ja3lvZpdKv5isVMSzqjsffxpRgxjvzKP
13 | uTrvO0WbmbBGr/OX4AZFHr0CAwEAAQ==
14 | -----END PUBLIC KEY-----
15 |
--------------------------------------------------------------------------------
/files/ssl/server/private.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIIEowIBAAKCAQEAotUs39Xh+D3zpp96ynmsxXOr+3sL2PQgjeseSFZ7cfux9q0w
3 | O2rb0LB2cRFPvcsE90elGuKMFDsHkt28huc+KR5s0V6Gz0nm0xo4PcPLbk+p7XyY
4 | fFMiXWAhUAXdOKppg+BnjttBcAFxmKCNOvvQcAPlbb7R/WWy89LnUSBDT3aN8ouV
5 | vYxgYrComcvZ/xzGcp1GBD3oINsmiF0bR9t1gV0c+alMgCWdthc1ZeEzpP7x8FVe
6 | KeazVCPaf98UpH5+1EC7UU2Ub85cMGYO4Qq7ZircZ8VtC7O609d6KdkvQ4gWdI7t
7 | vYBL9kBkjp+NoEWOfdF3opAkAgSZq5wHux3NewIDAQABAoIBAGra18LfuZVNGlpK
8 | p6q9ZCqC+OZj3ed2dPKMy2ePER1AnY2SI2eqfSua0W7rfFfBJbYcVvWom2IfRp4T
9 | Usd4cmtLYv+WN4NKLOZ1e1jU5uex8YI+VFapu5BpKBM6dezcr7dyCKNPsMaOu/v7
10 | yBJf822+sM1u/qB6H5Av48pyEJnQ14QYwPAdZdXcq8SyJOMTaJb/pKsJm4iLsB6p
11 | iBOallwDeHz0eARwJf5UnbFhHERe68KS0MGYSCUXXdFwh+zisPaF83Umtrhav6xp
12 | 03onTb8SP0plTQGE5CsE8gLhxavDGWzESIhBHjAQSMi6z7VCvZ1bOHgKlAzJynnV
13 | kh948wECgYEA14Os0uoEmM/nQwzMpX9v1eDB6Etf4Bo3K1vcjLa3BtuPbyG/sztE
14 | YfufEoOnPcCHp5eT2MLqP/fvRxIXNH6cr4EjsQYmwl+iwI3x6Gzx7COjTZdKpfs9
15 | zaThFNkXzW0stH8s1ewn9qNnakTJhT/l0SHIbFqMdP5kAJx4i5NwF/sCgYEAwWv7
16 | SQnc7Lo7JURvqyMYIPSSdKc0XQDRUs+JrX7VmOapwKy1mQBy2/AGw7JtyQaDZaXh
17 | GmvRwTeHY0xEGLZYlluXIGH8B1Z6jNLhZDkRLFHACgcXJ2IR/1nfnwm+Pe21xsh5
18 | IKRjQ/P9yfpJ/DWGa35ypI6fdeXGwgbPjgGfqIECgYBmLn9lrSEq1wA+UTZCja6X
19 | yK4Hlp1JowRfYXmrmgIjlTxno6fBsisVDfl5DMThyYRIGN03nAr283YWy2QHNrTR
20 | nbgvecwswq1nAKYe3nDB1o/Z/Q6ergW6mB9EBD593vKgTeATOZolHYqt3xlxPT+Y
21 | rZzaiwAnhGojxAx/mRM/uwKBgFEvdcXuceCbOoAl/YkjrdkHTwHPvNbcpP/RRMSh
22 | 3B3Vk6Lf20lhOtS+Jti1aAdcyII94gIpB13GZPl05ZBJ2V0jDIf3GMYrsjyxtxFO
23 | MrsbhTOwTjOlolA/9PDYMhXkVMwfEVh2J4Q6QWgpuiw2ezlbVdtkUeI2k/qUyUGd
24 | xNoBAoGBAJ51gN3TgEgk7jEGTX1sI1Cl0uenq43PwqoSb4UHjKDt9n0Tur4ns32N
25 | hoCKFjUmG0mxanrZYGTYkcmk3DNCVHPwBDy1Ww6PsOMnGzVlFQKN2pJS0zKbnpyB
26 | BfITdS8VjosySYeDn8znqlQ6L8r2QwSHudkj9+dvgKqTJ09Mo657
27 | -----END RSA PRIVATE KEY-----
28 |
--------------------------------------------------------------------------------
/files/ssl/server/public.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN PUBLIC KEY-----
2 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAotUs39Xh+D3zpp96ynms
3 | xXOr+3sL2PQgjeseSFZ7cfux9q0wO2rb0LB2cRFPvcsE90elGuKMFDsHkt28huc+
4 | KR5s0V6Gz0nm0xo4PcPLbk+p7XyYfFMiXWAhUAXdOKppg+BnjttBcAFxmKCNOvvQ
5 | cAPlbb7R/WWy89LnUSBDT3aN8ouVvYxgYrComcvZ/xzGcp1GBD3oINsmiF0bR9t1
6 | gV0c+alMgCWdthc1ZeEzpP7x8FVeKeazVCPaf98UpH5+1EC7UU2Ub85cMGYO4Qq7
7 | ZircZ8VtC7O609d6KdkvQ4gWdI7tvYBL9kBkjp+NoEWOfdF3opAkAgSZq5wHux3N
8 | ewIDAQAB
9 | -----END PUBLIC KEY-----
10 |
--------------------------------------------------------------------------------
/lib/facter/ssldir.rb:
--------------------------------------------------------------------------------
1 | # == Fact: ssldir
2 | #
3 | # A custom fact that gets the puppet client's SSLdir
4 | #
5 | Facter.add("ssldir") do
6 | setcode do
7 | Puppet[:ssldir]
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/manifests/client.pp:
--------------------------------------------------------------------------------
1 | # == Class: mcollective::client
2 | #
3 | # This module manages the MCollective client application
4 | #
5 | # === Parameters
6 | #
7 | # [*etcdir*]
8 | # Location of mcollective configuration files.
9 | # Defaults to $mcollective::etcdir which defaults to os-dependent location
10 | #
11 | # [*hosts*]
12 | # An array of middleware brokers for the client to connect
13 | # Defaults to $mcollective::hosts
14 | #
15 | # [*collectives*]
16 | # An array of collectives for the client to subscribe to
17 | # Defaults to $mcollective::collectives
18 | #
19 | # [*package*]
20 | # The name of the package to install or remove
21 | # Defaults to os-dependent value from mcollective::params
22 | #
23 | # [*version*]
24 | # The version or state of the package
25 | # Values: latest (default), present, absent, or specific version number
26 | #
27 | # [*unix_group*]
28 | # The unix group that will be allowed to read the client.cfg file.
29 | # This is security for the pre-shared-key when PSK is used.
30 | # Default: wheel
31 | #
32 | # [*logger_type*]
33 | # Where to send log messages. You usually want the user to see them.
34 | # Values: console (default), syslog, file
35 | #
36 | # [*log_level*]
37 | # How verbose should logging be?
38 | # Values: fatal, error, warn (default), info, debug
39 | #
40 | # [*logfacility*]
41 | # If logger_type is syslog, which log facility to use? Default: user
42 | #
43 | # [*logfile*]
44 | # If logger_type is file, what file should the logs be put in?
45 | # Default is os-dependent, often /var/log/mcollective.log
46 | #
47 | # [*keeplogs*]
48 | # Any positive value will enable log rotation retaining that many files.
49 | # A blank or 0 value will disable log rotation.
50 | # Default: 5
51 | #
52 | # [*max_log_size*]
53 | # Max size in bytes for log files before rotation happens.
54 | # Default: 2097152 (2mb)
55 | #
56 | # [*sshkey_known_hosts*]
57 | # Defines a known hosts file for use instead of ~/.ssh/known_hosts
58 | # Default: undefined (only matters if security_provider is sshkey)
59 | #
60 | # [*disc_method*]
61 | # Defines the default discovery method to use
62 | # Default: mc
63 | #
64 | # [*disc_options*]
65 | # Defines the default discovery options to use
66 | # Default: undefined
67 | #
68 | # [*da_threshold*]
69 | # Defines the threshold used to determine when to use direct addressing
70 | # Default: 10
71 | #
72 | # === Variables
73 | #
74 | # This class makes use of these variables from base mcollective class
75 | #
76 | # [*client_user*]
77 | # The username clients will use to authenticate. Default: client
78 | #
79 | # [*client_password*]
80 | # Required: The password clients will use to authenticate
81 | #
82 | # [*connector*]
83 | # Which middleware connector to use. Values: 'activemq' (default) or 'rabbitmq'
84 | #
85 | # [*port*]
86 | # Which port to connect to. Default: 61613
87 | #
88 | # [*connector_ssl*]
89 | # Use SSL service? Values: false (default), true
90 | #
91 | # [*connector_ssl_type*]
92 | # Which type of SSL encryption should be used? (ActiveMQ only) Values: anonymous (default), trusted
93 | #
94 | # [*security_provider*]
95 | # Values: psk (default), sshkey, ssl, aes_security
96 | #
97 | # [*psk_key*]
98 | # Pre-shared key if provider is psk
99 | #
100 | # [*psk_callertype*]
101 | # Valid to put in the 'caller' field of each request.
102 | # Values: uid (default), gid, user, group, identity
103 | #
104 | # === Examples
105 | #
106 | # class { 'mcollective::client':
107 | # hosts => ['activemq.example.net'],
108 | # collectives => ['mcollective'],
109 | # }
110 | #
111 | # Hiera
112 | # mcollective::hosts :
113 | # - 'activemq.example.net'
114 | # mcollective::collectives :
115 | # - 'mcollective'
116 | #
117 | class mcollective::client(
118 | # This value can be overridden in Hiera or through class parameters
119 | $unix_group = 'wheel',
120 | $etcdir = $mcollective::etcdir,
121 | $hosts = $mcollective::hosts,
122 | $collectives = $mcollective::collectives,
123 | $package = $mcollective::params::client_package_name,
124 |
125 | # Package update?
126 | $version = 'latest',
127 | $sshkey_known_hosts = undef,
128 |
129 | # Logging
130 | $logfile = $mcollective::params::logfile,
131 | $logger_type = 'console',
132 | $log_level = 'warn',
133 | $logfacility = 'user',
134 | $keeplogs = '5',
135 | $max_log_size = '2097152',
136 | $disc_method = 'mc',
137 | $disc_options = undef,
138 | $da_threshold = '10',
139 | )
140 | inherits mcollective {
141 |
142 | validate_array( $hosts )
143 | validate_array( $collectives )
144 | validate_re( $version, '^present$|^latest$|^[._0-9a-zA-Z:-]+$' )
145 | validate_re( $unix_group, '^[._0-9a-zA-Z-]+$' )
146 | validate_re( $da_threshold, '^[0-9]+$' )
147 |
148 | # Validate that client username and password were supplied
149 | validate_re( $client_user, '^.{5}', 'Please provide a client username' )
150 | validate_re( $client_password, '^.{12}', 'Please provide at last twelve characters in client password' )
151 |
152 | package { $package:
153 | ensure => $version,
154 | }
155 |
156 | file { "${etcdir}/client.cfg":
157 | ensure => file,
158 | owner => root,
159 | group => $unix_group,
160 | mode => '0440',
161 | content => template( 'mcollective/client.cfg.erb' ),
162 | require => Package[ $package ],
163 | }
164 |
165 | # Handle all per-user configurations
166 | $userdefaults = { group => 'wheel' }
167 | $userlist = hiera_hash( 'mcollective::userconfigs', false )
168 | if is_hash( $userlist ) {
169 | create_resources( mcollective::userconfig, $userlist, $userdefaults )
170 | }
171 |
172 | # Load in all the appropriate mcollective client plugins
173 | $defaults = { version => 'present' }
174 | $clients = hiera_hash( 'mcollective::plugin::clients', false )
175 | if is_hash( $clients ) {
176 | create_resources( mcollective::plugin::client, $clients, $defaults )
177 | }
178 |
179 | # Management of SSL keys
180 | if( $mcollective::security_provider == 'ssl' ) {
181 | # Ensure the package is installed before we create this directory
182 | Package[$package] -> File["${etcdir}/ssl"]
183 |
184 | # copy the server public keys to all servers
185 | realize File["${etcdir}/ssl/server/public.pem"]
186 | }
187 | }
188 |
--------------------------------------------------------------------------------
/manifests/facts.pp:
--------------------------------------------------------------------------------
1 | # == Class: mcollective::facts
2 | #
3 | # This module sets a positive value read by facts::cronjob
4 | #
5 | # === Example
6 | #
7 | # include mcollective::facts
8 | #
9 | # === DEPRECATED
10 | # use hiera value mcollective::facts::cronjob::run_every instead
11 | #
12 |
13 | # This looks weird, huh? Going away soon.
14 | class mcollective::facts inherits mcollective::facts::cronjob {
15 |
16 | # Just in case they define the variable and include the class both
17 | if( ! $mcollective::facts::cronjob::run_every ) {
18 | # Override to enable and set minutes
19 | Cron['mcollective-facts'] {
20 | ensure => present,
21 | minute => '*/10',
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/manifests/facts/cronjob.pp:
--------------------------------------------------------------------------------
1 | # == Class: mcollective::facts
2 | #
3 | # This module installs a cron script that puts Puppet facts in a file for MCollective to use
4 | #
5 | # === Example
6 | #
7 | # Hiera:
8 | # mcollective::facts::cronjob::run_every: 15 # every quarter hour
9 | #
10 | class mcollective::facts::cronjob(
11 | $run_every = 'unknown',
12 | )
13 | inherits mcollective {
14 |
15 | # if they passed in Hiera value use that.
16 | $enable = $run_every ? {
17 | 'unknown' => 'absent',
18 | undef => 'absent',
19 | '' => 'absent',
20 | default => 'present',
21 | }
22 |
23 | # Define the minute to be all if runevery wasn't defined
24 | $minute = $enable ? {
25 | 'absent' => '*',
26 | 'present' => "*/${run_every}",
27 | }
28 |
29 | # shorten for ease of use
30 | $yamlfile = "${mcollective::etcdir}/facts.yaml"
31 |
32 | cron { 'mcollective-facts':
33 | ensure => $enable,
34 | command => "facter --puppet --yaml > ${yamlfile}.new && ! diff -q ${yamlfile}.new ${yamlfile} > /dev/null && mv -f ${yamlfile}.new ${yamlfile}",
35 | minute => $minute,
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/manifests/init.pp:
--------------------------------------------------------------------------------
1 | # == Class: mcollective
2 | #
3 | # This module manages the MCollective ecosystem
4 | #
5 | # === Parameters:
6 | #
7 | # [*client_user*]
8 | # The username clients will use to authenticate. Default: client
9 | #
10 | # [*client_password*]
11 | # The password clients will use to authenticate
12 | # Required for mcollective::client and mcollective::middleware classes
13 | #
14 | # [*server_user*]
15 | # The username servers will use to authenticate. Default: server
16 | #
17 | # [*server_password*]
18 | # The password servers will use to authenticate.
19 | # Required for mcollective::server and mcollective::middleware classes
20 | #
21 | # [*broker_user*]
22 | # The username brokers will use to authenticate. Default: admin
23 | #
24 | # [*broker_password*]
25 | # The password brokers will use to authenticate to each other
26 | # Required if hosts > 1
27 | #
28 | # [*connector*]
29 | # Which middleware connector to use. Values: 'activemq' (default) or 'rabbitmq'
30 | #
31 | # [*hosts*]
32 | # An array of middleware brokers to connect
33 | #
34 | # [*port*]
35 | # Which port to connect to. Default: 61613
36 | #
37 | # [*connector_ssl*]
38 | # Use SSL for connection? (ActiveMQ only) Values: false (default), true
39 | # Should change port to 61614 if this is enabled
40 | #
41 | # [*connector_ssl_type*]
42 | # Which type of SSL encryption should be used? (ActiveMQ only) Values: anonymous (default), trusted
43 | #
44 | # [*collectives*]
45 | # An array of collectives to support. Default ['mcollective']
46 | #
47 | # [*security_provider*]
48 | # Values: psk (default), sshkey, ssl, aes_security
49 | #
50 | # [*psk_key*]
51 | # Pre-shared key if provider is psk
52 | #
53 | # [*psk_callertype*]
54 | # Valid to put in the 'caller' field of each request.
55 | # Values: uid (default), gid, user, group, identity
56 | #
57 | # [*registerinterval*]
58 | # How often to resend registration information in seconds. Default 600
59 | #
60 | # === Examples
61 | #
62 | # node default {
63 | # class { 'mcollective':
64 | # client_password => 'changeme',
65 | # server_password => 'changeme',
66 | # security_password => 'changeme',
67 | # }
68 | # }
69 | #
70 | # Hiera
71 | # mcollective::client_password : 'changeme',
72 | # mcollective::server_password : 'changeme',
73 | # mcollective::security_password : 'changeme',
74 | #
75 | class mcollective(
76 | # Puppet v3 will look for values in Hiera before falling back to defaults defined in params class
77 | # These values tend to be common based on operating system
78 | $etcdir = $mcollective::params::etcdir,
79 | $libdir = $mcollective::params::libdir,
80 | $logfile = $mcollective::params::logfile,
81 | $stomp_package = $mcollective::params::stomp_package,
82 | $stomp_version = 'latest',
83 |
84 | # Puppet v3 will look for values in Hiera before falling back to defaults defined here
85 | $server_user = 'server',
86 | $server_password = undef,
87 | $client_user = 'client',
88 | $client_password = undef,
89 | $broker_user = 'admin',
90 | $broker_password = undef,
91 | $connector = 'activemq',
92 | $connector_ssl = false,
93 | $connector_ssl_type = 'anonymous',
94 | $port = undef,
95 | $hosts, # array required - no default value
96 | $collectives = ['mcollective'],
97 | $registerinterval = 600,
98 | $security_provider = 'psk',
99 | $psk_key = undef, # will be checked if provider = psk
100 | $psk_callertype = 'uid',
101 | )
102 | inherits mcollective::params {
103 |
104 | # Ensure that someone can order against this main class
105 | #contain 'mcollective::client'
106 | #contain 'mcollective::server'
107 | #contain 'mcollective::facts'
108 | #contain 'mcollective::middleware'
109 |
110 | # The main module just presets variables used in client classes.
111 | validate_array( $hosts )
112 | validate_re( $connector, [ '^activemq$', '^rabbitmq$' ] )
113 | validate_re( $security_provider, [ '^psk$', '^sshkey$', '^ssl', '^aes_security' ] )
114 | validate_bool( $connector_ssl )
115 |
116 | if( $security_provider == 'psk' ) {
117 | validate_re( $psk_key, '^\S{20}', 'Please use a longer string of non-whitespace characters for the pre-shared key' )
118 | }
119 |
120 | # Set the appropriate default port based on whether SSL is enabled
121 | if( $port != undef ) {
122 | $_port = $port
123 | }
124 | else {
125 | $_port = $connector_ssl ? { true => 61614, default => 61613 }
126 | }
127 |
128 | # Ensure that the common dependency is up to date
129 | package { $stomp_package:
130 | ensure => $stomp_version,
131 | }
132 |
133 | # ensure the ssl directory exists for the lient and server modules
134 | if( ( $mcollective::security_provider == 'aes_security' ) or ( $mcollective::security_provider == 'ssl' ) ) {
135 | file { "${etcdir}/ssl":
136 | ensure => directory,
137 | owner => 0,
138 | group => 0,
139 | mode => '0555',
140 | }
141 | if( $mcollective::security_provider == 'ssl' ) {
142 | file { "${etcdir}/ssl/server":
143 | ensure => directory,
144 | owner => 0,
145 | group => 0,
146 | mode => '0555',
147 | }
148 | @file { "${etcdir}/ssl/server/public.pem":
149 | ensure => file,
150 | owner => 0,
151 | group => 0,
152 | mode => '0444',
153 | links => follow,
154 | replace => true,
155 | source => 'puppet:///modules/mcollective/ssl/server/public.pem',
156 | }
157 | }
158 | }
159 | }
160 |
--------------------------------------------------------------------------------
/manifests/middleware.pp:
--------------------------------------------------------------------------------
1 | # == Class: mcollective::middleware
2 | #
3 | # This module manages the MCollective middleware transport
4 | #
5 | # === Parameters
6 | #
7 | # [*directory*]
8 | # Location of activemq/rabbitmq configuration files
9 | # Defaults to $mcollective::params::activemq_directory which defaults to os-dependent location
10 | #
11 | # [*user*]
12 | # Owner of the middleware configuration files
13 | # Defaults to $mcollective::params::activemq_user_name which defaults to os-dependent value
14 | #
15 | # [*config_file*]
16 | # The middleware configuration file
17 | # Defaults to $mcollective::params::activemq_config_file which defaults to os-dependent value
18 | #
19 | # [*defaults_file*]
20 | # The middleware init defaults file
21 | # Defaults to $mcollective::params::activemq_defaults_file which defaults to os-dependent value
22 | #
23 | # [*package*]
24 | # The name of the package to install or remove
25 | # Defaults to os-dependent value from mcollective::params::activemq_package_name
26 | #
27 | # [*version*]
28 | # The version or state of the package: latest, present (default), absent, or specific version number
29 | #
30 | # [*max_connections*]
31 | # The maximum number of connections: default 1000
32 | #
33 | # [*service*]
34 | # The name of the service to manage
35 | # Defaults to os-dependent value from mcollective::params::activemq_service_name
36 | #
37 | # [*java_memory_size*]
38 | # The memory size allowed for JVM heap
39 | # Defaults to '512m'
40 | #
41 | # [*ensure*]
42 | # Should the service be running?
43 | # Values: running (default), stopped
44 | #
45 | # [*enable*]
46 | # Should the service start at boot?
47 | # Values: true (default), false
48 | #
49 | # [*truststore_password*]
50 | # Password for the TLS Truststore
51 | #
52 | # [*keystore_password*]
53 | # Password for the TLS Keystore
54 | #
55 | # [*jetty_password*]
56 | # admin password for (and enable) the ActiveMQ Jetty Web Admin
57 | # Default: null (disabled)
58 | #
59 | # [*use_jmx*]
60 | # Whether to enable the ActiveMQ JMX MBeans console
61 | # Values: true, false (default)
62 | #
63 | # === Variables
64 | #
65 | # This class makes use of these variables from base mcollective class
66 | #
67 | # [*connector*]
68 | # Which middleware connector to use. Values: 'activemq' (default) or 'rabbitmq'
69 | #
70 | # [*hosts*]
71 | # An array of middleware brokers for the client to connect
72 | # Defaults to $mcollective::hosts
73 | #
74 | # [*collectives*]
75 | # An array of collectives for the client to subscribe to
76 | # Defaults to $mcollective::collectives
77 | #
78 | # [*client_user*]
79 | # The username clients will use to authenticate. Default: client
80 | #
81 | # [*client_password*]
82 | # Required: The password clients will use to authenticate
83 | #
84 | # [*server_user*]
85 | # The username servers will use to authenticate. Default: server
86 | #
87 | # [*server_password*]
88 | # The password servers will use to authenticate.
89 | # Required: The password servers will use to authenticate
90 | #
91 | # [*broker_user*]
92 | # The username brokers will use to authenticate. Default: admin
93 | #
94 | # [*broker_password*]
95 | # The password brokers will use to authenticate to each other
96 | # Required if hosts > 1
97 | #
98 | # [*port*]
99 | # Which port to connect to. Default: 61613
100 | #
101 | # [*connector_ssl*]
102 | # Use SSL service? Values: false (default), true
103 | #
104 | # [*connector_ssl_type*]
105 | # Which type of SSL encryption should be used? (ActiveMQ only)
106 | # Values: anonymous (default), trusted
107 | #
108 | # [*registerinterval*]
109 | # How often to resend registration information in seconds. Default 600
110 | #
111 | # === Examples
112 | #
113 | # class { 'mcollective::middleware':
114 | # hosts => ['activemq.1.example.net','activemq.2.example.net'],
115 | # }
116 | #
117 | # Hiera
118 | # mcollective::middleware::hosts :
119 | # - activemq.1.example.net
120 | # - activemq.2.example.net
121 | #
122 | class mcollective::middleware(
123 | $version = 'present',
124 | $max_connections = '1000',
125 | $ensure = 'running',
126 | $enable = true,
127 | $use_jmx = false,
128 | $jetty_password = undef,
129 | $java_memory_size = '512m',
130 |
131 | # This allows override for just this class
132 | $hosts = $mcollective::hosts,
133 |
134 | # These are OS-specific
135 | $package = $mcollective::params::activemq_package_name,
136 | $service = $mcollective::params::activemq_service_name,
137 | $user = $mcollective::params::activemq_user_name,
138 | $directory = $mcollective::params::activemq_directory,
139 | $config_file = $mcollective::params::activemq_config_file,
140 | $defaults_file = $mcollective::params::activemq_defaults_file,
141 |
142 | # Truststore and Keystore passwords
143 | $keystore_password = undef, # will be checked if security_provider is either tls option
144 | $truststore_password = undef, # will be checked if security_provider is 'trusted'
145 | )
146 | inherits mcollective {
147 |
148 | # Make an array of hosts not including self
149 | validate_absolute_path( $directory )
150 | validate_array( $hosts )
151 | if( size($hosts) > 1 ) {
152 | $remotehostsF = reject($hosts, $::fqdn)
153 | $remotehostsH = reject($remotehostsF, $::hostname)
154 | $remotehosts = reject($remotehostsH, $::clientcert)
155 | if( size($remotehosts) > 0 ) {
156 | $brokernetwork = true
157 | validate_string( $mcollective::broker_user )
158 | validate_string( $mcollective::broker_password )
159 | if( $mcollective::broker_password == undef ) {
160 | validate_re( $mcollective::broker_password, '^\S{6,}+', 'Broker password must be at least 6 characters when multiple brokers are listed.' )
161 | }
162 | }
163 | }
164 | else {
165 | $remotehosts = []
166 | }
167 |
168 | # The main module just presets variables used in client classes.
169 | validate_re( $mcollective::connector, [ '^activemq$', '^rabbitmq$' ] )
170 | validate_bool( $mcollective::connector_ssl )
171 | validate_bool( $use_jmx )
172 |
173 | # Validate that client and server username and password were supplied
174 | validate_re( $client_user, '^.{5}', 'Please provide a client username' )
175 | validate_re( $client_password, '^.{12}', 'Please provide at last twelve characters in client password' )
176 | validate_re( $server_user, '^.{5}', 'Please provide a server username' )
177 | validate_re( $server_password, '^.{12}', 'Please provide at last twelve characters in server password' )
178 |
179 |
180 | # Main menu
181 | package { $package:
182 | ensure => $version,
183 | notify => Service[ $service ],
184 | }
185 |
186 | # If Jetty is enabled, store the password in the jetty realm properties file
187 | if( ( $mcollective::connector == 'activemq' ) and ( $jetty_password != '' ) and ( $jetty_password != undef ) ) {
188 | $use_jetty = true
189 |
190 | file { "${directory}/jetty-realm.properties":
191 | ensure => file,
192 | owner => $user,
193 | group => 'nobody',
194 | mode => '0440',
195 | content => template('mcollective/jetty-realm.properties.erb'),
196 | require => Package[ $package ],
197 | before => File["${directory}/${config_file}"],
198 | }
199 | }
200 |
201 | # Now build the main file
202 | file { "${directory}/${config_file}":
203 | ensure => file,
204 | owner => $user,
205 | group => 0,
206 | mode => '0400',
207 | require => Package[ $package ],
208 | content => template( "mcollective/${config_file}.erb" ),
209 | notify => Service[ $service ],
210 | }
211 |
212 | if( ( $mcollective::connector == 'activemq' ) and ( $defaults_file != '' ) ) {
213 | file { '/etc/sysconfig/activemq':
214 | ensure => file,
215 | owner => $user,
216 | group => 0,
217 | mode => '0444',
218 | require => Package[ $package ],
219 | content => template( 'mcollective/activemq.sysconfig.erb' ),
220 | notify => Service[ $service ],
221 | }
222 | }
223 |
224 | service { $service:
225 | ensure => $ensure,
226 | enable => $enable,
227 | require => Package[ $package ],
228 | }
229 |
230 | # Set up keystore and truststore if necessary
231 | if( $mcollective::connector_ssl == true ) {
232 | validate_re( $keystore_password, '^\S{6,}$', 'Keystore password must be at least 6 characters' )
233 | file { "${directory}/ssl":
234 | ensure => directory,
235 | owner => $user,
236 | group => 0,
237 | mode => '0500',
238 | require => Package[ $package ],
239 | }
240 | # Keystore
241 | Exec {
242 | path => ['/bin:/usr/bin:/usr/local/bin'],
243 | timeout => 20,
244 | }
245 | # I don't like it, but there's no easy way to build a template of local files.
246 | # These operations are protected by the directory being unreadable except by activemq user and root
247 | exec { 'mcollective-create-pem':
248 | cwd => "${directory}/ssl",
249 | command => "cat ${::ssldir}/certs/${clientcert}.pem ${::ssldir}/private_keys/${clientcert}.pem > ${directory}/ssl/combined.pem",
250 | creates => "${directory}/ssl/combined.pem",
251 | returns => [0],
252 | require => File["${directory}/ssl"],
253 | before => Exec['mcollective-create-p12'],
254 | }
255 | file { "${directory}/ssl/combined.pem":
256 | ensure => file,
257 | owner => 0,
258 | group => 0,
259 | mode => '0400',
260 | require => Exec['mcollective-create-pem'],
261 | }
262 | exec { 'mcollective-create-p12':
263 | cwd => "${directory}/ssl",
264 | command => "openssl pkcs12 -export -in combined.pem -out combined.p12 -name ${::clientcert} -passout pass:${keystore_password}",
265 | creates => "${directory}/ssl/combined.p12",
266 | returns => [0],
267 | require => File["${directory}/ssl/combined.pem"],
268 | before => Exec['mcollective-create-keystore'],
269 | }
270 | file { "${directory}/ssl/combined.p12":
271 | ensure => file,
272 | owner => 0,
273 | group => 0,
274 | mode => '0400',
275 | require => Exec['mcollective-create-p12'],
276 | }
277 | exec { 'mcollective-create-keystore':
278 | cwd => "${directory}/ssl",
279 | command => "keytool -noprompt -importkeystore -destkeystore keystore.jks -srcstoretype PKCS12 -srckeystore combined.p12 -alias '${::clientcert}' -storetype JKS -srcstorepass '${keystore_password}' -deststorepass '${keystore_password}'",
280 | creates => "${directory}/ssl/keystore.jks",
281 | returns => [0],
282 | require => File["${directory}/ssl"],
283 | before => File["${directory}/ssl/keystore.jks"],
284 | }
285 | file { "${directory}/ssl/keystore.jks":
286 | ensure => file,
287 | owner => $user,
288 | group => 0,
289 | mode => '0400',
290 | before => Service[ $service ],
291 | }
292 |
293 | # Truststore
294 | if( $brokernetwork or ( $mcollective::connector_ssl_type == 'trusted' ) ) {
295 | validate_re( $truststore_password, '^\S{6,}$', 'Truststore password must be at least 6 characters' )
296 | exec { 'mcollective-create-truststore':
297 | cwd => "${directory}/ssl",
298 | command => "keytool -noprompt -importcert -alias '${::clientcert}' -file ${::ssldir}/certs/ca.pem -keystore ${directory}/ssl/truststore.jks -storetype JKS -storepass '${truststore_password}'",
299 | creates => "${directory}/ssl/truststore.jks",
300 | returns => [0],
301 | require => File["${directory}/ssl"],
302 | before => File["${directory}/ssl/truststore.jks"],
303 | }
304 | file { "${directory}/ssl/truststore.jks":
305 | ensure => file,
306 | owner => $user,
307 | group => 0,
308 | mode => '0400',
309 | before => Service[ $service ],
310 | }
311 | }
312 |
313 | }
314 | }
315 |
--------------------------------------------------------------------------------
/manifests/params.pp:
--------------------------------------------------------------------------------
1 | # == Class: mcollective::params
2 | #
3 | # OS-specific parameter defaults
4 | #
5 | class mcollective::params {
6 | # Default locations for certain os combinations
7 | $etcdir = $::clientversion ? {
8 | /(?:4\.)/ => '/etc/puppetlabs/mcollective',
9 | default => $::osfamily ? {
10 | /(?i-mx:redhat)/ => '/etc/mcollective',
11 | /(?i-mx:debian)/ => '/etc/mcollective',
12 | /(?i-mx:freebsd)/ => '/usr/local/etc/mcollective',
13 | default => '/etc/puppetlabs/mcollective',
14 | }
15 | }
16 |
17 | $logrotate_directory = $::osfamily ? {
18 | /(?i-mx:freebsd)/ => '/usr/local/etc/logrotate.d',
19 | default => '/etc/logrotate.d',
20 | }
21 |
22 | $libdir = $::osfamily ? {
23 | /(?i-mx:redhat)/ => '/usr/libexec/mcollective',
24 | /(?i-mx:debian)/ => '/usr/share/mcollective/plugins',
25 | /(?i-mx:freebsd)/ => '/usr/local/share',
26 | default => '/usr/libexec/mcollective',
27 | }
28 |
29 | # Stomp Package
30 | $stomp_package = $::osfamily ? {
31 | /(?i-mx:redhat)/ => 'rubygem-stomp',
32 | /(?i-mx:debian)/ => 'ruby-stomp',
33 | /(?i-mx:freebsd)/ => 'devel/rubygem-stomp',
34 | default => 'rubygem-stomp',
35 | }
36 |
37 | # Package and service names
38 | $package_name = $::osfamily ? {
39 | /(?i-mx:redhat)/ => 'mcollective',
40 | /(?i-mx:debian)/ => 'mcollective',
41 | /(?i-mx:freebsd)/ => 'sysutils/mcollective',
42 | default => 'mcollective',
43 | }
44 |
45 | $client_package_name = $::osfamily ? {
46 | /(?i-mx:redhat)/ => 'mcollective-client',
47 | /(?i-mx:debian)/ => 'mcollective-client',
48 | /(?i-mx:freebsd)/ => 'sysutils/mcollective-client',
49 | default => 'mcollective-client',
50 | }
51 |
52 | $service_name = $::osfamily ? {
53 | /(?i-mx:redhat)/ => 'mcollective',
54 | /(?i-mx:debian)/ => 'mcollective',
55 | /(?i-mx:freebsd)/ => 'mcollectived',
56 | default => 'mcollective-client',
57 | }
58 |
59 | # Logfile locations (all platforms seem identical for this for now)
60 | $logfile = '/var/log/mcollective.log'
61 |
62 | # These appear to be the same for all platforms
63 | $activemq_config_file = 'activemq.xml'
64 | $activemq_service_name = 'activemq'
65 | $activemq_user_name = 'activemq'
66 |
67 | $activemq_package_name = $::osfamily ? {
68 | /(?i-mx:redhat)/ => 'activemq',
69 | /(?i-mx:debian)/ => 'activemq',
70 | /(?i-mx:freebsd)/ => 'net/activemq',
71 | default => 'activemq',
72 | }
73 |
74 | $activemq_directory = $::osfamily ? {
75 | /(?i-mx:redhat)/ => '/etc/activemq',
76 | /(?i-mx:debian)/ => '/etc/activemq',
77 | /(?i-mx:freebsd)/ => '/usr/local/etc/activemq',
78 | default => '/etc/activemq',
79 | }
80 |
81 | $activemq_defaults_file = $::osfamily ? {
82 | /(?i-mx:redhat)/ => '/etc/sysconfig/activemq',
83 | /(?i-mx:debian)/ => '/etc/default/activemq',
84 | /(?i-mx:freebsd)/ => undef,
85 | default => undef,
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/manifests/plugin/actionpolicy.pp:
--------------------------------------------------------------------------------
1 | # == Type: mcollective::plugin::actionpolicy
2 | #
3 | # This defined type creates an actionpolicy file for one agent
4 | #
5 | # === Parameters
6 | #
7 | # [*agent*]
8 | # Name of the agent
9 | #
10 | # [*default*]
11 | # Allow (default) or Deny
12 | #
13 | # [*rules*]
14 | # A hash of rules to implement
15 | #
16 | # === Examples
17 | #
18 | # mcollective::plugin::actionpolicy { 'puppet':
19 | # default => 'deny',
20 | # }
21 | #
22 | # Hiera
23 | # puppet:
24 | # default: deny
25 | # rules:
26 | # 'get out of jail free':
27 | # policy : allow
28 | # caller : *
29 | # actions: *
30 | # facts : *
31 | # classes: *
32 | #
33 | define mcollective::plugin::actionpolicy(
34 | $agent = $name,
35 | $default = 'allow',
36 | $rules = {},
37 | ) {
38 |
39 | # The template iterates through the rules
40 | file { "${mcollective::etcdir}/policies/${agent}.policy":
41 | ensure => present,
42 | owner => 0,
43 | group => 0,
44 | mode => '0440',
45 | replace => true,
46 | content => template( 'mcollective/agent.policy.erb' ),
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/manifests/plugin/agent.pp:
--------------------------------------------------------------------------------
1 | # == Type: mcollective::plugin::agent
2 | #
3 | # This defined type loads one agent
4 | #
5 | # === Parameters
6 | #
7 | # [*version*]
8 | # 'latest' (default) or a specific version of an agent
9 | #
10 | # [*dependencies*]
11 | # Other packages this agent depends on
12 | #
13 | # === Examples
14 | #
15 | # mcollective::plugin::agent { 'puppet':
16 | # version => 'latest',
17 | # }
18 | #
19 | # Hiera (plural version implemented in mcollective::server)
20 | #
21 | # mcollective::plugin::agents:
22 | # puppet:
23 | # version: latest
24 | #
25 | define mcollective::plugin::agent(
26 | $version = 'latest',
27 | $dependencies = [],
28 | ) {
29 | package { "mcollective-${name}-agent":
30 | ensure => $version,
31 | require => [ Package[$mcollective::server::package], $dependencies],
32 | notify => Service[ $mcollective::service_name ],
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/manifests/plugin/client.pp:
--------------------------------------------------------------------------------
1 | # == Type: mcollective::plugin::client
2 | #
3 | # This defined type loads one client application
4 | #
5 | # === Parameters
6 | #
7 | # [*version*]
8 | # 'latest' (default) or a specific version of an client
9 | #
10 | # [*dependencies*]
11 | # Other packages this client depends on
12 | #
13 | # === Examples
14 | #
15 | # mcollective::plugin::client: { 'puppet':
16 | # version => 'latest',
17 | # }
18 | #
19 | # Hiera (plural version implemented in mcollective::client)
20 | #
21 | # mcollective::plugin::clients:
22 | # puppet:
23 | # version: latest
24 | #
25 | define mcollective::plugin::client (
26 | $version = 'latest',
27 | $dependencies = [],
28 | ) {
29 | package { "mcollective-${name}-client":
30 | ensure => $version,
31 | require => [ Package[$mcollective::client::package], $dependencies],
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/manifests/server.pp:
--------------------------------------------------------------------------------
1 | # == Class: mcollective::server
2 | #
3 | # This module manages the MCollective server agent
4 | #
5 | # === Parameters
6 | #
7 | # [*etcdir*]
8 | # Location of mcollective configuration files.
9 | # Defaults to $mcollective::etcdir which defaults to os-dependent location
10 | #
11 | # [*libdir*]
12 | # Location of mcollective ruby lib directory.
13 | # Defaults to an os-dependent location in mcollective::params
14 | #
15 | # [*hosts*]
16 | # An array of middleware brokers for the server to connect
17 | # Defaults to $mcollective::hosts
18 | #
19 | # [*collectives*]
20 | # An array of collectives for the server to subscribe to
21 | # Defaults to $mcollective::collectives
22 | #
23 | # [*package*]
24 | # The name of the package to install or remove
25 | # Defaults to os-dependent value from mcollective::params
26 | #
27 | # [*version*]
28 | # The version or state of the package
29 | # Values: latest (default) , present, absent, or specific version number
30 | #
31 | # [*service*]
32 | # The name of the service to manage
33 | # Defaults to os-dependent value from mcollective::params
34 | #
35 | # [*ensure*]
36 | # Should the service be running?
37 | # Values: running (default), stopped
38 | #
39 | # [*enable*]
40 | # Should the service start at boot?
41 | # Values: true (default), false
42 | #
43 | # [*allow_managed_resources*]
44 | # Allow management of Puppet RAL-style resources?
45 | # Values: true (default), false
46 | #
47 | # [*resource_type_whitelist*]
48 | # Which resources are allowed to be managed?
49 | # Default: none
50 | #
51 | # [*resource_type_blacklist*]
52 | # If whitelist is empty, which resources should be blocked?
53 | # Default: null
54 | #
55 | # [*audit_logfile*]
56 | # If this logfile is specified then auditing is enabled.
57 | #
58 | # [*authorization_enable*]
59 | # Where or not to enable authorization
60 | # Values: false (default), true
61 | #
62 | # [*authorization_default_policy*]
63 | # What authorization policy should be applied to agents with a specific policy?
64 | #
65 | # [*logger_type*]
66 | # Where to send log messages. You usually want the user to see them.
67 | # Values: syslog (default), file, console
68 | #
69 | # [*log_level*]
70 | # How verbose should logging be?
71 | # Values: fatal, error, warn, info (default), debug
72 | #
73 | # [*logfacility*]
74 | # If logger_type is syslog, which log facility to use? Default: user
75 | #
76 | # [*logfile*]
77 | # If logger_type is file, what file should the logs be put in?
78 | # Default is os-dependent, often /var/log/mcollective.log
79 | #
80 | # [*keeplogs*]
81 | # Any positive value will enable log rotation retaining that many files.
82 | # A blank or 0 value will disable log rotation.
83 | # Default: 5
84 | #
85 | # [*max_log_size*]
86 | # Max size in bytes for log files before rotation happens.
87 | # Default: 2097152 (2mb)
88 | #
89 | # [*logrotate_directory*]
90 | # Directory where logrotate files are stored.
91 | # Default: /etc/logrotate.d
92 | # Nil or Undef value will disable logrotate installation
93 | #
94 | # [*sshkey_authorized_keys*]
95 | # Defines a authorized keys file for use instead of ~/.ssh/authorized_keys
96 | # Default: undefined (only matters if security_provider is sshkey)
97 | #
98 | # === Variables
99 | #
100 | # This class makes use of these variables from base mcollective class
101 | #
102 | # [*server_user*]
103 | # The username servers will use to authenticate. Default: server
104 | #
105 | # [*server_password*]
106 | # The password servers will use to authenticate.
107 | # Required: The password servers will use to authenticate
108 | #
109 | # [*connector*]
110 | # Which middleware connector to use. Values: 'activemq' (default) or 'rabbitmq'
111 | #
112 | # [*port*]
113 | # Which port to connect to. Default: 61613
114 | #
115 | # [*connector_ssl*]
116 | # Use SSL connection to the service? Values: false (default), true
117 | #
118 | # [*connector_ssl_type*]
119 | # Which type of SSL encryption should be used? (ActiveMQ only)
120 | # Values: anonymous (default), trusted
121 | #
122 | # [*security_provider*]
123 | # Values: psk (default), ssl, aes_security, sshkey
124 | #
125 | # [*psk_key*]
126 | # Pre-shared key if provider is psk
127 | #
128 | # [*registerinterval*]
129 | # How often to resend registration information in seconds. Default 600
130 | #
131 | # === Examples
132 | #
133 | # class { 'mcollective::server':
134 | # authorization_enable => true,
135 | # }
136 | #
137 | # Hiera
138 | # mcollective::server::authorization_enable : true,
139 | #
140 | class mcollective::server(
141 | # Package and Service defaults that are OS-specific, can override in Hiera
142 | $package = $mcollective::params::package_name,
143 | $service = $mcollective::params::service_name,
144 | $libdir = $mcollective::params::libdir,
145 | $etcdir = $mcollective::etcdir,
146 |
147 | # Connector settings
148 | # These values can be overridden for a given server in Hiera
149 | $version = 'latest',
150 | $ensure = 'running',
151 | $enable = true,
152 | $hosts = $mcollective::hosts,
153 | $collectives = $mcollective::collectives,
154 |
155 | # Authorization
156 | $allow_managed_resources = true,
157 | $resource_type_whitelist = 'none',
158 | $resource_type_blacklist = undef,
159 | $audit_logfile = undef,
160 | $authorization_enable = undef,
161 | $authorization_default_policy = undef,
162 | $ssh_authorized_keys = undef,
163 |
164 | # Logging
165 | $logrotate_directory = $mcollective::params::logrotate_directory,
166 | $logfile = $mcollective::params::logfile,
167 | $logger_type = 'syslog',
168 | $log_level = 'info',
169 | $logfacility = 'user',
170 | $keeplogs = '5',
171 | $max_log_size = '2097152',
172 | )
173 | inherits mcollective {
174 |
175 | validate_array( $hosts )
176 | validate_array( $collectives )
177 | validate_re( $version, '^present$|^latest$|^[._0-9a-zA-Z:-]+$' )
178 | validate_re( $ensure, '^running$|^stopped$' )
179 | validate_bool( $enable )
180 |
181 | # Validate that server username and password were supplied
182 | validate_re( $server_user, '^.{5}', 'Please provide a server username' )
183 | validate_re( $server_password, '^.{12}', 'Please provide at last twelve characters in server password' )
184 |
185 | # Ensure the facts cronjob is set up or removed
186 | include mcollective::facts::cronjob
187 |
188 | # Now install the packages
189 | package { $package:
190 | ensure => $version,
191 | notify => Service[ $service ],
192 | }
193 |
194 | file { "${etcdir}/server.cfg":
195 | ensure => file,
196 | owner => 0,
197 | group => 0,
198 | mode => '0400',
199 | content => template( 'mcollective/server.cfg.erb' ),
200 | require => Package[ $package ],
201 | notify => Service[ $service ],
202 | }
203 |
204 | # Management of SSL keys
205 | if( ( $mcollective::security_provider == 'aes_security' ) or ( $mcollective::security_provider == 'ssl' ) ) {
206 | Package[$package] -> File["${etcdir}/ssl"]
207 |
208 | # copy client public keys to all servers
209 | file { "${etcdir}/ssl/clients":
210 | ensure => directory,
211 | owner => 0,
212 | group => 0,
213 | mode => '0644',
214 | links => follow,
215 | purge => true,
216 | force => true,
217 | recurse => true,
218 | source => 'puppet:///modules/mcollective/ssl/clients',
219 | require => Package[ $package ],
220 | before => Service[ $service ],
221 | }
222 |
223 | # For SSL module One keypair is shared across all servers
224 | if( $mcollective::security_provider == 'ssl' ) {
225 | # Get the public key
226 | realize File["${etcdir}/ssl/server/public.pem"]
227 |
228 | # ...and the private key
229 | file { "${etcdir}/ssl/server/private.pem":
230 | ensure => file,
231 | owner => 0,
232 | group => 0,
233 | mode => '0400',
234 | links => follow,
235 | replace => true,
236 | source => 'puppet:///modules/mcollective/ssl/server/private.pem',
237 | require => [ Package[ $package ], File["${etcdir}/ssl/server/public.pem"] ],
238 | before => Service[ $service ],
239 | }
240 | }
241 | }
242 |
243 | # Policies used by the authorization plugins
244 | if( $authorization_enable ) {
245 | # Copy any files from the policies directory
246 | file { "${etcdir}/policies":
247 | ensure => directory,
248 | owner => 0,
249 | group => 0,
250 | mode => '0444',
251 | links => follow,
252 | recurse => true,
253 | replace => true,
254 | force => true,
255 | purge => false,
256 | source => 'puppet:///modules/mcollective/policies',
257 | require => Package[ $package ],
258 | before => Service[ $service ],
259 | }
260 |
261 | file { "${libdir}/mcollective/util":
262 | ensure => directory,
263 | owner => 0,
264 | group => 0,
265 | mode => '0755',
266 | require => Package[ $package ],
267 | before => Service[ $service ],
268 | }
269 |
270 | file { "${libdir}/mcollective/util/actionpolicy.rb":
271 | ensure => file,
272 | owner => 0,
273 | group => 0,
274 | mode => '0444',
275 | source => 'puppet:///modules/mcollective/actionpolicy-auth/util/actionpolicy.rb',
276 | require => File["${etcdir}/server.cfg"],
277 | before => Service[ $service ],
278 | }
279 |
280 | file { "${libdir}/mcollective/util/actionpolicy.ddl":
281 | ensure => file,
282 | owner => 0,
283 | group => 0,
284 | mode => '0444',
285 | source => 'puppet:///modules/mcollective/actionpolicy-auth/util/actionpolicy.ddl',
286 | require => File["${etcdir}/server.cfg"],
287 | before => Service[ $service ],
288 | }
289 |
290 | # Create rules from YAML for the ActionPolicy module
291 | $actionpolicies = hiera_hash( 'mcollective::plugin::actionpolicies', false )
292 | if is_hash( $actionpolicies ) {
293 | create_resources( mcollective::plugin::actionpolicy, $actionpolicies )
294 | }
295 | }
296 |
297 | # Now start the daemon
298 | service { $service:
299 | ensure => $ensure,
300 | enable => $enable,
301 | require => Package[ $package ],
302 | }
303 |
304 | # Load in all the appropriate mcollective agents
305 | $defaults = { version => 'present' }
306 | $agents = hiera_hash( 'mcollective::plugin::agents', false )
307 | if is_hash( $agents ) {
308 | create_resources( mcollective::plugin::agent, $agents, $defaults )
309 | }
310 |
311 | # Create or remove a logrotate config for the audit log
312 | if( $audit_logfile == undef ) {
313 | $auditlog_ensure = absent
314 | }
315 | else {
316 | $auditlog_ensure = file
317 | }
318 |
319 | # Only install logrotate if the logrotate directory is installed
320 | if( $logrotate_directory ) {
321 | file { 'logrotate-directory':
322 | ensure => directory,
323 | path => $logrotate_directory,
324 | owner => 0,
325 | group => 0,
326 | mode => '0755',
327 | }
328 | file { 'logrotate-auditlog':
329 | ensure => $auditlog_ensure,
330 | path => "${logrotate_directory}/mcollective-auditlog",
331 | owner => 0,
332 | group => 0,
333 | mode => '0444',
334 | content => template( 'mcollective/logrotate-auditlog.erb' ),
335 | }
336 | }
337 | }
338 |
--------------------------------------------------------------------------------
/manifests/userconfig.pp:
--------------------------------------------------------------------------------
1 | # == Type: mcollective::userconfig
2 | #
3 | # This module manages the MCollective client application
4 | #
5 | # === Parameters
6 | #
7 | # [*user*]
8 | # The user who should own the file to be created.
9 | # Default: $title
10 | #
11 | # [*group*]
12 | # The group who should own the file to be created.
13 | # Default: wheel
14 | #
15 | # [*homedir*]
16 | # The home directory of the user
17 | # Defaults to /home/$user
18 | #
19 | # [*filename*]
20 | # The name of the file to be created, relative to $homedir
21 | # Defaults to .mcollective
22 | #
23 | # [*hosts*]
24 | # An array of middleware brokers for the client to connect
25 | # Defaults to $mcollective::hosts
26 | #
27 | # [*collectives*]
28 | # An array of collectives for the client to subscribe to
29 | # Defaults to $mcollective::collectives
30 | #
31 | # [*logger_type*]
32 | # Where to send log messages. You usually want the user to see them.
33 | # Values: console (default), syslog, file
34 | #
35 | # [*log_level*]
36 | # How verbose should logging be?
37 | # Values: fatal, error, warn (default), info, debug
38 | #
39 | # === Variables
40 | #
41 | # This class makes use of these variables from base mcollective class
42 | #
43 | # [*client_user*]
44 | # The username clients will use to authenticate.
45 | # Default: client
46 | #
47 | # [*client_password*]
48 | # Required: The password clients will use to authenticate
49 | #
50 | # [*connector*]
51 | # Which middleware connector to use. Values: 'activemq' (default) or 'rabbitmq'
52 | #
53 | # [*port*]
54 | # Which port to connect to.
55 | #
56 | # [*connector_ssl*]
57 | # Use SSL service? Values: false, true
58 | #
59 | # [*connector_ssl_type*]
60 | # Which type of SSL encryption should be used? (ActiveMQ only)
61 | #
62 | # [*security_provider*]
63 | # Values: psk, sshkey, ssl, aes_security
64 | #
65 | # [*psk_key*]
66 | # Pre-shared key if provider is psk
67 | #
68 | # [*psk_callertype*]
69 | # Valid to put in the 'caller' field of each request.
70 | # Values: uid (default), gid, user, group, identity
71 | #
72 | # === Examples
73 | #
74 | # mcollective::userconfig { 'jorhett':
75 | # group => 'staff',
76 | # }
77 | #
78 | # Hiera
79 | # mcollective::userconfigs:
80 | # jill:
81 | # group: staff
82 | # jack: {}
83 | #
84 | define mcollective::userconfig(
85 | $user = $title,
86 | $group = 'wheel',
87 | $homedir = 'unknown',
88 | $filename = '.mcollective',
89 |
90 | # This value can be overridden in Hiera or through class parameters
91 | $etcdir = $mcollective::etcdir,
92 | $hosts = $mcollective::hosts,
93 | $collectives = $mcollective::collectives,
94 |
95 | # Logging
96 | $logger_type = $mcollective::client::logger_type,
97 | $log_level = $mcollective::client::log_level,
98 | ) {
99 |
100 | validate_array( $hosts )
101 | validate_array( $collectives )
102 | validate_re( $user, '^[._0-9a-zA-Z-]+$' )
103 | validate_re( $group, '^[._0-9a-zA-Z-]+$' )
104 |
105 | if( $homedir == 'unknown' ) {
106 | $homepath = "/home/${user}"
107 | }
108 | else {
109 | $homepath = $homedir
110 | }
111 | $private_key = "${homepath}/.mcollective.d/private_keys/${user}.pem"
112 | $public_key = "${homepath}/.mcollective.d/public_keys/${user}.pem"
113 |
114 | # Stubs for SSL trusted, must be created by user
115 | $ssl_private = "${homepath}/.puppet/ssl/private_keys/${user}.pem"
116 | $ssl_cert = "${homepath}/.puppet/ssl/certs/${user}.pem"
117 | $ca_cert = "${homepath}/.puppet/ssl/certs/ca.pem"
118 |
119 | file {[
120 | "${homepath}/.mcollective.d",
121 | "${homepath}/.mcollective.d/private_keys",
122 | "${homepath}/.mcollective.d/public_keys",
123 | "${homepath}/.mcollective.d/certs",
124 | ]:
125 | ensure => 'directory',
126 | owner => $user,
127 | group => $group,
128 | }
129 |
130 | exec { "create-private-${user}":
131 | path => '/usr/bin:/usr/local/bin',
132 | command => "openssl genrsa -out ${private_key} 2048",
133 | unless => "/usr/bin/test -e ${private_key}",
134 | }
135 |
136 | exec { "create-public-${user}":
137 | path => '/usr/bin:/usr/local/bin',
138 | command => "openssl rsa -in ${private_key} -out ${public_key}",
139 | unless => "/usr/bin/test -e ${public_key}",
140 | require => Exec["create-private-${user}"],
141 | }
142 |
143 | file { "${homepath}/${filename}":
144 | ensure => file,
145 | owner => $user,
146 | group => $group,
147 | mode => '0440',
148 | content => template( 'mcollective/userconfig.erb' ),
149 | }
150 | }
151 |
--------------------------------------------------------------------------------
/metadata.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "jorhett-mcollective",
3 | "version": "1.0.4",
4 | "author": "Jo Rhett",
5 | "license": "BSD-3-Clause",
6 | "summary": "Configures MCollective servers, clients, and middleware brokers; handles networks of brokers, subcollectives, and TLS security options",
7 | "source": "https://github.com/jorhett/puppet-mcollective",
8 | "project_page": "https://github.com/jorhett/puppet-mcollective",
9 | "issues_url": "https://github.com/jorhett/puppet-mcollective/issues",
10 | "tags": [
11 | "mcollective",
12 | "activemq",
13 | "deprecated"
14 | ],
15 | "operatingsystem_support": [
16 | {
17 | "operatingsystem":"RedHat",
18 | "operatingsystemrelease":[ "6","7" ]
19 | },
20 | {
21 | "operatingsystem":"CentOS",
22 | "operatingsystemrelease":[ "6","7" ]
23 | },
24 | {
25 | "operatingsystem":"OracleLinux",
26 | "operatingsystemrelease":[ "6","7" ]
27 | },
28 | {
29 | "operatingsystem":"Scientific",
30 | "operatingsystemrelease":[ "6","7" ]
31 | },
32 | {
33 | "operatingsystem":"Debian",
34 | "operatingsystemrelease":[ "6","7" ]
35 | },
36 | {
37 | "operatingsystem": "Ubuntu",
38 | "operatingsystemrelease": [ "15.04", "14.10", "14.04", "13.10", "13.04", "12.10", "12.04" ]
39 | },
40 | {
41 | "operatingsystem": "FreeBSD",
42 | "operatingsystemrelease": [ "10.1", "10.0", "9.3" ]
43 | }
44 | ],
45 | "requirements": [
46 | { "name": "pe", "version_requirement": ">= 3.3.0 <= 5.0.0" },
47 | { "name": "puppet", "version_requirement": ">= 3.5.0 <= 5.0.0" }
48 | ],
49 | "dependencies": [
50 | { "name": "puppetlabs/stdlib", "version_requirement": ">= 3.2.0 <= 5.0.0" }
51 | ]
52 | }
53 |
--------------------------------------------------------------------------------
/spec/classes/client_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe 'mcollective::client' do
4 | let(:pre_condition) do
5 | 'class { "mcollective":
6 | hosts => ["middleware.example.net"],
7 | client_password => "fakeTestingClientPassword",
8 | server_password => "fakeTestingServerPassword",
9 | psk_key => "fakeTestingPreSharedKey",
10 | }'
11 | end
12 |
13 | context 'with defaults for all parameters' do
14 | it do
15 | should contain_package('mcollective-client')
16 | end
17 |
18 | it do
19 | should compile.with_all_deps
20 | end
21 | end
22 |
23 | context "With a package name specified" do
24 | let :params do
25 | {
26 | :package => 'mcollective-client'
27 | }
28 | end
29 |
30 | it do
31 | should contain_package('mcollective-client').with( { 'name' => 'mcollective-client' } )
32 | end
33 | end
34 |
35 | context "On a RedHat OS with no package name specified" do
36 | let :facts do
37 | {
38 | :osfamily => 'RedHat',
39 | }
40 | end
41 |
42 | it do
43 | should contain_package('mcollective-client').with({
44 | 'name' => 'mcollective-client',
45 | 'ensure' => 'latest',
46 | })
47 | end
48 | end
49 |
50 | context "On a Debian OS with no package name specified" do
51 | let :facts do
52 | {
53 | :osfamily => 'Debian'
54 | }
55 | end
56 |
57 | it do
58 | should contain_package('mcollective-client').with({
59 | 'name' => 'mcollective-client',
60 | 'ensure' => 'latest',
61 | })
62 | end
63 | end
64 |
65 | context "On a FreeBSD OS with no package name specified" do
66 | let :facts do
67 | {
68 | :osfamily => 'FreeBSD'
69 | }
70 | end
71 |
72 | it do
73 | should contain_package('sysutils/mcollective-client').with({
74 | 'name' => 'sysutils/mcollective-client'
75 | })
76 | end
77 | end
78 |
79 | context "On an unknown OS with no stomp package name specified" do
80 | let :facts do
81 | {
82 | :osfamily => 'Darwin'
83 | }
84 | end
85 |
86 | it do
87 | should contain_package('rubygem-stomp').with({ 'name' => 'rubygem-stomp' })
88 | end
89 | end
90 | end
91 |
--------------------------------------------------------------------------------
/spec/classes/facts/cronjob_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe 'mcollective::facts::cronjob' do
4 | let(:pre_condition) do
5 | 'class { "mcollective":
6 | hosts => ["middleware.example.net"],
7 | client_password => "fakeTestingClientPassword",
8 | server_password => "fakeTestingServerPassword",
9 | psk_key => "fakeTestingPreSharedKey",
10 | }'
11 | end
12 |
13 | context 'with defaults for all parameters' do
14 | it do
15 | should contain_cron('mcollective-facts')
16 | end
17 |
18 | it do
19 | should compile.with_all_deps
20 | end
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/spec/classes/init_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe 'mcollective' do
4 | let(:params) do
5 | {
6 | :hosts => ['middleware.example.net'],
7 | :client_password => 'fakeTestingClientPassword',
8 | :server_password => 'fakeTestingServerPassword',
9 | :psk_key => 'fakeTestingPreSharedKey',
10 | }
11 | end
12 |
13 | context 'with defaults for all parameters' do
14 | it do
15 | should contain_class('mcollective')
16 | should contain_class('mcollective::params')
17 | end
18 |
19 | it do
20 | should compile.with_all_deps
21 | end
22 | end
23 |
24 | # Now test for failures
25 | context "Without a list of hosts" do
26 | let(:params) do {
27 | :hosts => nil,
28 | :client_password => 'fakeTestingClientPassword',
29 | :server_password => 'fakeTestingServerPassword',
30 | :psk_key => 'fakeTestingPreSharedKey',
31 | } end
32 |
33 | it do
34 | expect { should raise_error(Puppet::Error) }
35 | end
36 | end
37 |
38 | context "Without a client password" do
39 | let(:params) do {
40 | :hosts => ['middleware.example.net'],
41 | :client_password => nil,
42 | :server_password => 'fakeTestingServerPassword',
43 | :psk_key => 'fakeTestingPreSharedKey',
44 | } end
45 |
46 | it do
47 | expect { should raise_error(Puppet::Error) }
48 | end
49 | end
50 |
51 | context "Without a server password" do
52 | let(:params) do {
53 | :hosts => ['middleware.example.net'],
54 | :client_password => 'fakeTestingClientPassword',
55 | :server_password => nil,
56 | :psk_key => 'fakeTestingPreSharedKey',
57 | } end
58 |
59 | it do
60 | expect { should raise_error(Puppet::Error) }
61 | end
62 | end
63 |
64 | context "Without a pre-shared key" do
65 | let(:params) do {
66 | :hosts => ['middleware.example.net'],
67 | :client_password => 'fakeTestingClientPassword',
68 | :server_password => 'fakeTestingServerPassword',
69 | :psk_key => nil,
70 | } end
71 |
72 | it do
73 | expect { should raise_error(Puppet::Error) }
74 | end
75 | end
76 |
77 | #at_exit { RSpec::Puppet::Coverage.report! }
78 | end
79 |
--------------------------------------------------------------------------------
/spec/classes/middleware_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe 'mcollective::middleware' do
4 | let(:pre_condition) do
5 | 'class { "mcollective":
6 | hosts => ["middleware.example.net"],
7 | client_password => "fakeTestingClientPassword",
8 | server_password => "fakeTestingServerPassword",
9 | psk_key => "fakeTestingPreSharedKey",
10 | }'
11 | end
12 |
13 | let(:params) do
14 | {
15 | }
16 | end
17 |
18 | context 'with defaults for all parameters' do
19 | it do
20 | should compile.with_all_deps
21 | end
22 | end
23 |
24 | # Now test for failures
25 | context "Without a list of hosts" do
26 | let(:params) do {
27 | :hosts => nil,
28 | :client_password => 'fakeTestingClientPassword',
29 | :server_password => 'fakeTestingServerPassword',
30 | :psk_key => 'fakeTestingPreSharedKey',
31 | } end
32 |
33 | it do
34 | expect { should raise_error(Puppet::Error) }
35 | end
36 | end
37 |
38 | context 'with defaults for all parameters' do
39 | it do
40 | should contain_package('activemq')
41 | end
42 |
43 | it do
44 | should compile.with_all_deps
45 | end
46 | end
47 |
48 | context "With the rabbitmq package name specified" do
49 | let :params do
50 | {
51 | :package => 'rabbitmq'
52 | }
53 | end
54 |
55 | it do
56 | should contain_package('rabbitmq').with( { 'name' => 'rabbitmq' } )
57 | end
58 | end
59 | end
60 |
--------------------------------------------------------------------------------
/spec/classes/server_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe 'mcollective::server' do
4 | let(:pre_condition) {
5 | 'class { "mcollective":
6 | hosts => ["middleware.example.net"],
7 | client_password => "fakeTestingClientPassword",
8 | server_password => "fakeTestingServerPassword",
9 | psk_key => "fakeTestingPreSharedKey",
10 | }'
11 | }
12 |
13 | context 'with defaults for all parameters' do
14 | it do
15 | should contain_package('mcollective')
16 | end
17 |
18 | it do
19 | should compile.with_all_deps
20 | end
21 | end
22 |
23 | context "With a package name specified" do
24 | let :params do
25 | {
26 | :package => 'mcollectived'
27 | }
28 | end
29 |
30 | it do
31 | should contain_package('mcollectived').with({
32 | 'name' => 'mcollectived'
33 | })
34 | end
35 | end
36 |
37 | context "With an undefined logrotate directory" do
38 | let :params do
39 | {
40 | :logrotate_directory => '',
41 | }
42 | end
43 |
44 | it do
45 | should_not contain_file('logrotate-directory')
46 | end
47 | end
48 |
49 | context "On a RedHat OS with no package name specified" do
50 | let :facts do
51 | {
52 | :osfamily => 'RedHat',
53 | }
54 | end
55 |
56 | it do
57 | should contain_package('mcollective').with({
58 | 'name' => 'mcollective',
59 | 'ensure' => 'latest',
60 | })
61 | should contain_service('mcollective').with({
62 | 'name' => 'mcollective',
63 | 'ensure' => 'running',
64 | })
65 | should contain_file('logrotate-directory').with({
66 | 'path' => '/etc/logrotate.d',
67 | })
68 | end
69 | end
70 |
71 | context "On a Debian OS with no package name specified" do
72 | let :facts do
73 | {
74 | :osfamily => 'Debian'
75 | }
76 | end
77 |
78 | it do
79 | should contain_package('mcollective').with({
80 | 'name' => 'mcollective',
81 | 'ensure' => 'latest',
82 | })
83 | should contain_service('mcollective').with({
84 | 'name' => 'mcollective',
85 | 'ensure' => 'running',
86 | })
87 | end
88 | end
89 |
90 | context "On a FreeBSD OS with no package name specified" do
91 | let :facts do
92 | {
93 | :osfamily => 'FreeBSD'
94 | }
95 | end
96 |
97 | it do
98 | should contain_package('sysutils/mcollective').with({
99 | 'name' => 'sysutils/mcollective',
100 | })
101 | should contain_service('mcollectived').with({
102 | 'name' => 'mcollectived',
103 | 'ensure' => 'running',
104 | })
105 | end
106 | end
107 |
108 | context "On an unknown OS with no stomp package name specified" do
109 | let :facts do
110 | {
111 | :osfamily => 'Darwin'
112 | }
113 | end
114 |
115 | it do
116 | should contain_package('rubygem-stomp').with({ 'name' => 'rubygem-stomp' })
117 | end
118 | end
119 | end
120 |
--------------------------------------------------------------------------------
/spec/spec_helper.rb:
--------------------------------------------------------------------------------
1 | require 'rubygems'
2 | require 'puppetlabs_spec_helper/module_spec_helper'
3 |
--------------------------------------------------------------------------------
/templates/activemq.sysconfig.erb:
--------------------------------------------------------------------------------
1 | ACTIVEMQ_OPTS_MEMORY="-Xms<%= @java_memory_size -%> -Xmx<%= @java_memory_size -%>"
2 |
--------------------------------------------------------------------------------
/templates/activemq.xml.erb:
--------------------------------------------------------------------------------
1 |
17 |
22 |
23 |
24 |
25 |
26 |
32 | useJmx="true"
33 | populateJMSXUserID="true"
34 | <% end -%>
35 | >
36 |
37 |
38 |
39 |
40 |
47 |
51 |
52 |
53 |
54 |
59 |
60 |
61 |
62 |
63 |
66 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
85 |
86 |
88 | createConnector="true"
89 | connectorHost="localhost"
90 | rmiServerPort="1098"
91 | connectorPort="1099"
92 | <% else -%>
93 | createConnector="false"
94 | <% end -%>
95 | />
96 |
97 |
98 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 | <% if( @brokernetwork == true ) then -%>
112 |
113 | <% end -%>
114 |
115 |
116 |
117 |
118 |
119 |
120 |
144 |
145 |
146 |
147 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 | <%-
168 | # DoS protection, limit concurrent connections (default 1000) and frame size to 100MB
169 | dos_params = 'maximumConnections=' + @max_connections
170 | dos_params += '&wireFormat.maxFrameSize=104857600'
171 | ssl_connector_params = dos_params
172 | if( scope.lookupvar('mcollective::connector_ssl_type') == 'trusted' ) then
173 | ssl_connector_params = 'needClientAuth=true&' + dos_params
174 | end
175 | -%>
176 | <% if( scope.lookupvar('mcollective::connector_ssl') ) then -%>
177 |
178 |
182 |
183 | <% if( @brokernetwork == true ) then -%>
184 |
188 | <% end -%>
189 |
190 |
191 |
192 |
195 | trustStore="ssl/truststore.jks" trustStorePassword="<%= @truststore_password -%>"
196 | <% end -%>
197 | />
198 |
199 | <% else -%>
200 |
201 |
202 |
206 | <% if( @brokernetwork == true ) then -%>
207 |
211 | <% end -%>
212 |
213 | <% end # brokernetwork -%>
214 |
215 |
216 | <%- @remotehosts.each do |remotehost| -%>
217 |
220 | uri="static:(ssl://<%= remotehost -%>:61617?wireFormat.tightEncodingEnabled=false&wireFormat.maxInactivityDuration=0)"
221 | <% else -%>
222 | uri="static:(tcp://<%= remotehost -%>:61616?wireFormat.tightEncodingEnabled=false&wireFormat.maxInactivityDuration=0)"
223 | <% end -%>
224 | userName="<%= scope.lookupvar('mcollective::broker_user') -%>"
225 | password="<%= scope.lookupvar('mcollective::broker_password') -%>"
226 | duplex="false"
227 | decreaseNetworkConsumerPriority="true"
228 | suppressDuplicateTopicSubscriptions="true"
229 | networkTTL="2"
230 | dynamicOnly="true"
231 | conduitSubscriptions="true"
232 | >
233 |
234 |
235 |
236 |
237 |
240 | uri="static:(ssl://<%= remotehost -%>:61617?wireFormat.tightEncodingEnabled=false&wireFormat.maxInactivityDuration=0)"
241 | <% else -%>
242 | uri="static:(tcp://<%= remotehost -%>:61616?wireFormat.tightEncodingEnabled=false&wireFormat.maxInactivityDuration=0)"
243 | <% end -%>
244 | userName="<%= scope.lookupvar('mcollective::broker_user') -%>"
245 | password="<%= scope.lookupvar('mcollective::broker_password') -%>"
246 | duplex="false"
247 | decreaseNetworkConsumerPriority="true"
248 | suppressDuplicateTopicSubscriptions="true"
249 | networkTTL="2"
250 | dynamicOnly="true"
251 | conduitSubscriptions="false"
252 | >
253 |
254 |
255 |
256 |
257 | <% end -%>
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 | <% if( @use_jetty ) then -%>
266 |
270 |
271 | <% end -%>
272 |
273 |
--------------------------------------------------------------------------------
/templates/agent.policy.erb:
--------------------------------------------------------------------------------
1 | # /etc/mcollective/policies/<%= @agent -%>.policy
2 | <% if( @default ) then -%>
3 | policy default <%= @default %>
4 | <% end -%>
5 | <% @rules.sort.map do |comment, rule| -%>
6 | # <%= comment %>
7 | <%= rule['policy'] %> <%= rule['caller'] %> <%= rule['actions'] %> <%= rule['facts'] %> <%= rule['classes'] %>
8 | <% end -%>
9 |
--------------------------------------------------------------------------------
/templates/client.cfg.erb:
--------------------------------------------------------------------------------
1 | # Connector
2 | libdir = <%= scope.lookupvar('mcollective::libdir') %>
3 | <% if( scope.lookupvar('::clientversion').to_f >= 4.0 ) then -%>
4 | libdir = /opt/puppetlabs/mcollective/plugins
5 | <% end -%>
6 | direct_addressing = 1
7 | <% if( @collectives ) then -%>
8 | main_collective = <%= @collectives[0] %>
9 | collectives = <%= @collectives.join(',') %>
10 | <% end -%>
11 |
12 | connector = <%= scope.lookupvar('mcollective::connector') %>
13 | <% if( scope.lookupvar('mcollective::connector') == 'rabbitmq' ) then -%>
14 | plugin.rabbitmq.vhost = /mcollective
15 | <% elsif( scope.lookupvar('mcollective::connector') == 'activemq' ) then -%>
16 | plugin.activemq.heartbeat_interval = 30
17 | <% end -%>
18 | plugin.<%= scope.lookupvar('mcollective::connector') -%>.pool.size = <%= @hosts.length %>
19 | <% @hosts.each_with_index do |mqhost, index| -%>
20 | plugin.<%= scope.lookupvar('mcollective::connector') -%>.pool.<%= index+1 -%>.host = <%= mqhost %>
21 | plugin.<%= scope.lookupvar('mcollective::connector') -%>.pool.<%= index+1 -%>.port = <%= scope.lookupvar('mcollective::_port') %>
22 | plugin.<%= scope.lookupvar('mcollective::connector') -%>.pool.<%= index+1 -%>.user = <%= scope.lookupvar('mcollective::client_user') %>
23 | plugin.<%= scope.lookupvar('mcollective::connector') -%>.pool.<%= index+1 -%>.password = <%= scope.lookupvar('mcollective::client_password') %>
24 | <% if( scope.lookupvar('mcollective::connector') == 'activemq' ) then -%>
25 | plugin.<%= scope.lookupvar('mcollective::connector') -%>.pool.<%= index+1 -%>.ssl = <%= scope.lookupvar('mcollective::connector_ssl') %>
26 | <% if( scope.lookupvar('mcollective::connector_ssl_type') != 'trusted' ) then -%>
27 | plugin.<%= scope.lookupvar('mcollective::connector') -%>.pool.<%= index+1 -%>.ssl.fallback = true
28 | <% end -%>
29 | <% end -%>
30 | <% end -%>
31 |
32 | # Security provider
33 | <% if( scope.lookupvar('mcollective::security_provider') == 'psk' ) then -%>
34 | securityprovider = psk
35 | plugin.psk = <%= scope.lookupvar('mcollective::psk_key') %>
36 | plugin.psk.callertype = <%= scope.lookupvar('mcollective::psk_callertype') %>
37 | <% elsif( scope.lookupvar('mcollective::security_provider') == 'sshkey' ) then -%>
38 | securityprovider = sshkey
39 | <% if( @sshkey_known_hosts ) then -%>
40 | plugin.sshkey.client.known_hosts = <%= @sshkey_known_hosts %>
41 | <% end -%>
42 | <% elsif( scope.lookupvar('mcollective::security_provider') == 'ssl' ) then -%>
43 | securityprovider = ssl
44 | plugin.ssl_server_public = <%= scope.lookupvar('mcollective::etcdir') -%>/ssl/server/public.pem
45 | <% elsif( scope.lookupvar('mcollective::security_provider') == 'aes_security' ) then -%>
46 | securityprovider = aes_security
47 | <% end -%>
48 |
49 | # Discovery
50 | default_discovery_method = <%= scope.lookupvar('disc_method') %>
51 | <% if( scope.lookupvar('da_threshold') != '' ) then -%>
52 | direct_addressing_threshold = <%= scope.lookupvar('da_threshold') %>
53 | <% end -%>
54 | <% if( scope.lookupvar('disc_options') != '' ) then -%>
55 | default_discovery_options = <%= scope.lookupvar('disc_options') %>
56 | <% end -%>
57 |
58 | # Miscellaneous settings
59 | color = 1
60 | rpclimitmethod = first
61 |
62 | # Performance settings
63 | direct_addressing_threshold = 10
64 | ttl = 60
65 |
66 | # Logging
67 | logger_type = <%= @logger_type %>
68 | loglevel = <%= @log_level %>
69 | <% if( @logger_type == 'syslog' ) then -%>
70 | logfacility = <%= @logfacility %>
71 | <% end -%>
72 | <% if( @logger_type == 'file' ) then -%>
73 | logfile = <%= @logfile %>
74 | <% if( @keeplogs ) then -%>
75 | keeplogs = <%= @keeplogs %>
76 | <% end -%>
77 | <% if( @max_log_size ) then -%>
78 | max_log_size = <%= @max_log_size %>
79 | <% end -%>
80 | <% end -%>
81 |
--------------------------------------------------------------------------------
/templates/jetty-realm.properties.erb:
--------------------------------------------------------------------------------
1 | ## ---------------------------------------------------------------------------
2 | ## Licensed to the Apache Software Foundation (ASF) under one or more
3 | ## contributor license agreements. See the NOTICE file distributed with
4 | ## this work for additional information regarding copyright ownership.
5 | ## The ASF licenses this file to You under the Apache License, Version 2.0
6 | ## (the "License"); you may not use this file except in compliance with
7 | ## the License. You may obtain a copy of the License at
8 | ##
9 | ## http://www.apache.org/licenses/LICENSE-2.0
10 | ##
11 | ## Unless required by applicable law or agreed to in writing, software
12 | ## distributed under the License is distributed on an "AS IS" BASIS,
13 | ## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | ## See the License for the specific language governing permissions and
15 | ## limitations under the License.
16 | ## ---------------------------------------------------------------------------
17 |
18 | # Defines users that can access the web (console, demo, etc.)
19 | # username: password [,rolename ...]
20 | admin: <%= @jetty_password -%>, admin
21 | # user: user, user
22 |
--------------------------------------------------------------------------------
/templates/logrotate-auditlog.erb:
--------------------------------------------------------------------------------
1 | # This doesn't specify a time interval or a size, so as to inherit any site-specific policy
2 | <%= @audit_logfile -%> {
3 | missingok
4 | notifempty
5 | delaycompress
6 | create 0600 root
7 | }
8 |
--------------------------------------------------------------------------------
/templates/rabbitmq.config.erb:
--------------------------------------------------------------------------------
1 | [
2 | {rabbit, [
3 | <% if( scope.lookupvar('mcollective::connector_ssl') == 'true' ) then -%>
4 | {ssl_options, [
5 | {cacertfile,"<%= scope.lookupvar('::ssldir') -%>/ca/ca.pem"},
6 | {certfile,"<%= scope.lookupvar('::ssldir') -%>/certs/<%= scope.lookupvar('::clientcert') -%>.pem"},
7 | {keyfile,"<%= scope.lookupvar('::ssldir') -%>/private_keys/<%= scope.lookupvar('::clientcert') -%>.pem"},
8 | {verify,verify_peer},
9 | {fail_if_no_peer_cert,false}
10 | ]}
11 | <% end -%>
12 | ]},
13 | {rabbitmq_stomp, [
14 | <% if( @connector_ssl ) then -%>
15 | {ssl_listeners, [<%= @_port -%>]}
16 | <% else -%>
17 | {tcp_listeners, [<%= @_port -%>]}
18 | <% end -%>
19 | ]}
20 | ].
21 |
--------------------------------------------------------------------------------
/templates/server.cfg.erb:
--------------------------------------------------------------------------------
1 | # /etc/mcollective/server.cfg
2 | libdir = <%= scope.lookupvar('mcollective::libdir') %>
3 | <% if( scope.lookupvar('::clientversion').to_f >= 4.0 ) then -%>
4 | libdir = /opt/puppetlabs/mcollective/plugins
5 | classesfile = /opt/puppetlabs/puppet/cache/state/classes.txt
6 | <% end -%>
7 | daemonize = 1
8 | direct_addressing = 1
9 | <% if( @collectives ) then -%>
10 | main_collective = <%= @collectives[0] %>
11 | collectives = <%= @collectives.join(',') %>
12 | <% end -%>
13 |
14 | # ActiveMQ connector settings:
15 | connector = <%= scope.lookupvar('mcollective::connector') %>
16 | <% if( scope.lookupvar('mcollective::connector') == 'rabbitmq' ) then -%>
17 | plugin.rabbitmq.vhost = /mcollective
18 | <% elsif( scope.lookupvar('mcollective::connector') == 'activemq' ) then -%>
19 | plugin.activemq.heartbeat_interval = 30
20 | <% end -%>
21 | plugin.<%= scope.lookupvar('mcollective::connector') -%>.pool.size = <%= @hosts.length %>
22 | <% @hosts.each_with_index do |mqhost, index| -%>
23 | plugin.<%= scope.lookupvar('mcollective::connector') -%>.pool.<%= index+1 -%>.host = <%= mqhost %>
24 | plugin.<%= scope.lookupvar('mcollective::connector') -%>.pool.<%= index+1 -%>.port = <%= scope.lookupvar('mcollective::_port') %>
25 | plugin.<%= scope.lookupvar('mcollective::connector') -%>.pool.<%= index+1 -%>.user = <%= scope.lookupvar('mcollective::server_user') %>
26 | plugin.<%= scope.lookupvar('mcollective::connector') -%>.pool.<%= index+1 -%>.password = <%= scope.lookupvar('mcollective::server_password') %>
27 | <% if( scope.lookupvar('mcollective::connector') == 'activemq' ) then -%>
28 | plugin.<%= scope.lookupvar('mcollective::connector') -%>.pool.<%= index+1 -%>.ssl = <%= scope.lookupvar('mcollective::connector_ssl') %>
29 | <% if( scope.lookupvar('mcollective::connector_ssl_type') == 'trusted' ) then -%>
30 | plugin.<%= scope.lookupvar('mcollective::connector') -%>.pool.<%= index+1 -%>.ssl.key = <%= scope.lookupvar('::ssldir') -%>/private_keys/<%= scope.lookupvar('clientcert') -%>.pem
31 | plugin.<%= scope.lookupvar('mcollective::connector') -%>.pool.<%= index+1 -%>.ssl.cert = <%= scope.lookupvar('::ssldir') -%>/certs/<%= scope.lookupvar('clientcert') -%>.pem
32 | plugin.<%= scope.lookupvar('mcollective::connector') -%>.pool.<%= index+1 -%>.ssl.ca = <%= scope.lookupvar('::ssldir') -%>/certs/ca.pem
33 | <% else -%>
34 | plugin.<%= scope.lookupvar('mcollective::connector') -%>.pool.<%= index+1 -%>.ssl.fallback = true
35 | <% end -%>
36 | <% end -%>
37 | <% end -%>
38 |
39 | # Send these messages to keep the Stomp connection alive.
40 | # This solves NAT and firewall timeout problems.
41 | registerinterval = <%= scope.lookupvar('mcollective::registerinterval') %>
42 |
43 | # Security provider
44 | <% if( scope.lookupvar('mcollective::security_provider') == 'psk' ) then -%>
45 | securityprovider = psk
46 | plugin.psk = <%= scope.lookupvar('mcollective::psk_key') %>
47 | <% elsif( scope.lookupvar('mcollective::security_provider') == 'sshkey' ) then -%>
48 | securityprovider = sshkey
49 | <% if( @sshkey_authorized_keys ) then -%>
50 | plugin.sshkey.server.known_hosts = <%= @sshkey_authorized_keys %>
51 | <% end -%>
52 | <% elsif( scope.lookupvar('mcollective::security_provider') == 'ssl' ) then -%>
53 | securityprovider = ssl
54 | plugin.ssl_server_private = <%= scope.lookupvar('mcollective::etcdir') -%>/ssl/server/private.pem
55 | plugin.ssl_server_public = <%= scope.lookupvar('mcollective::etcdir') -%>/ssl/server/public.pem
56 | plugin.ssl_client_cert_dir = <%= scope.lookupvar('mcollective::etcdir') -%>/ssl/clients
57 | <% elsif( scope.lookupvar('mcollective::security_provider') == 'aes_security' ) then -%>
58 | securityprovider = aes_security
59 | plugin.aes.server_public = <%= scope.lookupvar('::ssldir') -%>/public_keys/<%= scope.lookupvar('clientcert') -%>.pem
60 | plugin.aes.server_private = <%= scope.lookupvar('::ssldir') -%>/private_keys/<%= scope.lookupvar('clientcert') -%>.pem
61 | plugin.aes.client_cert_dir = <%= scope.lookupvar('mcollective::etcdir') -%>/ssl/clients
62 | plugin.aes.enforce_ttl = true
63 | <% end -%>
64 |
65 | # Facts
66 | factsource = yaml
67 | plugin.yaml = <%= scope.lookupvar('mcollective::etcdir') %>/facts.yaml
68 |
69 | # Puppet resource control
70 | plugin.puppet.resource_allow_managed_resources = <%= @allow_managed_resources %>
71 | <% if( @resource_type_whitelist ) then -%>
72 | plugin.puppet.resource_type_whitelist = <%= @resource_type_whitelist %>
73 | <% else -%>
74 | plugin.puppet.resource_type_blacklist = <%= @resource_type_blacklist %>
75 | <% end -%>
76 |
77 | <% if( @audit_logfile ) then -%>
78 | # Auditing
79 | rpcaudit = 1
80 | rpcauditprovider = Logfile
81 | plugin.rpcaudit.logfile = <%= @audit_logfile %>
82 | <% end -%>
83 |
84 | <% if( @authorization_enable ) then -%>
85 | # Authorization policy
86 | rpcauthorization = 1
87 | rpcauthprovider = action_policy
88 | <% if( @authorization_default_policy ) then -%>
89 | plugin.actionpolicy.enable_default = 1
90 | plugin.actionpolicy.default_name = <%= @authorization_default_policy -%>
91 | <% else -%>
92 | plugin.actionpolicy.allow_unconfigured = 1
93 | <% end -%>
94 | <% end -%>
95 |
96 | # Logging
97 | logger_type = <%= @logger_type %>
98 | loglevel = <%= @log_level %>
99 | <% if( @logger_type == 'syslog' ) then -%>
100 | logfacility = <%= @logfacility %>
101 | <% end -%>
102 | <% if( @logger_type == 'file' ) then -%>
103 | logfile = <%= @logfile %>
104 | <% if( @keeplogs ) then -%>
105 | keeplogs = <%= @keeplogs %>
106 | <% end -%>
107 | <% if( @max_log_size ) then -%>
108 | max_log_size = <%= @max_log_size %>
109 | <% end -%>
110 | <% end -%>
111 |
--------------------------------------------------------------------------------
/templates/userconfig.erb:
--------------------------------------------------------------------------------
1 | # Connector
2 | libdir = <%= scope.lookupvar('mcollective::libdir') %>
3 | direct_addressing = 1
4 | <% if( @collectives ) then -%>
5 | main_collective = <%= @collectives[0] %>
6 | collectives = <%- @collectives.each do |collective| -%><%= collective -%>,<% end -%>
7 | <% end -%>
8 |
9 | connector = <%= scope.lookupvar('mcollective::connector') %>
10 | <% if( scope.lookupvar('mcollective::connector') == 'rabbitmq' ) then -%>
11 | plugin.rabbitmq.vhost = /mcollective
12 | <% elsif( scope.lookupvar('mcollective::connector') == 'activemq' ) then -%>
13 | plugin.activemq.heartbeat_interval = 30
14 | <% end -%>
15 | plugin.<%= scope.lookupvar('mcollective::connector') -%>.pool.size = <%= @hosts.length %>
16 | <% @hosts.each_with_index do |mqhost, index| -%>
17 | plugin.<%= scope.lookupvar('mcollective::connector') -%>.pool.<%= index+1 -%>.host = <%= mqhost %>
18 | plugin.<%= scope.lookupvar('mcollective::connector') -%>.pool.<%= index+1 -%>.port = <%= scope.lookupvar('mcollective::_port') %>
19 | plugin.<%= scope.lookupvar('mcollective::connector') -%>.pool.<%= index+1 -%>.user = <%= scope.lookupvar('mcollective::client_user') %>
20 | plugin.<%= scope.lookupvar('mcollective::connector') -%>.pool.<%= index+1 -%>.password = <%= scope.lookupvar('mcollective::client_password') %>
21 | <% if( scope.lookupvar('mcollective::connector') == 'activemq' ) then -%>
22 | plugin.<%= scope.lookupvar('mcollective::connector') -%>.pool.<%= index+1 -%>.ssl = <%= scope.lookupvar('mcollective::connector_ssl') %>
23 | <% if( scope.lookupvar('mcollective::connector_ssl_type') == 'trusted' ) then -%>
24 | plugin.<%= scope.lookupvar('mcollective::connector') -%>.pool.<%= index+1 -%>.ssl.key = <%= scope.lookupvar('ssl_private') %>
25 | plugin.<%= scope.lookupvar('mcollective::connector') -%>.pool.<%= index+1 -%>.ssl.cert = <%= scope.lookupvar('ssl_cert') %>
26 | plugin.<%= scope.lookupvar('mcollective::connector') -%>.pool.<%= index+1 -%>.ssl.ca = <%= scope.lookupvar('ca_cert') %>
27 | <% else -%>
28 | plugin.<%= scope.lookupvar('mcollective::connector') -%>.pool.<%= index+1 -%>.ssl.fallback = true
29 | <% end -%>
30 | <% end -%>
31 | <% end -%>
32 |
33 | # Security provider
34 | <% if( scope.lookupvar('mcollective::security_provider') == 'psk' ) then -%>
35 | securityprovider = psk
36 | plugin.psk = <%= scope.lookupvar('mcollective::psk_key') %>
37 | plugin.psk.callertype = <%= scope.lookupvar('mcollective::psk_callertype') %>
38 | <% elsif( scope.lookupvar('mcollective::security_provider') == 'sshkey' ) then -%>
39 | securityprovider = sshkey
40 | <% if( @sshkey_known_hosts ) then -%>
41 | plugin.sshkey.client.known_hosts = <%= @sshkey_known_hosts %>
42 | <% end -%>
43 | <% elsif( scope.lookupvar('mcollective::security_provider') == 'ssl' ) then -%>
44 | securityprovider = ssl
45 | plugin.ssl_server_public = <%= scope.lookupvar('mcollective::etcdir') -%>/ssl/server/public.pem
46 | plugin.ssl_client_private = <%= scope.lookupvar('private_key') %>
47 | plugin.ssl_client_public = <%= scope.lookupvar('public_key') %>
48 | <% elsif( scope.lookupvar('mcollective::security_provider') == 'aes_security' ) then -%>
49 | securityprovider = aes_security
50 | plugin.aes_client_private = <%= scope.lookupvar('private_key') %>
51 | plugin.aes_client_public = <%= scope.lookupvar('public_key') %>
52 | <% end -%>
53 |
54 | # Discovery
55 | default_discovery_method = <%= scope.lookupvar('disc_method') %>
56 | <% if( scope.lookupvar('da_threshold') != '' ) then -%>
57 | direct_addressing_threshold = <%= scope.lookupvar('da_threshold') %>
58 | <% end -%>
59 | <% if( scope.lookupvar('disc_options') != '' ) then -%>
60 | default_discovery_options = <%= scope.lookupvar('disc_options') %>
61 | <% end -%>
62 |
63 | # Miscellaneous settings
64 | color = 1
65 | rpclimitmethod = first
66 |
67 | # Performance settings
68 | direct_addressing_threshold = 10
69 | ttl = 60
70 |
71 | # Logging
72 | logger_type = <%= @logger_type %>
73 | loglevel = <%= @log_level %>
74 | <% if( @logger_type == 'syslog' ) then -%>
75 | logfacility = <%= @logfacility %>
76 | <% end -%>
77 | <% if( @logger_type == 'file' ) then -%>
78 | logfile = <%= @logfile %>
79 | <% if( @keeplogs ) then -%>
80 | keeplogs = <%= @keeplogs %>
81 | <% end -%>
82 | <% if( @max_log_size ) then -%>
83 | max_log_size = <%= @max_log_size %>
84 | <% end -%>
85 | <% end -%>
86 |
--------------------------------------------------------------------------------
/tests/init.pp:
--------------------------------------------------------------------------------
1 | # The baseline for module testing used by Puppet Labs is that each manifest
2 | # should have a corresponding test manifest that declares that class or defined
3 | # type.
4 | #
5 | # Tests are then run by using puppet apply --noop (to check for compilation
6 | # errors and view a log of events) or by fully applying the test in a virtual
7 | # environment (to compare the resulting system state to the desired state).
8 | #
9 | # Learn more about module testing here:
10 | # http://docs.puppetlabs.com/guides/tests_smoke.html
11 | #
12 | include mcollective
13 |
--------------------------------------------------------------------------------