Updates from May, 2015 Toggle Comment Threads | Keyboard Shortcuts

  • ThomasPowell 7:06 pm on May 22, 2015 Permalink
    Tags: cucumber, ladle, , ,   

    Hooking in an LDAP Test Server to Cucumber Tests 

    I managed to get a custom Devise strategy with LDAP working, but had no clear way of automating tests. I wanted to validate if I still had to keep the password fresh in the database, and needed to be able to write scenarios around that in case someone attempted to refactor out the code.

    After trying to incorporate the spec strategy used in the development devise_ldap_authenticatable and failing, I found a ruby wrapper of ApacheDS called ladle that looked like it would serve my purposes.

    I included in gem in my test group in my Gemfile:

      gem 'ladle'

    At the top of my features/env.rb file for configuring cucumber, I turned off admin binding (wanted the connection as simple as possible):

    ::Devise.ldap_use_admin_to_bind = false

    I then created an @ldap tag for my LDAP-dependent features than would start and stop the LDAP server in those instances. (Again, in my features/env.rb… probably need to clean that up.)

    Around('@ldap') do |scenario, block|
      $ladle ||= Ladle::Server.new(
        :ldif => "spec/ldap/test_users.ldif",
        :domain => "dc=example,dc=org",
        :quiet => true

    I then created an the spec/ldap/test_users.ldif (from following the example in the ladle project).

    version: 1
    dn: ou=people,dc=example,dc=org
    objectClass: top
    objectClass: organizationalUnit
    ou: people
    dn: uid=eadmin,ou=people,dc=example,dc=org
    objectClass: top
    objectClass: person
    objectClass: organizationalPerson
    objectClass: inetOrgPerson
    cn: Example Admin
    sn: Admin
    givenName: Example
    mail: [email protected]
    uid: eadmin
    # Password is "[email protected]!"
    userpassword: {SHA}Aedq5WHQSxglvJSfpX0kgdGRdHk=

    I generated the password with:

      slappasswd -h {SHA} -s [email protected]!

    One stupid mistake that I did in the process was kicking off two Ladle servers (with slightly different parameters). In one iteration, I couldn’t bind to the user. Another, the server using the test file failed to start. Be aware that Ladle will run happily with default parameters, but that they won’t be much use to you.

    If you want to test your configuration file:

    require 'net/ldap'
    require 'ladle'
    $ladle ||= Ladle::Server.new(
      :ldif => "spec/ldap/test_users.ldif",
      :domain => "dc=example,dc=org",
      :quiet => true
    ldap = Net::LDAP.new(host: 'localhost',
        :port => 3897,
    filter = Net::LDAP::Filter.eq('mail', '[email protected]') # or ('uid', 'eadmin') 
    ldap.search(:base => 'ou=people,dc=example,dc=org', :filter => filter) do |entry|
      ldap.auth(entry.dn, '[email protected]!') # or whatever your password is
      entry.each do |attribute, values|
        puts "   #{attribute}:"
        values.each do |value|
          puts "      --->#{value}"
  • ThomasPowell 8:14 pm on May 19, 2015 Permalink
    Tags: , pick 3   

    Kentucky Lottery Pick 3 Expected Payout 

    The expected payouts for the Kentucky Lottery Pick 3 game have an interesting idiosyncrasy. Playing the special “Straight Box” play pays out better than a separate 50¢ straight and 50¢ box play.

    All other plays average 60¢ per dollar played, but the straight box seems to be 65¢ and 70¢, depending on the numbers played. Maybe my spreadsheet is wrong somewhere in here:

    Kentucky Lottery Pick 3 Payouts and Odds

  • ThomasPowell 4:54 am on May 15, 2015 Permalink
    Tags: ,   

    devise_ldap_authentication for your domain email on top of database_authenticatable 

    I have a devise user model named LoginUser whose authentication key is :login. I want normal users of the system to be database_authenticatable.

    However, I want to be able to authenticate previously added users via internal LDAP. Furthermore, I didn’t want the underlying database_authenticatable password to be used or to expire on me (also using devise_security_extensions). Most of the work is in the LocalOverride custom strategy’s authenticate! method, with a few other hooks (such as default strategy added to devise.yml).


    To allow all other strategies to be used, but still trap our domains for one-off LDAP auth, I added devise :ldap_authenticatable to a singleton class inherited from the user loaded by the custom strategy.

    Also, removed the other two “fails” from the code. Not necessary and will result in a “Failed to Login” message for too many other Devise-related Unauthorized events.

    In config/initializers/local_override.rb:

    module Devise
      module Strategies
        class LocalOverride < Authenticatable
          def valid?
          def authenticate!
            if params[:login_user]
              user = LoginUser.find_by_login(params[:login_user][:login])
              # trap our domain only
              if params[:login_user][:login] =~ /@example.com/
                # fail! halts the authentication chain completely
                return fail! unless ::Devise::LDAP::Adapter.valid_login?(params[:login_user][:login])
                class << user
                  # make use of ldap_authenticatable for custom strategy only
                  devise :ldap_authenticatable
                return fail! unless user.valid_ldap_authentication?(params[:login_user][:password])
                # use the after_ldap_authentication hook
                return success!(user)
    Warden::Strategies.add(:local_override, Devise::Strategies::LocalOverride)

    In config/initializers/devise.rb:

      # use local_override as default strategy
      config.warden do |manager|
        manager.default_strategies(:scope => :login_user).unshift :local_override

    In config/models/login_user.rb:

    class LoginUser < ActiveRecord::Base
      devise :database_authenticatable,
             :recoverable, :trackable, :secure_validatable,
             :authentication_keys => [:login]
      def after_ldap_authentication
        # force fresh password every log in
        self.password = self.password_confirmation = Random.new.bytes(47)
    defaults:  &defaults
      host: our.ldap
      port: 636
      attribute: mail
      base: dc=IDENT,o=Orgname
      admin_password: adminpassw0rd
      ssl: sslmethod

    See local_override.rb for original tip that got me there.

Compose new post
Next post/Next comment
Previous post/Previous comment
Show/Hide comments
Go to top
Go to login
Show/Hide help
shift + esc
%d bloggers like this: