Blame SOURCES/0001-Issue-4678-RFE-automatique-disable-of-virtual-attrib.patch

9f2552
From 67e19da62a9e8958458de54173dcd9bcaf53164d Mon Sep 17 00:00:00 2001
9f2552
From: tbordaz <tbordaz@redhat.com>
9f2552
Date: Thu, 30 Sep 2021 15:59:40 +0200
9f2552
Subject: [PATCH 01/12] Issue 4678 - RFE automatique disable of virtual
9f2552
 attribute checking (#4918)
9f2552
9f2552
Bug description:
9f2552
	Virtual attributes are configured via Roles or COS definitions
9f2552
        and registered during initialization of those plugins.
9f2552
	Virtual attributes are processed during search evaluation of
9f2552
	filter and returned attributes. This processing is expensive
9f2552
	and prone to create contention between searches.
9f2552
	Use of virtual attribute is not frequent. So many of the
9f2552
	deployement process virtual attribute even if there is none.
9f2552
9f2552
Fix description:
9f2552
	The fix configure the server to ignore virtual attribute by
9f2552
        default (nsslapd-ignore-virtual-attrs: on).
9f2552
        At startup, if a new virtual attribute is registered or
9f2552
        it exists Roles/COS definitions, then the server is
9f2552
	configured to process the virtual attributes
9f2552
        (nsslapd-ignore-virtual-attrs: off)
9f2552
        design: https://www.port389.org/docs/389ds/design/vattr-automatic-toggle.html
9f2552
9f2552
relates: https://github.com/389ds/389-ds-base/issues/4678
9f2552
9f2552
Reviewed by: William Brown, Simon Pichugin, Mark Reynolds (Thanks !!)
9f2552
9f2552
Platforms tested: F34
9f2552
---
9f2552
 .../tests/suites/config/config_test.py        |  40 +++-
9f2552
 dirsrvtests/tests/suites/cos/cos_test.py      |  94 ++++++--
9f2552
 dirsrvtests/tests/suites/roles/basic_test.py  | 200 +++++++++++++++++-
9f2552
 ldap/servers/plugins/roles/roles_cache.c      |   9 +
9f2552
 ldap/servers/slapd/libglobs.c                 |   2 +-
9f2552
 ldap/servers/slapd/main.c                     |   2 +
9f2552
 ldap/servers/slapd/proto-slap.h               |   1 +
9f2552
 ldap/servers/slapd/vattr.c                    | 127 +++++++++++
9f2552
 src/lib389/lib389/idm/role.py                 |   4 +
9f2552
 9 files changed, 455 insertions(+), 24 deletions(-)
9f2552
9f2552
diff --git a/dirsrvtests/tests/suites/config/config_test.py b/dirsrvtests/tests/suites/config/config_test.py
9f2552
index 2ecff8f98..19232c87d 100644
9f2552
--- a/dirsrvtests/tests/suites/config/config_test.py
9f2552
+++ b/dirsrvtests/tests/suites/config/config_test.py
9f2552
@@ -351,7 +351,7 @@ def test_ignore_virtual_attrs(topo):
9f2552
     :setup: Standalone instance
9f2552
     :steps:
9f2552
          1. Check the attribute nsslapd-ignore-virtual-attrs is present in cn=config
9f2552
-         2. Check the default value of attribute nsslapd-ignore-virtual-attrs should be OFF
9f2552
+         2. Check the default value of attribute nsslapd-ignore-virtual-attrs should be ON
9f2552
          3. Set the valid values i.e. on/ON and off/OFF for nsslapd-ignore-virtual-attrs
9f2552
          4. Set invalid value for attribute nsslapd-ignore-virtual-attrs
9f2552
          5. Set nsslapd-ignore-virtual-attrs=off
9f2552
@@ -374,8 +374,8 @@ def test_ignore_virtual_attrs(topo):
9f2552
     log.info("Check the attribute nsslapd-ignore-virtual-attrs is present in cn=config")
9f2552
     assert topo.standalone.config.present('nsslapd-ignore-virtual-attrs')
9f2552
 
9f2552
-    log.info("Check the default value of attribute nsslapd-ignore-virtual-attrs should be OFF")
9f2552
-    assert topo.standalone.config.get_attr_val_utf8('nsslapd-ignore-virtual-attrs') == "off"
9f2552
+    log.info("Check the default value of attribute nsslapd-ignore-virtual-attrs should be ON")
9f2552
+    assert topo.standalone.config.get_attr_val_utf8('nsslapd-ignore-virtual-attrs') == "on"
9f2552
 
9f2552
     log.info("Set the valid values i.e. on/ON and off/OFF for nsslapd-ignore-virtual-attrs")
9f2552
     for attribute_value in ['on', 'off', 'ON', 'OFF']:
9f2552
@@ -415,6 +415,40 @@ def test_ignore_virtual_attrs(topo):
9f2552
     log.info("Test if virtual attribute i.e. postal code not shown while nsslapd-ignore-virtual-attrs: on")
9f2552
     assert not test_user.present('postalcode', '117')
9f2552
 
9f2552
+def test_ignore_virtual_attrs_after_restart(topo):
9f2552
+    """Test nsslapd-ignore-virtual-attrs configuration attribute
9f2552
+       The attribute is ON by default. If it set to OFF, it keeps
9f2552
+       its value on restart
9f2552
+
9f2552
+    :id: ac368649-4fda-473c-9ef8-e0c728b162af
9f2552
+    :setup: Standalone instance
9f2552
+    :steps:
9f2552
+         1. Check the attribute nsslapd-ignore-virtual-attrs is present in cn=config
9f2552
+         2. Check the default value of attribute nsslapd-ignore-virtual-attrs should be ON
9f2552
+         3. Set nsslapd-ignore-virtual-attrs=off
9f2552
+         4. restart the instance
9f2552
+         5. Check the attribute nsslapd-ignore-virtual-attrs is OFF
9f2552
+    :expectedresults:
9f2552
+         1. This should be successful
9f2552
+         2. This should be successful
9f2552
+         3. This should be successful
9f2552
+         4. This should be successful
9f2552
+         5. This should be successful
9f2552
+    """
9f2552
+
9f2552
+    log.info("Check the attribute nsslapd-ignore-virtual-attrs is present in cn=config")
9f2552
+    assert topo.standalone.config.present('nsslapd-ignore-virtual-attrs')
9f2552
+
9f2552
+    log.info("Check the default value of attribute nsslapd-ignore-virtual-attrs should be ON")
9f2552
+    assert topo.standalone.config.get_attr_val_utf8('nsslapd-ignore-virtual-attrs') == "on"
9f2552
+
9f2552
+    log.info("Set nsslapd-ignore-virtual-attrs = off")
9f2552
+    topo.standalone.config.set('nsslapd-ignore-virtual-attrs', 'off')
9f2552
+
9f2552
+    topo.standalone.restart()
9f2552
+
9f2552
+    log.info("Check the default value of attribute nsslapd-ignore-virtual-attrs should be OFF")
9f2552
+    assert topo.standalone.config.present('nsslapd-ignore-virtual-attrs', 'off')
9f2552
 
9f2552
 @pytest.mark.bz918694
9f2552
 @pytest.mark.ds408
9f2552
diff --git a/dirsrvtests/tests/suites/cos/cos_test.py b/dirsrvtests/tests/suites/cos/cos_test.py
9f2552
index d6a498c73..d1f99f96f 100644
9f2552
--- a/dirsrvtests/tests/suites/cos/cos_test.py
9f2552
+++ b/dirsrvtests/tests/suites/cos/cos_test.py
9f2552
@@ -6,6 +6,8 @@
9f2552
 # See LICENSE for details.
9f2552
 # --- END COPYRIGHT BLOCK ---
9f2552
 
9f2552
+import logging
9f2552
+import time
9f2552
 import pytest, os, ldap
9f2552
 from lib389.cos import  CosClassicDefinition, CosClassicDefinitions, CosTemplate
9f2552
 from lib389._constants import DEFAULT_SUFFIX
9f2552
@@ -14,26 +16,37 @@ from lib389.idm.role import FilteredRoles
9f2552
 from lib389.idm.nscontainer import nsContainer
9f2552
 from lib389.idm.user import UserAccount
9f2552
 
9f2552
+logging.getLogger(__name__).setLevel(logging.INFO)
9f2552
+log = logging.getLogger(__name__)
9f2552
+
9f2552
 pytestmark = pytest.mark.tier1
9f2552
+@pytest.fixture(scope="function")
9f2552
+def reset_ignore_vattr(topo, request):
9f2552
+    default_ignore_vattr_value = topo.standalone.config.get_attr_val_utf8('nsslapd-ignore-virtual-attrs')
9f2552
+    def fin():
9f2552
+        topo.standalone.config.set('nsslapd-ignore-virtual-attrs', default_ignore_vattr_value)
9f2552
 
9f2552
-def test_positive(topo):
9f2552
-    """
9f2552
-        :id: a5a74235-597f-4fe8-8c38-826860927472
9f2552
-        :setup: server
9f2552
-        :steps:
9f2552
-            1. Add filter role entry
9f2552
-            2. Add ns container
9f2552
-            3. Add cos template
9f2552
-            4. Add CosClassic Definition
9f2552
-            5. Cos entries should be added and searchable
9f2552
-            6. employeeType attribute should be there in user entry as per the cos plugin property
9f2552
-        :expectedresults:
9f2552
-            1. Operation should success
9f2552
-            2. Operation should success
9f2552
-            3. Operation should success
9f2552
-            4. Operation should success
9f2552
-            5. Operation should success
9f2552
-            6. Operation should success
9f2552
+    request.addfinalizer(fin)
9f2552
+
9f2552
+def test_positive(topo, reset_ignore_vattr):
9f2552
+    """CoS positive tests
9f2552
+
9f2552
+    :id: a5a74235-597f-4fe8-8c38-826860927472
9f2552
+    :setup: server
9f2552
+    :steps:
9f2552
+        1. Add filter role entry
9f2552
+        2. Add ns container
9f2552
+        3. Add cos template
9f2552
+        4. Add CosClassic Definition
9f2552
+        5. Cos entries should be added and searchable
9f2552
+        6. employeeType attribute should be there in user entry as per the cos plugin property
9f2552
+    :expectedresults:
9f2552
+        1. Operation should success
9f2552
+        2. Operation should success
9f2552
+        3. Operation should success
9f2552
+        4. Operation should success
9f2552
+        5. Operation should success
9f2552
+        6. Operation should success
9f2552
     """
9f2552
     # Adding ns filter role
9f2552
     roles = FilteredRoles(topo.standalone, DEFAULT_SUFFIX)
9f2552
@@ -77,7 +90,52 @@ def test_positive(topo):
9f2552
 
9f2552
     #  CoS definition entry's cosSpecifier attribute specifies the employeeType attribute
9f2552
     assert user.present('employeeType')
9f2552
+    cosdef.delete()
9f2552
+
9f2552
+def test_vattr_on_cos_definition(topo, reset_ignore_vattr):
9f2552
+    """Test nsslapd-ignore-virtual-attrs configuration attribute
9f2552
+       The attribute is ON by default. If a cos definition is
9f2552
+       added it is moved to OFF
9f2552
+
9f2552
+    :id: e7ef5254-386f-4362-bbb4-9409f3f51b08
9f2552
+    :setup: Standalone instance
9f2552
+    :steps:
9f2552
+         1. Check the attribute nsslapd-ignore-virtual-attrs is present in cn=config
9f2552
+         2. Check the default value of attribute nsslapd-ignore-virtual-attrs should be ON
9f2552
+         3. Create a cos definition for employeeType
9f2552
+         4. Check the value of nsslapd-ignore-virtual-attrs should be OFF (with a delay for postop processing)
9f2552
+         5. Check a message "slapi_vattrspi_regattr - Because employeeType,.." in error logs
9f2552
+    :expectedresults:
9f2552
+         1. This should be successful
9f2552
+         2. This should be successful
9f2552
+         3. This should be successful
9f2552
+         4. This should be successful
9f2552
+         5. This should be successful
9f2552
+    """
9f2552
+
9f2552
+    log.info("Check the attribute nsslapd-ignore-virtual-attrs is present in cn=config")
9f2552
+    assert topo.standalone.config.present('nsslapd-ignore-virtual-attrs')
9f2552
+
9f2552
+    log.info("Check the default value of attribute nsslapd-ignore-virtual-attrs should be ON")
9f2552
+    assert topo.standalone.config.get_attr_val_utf8('nsslapd-ignore-virtual-attrs') == "on"
9f2552
+
9f2552
+    # creating CosClassicDefinition
9f2552
+    log.info("Create a cos definition")
9f2552
+    properties = {'cosTemplateDn': 'cn=cosClassicGenerateEmployeeTypeUsingnsroleTemplates,{}'.format(DEFAULT_SUFFIX),
9f2552
+                  'cosAttribute': 'employeeType',
9f2552
+                  'cosSpecifier': 'nsrole',
9f2552
+                  'cn': 'cosClassicGenerateEmployeeTypeUsingnsrole'}
9f2552
+    cosdef = CosClassicDefinition(topo.standalone,'cn=cosClassicGenerateEmployeeTypeUsingnsrole,{}'.format(DEFAULT_SUFFIX))\
9f2552
+        .create(properties=properties)
9f2552
+
9f2552
+    log.info("Check the default value of attribute nsslapd-ignore-virtual-attrs should be OFF")
9f2552
+    time.sleep(2)
9f2552
+    assert topo.standalone.config.present('nsslapd-ignore-virtual-attrs', 'off')
9f2552
 
9f2552
+    topo.standalone.stop()
9f2552
+    assert topo.standalone.searchErrorsLog("slapi_vattrspi_regattr - Because employeeType is a new registered virtual attribute , nsslapd-ignore-virtual-attrs was set to \'off\'")
9f2552
+    topo.standalone.start()
9f2552
+    cosdef.delete()
9f2552
 
9f2552
 if __name__ == "__main__":
9f2552
     CURRENT_FILE = os.path.realpath(__file__)
9f2552
diff --git a/dirsrvtests/tests/suites/roles/basic_test.py b/dirsrvtests/tests/suites/roles/basic_test.py
9f2552
index 47a531794..bec3aedfc 100644
9f2552
--- a/dirsrvtests/tests/suites/roles/basic_test.py
9f2552
+++ b/dirsrvtests/tests/suites/roles/basic_test.py
9f2552
@@ -11,6 +11,8 @@
9f2552
 Importing necessary Modules.
9f2552
 """
9f2552
 
9f2552
+import logging
9f2552
+import time
9f2552
 import os
9f2552
 import pytest
9f2552
 
9f2552
@@ -22,6 +24,9 @@ from lib389.topologies import topology_st as topo
9f2552
 from lib389.idm.role import FilteredRoles, ManagedRoles, NestedRoles
9f2552
 from lib389.idm.domain import Domain
9f2552
 
9f2552
+logging.getLogger(__name__).setLevel(logging.INFO)
9f2552
+log = logging.getLogger(__name__)
9f2552
+
9f2552
 pytestmark = pytest.mark.tier1
9f2552
 
9f2552
 DNBASE = "o=acivattr,{}".format(DEFAULT_SUFFIX)
9f2552
@@ -35,7 +40,7 @@ FILTERROLESALESROLE = "cn=FILTERROLESALESROLE,{}".format(DNBASE)
9f2552
 FILTERROLEENGROLE = "cn=FILTERROLEENGROLE,{}".format(DNBASE)
9f2552
 
9f2552
 
9f2552
-def test_filterrole(topo):
9f2552
+def test_filterrole(topo, request):
9f2552
     """Test Filter Role
9f2552
 
9f2552
     :id: 8ada4064-786b-11e8-8634-8c16451d917b
9f2552
@@ -136,8 +141,20 @@ def test_filterrole(topo):
9f2552
                   SALES_OU, DNBASE]:
9f2552
         UserAccount(topo.standalone, dn_dn).delete()
9f2552
 
9f2552
+    def fin():
9f2552
+        topo.standalone.restart()
9f2552
+        try:
9f2552
+            filtered_roles = FilteredRoles(topo.standalone, DEFAULT_SUFFIX)
9f2552
+            for i in filtered_roles.list():
9f2552
+                i.delete()
9f2552
+        except:
9f2552
+            pass
9f2552
+        topo.standalone.config.set('nsslapd-ignore-virtual-attrs', 'on')
9f2552
+
9f2552
+    request.addfinalizer(fin)
9f2552
+
9f2552
 
9f2552
-def test_managedrole(topo):
9f2552
+def test_managedrole(topo, request):
9f2552
     """Test Managed Role
9f2552
 
9f2552
     :id: d52a9c00-3bf6-11e9-9b7b-8c16451d917b
9f2552
@@ -209,6 +226,16 @@ def test_managedrole(topo):
9f2552
     for i in roles.list():
9f2552
         i.delete()
9f2552
 
9f2552
+    def fin():
9f2552
+        topo.standalone.restart()
9f2552
+        try:
9f2552
+            role = ManagedRoles(topo.standalone, DEFAULT_SUFFIX).get('ROLE1')
9f2552
+            role.delete()
9f2552
+        except:
9f2552
+            pass
9f2552
+        topo.standalone.config.set('nsslapd-ignore-virtual-attrs', 'on')
9f2552
+
9f2552
+    request.addfinalizer(fin)
9f2552
 
9f2552
 @pytest.fixture(scope="function")
9f2552
 def _final(request, topo):
9f2552
@@ -220,6 +247,7 @@ def _final(request, topo):
9f2552
     def finofaci():
9f2552
         """
9f2552
         Removes and Restores ACIs and other users after the test.
9f2552
+        And restore nsslapd-ignore-virtual-attrs to default
9f2552
         """
9f2552
         domain = Domain(topo.standalone, DEFAULT_SUFFIX)
9f2552
         domain.remove_all('aci')
9f2552
@@ -234,6 +262,8 @@ def _final(request, topo):
9f2552
         for i in aci_list:
9f2552
             domain.add("aci", i)
9f2552
 
9f2552
+        topo.standalone.config.set('nsslapd-ignore-virtual-attrs', 'on')
9f2552
+
9f2552
     request.addfinalizer(finofaci)
9f2552
 
9f2552
 
9f2552
@@ -296,6 +326,172 @@ def test_nestedrole(topo, _final):
9f2552
     conn = users.get('test_user_3').bind(PW_DM)
9f2552
     assert UserAccounts(conn, DEFAULT_SUFFIX).list()
9f2552
 
9f2552
+def test_vattr_on_filtered_role(topo, request):
9f2552
+    """Test nsslapd-ignore-virtual-attrs configuration attribute
9f2552
+       The attribute is ON by default. If a filtered role is
9f2552
+       added it is moved to OFF
9f2552
+
9f2552
+    :id: 88b3ad3c-f39a-4eb7-a8c9-07c685f11908
9f2552
+    :setup: Standalone instance
9f2552
+    :steps:
9f2552
+         1. Check the attribute nsslapd-ignore-virtual-attrs is present in cn=config
9f2552
+         2. Check the default value of attribute nsslapd-ignore-virtual-attrs should be ON
9f2552
+         3. Create a filtered role
9f2552
+         4. Check the value of nsslapd-ignore-virtual-attrs should be OFF
9f2552
+         5. Check a message "roles_cache_trigger_update_role - Because of virtual attribute.." in error logs
9f2552
+    :expectedresults:
9f2552
+         1. This should be successful
9f2552
+         2. This should be successful
9f2552
+         3. This should be successful
9f2552
+         4. This should be successful
9f2552
+         5. This should be successful
9f2552
+    """
9f2552
+
9f2552
+    log.info("Check the attribute nsslapd-ignore-virtual-attrs is present in cn=config")
9f2552
+    assert topo.standalone.config.present('nsslapd-ignore-virtual-attrs')
9f2552
+
9f2552
+    log.info("Check the default value of attribute nsslapd-ignore-virtual-attrs should be ON")
9f2552
+    assert topo.standalone.config.get_attr_val_utf8('nsslapd-ignore-virtual-attrs') == "on"
9f2552
+
9f2552
+    log.info("Create a filtered role")
9f2552
+    try:
9f2552
+        Organization(topo.standalone).create(properties={"o": "acivattr"}, basedn=DEFAULT_SUFFIX)
9f2552
+    except:
9f2552
+        pass
9f2552
+    roles = FilteredRoles(topo.standalone, DNBASE)
9f2552
+    roles.create(properties={'cn': 'FILTERROLEENGROLE', 'nsRoleFilter': 'cn=eng*'})
9f2552
+
9f2552
+    log.info("Check the default value of attribute nsslapd-ignore-virtual-attrs should be OFF")
9f2552
+    assert topo.standalone.config.present('nsslapd-ignore-virtual-attrs', 'off')
9f2552
+
9f2552
+    topo.standalone.stop()
9f2552
+    assert topo.standalone.searchErrorsLog("roles_cache_trigger_update_role - Because of virtual attribute definition \(role\), nsslapd-ignore-virtual-attrs was set to \'off\'")
9f2552
+
9f2552
+    def fin():
9f2552
+        topo.standalone.restart()
9f2552
+        try:
9f2552
+            filtered_roles = FilteredRoles(topo.standalone, DEFAULT_SUFFIX)
9f2552
+            for i in filtered_roles.list():
9f2552
+                i.delete()
9f2552
+        except:
9f2552
+            pass
9f2552
+        topo.standalone.config.set('nsslapd-ignore-virtual-attrs', 'on')
9f2552
+
9f2552
+    request.addfinalizer(fin)
9f2552
+
9f2552
+def test_vattr_on_filtered_role_restart(topo, request):
9f2552
+    """Test nsslapd-ignore-virtual-attrs configuration attribute
9f2552
+    If it exists a filtered role definition at restart then
9f2552
+    nsslapd-ignore-virtual-attrs should be set to 'off'
9f2552
+
9f2552
+    :id: 972183f7-d18f-40e0-94ab-580e7b7d78d0
9f2552
+    :setup: Standalone instance
9f2552
+    :steps:
9f2552
+         1. Check the attribute nsslapd-ignore-virtual-attrs is present in cn=config
9f2552
+         2. Check the default value of attribute nsslapd-ignore-virtual-attrs should be ON
9f2552
+         3. Create a filtered role
9f2552
+         4. Check the value of nsslapd-ignore-virtual-attrs should be OFF
9f2552
+         5. restart the instance
9f2552
+         6. Check the presence of virtual attribute is detected
9f2552
+         7. Check the value of nsslapd-ignore-virtual-attrs should be OFF
9f2552
+    :expectedresults:
9f2552
+         1. This should be successful
9f2552
+         2. This should be successful
9f2552
+         3. This should be successful
9f2552
+         4. This should be successful
9f2552
+         5. This should be successful
9f2552
+         6. This should be successful
9f2552
+         7. This should be successful
9f2552
+    """
9f2552
+
9f2552
+    log.info("Check the attribute nsslapd-ignore-virtual-attrs is present in cn=config")
9f2552
+    assert topo.standalone.config.present('nsslapd-ignore-virtual-attrs')
9f2552
+
9f2552
+    log.info("Check the default value of attribute nsslapd-ignore-virtual-attrs should be ON")
9f2552
+    assert topo.standalone.config.get_attr_val_utf8('nsslapd-ignore-virtual-attrs') == "on"
9f2552
+
9f2552
+    log.info("Create a filtered role")
9f2552
+    try:
9f2552
+        Organization(topo.standalone).create(properties={"o": "acivattr"}, basedn=DEFAULT_SUFFIX)
9f2552
+    except:
9f2552
+        pass
9f2552
+    roles = FilteredRoles(topo.standalone, DNBASE)
9f2552
+    roles.create(properties={'cn': 'FILTERROLEENGROLE', 'nsRoleFilter': 'cn=eng*'})
9f2552
+
9f2552
+    log.info("Check the default value of attribute nsslapd-ignore-virtual-attrs should be OFF")
9f2552
+    assert topo.standalone.config.present('nsslapd-ignore-virtual-attrs', 'off')
9f2552
+
9f2552
+    
9f2552
+    log.info("Check the virtual attribute definition is found (after a required delay)")
9f2552
+    topo.standalone.restart()
9f2552
+    time.sleep(5)
9f2552
+    assert topo.standalone.searchErrorsLog("Found a role/cos definition in")
9f2552
+    assert topo.standalone.searchErrorsLog("roles_cache_trigger_update_role - Because of virtual attribute definition \(role\), nsslapd-ignore-virtual-attrs was set to \'off\'")
9f2552
+
9f2552
+    log.info("Check the default value of attribute nsslapd-ignore-virtual-attrs should be OFF")
9f2552
+    assert topo.standalone.config.present('nsslapd-ignore-virtual-attrs', 'off')
9f2552
+
9f2552
+    def fin():
9f2552
+        topo.standalone.restart()
9f2552
+        try:
9f2552
+            filtered_roles = FilteredRoles(topo.standalone, DEFAULT_SUFFIX)
9f2552
+            for i in filtered_roles.list():
9f2552
+                i.delete()
9f2552
+        except:
9f2552
+            pass
9f2552
+        topo.standalone.config.set('nsslapd-ignore-virtual-attrs', 'on')
9f2552
+
9f2552
+    request.addfinalizer(fin)
9f2552
+
9f2552
+
9f2552
+def test_vattr_on_managed_role(topo, request):
9f2552
+    """Test nsslapd-ignore-virtual-attrs configuration attribute
9f2552
+       The attribute is ON by default. If a managed role is
9f2552
+       added it is moved to OFF
9f2552
+
9f2552
+    :id: 664b722d-c1ea-41e4-8f6c-f9c87a212346
9f2552
+    :setup: Standalone instance
9f2552
+    :steps:
9f2552
+         1. Check the attribute nsslapd-ignore-virtual-attrs is present in cn=config
9f2552
+         2. Check the default value of attribute nsslapd-ignore-virtual-attrs should be ON
9f2552
+         3. Create a managed role
9f2552
+         4. Check the value of nsslapd-ignore-virtual-attrs should be OFF
9f2552
+         5. Check a message "roles_cache_trigger_update_role - Because of virtual attribute.." in error logs
9f2552
+    :expectedresults:
9f2552
+         1. This should be successful
9f2552
+         2. This should be successful
9f2552
+         3. This should be successful
9f2552
+         4. This should be successful
9f2552
+         5. This should be successful
9f2552
+    """
9f2552
+
9f2552
+    log.info("Check the attribute nsslapd-ignore-virtual-attrs is present in cn=config")
9f2552
+    assert topo.standalone.config.present('nsslapd-ignore-virtual-attrs')
9f2552
+
9f2552
+    log.info("Check the default value of attribute nsslapd-ignore-virtual-attrs should be ON")
9f2552
+    assert topo.standalone.config.get_attr_val_utf8('nsslapd-ignore-virtual-attrs') == "on"
9f2552
+
9f2552
+    log.info("Create a managed role")
9f2552
+    roles = ManagedRoles(topo.standalone, DEFAULT_SUFFIX)
9f2552
+    role = roles.create(properties={"cn": 'ROLE1'})
9f2552
+
9f2552
+    log.info("Check the default value of attribute nsslapd-ignore-virtual-attrs should be OFF")
9f2552
+    assert topo.standalone.config.present('nsslapd-ignore-virtual-attrs', 'off')
9f2552
+
9f2552
+    topo.standalone.stop()
9f2552
+    assert topo.standalone.searchErrorsLog("roles_cache_trigger_update_role - Because of virtual attribute definition \(role\), nsslapd-ignore-virtual-attrs was set to \'off\'")
9f2552
+
9f2552
+    def fin():
9f2552
+        topo.standalone.restart()
9f2552
+        try:
9f2552
+            filtered_roles = ManagedRoles(topo.standalone, DEFAULT_SUFFIX)
9f2552
+            for i in filtered_roles.list():
9f2552
+                i.delete()
9f2552
+        except:
9f2552
+            pass
9f2552
+        topo.standalone.config.set('nsslapd-ignore-virtual-attrs', 'on')
9f2552
+
9f2552
+    request.addfinalizer(fin)
9f2552
 
9f2552
 if __name__ == "__main__":
9f2552
     CURRENT_FILE = os.path.realpath(__file__)
9f2552
diff --git a/ldap/servers/plugins/roles/roles_cache.c b/ldap/servers/plugins/roles/roles_cache.c
9f2552
index 3d076a4cb..cd00e0aba 100644
9f2552
--- a/ldap/servers/plugins/roles/roles_cache.c
9f2552
+++ b/ldap/servers/plugins/roles/roles_cache.c
9f2552
@@ -530,6 +530,15 @@ roles_cache_trigger_update_role(char *dn, Slapi_Entry *roles_entry, Slapi_DN *be
9f2552
     }
9f2552
 
9f2552
     slapi_rwlock_unlock(global_lock);
9f2552
+    {
9f2552
+        /* A role definition has been updated, enable vattr handling */
9f2552
+        char errorbuf[SLAPI_DSE_RETURNTEXT_SIZE];
9f2552
+        errorbuf[0] = '\0';
9f2552
+        config_set_ignore_vattrs(CONFIG_IGNORE_VATTRS, "off", errorbuf, 1);
9f2552
+        slapi_log_err(SLAPI_LOG_INFO,
9f2552
+                      "roles_cache_trigger_update_role",
9f2552
+                      "Because of virtual attribute definition (role), %s was set to 'off'\n", CONFIG_IGNORE_VATTRS);
9f2552
+    }
9f2552
 
9f2552
     slapi_log_err(SLAPI_LOG_PLUGIN, ROLES_PLUGIN_SUBSYSTEM, "<-- roles_cache_trigger_update_role: %p \n", roles_list);
9f2552
 }
