Blame SOURCES/0001-Issue-50525-nsslapd-defaultnamingcontext-does-not-ch.patch

458e05
From d33743c8604ff4f97947dad14fddab0691e3d19e Mon Sep 17 00:00:00 2001
458e05
From: Mark Reynolds <mreynolds@redhat.com>
458e05
Date: Thu, 1 Aug 2019 16:50:34 -0400
458e05
Subject: [PATCH] Issue 50525 - nsslapd-defaultnamingcontext does not change
458e05
 when the assigned suffix gets deleted
458e05
458e05
Bug Description:
458e05
458e05
If you delete the suffix that is set as the default naming context, the attribute
458e05
is not reset.
458e05
458e05
Also using dsconf to delete a backend/suffix fails if there are vlv indexes, encrypted
458e05
attributes, or replication is configured.
458e05
458e05
Fix Description:
458e05
458e05
As for the default naming context, if there is a second suffix configured, it will be
458e05
automatically set as the new default naming context, otherwise the attribute is not
458e05
modified.
458e05
458e05
For dsconf backend delete issue, it now checks and removes replication configuration
458e05
and agreements, and removes all the child entries under the backend entry.
458e05
458e05
relates: https://pagure.io/389-ds-base/issue/50525
458e05
458e05
Reviewed by: spichugi(Thanks!)
458e05
---
458e05
 .../be_del_and_default_naming_attr_test.py    | 90 +++++++++++++++++++
458e05
 ldap/servers/slapd/mapping_tree.c             | 50 ++++++-----
458e05
 src/lib389/lib389/backend.py                  | 17 ++--
458e05
 src/lib389/lib389/replica.py                  |  2 +-
458e05
 4 files changed, 132 insertions(+), 27 deletions(-)
458e05
 create mode 100644 dirsrvtests/tests/suites/mapping_tree/be_del_and_default_naming_attr_test.py
458e05
458e05
diff --git a/dirsrvtests/tests/suites/mapping_tree/be_del_and_default_naming_attr_test.py b/dirsrvtests/tests/suites/mapping_tree/be_del_and_default_naming_attr_test.py
458e05
new file mode 100644
458e05
index 000000000..34a2de2ad
458e05
--- /dev/null
458e05
+++ b/dirsrvtests/tests/suites/mapping_tree/be_del_and_default_naming_attr_test.py
458e05
@@ -0,0 +1,90 @@
458e05
+import logging
458e05
+import pytest
458e05
+import os
458e05
+from lib389._constants import DEFAULT_SUFFIX
458e05
+from lib389.topologies import topology_m1 as topo
458e05
+from lib389.backend import Backends
458e05
+from lib389.encrypted_attributes import EncryptedAttrs
458e05
+
458e05
+DEBUGGING = os.getenv("DEBUGGING", default=False)
458e05
+if DEBUGGING:
458e05
+    logging.getLogger(__name__).setLevel(logging.DEBUG)
458e05
+else:
458e05
+    logging.getLogger(__name__).setLevel(logging.INFO)
458e05
+log = logging.getLogger(__name__)
458e05
+
458e05
+SECOND_SUFFIX = 'o=namingcontext'
458e05
+THIRD_SUFFIX = 'o=namingcontext2'
458e05
+
458e05
+def test_be_delete(topo):
458e05
+    """Test that we can delete a backend that contains replication
458e05
+    configuration and encrypted attributes.  The default naming 
458e05
+    context should also be updated to reflect the next available suffix
458e05
+
458e05
+    :id: 5208f897-7c95-4925-bad0-9ceb95fee678
458e05
+    :setup: Master Instance
458e05
+    :steps:
458e05
+        1. Create second backend/suffix
458e05
+        2. Add an encrypted attribute to the default suffix
458e05
+        2. Delete default suffix
458e05
+        3. Check the nsslapd-defaultnamingcontext is updated
458e05
+        4. Delete the last backend
458e05
+        5. Check the namingcontext has not changed
458e05
+        6. Add new backend
458e05
+        7. Set default naming context
458e05
+        8. Verify the naming context is correct
458e05
+    :expectedresults:
458e05
+        1. Success
458e05
+        2. Success
458e05
+        3. Success
458e05
+        4. Success
458e05
+        5. Success
458e05
+        6. Success
458e05
+        7. Success
458e05
+        8. Success
458e05
+    """
458e05
+    
458e05
+    inst = topo.ms["master1"] 
458e05
+    
458e05
+    # Create second suffix      
458e05
+    backends = Backends(inst)
458e05
+    default_backend = backends.get(DEFAULT_SUFFIX)
458e05
+    new_backend = backends.create(properties={'nsslapd-suffix': SECOND_SUFFIX,
458e05
+                                              'name': 'namingRoot'})
458e05
+  
458e05
+    # Add encrypted attribute entry under default suffix
458e05
+    encrypt_attrs = EncryptedAttrs(inst, basedn='cn=encrypted attributes,{}'.format(default_backend.dn))
458e05
+    encrypt_attrs.create(properties={'cn': 'employeeNumber', 'nsEncryptionAlgorithm': 'AES'})
458e05
+    
458e05
+    # Delete default suffix
458e05
+    default_backend.delete()
458e05
+    
458e05
+    # Check that the default naming context is set to the new/second suffix
458e05
+    default_naming_ctx = inst.config.get_attr_val_utf8('nsslapd-defaultnamingcontext')
458e05
+    assert default_naming_ctx == SECOND_SUFFIX
458e05
+
458e05
+    # delete new backend, but the naming context should not change
458e05
+    new_backend.delete()
458e05
+
458e05
+    # Check that the default naming context is still set to the new/second suffix
458e05
+    default_naming_ctx = inst.config.get_attr_val_utf8('nsslapd-defaultnamingcontext')
458e05
+    assert default_naming_ctx == SECOND_SUFFIX
458e05
+
458e05
+    # Add new backend
458e05
+    new_backend = backends.create(properties={'nsslapd-suffix': THIRD_SUFFIX,
458e05
+                                              'name': 'namingRoot2'})
458e05
+
458e05
+    # manaully set naming context
458e05
+    inst.config.set('nsslapd-defaultnamingcontext', THIRD_SUFFIX)
458e05
+
458e05
+    # Verify naming context is correct
458e05
+    default_naming_ctx = inst.config.get_attr_val_utf8('nsslapd-defaultnamingcontext')
458e05
+    assert default_naming_ctx == THIRD_SUFFIX
458e05
+
458e05
+
458e05
+if __name__ == '__main__':
458e05
+    # Run isolated
458e05
+    # -s for DEBUG mode
458e05
+    CURRENT_FILE = os.path.realpath(__file__)
458e05
+    pytest.main(["-s", CURRENT_FILE])
458e05
+
458e05
diff --git a/ldap/servers/slapd/mapping_tree.c b/ldap/servers/slapd/mapping_tree.c
458e05
index 834949a67..25e9fb80c 100644
458e05
--- a/ldap/servers/slapd/mapping_tree.c
458e05
+++ b/ldap/servers/slapd/mapping_tree.c
458e05
@@ -1521,26 +1521,36 @@ done:
458e05
                 strcpy_unescape_value(escaped, suffix);
