Class: GitHub::Ldap::MembershipValidators::Recursive
- Includes:
- Filter
- Defined in:
- lib/github/ldap/membership_validators/recursive.rb
Overview
Validates membership recursively.
The first step checks whether the entry is a direct member of the given groups. If they are, then we’ve validated membership successfully.
If not, query for all of the groups that have our groups as members, then we check if the entry is a member of any of those.
This is repeated until the entry is found, recursing and requesting groups in bulk each iteration until we hit the maximum depth allowed and have to give up.
This results in a maximum of ‘depth` queries (per domain) to validate membership in a list of groups.
Constant Summary collapse
- DEFAULT_MAX_DEPTH =
9
- ATTRS =
%w(dn cn)
Constants included from Filter
Filter::ALL_GROUPS_FILTER, Filter::MEMBERSHIP_NAMES
Instance Attribute Summary collapse
-
#depth ⇒ Object
readonly
Internal: The maximum depth to search for membership.
Attributes inherited from Base
Instance Method Summary collapse
-
#group_dns ⇒ Object
Internal: the group DNs to check against.
-
#initialize(ldap, groups, options = {}) ⇒ Recursive
constructor
Public: Instantiate new search strategy.
-
#member_filter(entry_or_uid, uid = ldap.uid) ⇒ Object
Internal: Construct a filter to find groups this entry is a direct member of.
-
#membership_filter(groups) ⇒ Object
Internal: Construct a filter to find groups whose members are the Array of String group DNs passed in.
- #perform(entry, depth_override = nil) ⇒ Object
Methods included from Filter
#all_members_by_uid, #group_contains_filter, #group_filter, #login_filter, #members_of_group, #posix_member_filter, #subgroups_of_group
Constructor Details
#initialize(ldap, groups, options = {}) ⇒ Recursive
Public: Instantiate new search strategy.
-
ldap: GitHub::Ldap object
-
groups: Array of Net::LDAP::Entry group objects
-
options: Hash of options depth: Integer limit of recursion
NOTE: This overrides default behavior to configure ‘depth`.
35 36 37 38 |
# File 'lib/github/ldap/membership_validators/recursive.rb', line 35 def initialize(ldap, groups, = {}) super @depth = [:depth] || DEFAULT_MAX_DEPTH end |
Instance Attribute Details
#depth ⇒ Object (readonly)
Internal: The maximum depth to search for membership.
25 26 27 |
# File 'lib/github/ldap/membership_validators/recursive.rb', line 25 def depth @depth end |
Instance Method Details
#group_dns ⇒ Object
Internal: the group DNs to check against.
Returns an Array of String DNs.
111 112 113 |
# File 'lib/github/ldap/membership_validators/recursive.rb', line 111 def group_dns @group_dns ||= groups.map(&:dn) end |
#member_filter(entry_or_uid, uid = ldap.uid) ⇒ Object
Internal: Construct a filter to find groups this entry is a direct member of.
Overloads the included ‘GitHub::Ldap::Filters#member_filter` method to inject `posixGroup` handling.
Returns a Net::LDAP::Filter object.
88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/github/ldap/membership_validators/recursive.rb', line 88 def member_filter(entry_or_uid, uid = ldap.uid) filter = super(entry_or_uid) if ldap.posix_support_enabled? if posix_filter = posix_member_filter(entry_or_uid, uid) filter |= posix_filter end end filter end |
#membership_filter(groups) ⇒ Object
Internal: Construct a filter to find groups whose members are the Array of String group DNs passed in.
Returns a String filter.
104 105 106 |
# File 'lib/github/ldap/membership_validators/recursive.rb', line 104 def membership_filter(groups) groups.map { |entry| member_filter(entry, :cn) }.reduce(:|) end |
#perform(entry, depth_override = nil) ⇒ Object
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/github/ldap/membership_validators/recursive.rb', line 40 def perform(entry, depth_override = nil) if depth_override warn "DEPRECATION WARNING: Calling Recursive#perform with a second argument is deprecated." warn "Usage:" warn " strategy = GitHub::Ldap::MembershipValidators::Recursive.new \\" warn " ldap, depth: 5" warn " strategy#perform(entry)" end # short circuit validation if there are no groups to check against return true if groups.empty? domains.each do |domain| # find groups entry is an immediate member of membership = domain.search(filter: member_filter(entry), attributes: ATTRS) # success if any of these groups match the restricted auth groups return true if membership.any? { |entry| group_dns.include?(entry.dn) } # give up if the entry has no memberships to recurse next if membership.empty? # recurse to at most `depth` (depth_override || depth).times do |n| # find groups whose members include membership groups membership = domain.search(filter: membership_filter(membership), attributes: ATTRS) # success if any of these groups match the restricted auth groups return true if membership.any? { |entry| group_dns.include?(entry.dn) } # give up if there are no more membersips to recurse break if membership.empty? end # give up on this base if there are no memberships to test next if membership.empty? end false end |