group.rb 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. class Ldap
  2. # Class for handling LDAP Groups.
  3. # ATTENTION: Make sure to add the following lines to your code if accessing this class.
  4. # Otherwise Rails will autoload the Group model or might throw parameter errors if crearing
  5. # an ::Ldap instance.
  6. #
  7. # @example
  8. # require 'ldap'
  9. # require 'ldap/group'
  10. class Group
  11. include Ldap::FilterLookup
  12. # Returns the uid attribute.
  13. #
  14. # @example
  15. # Ldap::Group.uid_attribute
  16. #
  17. # @return [String] The uid attribute.
  18. def self.uid_attribute
  19. 'dn'
  20. end
  21. # Initializes a wrapper around Net::LDAP and ::Ldap to handle LDAP groups.
  22. #
  23. # @param [Hash] config the configuration for establishing a LDAP connection. Default is Setting 'ldap_config'.
  24. # @option config [String] :uid_attribute The uid attribute. Default is determined automatically.
  25. # @option config [String] :filter The filter for LDAP groups. Default is determined automatically.
  26. # @param ldap [Ldap] An optional existing Ldap class instance. Default is a new connection with given configuration.
  27. #
  28. # @example
  29. # require 'ldap'
  30. # require 'ldap/group'
  31. # ldap_group = Ldap::Group.new
  32. #
  33. # @return [nil]
  34. def initialize(config = nil, ldap: nil)
  35. @ldap = ldap || ::Ldap.new(config)
  36. handle_config(config)
  37. end
  38. # Lists available LDAP groups.
  39. #
  40. # @param filter [String] The filter for listing groups. Default is initialization parameter.
  41. # @param base_dn [String] The applied base DN for listing groups. Default is Ldap#base_dn.
  42. #
  43. # @example
  44. # ldap_group.list
  45. # #=> {"cn=zamamd role admin,ou=zamamd groups,ou=test,dc=domain,dc=tld"=>"cn=zamamd role admin,ou=zamamd groups,ou=test,dc=domain,dc=tld", ...}
  46. #
  47. # @return [Hash{String=>String}] List of available LDAP groups.
  48. def list(filter: nil, base_dn: nil)
  49. filter ||= filter()
  50. # don't start a search if no filter was found
  51. return {} if filter.blank?
  52. groups = {}
  53. @ldap.search(filter, base: base_dn, attributes: %w[dn]) do |entry|
  54. groups[entry.dn.downcase] = entry.dn.downcase
  55. end
  56. groups
  57. end
  58. # Creates a mapping for user DN and local role IDs based on a given group DN to local role ID mapping.
  59. #
  60. # @param mapping [Hash{String=>String}] The group DN to local role mapping.
  61. # @param filter [String] The filter for finding groups. Default is initialization parameter.
  62. #
  63. # @example
  64. # mapping = {"cn=access control assistance operators,cn=builtin,dc=domain,dc=tld"=>"1", ...}
  65. # ldap_group.user_roles(mapping)
  66. # #=> {"cn=s-1-5-11,cn=foreignsecurityprincipals,dc=domain,dc=tld"=>[1, 2], ...}
  67. #
  68. # @return [Hash{String=>Array<Number>}] The user DN to local role IDs mapping.
  69. def user_roles(mapping, filter: nil)
  70. filter ||= filter()
  71. result = {}
  72. @ldap.search(filter, attributes: %w[dn member memberuid uniquemember]) do |entry|
  73. roles = mapping[entry.dn.downcase]
  74. next if roles.blank?
  75. members = group_user_dns(entry)
  76. next if members.blank?
  77. members.each do |user_dn|
  78. user_dn_key = user_dn.downcase
  79. roles.each do |role|
  80. role = role.to_i
  81. result[user_dn_key] ||= []
  82. next if result[user_dn_key].include?(role)
  83. result[user_dn_key].push(role)
  84. end
  85. end
  86. end
  87. result
  88. end
  89. # The active filter of the instance. If none give on initialization an automatic lookup is performed.
  90. #
  91. # @example
  92. # ldap_group.filter
  93. # #=> '(objectClass=group)'
  94. #
  95. # @return [String, nil] The active or found filter or nil if none could be found.
  96. def filter
  97. @filter ||= lookup_filter(['(objectClass=groupOfUniqueNames)', '(objectClass=group)', '(objectClass=posixgroup)', '(objectClass=organization)'])
  98. end
  99. # The active uid attribute of the instance. If none give on initialization an automatic lookup is performed.
  100. #
  101. # @example
  102. # ldap_group.uid_attribute
  103. # #=> 'dn'
  104. #
  105. # @return [String, nil] The active or found uid attribute or nil if none could be found.
  106. def uid_attribute
  107. @uid_attribute ||= self.class.uid_attribute
  108. end
  109. private
  110. def handle_config(config)
  111. return if config.blank?
  112. @uid_attribute = config[:uid_attribute]
  113. @filter = config[:filter]
  114. end
  115. def group_user_dns(entry)
  116. return entry[:member] if entry[:member].present?
  117. return group_user_dns_memberuid(entry) if entry[:memberuid].present?
  118. return entry[:uniquemember] if entry[:uniquemember].present?
  119. end
  120. def group_user_dns_memberuid(entry)
  121. entry[:memberuid].collect do |uid|
  122. dn = nil
  123. @ldap.search("(uid=#{uid})", attributes: %w[dn]) do |user|
  124. dn = user.dn
  125. end
  126. dn
  127. end.compact
  128. end
  129. end
  130. end