[Freeipa-devel] [PATCH, 4.1] 0166 updater: enable uid uniqueness plugin for posixAccount objects

Alexander Bokovoy abokovoy at redhat.com
Tue Oct 21 10:41:19 UTC 2014


On Tue, 21 Oct 2014, Alexander Bokovoy wrote:
> On Tue, 21 Oct 2014, Martin Kosek wrote:
>> On 10/21/2014 08:41 AM, Alexander Bokovoy wrote:
>>> On Tue, 21 Oct 2014, Martin Kosek wrote:
>>>> On 10/20/2014 08:25 PM, Alexander Bokovoy wrote:
>>>>> Hi!
>>>>> 
>>>>> This patch is for ipa-4-1 branch to enable uniqueness plugin for uid
>>>>> attribute for entries with objectclass posixAccount.
>>>>> 
>>>>> We don't have uid uniqueness enforced in FreeIPA < 4.1 yet but for
>>>>> posixAccounts it worked due to our design of a flat tree: as uid attribute is
>>>>> part of the DN, renaming user entries
>>>>> enforces uniqueness as MODRDN will fail if entry with the same uid
>>>>> already exists.
>>>>> 
>>>>> However, it is not enough for ID views -- we should be able to allow
>>>>> ID view overrides for the same uid across multiple views and we should
>>>>> be able to protect uid uniqueness more generally too.
>>>>> 
>>>>> Implementation is done via update plugin that checks for existing uid
>>>>> uniqueness plugin and if it is missing, it will be added. If plugin
>>>>> exists, its configuration will be updated.
>>>>> 
>>>>> I haven't added update specific to git master where staging subtree is
>>>>> added but I'll do that after FreeIPA 4.1 release as in 4.1 we don't yet
>>>>> have the staging subtree. Currently master has broken setup for uid
>>>>> uniqueness plugin that doesn't actually work anyway so it will be easier
>>>>> to add upgrade over properly configured entry.
>>>>> 
>>>>> https://fedorahosted.org/freeipa/ticket/4636
>>>> 
>>>> Hi Alexander,
>>>> 
>>>> Thanks for the patch! However, I am personally not very confident with merging
>>>> it right before 4.1 release, I thought it will be a simple update definition
>>>> while this is a complex upgrade script which needs to be properly tested.
>>>> 
>>>> I would rather wait for 4.1.x, especially given it does not block any 4.1 major
>>>> feature in any way.
>>> I disagree on it for multiple reasons and one of them is that 'a simple
>>> update definition' is not right here. Attribute uniqueness plugin
>>> supports three different types of setting its own arguments. These types
>>> aren't mixable, you have to do switch from one to another. That's why
>>> update plugin is the correct approach here.
>>> 
>>> The update plugin I've wrote is very simple by itself.
>> 
>> Ok, reviewing the patch now. I found 2 issues:
>> 
>> 1) It is missing in plugins' Makefile.am so it won't be built properly
>> 
>> 2) Instead of
>> +        if len(entries) == 0:
>> use
>> +        if entries:
> You mean 'if not entries:'? Will fix.
> 
> 
>> 3) I think we should force "uid uniqueness" plugin creation in all cases so
>> that we can expect it is there in future and for example do simple updates for it.
> It does enforce it creating already. The only case that is not handled
> right now is the case of already existing multiple uid uniqueness
> plugin instances which I explicitly want to handle in git master and
> then merge back to 4.1 as a backport -- we only have any chance to
> encounter this case with current git master.
> 
>> So if existing active UID uniqueness is there, should we just remove uid from
>> it's list of watched attributes, give warning and add our own controlled plugin?
> No. There could be multiple uid uniqueness plugin instances, looking for
> different subtrees, potentially with different top level object classes
> and different object class filtering.
> 
>> I am just trying to get rid of clashes with custom user configuration.
> I understand that, I'll handle it in git master version. Right now we
> didn't set up any of uid uniqueness and chances touching any custom
> configuration like that are low, looking into my experience with
> existing deployments.
> 
> 
>> 4) Because of 3), when I enabled "attribute uniqueness" plugin before upgrade,
>> it did a strange franken-update and now I have an update plugin with DN
>> "cn=attribute uniqueness,cn=plugins,cn=config" but "cn: uid uniqueness: inside.
> Good catch. I'll fix this part.
> 
>> (BTW these concerns is where my simplicity expectations came from ;-)
> Note that now you realize the whole deal is not that simple as you
> thought. ;)
> 
> New patch attached.
Missed Makefile.am part.

-- 
/ Alexander Bokovoy
-------------- next part --------------
From 7951e57ca52d38497b0a87610685f173ebb558a3 Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <abokovoy at redhat.com>
Date: Mon, 20 Oct 2014 21:01:33 +0300
Subject: [PATCH] updater: enable uid uniqueness plugin for posixAccounts

https://fedorahosted.org/freeipa/ticket/4636
---
 ipaserver/install/plugins/Makefile.am          |   1 +
 ipaserver/install/plugins/update_uniqueness.py | 115 +++++++++++++++++++++++++
 2 files changed, 116 insertions(+)
 create mode 100644 ipaserver/install/plugins/update_uniqueness.py

diff --git a/ipaserver/install/plugins/Makefile.am b/ipaserver/install/plugins/Makefile.am
index 7cf0495..635877d 100644
--- a/ipaserver/install/plugins/Makefile.am
+++ b/ipaserver/install/plugins/Makefile.am
@@ -12,6 +12,7 @@ app_PYTHON = 			\
 	update_anonymous_aci.py	\
 	update_pacs.py		\
 	ca_renewal_master.py	\
