summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--install/share/unique-attributes.ldif24
-rw-r--r--install/updates/10-uniqueness.update36
-rw-r--r--ipaserver/install/plugins/update_uniqueness.py203
3 files changed, 232 insertions, 31 deletions
diff --git a/install/share/unique-attributes.ldif b/install/share/unique-attributes.ldif
index 0e680a0e4..ea38ac753 100644
--- a/install/share/unique-attributes.ldif
+++ b/install/share/unique-attributes.ldif
@@ -8,8 +8,8 @@ nsslapd-pluginPath: libattr-unique-plugin
nsslapd-pluginInitfunc: NSUniqueAttr_Init
nsslapd-pluginType: preoperation
nsslapd-pluginEnabled: on
-nsslapd-pluginarg0: krbPrincipalName
-nsslapd-pluginarg1: $SUFFIX
+uniqueness-attribute-name: krbPrincipalName
+uniqueness-subtrees: $SUFFIX
nsslapd-plugin-depends-on-type: database
nsslapd-pluginId: NSUniqueAttr
nsslapd-pluginVersion: 1.1.0
@@ -26,8 +26,8 @@ nsslapd-pluginPath: libattr-unique-plugin
nsslapd-pluginInitfunc: NSUniqueAttr_Init
nsslapd-pluginType: preoperation
nsslapd-pluginEnabled: on
-nsslapd-pluginarg0: krbCanonicalName
-nsslapd-pluginarg1: $SUFFIX
+uniqueness-attribute-name: krbCanonicalName
+uniqueness-subtrees: $SUFFIX
nsslapd-plugin-depends-on-type: database
nsslapd-pluginId: NSUniqueAttr
nsslapd-pluginVersion: 1.1.0
@@ -44,8 +44,8 @@ nsslapd-pluginPath: libattr-unique-plugin
nsslapd-pluginInitfunc: NSUniqueAttr_Init
nsslapd-pluginType: preoperation
nsslapd-pluginEnabled: on
-nsslapd-pluginarg0: cn
-nsslapd-pluginarg1: cn=ng,cn=alt,$SUFFIX
+uniqueness-attribute-name: cn
+uniqueness-subtrees: cn=ng,cn=alt,$SUFFIX
nsslapd-plugin-depends-on-type: database
nsslapd-pluginId: NSUniqueAttr
nsslapd-pluginVersion: 1.1.0
@@ -62,8 +62,8 @@ nsslapd-pluginPath: libattr-unique-plugin
nsslapd-pluginInitfunc: NSUniqueAttr_Init
nsslapd-pluginType: preoperation
nsslapd-pluginEnabled: on
-nsslapd-pluginarg0: ipaUniqueID
-nsslapd-pluginarg1: $SUFFIX
+uniqueness-attribute-name: ipaUniqueID
+uniqueness-subtrees: $SUFFIX
nsslapd-plugin-depends-on-type: database
nsslapd-pluginId: NSUniqueAttr
nsslapd-pluginVersion: 1.1.0
@@ -81,8 +81,8 @@ nsslapd-pluginPath: libattr-unique-plugin
nsslapd-pluginInitfunc: NSUniqueAttr_Init
nsslapd-pluginType: preoperation
nsslapd-pluginEnabled: on
-nsslapd-pluginarg0: cn
-nsslapd-pluginarg1: cn=sudorules,cn=sudo,$SUFFIX
+uniqueness-attribute-name: cn
+uniqueness-subtrees: cn=sudorules,cn=sudo,$SUFFIX
nsslapd-plugin-depends-on-type: database
nsslapd-pluginId: NSUniqueAttr
nsslapd-pluginVersion: 1.1.0
@@ -97,8 +97,8 @@ nsslapd-pluginVendor: Fedora Project
#nsslapd-pluginInitfunc: NSUniqueAttr_Init
#nsslapd-pluginType: preoperation
#nsslapd-pluginEnabled: on
-#nsslapd-pluginarg0: uid
-#nsslapd-pluginarg1: cn=accounts,$SUFFIX
+#uniqueness-attribute-name: uid
+#uniqueness-subtrees: cn=accounts,$SUFFIX
#nsslapd-plugin-depends-on-type: database
#nsslapd-pluginId: NSUniqueAttr
#nsslapd-pluginVersion: 1.1.0
diff --git a/install/updates/10-uniqueness.update b/install/updates/10-uniqueness.update
index c9641c47f..b6e2fff6d 100644
--- a/install/updates/10-uniqueness.update
+++ b/install/updates/10-uniqueness.update
@@ -8,8 +8,8 @@ default:nsslapd-pluginPath: libattr-unique-plugin
default:nsslapd-pluginInitfunc: NSUniqueAttr_Init
default:nsslapd-pluginType: preoperation
default:nsslapd-pluginEnabled: on
-default:nsslapd-pluginarg0: cn
-default:nsslapd-pluginarg1: cn=sudorules,cn=sudo,$SUFFIX
+default:uniqueness-attribute-name: cn
+default:uniqueness-subtrees: cn=sudorules,cn=sudo,$SUFFIX
default:nsslapd-plugin-depends-on-type: database
default:nsslapd-pluginId: NSUniqueAttr
default:nsslapd-pluginVersion: 1.1.0
@@ -25,8 +25,8 @@ default:nsslapd-pluginPath: libattr-unique-plugin
default:nsslapd-pluginInitfunc: NSUniqueAttr_Init
default:nsslapd-pluginType: preoperation
default:nsslapd-pluginEnabled: on
-default:nsslapd-pluginarg0: ipaCertSubject
-default:nsslapd-pluginarg1: cn=certificates,cn=ipa,cn=etc,$SUFFIX
+default:uniqueness-attribute-name: ipaCertSubject
+default:uniqueness-subtrees: cn=certificates,cn=ipa,cn=etc,$SUFFIX
default:nsslapd-plugin-depends-on-type: database
default:nsslapd-pluginId: NSUniqueAttr
default:nsslapd-pluginVersion: 1.1.0
@@ -42,8 +42,8 @@ default:nsslapd-pluginPath: libattr-unique-plugin
default:nsslapd-pluginInitfunc: NSUniqueAttr_Init
default:nsslapd-pluginType: preoperation
default:nsslapd-pluginEnabled: on
-default:nsslapd-pluginarg0: ipaCertIssuerSerial
-default:nsslapd-pluginarg1: cn=certificates,cn=ipa,cn=etc,$SUFFIX
+default:uniqueness-attribute-name: ipaCertIssuerSerial
+default:uniqueness-subtrees: cn=certificates,cn=ipa,cn=etc,$SUFFIX
default:nsslapd-plugin-depends-on-type: database
default:nsslapd-pluginId: NSUniqueAttr
default:nsslapd-pluginVersion: 1.1.0
@@ -51,26 +51,26 @@ default:nsslapd-pluginVendor: Fedora Project
# uid uniqueness scopes Active/Delete containers
dn: cn=attribute uniqueness,cn=plugins,cn=config
-remove:nsslapd-pluginarg1:'$SUFFIX'
-add:nsslapd-pluginarg1:'cn=accounts,$SUFFIX'
-add:nsslapd-pluginarg2:'cn=deleted users,cn=accounts,cn=provisioning,$SUFFIX'
+remove:uniqueness-subtrees:'$SUFFIX'
+add:uniqueness-subtrees:'cn=accounts,$SUFFIX'
+add:uniqueness-subtrees:'cn=deleted users,cn=accounts,cn=provisioning,$SUFFIX'
remove:nsslapd-pluginenabled:off
add:nsslapd-pluginenabled:on
# krbPrincipalName uniqueness scopes Active/Delete containers
dn: cn=krbPrincipalName uniqueness,cn=plugins,cn=config
-remove:nsslapd-pluginarg1:'$SUFFIX'
-add:nsslapd-pluginarg1:'cn=accounts,$SUFFIX'
-add:nsslapd-pluginarg2:'cn=deleted users,cn=accounts,cn=provisioning,$SUFFIX'
+remove:uniqueness-subtrees:'$SUFFIX'
+add:uniqueness-subtrees:'cn=accounts,$SUFFIX'
+add:uniqueness-subtrees:'cn=deleted users,cn=accounts,cn=provisioning,$SUFFIX'
# krbCanonicalName uniqueness scopes Active/Delete containers
dn: cn=krbCanonicalName uniqueness,cn=plugins,cn=config
-remove:nsslapd-pluginarg1:'$SUFFIX'
-add:nsslapd-pluginarg1:'cn=accounts,$SUFFIX'
-add:nsslapd-pluginarg2:'cn=deleted users,cn=accounts,cn=provisioning,$SUFFIX'
+remove:uniqueness-subtrees:'$SUFFIX'
+add:uniqueness-subtrees:'cn=accounts,$SUFFIX'
+add:uniqueness-subtrees:'cn=deleted users,cn=accounts,cn=provisioning,$SUFFIX'
# ipaUniqueID uniqueness scopes Active/Delete containers
dn: cn=ipaUniqueID uniqueness,cn=plugins,cn=config
-remove:nsslapd-pluginarg1:'$SUFFIX'
-add:nsslapd-pluginarg1:'cn=accounts,$SUFFIX'
-add:nsslapd-pluginarg2:'cn=deleted users,cn=accounts,cn=provisioning,$SUFFIX'
+remove:uniqueness-subtrees:'$SUFFIX'
+add:uniqueness-subtrees:'cn=accounts,$SUFFIX'
+add:uniqueness-subtrees:'cn=deleted users,cn=accounts,cn=provisioning,$SUFFIX'
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