4 namespace Shaarli\Security
;
6 use PHPUnit\Framework\TestCase
;
10 * Test coverage for BanManager
12 class BanManagerTest
extends TestCase
14 /** @var BanManager Ban Manager instance */
15 protected $banManager;
17 /** @var string Banned IP filename */
18 protected $banFile = 'sandbox/ipbans.php';
20 /** @var string Log filename */
21 protected $logFile = 'sandbox/shaarli.log';
23 /** @var string Local client IP address */
24 protected $ipAddr = '127.0.0.1';
26 /** @var string Trusted proxy IP address */
27 protected $trustedProxy = '10.1.1.100';
29 /** @var array Simulates the $_SERVER array */
30 protected $server = [];
33 * Prepare or reset test resources
35 public function setUp()
37 if (file_exists($this->banFile
)) {
38 unlink($this->banFile
);
41 $this->banManager
= $this->getNewBanManagerInstance();
42 $this->server
['REMOTE_ADDR'] = $this->ipAddr
;
46 * Test constructor with initial file.
48 public function testInstantiateFromFile()
51 FileUtils
::writeFlatDB(
59 $ip2 = '8.8.8.8' => $time,
60 $ip3 = '1.1.1.1' => $time +
1,
64 $this->banManager
= $this->getNewBanManagerInstance();
66 $this->assertCount(2, $this->banManager
->getFailures());
67 $this->assertEquals(2, $this->banManager
->getFailures()[$this->ipAddr
]);
68 $this->assertEquals(1, $this->banManager
->getFailures()[$ip]);
69 $this->assertCount(2, $this->banManager
->getBans());
70 $this->assertEquals($time, $this->banManager
->getBans()[$ip2]);
71 $this->assertEquals($time +
1, $this->banManager
->getBans()[$ip3]);
75 * Test constructor with initial file with invalid values
77 public function testInstantiateFromCrappyFile()
79 FileUtils
::writeFlatDB($this->banFile
, 'plop');
80 $this->banManager
= $this->getNewBanManagerInstance();
82 $this->assertEquals([], $this->banManager
->getFailures());
83 $this->assertEquals([], $this->banManager
->getBans());
87 * Test failed attempt with a direct IP.
89 public function testHandleFailedAttempt()
91 $this->assertCount(0, $this->banManager
->getFailures());
93 $this->banManager
->handleFailedAttempt($this->server
);
94 $this->assertCount(1, $this->banManager
->getFailures());
95 $this->assertEquals(1, $this->banManager
->getFailures()[$this->ipAddr
]);
97 $this->banManager
->handleFailedAttempt($this->server
);
98 $this->assertCount(1, $this->banManager
->getFailures());
99 $this->assertEquals(2, $this->banManager
->getFailures()[$this->ipAddr
]);
103 * Test failed attempt behind a trusted proxy IP (with proper IP forwarding).
105 public function testHandleFailedAttemptBehingProxy()
108 'REMOTE_ADDR' => $this->trustedProxy
,
109 'HTTP_X_FORWARDED_FOR' => $this->ipAddr
,
111 $this->assertCount(0, $this->banManager
->getFailures());
113 $this->banManager
->handleFailedAttempt($server);
114 $this->assertCount(1, $this->banManager
->getFailures());
115 $this->assertEquals(1, $this->banManager
->getFailures()[$this->ipAddr
]);
117 $this->banManager
->handleFailedAttempt($server);
118 $this->assertCount(1, $this->banManager
->getFailures());
119 $this->assertEquals(2, $this->banManager
->getFailures()[$this->ipAddr
]);
123 * Test failed attempt behind a trusted proxy IP but without IP forwarding.
125 public function testHandleFailedAttemptBehindNotConfiguredProxy()
128 'REMOTE_ADDR' => $this->trustedProxy
,
130 $this->assertCount(0, $this->banManager
->getFailures());
132 $this->banManager
->handleFailedAttempt($server);
133 $this->assertCount(0, $this->banManager
->getFailures());
135 $this->banManager
->handleFailedAttempt($server);
136 $this->assertCount(0, $this->banManager
->getFailures());
140 * Test failed attempts with multiple direct IP.
142 public function testHandleFailedAttemptMultipleIp()
144 $this->assertCount(0, $this->banManager
->getFailures());
145 $this->banManager
->handleFailedAttempt($this->server
);
146 $this->server
['REMOTE_ADDR'] = '1.2.3.4';
147 $this->banManager
->handleFailedAttempt($this->server
);
148 $this->banManager
->handleFailedAttempt($this->server
);
149 $this->assertCount(2, $this->banManager
->getFailures());
150 $this->assertEquals(1, $this->banManager
->getFailures()[$this->ipAddr
]);
151 $this->assertEquals(2, $this->banManager
->getFailures()[$this->server
['REMOTE_ADDR']]);
155 * Test clear failure for provided IP without any additional data.
157 public function testClearFailuresEmpty()
159 $this->assertCount(0, $this->banManager
->getFailures());
160 $this->banManager
->clearFailures($this->server
);
161 $this->assertCount(0, $this->banManager
->getFailures());
165 * Test clear failure for provided IP with failed attempts.
167 public function testClearFailuresFromFile()
169 FileUtils
::writeFlatDB(
174 $ip = '1.2.3.4' => 1,
178 $this->banManager
= $this->getNewBanManagerInstance();
180 $this->assertCount(2, $this->banManager
->getFailures());
181 $this->banManager
->clearFailures($this->server
);
182 $this->assertCount(1, $this->banManager
->getFailures());
183 $this->assertEquals(1, $this->banManager
->getFailures()[$ip]);
187 * Test clear failure for provided IP with failed attempts, behind a reverse proxy.
189 public function testClearFailuresFromFileBehindProxy()
192 'REMOTE_ADDR' => $this->trustedProxy
,
193 'HTTP_X_FORWARDED_FOR' => $this->ipAddr
,
196 FileUtils
::writeFlatDB(
201 $ip = '1.2.3.4' => 1,
205 $this->banManager
= $this->getNewBanManagerInstance();
207 $this->assertCount(2, $this->banManager
->getFailures());
208 $this->banManager
->clearFailures($server);
209 $this->assertCount(1, $this->banManager
->getFailures());
210 $this->assertEquals(1, $this->banManager
->getFailures()[$ip]);
214 * Test clear failure for provided IP with failed attempts,
215 * behind a reverse proxy without forwarding.
217 public function testClearFailuresFromFileBehindNotConfiguredProxy()
220 'REMOTE_ADDR' => $this->trustedProxy
,
223 FileUtils
::writeFlatDB(
228 $ip = '1.2.3.4' => 1,
232 $this->banManager
= $this->getNewBanManagerInstance();
234 $this->assertCount(2, $this->banManager
->getFailures());
235 $this->banManager
->clearFailures($server);
236 $this->assertCount(2, $this->banManager
->getFailures());
240 * Test isBanned without any data
242 public function testIsBannedEmpty()
244 $this->assertFalse($this->banManager
->isBanned($this->server
));
248 * Test isBanned with banned IP from file data
250 public function testBannedFromFile()
252 FileUtils
::writeFlatDB(
256 $this->ipAddr
=> time() +
10,
260 $this->banManager
= $this->getNewBanManagerInstance();
262 $this->assertCount(1, $this->banManager
->getBans());
263 $this->assertTrue($this->banManager
->isBanned($this->server
));
267 * Test isBanned with banned IP from file data behind a reverse proxy
269 public function testBannedFromFileBehindProxy()
272 'REMOTE_ADDR' => $this->trustedProxy
,
273 'HTTP_X_FORWARDED_FOR' => $this->ipAddr
,
275 FileUtils
::writeFlatDB(
279 $this->ipAddr
=> time() +
10,
283 $this->banManager
= $this->getNewBanManagerInstance();
285 $this->assertCount(1, $this->banManager
->getBans());
286 $this->assertTrue($this->banManager
->isBanned($server));
290 * Test isBanned with banned IP from file data behind a reverse proxy,
291 * without IP forwarding
293 public function testBannedFromFileBehindNotConfiguredProxy()
296 'REMOTE_ADDR' => $this->trustedProxy
,
298 FileUtils
::writeFlatDB(
302 $this->ipAddr
=> time() +
10,
306 $this->banManager
= $this->getNewBanManagerInstance();
308 $this->assertCount(1, $this->banManager
->getBans());
309 $this->assertFalse($this->banManager
->isBanned($server));
313 * Test isBanned with an expired ban
315 public function testLiftBan()
317 FileUtils
::writeFlatDB(
321 $this->ipAddr
=> time() - 10,
325 $this->banManager
= $this->getNewBanManagerInstance();
327 $this->assertCount(1, $this->banManager
->getBans());
328 $this->assertFalse($this->banManager
->isBanned($this->server
));
332 * Test isBanned with an expired ban behind a reverse proxy
334 public function testLiftBanBehindProxy()
337 'REMOTE_ADDR' => $this->trustedProxy
,
338 'HTTP_X_FORWARDED_FOR' => $this->ipAddr
,
341 FileUtils
::writeFlatDB(
345 $this->ipAddr
=> time() - 10,
349 $this->banManager
= $this->getNewBanManagerInstance();
351 $this->assertCount(1, $this->banManager
->getBans());
352 $this->assertFalse($this->banManager
->isBanned($server));
356 * Test isBanned with an expired ban behind a reverse proxy
358 public function testLiftBanBehindNotConfiguredProxy()
361 'REMOTE_ADDR' => $this->trustedProxy
,
364 FileUtils
::writeFlatDB(
368 $this->ipAddr
=> time() - 10,
372 $this->banManager
= $this->getNewBanManagerInstance();
374 $this->assertCount(1, $this->banManager
->getBans());
375 $this->assertFalse($this->banManager
->isBanned($server));
379 * Build a new instance of BanManager, which will reread the ban file.
381 * @return BanManager instance
383 protected function getNewBanManagerInstance()
385 return new BanManager(
386 [$this->trustedProxy
],