lib/pg_ldap_sync/application.rb in pg-ldap-sync-0.3.0 vs lib/pg_ldap_sync/application.rb in pg-ldap-sync-0.4.0

- old
+ new

@@ -50,17 +50,22 @@ LdapRole = Struct.new :name, :dn, :member_dns def search_ldap_users ldap_user_conf = @config[:ldap_users] + name_attribute = ldap_user_conf[:name_attribute] users = [] - res = @ldap.search(:base => ldap_user_conf[:base], :filter => ldap_user_conf[:filter]) do |entry| - name = entry[ldap_user_conf[:name_attribute]].first + res = @ldap.search( + base: ldap_user_conf[:base], + filter: ldap_user_conf[:filter], + attributes: [name_attribute, :dn] + ) do |entry| + name = entry[name_attribute].first unless name - log.warn "user attribute #{ldap_user_conf[:name_attribute].inspect} not defined for #{entry.dn}" + log.warn "user attribute #{name_attribute.inspect} not defined for #{entry.dn}" next end log.info "found user-dn: #{entry.dn}" names = if ldap_user_conf[:bothcase_name] @@ -83,21 +88,60 @@ end raise LdapError, "LDAP: #{@ldap.get_operation_result.message}" unless res return users end + def retrieve_array_attribute(entry, attribute_name) + array = entry[attribute_name] + if array.empty? + # Possibly an attribute, which must be retrieved in several ranges + + ranged_attr = entry.attribute_names.find { |n| n =~ /\A#{Regexp.escape(attribute_name)};range=/ } + if ranged_attr + entry_dn = entry.dn + + loop do + array += entry[ranged_attr] + log.debug "retrieved attribute range #{ranged_attr.inspect} of dn #{entry_dn}" + + if ranged_attr =~ /;range=\d\-\*\z/ + break + end + + attribute_with_range = ranged_attr.to_s.gsub(/;range=.*/, ";range=#{array.size}-*") + entry = @ldap.search( + base: entry_dn, + scope: Net::LDAP::SearchScope_BaseObject, + attributes: attribute_with_range).first + + ranged_attr = entry.attribute_names.find { |n| n =~ /\A#{Regexp.escape(attribute_name)};range=/ } + end + end + else + # Values already received -> No ranged attribute + end + return array + end + def search_ldap_groups ldap_group_conf = @config[:ldap_groups] + name_attribute = ldap_group_conf[:name_attribute] + member_attribute = ldap_group_conf[:member_attribute] groups = [] - res = @ldap.search(:base => ldap_group_conf[:base], :filter => ldap_group_conf[:filter]) do |entry| - name = entry[ldap_group_conf[:name_attribute]].first + res = @ldap.search( + base: ldap_group_conf[:base], + filter: ldap_group_conf[:filter], + attributes: [name_attribute, member_attribute, :dn] + ) do |entry| + name = entry[name_attribute].first unless name - log.warn "user attribute #{ldap_group_conf[:name_attribute].inspect} not defined for #{entry.dn}" + log.warn "user attribute #{name_attribute.inspect} not defined for #{entry.dn}" next end + log.info "found group-dn: #{entry.dn}" names = if ldap_group_conf[:bothcase_name] [name, name.downcase].uniq elsif ldap_group_conf[:lowercase_name] @@ -105,11 +149,12 @@ else [name] end names.each do |n| - groups << LdapRole.new(n, entry.dn, entry[ldap_group_conf[:member_attribute]]) + group_members = retrieve_array_attribute(entry, member_attribute) + groups << LdapRole.new(n, entry.dn, group_members) end entry.each do |attribute, values| log.debug " #{attribute}:" values.each do |value| log.debug " --->#{value.inspect}" @@ -121,11 +166,11 @@ end PgRole = Struct.new :name, :member_names # List of default roles taken from https://www.postgresql.org/docs/current/predefined-roles.html - PG_BUILTIN_ROLES = %w[ pg_read_all_data pg_write_all_data pg_read_all_settings pg_read_all_stats pg_stat_scan_tables pg_monitor pg_database_owner pg_signal_backend pg_read_server_files pg_write_server_files pg_execute_server_program ] + PG_BUILTIN_ROLES = %w[ pg_read_all_data pg_write_all_data pg_read_all_settings pg_read_all_stats pg_stat_scan_tables pg_monitor pg_database_owner pg_signal_backend pg_read_server_files pg_write_server_files pg_execute_server_program pg_checkpoint] def search_pg_users pg_users_conf = @config[:pg_users] users = [] @@ -346,17 +391,17 @@ @pgconn.close end # Determine exitcode if log.had_errors? - raise ErrorExit, 1 + raise ErrorExit.new(1, log.first_error) end end def self.run(argv) s = self.new s.config_fname = '/etc/pg_ldap_sync.yaml' - s.log = Logger.new($stdout, @error_counters) + s.log = Logger.new($stdout) s.log.level = Logger::ERROR OptionParser.new do |opts| opts.version = VERSION opts.banner = "Usage: #{$0} [options]"