J’ai fais quelques scripts python pour manipuler un utilisateur sur Active Directory.
Pour voir votre arbre LDAP sur un AD 2012 vous pouvez utiliser l’outil ldp.exe. La documentation de Microsoft est disponible ici. Celui-ci vous permet de connaitre précisément la hiérarchie de votre arbre LDAP sur l’AD afin de renseigner les informations nécessaires au bon fonctionnement des scripts.
Attention ! Pour utiliser les scripts d’insertion et modification d’un utilisateur, il faut avoir activé le SSL sur le serveur AD. La connexion s’effectue alors en LDAPS sur le port 636. Pour ce faire , vous devez installer le rôle « Services de certificats Active Directory » sur le serveur.
Tester la connexion d’un utilisateur
Le premier script permet de tester un utilisateur. Les variables à saisir sont :
- LDAP_ADDR : adresse du serveur AD. De la forme ldap://monserveur.domaine:port
- LDAP_BASE : le base DN du ldap.
- LDAP_BIND : l’utilisateur pour lequel on va tester la connexion
- user_pwd : le mot de passe
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
#!/usr/bin/env python import ldap import sys LDAP_ADDR = 'ldaps://testad.mon.domaine.fr:636' LDAP_BASE = 'DC=mon,DC=domaine,DC=fr' LDAP_BIND = 'CN=nico,OU=test,DC=mon,DC=domaine,DC=fr' user_pwd = 'p@ssw0rd2' # Open the LDAP connection print "initializing .." try: # enable tls connexion ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER) l = ldap.initialize(LDAP_ADDR) except ldap.LDAPError, e: print e sys.exit(1) # Set protocol version to LDAPv3 l.protocol_version = ldap.VERSION3 # Bind to AD print "binding .." try: l.bind_s(LDAP_BIND, user_pwd) except ldap.LDAPError, e: print e sys.exit(1) else: print 'Sucessfully bound to AD' # close connexion l.unbind() |
Insérer un utilisateur
Les variables sont les mêmes que précédemment. Cette fois le bind se fait avec un utilisateur administrateur. A noter que l’utilisateur est ici juste enregistré sur l’AD mais non activé. L’activation ne peut se faire à la création.
- LDAP_BIND_ADMIN : utilisateur avec droit d’admin
- user_dn : le DN du future utilisateur
- ad_user : tableau associatif des attributs du nouvel utilisateur.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
import ldap import ldap.modlist as modlist import sys from time import sleep admin_pwd = 'secure_admin_password' LDAP_ADDR = 'ldaps://testad.mon.domaine.fr:636' LDAP_BASE = 'DC=mon,DC=domaine,DC=fr' LDAP_BIND_ADMIN = 'CN=administrateur,CN=Users,DC=testad,DC=mon,DC=domaine,DC=fr' # dn of the new user user_dn = 'CN=test1,OU=test,DC=testad,DC=mon,DC=domaine,DC=fr' # dict for all attributes of the user ad_user = { 'objectClass': ['top', 'person', 'organizationalPerson', 'user'], 'cn': 'test1', 'givenName': 'First_name ', 'displayName': 'test1', 'sAMAccountName': 'test1', 'sn': 'middle name i guest', 'userAccountControl': '514', # 514 will set user account to disabled, 512 is enable but can't create directly 'userPrincipalName': 'test1@mon.domaine.fr', 'mail': 'test1@mon.domaine.fr', 'userPassword': 'passsword', 'description': 'test' } # Open the LDAP connection print "initializing .." try: ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER) l = ldap.initialize(LDAP_ADDR) except ldap.LDAPError, e: print e sys.exit(1) # Set protocol version to LDAPv3 l.protocol_version = ldap.VERSION3 # Bind to AD with admin account print "binding .." try: l.bind_s(LDAP_BIND_ADMIN, admin_pwd) except ldap.LDAPError, e: print e sys.exit(1) else: print 'Sucessfully bound to AD' # create ldif from attributes ldif = modlist.addModlist(ad_user) # insert user try: l.add_s(user_dn, ldif) print "Insert new user" except ldap.LDAPError, e: sys.stderr.write('Error while insert new user \n') sys.stderr.write('Message: ' + str(e) + '\n') sys.exit(1) # close connexion l.unbind() |
Activer un utilisateur
Comme je l’ai dis plus haut, un utilisateur ne peut être activé à la création. Voici donc le script pour le faire juste après.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
import ldap import ldap.modlist as modlist import sys admin_pwd = 'secure' LDAP_ADDR = 'ldaps://testad.mon.domaine.fr:636' LDAP_BASE = 'DC=mon,DC=domaine,DC=fr' LDAP_BIND_ADMIN = 'CN=administrateur,CN=Users,DC=testad,DC=mon,DC=domaine,DC=fr' # dn of the user to activate user_dn = 'CN=test1,OU=test,DC=testad,DC=mon,DC=domaine,DC=fr' # Open the LDAP connection print "initializing .." try: ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER) l = ldap.initialize(LDAP_ADDR) except ldap.LDAPError, e: print e sys.exit(1) # Set protocol version to LDAPv3 l.protocol_version = ldap.VERSION3 # Bind to AD print "binding .." try: l.bind_s(LDAP_BIND_ADMIN, admin_pwd) except ldap.LDAPError, e: print e sys.exit(1) else: print 'Sucessfully bound to AD' # enable account after creation ATTR = "userAccountControl" ATT_VALUE = "512" userAccountControl = [(ldap.MOD_REPLACE, ATTR, [ATT_VALUE])] try: l.modify_s(user_dn, userAccountControl) print "Account enabled" except ldap.LDAPError, e: sys.stderr.write('Error while enabling the user account \n') sys.stderr.write('Message: ' + str(e) + '\n') # close connexion l.unbind() |
Modifier un mot de passe
La modification de mot de passe ne peut s’opérer que sur une couche TLS. Ici le script utilise le ldaps avec le port 636. Il est possible de conserver le port standard 389 en forçant le TLS.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
#!/usr/bin/env python import ldap import sys admin_pwd = 'secure' LDAP_ADDR = 'ldaps://testad.mon.domaine.fr:636' LDAP_BASE = 'DC=mon,DC=domaine,DC=fr' LDAP_BIND_ADMIN = 'CN=administrateur,CN=Users,DC=testad,DC=mon,DC=domaine,DC=fr' # dn of the user to change password user_dn = 'CN=test1,OU=test,DC=testad,DC=mon,DC=domaine,DC=fr' # the new password newpassword = "p@ssw0rd3" # Open the LDAP connection print "initializing .." try: ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER) l = ldap.initialize(LDAP_ADDR) except ldap.LDAPError, e: print e sys.exit(1) # Set protocol version to LDAPv3 l.protocol_version = ldap.VERSION3 # Bind to AD print "binding .." try: l.bind_s(LDAP_BIND_ADMIN, admin_pwd) except ldap.LDAPError, e: print e sys.exit(1) else: print 'Sucessfully bound to AD' # Set AD PASSWORD_ATTR = "unicodePwd" unicode_pass = unicode("\"" + newpassword + "\"", "iso-8859-1") password_value = unicode_pass.encode("utf-16-le") add_pass = [(ldap.MOD_REPLACE, PASSWORD_ATTR, [password_value])] # Replace password try: l.modify_s(user_dn, add_pass) print "Active Directory password for the user was set successfully!" except ldap.LDAPError, e: sys.stderr.write('Error setting AD password for the user \n') sys.stderr.write('Message: ' + str(e) + '\n') sys.exit(1) # close connexion l.unbind() |
Bonjour à vous,
merci pour tout ces exemples, seulement une chose ne fonctionne pas: userAccounControl.
Voici la solution qui est simple, dans le second script après avoir injecter le contenu du dico dans le ldap il faut de nouveau définir le password avec le bon formatage:
PASSWORD_ATTR = « unicodePwd »
unicode_pass = unicode(« \ » » + PWD_USER + « \ » », « iso-8859-1 »)
password_value = unicode_pass.encode(« utf-16-le »)
add_pass = [(ldap.MOD_REPLACE, PASSWORD_ATTR, [password_value])]
# Replace password
try:
l.modify_s(USER_DN, add_pass)
print « password OK »
except ldap.LDAPError, e:
sys.stderr.write(‘Error setting AD password for the user \n’)
sys.stderr.write(‘Message: ‘ + str(e) + ‘\n’)
sys.exit(1)
Sans cela mon user est désactivé par défaut (et c’est normal) mais il m’est impossible de le réactiver même par GUI, j’ai un gros message d’erreur comme quoi le password ne répond pas à la politique….
Avec ce bout de code je peux de nouveau l’activer via le GUI ou le script
Merci pour ce commentaire, cela servira surement sysadmin de passage sur l’article.
Bonjour,
Merci pour les scripts, il serait peut être intéressant de rappeler que la modification de password ne peut s’opérer que sur une couche TLS. Sur le port 389 ça ne fonctionne pas
Exact !
Bonjour,
En reprenant votre code tout fonctionne correctement dans l’ajout d’un utilisateur dans l’AD par contre impossible de prendre en compte l’attribut : attrs[‘memberOf’]=[‘CN=mon_groupe,OU=groups,DC=mondomaine,DC=fr’]
une idée ?
Oula, je ne me suis pas servi de ce script depuis des années. Désolé.
ok merci , savez vous si le compte doit être activé afin de lui attribuer un groupe merci