|
| 1 | +# BEGIN BPS TAGGED BLOCK {{{ |
| 2 | +# |
| 3 | +# COPYRIGHT: |
| 4 | +# |
| 5 | +# This software is Copyright (c) 1996-2023 Best Practical Solutions, LLC |
| 6 | +# <sales@bestpractical.com> |
| 7 | +# |
| 8 | +# (Except where explicitly superseded by other copyright notices) |
| 9 | +# |
| 10 | +# |
| 11 | +# LICENSE: |
| 12 | +# |
| 13 | +# This work is made available to you under the terms of Version 2 of |
| 14 | +# the GNU General Public License. A copy of that license should have |
| 15 | +# been provided with this software, but in any event can be snarfed |
| 16 | +# from www.gnu.org. |
| 17 | +# |
| 18 | +# This work is distributed in the hope that it will be useful, but |
| 19 | +# WITHOUT ANY WARRANTY; without even the implied warranty of |
| 20 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 21 | +# General Public License for more details. |
| 22 | +# |
| 23 | +# You should have received a copy of the GNU General Public License |
| 24 | +# along with this program; if not, write to the Free Software |
| 25 | +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
| 26 | +# 02110-1301 or visit their web page on the internet at |
| 27 | +# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. |
| 28 | +# |
| 29 | +# |
| 30 | +# CONTRIBUTION SUBMISSION POLICY: |
| 31 | +# |
| 32 | +# (The following paragraph is not intended to limit the rights granted |
| 33 | +# to you to modify and distribute this software under the terms of |
| 34 | +# the GNU General Public License and is only of importance to you if |
| 35 | +# you choose to contribute your changes and enhancements to the |
| 36 | +# community by submitting them to Best Practical Solutions, LLC.) |
| 37 | +# |
| 38 | +# By intentionally submitting any modifications, corrections or |
| 39 | +# derivatives to this work, or any other work intended for use with |
| 40 | +# Request Tracker, to Best Practical Solutions, LLC, you confirm that |
| 41 | +# you are the copyright holder for those contributions and you grant |
| 42 | +# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, |
| 43 | +# royalty-free, perpetual, license to use, copy, create derivative |
| 44 | +# works based on those contributions, and sublicense and distribute |
| 45 | +# those contributions and any derivatives thereof. |
| 46 | +# |
| 47 | +# END BPS TAGGED BLOCK }}} |
| 48 | + |
| 49 | +# Portions Copyright 2023 Andrew Ruthven <andrew@etc.gen.nz> |
| 50 | + |
| 51 | +package RT::Test::LDAP; |
| 52 | + |
| 53 | +use strict; |
| 54 | +use warnings; |
| 55 | +use IO::Socket::INET; |
| 56 | + |
| 57 | +use base 'RT::Test'; |
| 58 | + |
| 59 | +sub new { |
| 60 | + my $proto = shift; |
| 61 | + my %options = @_; |
| 62 | + my $class = ref($proto) ? ref($proto) : $proto; |
| 63 | + my $self = bless { |
| 64 | + ldap_ip => '127.0.0.1', |
| 65 | + base_dn => $options{base_dn} || 'dc=bestpractical,dc=com', |
| 66 | + }, $class; |
| 67 | + |
| 68 | + # Set a base default. Some tests will add or override portions of this |
| 69 | + # hash. |
| 70 | + $self->{'externalauth'} = { |
| 71 | + 'My_LDAP' => { |
| 72 | + 'type' => 'ldap', |
| 73 | + 'base' => $self->{'base_dn'}, |
| 74 | + 'filter' => '(objectClass=*)', |
| 75 | + 'd_filter' => '()', |
| 76 | + 'tls' => 0, |
| 77 | + 'net_ldap_args' => [ version => 3 ], |
| 78 | + 'attr_match_list' => [ 'Name', 'EmailAddress' ], |
| 79 | + 'attr_map' => { |
| 80 | + 'Name' => 'uid', |
| 81 | + 'EmailAddress' => 'mail', |
| 82 | + 'RealName' => 'cn', |
| 83 | + 'Gecos' => 'uid', |
| 84 | + 'NickName' => 'nick', |
| 85 | + }, |
| 86 | + }, |
| 87 | + }; |
| 88 | + |
| 89 | + return $self; |
| 90 | +} |
| 91 | + |
| 92 | +sub import { |
| 93 | + my $class = shift; |
| 94 | + |
| 95 | + $class->SUPER::import(@_, tests => undef); |
| 96 | + |
| 97 | + eval { |
| 98 | + require RT::LDAPImport; |
| 99 | + require RT::Authen::ExternalAuth; |
| 100 | + require Net::LDAP::Server::Test; |
| 101 | + 1; |
| 102 | + } or do { |
| 103 | + RT::Test::plan( |
| 104 | + skip_all => 'Unable to test without Net::LDAP and Net::LDAP::Server::Test' |
| 105 | + ); |
| 106 | + }; |
| 107 | + |
| 108 | + my %args = @_; |
| 109 | + RT::Test::plan( tests => $args{'tests'} ) if $args{tests}; |
| 110 | + |
| 111 | + $class->export_to_level(1); |
| 112 | +} |
| 113 | + |
| 114 | +sub new_server { |
| 115 | + my $self = shift; |
| 116 | + |
| 117 | + $self->{'ldap_port'} = RT::Test->find_idle_port; |
| 118 | + my $ldap_socket = IO::Socket::INET->new( |
| 119 | + Listen => 5, |
| 120 | + Proto => 'tcp', |
| 121 | + Reuse => 1, |
| 122 | + LocalAddr => $self->{'ldap_ip'}, |
| 123 | + LocalPort => $self->{'ldap_port'}, |
| 124 | + ) |
| 125 | + || die "Failed to create socket: $IO::Socket::errstr"; |
| 126 | + |
| 127 | + $self->{'ldap_server'} |
| 128 | + = Net::LDAP::Server::Test->new( $ldap_socket, auto_schema => 1 ) |
| 129 | + || die "Failed to spawn test LDAP server on port " . $self->{'ldap_port'}; |
| 130 | + |
| 131 | + my $ldap_client |
| 132 | + = Net::LDAP->new(join(':', $self->{'ldap_ip'}, $self->{'ldap_port'})) |
| 133 | + || die "Failed to connect to LDAP server: $@"; |
| 134 | + |
| 135 | + $ldap_client->bind(); |
| 136 | + $ldap_client->add($self->{'base_dn'}); |
| 137 | + |
| 138 | + return $ldap_client; |
| 139 | +} |
| 140 | + |
| 141 | +sub config_set_externalauth { |
| 142 | + my $self = shift; |
| 143 | + my $settings = shift; |
| 144 | + |
| 145 | + $settings->{'ExternalAuthPriority'} //= ['My_LDAP']; |
| 146 | + $settings->{'ExternalInfoPriority'} //= ['My_LDAP']; |
| 147 | + $settings->{'AutoCreateNonExternalUsers'} //= 0; |
| 148 | + $settings->{'AutoCreate'} //= undef; |
| 149 | + |
| 150 | + while (my ($key, $val) = each %{$settings}) { |
| 151 | + RT->Config->Set($key, $val); |
| 152 | + } |
| 153 | + |
| 154 | + $self->{'externalauth'}{'My_LDAP'}{'server'} //= |
| 155 | + join(':', $self->{'ldap_ip'}, $self->{'ldap_port'}); |
| 156 | + |
| 157 | + RT->Config->Set(ExternalSettings => $self->{'externalauth'}); |
| 158 | + RT->Config->PostLoadCheck; |
| 159 | +} |
| 160 | + |
| 161 | +sub config_set_ldapimport { |
| 162 | + my $self = shift; |
| 163 | + my $settings = shift; |
| 164 | + |
| 165 | + $settings->{'LDAPHost'} |
| 166 | + //= 'ldap://' . $self->{'ldap_ip'} . ':' . $self->{'ldap_port'}; |
| 167 | + $settings->{'LDAPMapping'} //= { |
| 168 | + Name => 'uid', |
| 169 | + EmailAddress => 'mail', |
| 170 | + RealName => 'cn', |
| 171 | + }; |
| 172 | + $settings->{'LDAPBase'} //= $self->{'base_dn'}; |
| 173 | + $settings->{'LDAPFilter'} //= '(objectClass=User)'; |
| 174 | + $settings->{'LDAPSkipAutogeneratedGroup'} //= 1; |
| 175 | +
|
| 176 | + while (my ($key, $val) = each %{$settings}) { |
| 177 | + RT->Config->Set($key, $val); |
| 178 | + } |
| 179 | +} |
| 180 | +
|
| 181 | +sub config_set_ldapimport_group { |
| 182 | + my $self = shift; |
| 183 | + my $settings = shift; |
| 184 | +
|
| 185 | + $settings->{'LDAPGroupBase'} //= $self->{'base_dn'}; |
| 186 | + $settings->{'LDAPGroupFilter'} //= '(objectClass=Group)'; |
| 187 | +
|
| 188 | + while (my ($key, $val) = each %{$settings}) { |
| 189 | + RT->Config->Set($key, $val); |
| 190 | + } |
| 191 | +} |
| 192 | +
|
| 193 | +1; |
0 commit comments