From aba09d65076dead82b185e5756c3b8c3f34dac63 Mon Sep 17 00:00:00 2001
From: Christian Heimes <cheimes@redhat.com>
Date: Mon, 21 Sep 2020 12:39:52 +0200
Subject: [PATCH 01/11] Add helper for poll/sleep loops with timeout

The Sleeper class is a helper that makes poll/sleep loops with timeout
easier to write. It takes care of edge cases and does not oversleep
timeout deadline.

Signed-off-by: Christian Heimes <cheimes@redhat.com>
---
 ipapython/ipautil.py | 78 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 78 insertions(+)

diff --git a/ipapython/ipautil.py b/ipapython/ipautil.py
index ebf740be48..61cdf348ef 100644
--- a/ipapython/ipautil.py
+++ b/ipapython/ipautil.py
@@ -1654,3 +1654,81 @@ def datetime_from_utctimestamp(t, units=1):
         raise TypeError(t)
     epoch = datetime.datetime(1970, 1, 1, tzinfo=datetime.timezone.utc)
     return epoch + datetime.timedelta(seconds=v // units)
+
+
+class Sleeper:
+    """Helper for time.sleep() loop with timeout
+
+    A sleeper object sleeps *sleep* seconds when it is called. Close to its
+    deadline it sleeps shorter to not oversleep the *timeout* deadline. A
+    sleeper object is *True* and returns *True* before it reaches *timeout*
+    deadline. After its deadline a sleeper raises the exception object/class
+    in *raises*. If *raises* is not given, it returns False instead.
+
+    With *max_sleep* a sleeper slowly ramps up sleep duration starting with
+    *sleep* and slowly incrementing its sleep duration until it reaches
+    *max_sleep*. It never sleep longer than *max_sleep* or oversleeps
+    *timeout* deadline.
+
+    sleep = Sleeper(sleep=1, timeout=60, raises=TimeoutError)
+    while True:
+        do_something()
+        sleep()
+
+    sleep = Sleeper(sleep=0.25, max_sleep=5, timeout=60)
+    # sleeps 0.25, 0.5, 1, 2, 4, 5, 5, 5, ...
+
+    sleep = Sleeper(sleep=0.5, timeout=60)
+    while True:
+        try:
+            do_something
+        except Exception:
+            # sleep duration can be extended
+            sleep(10)
+        else:
+            if not sleep():
+                log.info("timeout")
+                break
+
+    longsleep = Sleeper(sleep=1, timeout=sys.maxsize)
+    """
+    multiplier = 2
+
+    def __init__(self, *, sleep, timeout, max_sleep=None, raises=None):
+        if timeout <= 0:
+            raise ValueError(f"invalid timeout {timeout}")
+        if sleep < 0.01:
+            raise ValueError(f"sleep duration {sleep} is too short.")
+        if max_sleep is not None and max_sleep < sleep:
+            raise ValueError(f"invalid max_sleep {max_sleep}")
+
+        self.timeout = timeout
+        self.initial_sleep = sleep
+        self.max_sleep = max_sleep if max_sleep is not None else sleep
+        self.raises = raises
+        self.next_sleep = self.initial_sleep
+        self.deadline = time.monotonic() + self.timeout
+
+    def __bool__(self):
+        return time.monotonic() < self.deadline
+
+    def __call__(self, extended_sleep=None):
+        now = time.monotonic()
+        if now >= self.deadline:
+            if self.raises is not None:
+                raise self.raises
+            else:
+                return False
+
+        # caller can instruct sleeper to sleep longer
+        dur = self.next_sleep if extended_sleep is None else extended_sleep
+        # but don't sleep over deadline
+        dur = min(self.deadline - now, dur)
+
+        time.sleep(dur)
+
+        # slowly increment but don't sleep longer than max sleep
+        self.next_sleep = min(
+            self.next_sleep * self.multiplier, self.max_sleep
+        )
+        return True

From 5eafd74666ace56cbb1cd6dadbac6c962cbbf50b Mon Sep 17 00:00:00 2001
From: Christian Heimes <cheimes@redhat.com>
Date: Mon, 21 Sep 2020 12:45:08 +0200
Subject: [PATCH 02/11] Faster certmonger wait_for_request()

wait_for_request() now waits 0.5 instead of 5 seconds. This shoves off
15 to 20 seconds from ipa-server-install while marginally increased
load on the system.

Signed-off-by: Christian Heimes <cheimes@redhat.com>
---
 ipalib/install/certmonger.py | 23 +++++++++++++++--------
 1 file changed, 15 insertions(+), 8 deletions(-)

diff --git a/ipalib/install/certmonger.py b/ipalib/install/certmonger.py
index 9e8d46fc17..fe74bd282b 100644
--- a/ipalib/install/certmonger.py
+++ b/ipalib/install/certmonger.py
@@ -34,6 +34,7 @@
 from ipalib import api
 from ipalib.constants import CA_DBUS_TIMEOUT
 from ipapython.dn import DN
+from ipapython.ipautil import Sleeper
 from ipaplatform.paths import paths
 from ipaplatform import services
 
@@ -772,14 +773,20 @@ def check_state(dirs):
 
 
 def wait_for_request(request_id, timeout=120):
-    for _i in range(0, timeout, 5):
-        state = get_request_value(request_id, 'status')
-        logger.debug("certmonger request is in state %r", state)
-        if state in ('CA_REJECTED', 'CA_UNREACHABLE', 'CA_UNCONFIGURED',
-                     'NEED_GUIDANCE', 'NEED_CA', 'MONITORING'):
+    sleep = Sleeper(
+        sleep=0.5,  # getcert.c:waitfor() uses 125ms
+        timeout=timeout,
+        raises=RuntimeError("request timed out")
+    )
+    last_state = None
+    while True:
+        state = str(get_request_value(request_id, 'status'))
+        if state != last_state:
+            logger.debug("certmonger request is in state %r", state)
+        if state in {'CA_REJECTED', 'CA_UNREACHABLE', 'CA_UNCONFIGURED',
+                     'NEED_GUIDANCE', 'NEED_CA', 'MONITORING'}:
             break
-        time.sleep(5)
-    else:
-        raise RuntimeError("request timed out")
+        last_state = state
+        sleep()
 
     return state

From 7e083fd67cd9b1d287a68b6bc8b2804d3a2245f3 Mon Sep 17 00:00:00 2001
From: Christian Heimes <cheimes@redhat.com>
Date: Mon, 21 Sep 2020 12:52:36 +0200
Subject: [PATCH 03/11] Remove root-autobind configuration

The new lib389-based installer configured 389-DS with LDAPI support and
autobind for root.

cn=root-autobind,cn=config entry is no longer needed.

Signed-off-by: Christian Heimes <cheimes@redhat.com>
---
 install/share/Makefile.am        |  1 -
 install/share/root-autobind.ldif | 19 -------------------
 install/updates/10-config.update |  4 ++++
 ipaserver/install/dsinstance.py  | 14 ++------------
 4 files changed, 6 insertions(+), 32 deletions(-)
 delete mode 100644 install/share/root-autobind.ldif

diff --git a/install/share/Makefile.am b/install/share/Makefile.am
index 026d83035c..db2469f0af 100644
--- a/install/share/Makefile.am
+++ b/install/share/Makefile.am
@@ -81,7 +81,6 @@ dist_app_DATA =				\
 	uuid.ldif		\
 	modrdn-krbprinc.ldif		\
 	entryusn.ldif			\
-	root-autobind.ldif		\
 	pw-logging-conf.ldif	\
 	sudobind.ldif			\
 	automember.ldif			\
diff --git a/install/share/root-autobind.ldif b/install/share/root-autobind.ldif
deleted file mode 100644
index ecce11511d..0000000000
--- a/install/share/root-autobind.ldif
+++ /dev/null
@@ -1,19 +0,0 @@
-# root-autobind, config
-dn: cn=root-autobind,cn=config
-changetype: add
-objectClass: extensibleObject
-objectClass: top
-cn: root-autobind
-uidNumber: 0
-gidNumber: 0
-
-dn: cn=config
-changetype: modify
-replace: nsslapd-ldapiautobind
-nsslapd-ldapiautobind: on
-
-dn: cn=config
-changetype: modify
-replace: nsslapd-ldapimaptoentries
-nsslapd-ldapimaptoentries: on
-
diff --git a/install/updates/10-config.update b/install/updates/10-config.update
index dec42c0254..8e930ee365 100644
--- a/install/updates/10-config.update
+++ b/install/updates/10-config.update
@@ -73,3 +73,7 @@ only:nsslapd-ioblocktimeout:10000
 # on LDAP bind, see https://pagure.io/freeipa/issue/8315
 dn: cn=config
 only: nsslapd-enable-upgrade-hash:off
+
+# lib389 configures 389-DS for root-autobind. Then entry is no longer needed.
+dn: cn=root-autobind,cn=config
+deleteentry: cn=root-autobind,cn=config
diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py
index 24316aaee4..01c541ac76 100644
--- a/ipaserver/install/dsinstance.py
+++ b/ipaserver/install/dsinstance.py
@@ -224,7 +224,6 @@ def __init__(self, realm_name=None, domain_name=None, fstore=None,
     def __common_setup(self):
 
         self.step("creating directory server instance", self.__create_instance)
-        self.step("configure autobind for root", self.__root_autobind)
         self.step("stopping directory server", self.__stop_instance)
         self.step("updating configuration in dse.ldif", self.__update_dse_ldif)
         self.step("starting directory server", self.__start_instance)
@@ -565,17 +564,16 @@ def __create_instance(self):
         inst.local_simple_allocate(
             serverid=self.serverid,
             ldapuri=ipaldap.get_ldap_uri(realm=self.realm, protocol='ldapi'),
-            password=self.dm_password
         )
 
         # local_simple_allocate() configures LDAPI but doesn't set up the
         # DirSrv object to use LDAPI. Modify the DirSrv() object to use
-        # LDAPI with password bind. autobind is not available, yet.
+        # LDAPI with with autobind.
         inst.ldapi_enabled = 'on'
+        inst.ldapi_autobind = 'on'
         inst.ldapi_socket = paths.SLAPD_INSTANCE_SOCKET_TEMPLATE % (
             self.serverid
         )
-        inst.ldapi_autobind = 'off'
 
         # This actually opens the conn and binds.
         inst.open()
@@ -1248,14 +1246,6 @@ def add_ca_cert(self, cacert_fname, cacert_name=''):
 
         return status
 
-    def __root_autobind(self):
-        self._ldap_mod(
-            "root-autobind.ldif",
-            ldap_uri=ipaldap.get_ldap_uri(realm=self.realm, protocol='ldapi'),
-            # must simple bind until auto bind is configured
-            dm_password=self.dm_password
-        )
-
     def __add_sudo_binduser(self):
         self._ldap_mod("sudobind.ldif", self.sub_dict)
 

From 5d2984aed4f850f7fc4c634385791cb03c418611 Mon Sep 17 00:00:00 2001
From: Christian Heimes <cheimes@redhat.com>
Date: Mon, 21 Sep 2020 13:15:32 +0200
Subject: [PATCH 04/11] Skip offline dse.ldif patching by default

The installer now stop and patches dse.ldif only when the option
--dirsrv-config-file is used. LDBM nsslapd-db-locks are increased in a
new step.

This speeds up installer by 4 or more seconds on a fast system.

Signed-off-by: Christian Heimes <cheimes@redhat.com>
---
 install/share/Makefile.am                     |  1 +
 install/share/ldbm-tuning.ldif                |  4 ++++
 ipaserver/install/dsinstance.py               | 21 +++++++++++--------
 .../test_integration/test_installation.py     |  9 ++++++++
 4 files changed, 26 insertions(+), 9 deletions(-)
 create mode 100644 install/share/ldbm-tuning.ldif

diff --git a/install/share/Makefile.am b/install/share/Makefile.am
index db2469f0af..91cf1848fd 100644
--- a/install/share/Makefile.am
+++ b/install/share/Makefile.am
@@ -107,6 +107,7 @@ dist_app_DATA =				\
 	pki-acme-database.conf.template	\
 	pki-acme-engine.conf.template	\
 	pki-acme-issuer.conf.template	\
+	ldbm-tuning.ldif		\
 	$(NULL)
 
 kdcproxyconfdir = $(IPA_SYSCONF_DIR)/kdcproxy
diff --git a/install/share/ldbm-tuning.ldif b/install/share/ldbm-tuning.ldif
new file mode 100644
index 0000000000..c54389b36f
--- /dev/null
+++ b/install/share/ldbm-tuning.ldif
@@ -0,0 +1,4 @@
+dn: cn=config,cn=ldbm database,cn=plugins,cn=config
+changetype: modify
+replace: nsslapd-db-locks
+nsslapd-db-locks: 50000
diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py
index 01c541ac76..4de09c6602 100644
--- a/ipaserver/install/dsinstance.py
+++ b/ipaserver/install/dsinstance.py
@@ -224,9 +224,13 @@ def __init__(self, realm_name=None, domain_name=None, fstore=None,
     def __common_setup(self):
 
         self.step("creating directory server instance", self.__create_instance)
-        self.step("stopping directory server", self.__stop_instance)
-        self.step("updating configuration in dse.ldif", self.__update_dse_ldif)
-        self.step("starting directory server", self.__start_instance)
+        self.step("tune ldbm plugin", self.__tune_ldbm)
+        if self.config_ldif is not None:
+            self.step("stopping directory server", self.__stop_instance)
+            self.step(
+                "updating configuration in dse.ldif", self.__update_dse_ldif
+            )
+            self.step("starting directory server", self.__start_instance)
         self.step("adding default schema", self.__add_default_schemas)
         self.step("enabling memberof plugin", self.__add_memberof_module)
         self.step("enabling winsync plugin", self.__add_winsync_module)
@@ -590,6 +594,9 @@ def __create_instance(self):
         # Done!
         logger.debug("completed creating DS instance")
 
+    def __tune_ldbm(self):
+        self._ldap_mod("ldbm-tuning.ldif")
+
     def __update_dse_ldif(self):
         """
         This method updates dse.ldif right after instance creation. This is
@@ -608,11 +615,6 @@ def __update_dse_ldif(self):
             temp_filename = new_dse_ldif.name
             with open(dse_filename, "r") as input_file:
                 parser = installutils.ModifyLDIF(input_file, new_dse_ldif)
-                parser.replace_value(
-                        'cn=config,cn=ldbm database,cn=plugins,cn=config',
-                        'nsslapd-db-locks',
-                        [b'50000']
-                        )
                 if self.config_ldif:
                     # parse modifications from ldif file supplied by the admin
                     with open(self.config_ldif, "r") as config_ldif:
@@ -664,7 +666,8 @@ def stop(self, instance_name="", capture_output=True):
         )
 
     def restart(self, instance_name="", capture_output=True, wait=True):
-        api.Backend.ldap2.disconnect()
+        if api.Backend.ldap2.isconnected():
+            api.Backend.ldap2.disconnect()
         try:
             super(DsInstance, self).restart(
                 instance_name, capture_output=capture_output, wait=wait
diff --git a/ipatests/test_integration/test_installation.py b/ipatests/test_integration/test_installation.py
index a82d4131c5..f3a5d75e9c 100644
--- a/ipatests/test_integration/test_installation.py
+++ b/ipatests/test_integration/test_installation.py
@@ -972,6 +972,15 @@ def test_ds_disable_upgrade_hash(self):
         )
         assert "nsslapd-enable-upgrade-hash: off" in result.stdout_text
 
+    def test_lmdb_tuning(self):
+        result = tasks.ldapsearch_dm(
+            self.master,
+            "cn=config,cn=ldbm database,cn=plugins,cn=config",
+            ldap_args=["nsslapd-db-locks"],
+            scope="base"
+        )
+        assert "nsslapd-db-locks: 50000" in result.stdout_text
+
     def test_admin_root_alias_CVE_2020_10747(self):
         # Test for CVE-2020-10747 fix
         # https://bugzilla.redhat.com/show_bug.cgi?id=1810160

From 0c3bcb8736e83096e3757531d282db086e1b74d4 Mon Sep 17 00:00:00 2001
From: Christian Heimes <cheimes@redhat.com>
Date: Mon, 21 Sep 2020 13:23:32 +0200
Subject: [PATCH 05/11] Retry chronyc waitsync only once

It's unlikely that a third chrony synchronization attempt is going to
succeed after the the first two attempts have failed. Only retry chronyc
waitsync once. Each retry adds a 10 second delay.

This speed up installer by 10 seconds on systems without fully
configured chronyd or no chronyd (e.g. containers).

Signed-off-by: Christian Heimes <cheimes@redhat.com>
---
 ipaclient/install/timeconf.py | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/ipaclient/install/timeconf.py b/ipaclient/install/timeconf.py
index cb4b78e113..57b01472c3 100644
--- a/ipaclient/install/timeconf.py
+++ b/ipaclient/install/timeconf.py
@@ -82,12 +82,10 @@ def sync_chrony():
     # Restart chronyd
     services.knownservices.chronyd.restart()
 
-    sync_attempt_count = 3
+    sync_attempt_count = 2
     # chrony attempt count to sync with configiured servers
-    # each next attempt is tried after 10seconds of timeot
-    # 3 attempts means: if first immidiate attempt fails
-    # there is 10s delay between next attempts
-
+    # each next attempt is tried after 10 seconds of timeout
+    # 2 attempts means: if first attempt fails there is a 10s delay
     args = [paths.CHRONYC, 'waitsync', str(sync_attempt_count), '-d']
 
     try:

From 78cdbc5487d98dda7c50ffa61ac779e62b76837c Mon Sep 17 00:00:00 2001
From: Christian Heimes <cheimes@redhat.com>
Date: Mon, 21 Sep 2020 13:47:38 +0200
Subject: [PATCH 06/11] Reduce CA record DNS timeout to 10s

30 seconds is still a lot of time for a DNS query. Clients typically
do not wait that long. OpenSSH uses 10 seconds for reverse DNS lookup.
That's considered a long timeout already. It's unlikely that a DNS query
is going to succeed after 10 seconds of failed lookups.

At this point during the installer IPA's BIND DNS instance has been
running long enough to be fully available, too.

The changeset reduces installation time by 40 seconds when ipa-ca DNS
has not been created yet.

See: https://pagure.io/freeipa/issue/6176
Signed-off-by: Christian Heimes <cheimes@redhat.com>
---
 ipaserver/dns_data_management.py | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/ipaserver/dns_data_management.py b/ipaserver/dns_data_management.py
index 9ef2e6c384..254001004b 100644
--- a/ipaserver/dns_data_management.py
+++ b/ipaserver/dns_data_management.py
@@ -17,11 +17,10 @@
 )
 from dns.exception import DNSException
 
-from time import sleep, time
-
 from ipalib import errors
 from ipalib.dns import record_name_format
 from ipapython.dnsutil import DNSName, resolve_rrsets
+from ipapython.ipautil import Sleeper
 
 if six.PY3:
     unicode=str
@@ -55,7 +54,7 @@
     (DNSName("_ntp._udp"), 123),
 )
 
-CA_RECORDS_DNS_TIMEOUT = 30  # timeout in seconds
+CA_RECORDS_DNS_TIMEOUT = 10  # timeout in seconds
 
 
 class IPADomainIsNotManagedByIPAError(Exception):
@@ -140,15 +139,19 @@ def __add_ca_records_from_hostname(self, zone_obj, hostname):
         assert isinstance(hostname, DNSName) and hostname.is_absolute()
         r_name = DNSName('ipa-ca') + self.domain_abs
         rrsets = []
-        end_time = time() + CA_RECORDS_DNS_TIMEOUT
-        while time() < end_time:
+        sleep = Sleeper(
+            sleep=1.0,
+            timeout=CA_RECORDS_DNS_TIMEOUT
+        )
+        while True:
             try:
                 rrsets = resolve_rrsets(hostname, (rdatatype.A, rdatatype.AAAA))
             except DNSException:  # logging is done inside resolve_rrsets
                 pass
             if rrsets:
                 break
-            sleep(5)
+            if not sleep():
+                break
 
         if not rrsets:
             logger.error('unable to resolve host name %s to IP address, '

From 1588352e07e9a83ede6aeef8b2c00690aade1794 Mon Sep 17 00:00:00 2001
From: Christian Heimes <cheimes@redhat.com>
Date: Mon, 21 Sep 2020 14:57:14 +0200
Subject: [PATCH 07/11] Skip duplicate import of cert profiles

All supported Dogtag versions import the cert profiles during pkispawn
when using the LDAP profile backend.

This reduces the installation time by 9 to 14 seconds.

Signed-off-by: Christian Heimes <cheimes@redhat.com>
---
 ipaserver/install/cainstance.py | 2 --
 1 file changed, 2 deletions(-)

diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py
index 4d96a099c1..9399cb5e74 100644
--- a/ipaserver/install/cainstance.py
+++ b/ipaserver/install/cainstance.py
@@ -463,8 +463,6 @@ def configure_instance(self, host_name, dm_password, admin_password,
                         self.step("exposing CA instance on LDAP",
                                   self.__expose_ca_in_ldap)
 
-                    self.step("migrating certificate profiles to LDAP",
-                              migrate_profiles_to_ldap)
                     self.step("importing IPA certificate profiles",
                               import_included_profiles)
                     self.step("adding default CA ACL", ensure_default_caacl)

From eac603afb8816748365299bf99d4578dc2d6cf6f Mon Sep 17 00:00:00 2001
From: Christian Heimes <cheimes@redhat.com>
Date: Mon, 21 Sep 2020 15:12:57 +0200
Subject: [PATCH 08/11] Use single update LDIF for indices

Index definitions were split across four files. indices.ldif contained
the initial subset of indices. Three update files partly duplicated the
indices and partly added new indices.

All indices are now defined in a single update file that is sorted
alphanumerically.

The changeset avoids two additional index tasks and reduces installation
time by 5 to 10 seconds.

Fixes: https://pagure.io/freeipa/issue/8493
Signed-off-by: Christian Heimes <cheimes@redhat.com>
---
 install/share/Makefile.am                  |   1 -
 install/share/indices.ldif                 | 429 -----------
 install/updates/20-idoverride_index.update |  22 -
 install/updates/20-indices.update          | 822 ++++++++++++---------
 install/updates/20-winsync_index.update    |  12 -
 install/updates/Makefile.am                |   2 -
 ipaserver/install/dsinstance.py            |   2 +-
 7 files changed, 494 insertions(+), 796 deletions(-)
 delete mode 100644 install/share/indices.ldif
 delete mode 100644 install/updates/20-idoverride_index.update
 delete mode 100644 install/updates/20-winsync_index.update

diff --git a/install/share/Makefile.am b/install/share/Makefile.am
index 91cf1848fd..684da8ddec 100644
--- a/install/share/Makefile.am
+++ b/install/share/Makefile.am
@@ -44,7 +44,6 @@ dist_app_DATA =				\
 	dnssec.ldif			\
 	domainlevel.ldif			\
 	kerberos.ldif			\
-	indices.ldif			\
 	bind.ipa-ext.conf.template		\
 	bind.ipa-options-ext.conf.template	\
 	bind.named.conf.template	\
diff --git a/install/share/indices.ldif b/install/share/indices.ldif
deleted file mode 100644
index 1e83c1046d..0000000000
--- a/install/share/indices.ldif
+++ /dev/null
@@ -1,429 +0,0 @@
-dn: cn=krbPrincipalName,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-objectClass:top
-objectClass:nsIndex
-cn:krbPrincipalName
-nsSystemIndex:false
-nsIndexType:eq
-nsIndexType:sub
-nsIndexType:pres
-nsMatchingRule:caseIgnoreIA5Match
-nsMatchingRule:caseExactIA5Match
-
-dn: cn=ou,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-objectClass:top
-objectClass:nsIndex
-cn:ou
-nsSystemIndex:false
-nsIndexType:eq
-nsIndexType:sub
-
-dn: cn=carLicense,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-objectClass:top
-objectClass:nsIndex
-cn:carLicense
-nsSystemIndex:false
-nsIndexType:eq
-nsIndexType:sub
-
-dn: cn=title,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-objectClass:top
-objectClass:nsIndex
-cn:title
-nsSystemIndex:false
-nsIndexType:eq
-nsIndexType:sub
-
-dn: cn=manager,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-objectClass:top
-objectClass:nsIndex
-cn:manager
-nsSystemIndex:false
-nsIndexType:eq
-nsIndexType:pres
-nsIndexType:sub
-
-dn: cn=secretary,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-objectClass:top
-objectClass:nsIndex
-cn:secretary
-nsSystemIndex:false
-nsIndexType:eq
-nsIndexType:pres
-nsIndexType:sub
-
-dn: cn=displayname,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-objectClass:top
-objectClass:nsIndex
-cn:displayname
-nsSystemIndex:false
-nsIndexType:eq
-nsIndexType:sub
-
-dn: cn=uid,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-changetype: modify
-add: nsIndexType
-nsIndexType:sub
-
-dn: cn=uidnumber,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-objectClass:top
-objectClass:nsIndex
-cn:uidnumber
-nsSystemIndex:false
-nsIndexType:eq
-nsMatchingRule: integerOrderingMatch
-
-dn: cn=gidnumber,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-objectClass:top
-objectClass:nsIndex
-cn:gidnumber
-nsSystemIndex:false
-nsIndexType:eq
-nsMatchingRule: integerOrderingMatch
-
-dn: cn=ntUniqueId,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-changetype: modify
-replace: nsIndexType
-nsIndexType: eq
-nsIndexType: pres
-
-dn: cn=ntUserDomainId,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-changetype: modify
-replace: nsIndexType
-nsIndexType: eq
-nsIndexType: pres
-
-dn: cn=fqdn,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-ObjectClass: top
-ObjectClass: nsIndex
-cn: fqdn
-nsSystemIndex: false
-nsIndexType: eq
-nsIndexType: pres
-nsIndexType: sub
-
-dn: cn=macAddress,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-ObjectClass: top
-ObjectClass: nsIndex
-cn: macAddress
-nsSystemIndex: false
-nsIndexType: eq
-nsIndexType: pres
-
-dn: cn=memberHost,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-cn: memberHost
-ObjectClass: top
-ObjectClass: nsIndex
-nsSystemIndex: false
-nsIndexType: eq
-nsIndexType: pres
-nsIndexType: sub
-
-dn: cn=memberUser,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-cn: memberUser
-ObjectClass: top
-ObjectClass: nsIndex
-nsSystemIndex: false
-nsIndexType: eq
-nsIndexType: pres
-nsIndexType: sub
-
-dn: cn=sourcehost,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-cn: sourcehost
-ObjectClass: top
-ObjectClass: nsIndex
-nsSystemIndex: false
-nsIndexType: eq
-nsIndexType: pres
-nsIndexType: sub
-
-dn: cn=memberservice,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-cn: memberservice
-ObjectClass: top
-ObjectClass: nsIndex
-nsSystemIndex: false
-nsIndexType: eq
-nsIndexType: pres
-nsIndexType: sub
-
-dn: cn=managedby,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-cn: managedby
-ObjectClass: top
-ObjectClass: nsIndex
-nsSystemIndex: false
-nsIndexType: eq
-nsIndexType: pres
-nsIndexType: sub
-
-dn: cn=memberallowcmd,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-cn: memberallowcmd
-ObjectClass: top
-ObjectClass: nsIndex
-nsSystemIndex: false
-nsIndexType: eq
-nsIndexType: pres
-nsIndexType: sub
-
-dn: cn=memberdenycmd,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-cn: memberdenycmd
-ObjectClass: top
-ObjectClass: nsIndex
-nsSystemIndex: false
-nsIndexType: eq
-nsIndexType: pres
-nsIndexType: sub
-
-dn: cn=ipasudorunas,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-cn: ipasudorunas
-ObjectClass: top
-ObjectClass: nsIndex
-nsSystemIndex: false
-nsIndexType: eq
-nsIndexType: pres
-nsIndexType: sub
-
-dn: cn=ipasudorunasgroup,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-cn: ipasudorunasgroup
-ObjectClass: top
-ObjectClass: nsIndex
-nsSystemIndex: false
-nsIndexType: eq
-nsIndexType: pres
-nsIndexType: sub
-
-dn: cn=automountkey,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-cn: automountkey
-ObjectClass: top
-ObjectClass: nsIndex
-nsSystemIndex: false
-nsIndexType: eq
-nsIndexType: pres
-
-dn: cn=automountMapName,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-cn: automountMapName
-ObjectClass: top
-ObjectClass: nsIndex
-nsSystemIndex: false
-nsIndexType: eq
-
-dn: cn=ipaConfigString,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-cn: ipaConfigString
-objectClass:top
-objectClass:nsIndex
-nsSystemIndex: false
-nsIndexType: eq
-
-dn: cn=ipaEnabledFlag,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-cn: ipaEnabledFlag
-objectClass:top
-objectClass:nsIndex
-nsSystemIndex: false
-nsIndexType: eq
-
-dn: cn=ipaKrbAuthzData,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-cn: ipaKrbAuthzData
-objectClass: top
-objectClass: nsIndex
-nsSystemIndex: false
-nsIndexType: eq
-nsIndexType: sub
-
-dn: cn=ipakrbprincipalalias,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-cn: ipakrbprincipalalias
-ObjectClass: top
-ObjectClass: nsIndex
-nsSystemIndex: false
-nsIndexType: eq
-
-dn: cn=ipauniqueid,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-cn: ipauniqueid
-ObjectClass: top
-ObjectClass: nsIndex
-nsSystemIndex: false
-nsIndexType: eq
-
-dn: cn=ipaMemberCa,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-cn: ipaMemberCa
-ObjectClass: top
-ObjectClass: nsIndex
-nsSystemIndex: false
-nsIndexType: eq
-nsIndexType: pres
-nsIndexType: sub
-
-dn: cn=ipaMemberCertProfile,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-cn: ipaMemberCertProfile
-ObjectClass: top
-ObjectClass: nsIndex
-nsSystemIndex: false
-nsIndexType: eq
-nsIndexType: pres
-nsIndexType: sub
-
-dn: cn=userCertificate,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-cn: userCertificate
-ObjectClass: top
-ObjectClass: nsIndex
-nsSystemIndex: false
-nsIndexType: eq
-nsIndexType: pres
-
-dn: cn=ipalocation,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-cn: ipalocation
-ObjectClass: top
-ObjectClass: nsIndex
-nsSystemIndex: false
-nsIndexType: eq
-nsIndexType: pres
-
-dn: cn=krbCanonicalName,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-cn: krbCanonicalName
-objectClass: top
-objectClass: nsIndex
-nsSystemIndex: false
-nsIndexType: eq
-nsIndexType: sub
-
-dn: cn=serverhostname,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-cn: serverhostname
-objectClass: top
-objectClass: nsIndex
-nsSystemIndex: false
-nsIndexType: eq
-nsIndexType: sub
-
-dn: cn=description,cn=index,cn=userroot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-cn: description
-objectClass: top
-objectClass: nsindex
-nssystemindex: false
-nsindextype: eq
-nsindextype: sub
-
-dn: cn=l,cn=index,cn=userroot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-cn: l
-objectClass: top
-objectClass: nsindex
-nssystemindex: false
-nsindextype: eq
-nsindextype: sub
-
-dn: cn=nsOsVersion,cn=index,cn=userroot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-cn: nsOsVersion
-objectClass: top
-objectClass: nsindex
-nssystemindex: false
-nsindextype: eq
-nsindextype: sub
-
-dn: cn=nsHardwarePlatform,cn=index,cn=userroot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-cn: nsHardwarePlatform
-objectClass: top
-objectClass: nsindex
-nssystemindex: false
-nsindextype: eq
-nsindextype: sub
-
-dn: cn=nsHostLocation,cn=index,cn=userroot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-cn: nsHostLocation
-objectClass: top
-objectClass: nsindex
-nssystemindex: false
-nsindextype: eq
-nsindextype: sub
-
-# NOTE: There is no index on ipServiceProtocol because the index would have
-# poor selectivity. An ipService entry has either 'tcp' or 'udp' as protocol.
-dn: cn=ipServicePort,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-cn: ipServicePort
-objectClass: top
-objectClass: nsIndex
-nsSystemIndex: false
-nsIndexType: eq
-
-dn: cn=accessRuleType,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-cn: accessRuleType
-objectClass:top
-objectClass:nsIndex
-nsSystemIndex: false
-nsIndexType: eq
-
-dn: cn=hostCategory,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-cn: hostCategory
-objectClass:top
-objectClass:nsIndex
-nsSystemIndex: false
-nsIndexType: eq
-
-dn: cn=idnsName,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-cn: idnsName
-objectClass: top
-objectClass: nsIndex
-nsSystemIndex: false
-nsIndexType: eq
-
-dn: cn=ipaCertmapData,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-cn: ipaCertmapData
-objectClass: top
-objectClass: nsIndex
-nsSystemIndex: false
-nsIndexType: eq
-
-dn: cn=altSecurityIdentities,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-cn: altSecurityIdentities
-objectClass: top
-objectClass: nsIndex
-nsSystemIndex: false
-nsIndexType: eq
-
-dn: cn=memberManager,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-changetype: add
-cn: memberManager
-objectClass: top
-objectClass: nsIndex
-nsSystemIndex: false
-nsIndexType: eq
-nsIndexType: pres
diff --git a/install/updates/20-idoverride_index.update b/install/updates/20-idoverride_index.update
deleted file mode 100644
index 63d622f1f0..0000000000
--- a/install/updates/20-idoverride_index.update
+++ /dev/null
@@ -1,22 +0,0 @@
-#
-# Make sure ID override attributes have the correct indexing
-#
-
-dn: cn=ipaOriginalUid,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-default:cn: ipaOriginalUid
-default:ObjectClass: top
-default:ObjectClass: nsIndex
-default:nsSystemIndex: false
-only: nsIndexType: eq
-only: nsIndexType: pres
-
-dn: cn=ipaAnchorUUID,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-default:cn: ipaAnchorUUID
-default:ObjectClass: top
-default:ObjectClass: nsIndex
-default:nsSystemIndex: false
-only: nsIndexType: eq
-only: nsIndexType: pres
-
-dn: cn=ipaAnchorUUID,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-remove:cn: ipaOriginalUid
diff --git a/install/updates/20-indices.update b/install/updates/20-indices.update
index 65ee183a80..e060622cc3 100644
--- a/install/updates/20-indices.update
+++ b/install/updates/20-indices.update
@@ -1,412 +1,576 @@
+# Indices
 #
-# Some nss_ldap implementations will always ask for memberuid so we must
-# have an index for it.
+# - cn uses "only" to avoid bugs like https://pagure.io/freeipa/issue/6975
+# - nsIndexType uses "add" to allow users to add additional index types
+#   more easily. The "add" command adds index types that are required by
+#   IPA but does not remove additional index types.
 #
-# FreeIPA frequently searches for memberHost and memberUser to determine
-# group membership.
+# NOTE: There is no index on ipServiceProtocol because the index would have
+# poor selectivity. An ipService entry has either 'tcp' or 'udp' as protocol.
 #
-dn: cn=memberuid,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-default:cn: memberuid
-default:ObjectClass: top
-default:ObjectClass: nsIndex
+# Please keep entries sorted
+#
+
+dn: cn=accessRuleType,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: accessRuleType
+default:objectClass: nsIndex
+default:objectClass: top
 default:nsSystemIndex: false
-only:nsIndexType: eq
-only:nsIndexType: pres
+add:nsIndexType: eq
 
-dn: cn=memberHost,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-default:cn: memberHost
-default:ObjectClass: top
-default:ObjectClass: nsIndex
+dn: cn=altSecurityIdentities,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: altSecurityIdentities
+default:objectClass: nsIndex
+default:objectClass: top
 default:nsSystemIndex: false
-only:nsIndexType: eq
-only:nsIndexType: pres
-only:nsIndexType: sub
+add:nsIndexType: eq
 
-dn: cn=memberUser,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-default:cn: memberUser
-default:ObjectClass: top
-default:ObjectClass: nsIndex
+dn: cn=automountkey,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: automountkey
+default:objectClass: nsIndex
+default:objectClass: top
 default:nsSystemIndex: false
-only:nsIndexType: eq
-only:nsIndexType: pres
-only:nsIndexType: sub
+add:nsIndexType: eq
+add:nsIndexType: pres
 
-dn: cn=member,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-only:nsIndexType: eq
-only:nsIndexType: pres
-only:nsIndexType: sub
+dn: cn=automountMapName,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: automountMapName
+default:objectClass: nsIndex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
 
-dn: cn=uniquemember,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-only:nsIndexType: eq
-only:nsIndexType: sub
+dn: cn=carLicense,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: carLicense
+default:objectClass: nsIndex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
+add:nsIndexType: sub
 
-dn: cn=owner,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-only:nsIndexType: eq
-only:nsIndexType: sub
+dn: cn=cn,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: cn
+default:objectClass: nsIndex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
+add:nsIndexType: pres
+add:nsIndexType: sub
 
-dn: cn=manager,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-only:nsIndexType: eq
-only:nsIndexType: pres
-only:nsIndexType: sub
+dn: cn=description,cn=index,cn=userroot,cn=ldbm database,cn=plugins,cn=config
+only:cn: description
+default:objectClass: nsindex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
+add:nsIndexType: sub
 
-dn: cn=secretary,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-only:nsIndexType: eq
-only:nsIndexType: pres
-only:nsIndexType: sub
+dn: cn=displayname,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: displayname
+default:objectClass: nsIndex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
+add:nsIndexType: sub
+
+dn: cn=fqdn,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: fqdn
+default:objectClass: nsIndex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
+add:nsIndexType: pres
+add:nsIndexType: sub
 
-dn: cn=seealso,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-only:nsIndexType: eq
-only:nsIndexType: sub
+dn: cn=gidnumber,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: gidnumber
+default:objectClass: nsIndex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
 
-dn: cn=memberof,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-default:cn: memberof
-default:ObjectClass: top
-default:ObjectClass: nsIndex
+dn: cn=givenName,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: givenName
+default:objectClass: nsIndex
+default:objectClass: top
 default:nsSystemIndex: false
-default:nsIndexType: eq
+add:nsIndexType: eq
+add:nsIndexType: pres
+add:nsIndexType: sub
 
-dn: cn=fqdn,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-default:cn: fqdn
-default:ObjectClass: top
-default:ObjectClass: nsIndex
+dn: cn=hostCategory,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: hostCategory
+default:objectClass: nsIndex
+default:objectClass: top
 default:nsSystemIndex: false
-only:nsIndexType: eq
-only:nsIndexType: pres
-only:nsIndexType: sub
+add:nsIndexType: eq
 
-dn: cn=macAddress,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-default:cn: macAddress
-default:ObjectClass: top
-default:ObjectClass: nsIndex
+dn: cn=idnsName,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: idnsName
+default:objectClass: nsIndex
+default:objectClass: top
 default:nsSystemIndex: false
-default:nsIndexType: eq
-default:nsIndexType: pres
+add:nsIndexType: eq
 
-dn: cn=sourcehost,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-default:cn: sourcehost
-default:ObjectClass: top
-default:ObjectClass: nsIndex
+dn: cn=ipaallowedtarget,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: ipaallowedtarget
+default:objectClass: nsIndex
+default:objectClass: top
 default:nsSystemIndex: false
-only:nsIndexType: eq
-only:nsIndexType: pres
-only:nsIndexType: sub
+add:nsIndexType: eq
+add:nsIndexType: pres
+add:nsIndexType: sub
 
-dn: cn=memberservice,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-default:cn: memberservice
-default:ObjectClass: top
-default:ObjectClass: nsIndex
+dn: cn=ipaAnchorUUID,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: ipaAnchorUUID
+default:objectClass: nsIndex
+default:objectClass: top
 default:nsSystemIndex: false
-only:nsIndexType: eq
-only:nsIndexType: pres
-only:nsIndexType: sub
+add:nsIndexType: eq
+add:nsIndexType: pres
 
-dn: cn=managedby,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-default:cn: managedby
-default:ObjectClass: top
-default:ObjectClass: nsIndex
+dn: cn=ipaassignedidview,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: ipaassignedidview
+default:objectClass: nsIndex
+default:objectClass: top
 default:nsSystemIndex: false
-only:nsIndexType: eq
-only:nsIndexType: pres
-only:nsIndexType: sub
+add:nsIndexType: eq
+add:nsIndexType: pres
+add:nsIndexType: sub
 
-dn: cn=memberallowcmd,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-default:cn: memberallowcmd
-default:ObjectClass: top
-default:ObjectClass: nsIndex
+dn: cn=ipaCertmapData,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: ipaCertmapData
+default:objectClass: nsIndex
+default:objectClass: top
 default:nsSystemIndex: false
-only:nsIndexType: eq
-only:nsIndexType: pres
-only:nsIndexType: sub
+add:nsIndexType: eq
 
-dn: cn=memberdenycmd,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-default:cn: memberdenycmd
-default:ObjectClass: top
-default:ObjectClass: nsIndex
+dn: cn=ipaConfigString,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: ipaConfigString
+default:objectClass: nsIndex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
+
+dn: cn=ipaEnabledFlag,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: ipaEnabledFlag
+default:objectClass: nsIndex
+default:objectClass: top
 default:nsSystemIndex: false
-only:nsIndexType: eq
-only:nsIndexType: pres
-only:nsIndexType: sub
+add:nsIndexType: eq
+
+dn: cn=ipaKrbAuthzData,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: ipaKrbAuthzData
+default:objectClass: nsIndex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
+add:nsIndexType: sub
+
+dn: cn=ipakrbprincipalalias,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: ipakrbprincipalalias
+default:objectClass: nsIndex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
+
+dn: cn=ipalocation,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: ipalocation
+default:objectClass: nsIndex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
+add:nsIndexType: pres
+
+dn: cn=ipaMemberCa,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: ipaMemberCa
+default:objectClass: nsIndex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
+add:nsIndexType: pres
+add:nsIndexType: sub
+
+dn: cn=ipaMemberCertProfile,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: ipaMemberCertProfile
+default:objectClass: nsIndex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
+add:nsIndexType: pres
+add:nsIndexType: sub
+
+dn: cn=ipaOriginalUid,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: ipaOriginalUid
+default:objectClass: nsIndex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
+add:nsIndexType: pres
 
 dn: cn=ipasudorunas,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-default:cn: ipasudorunas
-default:ObjectClass: top
-default:ObjectClass: nsIndex
+only:cn: ipasudorunas
+default:objectClass: nsIndex
+default:objectClass: top
 default:nsSystemIndex: false
-only:nsIndexType: eq
-only:nsIndexType: pres
-only:nsIndexType: sub
+add:nsIndexType: eq
+add:nsIndexType: pres
+add:nsIndexType: sub
 
 dn: cn=ipasudorunasgroup,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-default:cn: ipasudorunasgroup
-default:ObjectClass: top
-default:ObjectClass: nsIndex
+only:cn: ipasudorunasgroup
+default:objectClass: nsIndex
+default:objectClass: top
 default:nsSystemIndex: false
-only:nsIndexType: eq
-only:nsIndexType: pres
-only:nsIndexType: sub
+add:nsIndexType: eq
+add:nsIndexType: pres
+add:nsIndexType: sub
 
-dn: cn=automountkey,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-default:cn: automountkey
-default:ObjectClass: top
-default:ObjectClass: nsIndex
+dn: cn=ipatokenradiusconfiglink,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: ipatokenradiusconfiglink
+default:objectClass: nsIndex
+default:objectClass: top
 default:nsSystemIndex: false
-default:nsIndexType: eq
+add:nsIndexType: eq
 add:nsIndexType: pres
+add:nsIndexType: sub
 
-dn: cn=automountMapName,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-default: cn: automountMapName
-default: ObjectClass: top
-default: ObjectClass: nsIndex
-default: nsSystemIndex: false
-default: nsIndexType: eq
+dn: cn=ipauniqueid,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: ipauniqueid
+default:objectClass: nsIndex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
 
-dn: cn=ipaConfigString,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-default: cn: ipaConfigString
-default: objectClass:top
-default: objectClass:nsIndex
-default: nsSystemIndex: false
-default: nsIndexType: eq
+dn: cn=ipServicePort,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: ipServicePort
+default:objectClass: nsIndex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
 
-dn: cn=ipaEnabledFlag,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-default: cn: ipaEnabledFlag
-default: objectClass:top
-default: objectClass:nsIndex
-default: nsSystemIndex: false
-default: nsIndexType: eq
+dn: cn=krbCanonicalName,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: krbCanonicalName
+default:objectClass: nsIndex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
+add:nsIndexType: sub
 
-dn: cn=ipaKrbAuthzData,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-default: cn: ipaKrbAuthzData
-default: objectClass: top
-default: objectClass: nsIndex
-default: nsSystemIndex: false
-default: nsIndexType: eq
-default: nsIndexType: sub
+dn: cn=krbPasswordExpiration,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: krbPasswordExpiration
+default:objectClass: nsIndex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
 
-dn: cn=ipakrbprincipalalias,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-default:cn: ipakrbprincipalalias
-default:ObjectClass: top
-default:ObjectClass: nsIndex
+dn: cn=krbPrincipalName,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: krbPrincipalName
+default:objectClass: nsIndex
+default:objectClass: top
 default:nsSystemIndex: false
-default:nsIndexType: eq
+add:nsIndexType: eq
+add:nsIndexType: sub
 
-dn: cn=ipauniqueid,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-default:cn: ipauniqueid
-default:ObjectClass: top
-default:ObjectClass: nsIndex
+dn: cn=l,cn=index,cn=userroot,cn=ldbm database,cn=plugins,cn=config
+only:cn: l
+default:objectClass: nsindex
+default:objectClass: top
 default:nsSystemIndex: false
-default:nsIndexType: eq
+add:nsIndexType: eq
+add:nsIndexType: sub
 
-dn: cn=ipatokenradiusconfiglink,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-default:cn: ipatokenradiusconfiglink
-default:ObjectClass: top
-default:ObjectClass: nsIndex
+dn: cn=macAddress,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: macAddress
+default:objectClass: nsIndex
+default:objectClass: top
 default:nsSystemIndex: false
-only:nsIndexType: eq
-only:nsIndexType: pres
-only:nsIndexType: sub
+add:nsIndexType: eq
+add:nsIndexType: pres
 
-dn: cn=ipaassignedidview,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-default:cn: ipaassignedidview
-default:ObjectClass: top
-default:ObjectClass: nsIndex
+dn: cn=mail,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: mail
+default:objectClass: nsIndex
+default:objectClass: top
 default:nsSystemIndex: false
-only:nsIndexType: eq
-only:nsIndexType: pres
-only:nsIndexType: sub
+add:nsIndexType: eq
+add:nsIndexType: pres
+add:nsIndexType: sub
 
-dn: cn=ipaallowedtarget,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-default:cn: ipaallowedtarget
-default:ObjectClass: top
-default:ObjectClass: nsIndex
+dn: cn=mailAlternateAddress,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: mailAlternateAddress
+default:objectClass: nsIndex
+default:objectClass: top
 default:nsSystemIndex: false
-only:nsIndexType: eq
-only:nsIndexType: pres
-only:nsIndexType: sub
+add:nsIndexType: eq
 
-dn: cn=ipaMemberCa,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-default:cn: ipaMemberCa
-default:ObjectClass: top
-default:ObjectClass: nsIndex
+dn: cn=mailHost,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: mailHost
+default:objectClass: nsIndex
+default:objectClass: top
 default:nsSystemIndex: false
-only:nsIndexType: eq
-only:nsIndexType: pres
-only:nsIndexType: sub
+add:nsIndexType: eq
 
-dn: cn=ipaMemberCertProfile,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-default:cn: ipaMemberCertProfile
-default:ObjectClass: top
-default:ObjectClass: nsIndex
+dn: cn=managedby,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: managedby
+default:objectClass: nsIndex
+default:objectClass: top
 default:nsSystemIndex: false
-only:nsIndexType: eq
-only:nsIndexType: pres
-only:nsIndexType: sub
+add:nsIndexType: eq
+add:nsIndexType: pres
+add:nsIndexType: sub
 
-dn: cn=userCertificate,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-default:cn: userCertificate
-default:ObjectClass: top
-default:ObjectClass: nsIndex
-only:nsSystemIndex: false
-only:nsIndexType: eq
-only:nsIndexType: pres
+dn: cn=manager,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: manager
+default:objectClass: nsIndex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
+add:nsIndexType: pres
+add:nsIndexType: sub
 
-dn: cn=ntUniqueId,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-default:cn: ntUniqueId
-default:ObjectClass: top
-default:ObjectClass: nsIndex
+dn: cn=member,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: member
+default:objectClass: nsIndex
+default:objectClass: top
 default:nsSystemIndex: false
-only:nsIndexType: eq
-only:nsIndexType: pres
+add:nsIndexType: eq
+add:nsIndexType: pres
+add:nsIndexType: sub
 
-dn: cn=ntUserDomainId,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-default:cn: ntUserDomainId
-default:ObjectClass: top
-default:ObjectClass: nsIndex
+dn: cn=memberallowcmd,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: memberallowcmd
+default:objectClass: nsIndex
+default:objectClass: top
 default:nsSystemIndex: false
-only:nsIndexType: eq
-only:nsIndexType: pres
+add:nsIndexType: eq
+add:nsIndexType: pres
+add:nsIndexType: sub
 
-dn: cn=ipalocation,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-default:cn: ipalocation
-default:ObjectClass: top
-default:ObjectClass: nsIndex
+dn: cn=memberdenycmd,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: memberdenycmd
+default:objectClass: nsIndex
+default:objectClass: top
 default:nsSystemIndex: false
-only:nsIndexType: eq
-only:nsIndexType: pres
+add:nsIndexType: eq
+add:nsIndexType: pres
+add:nsIndexType: sub
 
-dn: cn=krbPrincipalName,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-default:cn: krbPrincipalName
-default:ObjectClass: top
-default:ObjectClass: nsIndex
+dn: cn=memberHost,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: memberHost
+default:objectClass: nsIndex
+default:objectClass: top
 default:nsSystemIndex: false
-only: nsMatchingRule: caseIgnoreIA5Match
-only: nsMatchingRule: caseExactIA5Match
-only:nsIndexType: eq
-only:nsIndexType: sub
-only:nsIndexType: pres
+add:nsIndexType: eq
+add:nsIndexType: pres
+add:nsIndexType: sub
 
-dn: cn=krbCanonicalName,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-default: cn: krbCanonicalName
-default: objectClass: top
-default: objectClass: nsIndex
-only: nsSystemIndex: false
-only: nsIndexType: eq
-only: nsIndexType: sub
+dn: cn=memberManager,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: memberManager
+default:objectClass: nsIndex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
+add:nsIndexType: pres
 
-dn: cn=serverhostname,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-default: cn: serverhostname
-default: objectClass: top
-default: objectClass: nsIndex
-only: nsSystemIndex: false
-only: nsIndexType: eq
-only: nsIndexType: sub
+dn: cn=memberOf,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: memberOf
+default:objectClass: nsIndex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
 
-dn: cn=description,cn=index,cn=userroot,cn=ldbm database,cn=plugins,cn=config
-default: cn: description
-default: objectclass: top
-default: objectclass: nsindex
-default: nssystemindex: false
-default: nsindextype: eq
-default: nsindextype: sub
+dn: cn=memberservice,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: memberservice
+default:objectClass: nsIndex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
+add:nsIndexType: pres
+add:nsIndexType: sub
 
-dn: cn=l,cn=index,cn=userroot,cn=ldbm database,cn=plugins,cn=config
-default: cn: l
-default: objectclass: top
-default: objectclass: nsindex
-default: nssystemindex: false
-default: nsindextype: eq
-default: nsindextype: sub
+dn: cn=memberuid,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: memberuid
+default:objectClass: nsIndex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
+add:nsIndexType: pres
 
-dn: cn=nsOsVersion,cn=index,cn=userroot,cn=ldbm database,cn=plugins,cn=config
-default: cn: nsOsVersion
-default: objectclass: top
-default: objectclass: nsindex
-default: nssystemindex: false
-default: nsindextype: eq
-default: nsindextype: sub
+dn: cn=memberUser,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: memberUser
+default:objectClass: nsIndex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
+add:nsIndexType: pres
+add:nsIndexType: sub
+
+dn: cn=nsCertSubjectDN,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: nsCertSubjectDN
+default:objectClass: nsIndex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
 
 dn: cn=nsHardwarePlatform,cn=index,cn=userroot,cn=ldbm database,cn=plugins,cn=config
-default: cn: nsHardwarePlatform
-default: objectclass: top
-default: objectclass: nsindex
-default: nssystemindex: false
-default: nsindextype: eq
-default: nsindextype: sub
+only:cn: nsHardwarePlatform
+default:objectClass: nsindex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
+add:nsIndexType: sub
 
 dn: cn=nsHostLocation,cn=index,cn=userroot,cn=ldbm database,cn=plugins,cn=config
-default: cn: nsHostLocation
-default: objectclass: top
-default: objectclass: nsindex
-default: nssystemindex: false
-default: nsindextype: eq
-default: nsindextype: sub
+only:cn: nsHostLocation
+default:objectClass: nsindex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
+add:nsIndexType: sub
 
-dn: cn=ipServicePort,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-default: cn: ipServicePort
-default: objectClass: top
-default: objectClass: nsIndex
-default: nsSystemIndex: false
-default: nsIndexType: eq
+dn: cn=nsOsVersion,cn=index,cn=userroot,cn=ldbm database,cn=plugins,cn=config
+only:cn: nsOsVersion
+default:objectClass: nsindex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
+add:nsIndexType: sub
 
-dn: cn=accessRuleType,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-default: cn: accessRuleType
-default: objectClass:top
-default: objectClass:nsIndex
-default: nsSystemIndex: false
-default: nsIndexType: eq
+dn: cn=nsTombstoneCSN,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: nsTombstoneCSN
+default:objectClass: nsIndex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
 
-dn: cn=hostCategory,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-default: cn: hostCategory
-default: objectClass:top
-default: objectClass:nsIndex
-default: nsSystemIndex: false
-default: nsIndexType: eq
+dn: cn=ntUniqueId,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: ntUniqueId
+default:objectClass: nsIndex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
+add:nsIndexType: pres
 
-dn: cn=idnsName,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-default: cn: idnsName
-default: objectClass: top
-default: objectClass: nsIndex
-default: nsSystemIndex: false
-default: nsIndexType: eq
+dn: cn=ntUserDomainId,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: ntUserDomainId
+default:objectClass: nsIndex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
+add:nsIndexType: pres
 
-dn: cn=ipaCertmapData,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-default: cn: ipaCertmapData
-default: objectClass: top
-default: objectClass: nsIndex
-default: nsSystemIndex: false
-default: nsIndexType: eq
+dn: cn=ou,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: ou
+default:objectClass: nsIndex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
+add:nsIndexType: sub
 
-dn: cn=altSecurityIdentities,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-default: cn: altSecurityIdentities
-default: objectClass: top
-default: objectClass: nsIndex
-default: nsSystemIndex: false
-default: nsIndexType: eq
+dn: cn=owner,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: owner
+default:objectClass: nsIndex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
+add:nsIndexType: sub
 
-dn: cn=memberManager,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-default: cn: memberManager
-default: objectClass: top
-default: objectClass: nsIndex
-default: nsSystemIndex: false
-default: nsIndexType: eq
-default: nsIndexType: pres
+dn: cn=secretary,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: secretary
+default:objectClass: nsIndex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
+add:nsIndexType: pres
+add:nsIndexType: sub
+
+dn: cn=seeAlso,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: seeAlso
+default:objectClass: nsIndex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
+add:nsIndexType: sub
+
+dn: cn=serverhostname,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: serverhostname
+default:objectClass: nsIndex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
+add:nsIndexType: sub
+
+dn: cn=sn,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: sn
+default:objectClass: nsIndex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
+add:nsIndexType: pres
+add:nsIndexType: sub
+
+dn: cn=sourcehost,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: sourcehost
+default:objectClass: nsIndex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
+add:nsIndexType: pres
+add:nsIndexType: sub
+
+dn: cn=targetuniqueid,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: targetuniqueid
+default:objectClass: nsIndex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
+
+dn: cn=telephoneNumber,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: telephoneNumber
+default:objectClass: nsIndex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
+add:nsIndexType: pres
+add:nsIndexType: sub
+
+dn: cn=title,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: title
+default:objectClass: nsIndex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
+add:nsIndexType: sub
+
+dn: cn=uid,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: uid
+default:objectClass: nsIndex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
+add:nsIndexType: sub
+
+dn: cn=uidnumber,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: uidnumber
+default:objectClass: nsIndex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
+
+dn: cn=uniquemember,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: uniquemember
+default:objectClass: nsIndex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
+add:nsIndexType: sub
+
+dn: cn=userCertificate,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
+only:cn: userCertificate
+default:objectClass: nsIndex
+default:objectClass: top
+default:nsSystemIndex: false
+add:nsIndexType: eq
+add:nsIndexType: pres
 
-dn: cn=krbPasswordExpiration,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-default: cn: krbPasswordExpiration
-default: objectClass: top
-default: objectClass: nsIndex
-default: nsSystemIndex: false
-default: nsIndexType: eq
-
-dn: cn=ipaNTTrustPartner,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-default: cn: ipaNTTrustPartner
-default: objectClass: top
-default: objectClass: nsIndex
-default: nsSystemIndex: false
-default: nsIndexType: pres
-
-dn: cn=ipaNTSecurityIdentifier,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-default: cn: ipaNTSecurityIdentifier
-default: objectClass: top
-default: objectClass: nsIndex
-default: nsSystemIndex: false
-default: nsIndexType: pres
diff --git a/install/updates/20-winsync_index.update b/install/updates/20-winsync_index.update
deleted file mode 100644
index 45c8ae4b60..0000000000
--- a/install/updates/20-winsync_index.update
+++ /dev/null
@@ -1,12 +0,0 @@
-#
-# Make sure winsync attributes have the correct indexing
-#
-
-dn: cn=ntUniqueId,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-only: nsIndexType: eq
-only: nsIndexType: pres
-
-dn: cn=ntUserDomainId,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
-only: nsIndexType: eq
-only: nsIndexType: pres
-
diff --git a/install/updates/Makefile.am b/install/updates/Makefile.am
index 8a4d9cc6cf..a324f9d6d7 100644
--- a/install/updates/Makefile.am
+++ b/install/updates/Makefile.am
@@ -21,8 +21,6 @@ app_DATA =				\
 	20-sslciphers.update		\
 	20-syncrepl.update		\
 	20-user_private_groups.update	\
-	20-winsync_index.update		\
-	20-idoverride_index.update	\
 	20-uuid.update  \
 	20-default_password_policy.update \
 	20-whoami.update	\
diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py
index 4de09c6602..dcd72bfb88 100644
--- a/ipaserver/install/dsinstance.py
+++ b/ipaserver/install/dsinstance.py
@@ -1025,7 +1025,7 @@ def __add_principal(last_cn, principal, self):
         __add_principal('ipa-ldap-delegation-targets', 'ldap', self)
 
     def __create_indices(self):
-        self._ldap_mod("indices.ldif")
+        self._ldap_update(["20-indices.update"])
 
     def __certmap_conf(self):
         write_certmap_conf(self.realm, self.ca_subject)

From 03c76d7497d05635893c2d5d6229ccaf60f675b2 Mon Sep 17 00:00:00 2001
From: Christian Heimes <cheimes@redhat.com>
Date: Mon, 21 Sep 2020 16:25:53 +0200
Subject: [PATCH 09/11] Remove magic sleep from create_index_task

11 years ago 5ad91a0781 added a magic sleep to work around a rare deadlock
bug in memberOf plugin. Thierry is not aware of any outstanding issues
with memberOf plugin that could lead to a deadlock.

Signed-off-by: Christian Heimes <cheimes@redhat.com>
---
 ipaserver/install/ldapupdate.py | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/ipaserver/install/ldapupdate.py b/ipaserver/install/ldapupdate.py
index 87c74a053d..15c0ccb508 100644
--- a/ipaserver/install/ldapupdate.py
+++ b/ipaserver/install/ldapupdate.py
@@ -511,10 +511,6 @@ def emit_plugin_update(update):
 
     def create_index_task(self, *attributes):
         """Create a task to update an index for attributes"""
-
-        # Sleep a bit to ensure previous operations are complete
-        time.sleep(5)
-
         cn_uuid = uuid.uuid1()
         # cn_uuid.time is in nanoseconds, but other users of LDAPUpdate expect
         # seconds in 'TIME' so scale the value down

From 4da813666a9f289722c475d3b1811a1d8bc3c33e Mon Sep 17 00:00:00 2001
From: Christian Heimes <cheimes@redhat.com>
Date: Wed, 16 Sep 2020 13:27:14 +0200
Subject: [PATCH 10/11] Add timings to install logs

The logging manager now adds timings for installation steps to the
installer logs. The information can be extracted and dumped to a CSV
file with a simple grep command:

    grep -Po 'TIMING: \K.*' /var/log/ipaserver.log > ipaserver.csv

Signed-off-by: Christian Heimes <cheimes@redhat.com>
---
 install/tools/ipa-ca-install.in      |  1 +
 install/tools/ipa-dns-install.in     |  5 +++--
 ipapython/admintool.py               | 13 +++++++++++++
 ipapython/ipa_log_manager.py         | 28 +++++++++++++++++++++++++++-
 ipaserver/install/dsinstance.py      |  2 +-
 ipaserver/install/ldapupdate.py      | 13 +++++++++++++
 ipaserver/install/service.py         |  8 ++++++--
 ipaserver/install/upgradeinstance.py |  3 ++-
 8 files changed, 66 insertions(+), 7 deletions(-)

diff --git a/install/tools/ipa-ca-install.in b/install/tools/ipa-ca-install.in
index ce6d5fcb52..3b71db412e 100644
--- a/install/tools/ipa-ca-install.in
+++ b/install/tools/ipa-ca-install.in
@@ -316,6 +316,7 @@ def main():
     api.Backend.ldap2.disconnect()
 
     # execute ipactl to refresh services status
+    logger.info("Restarting IPA services")
     ipautil.run([paths.IPACTL, 'start', '--ignore-service-failures'],
                 raiseonerr=False)
 
diff --git a/install/tools/ipa-dns-install.in b/install/tools/ipa-dns-install.in
index 43e2be88a5..ab5045edf1 100644
--- a/install/tools/ipa-dns-install.in
+++ b/install/tools/ipa-dns-install.in
@@ -143,12 +143,13 @@ def main():
     dns_installer.install(True, False, options)
     # Services are enabled in dns_installer.install()
 
+    api.Backend.ldap2.disconnect()
+
     # execute ipactl to refresh services status
+    logger.info("Restarting IPA services")
     ipautil.run([paths.IPACTL, 'start', '--ignore-service-failures'],
                 raiseonerr=False)
 
-    api.Backend.ldap2.disconnect()
-
     return 0
 
 if __name__ == '__main__':
diff --git a/ipapython/admintool.py b/ipapython/admintool.py
index 991e85e016..c7d9c5b487 100644
--- a/ipapython/admintool.py
+++ b/ipapython/admintool.py
@@ -25,6 +25,7 @@
 import logging
 import sys
 import os
+import time
 import traceback
 from optparse import OptionGroup  # pylint: disable=deprecated-module
 
@@ -94,6 +95,7 @@ class AdminTool:
     log_file_name = None
     usage = None
     description = None
+    _start_monotonic = None
 
     _option_parsers = dict()
 
@@ -171,6 +173,8 @@ def execute(self):
         This includes validating options, setting up logging, doing the
         actual work, and handling the result.
         """
+        # use monotonic as chronyc can change clocks
+        self._start_monotonic = time.monotonic()
         self._setup_logging(no_file=True)
         return_value = 1
         try:
@@ -323,6 +327,15 @@ def log_failure(self, error_message, return_value, exception, backtrace):
         if self.log_file_initialized and return_value != SERVER_NOT_CONFIGURED:
             message += " See %s for more information" % self.log_file_name
         logger.error('%s', message)
+        self._log_time()
 
     def log_success(self):
         logger.info('The %s command was successful', self.command_name)
+        self._log_time()
+
+    def _log_time(self):
+        dur = time.time() - self._start_monotonic
+        logger.debug(
+            "Finished in %0.3f", dur,
+            extra={"timing": (self.command_name, None, None, dur)}
+        )
diff --git a/ipapython/ipa_log_manager.py b/ipapython/ipa_log_manager.py
index 42c13d79fc..00a6384de1 100644
--- a/ipapython/ipa_log_manager.py
+++ b/ipapython/ipa_log_manager.py
@@ -70,6 +70,32 @@ def __init__(
         self.converter = time.gmtime
 
 
+class FileFormatter(Formatter):
+    r"""File output formatter with timing extra line
+
+    $ grep -Po 'TIMING: \K.*' /var/log/ipaserver.log > ipaserver.csv
+    """
+    def __init__(
+        self,
+        fmt=LOGGING_FORMAT_STANDARD_FILE,
+        datefmt=ISO8601_UTC_DATETIME_FMT
+    ):
+        super().__init__(fmt, datefmt)
+
+    def format(self, record):
+        text = super().format(record)
+        timing = getattr(record, "timing", None)
+        if timing:
+            # print timing information as extra line
+            system, name, sub, dur = record.timing
+            if sub is None:
+                sub = ''
+            ttext = f"TIMING: {system},{name},{sub},{dur:0.3f}"
+            return f"{text} {ttext}"
+        else:
+            return text
+
+
 def standard_logging_setup(filename=None, verbose=False, debug=False,
                            filemode='w', console_format=None):
     if console_format is None:
@@ -86,7 +112,7 @@ def standard_logging_setup(filename=None, verbose=False, debug=False,
         finally:
             os.umask(umask)
         file_handler.setLevel(logging.DEBUG)
-        file_handler.setFormatter(Formatter(LOGGING_FORMAT_STANDARD_FILE))
+        file_handler.setFormatter(FileFormatter())
         root_logger.addHandler(file_handler)
 
     level = logging.ERROR
diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py
index dcd72bfb88..07dc8f3711 100644
--- a/ipaserver/install/dsinstance.py
+++ b/ipaserver/install/dsinstance.py
@@ -329,7 +329,7 @@ def enable_ssl(self):
                       self.__import_ca_certs)
         self.step("restarting directory server", self.__restart_instance)
 
-        self.start_creation()
+        self.start_creation(timing_name="dirsrv_tls")
 
     def create_replica(self, realm_name, master_fqdn, fqdn,
                        domain_name, dm_password,
diff --git a/ipaserver/install/ldapupdate.py b/ipaserver/install/ldapupdate.py
index 15c0ccb508..77f7a6a195 100644
--- a/ipaserver/install/ldapupdate.py
+++ b/ipaserver/install/ldapupdate.py
@@ -538,6 +538,7 @@ def create_index_task(self, *attributes):
     def monitor_index_task(self, dn):
         """Give a task DN monitor it and wait until it has completed (or failed)
         """
+        start = time.time()
 
         assert isinstance(dn, DN)
 
@@ -570,6 +571,12 @@ def monitor_index_task(self, dn):
             logger.debug("Indexing in progress")
             time.sleep(1)
 
+        dur = time.time() - start
+        logger.debug(
+            "LDAP index task: %s %.03f sec", dn, dur,
+            extra={'timing': ('ldapupdate', "indextask", None, dur)}
+        )
+
         return
 
     def _create_default_entry(self, dn, default):
@@ -869,6 +876,7 @@ def get_all_files(self, root, recursive=False):
         return f
 
     def _run_update_plugin(self, plugin_name):
+        start = time.time()
         logger.debug("Executing upgrade plugin: %s", plugin_name)
         restart_ds, updates = self.api.Updater[plugin_name]()
         if updates:
@@ -879,6 +887,11 @@ def _run_update_plugin(self, plugin_name):
             self.close_connection()
             self.restart_ds()
             self.create_connection()
+        dur = time.time() - start
+        logger.debug(
+            "Upgrade plugin duration: %s %.03f sec", plugin_name, dur,
+            extra={'timing': ('ldapupdate', 'plugin', plugin_name, dur)}
+        )
 
     def create_connection(self):
         if self.conn is None:
diff --git a/ipaserver/install/service.py b/ipaserver/install/service.py
index 896fb19ca9..3ee4aa0510 100644
--- a/ipaserver/install/service.py
+++ b/ipaserver/install/service.py
@@ -563,7 +563,8 @@ def step(self, message, method, run_after_failure=False):
         self.steps.append((message, method, run_after_failure))
 
     def start_creation(self, start_message=None, end_message=None,
-                       show_service_name=True, runtime=None):
+                       show_service_name=True, runtime=None,
+                       timing_name=None):
         """
         Starts creation of the service.
 
@@ -600,6 +601,9 @@ def start_creation(self, start_message=None, end_message=None,
                 else:
                     end_message = "Done configuring %s." % self.service_desc
 
+        if timing_name is None:
+            timing_name = self.service_name
+
         if runtime is not None and runtime > 0:
             self.print_msg('%s. Estimated time: %s' % (start_message,
                                                       format_seconds(runtime)))
@@ -615,7 +619,7 @@ def run_step(message, method):
             logger.debug(
                 "step duration: %s %s %.02f sec",
                 self.service_name, name, dur,
-                extra={'timing': ('step', self.service_name, name, dur)},
+                extra={'timing': ('step', timing_name, name, dur)},
             )
 
         step = 0
diff --git a/ipaserver/install/upgradeinstance.py b/ipaserver/install/upgradeinstance.py
index f2455ff856..9e865cb69b 100644
--- a/ipaserver/install/upgradeinstance.py
+++ b/ipaserver/install/upgradeinstance.py
@@ -130,7 +130,8 @@ def create_instance(self):
             self.step("starting directory server", self.__start)
         self.start_creation(start_message="Upgrading IPA:",
                             show_service_name=False,
-                            runtime=90)
+                            runtime=90,
+                            timing_name="upgrade")
 
     def __save_config(self):
         shutil.copy2(self.filename, self.savefilename)

From 1de5f6961d60117aeb3323446ca8f47b63390e67 Mon Sep 17 00:00:00 2001
From: Christian Heimes <cheimes@redhat.com>
Date: Thu, 24 Sep 2020 08:35:27 +0200
Subject: [PATCH 11/11] Use separate install logs for AD and DNS instance

ipa-dns-install and ipa-adtrust-install no longer overwrite
ipaserver-install.log. Instead they use a separate log file.

Add AD-Trust, DNS, KRA, and replica log files to backups.

Signed-off-by: Christian Heimes <cheimes@redhat.com>
---
 install/tools/ipa-adtrust-install.in        | 2 +-
 install/tools/ipa-dns-install.in            | 2 +-
 ipaplatform/base/paths.py                   | 2 ++
 ipaserver/install/ipa_backup.py             | 6 ++++++
 ipatests/pytest_ipa/integration/__init__.py | 4 +++-
 5 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/install/tools/ipa-adtrust-install.in b/install/tools/ipa-adtrust-install.in
index 7d94b718e2..93365cc23d 100644
--- a/install/tools/ipa-adtrust-install.in
+++ b/install/tools/ipa-adtrust-install.in
@@ -50,7 +50,7 @@ if six.PY3:
 
 logger = logging.getLogger(os.path.basename(__file__))
 
-log_file_name = paths.IPASERVER_INSTALL_LOG
+log_file_name = paths.IPASERVER_ADTRUST_INSTALL_LOG
 
 
 def parse_options():
diff --git a/install/tools/ipa-dns-install.in b/install/tools/ipa-dns-install.in
index ab5045edf1..81e8c9793b 100644
--- a/install/tools/ipa-dns-install.in
+++ b/install/tools/ipa-dns-install.in
@@ -38,7 +38,7 @@ from ipaserver.install import dns as dns_installer
 
 logger = logging.getLogger(os.path.basename(__file__))
 
-log_file_name = paths.IPASERVER_INSTALL_LOG
+log_file_name = paths.IPASERVER_DNS_INSTALL_LOG
 
 def parse_options():
     parser = IPAOptionParser(version=version.VERSION)
diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py
index ef894dd77a..b12d0f0168 100644
--- a/ipaplatform/base/paths.py
+++ b/ipaplatform/base/paths.py
@@ -350,6 +350,8 @@ class BasePathNamespace:
     IPAREPLICA_INSTALL_LOG = "/var/log/ipareplica-install.log"
     IPARESTORE_LOG = "/var/log/iparestore.log"
     IPASERVER_INSTALL_LOG = "/var/log/ipaserver-install.log"
+    IPASERVER_ADTRUST_INSTALL_LOG = "/var/log/ipaserver-adtrust-install.log"
+    IPASERVER_DNS_INSTALL_LOG = "/var/log/ipaserver-dns-install.log"
     IPASERVER_KRA_INSTALL_LOG = "/var/log/ipaserver-kra-install.log"
     IPASERVER_UNINSTALL_LOG = "/var/log/ipaserver-uninstall.log"
     IPAUPGRADE_LOG = "/var/log/ipaupgrade.log"
diff --git a/ipaserver/install/ipa_backup.py b/ipaserver/install/ipa_backup.py
index b9aa22ff6b..56f64fef88 100644
--- a/ipaserver/install/ipa_backup.py
+++ b/ipaserver/install/ipa_backup.py
@@ -203,6 +203,12 @@ class Backup(admintool.AdminTool):
       paths.VAR_LOG_PKI_DIR,
       paths.VAR_LOG_HTTPD_DIR,
       paths.IPASERVER_INSTALL_LOG,
+      paths.IPASERVER_ADTRUST_INSTALL_LOG,
+      paths.IPASERVER_DNS_INSTALL_LOG,
+      paths.IPASERVER_KRA_INSTALL_LOG,
+      paths.IPAREPLICA_INSTALL_LOG,
+      paths.IPAREPLICA_CONNCHECK_LOG,
+      paths.IPAREPLICA_CA_INSTALL_LOG,
       paths.KADMIND_LOG,
       paths.MESSAGES,
       paths.IPACLIENT_INSTALL_LOG,
diff --git a/ipatests/pytest_ipa/integration/__init__.py b/ipatests/pytest_ipa/integration/__init__.py
index 5b0a22ff06..1e5400152c 100644
--- a/ipatests/pytest_ipa/integration/__init__.py
+++ b/ipatests/pytest_ipa/integration/__init__.py
@@ -45,11 +45,13 @@
     paths.VAR_LOG_DIRSRV,
     # IPA install logs
     paths.IPASERVER_INSTALL_LOG,
+    paths.IPASERVER_ADTRUST_INSTALL_LOG,
+    paths.IPASERVER_DNS_INSTALL_LOG,
+    paths.IPASERVER_KRA_INSTALL_LOG,
     paths.IPACLIENT_INSTALL_LOG,
     paths.IPAREPLICA_INSTALL_LOG,
     paths.IPAREPLICA_CONNCHECK_LOG,
     paths.IPAREPLICA_CA_INSTALL_LOG,
-    paths.IPASERVER_KRA_INSTALL_LOG,
     paths.IPA_CUSTODIA_AUDIT_LOG,
     paths.IPACLIENTSAMBA_INSTALL_LOG,
     paths.IPACLIENTSAMBA_UNINSTALL_LOG,
