Patch 0540 adds a bunch of managed read ACIs for user, as discussed previously [0].

Patch 0541 is some minor refactoring for the next part.

Patch 0542 sets the read acces to addressbook attributes to anonymous when upgrading from pre-4.0. I first this by checking if the update is run from ipa-server-install or not, but then I realized the logic I want is simple: if the global anon read ACI exists, we want to preserve its spirit by setting addressbook attribute ACI to anonymous.


[0] http://www.redhat.com/archives/freeipa-devel/2014-April/msg00363.html et al.

--
PetrĀ³
From 9f9681c2e302923e28941c97f6b489b4d46ded8a Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pvikt...@redhat.com>
Date: Wed, 26 Mar 2014 17:11:23 +0100
Subject: [PATCH] Add managed read permissions to user

Part of the work for: https://fedorahosted.org/freeipa/ticket/3566
---
 ipalib/plugins/user.py | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 55 insertions(+)

diff --git a/ipalib/plugins/user.py b/ipalib/plugins/user.py
index 166955933b2fd8b1cd1cddd5e4d48f4c97b2d7cd..12101256b9e7b42f3d85a9ff4d23690f78efd7bf 100644
--- a/ipalib/plugins/user.py
+++ b/ipalib/plugins/user.py
@@ -232,6 +232,61 @@ class user(LDAPObject):
     bindable = True
     password_attributes = [('userpassword', 'has_password'),
                            ('krbprincipalkey', 'has_keytab')]
+    managed_permissions = {
+        'System: Read User POSIX Attributes': {
+            'replaces_global_anonymous_aci': True,
+            'ipapermbindruletype': 'anonymous',
+            'ipapermright': {'read', 'search', 'compare'},
+            'ipapermdefaultattr': {
+                'objectclass', 'cn', 'sn', 'description', 'title', 'uid',
+                'displayname', 'givenname', 'initials', 'manager',
+                'ipauniqueid', 'ipasshpubkey', 'ipauserauthtype', 'gecos',
+                'gidnumber', 'homedirectory', 'loginshell', 'uidnumber'
+            },
+        },
+        'System: Read User Addressbook Attributes': {
+            'replaces_global_anonymous_aci': True,
+            'ipapermbindruletype': 'all',
+            'ipapermright': {'read', 'search', 'compare'},
+            'ipapermdefaultattr': {
+                'seealso', 'telephonenumber',
+                'fax', 'l', 'ou', 'st', 'postalcode', 'street',
+                'destinationindicator', 'internationalisdnnumber',
+                'physicaldeliveryofficename', 'postaladdress', 'postofficebox',
+                'preferreddeliverymethod', 'registeredaddress',
+                'teletexterminalidentifier', 'telexnumber', 'x121address',
+                'carlicense', 'departmentnumber', 'employeenumber',
+                'employeetype', 'preferredlanguage', 'mail', 'mobile', 'pager',
+                'audio', 'businesscategory', 'homephone', 'homepostaladdress',
+                'jpegphoto', 'labeleduri', 'o', 'photo', 'roomnumber',
+                'secretary', 'usercertificate', 'userpkcs12',
+                'usersmimecertificate', 'x500uniqueidentifier',
+                'inetuserhttpurl', 'inetuserstatus', 'userclass',
+            },
+        },
+        'System: Read User Kerberos Attributes': {
+            'replaces_global_anonymous_aci': True,
+            'ipapermbindruletype': 'all',
+            'ipapermright': {'read', 'search', 'compare'},
+            'ipapermdefaultattr': {
+                'krbprincipalname', 'krbcanonicalname', 'krbprincipalaliases',
+                'krbprincipalexpiration', 'krbpasswordexpiration',
+                'krblastpwdchange', 'nsaccountlock', 'krbprincipaltype',
+            },
+        },
+        'System: Read User Kerberos Login Attributes': {
+            'replaces_global_anonymous_aci': True,
+            'ipapermbindruletype': 'permission',
+            'ipapermright': {'read', 'search', 'compare'},
+            'ipapermdefaultattr': {
+                'krblastsuccessfulauth', 'krblastfailedauth',
+                'krblastpwdchange', 'krblastadminunlock',
+                'krbloginfailedcount', 'krbpwdpolicyreference',
+                'krbticketpolicyreference', 'krbupenabled',
+            },
+            'default_privileges': {'User Administrators'},
+        },
+    }
 
     label = _('Users')
     label_singular = _('User')
