LDAP via Ruby ou Rails

J’ai essayé de connecter une application Rails à ActiveDirectory. Je vais synchroniser les données sur les utilisateurs entre AD et une firebase database, actuellement MySQL (mais peut devenir SQL Server ou PostgreSQL).

J’ai vérifié activedirectory-ruby, et ça a l’air vraiment bogué (pour une version 1.0 !?). Il enveloppe Net :: LDAP, alors j’ai essayé de l’utiliser à la place, mais il est très proche de la syntaxe réelle de LDAP, et j’ai apprécié l’abstraction d’ActiveDirectory-Ruby en raison de sa syntaxe similaire à ActiveRecord.

Existe-t-il un outil élégant de type ORM pour un serveur d’annuaire? Mieux encore, s’il existait une sorte d’outil d’échafaudage pour LDAP (CRUD pour les utilisateurs, les groupes, les unités d’organisation, etc.). Ensuite, je pourrais rapidement intégrer cela à mon code d’authentification existant via Authlogic, et garder toutes les données synchronisées.

Voici un exemple de code que j’utilise avec le gem net-ldap pour vérifier les connexions utilisateur à partir du serveur ActiveDirectory au travail:

require 'net/ldap' # gem install net-ldap def name_for_login( email, password ) email = email[/\A\w+/].downcase # Throw out the domain, if it was there email << "@mycompany.com" # I only check people in my company ldap = Net::LDAP.new( host: 'ldap.mycompany.com', # Thankfully this is a standard name auth: { method: :simple, email: email, password:password } ) if ldap.bind # Yay, the login credentials were valid! # Get the user's full name and return it ldap.search( base: "OU=Users,OU=Accounts,DC=mycompany,DC=com", filter: Net::LDAP::Filter.eq( "mail", email ), attributes: %w[ displayName ], return_result:true ).first.displayName.first end end 

Le first.displayName.first code first.displayName.first à la fin semble un peu bizarre, et pourrait donc bénéficier d'une explication:

  • Net::LDAP#search toujours un tableau de résultats, même si vous vous retrouvez avec une seule entrée. Le premier appel à la first trouve la première (et vraisemblablement la seule) entrée correspondant à l'adresse électronique.

  • Net::LDAP::Entry renvoyé par la recherche vous permet d'accéder facilement aux atsortingbuts via le nom de la méthode, de sorte que some_entry.displayName est identique à some_entry['displayName'] .

  • Chaque atsortingbut dans un Net::LDAP::Entry est toujours un tableau de valeurs, même si une seule valeur est présente. Bien qu'il puisse être idiot d'avoir un utilisateur avec plusieurs valeurs "displayName", la nature générique de LDAP signifie que c'est possible. La first invocation finale transforme le tableau-d'une-chaîne en une chaîne pour le nom complet de l'utilisateur.

C’est plus anecdotique qu’une vraie réponse …

J’ai eu une expérience similaire en utilisant le serveur Samba et OpenLDAP. Je ne pouvais pas trouver une bibliothèque pour vraiment faire ce que je voulais, alors j’ai roulé mes propres classes d’assistance.

J’ai utilisé ldapbrowser pour voir quels champs Samba remplissait lorsque je créais un utilisateur de manière “officielle” et que je le dupliquais.

Le seul truc LDAP difficile / non standard était le cryptage de mot de passe fou que nous avons:

passe d’utilisateur:

 "{MD5}" + Base64.encode64(Digest::MD5.digest(pass)) 

sambaNTPassword:

 OpenSSL::Digest::MD4.hexdigest(Iconv.iconv("UCS-2", "UTF-8", pass).join).upcase 

Pour la fonction def authenticate(user, pass) , j’essaie de faire en sorte que LDAP se lie au domaine à l’aide de ses informations d’identification, si j’attrape une exception, la connexion a échoué, sinon laissez-la entrer.

J’ai commencé à utiliser ruby-activedirectory, et j’ai même étendu / corrigé quelques choses, en hébergeant judy-activedirectory dans Github.

En faisant la prochaine itération, j’ai découvert qu’ActiveLdap avait une base de code bien meilleure, et j’envisage sérieusement de le changer. Est-ce que quelqu’un a une expérience personnelle avec cela?

Désolé, je ne peux pas encore commenter … peut-être que quelqu’un peut le déplacer correctement.

La solution @ Phrogz fonctionne bien, mais bind_simple (à l’intérieur de bind) déclenche une exception Net :: LDAP :: LdapError car auth [: username] n’est pas défini comme indiqué ici:

https://github.com/ruby-ldap/ruby-net-ldap/blob/master/lib/net/ldap.rb

Le corrigé remplace:

 auth: { method: :simple, email: email, password:password } 

avec:

 auth: { method: :simple, username: email, password:password } 

Avez-vous vérifié ldap-activerecord-gateway de thinkbot? Cela pourrait être quelque chose à considérer pour vous …

http://github.com/thoughtbot/ldap-activerecord-gateway/tree/master