458e05
             }
458e05
             if (escaped && (0 == strcasecmp(escaped, default_naming_context))) {
458e05
-                int rc = _mtn_update_config_param(LDAP_MOD_DELETE,
458e05
-                                                  CONFIG_DEFAULT_NAMING_CONTEXT,
458e05
-                                                  NULL);
458e05
-                if (rc) {
458e05
-                    slapi_log_err(SLAPI_LOG_ERR,
458e05
-                                  "mapping_tree_entry_delete_callback",
458e05
-                                  "deleting config param %s failed: RC=%d\n",
458e05
-                                  CONFIG_DEFAULT_NAMING_CONTEXT, rc);
458e05
-                }
458e05
-                if (LDAP_SUCCESS == rc) {
458e05
-                    char errorbuf[SLAPI_DSE_RETURNTEXT_SIZE] = {0};
458e05
-                    /* Removing defaultNamingContext from cn=config entry
458e05
-                     * was successful.  The remove does not reset the
458e05
-                     * global parameter.  We need to reset it separately. */
458e05
-                    if (config_set_default_naming_context(
458e05
-                            CONFIG_DEFAULT_NAMING_CONTEXT,
458e05
-                            NULL, errorbuf, CONFIG_APPLY)) {
458e05
-                        slapi_log_err(SLAPI_LOG_ERR, "mapping_tree_entry_delete_callback",
458e05
-                                      "Setting NULL to %s failed. %s\n",
458e05
-                                      CONFIG_DEFAULT_NAMING_CONTEXT, errorbuf);
458e05
+                /*
458e05
+                 * We can not delete the default naming attribute, so instead
458e05
+                 * replace it only if there is another suffix available
458e05
+                 */
458e05
+                void *node = NULL;
458e05
+                Slapi_DN *sdn;
458e05
+                sdn = slapi_get_first_suffix(&node, 0);
458e05
+                if (sdn) {
458e05
+                    char *replacement_suffix = (char *)slapi_sdn_get_dn(sdn);
458e05
+                    int rc = _mtn_update_config_param(LDAP_MOD_REPLACE,
458e05
+                                                      CONFIG_DEFAULT_NAMING_CONTEXT,
458e05
+                                                      replacement_suffix);
458e05
+                    if (rc) {
458e05
+                        slapi_log_err(SLAPI_LOG_ERR,
458e05
+                                      "mapping_tree_entry_delete_callback",
458e05
+                                      "replacing config param %s failed: RC=%d\n",
458e05
+                                      CONFIG_DEFAULT_NAMING_CONTEXT, rc);
458e05
+                    }
458e05
+                    if (LDAP_SUCCESS == rc) {
458e05
+                        char errorbuf[SLAPI_DSE_RETURNTEXT_SIZE] = {0};
458e05
+                        /* Replacing defaultNamingContext from cn=config entry
458e05
+                         * was successful.  The replace does not reset the
458e05
+                         * global parameter.  We need to reset it separately. */
458e05
+                        if (config_set_default_naming_context(
458e05
+                                CONFIG_DEFAULT_NAMING_CONTEXT,
458e05
+                                replacement_suffix, errorbuf, CONFIG_APPLY)) {
458e05
+                            slapi_log_err(SLAPI_LOG_ERR, "mapping_tree_entry_delete_callback",
458e05
+                                          "Setting %s tp %s failed. %s\n",
458e05
+                                          CONFIG_DEFAULT_NAMING_CONTEXT, replacement_suffix, errorbuf);
458e05
+                        }
458e05
                     }
458e05
                 }
458e05
             }
458e05
diff --git a/src/lib389/lib389/backend.py b/src/lib389/lib389/backend.py
458e05
index 6f4c8694e..4d32038f6 100644
458e05
--- a/src/lib389/lib389/backend.py
458e05
+++ b/src/lib389/lib389/backend.py
458e05
@@ -17,6 +17,7 @@ from lib389 import Entry
458e05
 from lib389._mapped_object import DSLdapObjects, DSLdapObject
458e05
 from lib389.mappingTree import MappingTrees, MappingTree
458e05
 from lib389.exceptions import NoSuchEntryError, InvalidArgumentError
458e05
+from lib389.replica import Replicas
458e05
 
458e05
 # We need to be a factor to the backend monitor
458e05
 from lib389.monitor import MonitorBackend
458e05
@@ -507,20 +508,24 @@ class Backend(DSLdapObject):
458e05
             mt = self._mts.get(selector=bename)
458e05
             # Assert the type is "backend"
458e05
             # Are these the right types....?
458e05
-            if mt.get_attr_val('nsslapd-state') != ensure_bytes('backend'):
458e05
+            if mt.get_attr_val('nsslapd-state').lower() != ensure_bytes('backend'):
458e05
                 raise ldap.UNWILLING_TO_PERFORM('Can not delete the mapping tree, not for a backend! You may need to delete this backend via cn=config .... ;_; ')
458e05
+
458e05
+            # Delete replicas first
458e05
+            try:
458e05
+                Replicas(self._instance).get(mt.get_attr_val_utf8('cn')).delete()
458e05
+            except ldap.NO_SUCH_OBJECT:
458e05
+                # No replica, no problem
458e05
+                pass
458e05
+
458e05
             # Delete our mapping tree if it exists.
458e05
             mt.delete()
458e05
         except ldap.NO_SUCH_OBJECT:
458e05
             # Righto, it's already gone! Do nothing ...
458e05
             pass
458e05
-        # Delete all our related indices
458e05
-        self._instance.index.delete_all(bename)
458e05
 
458e05
         # Now remove our children, this is all ldbm config
458e05
-        self._instance.delete_branch_s(self._dn, ldap.SCOPE_ONELEVEL)
458e05
-        # The super will actually delete ourselves.
458e05
-        super(Backend, self).delete()
458e05
+        self._instance.delete_branch_s(self._dn, ldap.SCOPE_SUBTREE)
458e05
 
458e05
     def _lint_mappingtree(self):
458e05
         """Backend lint
458e05
diff --git a/src/lib389/lib389/replica.py b/src/lib389/lib389/replica.py
458e05
index cdd0a9729..7b45683d9 100644
458e05
--- a/src/lib389/lib389/replica.py
458e05
+++ b/src/lib389/lib389/replica.py
458e05
@@ -458,7 +458,7 @@ class ReplicaLegacy(object):
458e05
         try:
458e05
             self.deleteAgreements(nsuffix)
458e05
         except ldap.LDAPError as e:
458e05
-            self.log.fatal('Failed to delete replica agreements!')
458e05
+            self.log.fatal('Failed to delete replica agreements!  ' + str(e))
458e05
             raise
458e05
 
458e05
         # Delete the replica
458e05
-- 
458e05
2.21.0
458e05