Role Based Access Control (RBAC) describes a set of promises made by a host to grant privileged access to the system. In this regard, RBAC is no different from any other form of access control, however, it is normally used to grant the privilege to execute certain commands that make changes to the system – thus it involves write or change privilege.
The term role-based is used because users are often classified into managerial roles that are each assigned different levels of privilege with regard to the kind of tasks they need to perform.
Role Based Access Control is used when remote users request access to a privileged service from some kind of service-agent running on a host. For example, the password on the Unix root account is a simple RBAC system where access is granted to execute any command with unlimited privilege, to any user who knows the root password.
Granting privilege to execute commands has obvious risks. The implementation of restricted access is usually handled in one of a number of different ways. The term RBAC does not explain, in itself, which of these models will be used.
Two common alternatives may be distinguished:
CFEngine handles privileged access somewhat differently. To see why, it is important to understand what CFEngine is not:
roles
promises), providing a version of the second form of RBAC above. We shall return to this
below.
By design it is not possible to send instructions to CFEngine that have
not been pre-approved by the host administrator and promised as
policy. Ultimately the local host administrator can veto any proposals
for change in any configuration system (e.g. by unplugging the network).
In CFEngine this is made a central tenet of the management model. |
From a security perspective, the elimination of remote command access presents a huge simplification to security, without loss of functionality. The risk of executing privileged commands on the system is exchanged for a right to submit policy changes. Thus the access control becomes a matter of who is allowed to approve policy for dissemination to the system.
Even though CFEngine is not in the business of granting privilege for command execution, there are security implications to using CFEngine and thus we should examine the chain of influence from user to host to understand the implications.
In normal usage, users work as follows:
Centralization is a strategy of collecting resources into a single location. A central resource often becomes authoritative for a collection of hosts. Centralization has positive and negative aspects
In terms of privilege, the implications of centralization are significantly different for push and pull based systems (see the figures below). |
Let us first consider the general problem, without reference to CFEngine.
A push is defined to be either
One configures a system for a push system just as one configures a system against attack from outside. In configuration terms, push is indistinguishable from an attack. |
Pull-based management is fundamentally different. In a pull model, hosts download public information (their policy) from a trusted source.
There is no need for access control on the hosts anymore, since they are only reading information voluntarily. They may simply reject all attempts to send them data, in favour of their voluntary decision to download updates.
Moving from push to pull-based configuration simplifies the number of independent points of configuration from N to 1, and the location of access control information is simplified from N separate models to a single model at the hub. The hub can decide which hosts will have access to which policy proposals, so there is no loss of privacy: the security model's definition is fully centralized (single point of definition for consistency).
|
In all further sections, we assume CFEngine's pull-based model.
Before continuing, it is important to emphasize that CFEngine has no technological need for centralization. The decision to centralize management is a policy decision. Every host can, if desired, be configured as an independent device, with its own policy, making no contact with any external host. CFEngine is thus ideal for embedded systems and environments with partial connectivity, such as ships and submarines. Nevertheless, centralized management is often chosen for its simple coordination of decision making. What is important to realize is that centralized decision-making is a convenient fiction for managers – no remote party can truly decide the state of a host.
The owner of a machine always has the privilege to make changes to it. Push-based models of management that pretend to control hosts absolutely are simply misleading, as they exist by the good grace of end systems. |
In the remainder of this Special Topics Guide, we shall assume the common model of centralized management, because that is the context in which RBAC is relevant.
Centralization has implications for risk2. Gaining malicious control of a trusted source could have a significant impact on all the hosts that subscribe to updates from it.
The risk, in this case, is precisely the same as that for a push-based system that executes certain commands. However, the task of defending a single trusted host is (at least psychologically) simpler than that of defending all the hosts in the network3.
The risk of propagating a bad change (i.e. an unfortunate mistake) is also no different between push and pull. A bad decision is simply a bad decision. The antidote to human errors is to conduct policy reviews, i.e. use more pairs of eyes, or `dual-key' solutions.
Centralize the writing of policy, within a local region to obtain straightforward consistency. Don't overcentralize, or you will oversimplfy. One size rarely fits all (see the Special Topics Guide on Federation and Organizational Complexity). RBAC then becomes an issue of: who should have the right to edit and publish changes to policy? |
The burden of security is now localized entirely at the Policy Dispatch Point. It becomes the responsibility of this `role' (policy dispatcher) to ensure that the desired state is in fact the one that is promised. This happens in two practical steps:
Where the highest levels of paranoia are justified, no host should receive automatic updates of policy without explicit human inspection and policy review. This is equivalent to allowing no RBAC privileges.
Let's recap' for a moment. The CFEngine agent runs with maximum system privilege (root/Administrator), and makes its decisions based on a set of promise proposals that come from some trusted source, e.g. the owner of the machine, or some central policy decision point. Once a set of proposals has been published, we simply call these `the policy'. The agent on each host reads these proposals and picks out those that are relevant to the current context (`here and now') for each host. The agent then tries to keep these promises, by making any necessary changes to the system. For most common usages of CFEngine, the effect is that anything that is in the published policy is executed with up to maximum privilege.
This means the following:
The conclusion of this section is that only a small number of highly trusted individuals should be able to alter policy themselves.
Distributed coordination. RBAC is a poor tool for delegating tasks alone, because if multiple individuals with access rights are not coordinated in their promises, the result will merely be a conflict.
Promise theory allows us to model the collaborative security implications of this (see the figure of the bow-tie structure). A simple method of delegating is the following.
A review procedure for policy-promises is a good solution if you want to delegate responsibility for different parts of a policy to different sources. Human judgement as the `arbiter' is irreplaceable, but tools can be added to make conflicts easier to detect.
Promise theory underlines that, if a host or computing device accepts policy from any source, then it is alone and entirely responsible for this decision. The ultimate responsibility for the published version policy is the vetting agent. This creates a shallow hierarchy, but there is no reason why this formal body could not be comprised of representatives from the multiple teams.
The figure below shows how a number of policy authoring teams can work together safely and securely to write the policy for a number of hosts, by vetting through a checkpoint, in a classic `bow-tie' formation.
CFEngine offers one technological convenience that is relevant to RBAC.
In the Clark-Wilson security model, non-privileged users can be
granted limited privilege to execute predefined commands that are
locked down to specific actions. The Unix ps
and passwd
commands are examples of this, for example.
Most users do not need to touch CFEngine at all, because policy is checked very regularly and promises are enforced with 5 minute intervals. In other words, for most users, just waiting will fix anny problem. In some cases, there are extraordinary promises or tasks that one does not want implemented without human oversight. In that instance, one places the relevant promises in a context that is not normally active. Users can then activate those sleeping promises by defining the context class manually.
bundle agent mybundle { files: extraordindary:: # ... promises ... }Privileged users who have access to the system do not need RBAC to do this as they already have all credentials they need, and can achieve the same thing by running the agent with a defined class, e.g.
host# cf-agent -D extraordinaryHowever, it is also possible to grant access to these parts of a CFEngine policy that are normally switched off by using
cf-serverd
to mediate privilege to execute the agent with this class
active. For example, setting:
bundle server access_rules() { roles: # Allow mark "extraordinary" authorize => { "mark", "sally" }; }and running:
host# cf-runagent -H special_host -D extraordinarywould achieve the same effect without granting any rights to change the policy.
In this example CFEngine promises to grant permission to users
‘mark’ and ‘sally’ to remotely activate classes matching the regular
expression ‘extraordinary’ when using the cf-runagent
to
activate CFEngine. In this way one can implement a form of Role Based
Access Control (RBAC) for unprivileged users, provided users do not
have privileged access on the host directly. User identity is based on
trusted CFEngine keys created by the user and exchanged with the
server.
CFEngine Nova 2.2.0 introduces Role Based Access Control (RBAC) for all reports and promises shown in the Mission Portal. This does not cover access control for making policy changes, but displaying reports.
RBAC can be globally switched on or off in the Mission Portal settings.
User-authentication is carried out when users log in to the Mission Portal. This is done by requiring a user name and password, which is checked against the following possible sources.
The selection between these options are available in the Mission Portal settings.
The information a user is authorized to see is determined from his role memberships. A user may be member of an arbitrary number of roles, each which may grant and deny access to certain information.
The effective permissions of a user is the cumulative set of permission granted or denied by his roles, and is used to filter the information displayed in the following standard way.
RBAC is supported on the host and promise bundle level, each applying to different parts of the Mission Portal. Both these entities are atomic with respect to RBAC — either a user can see everything they contain, or nothing of it.
Access to a host is required to see any information about it, e.g. all its reports (Engineering->Reports), host page, and compliance category. If a user is not allowed access to a host, the Mission Portal would look the same as if the host was not bootstrapped to that hub.
Information about the running policy is also available in the Mission Portal, either through the Promise Finder at the Engineering page, or by clicking a promise handle from one of the reports. The searchable promises in the Promise Finder and information pages about promises and bundles are filtered in the same manner as the hosts, but defined based on promise bundles instead. The Policy Editor is not covered by RBAC — access to the policy source repository allows the user to see the whole policy. Some version control systems can be configured to only allow users to access sub-directories of the policy, which may help in this case.
Note that the host and promise filtering is independent — no attempt is made to try to infer which promises a role should have access to based on the hosts it has access to or vice versa.
From the above discussion, we see that a role is defined as reporting
access to a set of hosts and promise bundles from the Mission Portal
and REST API. This does not give any rights with respect to changing
the content or execution of the policy. It should not be confused with
the roles
promise-type that can be used by cf-runagent
and cf-serverd
.
In order to scale, both entities are defined as a set of regular expressions to allow and deny.
Access to hosts is defined by regular expressions on classes, not the hostname, ip, or any other name. This is done to ensure maximum scalability. Classes can be arbitrarily defined in the CFEngine policy language, so this incurs no loss of flexibility, but ensures distributed computation.
In contrast to users, a role definition and membership can only be obtained from the internal Mission Portal database. This means that any roles must be defined through the Mission Portal web interface, and can not be obtained from e.g. LDAP at this time. The rationale is that querying complex LDAP structures for role membership is too inefficient and error-prone. This may change in future releases, if requested. Note that the possible members of a role can be obtained from other sources, as described in ‘Authentication’ above. However, assigning possible members to roles must be done through the Mission Portal user-interface.
A sample definition of the role ‘lob_a’ is shown below.
Only members of the ‘admin’ role has the ability to manipulate roles and their memberships.
After defining the role itself, the next step is to make the designated users members of the role, using the Mission Portal.
cf-report
from the command-line on the hub will
bypass all RBAC checks.
[1] Many provisioning and management systems are indeed
effectively remote execution agents and thus RBAC is more relevant to them. [2] A single point of
definition could also be a single point of failure. In CFEngine, a
central policy hub is not a point of failure, because each agent
caches all the resources it needs to maintain systems according to its
current model. At worst, the loss of a hub would mean a delay to
updates. [3] User who are adept at automated
configuration might disagree, as automation makes it easy to harden
all hosts equally well. Network policies such as firewalls, etc, are
however, simpler to manage for a single host. [4] Note that the decision to collect policy updates from somewhere is
itself a policy decision in CFEngine, so users should always think carefully
about these decisions.Table of Contents
Footnotes