9f2552
diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c
9f2552
index 2ea4cd760..f6dacce30 100644
9f2552
--- a/ldap/servers/slapd/libglobs.c
9f2552
+++ b/ldap/servers/slapd/libglobs.c
9f2552
@@ -1803,7 +1803,7 @@ FrontendConfig_init(void)
9f2552
     init_ndn_cache_enabled = cfg->ndn_cache_enabled = LDAP_ON;
9f2552
     cfg->ndn_cache_max_size = SLAPD_DEFAULT_NDN_SIZE;
9f2552
     init_sasl_mapping_fallback = cfg->sasl_mapping_fallback = LDAP_OFF;
9f2552
-    init_ignore_vattrs = cfg->ignore_vattrs = LDAP_OFF;
9f2552
+    init_ignore_vattrs = cfg->ignore_vattrs = LDAP_ON;
9f2552
     cfg->sasl_max_bufsize = SLAPD_DEFAULT_SASL_MAXBUFSIZE;
9f2552
     cfg->unhashed_pw_switch = SLAPD_DEFAULT_UNHASHED_PW_SWITCH;
9f2552
     init_return_orig_type = cfg->return_orig_type = LDAP_OFF;
9f2552
diff --git a/ldap/servers/slapd/main.c b/ldap/servers/slapd/main.c
9f2552
index 4931a4ca4..61ed40b7d 100644
9f2552
--- a/ldap/servers/slapd/main.c
9f2552
+++ b/ldap/servers/slapd/main.c
9f2552
@@ -1042,6 +1042,8 @@ main(int argc, char **argv)
9f2552
         eq_start(); /* must be done after plugins started - DEPRECATED */