+	update_uniqueness.py	\
 	$(NULL)
 
 EXTRA_DIST =			\
diff --git a/ipaserver/install/plugins/update_uniqueness.py b/ipaserver/install/plugins/update_uniqueness.py
new file mode 100644
index 0000000..a1b4638
--- /dev/null
+++ b/ipaserver/install/plugins/update_uniqueness.py
@@ -0,0 +1,115 @@
+# Authors:
+#   Alexander Bokovoy <abokovoy at redhat.com>
+#
+# Copyright (C) 2014  Red Hat
+# see file 'COPYING' for use and warranty information
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+from ipaserver.install.plugins import MIDDLE
+from ipaserver.install.plugins.baseupdate import PostUpdate
+from ipalib import api, errors
+from ipapython.dn import DN
+from ipapython.ipa_log_manager import *
+
+
+class update_uid_uniqueness(PostUpdate):
+    """
+    Create plugin configuration to ensure uid uniqueness
+    """
+    order = MIDDLE
+
+    uid_uniqueness_dn = DN(('cn', 'uid uniqueness'), ('cn', 'plugins'), ('cn', 'config'))
+
+    uid_uniqueness_template = {
+     'objectClass'                   : ["top", "nsSlapdPlugin", "extensibleObject"],
+     'cn'                            : 'uid uniqueness',
+     'nsslapd-pluginPath'            : 'libattr-unique-plugin',
+     'nsslapd-pluginInitfunc'        : 'NSUniqueAttr_Init',
+     'nsslapd-pluginType'            : 'betxnpreoperation',
+     'nsslapd-pluginEnabled'         : 'on',
+     'uniqueness-attribute-name'     : 'uid',
+     'uniqueness-subtrees'           : 'dc=example,dc=com',
+     'uniqueness-across-all-subtrees': 'off',
+     'uniqueness-subtree-entries-oc' : 'posixAccount',
+     'nsslapd-plugin-depends-on-type': 'database',
+     'nsslapd-pluginId'              : 'none',
+     'nsslapd-pluginVersion'         : 'none',
+     'nsslapd-pluginVendor'          : 'none',
+     'nsslapd-pluginDescription'     : 'none',
+    }
+
+    def execute(self, **options):
+        ldap = self.obj.backend
+
+        config_dn = DN(('cn','config'))
+        search_filter = ("(&(objectclass=nsslapdplugin)"
+                           "(nsslapd-pluginpath=libattr-unique-plugin)"
+                           "(nsslapd-pluginInitfunc=NSUniqueAttr_Init)"
+                           "(!(nsslapd-pluginenabled=off))"
+                           "(|(uniqueness-attribute-name=uid)(nsslapd-plugarg0=uid)))")
+        root_logger.debug("update_uid_uniqueness: search for existing uid uniqueness "
+                          "configuration")
+
+        try:
+            (entries, truncated) = ldap.find_entries(search_filter, ['*'], config_dn,
+                                                     time_limit=0, size_limit=0)
+        except errors.NotFound:
+            # add entry
+            entries = []
+        except errors.ExecutionError, e:
+            root_logger.error("update_uid_uniqueness: cannot retrieve "
+                              "list of uniqueness plugin instances: %s", e)
+            return (False, False, [])
+
+        if len(entries) > 1:
+            root_logger.error("update_uid_uniqueness: found more than one uid "
+                              "uniqueness plugin definition: %s", [str(x.dn) for x in entries])
+            return (False, False, [])
+
+        error = False
+        if not entries:
+            root_logger.debug("update_uid_uniqueness: adding new uid uniqueness "
+                              "plugin definition")
+            uid_uniqueness_plugin_attrs = dict(self.uid_uniqueness_template)
+            uid_uniqueness_plugin_attrs['uniqueness-subtrees'] = api.env.basedn
+            uid_uniqueness_plugin = ldap.make_entry(self.uid_uniqueness_dn, uid_uniqueness_plugin_attrs)
+
+            try:
+                ldap.add_entry(uid_uniqueness_plugin)
+            except errors.ExecutionError, e:
+                root_logger.debug("update_uid_uniqueness: cannot "
+                                  "create uid uniqueness plugin entry: %s", e)
+                error = True
+        else:
+            root_logger.debug("update_uid_uniqueness: updating existing uid uniqueness "
+                              "plugin definition")
+            uid_uniqueness_plugin_attrs = dict(self.uid_uniqueness_template)
+            uid_uniqueness_plugin_attrs['uniqueness-subtrees'] = api.env.basedn
+            uid_uniqueness_plugin_attrs['cn'] = entries[0]['cn']
+            uid_uniqueness_plugin = ldap.make_entry(entries[0].dn, uid_uniqueness_plugin_attrs)
+
+            try:
+                ldap.update_entry(uid_uniqueness_plugin)
+            except errors.ExecutionError, e:
+                root_logger.debug("update_uid_uniqueness: cannot "
+                                  "update uid uniqueness plugin entry: %s", e)
+                error = True
+
+        if error:
+            root_logger.error("update_uid_uniqueness: error(s)"
+                              "detected during plugin update")
+        return (True, False, [])
+
+api.register(update_uid_uniqueness)
-- 
2.1.0



More information about the Freeipa-devel mailing list