-- 
1.9.0

From 4efc66dfe0ce2ecc53ac1562c03c43f45f77babd Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pvikt...@redhat.com>
Date: Tue, 29 Apr 2014 21:15:05 +0200
Subject: [PATCH] update_managed_permissions: Pass around anonymous ACI rather
 than its blacklist

It turns out the ACI object of the anonymous read ACI, rather than just the
list of its attributes, will be useful in the future.
Change the plugin so that the ACI object is passed around.
---
 .../install/plugins/update_managed_permissions.py  | 35 +++++++++++-----------
 1 file changed, 18 insertions(+), 17 deletions(-)

diff --git a/ipaserver/install/plugins/update_managed_permissions.py b/ipaserver/install/plugins/update_managed_permissions.py
index bffd9bbf434e76c9c6d74d0167a718acc96a54b1..6529fd257172a6da08b2e64525493a7bab04f512 100644
--- a/ipaserver/install/plugins/update_managed_permissions.py
+++ b/ipaserver/install/plugins/update_managed_permissions.py
@@ -168,8 +168,7 @@ class update_managed_permissions(PostUpdate):
     """
     order = LAST
 
-    def get_anonymous_read_blacklist(self, ldap):
-        """Get the list of attributes from the legacy anonymous access ACI"""
+    def get_anonymous_read_aci(self, ldap):
         aciname = u'Enable Anonymous access'
         aciprefix = u'none'
 
@@ -178,19 +177,19 @@ def get_anonymous_read_blacklist(self, ldap):
         acistrs = base_entry.get('aci', [])
         acilist = aci._convert_strings_to_acis(acistrs)
         try:
-            rawaci = aci._find_aci_by_name(acilist, aciprefix, aciname)
+            return aci._find_aci_by_name(acilist, aciprefix, aciname)
         except errors.NotFound:
-            self.log.info('Anonymous ACI not found, using no blacklist')
-            return []
-
-        return rawaci.target['targetattr']['expression']
+            return None
 
     def execute(self, **options):
         ldap = self.api.Backend[ldap2]
 
-        anonymous_read_blacklist = self.get_anonymous_read_blacklist(ldap)
+        anonymous_read_aci = self.get_anonymous_read_aci(ldap)
 
-        self.log.info('Anonymous read blacklist: %s', anonymous_read_blacklist)
+        if anonymous_read_aci:
+            self.log.info('Anonymous read ACI: %s', anonymous_read_aci)
+        else:
+            self.log.info('Anonymous ACI not found')
 
         for obj in self.api.Object():
             managed_permissions = getattr(obj, 'managed_permissions', {})
@@ -201,17 +200,16 @@ def execute(self, **options):
                                        obj,
                                        unicode(name),
                                        template,
-                                       anonymous_read_blacklist)
+                                       anonymous_read_aci)
 
         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)
+                                   anonymous_read_aci)
 
         return False, False, ()
 
-    def update_permission(self, ldap, obj, name, template,
-                          anonymous_read_blacklist):
+    def update_permission(self, ldap, obj, name, template, anonymous_read_aci):
         """Update the given permission and the corresponding ACI"""
         assert name.startswith('System:')
 
@@ -228,7 +226,7 @@ def update_permission(self, ldap, obj, name, template,
 
         self.log.debug('Updating managed permission: %s', name)
         self.update_entry(obj, entry, template,
-                          anonymous_read_blacklist, is_new=is_new)
+                          anonymous_read_aci, is_new=is_new)
 
         if is_new:
             ldap.add_entry(entry)
@@ -244,7 +242,7 @@ def update_permission(self, ldap, obj, name, template,
         self.api.Object[permission].update_aci(entry)
 
     def update_entry(self, obj, entry, template,
-                     anonymous_read_blacklist, is_new):
+                     anonymous_read_aci, is_new):
         """Update the given permission Entry (without contacting LDAP)"""
 
         [name_ava] = entry.dn[0]
@@ -304,8 +302,11 @@ def update_entry(self, obj, entry, template,
         entry['ipapermdefaultattr'] = list(attributes)
 
         # Exclude attributes filtered from the global read ACI
-        if template.pop('replaces_global_anonymous_aci', False) and is_new:
-            read_blacklist = set(a.lower() for a in anonymous_read_blacklist)
+        replaces_ga_aci = template.pop('replaces_global_anonymous_aci', False)
+        if replaces_ga_aci and is_new and anonymous_read_aci:
+            read_blacklist = set(
+                a.lower() for a in
+                anonymous_read_aci.target['targetattr']['expression'])
             read_blacklist &= attributes
             if read_blacklist:
                 self.log.info('Excluded attributes for %s: %s',
-- 
1.9.0

From f2d0f85dbbac65058a01ee03812485ac89b15ed2 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pvikt...@redhat.com>
Date: Tue, 29 Apr 2014 21:32:29 +0200
Subject: [PATCH] Set user addressbook attribute read ACI to anonymous on
 upgrades from 3.x

When upgrading from an "old" IPA, or installing the first "new" replica,
we need to keep allowing anonymous access to many user attributes.

Add an optional 'fixup_function' to the managed permission templates,
and use it to set the bind rule type to 'anonymous' when installing
(or upgrading to) the first "new" master.

This assumes that the anonymous read ACI will be removed in a "new" IPA.

Part of the work for: https://fedorahosted.org/freeipa/ticket/3566
---
 ipalib/plugins/user.py                                  | 16 ++++++++++++++++
 ipaserver/install/plugins/update_managed_permissions.py | 14 ++++++++++++++
 2 files changed, 30 insertions(+)

diff --git a/ipalib/plugins/user.py b/ipalib/plugins/user.py
index 12101256b9e7b42f3d85a9ff4d23690f78efd7bf..a9c5c76a725d6a2fd91cbc8f8ff9d3a530434652 100644
--- a/ipalib/plugins/user.py
+++ b/ipalib/plugins/user.py
@@ -195,6 +195,21 @@ def check_protected_member(user, protected_group_name=u'admins'):
         raise errors.LastMemberError(key=user, label=_(u'group'),
             container=protected_group_name)
 
+
+def fix_addressbook_permission_bindrule(name, template, is_new,
+                                        anonymous_read_aci,
+                                        **other_options):
+    """Fix bind rule type for 'Read User Addressbook Attributes' permission
+
+    When upgrading from an old IPA that had the global read ACI,
+    or when installing the first replica with granular read permissions,
+    we need to keep allowing anonymous access to many user attributes.
+    This fixup_function changes the bind rule type accordingly.
+    """
+    if is_new and anonymous_read_aci:
+        template['ipapermbindruletype'] = 'anonymous'
+
+
 class user(LDAPObject):
     """
     User object.
