OpenDJ : mise en place du suivi des connexions

Par défaut, il n'est pas possible de déterminer la date de dernière connexion réussie sur un annuaire LDAP (last login time). Seules les erreurs de connexion peuvent être détectées dans les politiques de mots de passe.

Parfois cependant, il est intéressant de connaître la date de dernière connexion, afin de pouvoir supprimer - ou bloquer - des comptes inutilisés depuis plusieurs mois.

Certains annuaire permettent de modifier les politiques de mots de passe pour tracer les connexions réussies, mais ceci a un impact sur les authentifications. En effet, à chaque authentification réussie, l'annuaire doit écrire la date de connexion sur l'objet utilisateur. On passe donc d'une suite d'opérations search and bind à une suite search and bind and mod.

Quel est donc l'impact de ce suivi sur les performances d'un annuaire ? C'est l'objet de ce test, réalisé sur un annuaire LDAP Forgerock Opendj (DS 5.5).

Configuration utilisée

La configuration utilisée est la suivante :

  • 2 vCPU Intel(R) Xeon(R) CPU E5-2698 v3 @ 2.30GHz
  • 16 Go de RAM

Le jeu de test est constitué d'un fichier LDIF de 481 Mo, comprenant 220 000 entrées utilisateur.

Parmi ces 220 000 entrées, 50 000 sont situées dans une OU (organizational unit) spécifique : ou=People,ou=FR,o=example.

Politique de mots de passe par défaut

La politique de mot de passe par défaut est utilisée, avec le chargement des entrées.

Property                                  : Value(s)
------------------------------------------:------------------------------------
account-status-notification-handler       : -
allow-expired-password-changes            : false
allow-multiple-password-values            : false
allow-pre-encoded-passwords               : false
allow-user-password-changes               : true
default-password-storage-scheme           : Salted SHA-512
deprecated-password-storage-scheme        : -
expire-passwords-without-warning          : false
force-change-on-add                       : false
force-change-on-reset                     : false
grace-login-count                         : 0
idle-lockout-interval                     : 0 s
java-class                                : org.opends.server.core.PasswordPolicyFactory
last-login-time-attribute                 : -
last-login-time-format                    : -
lockout-duration                          : 0 s
lockout-failure-count                     : 0
lockout-failure-expiration-interval       : 0 s
max-password-age                          : 25 w 5 d
max-password-reset-age                    : 0 s
min-password-age                          : 0 s
password-attribute                        : userPassword
password-change-requires-current-password : false
password-expiration-warning-interval      : 5 d
password-generator                        : Random Password Generator
password-history-count                    : 5
password-history-duration                 : 0 s
password-validator                        : Length-Based Password Validator
previous-last-login-time-format           : -
require-change-by-time                    : -
require-secure-authentication             : false
require-secure-password-changes           : false
skip-validation-for-administrators        : false
state-update-failure-policy               : reactive

Outils de benchmark

Les tests sont lancés avec les utilitaires authrate et searchrate, qui sont intégrés aux binaires de l'annuaire.

Pour la recherche :

/opt/opendj/bin/searchrate -h 10.150.29.161 -p 1389 -D 'uid=user.1,ou=people,ou=fr,o=example' -w password -F -c 10 -b o=example -m 300000 -g 'rand(100,49000)' '(uid=user.%d)'

 

Pour les authentifications, en mode search + bind :

/opt/opendj/bin/authrate -h 10.150.29.161 -p 1389 -D '%2$s' -w password -f -c 10 -b ou=people,ou=fr,o=example -s sub -m 300000 -g 'rand(100,49000)' '(uid=user.%d)'

Procédure de tests

La procédure de tests est la suivante :

  • démarrage de l'annuaire
  • lancement d'un premier test de type searchrate, qui permet de cacher les entrées en RAM
  • lancement d'un test d'authentification avec authrate en mode search + bind

Mesures sans suivi de la date de dernière connexion

Avec le paramétrage par défaut, on obtient un débit moyen de 4283 authentifications par seconde, avec un temps de réponse moyen de 2.131 millisecondes.

------------------------------------------------------------------------------
     Throughput                            Response Time                      
   (ops/second)                           (milliseconds)                      
