Merge master and manually resolve merge conflicts

This commit is contained in:
Colin Seymour 2016-09-08 16:59:51 +01:00
Родитель 0e695c622a 2b248d342e
Коммит 7be5c555d3
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 88109C73073E7080
20 изменённых файлов: 671 добавлений и 10 удалений

Просмотреть файл

@ -1,12 +1,18 @@
language: ruby
rvm:
- 1.9.3
- 2.0.0
- 2.1.0
env:
- TESTENV=openldap
- TESTENV=apacheds
# https://docs.travis-ci.com/user/hosts/
addons:
hosts:
- ad1.ghe.dev
- ad2.ghe.dev
install:
- if [ "$TESTENV" = "openldap" ]; then ./script/install-openldap; fi
- bundle install

Просмотреть файл

@ -1,5 +1,9 @@
# CHANGELOG
# v1.10.0
* Bump net-ldap to 0.15.0 [#92](https://github.com/github/github-ldap/pull/92)
# v1.9.0
* Update net-ldap dependency to `~> 0.11.0` [#84](https://github.com/github/github-ldap/pull/84)

Просмотреть файл

@ -6,3 +6,7 @@ gemspec
group :test, :development do
gem "byebug", :platforms => [:mri_20, :mri_21]
end
group :test do
gem "mocha"
end

Просмотреть файл

@ -2,7 +2,7 @@
Gem::Specification.new do |spec|
spec.name = "github-ldap"
spec.version = "1.9.1"
spec.version = "1.10.0"
spec.authors = ["David Calavera", "Matt Todd"]
spec.email = ["david.calavera@gmail.com", "chiology@gmail.com"]
spec.description = %q{LDAP authentication for humans}
@ -15,7 +15,7 @@ Gem::Specification.new do |spec|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
spec.require_paths = ["lib"]
spec.add_dependency 'net-ldap', '~> 0.14.0'
spec.add_dependency 'net-ldap', '~> 0.15.0'
spec.add_development_dependency "bundler", "~> 1.3"
spec.add_development_dependency 'ladle'

Просмотреть файл

@ -10,6 +10,11 @@ require 'github/ldap/virtual_attributes'
require 'github/ldap/instrumentation'
require 'github/ldap/member_search'
require 'github/ldap/membership_validators'
require 'github/ldap/user_search/default'
require 'github/ldap/user_search/active_directory'
require 'github/ldap/connection_cache'
require 'github/ldap/referral_chaser'
require 'github/ldap/url'
module GitHub
class Ldap
@ -38,11 +43,17 @@ module GitHub
#
# Returns the return value of the block.
def_delegator :@connection, :open
def_delegator :@connection, :host
attr_reader :uid, :search_domains, :virtual_attributes,
:membership_validator,
:member_search_strategy,
:instrumentation_service
:instrumentation_service,
:user_search_strategy,
:connection,
:admin_user,
:admin_password,
:port
# Build a new GitHub::Ldap instance
#
@ -72,6 +83,11 @@ module GitHub
def initialize(options = {})
@uid = options[:uid] || "sAMAccountName"
# Keep a reference to these as default auth for a Global Catalog if needed
@admin_user = options[:admin_user]
@admin_password = options[:admin_password]
@port = options[:port]
@connection = Net::LDAP.new({
host: options[:host],
port: options[:port],
@ -102,6 +118,9 @@ module GitHub
# configure both the membership validator and the member search strategies
configure_search_strategy(options[:search_strategy])
# configure the strategy used by Domain#user? to look up a user entry for login
configure_user_search_strategy(options[:user_search_strategy])
# enables instrumenting queries
@instrumentation_service = options[:instrumentation_service]
end
@ -285,6 +304,28 @@ module GitHub
end
end
# Internal: Set the user search strategy that will be used by
# Domain#user?.
#
# strategy - Can be either 'default' or 'global_catalog'.
# 'default' strategy will search the configured
# domain controller with a search base relative
# to the controller's domain context.
# 'global_catalog' will search the entire forest
# using Active Directory's Global Catalog
# functionality.
def configure_user_search_strategy(strategy)
@user_search_strategy =
case strategy.to_s
when "default"
GitHub::Ldap::UserSearch::Default.new(self)
when "global_catalog"
GitHub::Ldap::UserSearch::ActiveDirectory.new(self)
else
GitHub::Ldap::UserSearch::Default.new(self)
end
end
# Internal: Configure the member search strategy.
#
#

Просмотреть файл

@ -0,0 +1,26 @@
module GitHub
class Ldap
# A simple cache of GitHub::Ldap objects to prevent creating multiple
# instances of connections that point to the same URI/host.
class ConnectionCache
# Public - Create or return cached instance of GitHub::Ldap created with options,
# where the cache key is the value of options[:host].
#
# options - Initialization attributes suitable for creating a new connection with
# GitHub::Ldap.new(options)
#
# Returns true or false.
def self.get_connection(options={})
@cache ||= self.new
@cache.get_connection(options)
end
def get_connection(options)
@connections ||= {}
@connections[options[:host]] ||= GitHub::Ldap.new(options)
end
end
end
end

Просмотреть файл

@ -115,10 +115,7 @@ module GitHub
# Returns the user if the login matches any `uid`.
# Returns nil if there are no matches.
def user?(login, search_options = {})
options = search_options.merge \
filter: login_filter(@uid, login),
size: 1
search(options).first
@ldap.user_search_strategy.perform(login, @base_name, @uid, search_options).first
end
# Check if a user can be bound with a password.

Просмотреть файл

@ -24,15 +24,23 @@ module GitHub
# Sets the entry to the base and scopes the search to the base,
# according to the source documentation, found here:
# http://msdn.microsoft.com/en-us/library/aa746475(v=vs.85).aspx
matched = ldap.search \
#
# Use ReferralChaser to chase any potential referrals for an entry that may be owned by a different
# domain controller.
matched = referral_chaser.search \
filter: membership_in_chain_filter(entry),
base: entry.dn,
scope: Net::LDAP::SearchScope_BaseObject,
return_referrals: true,
attributes: ATTRS
# membership validated if entry was matched and returned as a result
# Active Directory DNs are case-insensitive
matched.map { |m| m.dn.downcase }.include?(entry.dn.downcase)
Array(matched).map { |m| m.dn.downcase }.include?(entry.dn.downcase)
end
def referral_chaser
@referral_chaser ||= GitHub::Ldap::ReferralChaser.new(@ldap)
end
# Internal: Constructs a membership filter using the "in chain"

Просмотреть файл

@ -0,0 +1,98 @@
module GitHub
class Ldap
# This class adds referral chasing capability to a GitHub::Ldap connection.
#
# See: https://technet.microsoft.com/en-us/library/cc978014.aspx
# http://www.umich.edu/~dirsvcs/ldap/doc/other/ldap-ref.html
#
class ReferralChaser
# Public - Creates a ReferralChaser that decorates an instance of GitHub::Ldap
# with additional functionality to the #search method, allowing it to chase
# any referral entries and aggregate the results into a single response.
#
# connection - The instance of GitHub::Ldap to use for searching. Will use
# the connection's authentication, (admin_user and admin_password) as credentials
# for connecting to referred domain controllers.
def initialize(connection)
@connection = connection
@admin_user = connection.admin_user
@admin_password = connection.admin_password
@port = connection.port
end
# Public - Search the domain controller represented by this instance's connection.
# If a referral is returned, search only one of the domain controllers indicated
# by the referral entries, per RFC 4511 (https://tools.ietf.org/html/rfc4511):
#
# "If the client wishes to progress the operation, it contacts one of
# the supported services found in the referral. If multiple URIs are
# present, the client assumes that any supported URI may be used to
# progress the operation."
#
# options - is a hash with the same options that Net::LDAP::Connection#search supports.
# Referral searches will use the given options, but will replace options[:base]
# with the referral URL's base search dn.
#
# Does not take a block argument as GitHub::Ldap and Net::LDAP::Connection#search do.
#
# Will not recursively follow any subsequent referrals.
#
# Returns an Array of Net::LDAP::Entry.
def search(options)
search_results = []
referral_entries = []
search_results = connection.search(options) do |entry|
if entry && entry[:search_referrals]
referral_entries << entry
end
end
unless referral_entries.empty?
entry = referral_entries.first
referral_string = entry[:search_referrals].first
if GitHub::Ldap::URL.valid?(referral_string)
referral = Referral.new(referral_string, admin_user, admin_password, port)
search_results = referral.search(options)
end
end
Array(search_results)
end
private
attr_reader :connection, :admin_user, :admin_password, :port
# Represents a referral entry from an LDAP search result. Constructs a corresponding
# GitHub::Ldap object from the paramaters on the referral_url and provides a #search
# method to continue the search on the referred domain.
class Referral
def initialize(referral_url, admin_user, admin_password, port=nil)
url = GitHub::Ldap::URL.new(referral_url)
@search_base = url.dn
connection_options = {
host: url.host,
port: port || url.port,
scope: url.scope,
admin_user: admin_user,
admin_password: admin_password
}
@connection = GitHub::Ldap::ConnectionCache.get_connection(connection_options)
end
# Search the referred domain controller with options, merging in the referred search
# base DN onto options[:base].
def search(options)
connection.search(options.merge(base: search_base))
end
attr_reader :search_base, :connection
end
end
end
end

87
lib/github/ldap/url.rb Normal file
Просмотреть файл

@ -0,0 +1,87 @@
module GitHub
class Ldap
# This class represents an LDAP URL
#
# See: https://tools.ietf.org/html/rfc4516#section-2
# https://docs.oracle.com/cd/E19957-01/817-6707/urls.html
#
class URL
extend Forwardable
SCOPES = {
"base" => Net::LDAP::SearchScope_BaseObject,
"one" => Net::LDAP::SearchScope_SingleLevel,
"sub" => Net::LDAP::SearchScope_WholeSubtree
}
SCOPES.default = Net::LDAP::SearchScope_BaseObject
attr_reader :dn, :attributes, :scope, :filter
def_delegators :@uri, :port, :host, :scheme
# Public - Creates a new GitHub::Ldap::URL object with :port, :host and :scheme
# delegated to a URI object parsed from url_string, and then parses the
# query params according to the LDAP specification.
#
# url_string - An LDAP URL string.
# returns - a GitHub::Ldap::URL with the following attributes:
# host - Name or IP of the LDAP server.
# port - The given port, defaults to 389.
# dn - The base search DN.
# attributes - The comma-delimited list of attributes to be returned.
# scope - The scope of the search.
# filter - Search filter to apply to entries within the specified scope of the search.
#
# Supported LDAP URL strings look like this, where sections in brackets are optional:
#
# ldap[s]://[hostport][/[dn[?[attributes][?[scope][?[filter]]]]]]
#
# where:
#
# hostport is a host name with an optional ":portnumber"
# dn is the base DN to be used for an LDAP search operation
# attributes is a comma separated list of attributes to be retrieved
# scope is one of these three strings: base one sub (default=base)
# filter is LDAP search filter as used in a call to ldap_search
#
# For example:
#
# ldap://dc4.ghe.local:456/CN=Maggie,DC=dc4,DC=ghe,DC=local?cn,mail?base?(cn=Charlie)
#
def initialize(url_string)
if !self.class.valid?(url_string)
raise InvalidLdapURLException.new("Invalid LDAP URL: #{url_string}")
end
@uri = URI(url_string)
@dn = URI.unescape(@uri.path.sub(/^\//, ""))
if @uri.query
@attributes, @scope, @filter = @uri.query.split("?")
end
end
def self.valid?(url_string)
url_string =~ URI::regexp && ["ldap", "ldaps"].include?(URI(url_string).scheme)
end
# Maps the returned scope value from the URL to one of Net::LDAP::Scopes
#
# The URL scope value can be one of:
# "base" - retrieves information only about the DN (base_dn) specified.
# "one" - retrieves information about entries one level below the DN (base_dn) specified. The base entry is not included in this scope.
# "sub" - retrieves information about entries at all levels below the DN (base_dn) specified. The base entry is included in this scope.
#
# Which will map to one of the following Net::LDAP::Scopes:
# SearchScope_BaseObject = 0
# SearchScope_SingleLevel = 1
# SearchScope_WholeSubtree = 2
#
# If no scope or an invalid scope is given, defaults to SearchScope_BaseObject
def net_ldap_scope
Net::LDAP::SearchScopes[SCOPES[scope]]
end
class InvalidLdapURLException < Exception; end
end
end
end

Просмотреть файл

@ -0,0 +1,51 @@
module GitHub
class Ldap
module UserSearch
class ActiveDirectory < Default
private
# Private - Overridden from base class to set the base to "", and use the
# Global Catalog to perform the user search.
def search(search_options)
Array(global_catalog_connection.search(search_options.merge(options)))
end
def global_catalog_connection
GlobalCatalog.connection(ldap)
end
# When doing a global search for a user's DN, set the search base to blank
def options
super.merge(base: "")
end
end
class GlobalCatalog < Net::LDAP
STANDARD_GC_PORT = 3268
LDAPS_GC_PORT = 3269
# Returns a connection to the Active Directory Global Catalog
#
# See: https://technet.microsoft.com/en-us/library/cc728188(v=ws.10).aspx
#
def self.connection(ldap)
@global_catalog_instance ||= begin
netldap = ldap.connection
# This is ugly, but Net::LDAP doesn't expose encryption or auth
encryption = netldap.instance_variable_get(:@encryption)
auth = netldap.instance_variable_get(:@auth)
new({
host: ldap.host,
instrumentation_service: ldap.instrumentation_service,
port: encryption ? LDAPS_GC_PORT : STANDARD_GC_PORT,
auth: auth,
encryption: encryption
})
end
end
end
end
end
end

Просмотреть файл

@ -0,0 +1,40 @@
module GitHub
class Ldap
module UserSearch
# The default user search strategy, mainly for allowing Domain#user? to
# search for a user on the configured domain controller, or use the Global
# Catalog to search across the entire Active Directory forest.
class Default
include Filter
def initialize(ldap)
@ldap = ldap
@options = {
:attributes => [],
:paged_searches_supported => true,
:size => 1
}
end
# Performs a normal search on the configured domain controller
# using the default base DN, uid, search_options
def perform(login, base_name, uid, search_options)
search_options[:filter] = login_filter(uid, login)
search_options[:base] = base_name
search(options.merge(search_options))
end
# The default search. This can be overridden by a child class
# like GitHub::Ldap::UserSearch::ActiveDirectory to change the
# scope of the search.
def search(options)
ldap.search(options)
end
private
attr_reader :options, :ldap
end
end
end
end

Просмотреть файл

@ -0,0 +1,18 @@
require_relative 'test_helper'
class GitHubLdapConnectionCacheTestCases < GitHub::Ldap::Test
def test_returns_cached_connection
conn1 = GitHub::Ldap::ConnectionCache.get_connection(options.merge(:host => "ad1.ghe.dev"))
conn2 = GitHub::Ldap::ConnectionCache.get_connection(options.merge(:host => "ad1.ghe.dev"))
assert_equal conn1.object_id, conn2.object_id
end
def test_creates_new_connections_per_host
conn1 = GitHub::Ldap::ConnectionCache.get_connection(options.merge(:host => "ad1.ghe.dev"))
conn2 = GitHub::Ldap::ConnectionCache.get_connection(options.merge(:host => "ad2.ghe.dev"))
conn3 = GitHub::Ldap::ConnectionCache.get_connection(options.merge(:host => "ad2.ghe.dev"))
refute_equal conn1.object_id, conn2.object_id
assert_equal conn2.object_id, conn3.object_id
end
end

Просмотреть файл

@ -140,6 +140,15 @@ module GitHubLdapDomainTestCases
assert user = @domain.user?('user1')
refute @domain.auth(user, 'foo'), 'Expected user not not bind'
end
def test_user_search_returns_first_entry
entry = mock("Net::Ldap::Entry")
search_strategy = mock("GitHub::Ldap::UserSearch::Default")
search_strategy.stubs(:perform).returns([entry])
@ldap.expects(:user_search_strategy).returns(search_strategy)
user = @domain.user?('user1', :attributes => [:cn])
assert_equal entry, user
end
end
class GitHubLdapDomainTest < GitHub::Ldap::Test

Просмотреть файл

@ -129,6 +129,17 @@ module GitHubLdapTestCases
assert_equal GitHub::Ldap::MemberSearch::Recursive, @ldap.member_search_strategy
end
def test_user_search_strategy_global_catalog_when_configured
@ldap.configure_user_search_strategy("global_catalog")
assert_kind_of GitHub::Ldap::UserSearch::ActiveDirectory, @ldap.user_search_strategy
end
def test_user_search_strategy_default_when_configured
@ldap.configure_user_search_strategy("default")
refute_kind_of GitHub::Ldap::UserSearch::ActiveDirectory, @ldap.user_search_strategy
assert_kind_of GitHub::Ldap::UserSearch::Default, @ldap.user_search_strategy
end
def test_capabilities
assert_kind_of Net::LDAP::Entry, @ldap.capabilities
end

Просмотреть файл

@ -0,0 +1,102 @@
require_relative 'test_helper'
class GitHubLdapReferralChaserTestCases < GitHub::Ldap::Test
def setup
@ldap = GitHub::Ldap.new(options)
@chaser = GitHub::Ldap::ReferralChaser.new(@ldap)
end
def test_creates_referral_with_connection_credentials
@ldap.expects(:search).yields({ search_referrals: ["ldap://dc1.ghe.local/"]}).returns([])
referral = mock("GitHub::Ldap::ReferralChaser::Referral")
referral.stubs(:search).returns([])
GitHub::Ldap::ReferralChaser::Referral.expects(:new)
.with("ldap://dc1.ghe.local/", "uid=admin,dc=github,dc=com", "passworD1", options[:port])
.returns(referral)
@chaser.search({})
end
def test_creates_referral_with_default_port
@ldap.expects(:search).yields({
search_referrals: ["ldap://dc1.ghe.local/CN=Maggie%20Mae,CN=Users,DC=dc4,DC=ghe,DC=local"]
}).returns([])
stub_referral_connection = mock("GitHub::Ldap")
stub_referral_connection.stubs(:search).returns([])
GitHub::Ldap::ConnectionCache.expects(:get_connection).with(has_entry(port: options[:port])).returns(stub_referral_connection)
chaser = GitHub::Ldap::ReferralChaser.new(@ldap)
chaser.search({})
end
def test_creates_referral_for_first_referral_string
@ldap.expects(:search).multiple_yields([
{ search_referrals:
["ldap://dc1.ghe.local/CN=Maggie%20Mae,CN=Users,DC=dc4,DC=ghe,DC=local",
"ldap://dc2.ghe.local/CN=Maggie%20Mae,CN=Users,DC=dc4,DC=ghe,DC=local"]
}
],[
{ search_referrals:
["ldap://dc3.ghe.local/CN=Maggie%20Mae,CN=Users,DC=dc4,DC=ghe,DC=local",
"ldap://dc4.ghe.local/CN=Maggie%20Mae,CN=Users,DC=dc4,DC=ghe,DC=local"]
}
]).returns([])
referral = mock("GitHub::Ldap::ReferralChaser::Referral")
referral.stubs(:search).returns([])
GitHub::Ldap::ReferralChaser::Referral.expects(:new)
.with(
"ldap://dc1.ghe.local/CN=Maggie%20Mae,CN=Users,DC=dc4,DC=ghe,DC=local",
"uid=admin,dc=github,dc=com",
"passworD1",
options[:port])
.returns(referral)
@chaser.search({})
end
def test_returns_referral_search_results
@ldap.expects(:search).multiple_yields([
{ search_referrals:
["ldap://dc1.ghe.local/CN=Maggie%20Mae,CN=Users,DC=dc4,DC=ghe,DC=local",
"ldap://dc2.ghe.local/CN=Maggie%20Mae,CN=Users,DC=dc4,DC=ghe,DC=local"]
}
],[
{ search_referrals:
["ldap://dc3.ghe.local/CN=Maggie%20Mae,CN=Users,DC=dc4,DC=ghe,DC=local",
"ldap://dc4.ghe.local/CN=Maggie%20Mae,CN=Users,DC=dc4,DC=ghe,DC=local"]
}
]).returns([])
referral = mock("GitHub::Ldap::ReferralChaser::Referral")
referral.expects(:search).returns(["result", "result"])
GitHub::Ldap::ReferralChaser::Referral.expects(:new).returns(referral)
results = @chaser.search({})
assert_equal(["result", "result"], results)
end
def test_handle_blank_url_string_in_referral
@ldap.expects(:search).yields({ search_referrals: [""] })
results = @chaser.search({})
assert_equal([], results)
end
def test_returns_referral_search_results
@ldap.expects(:search).yields({ foo: ["not a referral"] })
GitHub::Ldap::ReferralChaser::Referral.expects(:new).never
results = @chaser.search({})
end
def test_referral_should_use_host_from_referral_string
GitHub::Ldap::ConnectionCache.expects(:get_connection).with(has_entry(host: "dc4.ghe.local"))
GitHub::Ldap::ReferralChaser::Referral.new("ldap://dc4.ghe.local/CN=Maggie%20Mae,CN=Users,DC=dc4,DC=ghe,DC=local", "", "")
end
end

Просмотреть файл

@ -13,6 +13,8 @@ require 'github/ldap/server'
require 'minitest/mock'
require 'minitest/autorun'
require 'mocha/mini_test'
if ENV.fetch('TESTENV', "apacheds") == "apacheds"
# Make sure we clean up running test server
# NOTE: We need to do this manually since its internal `at_exit` hook

85
test/url_test.rb Normal file
Просмотреть файл

@ -0,0 +1,85 @@
require_relative 'test_helper'
class GitHubLdapURLTestCases < GitHub::Ldap::Test
def setup
@url = GitHub::Ldap::URL.new("ldap://dc4.ghe.local:123/CN=Maggie%20Mae,CN=Users,DC=dc4,DC=ghe,DC=local?cn,mail,telephoneNumber?base?(cn=Charlie)")
end
def test_host
assert_equal "dc4.ghe.local", @url.host
end
def test_port
assert_equal 123, @url.port
end
def test_scheme
assert_equal "ldap", @url.scheme
end
def test_default_port
url = GitHub::Ldap::URL.new("ldap://dc4.ghe.local/CN=Maggie%20Mae,CN=Users,DC=dc4,DC=ghe,DC=local?attributes?scope?filter")
assert_equal 389, url.port
end
def test_simple_url
url = GitHub::Ldap::URL.new("ldap://dc4.ghe.local")
assert_equal 389, url.port
assert_equal "dc4.ghe.local", url.host
assert_equal "ldap", url.scheme
assert_equal "", url.dn
assert_equal nil, url.attributes
assert_equal nil, url.filter
assert_equal nil, url.scope
end
def test_invalid_scheme
ex = assert_raises(GitHub::Ldap::URL::InvalidLdapURLException) do
GitHub::Ldap::URL.new("http://dc4.ghe.local")
end
assert_equal("Invalid LDAP URL: http://dc4.ghe.local", ex.message)
end
def test_invalid_url
ex = assert_raises(GitHub::Ldap::URL::InvalidLdapURLException) do
GitHub::Ldap::URL.new("not a url")
end
assert_equal("Invalid LDAP URL: not a url", ex.message)
end
def test_parse_dn
assert_equal "CN=Maggie Mae,CN=Users,DC=dc4,DC=ghe,DC=local", @url.dn
end
def test_parse_attributes
assert_equal "cn,mail,telephoneNumber", @url.attributes
end
def test_parse_filter
assert_equal "(cn=Charlie)", @url.filter
end
def test_parse_scope
assert_equal "base", @url.scope
end
def test_default_scope
url = GitHub::Ldap::URL.new("ldap://dc4.ghe.local/base_dn?cn=joe??filter")
assert_equal "", url.scope
end
def test_net_ldap_scopes
sub_scope_url = GitHub::Ldap::URL.new("ldap://ghe.local/base_dn?cn=joe?sub?filter")
one_scope_url = GitHub::Ldap::URL.new("ldap://ghe.local/base_dn?cn=joe?one?filter")
base_scope_url = GitHub::Ldap::URL.new("ldap://ghe.local/base_dn?cn=joe?base?filter")
default_scope_url = GitHub::Ldap::URL.new("ldap://dc4.ghe.local/base_dn?cn=joe??filter")
invalid_scope_url = GitHub::Ldap::URL.new("ldap://dc4.ghe.local/base_dn?cn=joe?invalid?filter")
assert_equal Net::LDAP::SearchScope_BaseObject, base_scope_url.net_ldap_scope
assert_equal Net::LDAP::SearchScope_SingleLevel, one_scope_url.net_ldap_scope
assert_equal Net::LDAP::SearchScope_WholeSubtree, sub_scope_url.net_ldap_scope
assert_equal Net::LDAP::SearchScope_BaseObject, default_scope_url.net_ldap_scope
assert_equal Net::LDAP::SearchScope_BaseObject, invalid_scope_url.net_ldap_scope
end
end

Просмотреть файл

@ -0,0 +1,53 @@
require_relative '../test_helper'
class GitHubLdapActiveDirectoryUserSearchTests < GitHub::Ldap::Test
def test_global_catalog_returns_empty_array_for_no_results
ldap = GitHub::Ldap.new(options.merge(host: 'ghe.dev'))
ad_user_search = GitHub::Ldap::UserSearch::ActiveDirectory.new(ldap)
mock_global_catalog_connection = mock("GitHub::Ldap::UserSearch::GlobalCatalog")
mock_global_catalog_connection.expects(:search).returns(nil)
ad_user_search.expects(:global_catalog_connection).returns(mock_global_catalog_connection)
results = ad_user_search.perform("login", "CN=Joe", "uid", {})
assert_equal [], results
end
def test_global_catalog_returns_array_of_results
ldap = GitHub::Ldap.new(options.merge(host: 'ghe.dev'))
ad_user_search = GitHub::Ldap::UserSearch::ActiveDirectory.new(ldap)
mock_global_catalog_connection = mock("GitHub::Ldap::UserSearch::GlobalCatalog")
stub_entry = mock("Net::LDAP::Entry")
mock_global_catalog_connection.expects(:search).returns(stub_entry)
ad_user_search.expects(:global_catalog_connection).returns(mock_global_catalog_connection)
results = ad_user_search.perform("login", "CN=Joe", "uid", {})
assert_equal [stub_entry], results
end
def test_searches_with_empty_base_dn
ldap = GitHub::Ldap.new(options.merge(host: 'ghe.dev'))
ad_user_search = GitHub::Ldap::UserSearch::ActiveDirectory.new(ldap)
mock_global_catalog_connection = mock("GitHub::Ldap::UserSearch::GlobalCatalog")
mock_global_catalog_connection.expects(:search).with(has_entry(:base => ""))
ad_user_search.expects(:global_catalog_connection).returns(mock_global_catalog_connection)
ad_user_search.perform("login", "CN=Joe", "uid", {})
end
def test_global_catalog_default_settings
ldap = GitHub::Ldap.new(options.merge(host: 'ghe.dev'))
global_catalog = GitHub::Ldap::UserSearch::GlobalCatalog.connection(ldap)
instrumentation_service = global_catalog.instance_variable_get(:@instrumentation_service)
auth = global_catalog.instance_variable_get(:@auth)
assert_equal :simple, auth[:method]
assert_equal "uid=admin,dc=github,dc=com", auth[:username]
assert_equal "passworD1", auth[:password]
assert_equal "ghe.dev", global_catalog.host
assert_equal 3268, global_catalog.port
assert_equal "MockInstrumentationService", instrumentation_service.class.name
end
end

Просмотреть файл

@ -0,0 +1,19 @@
require_relative '../test_helper'
class GitHubLdapActiveDirectoryUserSearchTests < GitHub::Ldap::Test
def setup
@ldap = GitHub::Ldap.new(options)
@default_user_search = GitHub::Ldap::UserSearch::Default.new(@ldap)
end
def test_default_search_options
@ldap.expects(:search).with(has_entries(
attributes: [],
size: 1,
paged_searches_supported: true,
base: "CN=HI,CN=McDunnough",
filter: kind_of(Net::LDAP::Filter)
))
@default_user_search.perform("","CN=HI,CN=McDunnough","",{})
end
end