Bug 26705: (QA follow-up) Clarify test result
[koha.git] / t / Koha / Middleware / RealIP.t
1 #!/usr/bin/perl
2
3 #
4 # Copyright 2020 Prosentient Systems
5 #
6 # This file is part of Koha.
7 #
8 # Koha is free software; you can redistribute it and/or modify it
9 # under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 3 of the License, or
11 # (at your option) any later version.
12 #
13 # Koha is distributed in the hope that it will be useful, but
14 # WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
17 #
18 # You should have received a copy of the GNU General Public License
19 # along with Koha; if not, see <http://www.gnu.org/licenses>.
20
21 use strict;
22 use warnings;
23 use Test::More tests => 11;
24 use Test::Warn;
25
26 use t::lib::Mocks;
27 use_ok("Koha::Middleware::RealIP");
28
29 my ($remote_address,$x_forwarded_for_header,$address);
30
31 subtest "No X-Forwarded-For header" => sub {
32     plan tests => 1;
33     $remote_address = "1.1.1.1";
34     $x_forwarded_for_header = "";
35     $address = Koha::Middleware::RealIP::get_real_ip( $remote_address, $x_forwarded_for_header );
36     is($address,'1.1.1.1',"There is no X-Forwarded-For header, so just use the remote address");
37 };
38
39 subtest "No configuration" => sub {
40     plan tests => 1;
41     $remote_address = "2.2.2.2";
42     $x_forwarded_for_header = "1.1.1.1";
43     $address = Koha::Middleware::RealIP::get_real_ip( $remote_address, $x_forwarded_for_header );
44     is($address,'2.2.2.2',"No trusted proxies available, so don't trust 2.2.2.2 as a proxy, instead use it as the remote address");
45 };
46
47 subtest "Bad configuration" => sub {
48     plan tests => 4;
49     $remote_address = "1.1.1.1";
50     $x_forwarded_for_header = "2.2.2.2,3.3.3.3";
51     t::lib::Mocks::mock_config('koha_trusted_proxies', 'bad configuration');
52     warnings_are {
53         $address = Koha::Middleware::RealIP::get_real_ip( $remote_address, $x_forwarded_for_header );
54     } ["could not parse bad","could not parse configuration"],"Warn on misconfigured koha_trusted_proxies";
55     is($address,'1.1.1.1',"koha_trusted_proxies is misconfigured so ignore the X-Forwarded-For header");
56
57     $remote_address = "1.1.1.1";
58     $x_forwarded_for_header = "2.2.2.2";
59     t::lib::Mocks::mock_config('koha_trusted_proxies', 'bad 1.1.1.1');
60     warning_is {
61         $address = Koha::Middleware::RealIP::get_real_ip( $remote_address, $x_forwarded_for_header );
62     } "could not parse bad","Warn on partially misconfigured koha_trusted_proxies";
63     is($address,'2.2.2.2',"koha_trusted_proxies contains an invalid value but still includes one correct value, which is relevant, so use X-Forwarded-For header");
64 };
65
66 subtest "Fail proxy isn't trusted" => sub {
67     plan tests => 1;
68     $remote_address = "2.2.2.2";
69     $x_forwarded_for_header = "1.1.1.1";
70     t::lib::Mocks::mock_config('koha_trusted_proxies', '3.3.3.3');
71     $address = Koha::Middleware::RealIP::get_real_ip( $remote_address, $x_forwarded_for_header );
72     is($address,'2.2.2.2',"The 2.2.2.2 proxy isn't in our trusted list, so use it as the remote address");
73 };
74
75 subtest "The most recent proxy is trusted but the proxy before it is not trusted" => sub {
76     plan tests => 1;
77     $remote_address = "3.3.3.3";
78     $x_forwarded_for_header = "1.1.1.1, 2.2.2.2";
79     t::lib::Mocks::mock_config('koha_trusted_proxies', '3.3.3.3');
80     $address = Koha::Middleware::RealIP::get_real_ip( $remote_address, $x_forwarded_for_header );
81     is($address,'2.2.2.2',"We trust 3.3.3.3, but we don't trust 2.2.2.2, so use 2.2.2.2 as the remote address");
82 };
83
84 subtest "Success one proxy" => sub {
85     plan tests => 1;
86     $remote_address = "2.2.2.2";
87     $x_forwarded_for_header = "1.1.1.1";
88     t::lib::Mocks::mock_config('koha_trusted_proxies', '2.2.2.2');
89     $address = Koha::Middleware::RealIP::get_real_ip( $remote_address, $x_forwarded_for_header );
90     is($address,'1.1.1.1',"Trust proxy (2.2.2.2), so use the client IP from the X-Forwarded-For header for the remote address");
91 };
92
93 subtest "Success multiple proxies" => sub {
94     plan tests => 1;
95     $remote_address = "2.2.2.2";
96     $x_forwarded_for_header = "1.1.1.1,3.3.3.3";
97     t::lib::Mocks::mock_config('koha_trusted_proxies', '2.2.2.2 3.3.3.3');
98     $address = Koha::Middleware::RealIP::get_real_ip( $remote_address, $x_forwarded_for_header );
99     is($address,'1.1.1.1',"Trust multiple proxies (2.2.2.2 and 3.3.3.3), so use the X-Forwaded-For <client> portion for the remote address");
100 };
101
102 subtest "Test alternative configuration styles" => sub {
103     plan tests => 3;
104     $remote_address = "2.2.2.2";
105     $x_forwarded_for_header = "1.1.1.1";
106     t::lib::Mocks::mock_config('koha_trusted_proxies', '2.2.2.0/24');
107     $address = Koha::Middleware::RealIP::get_real_ip( $remote_address, $x_forwarded_for_header );
108     is($address,'1.1.1.1',"Trust proxy (2.2.2.2) using CIDR notation, so use the X-Forwarded-For header for the remote address");
109
110     $remote_address = "2.2.2.2";
111     $x_forwarded_for_header = "1.1.1.1";
112     t::lib::Mocks::mock_config('koha_trusted_proxies', '2.2.2');
113     $address = Koha::Middleware::RealIP::get_real_ip( $remote_address, $x_forwarded_for_header );
114     is($address,'1.1.1.1',"Trust proxy (2.2.2.2) using abbreviated notation, so use the X-Forwarded-For header for the remote address");
115
116     $remote_address = "2.2.2.2";
117     $x_forwarded_for_header = "1.1.1.1";
118     t::lib::Mocks::mock_config('koha_trusted_proxies', '2.2.2.0:255.255.255.0');
119     $address = Koha::Middleware::RealIP::get_real_ip( $remote_address, $x_forwarded_for_header );
120     is($address,'1.1.1.1',"Trust proxy (2.2.2.2) using an IP address and netmask separated by a colon, so use the X-Forwarded-For header for the remote address");
121 };
122
123 subtest "Client IP is properly processed even if it is in koha_trusted_proxies" => sub {
124     $remote_address = "1.1.1.2";
125     $x_forwarded_for_header = "1.1.1.1";
126     t::lib::Mocks::mock_config('koha_trusted_proxies', '1.1.1.0/24');
127     $address = Koha::Middleware::RealIP::get_real_ip( $remote_address, $x_forwarded_for_header );
128     is($address,'1.1.1.1',"The X-Forwarded-For value matches the koha_trusted_proxies, but there is no proxy specified");
129     done_testing(1);
130 };
131
132 subtest "IPv6 support" => sub {
133     my ($remote_address,$x_forwarded_for_header,$address);
134     require Net::Netmask;
135     if (Net::Netmask->VERSION < 1.9104){
136         $remote_address         = "2001:db8:1234:5678:abcd:1234:abcd:1234";
137         $x_forwarded_for_header = "2.2.2.2";
138         t::lib::Mocks::mock_config( 'koha_trusted_proxies', '2001:db8:1234:5678::/64' );
139
140         warning_is {
141             $address = Koha::Middleware::RealIP::get_real_ip( $remote_address,
142                 $x_forwarded_for_header );
143         }
144         "could not parse 2001:db8:1234:5678::/64",
145           "Warn on IPv6 koha_trusted_proxies";
146         is(
147             $address,
148             '2001:db8:1234:5678:abcd:1234:abcd:1234',
149             "Unable to parse IPv6 address for trusted proxy, so ignore the X-Forwarded-For header"
150         );
151         done_testing(2);
152     } else {
153         $remote_address         = "2001:db8:1234:5678:abcd:1234:abcd:1234";
154         $x_forwarded_for_header = "2.2.2.2";
155         t::lib::Mocks::mock_config( 'koha_trusted_proxies', '2001:db8:1234:5678::/64' );
156
157         $address = Koha::Middleware::RealIP::get_real_ip( $remote_address,$x_forwarded_for_header );
158         is($address,'2.2.2.2',"Trust proxy (2001:db8:1234:5678:abcd:1234:abcd:1234) using IPv6 CIDR notation, so use the X-Forwarded-For header for the remote address");
159         done_testing(1);
160     }
161 };