recent  average  recent  average  99.9%  99.99%  99.999%  err/sec  bind time %
------------------------------------------------------------------------------
3901.6   3907.1   2.573    2.573  25.304  162.729  167.620      0.0         44.4
4186.4   4047.8   2.372    2.469  26.546  166.949  195.819      0.0         46.6
4540.4   4212.9   2.183    2.365  23.388  166.223  195.819      0.0         44.2
4624.0   4315.7   2.147    2.307  22.435  162.729  195.819      0.0         42.6
4609.7   4374.6   2.156    2.275  22.083  160.540  172.100      0.0         43.0
4663.1   4422.7   2.130    2.250  21.634  158.399  172.100      0.0         42.5
4765.9   4471.7   2.088    2.225  21.431  154.617  172.100      0.0         42.8
4764.9   4508.4   2.089    2.207  20.982  141.395  172.100      0.0         42.0
4864.1   4547.9   2.050    2.188  21.024  39.778  169.393      0.0         42.2
4811.6   4574.2   2.077    2.177  20.934  34.832  169.393      0.0         42.0
4777.0   4592.6   2.091    2.169  20.525  32.932  169.393      0.0         41.8
4825.5   4611.9   2.072    2.160  20.090  32.724  169.393      0.0         41.9
4101.4   4572.6   1.898    2.142  19.807  32.213  169.393      0.0         41.7
 530.8   4283.0   0.869    2.131  19.703  32.118  167.620      0.0         41.0

La CPU est utilisée à 90 % environ sur le serveur cible (qui dispose de 2 vCPU).

Mise en place du suivi du last login time

Création d'un attribut spécifique

La mise en place du suivi demande tout d'abord de créer un attribut qui sera utilisé pour stocker la date de dernière connexion. La documentation donne justement un exemple de politique de mots de passe qui met en oeuvre le suivi.

dn: cn=schema
changetype: modify
add: attributeTypes
attributeTypes: ( lastLoginTime-oid
  NAME 'lastLoginTime'
  DESC 'Last time the user logged in'
  EQUALITY generalizedTimeMatch
  ORDERING generalizedTimeOrderingMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
  SINGLE-VALUE
  NO-USER-MODIFICATION
  USAGE directoryOperation
  X-ORIGIN 'OpenDJ example documentation' )

On ajoute l'attribut au schéma via la commande ldapmodify :

ldapmodify \
--hostname localhost \
--port 1389 \
--bindDN "cn=Directory Manager" \
--bindPassword password \
lastLoginTime.ldif

Création d'une politique de mots de passe spécifique

Si on veut cibler certains comptes utilisateurs, on peut créer une politique de mots de passe spécifiquement pour cet usage :

/opt/opendj/bin/dsconfig \
create-password-policy \
--hostname localhost --port 4444 \
--bindDN "cn=Directory Manager" \
--bindPassword password \
--policy-name "Track Last Login Time" \
--type password-policy \
--set default-password-storage-scheme:"Salted SHA-512" \
--set password-attribute:userPassword \
--set last-login-time-attribute:lastLoginTime \
--set last-login-time-format:"yyyyMMddHH'Z'" \
--trustAll \
--no-prompt

Modification de la politique de mots de passe

On peut créer une nouvelle politique de mots de passe, ou modifier la politique existante. Dans ce cas, la commande à utiliser est la suivante :

/opt/opendj/bin/dsconfig set-password-policy-prop \
   --policy-name Default\ Password\ Policy \
   --set last-login-time-attribute:lastLoginTime \
   --set last-login-time-format:"yyyyMMddHH'Z'" \
   --hostname localhost \
   --port 4444 \
   --bindDn cn=Directory\ Manager \
   --bindPassword password \
   --trustAll \
   --no-prompt

Test sur une entrée

Si on fait une requête avec un utilisateur en se connectant, on peut ensuite récupérer la date de dernière connexion sur son entrée, à condition de disposer des droits adéquats.

Par exemple :

ldapsearch  -x -h localhost -p 1389 -D 'cn=Directory Manager' -w password -b o=example '(uid=user.2)' lastLoginTime
dn: uid=user.2,ou=People,ou=FR,o=example
lastLoginTime: 2017121909Z

On constate que la date est bien au format déclaré, c'est à dire comprenant l'année, le mois, le jour et l'heure. En effet, il n'est pas nécessaire de suivre les connexions à la minute près.

