This fork is only updated for security issues and bugs with its use in Puppet Enterprise. Please file bugs with PE support. For security issues, see Puppet's product security policy.
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.
- Follow the plugin deployment guide, using the libdir copy method and placing the
actionpolicy.rb
andactionpolicy.ddl
files in theutil
directory.
Note that it is not currently possible to use the 'mco plugin package' command to package this plugin.
There are three settings available for the actionpolicy plugin:
allow_unconfigured
-- whether to allow requests to agents that do not have policy files configured. Boolean, with allowed values of0
,1
,y
,n
; values oftrue
orfalse
are not allowed. Defaults to0
.enable_default
-- whether to use a default policy file. Boolean, with allowed values of0
,1
,y
,n
; values oftrue
orfalse
are not allowed. Defaults to0
.default_name
-- the name of the default policy file, ifenable_default
is set to1
ory
.
General authentication configuration options can be set in the server config file.
# Enables system wide rpc authorization
rpcauthorization = 1
# Sets the authorization provider to use the actionpolicy plugin
rpcauthprovider = action_policy
# Allow requests to agents without policies
plugin.actionpolicy.allow_unconfigured = 1
You can optionally have a default policy file that applies in the absence of an agent-specific policy file.
plugin.actionpolicy.enable_default = 1
plugin.actionpolicy.default_name = default
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
allow_unconfigured
and enable_default
are configured, all requests will go through the default policy, as enable_default
takes precedence
over allow_unconfigured
.
Policies are defined in files like <configdir>/policies/<agent>.policy
Example: Puppet agent policy file
# /etc/mcollective/policies/puppet.policy
policy default deny
allow cert=admin * * *
allow cert=acme-devs * customer=acme acme::devserver
allow cert=acme-devs enable disable status customer=acme *
# /etc/mcollective/policies/service.policy
policy default deny
allow cert=puppet-admins restart (puppet().enabled=false and environment=production) or environment=development
The above policy can be described as:
- Allow the
admin
user to invoke all Puppet actions on all servers. - Allow the
acme-devs
user to invoke all Puppet actions on machines with the fact customer=acme and the config class acme::devserver - Allow the
acme-devs
user to invoke the enable, disable and status actions on all other machines with fact customer=acme - Allow the
puppet-admins
user to restart services at any time in development but in production only when Puppet has been disabled - All other commands get denied
Policy files must have the following format:
- Any lines starting with
#
are comments. - A single
policy default deny
orpolicy 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 theplugin.actionpolicy.allow_unconfigured
setting will be used as the default. - 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:
allow
ordeny
- Caller ID --- must be either
*
(always matches) or a space-separated list of caller ID strings (see below) - Actions --- must be either
*
(always matches) or a space-separated list of actions - Facts --- may be either
*
(always matches), a space-separated list offact=value
pairs (matches if every listed fact matches), or any valid compound filter string - 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
- 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.
- Policy lines must use hard tabs; editor features that convert tabs to spaces (like Vim's
expandtab
) will result in non-functional policy lines. - 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.
In the case of a single user the Caller ID strings are always of the form <kind>=<value>
, 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. Multiple Caller IDs separated by spaces are supported to allow grouping similar callers together.
You can also define named groups of callers like sysadmin
, see the Groups section below.
- The recommended SSL security plugin sets caller IDs of
cert=<NAME>
, where<NAME>
is the filename of the client's public key file (minus the.pem
extension). So a request validated with thepuppet-admins.pem
public key file would be given a caller ID ofcert=puppet-admins
. This kind of caller ID is cryptographically authenticated. - The PSK security plugin defaults to caller IDs of
uid=<UID>
, where<UID>
is the local UID of the client process. There are several other options available, which can be configured with theplugin.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.
You can create a file called <configdir>/policies/groups
with content as here:
# sample groups file
sysadmins cert=sa1 cert=sa2
Fields are space separated, group names should match ^([\w\.\-]+)$
Here we create a sysadmins
group that has 2 Caller IDs in it, the same rules as above for Caller IDs apply here. Only Caller IDs can be references not other groups.
This group can then be used where you would normal put a Caller ID:
allow sysadmins * customer=acme acme::devserver
You can list multiple groups in space separated lists. You cannot mix certnames and group names in the same policy line.
Instead of using the site-wide authorization settings (as described above), you can also hardcode authorization plugins in your agents:
module MCollective::Agent
class Service<RPC::Agent
authorized_by :action_policy
# ...
end
end
By hardcoding, you're indicating that the ActionPolicy rules must allow this action or it will fail.