Patch 0508:
This documents the inputs for the permission updater in the module itself. This is taken from the design page. I expect it'll need an addition now and then, so I think it's better to have this near the code it corresponds to.


Patch 0509:
So far the new default permissions have been tied to an Object plugin, and took the ACI location and objectclass filter from the object. However there are some permissions that are not tied to an IPA object, for instance ones dealing with a compat tree. However, these permissions should behave similarly to the Object-based ones, so it makes sense to use the same updater with them.

A question is where the non-Object permissions should be stored. I can think of several alternatives:
a) in a special data file, like .update files
b) in a new plugin type
c) somewhere in the code

I went for c) for simplicity, but feel free to discuss. (CCing Rob since he had some strong opinions in this area.)

This patch makes ipapermlocation, ipapermtargetfilter and other Permission attributes overridable, and adds a central list of non-object permissions to the updater module. (For now, the list is empty).


My patch 0504.2 (Default read ACIs for Sudo objects) will add a non-object permission for ou=sudoers.


--
PetrĀ³
From aa98fbd527727a301737c365dcfeb3245d6a51b2 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pvikt...@redhat.com>
Date: Thu, 27 Mar 2014 12:17:37 +0100
Subject: [PATCH] Document the managed permission updater operation

The method was explained on the [Design] page, but as the updater
is extended the design page would become obsolete.
Document the operation in the docstring of the plugin itself.

Design: http://www.freeipa.org/page/V3/Managed_Read_permissions#Default_Permission_Updater
---
 .../install/plugins/update_managed_permissions.py  | 34 ++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/ipaserver/install/plugins/update_managed_permissions.py b/ipaserver/install/plugins/update_managed_permissions.py
index 603f3f0b74c97b14be0992d2c110f5bb6cd0e0e6..b2548f4f12aab2ae05c3c4a63e38eb8ca2b65ad6 100644
--- a/ipaserver/install/plugins/update_managed_permissions.py
+++ b/ipaserver/install/plugins/update_managed_permissions.py
@@ -17,6 +17,40 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+"""
+Plugin for updating managed permissions.
+
+The permissions are declared in Object plugins in the "managed_permissions"
+attribute, which is a dictionary mapping permission names to a "template"
+for the updater.
+For example, an entry could look like this:
+
+    managed_permissions = {
+        'System: Read Object A': {
+            'ipapermbindruletype': 'all',
+            'ipapermright': {'read', 'search', 'compare'},
+            'ipapermdefaultattr': {'cn', 'description'},
+            'replaces_global_anonymous_aci': True,
+        },
+    }
+
+The permission name must start with the "System:" prefix.
+
+The template dictionary can have the following keys:
+* ipapermbindruletype, ipapermright
+  - Directly used as attributes on the permission.
+  - Replaced when upgrading an existing permission
+* ipapermdefaultattr
+  - Used as attribute of the permission.
+  - When upgrading, only new values are added; all old values are kept.
+* replaces_global_anonymous_aci
+  - If true, any attributes specified (denied) in the legacy global anonymous
+    read ACI will be added to excluded_attributes of the new permission.
+  - Has no effect when existing permissions are updated.
+
+No other keys are allowed in the template
+"""
+
 from ipalib import errors
 from ipapython.dn import DN
 from ipalib.plugable import Registry
-- 
1.9.0

From 333b846ed1d7228d4e6bd86b63b248a91debc8c0 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pvikt...@redhat.com>
Date: Thu, 27 Mar 2014 15:36:54 +0100
Subject: [PATCH] Add support for non-object default permissions

Add support for managed permissions that are not tied to an object
class and thus can't be defined in an Object plugin.

Permission attributes that were previously taken from the object
can now be overriden, and if no object is present they default to
general permission defaults.

A dict is added to hold templates for the non-object permissions.
---
 .../install/plugins/update_managed_permissions.py  | 55 +++++++++++++++++-----
 1 file changed, 43 insertions(+), 12 deletions(-)

diff --git a/ipaserver/install/plugins/update_managed_permissions.py b/ipaserver/install/plugins/update_managed_permissions.py
index b2548f4f12aab2ae05c3c4a63e38eb8ca2b65ad6..8415b93a8cdac5ac23d07f0664e8f401239e4c25 100644
--- a/ipaserver/install/plugins/update_managed_permissions.py
+++ b/ipaserver/install/plugins/update_managed_permissions.py
@@ -34,12 +34,22 @@
         },
     }
 