Mesures AVEC suivi de la date de dernière connexion

Avec le nouveau paramétrage, incluant la mise à jour de la dernière date de connexion, on obtient un débit maximum de 2860 authentifications par seconde en moyenne, avec un temps de réponse moyen de 3.382 millisecondes.

La charge CPU sur le serveur d'annuaire oscille entre 50 et 95%, avec des I/O wait.

On a bien un impact assez fort, avec notamment des phases pendant laquelle l'annuaire est en I/O wait, révélateur des mises à jour effectuées sur les entrées.

------------------------------------------------------------------------------
     Throughput                            Response Time                      
   (ops/second)                           (milliseconds)                      
recent  average  recent  average  99.9%  99.99%  99.999%  err/sec  bind time %
------------------------------------------------------------------------------
1570.3   1573.1   6.421    6.421  152.833  177.026  177.026      0.0         63.6
2308.4   1942.2   4.325    5.170  53.701  176.974  177.026      0.0         57.0
2479.4   2122.0   4.023    4.722  49.889  165.267  177.026      0.0         53.3
1025.2   1847.4   3.712    4.581  48.670  165.267  177.026      0.0         51.6
   0.0   1477.0       -    4.581  48.670  165.267  177.026      0.0          NaN
1013.4   1399.8  25.871    7.149  50.589  11195.648  11204.023      0.0         93.5
2996.8   1627.5   3.332    6.147  46.142  11193.992  11204.023      0.0         49.8
3301.1   1836.1   3.028    5.447  44.262  11187.622  11204.023      0.0         48.4
3329.9   2001.8   2.737    4.948  41.735  11165.580  11204.023      0.0         47.0
   0.0   1800.9       -    4.948  41.735  11165.580  11204.023      0.0          NaN
  92.4   1645.4  226.166    6.078  43.042  11156.315  11204.023      0.0         99.2
4024.9   1843.1   2.485    5.426  39.488  10339.090  11203.705      0.0         45.4
4193.7   2023.6   2.382    4.942  38.478  10328.566  11203.705      0.0         44.3
4487.2   2199.3   2.227    4.547  36.814  10316.059  11203.705      0.0         43.1
4496.0   2352.3   2.222    4.251  35.540  10313.618  11203.705      0.0         43.3
4530.5   2488.3   2.207    4.018  34.530  10213.330  11203.705      0.0         43.0
4535.5   2608.8   2.204    3.833  33.649  168.792  11202.112      0.0         43.3
4479.8   2712.7   2.230    3.686  33.112  163.941  11202.112      0.0         42.7
4722.0   2818.5   2.116    3.547  32.285  160.038  11202.112      0.0         42.6
4710.9   2913.1   2.108    3.431  31.666  79.285  11202.112      0.0         42.5
1816.5   2860.5   1.834    3.382  31.418  75.221  11195.866      0.0         42.9

Note : ceci est cependant à modérer, puisque notre première campagne de tir va déclencher une écriture pour chaque utilisateur qui s'authentifie. Si on relance un deuxième tir dans l'heure (qui est l'unité minimale de suivi de la date de connexion), on retrouve des résultats quasiment identiques au premier cas : un débit de 4291 authentifications par seconde, et un temps de réponse de 2.195 ms. Si on regarde la charge sur le serveur d'annuaire, on ne constate plus d'écritures sur disque.

------------------------------------------------------------------------------
     Throughput                            Response Time                      
   (ops/second)                           (milliseconds)                      
recent  average  recent  average  99.9%  99.99%  99.999%  err/sec  bind time %
------------------------------------------------------------------------------
3988.3   3994.8   2.514    2.514  23.066  163.522  167.640      0.0         42.6
.../...
4628.0   4525.7   2.159    2.206  18.978  28.433  158.819      0.0         42.9
4327.2   4510.4   2.219    2.207  19.051  28.221  158.819      0.0         43.0
1450.9   4291.0   1.721    2.195  18.968  28.071  158.406      0.0         42.1

Conclusion

Si l'impact du suivi de la date de dernière connexion n'est pas anodin, surtout dans le cas d'un test, en situation réelle, l'impact peut être relativement négligeable, notamment si les authentifications se font au fil de l'eau.

Catégorie