From 81473fb2b45a612a935b192a2a0c0564dddf86d3 Mon Sep 17 00:00:00 2001 From: Lars Kanis Date: Thu, 1 Dec 2022 15:21:39 +0100 Subject: [PATCH] Re-add support for attribute ranges This is an alternative implementation of #37 . It doesn't need additional configuration, but enables range retrieval automatic. It also add some testing. Fixes #32 --- Gemfile | 5 ++++ lib/pg_ldap_sync/application.rb | 42 ++++++++++++++++++++++++++++++--- test/fixtures/ldapdb.yaml | 4 ++++ test/ldap_server.rb | 3 +-- test/test_pg_ldap_sync.rb | 5 ++-- 5 files changed, 52 insertions(+), 7 deletions(-) diff --git a/Gemfile b/Gemfile index dfa2a95..8ab954d 100644 --- a/Gemfile +++ b/Gemfile @@ -2,3 +2,8 @@ source "https://rubygems.org" # Specify your gem's dependencies in pg_ldap_sync.gemspec gemspec + +group :development do + gem "debug" + gem "ruby-ldapserver", git: "https://github.com/larskanis/ruby-ldapserver/" +end diff --git a/lib/pg_ldap_sync/application.rb b/lib/pg_ldap_sync/application.rb index d68c858..252140b 100644 --- a/lib/pg_ldap_sync/application.rb +++ b/lib/pg_ldap_sync/application.rb @@ -85,17 +85,52 @@ class Application 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 + 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] @@ -107,7 +142,8 @@ class Application 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}:" diff --git a/test/fixtures/ldapdb.yaml b/test/fixtures/ldapdb.yaml index cac7e90..08438c3 100644 --- a/test/fixtures/ldapdb.yaml +++ b/test/fixtures/ldapdb.yaml @@ -2,6 +2,9 @@ dc=example,dc=com: cn: - Top object +cn=Unknown Flintstone,dc=example,dc=com: + cn: + - Unknown Flintstone cn=Fred Flintstone,dc=example,dc=com: cn: - Fred Flintstone @@ -36,3 +39,4 @@ cn=All Users,dc=example,dc=com: member: - cn=Wilmas,dc=example,dc=com - cn=Fred Flintstone,dc=example,dc=com + - cn=Unknown Flintstone,dc=example,dc=com diff --git a/test/ldap_server.rb b/test/ldap_server.rb index 3bb1d4f..b89158e 100644 --- a/test/ldap_server.rb +++ b/test/ldap_server.rb @@ -17,11 +17,10 @@ class HashOperation < LDAP::Server::Operation def search(basedn, scope, deref, filter) basedn.downcase! - case scope when LDAP::Server::BaseObject # client asked for single object by DN - obj = @hash[basedn] + obj = @hash.transform_keys(&:downcase)[basedn] raise LDAP::ResultError::NoSuchObject unless obj send_SearchResultEntry(basedn, obj) if LDAP::Server::Filter.run(filter, obj) diff --git a/test/test_pg_ldap_sync.rb b/test/test_pg_ldap_sync.rb index 245e3bb..65a5aae 100644 --- a/test/test_pg_ldap_sync.rb +++ b/test/test_pg_ldap_sync.rb @@ -41,7 +41,8 @@ class TestPgLdapSync < Minitest::Test # :ssl_cert_file => "cert.pem", # :ssl_on_connect => true, :operation_class => HashOperation, - :operation_args => @directory + :operation_args => @directory, + :attribute_range_limit => 2 ) @ldap_server.run_tcpserver end @@ -122,7 +123,7 @@ class TestPgLdapSync < Minitest::Test end def sync_with_config(config="config-ldapdb") - PgLdapSync::Application.run(["-c", "test/fixtures/#{config}.yaml"] + ($DEBUG ? ["-vv"] : ["--no-verbose"])) + PgLdapSync::Application.run(["-c", "test/fixtures/#{config}.yaml"] + ($DEBUG ? ["-vvv"] : ["--no-verbose"])) end def sync_to_fixture(fixture: "ldapdb", config: "config-ldapdb")