summaryrefslogtreecommitdiffstats
path: root/ipaserver
diff options
context:
space:
mode:
authorMartin Basti <mbasti@redhat.com>2015-02-23 16:09:25 +0100
committerTomas Babej <tbabej@redhat.com>2015-03-05 12:43:35 +0100
commit4b2ec5468fd8b76d118f919f8d02ca4fccee9aab (patch)
treee8c9a311e4b01ef8027a3b150da62fb2bc204cc0 /ipaserver
parent8713c5a6953e92f72d9ea7aad40588c284011025 (diff)
downloadfreeipa-4b2ec5468fd8b76d118f919f8d02ca4fccee9aab.tar.gz
freeipa-4b2ec5468fd8b76d118f919f8d02ca4fccee9aab.tar.xz
freeipa-4b2ec5468fd8b76d118f919f8d02ca4fccee9aab.zip
Migrate uniquess plugins configuration to new style
New configuration style contains options required for user lifecycle management. Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
Diffstat (limited to 'ipaserver')
-rw-r--r--ipaserver/install/plugins/update_uniqueness.py203
1 files changed, 202 insertions, 1 deletions
diff --git a/ipaserver/install/plugins/update_uniqueness.py b/ipaserver/install/plugins/update_uniqueness.py
index a1b4638d6..8769f83a1 100644
--- a/ipaserver/install/plugins/update_uniqueness.py
+++ b/ipaserver/install/plugins/update_uniqueness.py
@@ -18,12 +18,213 @@
# 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 ipaserver.install.plugins.baseupdate import PostUpdate, PreUpdate
from ipalib import api, errors
from ipapython.dn import DN
from ipapython.ipa_log_manager import *
+class update_uniqueness_plugins_to_new_syntax(PreUpdate):
+ """
+ Migrate uniqueness plugins to new style syntax
+
+ * OLD: *
+ nsslapd-pluginarg0: uid
+ nsslapd-pluginarg1: dc=people,dc=example,dc=com
+ nsslapd-pluginarg2: dc=sales, dc=example,dc=com
+
+ or
+
+ nsslapd-pluginarg0: attribute=uid
+ nsslapd-pluginarg1: markerobjectclass=organizationalUnit
+ nsslapd-pluginarg2: requiredobjectclass=person
+
+ * NEW: *
+ uniqueness-attribute-name: uid
+ uniqueness-subtrees: dc=people,dc=example,dc=com
+ uniqueness-subtrees: dc=sales, dc=example,dc=com
+ uniqueness-across-all-subtrees: on
+
+ or
+
+ uniqueness-attribute-name: uid
+ uniqueness-top-entry-oc: organizationalUnit
+ uniqueness-subtree-entries-oc: person
+ """
+
+ plugins_dn = DN(('cn', 'plugins'), ('cn', 'config'))
+
+ def __remove_update(self, update, key, value):
+ # ldapupdate uses CSV, use '' for DN value
+ statement = "remove:%s:'%s'" % (key, value)
+ update.setdefault('updates', []).append(statement)
+
+ def __add_update(self, update, key, value):
+ # ldapupdate uses CSV, use '' for DN value
+ statement = "add:%s:'%s'" % (key, value)
+ update.setdefault('updates', []).append(statement)
+
+ def __subtree_style(self, entry):
+ """
+ old attr -> new attr
+ nsslapd-pluginArg0 -> uniqueness-attribute-name
+ nsslapd-pluginArg1..N -> uniqueness-subtrees[1..N]
+ """
+ update = {
+ 'dn': entry.dn,
+ 'updates': [],
+ }
+
+ # nsslapd-pluginArg0 -> referint-update-delay
+ attribute = entry.single_value['nsslapd-pluginArg0']
+ if not attribute:
+ raise ValueError("'nsslapd-pluginArg0' not found")
+ self.__remove_update(update, 'nsslapd-pluginArg0', attribute)
+ self.__add_update(update, 'uniqueness-attribute-name', attribute)
+ entry['nsslapd-pluginArg0'] = None
+
+ # nsslapd-pluginArg1..N -> uniqueness-subtrees[1..N]
+ for key in entry.keys():
+ if key.lower().startswith('nsslapd-pluginarg'):
+ subtree_dn = entry.single_value[key]
+ if subtree_dn:
+ self.__remove_update(update, key, subtree_dn)
+ self.__add_update(update, 'uniqueness-subtrees', subtree_dn)
+
+ return update
+
+ def __objectclass_style(self, entry):
+ """
+ old attr -> new attr
+ nsslapd-pluginArg?[attribute] -> uniqueness-attribute-name
+ nsslapd-pluginArg?[markerobjectclass] -> uniqueness-top-entry-oc
+ nsslapd-pluginArg?[requiredobjectclass](optional)
+ -> uniqueness-subtree-entries-oc
+ nsslapd-pluginArg?[others] -> ERROR: unexpected args
+
+ Single value attributes.
+ """
+
+ update = {
+ 'dn': entry.dn,
+ 'updates': [],
+ }
+
+ attribute = None
+ markerobjectclass = None
+ requiredobjectclass = None
+
+ for key in entry.keys():
+ if key.lower().startswith('nsslapd-pluginarg'):
+ try:
+ # split argument name and value
+ value = entry.single_value[key]
+ arg_name, arg_val = value.split('=', 1)
+ except ValueError:
+ # unable to split
+ raise ValueError("unexpected argument %s: %s" %
+ (key, value))
+ arg_name = arg_name.lower()
+ if arg_name == 'attribute':
+ if attribute:
+ raise ValueError("single value argument 'attribute' "
+ "is specified mutliple times")
+ attribute = arg_val
+ self.__remove_update(update, key, value)
+ elif arg_name == 'markerobjectclass':
+ if markerobjectclass:
+ raise ValueError("single value argument "
+ "'markerobjectclass' "
+ "is specified mutliple times")
+ markerobjectclass = arg_val
+ self.__remove_update(update, key, value)
+ elif arg_name == 'requiredobjectclass':
+ if requiredobjectclass:
+ raise ValueError("single value argument "
+ "'requiredobjectclass' "
+ "is specified mutliple times")
+ requiredobjectclass = arg_val
+ self.__remove_update(update, key, value)
+ else:
+ raise ValueError("unexpected argument '%s: %s'" %
+ (key, value))
+
+ if not attribute:
+ raise ValueError("missing required argument 'attribute'")
+ if not markerobjectclass:
+ raise ValueError("missing required argument 'markerobjectclass'")
+
+ self.__add_update(update, 'uniqueness-attribute-name', attribute)
+ self.__add_update(update, 'uniqueness-top-entry-oc', markerobjectclass)
+
+ if requiredobjectclass:
+ # optional argument
+ self.__add_update(update, 'uniqueness-subtree-entries-oc',
+ requiredobjectclass)
+
+ return update
+
+ def execute(self, **options):
+ ldap = self.obj.backend
+
+ old_style_plugin_search_filter = (
+ "(&"
+ "(objectclass=nsSlapdPlugin)"
+ "(nsslapd-pluginId=NSUniqueAttr)"
+ "(nsslapd-pluginPath=libattr-unique-plugin)"
+ "(nsslapd-pluginarg0=*)" # only entries with old configuration
+ ")"
+ )
+
+ try:
+ entries, truncated = ldap.find_entries(
+ filter=old_style_plugin_search_filter,
+ base_dn=self.plugins_dn,
+ )
+ except errors.NotFound:
+ root_logger.debug("No uniqueness plugin entries with old style "
+ "configuration found")
+ return False, False, []
+
+ update_list = []
+ new_attributes = [
+ 'uniqueness-subtree-entries-oc',
+ 'uniqueness-top-entry-oc',
+ 'uniqueness-attribute-name',
+ 'uniqueness-subtrees',
+ 'uniqueness-across-all-subtrees',
+ ]
+
+ for entry in entries:
+ # test for mixed configuration
+ if any(attr in entry for attr in new_attributes):
+ root_logger.critical("Mixed old and new style configuration "
+ "for plugin %s. Plugin will not work. "
+ "Skipping plugin migration, please fix it "
+ "manually",
+ entry.dn)
+ continue
+ root_logger.debug("Configuration of plugin %s will be migrated "
+ "to new style", entry.dn)
+ try:
+ # detect which configuration was used
+ arg0 = entry.get('nsslapd-pluginarg0')
+ if '=' in arg0:
+ update = self.__objectclass_style(entry)
+ else:
+ update = self.__subtree_style(entry)
+ except ValueError as e:
+ root_logger.error("Unable to migrate configuration of "
+ "plugin %s (%s)",
+ entry.dn, e)
+
+ update_list.append({entry.dn: update})
+
+ return False, True, update_list
+
+api.register(update_uniqueness_plugins_to_new_syntax)
+
+
class update_uid_uniqueness(PostUpdate):
"""
Create plugin configuration to ensure uid uniqueness