Greetings.
How should I use the 'unique' overlay to enforce uniqueness of an attribute across two trees?
I'd have thought that the following would work, to enforce uniqueness across ou=dept1 and ou=dept2, but it doesn't seem to.
dn: olcOverlay=unique,olcDatabase={1}mdb,cn=config objectClass: olcOverlayConfig objectClass: olcUniqueConfig olcOverlay: unique olcUniqueURI: ldap:///ou=dept1,o=example?uidnumber?sub ldap:///ou=dept2,o=example?uidnumber?sub
(and cf, slapd/overlays/unique.c:unique_new_domain).
When I configure a server with this, and load two entities with the same uidNumber, the server doesn't object. I'm clearly misunderstanding something.
The slapo-unique(5) manpage suggests that having two URIs juxtaposed like this is syntactically OK, but it doesn't make clear the semantics of this. I'd guessed that the above configuration would create a 'domain' which is the union of the two subtrees, but that doesn't seem to be the case.
Another thing that such a line could potentially specify is that a tuple of attributes is unique. For example that 'olcUniqueUri: ldap:///?sn?sub ldap:///?cn?sub' specifies that (sn,cn) is unique. There's nothing in the slapo-unique manpage that would back up this interpretation, though.
Or is the above configuration in fact equivalent to
olcUniqueURI: ldap:///ou=dept1,o=example?uidnumber?sub olcUniqueURI: ldap:///ou=dept2,o=example?uidnumber?sub
which would enforce uniqueness of uidnumber on trees ou=dept1 and ou=dept2 separately. I take it that this isn't so, because the manpage talks of multiple 'domains', each of which can have multiple URIs.
In the example below, if I instead add user uid=u2,ou=dept1,o=example, then a duplicated uidNumber is indeed rejected in the ldapadd step (so the overlay is active).
I see an older thread [1] on this topic, but that refers only to a single URI in the olcUniqueURI attribute. That was resolved by adding an index on the relevant attribute, but that index is included in the configuration below.
(The goal here is to enforce uniqueness of uidNumber attributes in (dept1 union dept2) and (dept1 union dept3), but permit duplication in dept2 and dept3.)
Thanks for any illumination,
Norman
[1] https://www.openldap.org/lists/openldap-technical/201808/msg00016.html
Witness:
% cat uniqueness-test-config.ldif dn: cn=config objectclass: olcGlobal cn: config olcPidFile: /tmp/uniquenesstest/slapd.pid
dn: cn=module,cn=config objectClass: olcModuleList cn: module olcModuleload: back_mdb.la olcModuleload: unique
dn: cn=schema,cn=config objectClass: olcSchemaConfig cn: schema
include: file:///etc/openldap/schema/core.ldif include: file:///etc/openldap/schema/cosine.ldif include: file:///etc/openldap/schema/nis.ldif
dn: olcDatabase={1}mdb,cn=config objectClass: olcDatabaseConfig objectClass: olcMdbConfig olcDatabase: mdb olcSuffix: o=example olcRootDN: cn=admin,o=example olcRootPW: dummypass olcDbIndex: default eq olcDbIndex: objectclass olcDbIndex: uidNumber eq olcDbDirectory: /tmp/uniquenesstest/data
dn: olcOverlay=unique,olcDatabase={1}mdb,cn=config objectClass: olcOverlayConfig objectClass: olcUniqueConfig olcOverlay: unique olcUniqueURI: ldap:///ou=dept1,o=example?uidNumber?sub ldap:///ou=dept2,o=example?uidNumber?sub
% cat uniqueness-test-data.ldif dn: o=example objectClass: organization o: example
dn: ou=dept1,o=example objectclass: organizationalunit ou: dept1
dn: uid=u1,ou=dept1,o=example objectclass: person objectclass: posixAccount sn: Two cn: User One uid: u1 uidNumber: 1000 gidNumber: 1000 homeDirectory: /home/u1
dn: ou=dept2,o=example objectclass: organizationalunit ou: dept2
dn: uid=u2,ou=dept2,o=example objectclass: person objectclass: posixAccount sn: Two cn: User Two uid: u2 uidNumber: 1000 gidNumber: 1000 homeDirectory: /home/u2
% slapadd -v -F /tmp/uniquenesstest/slapd.d -n0 -l uniqueness-test-config.ldif added: "cn=config" (00000001) added: "cn=module{0},cn=config" (00000001) added: "cn=schema,cn=config" (00000001) added: "cn={0}core,cn=schema,cn=config" (00000001) added: "cn={1}cosine,cn=schema,cn=config" (00000001) added: "cn={2}nis,cn=schema,cn=config" (00000001) added: "olcDatabase={1}mdb,cn=config" (00000001) added: "olcOverlay={0}unique,olcDatabase={1}mdb,cn=config" (00000001) Closing DB...
% slapd -F /tmp/uniquenesstest/slapd.d
% ldapadd -x -H ldap:/// -D cn=admin,o=example -w dummypass -f uniqueness-test-data.ldif adding new entry "o=example"
adding new entry "ou=dept1,o=example"
adding new entry "uid=u1,ou=dept1,o=example"
adding new entry "ou=dept2,o=example"
adding new entry "uid=u2,ou=dept2,o=example"
% ldapsearch -LLL -H ldap:/// -b o=example '(objectclass=person)' uidnumber dn: uid=u1,ou=dept1,o=example uidNumber: 1000
dn: uid=u2,ou=dept2,o=example uidNumber: 1000
% slapd -VVV @(#) $OpenLDAP: slapd 2.6.7 (Jan 1 1980 00:00:00) $ openldap
Included static overlays: accesslog syncprov unique Included static backends: config ldif monitor mdb relay
--On Tuesday, February 6, 2024 12:29 PM +0000 Norman Gray gray@nxg.name wrote:
Greetings.
How should I use the 'unique' overlay to enforce uniqueness of an attribute across two trees?
I'd have thought that the following would work, to enforce uniqueness across ou=dept1 and ou=dept2, but it doesn't seem to.
Questions about slapo-unique aside, this is a horrific way to organize your data tree. I'd strongly advise creating a tree for people, like:
cn=people,dc=example,dc=com
uid=x,cn=people,dc=example,dc=com uid=y,cn=people,dc=example,dc=com
Store what department(s) they belong to as attribute in their user entry.
--Quanah
Quanah, hello.
On 6 Feb 2024, at 16:03, Quanah Gibson-Mount wrote:
Questions about slapo-unique aside, this is a horrific way to organize your data tree. I'd strongly advise creating a tree for people, like:
cn=people,dc=example,dc=com
uid=x,cn=people,dc=example,dc=com uid=y,cn=people,dc=example,dc=com
Store what department(s) they belong to as attribute in their user entry.
I take the point, and I certainly wouldn't organise things this way if _I_ were king.
In this case, though, dept1, dept2, and so on, are separate administrative domains, in both IT terms and real bureaucratic ones, and this is an attempt to bring some sort of coherence to a bit of historic anarchy (and yes, there is an ou=staff layer in the middle of the real trees).
Everyone more-or-less agrees on the names and uidNumbers in dept1, but there might be a local 'norman' in both dept2 and dept3, or people in those trees with historically colliding UIDs. The result is that systems in dept2 will acknowledge users in ou=dept1 and ou=dept2, users in dept3 acknowledge ou=dept1 and dept3 but ignore ou=dept2, and so on. I expect that names will soon no longer be created in the deptN trees (pretty please?), in favour of the dept1 tree, and the ou=staff parts of those will atrophy, but I'll be retired by then.
If there's a different way of approaching that particular problem, though, right now is the time for me to be rethinking this, so I'm open to challenge.
Best wishes,
Norman
--On Tuesday, February 6, 2024 4:27 PM +0000 Norman Gray gray@nxg.name wrote:
Store what department(s) they belong to as attribute in their user entry.
I take the point, and I certainly wouldn't organise things this way if _I_ were king.
In this case, though, dept1, dept2, and so on, are separate administrative domains, in both IT terms and real bureaucratic ones, and this is an attempt to bring some sort of coherence to a bit of historic anarchy (and yes, there is an ou=staff layer in the middle of the real trees).
Everyone more-or-less agrees on the names and uidNumbers in dept1, but there might be a local 'norman' in both dept2 and dept3, or people in those trees with historically colliding UIDs. The result is that systems in dept2 will acknowledge users in ou=dept1 and ou=dept2, users in dept3 acknowledge ou=dept1 and dept3 but ignore ou=dept2, and so on. I expect that names will soon no longer be created in the deptN trees (pretty please?), in favour of the dept1 tree, and the ou=staff parts of those will atrophy, but I'll be retired by then.
If there's a different way of approaching that particular problem, though, right now is the time for me to be rethinking this, so I'm open to challenge.
Ah, ok I thought you were setting up a new server. Since it was historically done this way, yeah, best thing is to slowly fix the data until it can be done correctly. Sounds like it would take an institutional commitment to resolving the collisions to ever fix this fully.
--Quanah
Quanah, hello.
On 7 Feb 2024, at 19:26, Quanah Gibson-Mount wrote:
Since it was historically done this way, yeah, best thing is to slowly fix the data until it can be done correctly.
It's really a local case of NIS. Must. Die....
Norman
On Tue, Feb 06, 2024 at 12:29:37PM +0000, Norman Gray wrote:
Greetings.
How should I use the 'unique' overlay to enforce uniqueness of an attribute across two trees?
I'd have thought that the following would work, to enforce uniqueness across ou=dept1 and ou=dept2, but it doesn't seem to.
dn: olcOverlay=unique,olcDatabase={1}mdb,cn=config objectClass: olcOverlayConfig objectClass: olcUniqueConfig olcOverlay: unique olcUniqueURI: ldap:///ou=dept1,o=example?uidnumber?sub ldap:///ou=dept2,o=example?uidnumber?sub
(and cf, slapd/overlays/unique.c:unique_new_domain).
When I configure a server with this, and load two entities with the same uidNumber, the server doesn't object. I'm clearly misunderstanding something.
The slapo-unique(5) manpage suggests that having two URIs juxtaposed like this is syntactically OK, but it doesn't make clear the semantics of this. I'd guessed that the above configuration would create a 'domain' which is the union of the two subtrees, but that doesn't seem to be the case.
Hi Norman, you're right, the uniqueness domains aren't specified anywhere and the overlay currently just runs through each URI independently. It also checks that the entry matches the URI as well, so a DN like "uid=u2,ou=dept1,o=example" is only checked against the first URI and dept2 wouldn't be checked.
The next best thing I can see is if you create two URIs, one for each dept2 and dept3 more or less like this:
ldap:///?uidnumber?sub?(|\ (entryDN:dnSubtreeMatch:=ou=dept1,o=example) (entryDN:dnSubtreeMatch:=ou=dept2,o=example)) ldap:///?uidnumber?sub?(|\ (entryDN:dnSubtreeMatch:=ou=dept1,o=example) (entryDN:dnSubtreeMatch:=ou=dept3,o=example))
That should trigger exactly as you need and cover the relevant parts of the tree. Not sure it works when there's a lot of gluing going on but worth a try.
Regards,
openldap-technical@openldap.org