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.
[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