+For permissions not tied to an object plugin, a NONOBJECT_PERMISSIONS
+dict of the same format is defined in this module.
+
 The permission name must start with the "System:" prefix.
 
 The template dictionary can have the following keys:
-* ipapermbindruletype, ipapermright
+* ipapermtarget, ipapermtargetfilter, ipapermlocation, ipapermright, objectclass
   - Directly used as attributes on the permission.
   - Replaced when upgrading an existing permission
+  - If not specified, these default to the defaults of a permission of the
+    corresponding --type, or general permission defaults if not on an object.
+  - ipapermlocation and ipapermtarget must be DNs
+  - ipapermtargetfilter and objectclass must be iterables of strings
+* ipapermbindruletype
+  - Directly used as attribute on the permission.
+  - Not replaced when upgrading an existing permission.
 * ipapermdefaultattr
   - Used as attribute of the permission.
   - When upgrading, only new values are added; all old values are kept.
@@ -63,6 +73,8 @@
 
 register = Registry()
 
+NONOBJECT_PERMISSIONS = {}
+
 
 @register()
 class update_managed_permissions(PostUpdate):
@@ -103,18 +115,24 @@ def execute(self, **options):
             if managed_permissions:
                 self.log.info('Updating managed permissions for %s', obj.name)
             for name, template in managed_permissions.items():
-                assert name.startswith('System:')
                 self.update_permission(ldap,
                                        obj,
                                        unicode(name),
                                        template,
                                        anonymous_read_blacklist)
 
+        self.log.info('Updating non-object managed permissions')
+        for name, template in NONOBJECT_PERMISSIONS.iteritems():
+            self.update_permission(ldap, None, unicode(name), template,
+                                   anonymous_read_blacklist)
+
         return False, False, ()
 
     def update_permission(self, ldap, obj, name, template,
                           anonymous_read_blacklist):
         """Update the given permission and the corresponding ACI"""
+        assert name.startswith('System:')
+
         dn = self.api.Object[permission].get_dn(name)
 
         try:
@@ -125,7 +143,7 @@ def update_permission(self, ldap, obj, name, template,
             entry = ldap.make_entry(dn)
             is_new = True
 
-        self.log.info('Updating managed permission: %s', name)
+        self.log.debug('Updating managed permission: %s', name)
         self.update_entry(obj, entry, template,
                           anonymous_read_blacklist, is_new=is_new)
 
@@ -153,22 +171,35 @@ def update_entry(self, obj, entry, template,
 
         template = dict(template)
 
-        # Common attributes
-        entry['objectclass'] = self.api.Object[permission].object_class
-
         entry['ipapermissiontype'] = [u'SYSTEM', u'V2', u'MANAGED']
 
-        # Object-specific attributes
-        ldap_filter = ['(objectclass=%s)' % oc
-                       for oc in obj.permission_filter_objectclasses]
-        entry['ipapermtargetfilter'] = ldap_filter
+        # Attributes with defaults
+        objectclass = template.pop('objectclass', None)
+        if objectclass is None:
+            objectclass = self.api.Object[permission].object_class
+        entry['objectclass'] = list(objectclass)
 
-        ipapermlocation = DN(obj.container_dn, self.api.env.basedn)
+        ldap_filter = template.pop('ipapermtargetfilter', None)
+        if obj and ldap_filter is None:
+            ldap_filter = ['(objectclass=%s)' % oc
+                           for oc in obj.permission_filter_objectclasses]
+        entry['ipapermtargetfilter'] = list(ldap_filter or [])
+
+        ipapermlocation = template.pop('ipapermlocation', None)
+        if ipapermlocation is None:
+            assert obj
+            ipapermlocation = DN(obj.container_dn, self.api.env.basedn)
         entry.single_value['ipapermlocation'] = ipapermlocation
 
+        # Optional attributes
+        ipapermtarget = template.pop('ipapermtarget', None)
+        if ipapermtarget is not None:
+            entry['ipapermtarget'] = ipapermtarget
+
         # Attributes from template
         bindruletype = template.pop('ipapermbindruletype')
-        entry.single_value['ipapermbindruletype'] = bindruletype
+        if is_new:
+            entry.single_value['ipapermbindruletype'] = bindruletype
 
         entry['ipapermright'] = list(template.pop('ipapermright'))
 
-- 
1.9.0

_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to