web-dev-qa-db-fra.com

LDAP via Ruby ou Rails

J'ai essayé de connecter une application Rails à ActiveDirectory. Je synchroniserai les données sur les utilisateurs entre AD et une base de données, actuellement MySQL (mais peut se transformer en SQL Server ou PostgreSQL).

J'ai vérifié activedirectory-Ruby, et il semble vraiment bogué (pour une version 1.0!?). Il enveloppe Net :: LDAP, j'ai donc essayé de l'utiliser à la place, mais il est vraiment proche de la syntaxe réelle de LDAP, et j'ai apprécié l'abstraction d'ActiveDirectory-Ruby en raison de sa syntaxe de type ActiveRecord.

Existe-t-il un élégant outil 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 organisationnelles, etc.). Ensuite, je pourrais rapidement l'intégrer à mon code d'authentification existant via Authlogic et garder toutes les données synchronisées.

44
Clinton Judy

Voici un exemple de code que j'utilise avec la gemme net-ldap pour vérifier les connexions utilisateur depuis le serveur ActiveDirectory à mon 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 le code à la fin semble un peu maladroit, et pourrait donc bénéficier d'une explication:

  • Net::LDAP#search renvoie toujours un tableau de résultats, même si vous finissez par correspondre à une seule entrée. Le premier appel à first recherche la première entrée (et probablement seulement) qui correspond à l'adresse e-mail.

  • Le Net::LDAP::Entry renvoyé par la recherche vous permet d'accéder facilement aux attributs via le nom de la méthode, donc some_entry.displayName est le même que some_entry['displayName'].

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

40
Phrogz
8
mrTomahawk

C'est plus anecdotique qu'une vraie réponse ...

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

J'ai utilisé ldapbrowser pour voir les champs remplis par Samba lorsque j'ai créé un utilisateur de manière "officielle" et en gros, j'ai dupliqué cela.

La seule chose LDAP délicate/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 d'obtenir LDAP pour se lier au domaine en utilisant leurs informations d'identification, si j'attrape une exception, la connexion a échoué, sinon laissez-les entrer.

4
Lolindrath

Désolé, je ne peux pas encore commenter ... peut-être que quelqu'un peut le déplacer de manière appropriée.

La solution de @ Phrogz fonctionne bien, mais bind_simple (à l'intérieur de bind) déclenche une exception Net :: LDAP :: LdapError car l'auth [: nom d'utilisateur] 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 }
3
jordanpg

J'ai commencé à utiliser Ruby-activedirectory, et je l'ai même étendu/corrigé quelques choses, hébergeant judy-activedirectory dans Github.

Lors de la prochaine itération, j'ai découvert qu'ActiveLdap a une bien meilleure base de code, et j'envisage sérieusement d'y passer. Quelqu'un at-il une expérience personnelle avec cela?

2
Clinton Judy

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

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

1
Tim