9f2552
         eq_start_rel(); /* must be done after plugins started */
9f2552
 
9f2552
+        vattr_check(); /* Check if it exists virtual attribute definitions */
9f2552
+
9f2552
 #ifdef HPUX10
9f2552
         /* HPUX linker voodoo */
9f2552
         if (collation_init == NULL) {
9f2552
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
9f2552
index c143f3772..442a621aa 100644
9f2552
--- a/ldap/servers/slapd/proto-slap.h
9f2552
+++ b/ldap/servers/slapd/proto-slap.h
9f2552
@@ -1462,6 +1462,7 @@ void subentry_create_filter(Slapi_Filter **filter);
9f2552
  */
9f2552
 void vattr_init(void);
9f2552
 void vattr_cleanup(void);
9f2552
+void vattr_check(void);
9f2552
 
9f2552
 /*
9f2552
  * slapd_plhash.c - supplement to NSPR plhash
9f2552
diff --git a/ldap/servers/slapd/vattr.c b/ldap/servers/slapd/vattr.c
9f2552
index 09dab6ecf..24750a57c 100644
9f2552
--- a/ldap/servers/slapd/vattr.c
9f2552
+++ b/ldap/servers/slapd/vattr.c
9f2552
@@ -64,6 +64,10 @@
9f2552
 #define SOURCEFILE "vattr.c"
9f2552
 static char *sourcefile = SOURCEFILE;
9f2552
 
9f2552
+/* stolen from roles_cache.h, must remain in sync */
9f2552
+#define NSROLEATTR "nsRole"
9f2552
+static Slapi_Eq_Context vattr_check_ctx = {0};
9f2552
+
9f2552
 /* Define only for module test code */
9f2552
 /* #define VATTR_TEST_CODE */
9f2552
 
9f2552
@@ -130,6 +134,112 @@ vattr_cleanup()
9f2552
 {
9f2552
     /* We need to free and remove anything that was inserted first */
9f2552
     vattr_map_destroy();
9f2552
+    slapi_eq_cancel_rel(vattr_check_ctx);
9f2552
+}
9f2552
+
9f2552
+static void
9f2552
+vattr_check_thread(void *arg)
9f2552
+{
9f2552
+    Slapi_Backend *be = NULL;
9f2552
+    char *cookie = NULL;
9f2552
+    Slapi_DN *base_sdn = NULL;
9f2552
+    Slapi_PBlock *search_pb = NULL;
9f2552
+    Slapi_Entry **entries = NULL;
9f2552
+    int32_t rc;
9f2552
+    int32_t check_suffix; /* used to skip suffixes in ignored_backend */
9f2552
+    PRBool exist_vattr_definition = PR_FALSE;
9f2552
+    char *ignored_backend[5] = {"cn=config", "cn=schema", "cn=monitor", "cn=changelog", NULL}; /* suffixes to ignore */
9f2552
+    char *suffix;
9f2552
+    int ignore_vattrs;
9f2552
+
9f2552
+    ignore_vattrs = config_get_ignore_vattrs();
9f2552
+
9f2552
+    if (!ignore_vattrs) {
9f2552
+        /* Nothing to do more, we are already evaluating virtual attribute */
9f2552
+        return;
9f2552
+    }
9f2552
+
9f2552
+    search_pb = slapi_pblock_new();
9f2552
+    be = slapi_get_first_backend(&cookie);
9f2552
+    while (be && !exist_vattr_definition && !slapi_is_shutting_down()) {
9f2552
+        base_sdn = (Slapi_DN *) slapi_be_getsuffix(be, 0);
9f2552
+        suffix = (char *) slapi_sdn_get_dn(base_sdn);
9f2552
+
9f2552
+        if (suffix) {
9f2552
+            /* First check that we need to check that suffix */
9f2552
+            check_suffix = 1;
9f2552
+            for (size_t i = 0; ignored_backend[i]; i++) {
9f2552
+                if (strcasecmp(suffix, ignored_backend[i]) == 0) {
9f2552
+                    check_suffix = 0;
9f2552
+                    break;
9f2552
+                }
9f2552
+            }
9f2552
+
9f2552
+            /* search for a role or cos definition */
9f2552
+            if (check_suffix) {
9f2552
+                slapi_search_internal_set_pb(search_pb, slapi_sdn_get_dn(base_sdn),
9f2552
+                        LDAP_SCOPE_SUBTREE, "(&(objectclass=ldapsubentry)(|(objectclass=nsRoleDefinition)(objectclass=cosSuperDefinition)))",
9f2552
+                        NULL, 0, NULL, NULL, (void *) plugin_get_default_component_id(), 0);
9f2552
+                slapi_search_internal_pb(search_pb);
9f2552
+                slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
9f2552
+
9f2552
+                if (rc == LDAP_SUCCESS) {
9f2552
+                    slapi_pblock_get(search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
9f2552
+                    if (entries && entries[0]) {
9f2552
+                        /* it exists at least a cos or role definition */
9f2552
+                        exist_vattr_definition = PR_TRUE;
9f2552
+                        slapi_log_err(SLAPI_LOG_INFO,
9f2552
+                                "vattr_check_thread",
9f2552
+                                "Found a role/cos definition in %s\n", slapi_entry_get_dn(entries[0]));
9f2552
+                    } else {
9f2552
+                        slapi_log_err(SLAPI_LOG_INFO,
9f2552
+                                "vattr_check_thread",
9f2552
+                                "No role/cos definition in %s\n", slapi_sdn_get_dn(base_sdn));
9f2552
+                    }
9f2552
+                }
9f2552
+                slapi_free_search_results_internal(search_pb);
9f2552
+            } /* check_suffix */
9f2552
+        } /* suffix */
9f2552
+        be = (backend *) slapi_get_next_backend(cookie);
9f2552
+    }
9f2552
+    slapi_pblock_destroy(search_pb);
9f2552
+    slapi_ch_free_string(&cookie);
9f2552
+
9f2552
+    /* Now if a virtual attribute is defined, then CONFIG_IGNORE_VATTRS -> off */
9f2552
+    if (exist_vattr_definition) {
9f2552
+        char errorbuf[SLAPI_DSE_RETURNTEXT_SIZE];
9f2552
+        errorbuf[0] = '\0';
9f2552
+        config_set_ignore_vattrs(CONFIG_IGNORE_VATTRS, "off", errorbuf, 1);
9f2552
+        slapi_log_err(SLAPI_LOG_INFO,
9f2552
+                      "vattr_check_thread",
9f2552
+                      "Because of virtual attribute definition, %s was set to 'off'\n", CONFIG_IGNORE_VATTRS);
9f2552
+    }
9f2552
+}
9f2552
+static void
9f2552
+vattr_check_schedule_once(time_t when __attribute__((unused)), void *arg)
9f2552
+{
9f2552
+    if (PR_CreateThread(PR_USER_THREAD,
9f2552
+                        vattr_check_thread,
9f2552
+                        (void *) arg,
9f2552
+                        PR_PRIORITY_NORMAL,
9f2552
+                        PR_GLOBAL_THREAD,
9f2552
+                        PR_UNJOINABLE_THREAD,
9f2552
+                        SLAPD_DEFAULT_THREAD_STACKSIZE) == NULL) {
9f2552
+        slapi_log_err(SLAPI_LOG_ERR,
9f2552
+                      "vattr_check_schedule_once",
9f2552
+                      "Fails to check if %s needs to be toggled to FALSE\n", CONFIG_IGNORE_VATTRS);
9f2552
+    }
9f2552
+}
9f2552
+#define VATTR_CHECK_DELAY 3
9f2552
+void
9f2552
+vattr_check()
9f2552
+{
9f2552
+    /* Schedule running a callback that will create a thread
9f2552
+     * but make sure it is called a first thing when event loop is created */
9f2552
+    time_t now;
9f2552
+
9f2552
+    now = slapi_current_rel_time_t();
9f2552
+    vattr_check_ctx = slapi_eq_once_rel(vattr_check_schedule_once, NULL, now + VATTR_CHECK_DELAY);
9f2552
 }
9f2552
 
9f2552
 /* The public interface functions start here */
9f2552
@@ -1631,6 +1741,9 @@ slapi_vattrspi_regattr(vattr_sp_handle *h, char *type_name_to_register, char *DN
9f2552
     char *type_to_add;
9f2552
     int free_type_to_add = 0;
9f2552
     Slapi_DN original_dn;
9f2552
+    int ignore_vattrs;
9f2552
+
9f2552
+    ignore_vattrs = config_get_ignore_vattrs();
9f2552
 
9f2552
     slapi_sdn_init(&original_dn);
9f2552
 
9f2552
@@ -1676,6 +1789,20 @@ slapi_vattrspi_regattr(vattr_sp_handle *h, char *type_name_to_register, char *DN
9f2552
     if (free_type_to_add) {
9f2552
         slapi_ch_free((void **)&type_to_add);
9f2552
     }
9f2552
+    if (ignore_vattrs && strcasecmp(type_name_to_register, NSROLEATTR)) {
9f2552
+        /* A new virtual attribute is registered.
9f2552
+         * This new vattr being *different* than the default roles vattr 'nsRole'
9f2552
+         * It is time to allow vattr lookup
9f2552
+         */
9f2552
+        char errorbuf[SLAPI_DSE_RETURNTEXT_SIZE];
9f2552
+        errorbuf[0] = '\0';
9f2552
+        config_set_ignore_vattrs(CONFIG_IGNORE_VATTRS, "off", errorbuf, 1);
9f2552
+        slapi_log_err(SLAPI_LOG_INFO,
9f2552
+                      "slapi_vattrspi_regattr",
9f2552
+                      "Because %s is a new registered virtual attribute , %s was set to 'off'\n",
9f2552
+                      type_name_to_register,
9f2552
+                      CONFIG_IGNORE_VATTRS);
9f2552
+    }
9f2552
 
9f2552
     return ret;
9f2552
 }
9f2552
diff --git a/src/lib389/lib389/idm/role.py b/src/lib389/lib389/idm/role.py
9f2552
index fe91aab6f..9a2bff3d6 100644
9f2552
--- a/src/lib389/lib389/idm/role.py
9f2552
+++ b/src/lib389/lib389/idm/role.py
9f2552
@@ -252,6 +252,8 @@ class FilteredRole(Role):
9f2552
         self._rdn_attribute = 'cn'
9f2552
         self._create_objectclasses = ['nsComplexRoleDefinition', 'nsFilteredRoleDefinition']
9f2552
 
9f2552
+        self._protected = False
9f2552
+
9f2552
 
9f2552
 
9f2552
 class FilteredRoles(Roles):
9f2552
@@ -285,6 +287,7 @@ class ManagedRole(Role):
9f2552
         self._rdn_attribute = 'cn'
9f2552
         self._create_objectclasses = ['nsSimpleRoleDefinition', 'nsManagedRoleDefinition']
9f2552
 
9f2552
+        self._protected = False
9f2552
 
9f2552
 class ManagedRoles(Roles):
9f2552
     """DSLdapObjects that represents all Managed Roles entries
9f2552
@@ -320,6 +323,7 @@ class NestedRole(Role):
9f2552
         self._rdn_attribute = 'cn'
9f2552
         self._create_objectclasses = ['nsComplexRoleDefinition', 'nsNestedRoleDefinition']
9f2552
 
9f2552
+        self._protected = False
9f2552
 
9f2552
 class NestedRoles(Roles):
9f2552
     """DSLdapObjects that represents all NestedRoles entries in suffix.
9f2552
-- 
9f2552
2.31.1
9f2552