Password reset en OpenDJ (ACI Permissions y ds-privilege-name)

Para delegar la posibilidad de realizar cambios de password en un usuario estándar de OpenDJ Directory Services Project (antiguo Sun OpenDS) es necesario establecer ciertos privilegios y ACIs (Access control instructions) al usuario.

En primera instancia, lo normal es pensar que asignar privilegios sería suficiente, vamos a ver el caso. Tenemos un usuario estándar sin privilegios llamado user.1:

# ./ldapsearch -D "cn=directory manager" -w password -b "dc=example,dc=com" "(uid=user.1)" '+'

dn: uid=user.1,ou=People,dc=example,dc=com
numSubordinates: 0
structuralObjectClass: inetOrgPerson
pwdPolicySubentry: cn=Default Password Policy,cn=Password Policies,cn=config
subschemaSubentry: cn=schema
hasSubordinates: false
entryDN: uid=user.1,ou=people,dc=example,dc=com
entryUUID: 4e9b7847-edcb-3791-b11b-7505f4a55af4

Si quisiéramos con este usuario, cambiar la clave a otro usuario, lógicamente recibiríamos el error de que no tenemos suficientes privilegios para realizar la operación. Usando este usuario sin privilegios como Bind DN intentamos cambiar la clave de otro usuario (user.2):

# ./ldappasswordmodify -D "uid=user.1,ou=People,dc=example,dc=com" \
-w user.1 -a "uid=user.2,ou=People,dc=example,dc=com" -n user.2

The LDAP password modify operation failed with result code 50
Error Message: You do not have sufficient privileges to perform password
reset operations

Lógicamente no tenemos privilegios, en el log vemos algo más de información:

[25/Dec/2012:21:58:26 +0100] CONNECT conn=4 from=127.0.0.1:54354 to=127.0.0.1:389 protocol=LDAP
[25/Dec/2012:21:58:26 +0100] BIND REQ conn=4 op=0 msgID=1 type=SIMPLE dn="uid=user.1,ou=People,dc=example,dc=com"
[25/Dec/2012:21:58:26 +0100] BIND RES conn=4 op=0 msgID=1 result=0 authDN="uid=user.1,ou=People,dc=example,dc=com" etime=14
[25/Dec/2012:21:58:26 +0100] EXTENDED REQ conn=4 op=1 msgID=2 name="Password Modify" oid="1.3.6.1.4.1.4203.1.11.1"
[25/Dec/2012:21:58:26 +0100] EXTENDED RES conn=4 op=1 msgID=2 result=50 message=
"You do not have sufficient privileges to perform password reset operations" etime=19
[25/Dec/2012:21:58:26 +0100] UNBIND REQ conn=4 op=2 msgID=3
[25/Dec/2012:21:58:26 +0100] DISCONNECT conn=4 reason="Client Unbind"

Vamos entonces a asignarle privilegios de lectura de configuración y cambio de password. Para ello creamos un ldif en el que añadamos a user.1 los privilegios (ds-privilege-name) de lectura de configuración (config-read) y cambio de passwords (password-reset)

# cat privilegios.ldif 
dn: uid=user.1,ou=People,dc=example,dc=com
changetype: modify
add: ds-privilege-name
ds-privilege-name: config-read
ds-privilege-name: password-reset

# ./ldapmodify -D "cn=directory manager" -w password --filename privilegios.ldif 
Processing MODIFY request for uid=user.1,ou=People,dc=example,dc=com
MODIFY operation successful for DN uid=user.1,ou=People,dc=example,dc=com

Consultamos de nuevo el usuario y vemos que efectivamente tiene los permisos asignados:

# ./ldapsearch -D "cn=directory manager" -w password -b "dc=example,dc=com" "(uid=user.1)" '+'
dn: uid=user.1,ou=People,dc=example,dc=com
numSubordinates: 0
structuralObjectClass: inetOrgPerson
ds-privilege-name: config-read
ds-privilege-name: password-reset
pwdPolicySubentry: cn=Default Password Policy,cn=Password Policies,cn=config
subschemaSubentry: cn=schema
hasSubordinates: false
entryDN: uid=user.1,ou=people,dc=example,dc=com
entryUUID: 4e9b7847-edcb-3791-b11b-7505f4a55af4
pwdChangedTime: 20121225205717.192Z
modifyTimestamp: 20121225210153Z
modifiersName: cn=Directory Manager,cn=Root DNs,cn=config

Vamos entonces a volver a intentar cambiar la clave de otro usuario (user.2):

# ./ldappasswordmodify -D "uid=user.1,ou=People,dc=example,dc=com" \
-w user.1 -a "uid=user.2,ou=People,dc=example,dc=com" -n user.2

The LDAP password modify operation failed with result code 50
Error Message:  The entry uid=user.2,ou=People,dc=example,dc=com cannot be
modified due to insufficient access rights

Todavía no funciona porque pese a tener asignados estos permisos. OpenDJ protege este tipo de privilegios anteponiéndoles ACIs (Access control instructions), de modo que si queremos que el usuario pueda cambiar passwords de otros usuarios, también habrá que permitirle ciertas ACI para evitar que se antepongan a los privilegios. En definitiva, los privilegios son complementarios a las ACI.

En estos casos lo óptimo es, por ejemplo, usar un grupo de administración e ir asignando las ACi en lugar de hacerlo de forma individual, pero para este ejemplo las asignamos directamente al usuario. Tenéis toda la documentación de las ACI en la guía de administración de OpenDJ.

Asigno los ACI Permissions de lectura y escritura al user.1:

# ./dsconfig -h localhost -D "cn=Directory Manager" \
-w password -X -n set-access-control-handler-prop \
--add global-aci:"(target=\"ldap:///dc=example,dc=com\") \
(targetattr = \"*\")(version 3.0; acl \"allow read/write user.1\"; \
allow(read,write) userdn = \"ldap:///uid=user.1,ou=People,dc=example,dc=com\";)"

Y ahora sí que puedo realizar los cambios de password a otros usuarios:

# ./ldappasswordmodify -D "uid=user.1,ou=People,dc=example,dc=com" \
-w user.1 -a "uid=user.2,ou=People,dc=example,dc=com" -n user.2

The LDAP password modify operation was successful

Os recomiendo revisar bien el enlace de la guía de administración que he publicado en el anterior párrafo para ampliar toda esta información.