[Pacemaker] Multi-level ACLs for the CIB

Yan Gao ygao at novell.com
Mon Dec 7 03:06:30 EST 2009


Hi all, Andrew,

This planned feature was proposed by Lars. After some discussions
with Lars and Tim, I'm sharing it here, and looking forward to hearing
your thoughts and suggestions.

The goal of this feature is to provide different levels of
administration to users.

Some of the common scenarios:
1. There are cluster admins who are allowed to do "everything", usually
they have root on the cluster.

2. Some operators, allowed to see the cluster status, perhaps modify
node status (shutdown/standby). Possibly not allowed to see specific
bits of the CIB (such as passwords for the stonith devices).

3. Admins who are allowed access only to a very specific resource, but
not to others. (ie, application admins who only may (re-)start/stop
their own service/VM.) Also restricted read rights.

4. Monitors who only have restricted read rights.

There might be others...So we'd like to make it flexible. Users should
be able to configure any of the system accounts to be a particular role
as they wish.

Basically, we'd like to see an ACL mechanism. It would be implemented at
the CIB level. So that all the clients - CLI , CRM shell, GUI, etc... -
could benefit. Clients are authenticated via PAM, so we can use uid/gid
for identification.

The original idea is using XPath/XSLT to achieve this. But it was
considered impractical. The syntax would become so ugly. Hence we now
prefer a black-/whitelist, and the first match defines whether access is
granted or denied.

The basic implementation idea is to introduce a new "acls" section in
the CIB under "configuration" which defines these permissions.

Example syntax:

..
  <configuration>
    <resources>
      <primitive id="stonith1" class="stonith" type="external/riloe">
        <instance_attributes id="stonith1-instance_attributes">
          <nvpair id="stonith1-instance_attributes-hostlist"
name="hostlist" value="host1"/>
          <nvpair id="stonith1-instance_attributes-ilo_hostname"
name="ilo_hostname" value="192.168.0.101"/>
          <nvpair id="stonith1-instance_attributes-ilo_user"
name="ilo_user" value="admin"/>
          <nvpair id="stonith1-instance_attributes-ilo_password"
name="ilo_password" value="123456"/>
        </instance_attributes>
        <meta_attributes id="stonith1-meta_attributes">
          <nvpair id="stonith1-meta_attributes-target_role"
name="target_role" value="stopped"/>
        </meta_attributes>
      </primitive>
    </resources>
    <constraints>
      <rsc_location id="loc-stonith1" node="host2" rsc="stonith1"
score="1000"/>
    </constraints>
    <acls>
      <acl uid="ygao">
        <write ref="stonith1-meta_attributes-target_role"
attribute="value" />
        <write ref="loc-stonith1"/>
        <deny ref="stonith1-instance_attributes-ilo_password" />
        <read ref="stonith1" />
        <read ref="#status" />
        <deny />
      </acl>
    </acls>
  </configuration>
..

Basically, this means that the user "ygao" would be allowed to write to
the target-role and the location of the resource "stonith1", read all of
the "stonith1" definition except the "ilo_password" nvpair,  and be
allowed to see the "status" section; everything else would be denied.

The final "<deny />" might not be needed. As Tim suggested, if no ACL
matches the object, it's more secure to just assume access is denied.

Data going out from or in to the CIB from these accounts would be
matched against and filtered through this list.

Hence if "ygao" excutes:
> cibadmin -Q -o resources

The outputs would be:
    <resources>
      <primitive id="stonith1" class="stonith" type="external/riloe">
        <instance_attributes id="stonith1-instance_attributes">
          <nvpair id="stonith1-instance_attributes-hostlist"
name="hostlist" value="host1"/>
          <nvpair id="stonith1-instance_attributes-ilo_hostname"
name="ilo_hostname" value="192.168.0.101"/>
          <nvpair id="stonith1-instance_attributes-ilo_user"
name="ilo_user" value="admin"/>
        </instance_attributes>
        <meta_attributes id="stonith1-meta_attributes">
          <nvpair id="stonith1-meta_attributes-target_role"
name="target_role" value="stopped"/>
        </meta_attributes>
      </primitive>
    </resources>

He cannot see the "ilo_password".

If there's more than one user that needs the same access rights. We
could specify that like:

..
<acl role="ha_monitor">
  <read ref="#status"/>
</acl>
<acl uid="ygao">
  <ref role="ha_monitor"/>
</acl>
<acl uid="tesrong">
  <ref role="ha_monitor"/>
</acl>
..

or could be like:
..
<acl role="ha_monitor">
  <users>
    <uid="ygao"/>
    <uid="tesrong"/>
  </users>
  <read ref="#status"/>
</acl>
..

And it should also support system group:
..
<acl gid="ha_group">
  <read ref="#status"/>
</acl>
..

I think the syntax isn't perfect yet, but that should be the basic
direction. I'd like to hear your thoughts about it.

Andrew ever mentioned two criteria:
> It should be implemented cleanly.
I'll look into it, and see how we could achieve that. Andrew, if you
have any suggestions on that, I would be very appreciated:-)

> It could be compiled out.
The basic consideration is this would impact the performance of CIB.
Actually for superusers (root/hacluster), all these security checks
would be bypassed. So for all of the current operations which is done by
superusers including the internal processes, the performance would be
preserved. Anyway, we'll make it optional when compiling.

Any comments or suggestions are welcome.

Thanks,
  Yan
-- 
ygao at novell.com
Software Engineer
China Server Team, OPS Engineering

Novell, Inc.
Making IT Work As One™




More information about the Pacemaker mailing list