From 477f270b52c5817e4b22f8ac7d4405144180d4ee Mon Sep 17 00:00:00 2001 From: Belen Bustamante Date: Thu, 28 May 2020 10:42:47 -0700 Subject: [PATCH] Enable support for multiple user objects --- lib/vmpooler/api/helpers.rb | 30 ++++---- spec/unit/api/helpers_spec.rb | 129 ++++++++++++++++++++++++++++++++++ 2 files changed, 144 insertions(+), 15 deletions(-) diff --git a/lib/vmpooler/api/helpers.rb b/lib/vmpooler/api/helpers.rb index 0b98143..a906d8c 100644 --- a/lib/vmpooler/api/helpers.rb +++ b/lib/vmpooler/api/helpers.rb @@ -84,29 +84,29 @@ module Vmpooler when 'ldap' ldap_base = auth[:ldap]['base'] ldap_port = auth[:ldap]['port'] || 389 + ldap_user_obj = auth[:ldap]['user_object'] + ldap_host = auth[:ldap]['host'] - if ldap_base.is_a? Array - ldap_base.each do |search_base| + unless ldap_base.is_a? Array + ldap_base = ldap_base.split + end + + unless ldap_user_obj.is_a? Array + ldap_user_obj = ldap_user_obj.split + end + + ldap_base.each do |search_base| + ldap_user_obj.each do |search_user_obj| result = authenticate_ldap( ldap_port, - auth[:ldap]['host'], - auth[:ldap]['user_object'], + ldap_host, + search_user_obj, search_base, username_str, password_str ) - return true if result == true + return true if result end - else - result = authenticate_ldap( - ldap_port, - auth[:ldap]['host'], - auth[:ldap]['user_object'], - ldap_base, - username_str, - password_str - ) - return result end return false diff --git a/spec/unit/api/helpers_spec.rb b/spec/unit/api/helpers_spec.rb index 62fed34..2660460 100644 --- a/spec/unit/api/helpers_spec.rb +++ b/spec/unit/api/helpers_spec.rb @@ -342,6 +342,135 @@ describe Vmpooler::API::Helpers do end end + context 'with multiple search user objects' do + let(:user_object) { + [ + 'uid', + 'cn' + ] + } + before(:each) do + auth[:ldap]['user_object'] = user_object + end + + it 'should attempt to bind with each user object' do + expect(subject).to receive(:authenticate_ldap).with(default_port, host, user_object[0], base, username_str, password_str) + expect(subject).to receive(:authenticate_ldap).with(default_port, host, user_object[1], base, username_str, password_str) + + subject.authenticate(auth, username_str, password_str) + end + + it 'should not search the second user object when the first binds' do + expect(subject).to receive(:authenticate_ldap).with(default_port, host, user_object[0], base, username_str, password_str).and_return(true) + expect(subject).to_not receive(:authenticate_ldap).with(default_port, host, user_object[1], base, username_str, password_str) + + subject.authenticate(auth, username_str, password_str) + end + + it 'should search the second user object when the first bind fails' do + expect(subject).to receive(:authenticate_ldap).with(default_port, host, user_object[0], base, username_str, password_str).and_return(false) + expect(subject).to receive(:authenticate_ldap).with(default_port, host, user_object[1], base, username_str, password_str) + + subject.authenticate(auth, username_str, password_str) + end + + it 'should return true when any bind succeeds' do + expect(subject).to receive(:authenticate_ldap).with(default_port, host, user_object[0], base, username_str, password_str).and_return(false) + expect(subject).to receive(:authenticate_ldap).with(default_port, host, user_object[1], base, username_str, password_str).and_return(true) + + expect(subject.authenticate(auth, username_str, password_str)).to be true + end + + it 'should return false when all bind attempts fail' do + expect(subject).to receive(:authenticate_ldap).with(default_port, host, user_object[0], base, username_str, password_str).and_return(false) + expect(subject).to receive(:authenticate_ldap).with(default_port, host, user_object[1], base, username_str, password_str).and_return(false) + + expect(subject.authenticate(auth, username_str, password_str)).to be false + end + end + + context 'with multiple search user objects and with multiple search bases' do + let(:user_object) { + [ + 'uid', + 'cn' + ] + } + let(:base) { + [ + 'ou=user,dc=test,dc=com', + 'ou=service,ou=user,dc=test,dc=com' + ] + } + before(:each) do + auth[:ldap]['base'] = base + auth[:ldap]['user_object'] = user_object + end + + it 'should attempt to bind with each user object and base' do + expect(subject).to receive(:authenticate_ldap).with(default_port, host, user_object[0], base[0], username_str, password_str) + expect(subject).to receive(:authenticate_ldap).with(default_port, host, user_object[1], base[0], username_str, password_str) + expect(subject).to receive(:authenticate_ldap).with(default_port, host, user_object[0], base[1], username_str, password_str) + expect(subject).to receive(:authenticate_ldap).with(default_port, host, user_object[1], base[1], username_str, password_str) + + subject.authenticate(auth, username_str, password_str) + end + + it 'should not continue searching when the first combination binds' do + expect(subject).to receive(:authenticate_ldap).with(default_port, host, user_object[0], base[0], username_str, password_str).and_return(true) + expect(subject).to_not receive(:authenticate_ldap).with(default_port, host, user_object[1], base[0], username_str, password_str) + expect(subject).to_not receive(:authenticate_ldap).with(default_port, host, user_object[0], base[1], username_str, password_str) + expect(subject).to_not receive(:authenticate_ldap).with(default_port, host, user_object[1], base[1], username_str, password_str) + + subject.authenticate(auth, username_str, password_str) + end + + it 'should search the remaining combinations when the first bind fails' do + expect(subject).to receive(:authenticate_ldap).with(default_port, host, user_object[0], base[0], username_str, password_str).and_return(false) + expect(subject).to receive(:authenticate_ldap).with(default_port, host, user_object[1], base[0], username_str, password_str) + expect(subject).to receive(:authenticate_ldap).with(default_port, host, user_object[0], base[1], username_str, password_str) + expect(subject).to receive(:authenticate_ldap).with(default_port, host, user_object[1], base[1], username_str, password_str) + + subject.authenticate(auth, username_str, password_str) + end + + it 'should search the remaining combinations when the first two binds fail' do + expect(subject).to receive(:authenticate_ldap).with(default_port, host, user_object[0], base[0], username_str, password_str).and_return(false) + expect(subject).to receive(:authenticate_ldap).with(default_port, host, user_object[1], base[0], username_str, password_str).and_return(false) + expect(subject).to receive(:authenticate_ldap).with(default_port, host, user_object[0], base[1], username_str, password_str) + expect(subject).to receive(:authenticate_ldap).with(default_port, host, user_object[1], base[1], username_str, password_str) + + subject.authenticate(auth, username_str, password_str) + end + + it 'should search the remaining combination when the first three binds fail' do + expect(subject).to receive(:authenticate_ldap).with(default_port, host, user_object[0], base[0], username_str, password_str).and_return(false) + expect(subject).to receive(:authenticate_ldap).with(default_port, host, user_object[1], base[0], username_str, password_str).and_return(false) + expect(subject).to receive(:authenticate_ldap).with(default_port, host, user_object[0], base[1], username_str, password_str).and_return(false) + expect(subject).to receive(:authenticate_ldap).with(default_port, host, user_object[1], base[1], username_str, password_str) + + subject.authenticate(auth, username_str, password_str) + end + + it 'should return true when any bind succeeds' do + expect(subject).to receive(:authenticate_ldap).with(default_port, host, user_object[0], base[0], username_str, password_str).and_return(false) + expect(subject).to receive(:authenticate_ldap).with(default_port, host, user_object[1], base[0], username_str, password_str).and_return(false) + expect(subject).to receive(:authenticate_ldap).with(default_port, host, user_object[0], base[1], username_str, password_str).and_return(false) + expect(subject).to receive(:authenticate_ldap).with(default_port, host, user_object[1], base[1], username_str, password_str).and_return(true) + + expect(subject.authenticate(auth, username_str, password_str)).to be true + end + + it 'should return false when all bind attempts fail' do + expect(subject).to receive(:authenticate_ldap).with(default_port, host, user_object[0], base[0], username_str, password_str).and_return(false) + expect(subject).to receive(:authenticate_ldap).with(default_port, host, user_object[1], base[0], username_str, password_str).and_return(false) + expect(subject).to receive(:authenticate_ldap).with(default_port, host, user_object[0], base[1], username_str, password_str).and_return(false) + expect(subject).to receive(:authenticate_ldap).with(default_port, host, user_object[1], base[1], username_str, password_str).and_return(false) + + expect(subject.authenticate(auth, username_str, password_str)).to be false + end + end + end context 'with unknown provider' do