I have encountered an effect that I believe is a bug, but I might be wrong. It would be nice if someone could confirm that my acls should be working, or in case they should not, give me a hint what I am doing wrong.
Here is what I am trying to archive: * there is one ldap provider (master) server that contains all attributes that are relevant for my organisation * on the master there is a user allowing a highly secured consumer(slave) ldap server the replication of all attributes from the master * on the master there is a user allowing a low-security consumer(slave) ldap server the replication of all attributes from the master except some critical ones * on the master there is a user (cn=provisioninguser) that can read the accesslog. it is used by scripts to e.g. notify non-ldap systems of password changes.
I would like to put the acls for the replication users (high and low security ldap slaves) on the databases and not the frontend to avoid accidental modifications. All other acls should be on the frontend.
If I configure all my acls on the frontend only everything works as I think it should. If some acls are on the database the results are rather weird ( the cn=provisioninguser can see only one value of the multi-valued reqMod attribte)
The following acl snippet only deals with accesslog access which is where I encounter the problem:
dn: olcDatabase={2}hdb,cn=config olcAccess: {0}to dn.subtree="cn=accesslog" attrs=reqMod val.regex="^topSecretAttribute:.*" by dn.base="cn=replicationuser,dc=organisation,dc=com" read by dn.base="cn=replication_low_security,dc=organisation,dc=com" none by * break
dn: olcDatabase={2}hdb,cn=config olcAccess: {1}to dn.subtree="cn=accesslog" by dn.base="cn=replicationuser,dc=organisation,dc=com" read by dn.base="cn=replication_low_security,dc=organisation,dc=com" read by * break
dn: olcDatabase={-1}frontend,cn=config olcAccess: {0}to dn.subtree="cn=accesslog" by dn.base="cn=provisioninguser,dc=organisation,dc=com" read by * none
*if the acls 1,2 and 3 are on "olcDatabase={-1}frontend,cn=config" (which they are not in the example above) cn=provisioninguser,dc=organisation,dc=com can read all values from the multi-valued attribute reqMod (which is what I want).
ldapsearch -D cn=provisioninguser,dc=organisation,dc=com -w 123 -b cn=accesslog reqDN=cn=user1,dc=organisation,dc=com reqMod
dn: reqStart=20131227145130.000001Z,cn=accesslog reqMod: userPassword:= {SSHA}bmyaw8Xy1UftlTorPDQE9yLzruoxDnGq reqMod: topSecretAttribute:= topsecret reqMod: pwdChangedTime:= 20131227145130Z reqMod: entryCSN:= 20131227145130.917649Z#000000#000#000000 reqMod: modifiersName:= cn=admin reqMod: modifyTimestamp:= 20131227145130Z
*if the acls 1 and 2 are on "olcDatabase={2}hdb,cn=config" and the 3rd one is on "olcDatabase={-1}frontend,cn=config" cn=provisioninguser,dc=organisation,dc=com can read only one value from the multi-valued attribute reqMod (why?).
ldapsearch -D cn=provisioninguser,dc=organisation,dc=com -w 123 -b cn=accesslog reqDN=cn=user1,dc=organisation,dc=com reqMod
dn: reqStart=20131227145130.000001Z,cn=accesslog reqMod: userPassword:= {SSHA}bmyaw8Xy1UftlTorPDQE9yLzruoxDnGq
Best regards,
Marvin Mundry University of Hamburg Regional Computer Center (RRZ) Division Zentrale Dienste Schlueterstrasse 70 20146 Hamburg +49 (0)40 42838-9109
Am Fri, 27 Dec 2013 18:12:20 +0000 schrieb "Mundry, Marvin" Marvin.Mundry@uni-hamburg.de:
I have encountered an effect that I believe is a bug, but I might be wrong. It would be nice if someone could confirm that my acls should be working, or in case they should not, give me a hint what I am doing wrong.
Here is what I am trying to archive:
- there is one ldap provider (master) server that contains all
attributes that are relevant for my organisation
- on the master there is a user allowing a highly secured
consumer(slave) ldap server the replication of all attributes from the master
- on the master there is a user allowing a low-security
consumer(slave) ldap server the replication of all attributes from the master except some critical ones
- on the master there is a user (cn=provisioninguser) that can read
the accesslog. it is used by scripts to e.g. notify non-ldap systems of password changes.
I would like to put the acls for the replication users (high and low security ldap slaves) on the databases and not the frontend to avoid accidental modifications. All other acls should be on the frontend.
If I configure all my acls on the frontend only everything works as I think it should. If some acls are on the database the results are rather weird ( the cn=provisioninguser can see only one value of the multi-valued reqMod attribte)
The following acl snippet only deals with accesslog access which is where I encounter the problem:
dn: olcDatabase={2}hdb,cn=config olcAccess: {0}to dn.subtree="cn=accesslog" attrs=reqMod val.regex="^topSecretAttribute:.*" by dn.base="cn=replicationuser,dc=organisation,dc=com" read by dn.base="cn=replication_low_security,dc=organisation,dc=com" none by * break
the break rule will be ignored, as 'none' is the implicit last rule.
[...]
run slapd with -dacl
-Dieter
On 2013-12-28 09:36, Dieter Klünter wrote:
[...] by dn.base="cn=replication_low_security,dc=organisation,dc=com" none by * break
the break rule will be ignored, as 'none' is the implicit last rule.
No, "none" does not imply "this is the last rule". OTOH there is an implicit last "by * none", hidden by the "by * break".
[...]
run slapd with -dacl
Indeed.
by dn.base="cn=replication_low_security,dc=organisation,dc=com" none by * break
the break rule will be ignored, as 'none' is the implicit last rule.
No, "none" does not imply "this is the last rule". OTOH there is an implicit last "by * none", hidden by the "by * break".
to me it seems that if a "by * break" appears * in the database acls, in my case slapd does not continue looking for global access directives in the frontend. * in the frontend acls, slapd continues evaluating statements from the global access directives
http://www.openldap.org/doc/admin24/access-control.html states "For each entry, access controls provided in the database which holds the entry [...] apply first, followed by the global access directives"
so my understanding is that what I am observing should not happen
run slapd with -dacl
the interesting line here should be "52c12415 => slap_access_allowed: no more rules" (although there are more in the frontend)
dn: ACCESSLOG_DB olcAccess: {0}to dn.subtree="cn=accesslog" attrs=reqMod val.regex="^topSecretAttribute:.*" by dn.base="cn=replicationuser,dc=organisation,dc=com" read by dn.base="cn=replication_low_security,dc=organisation,dc=com" none by * break
dn: ACCESSLOG_DB olcAccess: {1}to dn.subtree="cn=accesslog" by dn.base="cn=replicationuser,dc=organisation,dc=com" read by dn.base="cn=replication_low_security,dc=organisation,dc=com" read by * break
dn: FRONTEND olcAccess: {0}to dn.subtree="cn=accesslog" by dn.base="cn=provisioninguser,dc=organisation,dc=com" read by * none
52c12415 => access_allowed: read access to "reqStart=20131227145130.000001Z,cn=accesslog" "reqMod" requested 52c12415 => dn: [1] cn=accesslog 52c12415 => acl_get: [1] matched 52c12415 acl_get: valpat ^topSecretAttribute:.* 52c12415 => dn: [2] cn=accesslog 52c12415 => acl_get: [2] matched 52c12415 => acl_get: [2] attr reqMod 52c12415 => acl_mask: access to entry "reqStart=20131227145130.000001Z,cn=accesslog", attr "reqMod" requested 52c12415 => acl_mask: to value by "cn=provisioninguser,dc=organisation,dc=com", (=0) 52c12415 <= check a_dn_pat: cn=replicationuser,dc=organisation,dc=com 52c12415 <= check a_dn_pat: cn=replication_public_user,dc=organisation,dc=com 52c12415 <= check a_dn_pat: * 52c12415 <= acl_mask: [3] applying +0 (break) 52c12415 <= acl_mask: [3] mask: =0 52c12415 <= acl_get: done. 52c12415 => slap_access_allowed: no more rules 52c12415 => access_allowed: no more rules 52c12415 send_search_entry: conn 1002 access to attribute reqMod, value #6 not allowed
############################################################################### dn: FRONTEND olcAccess: {0}to dn.subtree="cn=accesslog" attrs=reqMod val.regex="^topSecretAttribute:.*" by dn.base="cn=replicationuser,dc=organisation,dc=com" read by dn.base="cn=replication_low_security,dc=organisation,dc=com" none by * break
dn: FRONTEND olcAccess: {1}to dn.subtree="cn=accesslog" by dn.base="cn=replicationuser,dc=organisation,dc=com" read by dn.base="cn=replication_low_security,dc=organisation,dc=com" read by * break
dn: FRONTEND olcAccess: {0}to dn.subtree="cn=accesslog" by dn.base="cn=provisioninguser,dc=organisation,dc=com" read by * none
52c12bbf => access_allowed: read access to "reqStart=20131227145130.000001Z,cn=accesslog" "reqMod" requested 52c12bbf => dn: [24] cn=accesslog 52c12bbf => acl_get: [24] matched 52c12bbf acl_get: valpat ^topSecretAttribute:.* 52c12bbf => dn: [25] cn=accesslog 52c12bbf => acl_get: [25] matched 52c12bbf => acl_get: [25] attr reqMod 52c12bbf => acl_mask: access to entry "reqStart=20131227145130.000001Z,cn=accesslog", attr "reqMod" requested 52c12bbf => acl_mask: to value by "cn=provisioninguser,dc=organisation,dc=com", (=0) 52c12bbf <= check a_dn_pat: cn=replicationuser,dc=organisation,dc=com 52c12bbf <= check a_dn_pat: cn=replication_public_user,dc=organisation,dc=com 52c12bbf <= check a_dn_pat: * 52c12bbf <= acl_mask: [3] applying +0 (break) 52c12bbf <= acl_mask: [3] mask: =0 52c12bbf => dn: [26] cn=accesslog 52c12bbf => acl_get: [26] matched 52c12bbf => acl_get: [26] attr reqMod 52c12bbf => acl_mask: access to entry "reqStart=20131227145130.000001Z,cn=accesslog", attr "reqMod" requested 52c12bbf => acl_mask: to value by "cn=provisioninguser,dc=organisation,dc=com", (=0) 52c12bbf <= check a_dn_pat: cn=provisioninguser,dc=organisation,dc=com 52c12bbf <= acl_mask: [1] applying read(=rscxd) (stop) 52c12bbf <= acl_mask: [1] mask: read(=rscxd) 52c12bbf => slap_access_allowed: read access granted by read(=rscxd) 52c12bbf => access_allowed: read access granted by read(=rscxd)
openldap-technical@openldap.org