|
|
9f2552 |
From 2ae2f53756b6f13e2816bb30812740cb7ad97403 Mon Sep 17 00:00:00 2001
|
|
|
9f2552 |
From: tbordaz <tbordaz@redhat.com>
|
|
|
9f2552 |
Date: Fri, 5 Nov 2021 09:56:43 +0100
|
|
|
9f2552 |
Subject: [PATCH 09/12] Issue 4972 - gecos with IA5 introduces a compatibility
|
|
|
9f2552 |
issue with previous (#4981)
|
|
|
9f2552 |
|
|
|
9f2552 |
releases where it was DirectoryString
|
|
|
9f2552 |
|
|
|
9f2552 |
Bug description:
|
|
|
9f2552 |
For years 'gecos' was DirectoryString (UTF8), with #50933 it was restricted to IA5 (ascii)
|
|
|
9f2552 |
https://github.com/389ds/389-ds-base/commit/0683bcde1b667b6d0ca6e8d1ef605f17c51ea2f7#
|
|
|
9f2552 |
|
|
|
9f2552 |
IA5 definition conforms rfc2307 but is a problem for existing deployments
|
|
|
9f2552 |
where entries can have 'gecos' attribute value with UTF8.
|
|
|
9f2552 |
|
|
|
9f2552 |
Fix description:
|
|
|
9f2552 |
Revert the definition to of 'gecos' being Directory String
|
|
|
9f2552 |
|
|
|
9f2552 |
Additional fix to make test_replica_backup_and_restore more
|
|
|
9f2552 |
robust to CI
|
|
|
9f2552 |
|
|
|
9f2552 |
relates: https://github.com/389ds/389-ds-base/issues/4972
|
|
|
9f2552 |
|
|
|
9f2552 |
Reviewed by: William Brown, Pierre Rogier, James Chapman (Thanks !)
|
|
|
9f2552 |
|
|
|
9f2552 |
Platforms tested: F34
|
|
|
9f2552 |
---
|
|
|
9f2552 |
.../tests/suites/schema/schema_test.py | 398 +++++++++++++++++-
|
|
|
9f2552 |
ldap/schema/10rfc2307compat.ldif | 6 +-
|
|
|
9f2552 |
2 files changed, 400 insertions(+), 4 deletions(-)
|
|
|
9f2552 |
|
|
|
9f2552 |
diff --git a/dirsrvtests/tests/suites/schema/schema_test.py b/dirsrvtests/tests/suites/schema/schema_test.py
|
|
|
9f2552 |
index d590624b6..5d62b8d59 100644
|
|
|
9f2552 |
--- a/dirsrvtests/tests/suites/schema/schema_test.py
|
|
|
9f2552 |
+++ b/dirsrvtests/tests/suites/schema/schema_test.py
|
|
|
9f2552 |
@@ -18,8 +18,12 @@ import pytest
|
|
|
9f2552 |
import six
|
|
|
9f2552 |
from ldap.cidict import cidict
|
|
|
9f2552 |
from ldap.schema import SubSchema
|
|
|
9f2552 |
+from lib389.schema import SchemaLegacy
|
|
|
9f2552 |
from lib389._constants import *
|
|
|
9f2552 |
-from lib389.topologies import topology_st
|
|
|
9f2552 |
+from lib389.topologies import topology_st, topology_m2 as topo_m2
|
|
|
9f2552 |
+from lib389.idm.user import UserAccounts, UserAccount
|
|
|
9f2552 |
+from lib389.replica import ReplicationManager
|
|
|
9f2552 |
+from lib389.utils import ensure_bytes
|
|
|
9f2552 |
|
|
|
9f2552 |
pytestmark = pytest.mark.tier1
|
|
|
9f2552 |
|
|
|
9f2552 |
@@ -165,6 +169,398 @@ def test_schema_comparewithfiles(topology_st):
|
|
|
9f2552 |
|
|
|
9f2552 |
log.info('test_schema_comparewithfiles: PASSED')
|
|
|
9f2552 |
|
|
|
9f2552 |
+def test_gecos_directoryString(topology_st):
|
|
|
9f2552 |
+ """Check that gecos supports directoryString value
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ :id: aee422bb-6299-4124-b5cd-d7393dac19d3
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ :setup: Standalone instance
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ :steps:
|
|
|
9f2552 |
+ 1. Add a common user
|
|
|
9f2552 |
+ 2. replace gecos with a direstoryString value
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ :expectedresults:
|
|
|
9f2552 |
+ 1. Success
|
|
|
9f2552 |
+ 2. Success
|
|
|
9f2552 |
+ """
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ users = UserAccounts(topology_st.standalone, DEFAULT_SUFFIX)
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ user_properties = {
|
|
|
9f2552 |
+ 'uid': 'testuser',
|
|
|
9f2552 |
+ 'cn' : 'testuser',
|
|
|
9f2552 |
+ 'sn' : 'user',
|
|
|
9f2552 |
+ 'uidNumber' : '1000',
|
|
|
9f2552 |
+ 'gidNumber' : '2000',
|
|
|
9f2552 |
+ 'homeDirectory' : '/home/testuser',
|
|
|
9f2552 |
+ }
|
|
|
9f2552 |
+ testuser = users.create(properties=user_properties)
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ # Add a gecos UTF value
|
|
|
9f2552 |
+ testuser.replace('gecos', 'Hélène')
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+def test_gecos_mixed_definition_topo(topo_m2, request):
|
|
|
9f2552 |
+ """Check that replication is still working if schema contains
|
|
|
9f2552 |
+ definitions that does not conform with a replicated entry
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ :id: d5940e71-d18a-4b71-aaf7-b9185361fffe
|
|
|
9f2552 |
+ :setup: Two suppliers replication setup
|
|
|
9f2552 |
+ :steps:
|
|
|
9f2552 |
+ 1. Create a testuser on M1
|
|
|
9f2552 |
+ 2 Stop M1 and M2
|
|
|
9f2552 |
+ 3 Change gecos def on M2 to be IA5
|
|
|
9f2552 |
+ 4 Update testuser with gecos directoryString value
|
|
|
9f2552 |
+ 5 Check replication is still working
|
|
|
9f2552 |
+ :expectedresults:
|
|
|
9f2552 |
+ 1. success
|
|
|
9f2552 |
+ 2. success
|
|
|
9f2552 |
+ 3. success
|
|
|
9f2552 |
+ 4. success
|
|
|
9f2552 |
+ 5. success
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ """
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ repl = ReplicationManager(DEFAULT_SUFFIX)
|
|
|
9f2552 |
+ m1 = topo_m2.ms["supplier1"]
|
|
|
9f2552 |
+ m2 = topo_m2.ms["supplier2"]
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ # create a test user
|
|
|
9f2552 |
+ testuser_dn = 'uid={},{}'.format('testuser', DEFAULT_SUFFIX)
|
|
|
9f2552 |
+ testuser = UserAccount(m1, testuser_dn)
|
|
|
9f2552 |
+ try:
|
|
|
9f2552 |
+ testuser.create(properties={
|
|
|
9f2552 |
+ 'uid': 'testuser',
|
|
|
9f2552 |
+ 'cn': 'testuser',
|
|
|
9f2552 |
+ 'sn': 'testuser',
|
|
|
9f2552 |
+ 'uidNumber' : '1000',
|
|
|
9f2552 |
+ 'gidNumber' : '2000',
|
|
|
9f2552 |
+ 'homeDirectory' : '/home/testuser',
|
|
|
9f2552 |
+ })
|
|
|
9f2552 |
+ except ldap.ALREADY_EXISTS:
|
|
|
9f2552 |
+ pass
|
|
|
9f2552 |
+ repl.wait_for_replication(m1, m2)
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ # Stop suppliers to update the schema
|
|
|
9f2552 |
+ m1.stop()
|
|
|
9f2552 |
+ m2.stop()
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ # on M1: gecos is DirectoryString (default)
|
|
|
9f2552 |
+ # on M2: gecos is IA5
|
|
|
9f2552 |
+ schema_filename = (m2.schemadir + "/99user.ldif")
|
|
|
9f2552 |
+ try:
|
|
|
9f2552 |
+ with open(schema_filename, 'w') as schema_file:
|
|
|
9f2552 |
+ schema_file.write("dn: cn=schema\n")
|
|
|
9f2552 |
+ schema_file.write("attributetypes: ( 1.3.6.1.1.1.1.2 NAME " +
|
|
|
9f2552 |
+ "'gecos' DESC 'The GECOS field; the common name' " +
|
|
|
9f2552 |
+ "EQUALITY caseIgnoreIA5Match " +
|
|
|
9f2552 |
+ "SUBSTR caseIgnoreIA5SubstringsMatch " +
|
|
|
9f2552 |
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 " +
|
|
|
9f2552 |
+ "SINGLE-VALUE )\n")
|
|
|
9f2552 |
+ os.chmod(schema_filename, 0o777)
|
|
|
9f2552 |
+ except OSError as e:
|
|
|
9f2552 |
+ log.fatal("Failed to update schema file: " +
|
|
|
9f2552 |
+ "{} Error: {}".format(schema_filename, str(e)))
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ # start the instances
|
|
|
9f2552 |
+ m1.start()
|
|
|
9f2552 |
+ m2.start()
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ # Check that gecos is IA5 on M2
|
|
|
9f2552 |
+ schema = SchemaLegacy(m2)
|
|
|
9f2552 |
+ attributetypes = schema.query_attributetype('gecos')
|
|
|
9f2552 |
+ assert attributetypes[0].syntax == "1.3.6.1.4.1.1466.115.121.1.26"
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ # Add a gecos UTF value on M1
|
|
|
9f2552 |
+ testuser.replace('gecos', 'Hélène')
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ # Check replication is still working
|
|
|
9f2552 |
+ testuser.replace('displayName', 'ascii value')
|
|
|
9f2552 |
+ repl.wait_for_replication(m1, m2)
|
|
|
9f2552 |
+ testuser_m2 = UserAccount(m2, testuser_dn)
|
|
|
9f2552 |
+ assert testuser_m2.exists()
|
|
|
9f2552 |
+ assert testuser_m2.get_attr_val_utf8('displayName') == 'ascii value'
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ def fin():
|
|
|
9f2552 |
+ m1.start()
|
|
|
9f2552 |
+ m2.start()
|
|
|
9f2552 |
+ testuser.delete()
|
|
|
9f2552 |
+ repl.wait_for_replication(m1, m2)
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ # on M2 restore a default 99user.ldif
|
|
|
9f2552 |
+ m2.stop()
|
|
|
9f2552 |
+ os.remove(m2.schemadir + "/99user.ldif")
|
|
|
9f2552 |
+ schema_filename = (m2.schemadir + "/99user.ldif")
|
|
|
9f2552 |
+ try:
|
|
|
9f2552 |
+ with open(schema_filename, 'w') as schema_file:
|
|
|
9f2552 |
+ schema_file.write("dn: cn=schema\n")
|
|
|
9f2552 |
+ os.chmod(schema_filename, 0o777)
|
|
|
9f2552 |
+ except OSError as e:
|
|
|
9f2552 |
+ log.fatal("Failed to update schema file: " +
|
|
|
9f2552 |
+ "{} Error: {}".format(schema_filename, str(e)))
|
|
|
9f2552 |
+ m2.start()
|
|
|
9f2552 |
+ m1.start()
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ request.addfinalizer(fin)
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+def test_gecos_directoryString_wins_M1(topo_m2, request):
|
|
|
9f2552 |
+ """Check that if inital syntax are IA5(M2) and DirectoryString(M1)
|
|
|
9f2552 |
+ Then directoryString wins when nsSchemaCSN M1 is the greatest
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ :id: ad119fa5-7671-45c8-b2ef-0b28ffb68fdb
|
|
|
9f2552 |
+ :setup: Two suppliers replication setup
|
|
|
9f2552 |
+ :steps:
|
|
|
9f2552 |
+ 1. Create a testuser on M1
|
|
|
9f2552 |
+ 2 Stop M1 and M2
|
|
|
9f2552 |
+ 3 Change gecos def on M2 to be IA5
|
|
|
9f2552 |
+ 4 Start M1 and M2
|
|
|
9f2552 |
+ 5 Update M1 schema so that M1 has greatest nsSchemaCSN
|
|
|
9f2552 |
+ 6 Update testuser with gecos directoryString value
|
|
|
9f2552 |
+ 7 Check replication is still working
|
|
|
9f2552 |
+ 8 Check gecos is DirectoryString on M1 and M2
|
|
|
9f2552 |
+ :expectedresults:
|
|
|
9f2552 |
+ 1. success
|
|
|
9f2552 |
+ 2. success
|
|
|
9f2552 |
+ 3. success
|
|
|
9f2552 |
+ 4. success
|
|
|
9f2552 |
+ 5. success
|
|
|
9f2552 |
+ 6. success
|
|
|
9f2552 |
+ 7. success
|
|
|
9f2552 |
+ 8. success
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ """
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ repl = ReplicationManager(DEFAULT_SUFFIX)
|
|
|
9f2552 |
+ m1 = topo_m2.ms["supplier1"]
|
|
|
9f2552 |
+ m2 = topo_m2.ms["supplier2"]
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ # create a test user
|
|
|
9f2552 |
+ testuser_dn = 'uid={},{}'.format('testuser', DEFAULT_SUFFIX)
|
|
|
9f2552 |
+ testuser = UserAccount(m1, testuser_dn)
|
|
|
9f2552 |
+ try:
|
|
|
9f2552 |
+ testuser.create(properties={
|
|
|
9f2552 |
+ 'uid': 'testuser',
|
|
|
9f2552 |
+ 'cn': 'testuser',
|
|
|
9f2552 |
+ 'sn': 'testuser',
|
|
|
9f2552 |
+ 'uidNumber' : '1000',
|
|
|
9f2552 |
+ 'gidNumber' : '2000',
|
|
|
9f2552 |
+ 'homeDirectory' : '/home/testuser',
|
|
|
9f2552 |
+ })
|
|
|
9f2552 |
+ except ldap.ALREADY_EXISTS:
|
|
|
9f2552 |
+ pass
|
|
|
9f2552 |
+ repl.wait_for_replication(m1, m2)
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ # Stop suppliers to update the schema
|
|
|
9f2552 |
+ m1.stop()
|
|
|
9f2552 |
+ m2.stop()
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ # on M1: gecos is DirectoryString (default)
|
|
|
9f2552 |
+ # on M2: gecos is IA5
|
|
|
9f2552 |
+ schema_filename = (m2.schemadir + "/99user.ldif")
|
|
|
9f2552 |
+ try:
|
|
|
9f2552 |
+ with open(schema_filename, 'w') as schema_file:
|
|
|
9f2552 |
+ schema_file.write("dn: cn=schema\n")
|
|
|
9f2552 |
+ schema_file.write("attributetypes: ( 1.3.6.1.1.1.1.2 NAME " +
|
|
|
9f2552 |
+ "'gecos' DESC 'The GECOS field; the common name' " +
|
|
|
9f2552 |
+ "EQUALITY caseIgnoreIA5Match " +
|
|
|
9f2552 |
+ "SUBSTR caseIgnoreIA5SubstringsMatch " +
|
|
|
9f2552 |
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 " +
|
|
|
9f2552 |
+ "SINGLE-VALUE )\n")
|
|
|
9f2552 |
+ os.chmod(schema_filename, 0o777)
|
|
|
9f2552 |
+ except OSError as e:
|
|
|
9f2552 |
+ log.fatal("Failed to update schema file: " +
|
|
|
9f2552 |
+ "{} Error: {}".format(schema_filename, str(e)))
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ # start the instances
|
|
|
9f2552 |
+ m1.start()
|
|
|
9f2552 |
+ m2.start()
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ # Check that gecos is IA5 on M2
|
|
|
9f2552 |
+ schema = SchemaLegacy(m2)
|
|
|
9f2552 |
+ attributetypes = schema.query_attributetype('gecos')
|
|
|
9f2552 |
+ assert attributetypes[0].syntax == "1.3.6.1.4.1.1466.115.121.1.26"
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ # update M1 schema to increase its nsschemaCSN
|
|
|
9f2552 |
+ new_at = "( dummy-oid NAME 'dummy' DESC 'dummy attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'RFC 2307' )"
|
|
|
9f2552 |
+ m1.schema.add_schema('attributetypes', ensure_bytes(new_at))
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ # Add a gecos UTF value on M1
|
|
|
9f2552 |
+ testuser.replace('gecos', 'Hélène')
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ # Check replication is still working
|
|
|
9f2552 |
+ testuser.replace('displayName', 'ascii value')
|
|
|
9f2552 |
+ repl.wait_for_replication(m1, m2)
|
|
|
9f2552 |
+ testuser_m2 = UserAccount(m2, testuser_dn)
|
|
|
9f2552 |
+ assert testuser_m2.exists()
|
|
|
9f2552 |
+ assert testuser_m2.get_attr_val_utf8('displayName') == 'ascii value'
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ # Check that gecos is DirectoryString on M1
|
|
|
9f2552 |
+ schema = SchemaLegacy(m1)
|
|
|
9f2552 |
+ attributetypes = schema.query_attributetype('gecos')
|
|
|
9f2552 |
+ assert attributetypes[0].syntax == "1.3.6.1.4.1.1466.115.121.1.15"
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ # Check that gecos is DirectoryString on M2
|
|
|
9f2552 |
+ schema = SchemaLegacy(m2)
|
|
|
9f2552 |
+ attributetypes = schema.query_attributetype('gecos')
|
|
|
9f2552 |
+ assert attributetypes[0].syntax == "1.3.6.1.4.1.1466.115.121.1.15"
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ def fin():
|
|
|
9f2552 |
+ m1.start()
|
|
|
9f2552 |
+ m2.start()
|
|
|
9f2552 |
+ testuser.delete()
|
|
|
9f2552 |
+ m1.schema.del_schema('attributetypes', ensure_bytes(new_at))
|
|
|
9f2552 |
+ repl.wait_for_replication(m1, m2)
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ # on M2 restore a default 99user.ldif
|
|
|
9f2552 |
+ m2.stop()
|
|
|
9f2552 |
+ os.remove(m2.schemadir + "/99user.ldif")
|
|
|
9f2552 |
+ schema_filename = (m2.schemadir + "/99user.ldif")
|
|
|
9f2552 |
+ try:
|
|
|
9f2552 |
+ with open(schema_filename, 'w') as schema_file:
|
|
|
9f2552 |
+ schema_file.write("dn: cn=schema\n")
|
|
|
9f2552 |
+ os.chmod(schema_filename, 0o777)
|
|
|
9f2552 |
+ except OSError as e:
|
|
|
9f2552 |
+ log.fatal("Failed to update schema file: " +
|
|
|
9f2552 |
+ "{} Error: {}".format(schema_filename, str(e)))
|
|
|
9f2552 |
+ m2.start()
|
|
|
9f2552 |
+ m1.start()
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ request.addfinalizer(fin)
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+def test_gecos_directoryString_wins_M2(topo_m2, request):
|
|
|
9f2552 |
+ """Check that if inital syntax are IA5(M2) and DirectoryString(M1)
|
|
|
9f2552 |
+ Then directoryString wins when nsSchemaCSN M2 is the greatest
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ :id: 2da7f1b1-f86d-4072-a940-ba56d4bc8348
|
|
|
9f2552 |
+ :setup: Two suppliers replication setup
|
|
|
9f2552 |
+ :steps:
|
|
|
9f2552 |
+ 1. Create a testuser on M1
|
|
|
9f2552 |
+ 2 Stop M1 and M2
|
|
|
9f2552 |
+ 3 Change gecos def on M2 to be IA5
|
|
|
9f2552 |
+ 4 Start M1 and M2
|
|
|
9f2552 |
+ 5 Update M2 schema so that M2 has greatest nsSchemaCSN
|
|
|
9f2552 |
+ 6 Update testuser on M2 and trigger replication to M1
|
|
|
9f2552 |
+ 7 Update testuser on M2 with gecos directoryString value
|
|
|
9f2552 |
+ 8 Check replication is still working
|
|
|
9f2552 |
+ 9 Check gecos is DirectoryString on M1 and M2
|
|
|
9f2552 |
+ :expectedresults:
|
|
|
9f2552 |
+ 1. success
|
|
|
9f2552 |
+ 2. success
|
|
|
9f2552 |
+ 3. success
|
|
|
9f2552 |
+ 4. success
|
|
|
9f2552 |
+ 5. success
|
|
|
9f2552 |
+ 6. success
|
|
|
9f2552 |
+ 7. success
|
|
|
9f2552 |
+ 8. success
|
|
|
9f2552 |
+ 9. success
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ """
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ repl = ReplicationManager(DEFAULT_SUFFIX)
|
|
|
9f2552 |
+ m1 = topo_m2.ms["supplier1"]
|
|
|
9f2552 |
+ m2 = topo_m2.ms["supplier2"]
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ # create a test user
|
|
|
9f2552 |
+ testuser_dn = 'uid={},{}'.format('testuser', DEFAULT_SUFFIX)
|
|
|
9f2552 |
+ testuser = UserAccount(m1, testuser_dn)
|
|
|
9f2552 |
+ try:
|
|
|
9f2552 |
+ testuser.create(properties={
|
|
|
9f2552 |
+ 'uid': 'testuser',
|
|
|
9f2552 |
+ 'cn': 'testuser',
|
|
|
9f2552 |
+ 'sn': 'testuser',
|
|
|
9f2552 |
+ 'uidNumber' : '1000',
|
|
|
9f2552 |
+ 'gidNumber' : '2000',
|
|
|
9f2552 |
+ 'homeDirectory' : '/home/testuser',
|
|
|
9f2552 |
+ })
|
|
|
9f2552 |
+ except ldap.ALREADY_EXISTS:
|
|
|
9f2552 |
+ pass
|
|
|
9f2552 |
+ testuser.replace('displayName', 'to trigger replication M1-> M2')
|
|
|
9f2552 |
+ repl.wait_for_replication(m1, m2)
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ # Stop suppliers to update the schema
|
|
|
9f2552 |
+ m1.stop()
|
|
|
9f2552 |
+ m2.stop()
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ # on M1: gecos is DirectoryString (default)
|
|
|
9f2552 |
+ # on M2: gecos is IA5
|
|
|
9f2552 |
+ schema_filename = (m2.schemadir + "/99user.ldif")
|
|
|
9f2552 |
+ try:
|
|
|
9f2552 |
+ with open(schema_filename, 'w') as schema_file:
|
|
|
9f2552 |
+ schema_file.write("dn: cn=schema\n")
|
|
|
9f2552 |
+ schema_file.write("attributetypes: ( 1.3.6.1.1.1.1.2 NAME " +
|
|
|
9f2552 |
+ "'gecos' DESC 'The GECOS field; the common name' " +
|
|
|
9f2552 |
+ "EQUALITY caseIgnoreIA5Match " +
|
|
|
9f2552 |
+ "SUBSTR caseIgnoreIA5SubstringsMatch " +
|
|
|
9f2552 |
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 " +
|
|
|
9f2552 |
+ "SINGLE-VALUE )\n")
|
|
|
9f2552 |
+ os.chmod(schema_filename, 0o777)
|
|
|
9f2552 |
+ except OSError as e:
|
|
|
9f2552 |
+ log.fatal("Failed to update schema file: " +
|
|
|
9f2552 |
+ "{} Error: {}".format(schema_filename, str(e)))
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ # start the instances
|
|
|
9f2552 |
+ m1.start()
|
|
|
9f2552 |
+ m2.start()
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ # Check that gecos is IA5 on M2
|
|
|
9f2552 |
+ schema = SchemaLegacy(m2)
|
|
|
9f2552 |
+ attributetypes = schema.query_attributetype('gecos')
|
|
|
9f2552 |
+ assert attributetypes[0].syntax == "1.3.6.1.4.1.1466.115.121.1.26"
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ # update M2 schema to increase its nsschemaCSN
|
|
|
9f2552 |
+ new_at = "( dummy-oid NAME 'dummy' DESC 'dummy attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'RFC 2307' )"
|
|
|
9f2552 |
+ m2.schema.add_schema('attributetypes', ensure_bytes(new_at))
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ # update just to trigger replication M2->M1
|
|
|
9f2552 |
+ # and update of M2 schema
|
|
|
9f2552 |
+ testuser_m2 = UserAccount(m2, testuser_dn)
|
|
|
9f2552 |
+ testuser_m2.replace('displayName', 'to trigger replication M2-> M1')
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ # Add a gecos UTF value on M1
|
|
|
9f2552 |
+ testuser.replace('gecos', 'Hélène')
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ # Check replication is still working
|
|
|
9f2552 |
+ testuser.replace('displayName', 'ascii value')
|
|
|
9f2552 |
+ repl.wait_for_replication(m1, m2)
|
|
|
9f2552 |
+ assert testuser_m2.exists()
|
|
|
9f2552 |
+ assert testuser_m2.get_attr_val_utf8('displayName') == 'ascii value'
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ # Check that gecos is DirectoryString on M1
|
|
|
9f2552 |
+ schema = SchemaLegacy(m1)
|
|
|
9f2552 |
+ attributetypes = schema.query_attributetype('gecos')
|
|
|
9f2552 |
+ assert attributetypes[0].syntax == "1.3.6.1.4.1.1466.115.121.1.15"
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ # Check that gecos is DirectoryString on M2
|
|
|
9f2552 |
+ schema = SchemaLegacy(m2)
|
|
|
9f2552 |
+ attributetypes = schema.query_attributetype('gecos')
|
|
|
9f2552 |
+ assert attributetypes[0].syntax == "1.3.6.1.4.1.1466.115.121.1.15"
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ def fin():
|
|
|
9f2552 |
+ m1.start()
|
|
|
9f2552 |
+ m2.start()
|
|
|
9f2552 |
+ testuser.delete()
|
|
|
9f2552 |
+ m1.schema.del_schema('attributetypes', ensure_bytes(new_at))
|
|
|
9f2552 |
+ repl.wait_for_replication(m1, m2)
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ # on M2 restore a default 99user.ldif
|
|
|
9f2552 |
+ m2.stop()
|
|
|
9f2552 |
+ os.remove(m2.schemadir + "/99user.ldif")
|
|
|
9f2552 |
+ schema_filename = (m2.schemadir + "/99user.ldif")
|
|
|
9f2552 |
+ try:
|
|
|
9f2552 |
+ with open(schema_filename, 'w') as schema_file:
|
|
|
9f2552 |
+ schema_file.write("dn: cn=schema\n")
|
|
|
9f2552 |
+ os.chmod(schema_filename, 0o777)
|
|
|
9f2552 |
+ except OSError as e:
|
|
|
9f2552 |
+ log.fatal("Failed to update schema file: " +
|
|
|
9f2552 |
+ "{} Error: {}".format(schema_filename, str(e)))
|
|
|
9f2552 |
+ m2.start()
|
|
|
9f2552 |
+
|
|
|
9f2552 |
+ request.addfinalizer(fin)
|
|
|
9f2552 |
|
|
|
9f2552 |
if __name__ == '__main__':
|
|
|
9f2552 |
# Run isolated
|
|
|
9f2552 |
diff --git a/ldap/schema/10rfc2307compat.ldif b/ldap/schema/10rfc2307compat.ldif
|
|
|
9f2552 |
index 8ba72e1e3..998b8983b 100644
|
|
|
9f2552 |
--- a/ldap/schema/10rfc2307compat.ldif
|
|
|
9f2552 |
+++ b/ldap/schema/10rfc2307compat.ldif
|
|
|
9f2552 |
@@ -21,9 +21,9 @@ attributeTypes: (
|
|
|
9f2552 |
attributeTypes: (
|
|
|
9f2552 |
1.3.6.1.1.1.1.2 NAME 'gecos'
|
|
|
9f2552 |
DESC 'The GECOS field; the common name'
|
|
|
9f2552 |
- EQUALITY caseIgnoreIA5Match
|
|
|
9f2552 |
- SUBSTR caseIgnoreIA5SubstringsMatch
|
|
|
9f2552 |
- SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
|
|
|
9f2552 |
+ EQUALITY caseIgnoreMatch
|
|
|
9f2552 |
+ SUBSTR caseIgnoreSubstringsMatch
|
|
|
9f2552 |
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
|
|
|
9f2552 |
SINGLE-VALUE
|
|
|
9f2552 |
)
|
|
|
9f2552 |
attributeTypes: (
|
|
|
9f2552 |
--
|
|
|
9f2552 |
2.31.1
|
|
|
9f2552 |
|