@@ -263,6 +278,7 @@ class user(LDAPObject):
                 'usersmimecertificate', 'x500uniqueidentifier',
                 'inetuserhttpurl', 'inetuserstatus', 'userclass',
             },
+            'fixup_function': fix_addressbook_permission_bindrule,
         },
         'System: Read User Kerberos Attributes': {
             'replaces_global_anonymous_aci': True,
diff --git a/ipaserver/install/plugins/update_managed_permissions.py b/ipaserver/install/plugins/update_managed_permissions.py
index 6529fd257172a6da08b2e64525493a7bab04f512..91686e1108303d19358886934c98926a8d57ed5c 100644
--- a/ipaserver/install/plugins/update_managed_permissions.py
+++ b/ipaserver/install/plugins/update_managed_permissions.py
@@ -64,6 +64,14 @@
 * non_object
   - If true, no object-specific defaults are used (e.g. for
     ipapermtargetfilter, ipapermlocation).
+* fixup_function
+  - A callable that may modify the template in-place before it is applied.
+  - Called with the permission name, template dict, and keyword arguments:
+    - is_new: true if the permission was previously existing
+    - anonymous_read_aci: the legacy 'Enable Anonymous access' ACI as
+      an ipalib.aci.ACI object, or None if it does not exist
+    Extra keyword arguments must be ignored, since this list may grow
+    in the future.
 
 No other keys are allowed in the template
 """
@@ -252,6 +260,12 @@ def update_entry(self, obj, entry, template,
 
         template = dict(template)
 
+        fixup_function = template.pop('fixup_function', None)
+        if fixup_function:
+            fixup_function(name, template,
+                           is_new=is_new,
+                           anonymous_read_aci=anonymous_read_aci)
+
         if template.pop('non_object', False):
             obj = None
 
-- 
1.9.0

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

Reply via email to