On 05/16/2014 01:54 PM, Martin Kosek wrote:
On 04/29/2014 11:00 PM, Petr Viktorin wrote:
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.


540:

Looks good! The only attributes I am concerned about are special IPA attributes:

- ipauniqueid
- ipasshpubkey
- ipauserauthtype
- userclass

I personally do not think they should be included in POSIX attributes
permissions, they are far from POSIX definition...

What about creating one more permission "System: Read User IPA Attributes" as
these are specific to FreeIPA use and allowing that permission for all
authenticated users?

Sounds reasonable. I assume we want this one to be also set to anonymous when upgrading from old versions.
Attaching updated patches.

541, 542:
ACK for both, works fine in both new installation and upgrade.

Martin


--
PetrĀ³

From 04311c33f4cee613865521469779b625ab4657c9 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 | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 62 insertions(+)

diff --git a/ipalib/plugins/user.py b/ipalib/plugins/user.py
index d9c7c6c858aa0a4927efc01fb41b535b7bb04ba2..bc6c2a300c58783dceed1aebbbde56e28f06f518 100644
--- a/ipalib/plugins/user.py
+++ b/ipalib/plugins/user.py
@@ -233,6 +233,68 @@ 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', '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',
+            },
+        },
+        'System: Read User IPA Attributes': {
+            'replaces_global_anonymous_aci': True,
+            'ipapermbindruletype': 'all',
+            'ipapermright': {'read', 'search', 'compare'},
+            'ipapermdefaultattr': {
+                'ipauniqueid', 'ipasshpubkey', 'ipauserauthtype', '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 a3e5aaa25bec04fa2a376f8d5773c60a06453dac 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 1f4f5c434b209161977c52be6564ded9ddea4f30 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/IPA 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                                  | 17 +++++++++++++++++
 ipaserver/install/plugins/update_managed_permissions.py | 14 ++++++++++++++
 2 files changed, 31 insertions(+)

diff --git a/ipalib/plugins/user.py b/ipalib/plugins/user.py
index bc6c2a300c58783dceed1aebbbde56e28f06f518..5532a8a285fc554f4d1d249eae21b610eb5dbc1c 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/IPA 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',
             },
+            'fixup_function': fix_addressbook_permission_bindrule,
         },
         'System: Read User IPA Attributes': {
             'replaces_global_anonymous_aci': True,
@@ -271,6 +287,7 @@ class user(LDAPObject):
             'ipapermdefaultattr': {
                 'ipauniqueid', 'ipasshpubkey', 'ipauserauthtype', '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