From b15c99fe1b1f7b592fb7b3749ea766e229945b3a Mon Sep 17 00:00:00 2001 From: Andrew Ruthven Date: Sat, 3 Feb 2024 17:43:10 +1300 Subject: [PATCH] Add tests for LDAP sync of users and groups. --- testing/regression-conf.php.example | 31 +++-- .../ldap/0000-confirm-no-ldap1-user.test | 6 +- .../tests/ldap/0002-test-invalid-user.test | 11 +- testing/tests/ldap/0003-sync-ldap.result | 119 +++++++++++++++++ testing/tests/ldap/0003-sync-ldap.test | 112 ++++++++++++++++ .../tests/ldap/0004-sync-ldap-changes.result | 122 +++++++++++++++++ .../tests/ldap/0004-sync-ldap-changes.test | 125 ++++++++++++++++++ ...test-ldap.result => 0005-test-ldap.result} | 12 +- ...001-test-ldap.test => 0005-test-ldap.test} | 24 +--- 9 files changed, 521 insertions(+), 41 deletions(-) create mode 100644 testing/tests/ldap/0003-sync-ldap.result create mode 100644 testing/tests/ldap/0003-sync-ldap.test create mode 100644 testing/tests/ldap/0004-sync-ldap-changes.result create mode 100644 testing/tests/ldap/0004-sync-ldap-changes.test rename testing/tests/ldap/{0001-test-ldap.result => 0005-test-ldap.result} (86%) rename testing/tests/ldap/{0001-test-ldap.test => 0005-test-ldap.test} (77%) diff --git a/testing/regression-conf.php.example b/testing/regression-conf.php.example index 27223c30..69de7d72 100644 --- a/testing/regression-conf.php.example +++ b/testing/regression-conf.php.example @@ -29,18 +29,29 @@ //ldap $c->authenticate_hook['config'] = array( //ldap 'host' => 'localhost', //ldap 'port' => '21394', - //ldap 'baseDNUsers' => 'dc=example,dc=com', - //ldap 'mapping_field' => array("username" => "uid", - //ldap "modified" => "modifyTimestamp", - //ldap "fullname" => "cn" , - //ldap "email" =>"mail" + //ldap 'protocolVersion' => 3, + //ldap 'baseDNUsers' => 'ou=users,dc=example,dc=com', + //ldap 'baseDNGroups' => 'ou=groups,dc=example,dc=com', + //ldap 'mapping_field' => array( + //ldap "username" => "uid", + //ldap "modified" => "modifyTimestamp", + //ldap "fullname" => "cn", + //ldap "email" => "mail" //ldap ), - //ldap 'group_mapping_field' => array("username" => "cn", - //ldap "modified" => "modifyTimestamp", - //ldap "fullname" => "cn" , - //ldap "members" =>"memberUid" + //ldap 'group_mapping_field' => array( + //ldap "username" => "cn", + //ldap "modified" => "modifyTimestamp", + //ldap "fullname" => "cn" , + //ldap "members" => "memberUid", //ldap ), - //ldap 'format_updated' => array('Y' => array(0,4), 'm' => array(4,2), 'd' => array(6,2), 'H' => array(8,2), 'M' => array(10,2), 'S' => array(12,2)) + //ldap 'format_updated' => array( + //ldap 'Y' => array(0,4), + //ldap 'm' => array(4,2), + //ldap 'd' => array(6,2), + //ldap 'H' => array(8,2), + //ldap 'M' => array(10,2), + //ldap 'S' => array(12,2) + //ldap ) //ldap ); //ldap include('drivers_ldap.php'); diff --git a/testing/tests/ldap/0000-confirm-no-ldap1-user.test b/testing/tests/ldap/0000-confirm-no-ldap1-user.test index 8bd8893f..e1323a8a 100644 --- a/testing/tests/ldap/0000-confirm-no-ldap1-user.test +++ b/testing/tests/ldap/0000-confirm-no-ldap1-user.test @@ -1,6 +1,6 @@ -# Check that no usr record exists +# Check that no ldap usr records exist QUERY -SELECT active ,email, fullname, last_used, password, username, user_no +SELECT active, email, fullname, last_used, password, username, user_no FROM usr -WHERE username = 'ldap1'; +WHERE username LIKE 'ldap%'; ENDQUERY diff --git a/testing/tests/ldap/0002-test-invalid-user.test b/testing/tests/ldap/0002-test-invalid-user.test index 75bbd17e..620a4284 100644 --- a/testing/tests/ldap/0002-test-invalid-user.test +++ b/testing/tests/ldap/0002-test-invalid-user.test @@ -1,3 +1,9 @@ +# Copyright (c) 2021-2024 Andrew Ruthven +# Portions Copyright (c) Best Practical Solutions, LLC +# , licensed under the GPL v2. +# +# Test with LDAP auth logging in as a user which is in neither the DB +# or LDAP. BEGINPERL if ($debug) { $ENV{'LDAP_DEBUG'} = 1 }; @@ -5,9 +11,6 @@ use Net::LDAP::Server::Test; use Net::LDAP; use IO::Socket::INET; -#my $port = find_idle_port(); - -#my $ldap_port = RT::Test->find_idle_port; my $ldap_port = 21394; my $ldap_socket = IO::Socket::INET->new( Listen => 5, @@ -58,7 +61,7 @@ ENDDATA # Check that no usr record has been created. QUERY SELECT active, email, fullname, last_used, password, username, user_no -FROM usr +FROM usr WHERE username = 'ldap2'; ENDQUERY diff --git a/testing/tests/ldap/0003-sync-ldap.result b/testing/tests/ldap/0003-sync-ldap.result new file mode 100644 index 00000000..1bffbba9 --- /dev/null +++ b/testing/tests/ldap/0003-sync-ldap.result @@ -0,0 +1,119 @@ +HTTP/1.1 207 Multi-Status +Date: Dow, 01 Jan 2000 00:00:00 GMT +DAV: 1, 2, 3, access-control, calendar-access, calendar-schedule +DAV: extended-mkcol, bind, addressbook, calendar-auto-schedule, calendar-proxy +ETag: "ed58709591152964fd4a584af5b55d79" +Content-Length: 942 +Content-Type: text/xml; charset="utf-8" + + + + + /caldav.php/ + + + + + + + HTTP/1.1 200 OK + + + + /caldav.php/resource1/ + + + + + + + + HTTP/1.1 200 OK + + + + /caldav.php/resource2/ + + + + + + + + HTTP/1.1 200 OK + + + + /caldav.php/ldap1/ + + + + + + + + HTTP/1.1 200 OK + + + + + active: >1< + email: >ldap1@example.com< + fullname: >LDAP 1< + last_used: >NULL< + password: >NULL< + user_no: >1001< + username: >ldap1< + + active: >1< + email: >ldap2@example.com< + fullname: >LDAP 2< + last_used: >NULL< + password: >NULL< + user_no: >1002< + username: >ldap2< + + active: >1< + email: >NULL< + fullname: >ldap_group1< + last_used: >NULL< + password: >NULL< + user_no: >1003< + username: >ldap_group1< + + active: >1< + email: >NULL< + fullname: >ldap_group2< + last_used: >NULL< + password: >NULL< + user_no: >1004< + username: >ldap_group2< + + active: >1< + email: >NULL< + fullname: >ldap_group3< + last_used: >NULL< + password: >NULL< + user_no: >1005< + username: >ldap_group3< + + active: >1< + email: >NULL< + fullname: >ldap_group4< + last_used: >NULL< + password: >NULL< + user_no: >1006< + username: >ldap_group4< + + group_name: >ldap_group1< + user_name: >ldap1< + + group_name: >ldap_group2< + user_name: >ldap2< + + group_name: >ldap_group3< + user_name: >NULL< + + group_name: >ldap_group4< + user_name: >NULL< + diff --git a/testing/tests/ldap/0003-sync-ldap.test b/testing/tests/ldap/0003-sync-ldap.test new file mode 100644 index 00000000..777eb789 --- /dev/null +++ b/testing/tests/ldap/0003-sync-ldap.test @@ -0,0 +1,112 @@ +# Copyright (c) 2021-2024 Andrew Ruthven +# Portions Copyright (c) Best Practical Solutions, LLC +# , licensed under the GPL v2. +# +BEGINPERL +if ($debug) { $ENV{'LDAP_DEBUG'} = 1 }; + +use Net::LDAP::Server::Test; +use Net::LDAP; +use IO::Socket::INET; + +my $ldap_port = 21394; +my $ldap_socket = IO::Socket::INET->new( + Listen => 5, + Proto => 'tcp', + Reuse => 1, + LocalPort => $ldap_port, +); + +# Keep it around after this block exits. +$evaled{'ldap_server'} = Net::LDAP::Server::Test->new( $ldap_socket, auto_schema => 1 ); + +my $ldap = Net::LDAP->new("localhost:$ldap_port") || die "Failed to instantiate Net::LDAP: $!"; +$ldap->bind(); +my $base = "dc=example,dc=com"; +my $users = "ou=users,$base"; +my $groups = "ou=groups,$base"; +$ldap->add( $base ); + +for my $username (qw/ldap1 ldap2/) { + my $dn = "uid=$username,$users"; + (my $cn = $username) =~ s/ldap(\d+)/LDAP $1/; + my $entry = { + cn => $cn, + mail => "$username\@example.com", + uid => $username, + objectClass => 'User', + userPassword => $username, + modifyTimestamp => 20240203001020, + }; + $ldap->add( $dn, attr => [%$entry] ); +} + +for my $group (qw/ldap_group1 ldap_group2/) { + my $dn = "cn=$group,$groups"; + (my $member = $group) =~ s/_group//; + my $entry = { + cn => $group, + objectClass => 'groupofNames', + memberUid => $member, + modifyTimestamp => 20240203001020, + }; + $ldap->add( $dn, attr => [%$entry] ); +} + +# Create some empty groups. +for my $group (qw/ldap_group3 ldap_group4/) { + my $dn = "cn=$group,$groups"; + my $entry = { + cn => $group, + objectClass => 'groupofNames', + modifyTimestamp => 20240203001020, + }; + $ldap->add( $dn, attr => [%$entry] ); +} + + +# We need to keep the client around, otherwise the test server will exit. +$evaled{'ldap_client'} = $ldap; +#sleep 60; +ENDPERL + +SCRIPT=../scripts/cron-sync-ldap.php regression_ldap.host + +# Testing logging in as one of the users - should work. +TYPE=PROPFIND +URL=http://regression_ldap.host/caldav.php/ +HEADER=Content-Type: text/xml +HEADER=Depth: 1 +AUTH=ldap1:ldap1 +HEAD + +BEGINDATA + + + + + + +ENDDATA + + +# Check that a usr record has been created for all users and groups +QUERY +SELECT active, email, fullname, last_used, password, username, user_no +FROM usr +WHERE username LIKE 'ldap%' +ORDER BY username; +ENDQUERY + +# Check that ldap1 is a member of ldap_qroup1 and ldap2 is a member of +# ldap_group2, and that ldap_group3 is empty. +QUERY +SELECT grp_u.username AS group_name, usr_u.username AS user_name +FROM principal AS grp_p + left join group_member ON (grp_p.principal_id = group_member.group_id) + left join principal AS usr_p ON (group_member.member_id = usr_p.principal_id) + left join usr AS usr_u ON (usr_p.user_no = usr_u.user_no) + left join usr AS grp_u ON (grp_p.user_no = grp_u.user_no) +WHERE grp_u.username LIKE 'ldap_group%' +ORDER BY group_name, user_name; +ENDQUERY diff --git a/testing/tests/ldap/0004-sync-ldap-changes.result b/testing/tests/ldap/0004-sync-ldap-changes.result new file mode 100644 index 00000000..46ee9b73 --- /dev/null +++ b/testing/tests/ldap/0004-sync-ldap-changes.result @@ -0,0 +1,122 @@ +HTTP/1.1 207 Multi-Status +Date: Dow, 01 Jan 2000 00:00:00 GMT +DAV: 1, 2, 3, access-control, calendar-access, calendar-schedule +DAV: extended-mkcol, bind, addressbook, calendar-auto-schedule, calendar-proxy +ETag: "ed58709591152964fd4a584af5b55d79" +Content-Length: 942 +Content-Type: text/xml; charset="utf-8" + + + + + /caldav.php/ + + + + + + + HTTP/1.1 200 OK + + + + /caldav.php/resource1/ + + + + + + + + HTTP/1.1 200 OK + + + + /caldav.php/resource2/ + + + + + + + + HTTP/1.1 200 OK + + + + /caldav.php/ldap1/ + + + + + + + + HTTP/1.1 200 OK + + + + + active: >1< + email: >ldap1@example.com< + fullname: >LDAP 1< + last_used: >NULL< + password: >NULL< + user_no: >1001< + username: >ldap1< + + active: >1< + email: >ldap2@example.com< + fullname: >LDAP 2< + last_used: >NULL< + password: >NULL< + user_no: >1002< + username: >ldap2< + + active: >1< + email: >NULL< + fullname: >ldap_group1< + last_used: >NULL< + password: >NULL< + user_no: >1003< + username: >ldap_group1< + + active: >1< + email: >NULL< + fullname: >ldap_group2< + last_used: >NULL< + password: >NULL< + user_no: >1004< + username: >ldap_group2< + + active: >1< + email: >NULL< + fullname: >ldap_group3< + last_used: >NULL< + password: >NULL< + user_no: >1005< + username: >ldap_group3< + + active: >1< + email: >NULL< + fullname: >ldap_group4< + last_used: >NULL< + password: >NULL< + user_no: >1006< + username: >ldap_group4< + + group_name: >ldap_group1< + user_name: >ldap2< + + group_name: >ldap_group2< + user_name: >ldap1< + + group_name: >ldap_group2< + user_name: >ldap2< + + group_name: >ldap_group3< + user_name: >ldap1< + + group_name: >ldap_group4< + user_name: >NULL< + diff --git a/testing/tests/ldap/0004-sync-ldap-changes.test b/testing/tests/ldap/0004-sync-ldap-changes.test new file mode 100644 index 00000000..51e4050f --- /dev/null +++ b/testing/tests/ldap/0004-sync-ldap-changes.test @@ -0,0 +1,125 @@ +# Copyright (c) 2021-2024 Andrew Ruthven +# Portions Copyright (c) Best Practical Solutions, LLC +# , licensed under the GPL v2. +# +# In this test we create LDAP records that are slightly different from +# the previous test to make sure that changes are reflected. +# +# Database will start with: +# ldap_group1: ldap1 +# ldap_group2: ldap2 +# ldap_group3: +# ldap_group4: ldap1 +# +# We will change that to: +# ldap_group1: ldap2 +# ldap_group2: ldap1, ldap2 +# ldap_group3: ldap1 +# ldap_group4: +# +BEGINPERL +if ($debug) { $ENV{'LDAP_DEBUG'} = 1 }; + +use Net::LDAP::Server::Test; +use Net::LDAP; +use IO::Socket::INET; + +my $ldap_port = 21394; +my $ldap_socket = IO::Socket::INET->new( + Listen => 5, + Proto => 'tcp', + Reuse => 1, + LocalPort => $ldap_port, +); + +# Keep it around after this block exits. +$evaled{'ldap_server'} = Net::LDAP::Server::Test->new( $ldap_socket, auto_schema => 1 ); + +my $ldap = Net::LDAP->new("localhost:$ldap_port") || die "Failed to instantiate Net::LDAP: $!"; +$ldap->bind(); +my $base = "dc=example,dc=com"; +my $users = "ou=users,$base"; +my $groups = "ou=groups,$base"; +$ldap->add( $base ); + +for my $username (qw/ldap1 ldap2/) { + my $dn = "uid=$username,$users"; + (my $cn = $username) =~ s/ldap(\d+)/LDAP $1/; + my $entry = { + cn => $cn, + mail => "$username\@example.com", + uid => $username, + objectClass => 'User', + userPassword => $username, + modifyTimestamp => 20240203001020, + }; + $ldap->add( $dn, attr => [%$entry] ); +} + +make_group($ldap, 'ldap_group1', 'ldap2'); +make_group($ldap, 'ldap_group2', 'ldap1', 'ldap2'); +make_group($ldap, 'ldap_group3', 'ldap1'); +make_group($ldap, 'ldap_group4'); + +# We need to keep the client around, otherwise the test server will exit. +$evaled{'ldap_client'} = $ldap; +sleep 60; + +sub make_group { + my $ldap = shift; + my $name = shift; + my @users = @_; + + my $dn = "cn=$name,$groups"; + my $entry = { + cn => $name, + objectClass => 'groupofNames', + (@users + ? (memberUid => [ @users ]) + : () + ), + modifyTimestamp => 20240203001020, + }; + $ldap->add( $dn, attr => [%$entry] ); +} +ENDPERL + +SCRIPT=../scripts/cron-sync-ldap.php regression_ldap.host + +# Testing logging in as one of the users - should work. +TYPE=PROPFIND +URL=http://regression_ldap.host/caldav.php/ +HEADER=Content-Type: text/xml +HEADER=Depth: 1 +AUTH=ldap1:ldap1 +HEAD + +BEGINDATA + + + + + + +ENDDATA + +# Check that a usr record has been created for all users and groups +QUERY +SELECT active, email, fullname, last_used, password, username, user_no +FROM usr +WHERE username LIKE 'ldap%' +ORDER BY username; +ENDQUERY + +# Check that ldap1 is a member of ldap_qroup1 and ldap2 is a member of +# ldap_group2, and that ldap_group3 is empty. +QUERY +SELECT grp_u.username AS group_name, usr_u.username AS user_name +FROM principal AS grp_p + left join group_member ON (grp_p.principal_id = group_member.group_id) + left join principal AS usr_p ON (group_member.member_id = usr_p.principal_id) + left join usr AS usr_u ON (usr_p.user_no = usr_u.user_no) + left join usr AS grp_u ON (grp_p.user_no = grp_u.user_no) +WHERE grp_u.username LIKE 'ldap_group%' +ORDER BY group_name, user_name; +ENDQUERY diff --git a/testing/tests/ldap/0001-test-ldap.result b/testing/tests/ldap/0005-test-ldap.result similarity index 86% rename from testing/tests/ldap/0001-test-ldap.result rename to testing/tests/ldap/0005-test-ldap.result index 2fedb1a2..e8434050 100644 --- a/testing/tests/ldap/0001-test-ldap.result +++ b/testing/tests/ldap/0005-test-ldap.result @@ -2,7 +2,7 @@ HTTP/1.1 207 Multi-Status Date: Dow, 01 Jan 2000 00:00:00 GMT DAV: 1, 2, 3, access-control, calendar-access, calendar-schedule DAV: extended-mkcol, bind, addressbook, calendar-auto-schedule, calendar-proxy -ETag: "ed58709591152964fd4a584af5b55d79" +ETag: "dc507be383f0899568adb9d02a1ddb03" Content-Length: 942 Content-Type: text/xml; charset="utf-8" @@ -44,7 +44,7 @@ Content-Type: text/xml; charset="utf-8" - /caldav.php/ldap1/ + /caldav.php/ldap3/ @@ -58,10 +58,10 @@ Content-Type: text/xml; charset="utf-8" active: >1< - email: >ldap1@example.com< - fullname: >ldap1< + email: >ldap3@example.com< + fullname: >ldap3< last_used: >NULL< password: >NULL< - user_no: >1001< - username: >ldap1< + user_no: >1007< + username: >ldap3< diff --git a/testing/tests/ldap/0001-test-ldap.test b/testing/tests/ldap/0005-test-ldap.test similarity index 77% rename from testing/tests/ldap/0001-test-ldap.test rename to testing/tests/ldap/0005-test-ldap.test index bb893ab1..bf9c0dd3 100644 --- a/testing/tests/ldap/0001-test-ldap.test +++ b/testing/tests/ldap/0005-test-ldap.test @@ -2,6 +2,8 @@ # Portions Copyright (c) Best Practical Solutions, LLC # , licensed under the GPL v2. # +# Test logging in using an LDAP user that doesn't exist in the +# database, should be copied over. BEGINPERL if ($debug) { $ENV{'LDAP_DEBUG'} = 1 }; @@ -9,9 +11,6 @@ use Net::LDAP::Server::Test; use Net::LDAP; use IO::Socket::INET; -#my $port = find_idle_port(); - -#my $ldap_port = RT::Test->find_idle_port; my $ldap_port = 21394; my $ldap_socket = IO::Socket::INET->new( Listen => 5, @@ -30,7 +29,7 @@ my $users = "ou=users,$base"; my $groups = "ou=groups,$base"; $ldap->add( $base ); -for my $username (qw/ldap1 ldap2/) { +for my $username (qw/ldap3 ldap4/) { my $dn = "uid=$username,$users"; my $entry = { cn => $username, @@ -42,17 +41,6 @@ for my $username (qw/ldap1 ldap2/) { $ldap->add( $dn, attr => [%$entry] ); } -for my $group (qw/group1 group2/) { - my $dn = "cn=$group,$groups"; - (my $member = $group) =~ s/group/ldap/; - my $entry = { - cn => $group, - objectClass => 'groupofNames', - member => "cn=$member,$users", - }; - $ldap->add( $dn, attr => [%$entry] ); -} - # We need to keep the client around, otherwise the test server will exit. $evaled{'ldap_client'} = $ldap; #sleep 100; @@ -62,7 +50,7 @@ TYPE=PROPFIND URL=http://regression_ldap.host/caldav.php/ HEADER=Content-Type: text/xml HEADER=Depth: 1 -AUTH=ldap1:ldap1 +AUTH=ldap3:ldap3 HEAD BEGINDATA @@ -77,7 +65,7 @@ ENDDATA # Check that a usr record has been created. QUERY SELECT active, email, fullname, last_used, password, username, user_no -FROM usr -WHERE username = 'ldap1'; +FROM usr +WHERE username = 'ldap3'; ENDQUERY