Skip to content

Commit 377507c

Browse files
feat(auto-prepend): Move custom error handler logic to auto-prepend file
1 parent 6014d8e commit 377507c

File tree

9 files changed

+119
-26
lines changed

9 files changed

+119
-26
lines changed

.github/workflows/test-suite.yml

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,10 +164,77 @@ jobs:
164164
exit 1
165165
fi
166166
167+
- name: Run "Display error with bad settings" test
168+
run: |
169+
cd ${{ github.workspace }}/${{env.EXTENSION_PATH}}
170+
sed -i 's/\x27cache_system\x27 => Constants::CACHE_SYSTEM_PHPFS/\x27cache_system\x27 => 1/g' scripts/auto-prepend/settings.php
171+
cat scripts/auto-prepend/settings.php
172+
cd ${{ github.workspace }}/${{env.EXTENSION_PATH}}/tests/end-to-end/
173+
./__scripts__/run-tests.sh ci "./__tests__/6-display-error-on.js"
174+
PENDING_TESTS=$(grep -oP '"numPendingTests":\K(.*),"numRuntimeErrorTestSuites"' .test-results.json | sed 's/,"numRuntimeErrorTestSuites"//g')
175+
if [[ $PENDING_TESTS == "0" ]]
176+
then
177+
echo "No pending tests: OK"
178+
else
179+
echo "There are pending tests: $PENDING_TESTS (KO)"
180+
exit 1
181+
fi
182+
183+
- name: Run "No display error with bad settings" test
184+
run: |
185+
cd ${{ github.workspace }}/${{env.EXTENSION_PATH}}
186+
sed -i 's/\x27cache_system\x27 => Constants::CACHE_SYSTEM_PHPFS/\x27cache_system\x27 => 1/g' scripts/auto-prepend/settings.php
187+
sed -i 's/\x27display_errors\x27 => true/\x27display_errors\x27 => false/g' scripts/auto-prepend/settings.php
188+
cat scripts/auto-prepend/settings.php
189+
cd ${{ github.workspace }}/${{env.EXTENSION_PATH}}/tests/end-to-end/
190+
./__scripts__/run-tests.sh ci "./__tests__/5-display-error-off.js"
191+
PENDING_TESTS=$(grep -oP '"numPendingTests":\K(.*),"numRuntimeErrorTestSuites"' .test-results.json | sed 's/,"numRuntimeErrorTestSuites"//g')
192+
if [[ $PENDING_TESTS == "0" ]]
193+
then
194+
echo "No pending tests: OK"
195+
else
196+
echo "There are pending tests: $PENDING_TESTS (KO)"
197+
exit 1
198+
fi
199+
200+
- name: Run "No display error with error while bouncing" test
201+
run: |
202+
cd ${{ github.workspace }}/${{env.EXTENSION_PATH}}
203+
sed -i 's/\x27cache_system\x27 => 1/\x27cache_system\x27 => Constants::CACHE_SYSTEM_PHPFS/g' scripts/auto-prepend/settings.php
204+
sed -i 's/\x27forced_test_ip\x27 => \x27\x27/\x27forced_test_ip\x27 => \x27bad-ip\x27/g' scripts/auto-prepend/settings.php
205+
cat scripts/auto-prepend/settings.php
206+
cd ${{ github.workspace }}/${{env.EXTENSION_PATH}}/tests/end-to-end/
207+
./__scripts__/run-tests.sh ci "./__tests__/5-display-error-off.js"
208+
PENDING_TESTS=$(grep -oP '"numPendingTests":\K(.*),"numRuntimeErrorTestSuites"' .test-results.json | sed 's/,"numRuntimeErrorTestSuites"//g')
209+
if [[ $PENDING_TESTS == "0" ]]
210+
then
211+
echo "No pending tests: OK"
212+
else
213+
echo "There are pending tests: $PENDING_TESTS (KO)"
214+
exit 1
215+
fi
216+
217+
- name: Run "Display error with error while bouncing" test
218+
run: |
219+
cd ${{ github.workspace }}/${{env.EXTENSION_PATH}}
220+
sed -i 's/\x27display_errors\x27 => false/\x27display_errors\x27 => true/g' scripts/auto-prepend/settings.php
221+
cat scripts/auto-prepend/settings.php
222+
cd ${{ github.workspace }}/${{env.EXTENSION_PATH}}/tests/end-to-end/
223+
./__scripts__/run-tests.sh ci "./__tests__/6-display-error-on.js"
224+
PENDING_TESTS=$(grep -oP '"numPendingTests":\K(.*),"numRuntimeErrorTestSuites"' .test-results.json | sed 's/,"numRuntimeErrorTestSuites"//g')
225+
if [[ $PENDING_TESTS == "0" ]]
226+
then
227+
echo "No pending tests: OK"
228+
else
229+
echo "There are pending tests: $PENDING_TESTS (KO)"
230+
exit 1
231+
fi
232+
167233
- name: Run "live mode with cURL and without geolocation" test
168234
run: |
169235
cd ${{ github.workspace }}/${{env.EXTENSION_PATH}}
170236
sed -i 's/\x27use_curl\x27 => false/\x27use_curl\x27 => true/g' scripts/auto-prepend/settings.php
237+
sed -i 's/\x27forced_test_ip\x27 => \x27bad-ip\x27/\x27forced_test_ip\x27 => \x27\x27/g' scripts/auto-prepend/settings.php
171238
cat scripts/auto-prepend/settings.php
172239
cd ${{ github.workspace }}/${{env.EXTENSION_PATH}}/tests/end-to-end/
173240
./__scripts__/run-tests.sh ci "./__tests__/1-live-mode.js"
@@ -332,7 +399,6 @@ jobs:
332399
echo "There are pending tests: $PENDING_TESTS (KO)"
333400
exit 1
334401
fi
335-
336402
337403
- name: Run "stream mode with TLS auth and cURL and Memcached" test
338404
run: |

docs/USER_GUIDE.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ class MyCustomBouncer extends AbstractBouncer
192192

193193

194194
Once you have implemented these methods, you could retrieve all required configurations to instantiate your
195-
bouncer and then call the `safelyBounce` method to apply a bounce for the current detected IP.
195+
bouncer and then call the `run` method to apply a bounce for the current detected IP.
196196

197197
In order to instantiate the bouncer, you will have to create at least a `CrowdSec\RemediationEngine\LapiRemediation`
198198
object too.
@@ -211,7 +211,7 @@ $remediationEngine = new LapiRemediation($configs, $client, $cacheStorage);
211211

212212
$bouncer = new MyCustomBouncer($configs, $remediationEngine);
213213

214-
$bouncer->safelyBounce();
214+
$bouncer->run();
215215

216216
```
217217

scripts/auto-prepend/bounce.php

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,20 @@
99
require_once __DIR__ . '/../../vendor/autoload.php';
1010
require_once __DIR__ . '/settings.php';
1111

12+
use CrowdSecBouncer\BouncerException;
1213
use CrowdSecBouncer\StandaloneBouncer;
1314

14-
$bouncer = new StandaloneBouncer($crowdSecStandaloneBouncerConfig);
15-
$bouncer->safelyBounce();
15+
// If there is any technical problem while bouncing, don't block the user.
16+
set_error_handler(function ($errno, $errstr) {
17+
throw new BouncerException("$errstr (Error level: $errno)");
18+
});
19+
try {
20+
$bouncer = new StandaloneBouncer($crowdSecStandaloneBouncerConfig);
21+
$bouncer->run();
22+
} catch (\Throwable $e) {
23+
$displayErrors = $crowdSecStandaloneBouncerConfig['display_errors'] ?? false;
24+
if (true === $displayErrors) {
25+
throw $e;
26+
}
27+
}
28+
restore_error_handler();

scripts/auto-prepend/settings.example.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
*/
1818
'bouncing_level' => Constants::BOUNCING_LEVEL_NORMAL,
1919

20-
/** If you use a CDN, a reverse proxy or a load balancer, you can use this setting to whitelist their IPs
20+
/** If you use a CDN, a reverse proxy or a load balancer, you can use this setting to whitelist their IPs.
2121
*
2222
* For other IPs, the bouncer will not trust the X-Forwarded-For header.
2323
*
@@ -26,7 +26,6 @@
2626
* [['001.002.003.004', '001.002.003.004'], ['005.006.007.008', '005.006.006.007']]
2727
*
2828
* If you use your own bouncer, you should have to set directly an array of comparable IPs arrays
29-
*
3029
*/
3130
'trust_ip_forward_array' => [],
3231
/**

src/AbstractBouncer.php

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -202,20 +202,17 @@ public function refreshBlocklistCache(): array
202202
}
203203

204204
/**
205-
* If there is any technical problem while bouncing, don't block the user. Bypass bouncing and log the error.
205+
* Handle a bounce for current IP
206206
*
207207
* @return bool
208208
* @throws BouncerException
209209
* @throws CacheException
210210
* @throws InvalidArgumentException
211211
* @throws \Symfony\Component\Cache\Exception\InvalidArgumentException
212212
*/
213-
public function safelyBounce(): bool
213+
public function run(): bool
214214
{
215215
$result = false;
216-
set_error_handler(function ($errno, $errstr) {
217-
throw new BouncerException("$errstr (Error level: $errno)");
218-
});
219216
try {
220217
if ($this->shouldBounceCurrentIp()) {
221218
$this->bounceCurrentIp();
@@ -230,10 +227,9 @@ public function safelyBounce(): bool
230227
'line' => $e->getLine(),
231228
]);
232229
if (true === $this->getConfig('display_errors')) {
233-
throw $e;
230+
throw new BouncerException($e->getMessage());
234231
}
235232
}
236-
restore_error_handler();
237233

238234
return $result;
239235
}

tests/Integration/IpVerificationTest.php

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
* @covers \CrowdSecBouncer\AbstractBouncer::shouldTrustXforwardedFor
4747
* @covers \CrowdSecBouncer\StandaloneBouncer::getHttpRequestHeader
4848
* @covers \CrowdSecBouncer\StandaloneBouncer::getRemoteIp
49-
* @covers \CrowdSecBouncer\StandaloneBouncer::safelyBounce
49+
* @covers \CrowdSecBouncer\StandaloneBouncer::run
5050
* @covers \CrowdSecBouncer\StandaloneBouncer::shouldBounceCurrentIp
5151
* @covers \CrowdSecBouncer\StandaloneBouncer::getHttpMethod
5252
* @covers \CrowdSecBouncer\StandaloneBouncer::getPostedVariable
@@ -187,6 +187,7 @@ private function addTlsConfig(&$bouncerConfigs, $tlsPath)
187187

188188
public function testConstructAndSomeMethods()
189189
{
190+
unset($_SERVER['REMOTE_ADDR'] );
190191
$bouncer = new StandaloneBouncer(array_merge($this->configs, ['unexpected_config' => 'test']));
191192
$this->assertEquals('', $bouncer->getRemoteIp(), 'Should return empty string');
192193
$_SERVER['REMOTE_ADDR'] = '5.6.7.8';
@@ -730,7 +731,7 @@ public function testCaptchaFlow()
730731
);
731732
}
732733

733-
public function testSafelyBounce()
734+
public function testRun()
734735
{
735736
$this->assertEquals(
736737
false,
@@ -749,7 +750,7 @@ public function testSafelyBounce()
749750
// Test 2: not bouncing exclude URI
750751
$_SERVER['REMOTE_ADDR'] = '127.0.0.2';
751752
$_SERVER['REQUEST_URI'] = self::EXCLUDED_URI;
752-
$this->assertEquals(false, $bouncer->safelyBounce(), 'Should not bounce excluded uri');
753+
$this->assertEquals(false, $bouncer->run(), 'Should not bounce excluded uri');
753754
PHPUnitUtil::assertRegExp(
754755
$this,
755756
'/.*100.*Will not bounce as URI is excluded/',
@@ -760,12 +761,12 @@ public function testSafelyBounce()
760761
// Test 3: bouncing URI
761762
$_SERVER['REMOTE_ADDR'] = '127.0.0.3';
762763
$_SERVER['REQUEST_URI'] = '/home';
763-
$this->assertEquals(true, $bouncer->safelyBounce(), 'Should bounce uri');
764+
$this->assertEquals(true, $bouncer->run(), 'Should bounce uri');
764765
// Test 4: not bouncing URI if disabled
765766
$_SERVER['REMOTE_ADDR'] = '127.0.0.4';
766767
$bouncer = new StandaloneBouncer(array_merge($this->configs, ['bouncing_level' =>
767768
Constants::BOUNCING_LEVEL_DISABLED]), $this->logger);
768-
$this->assertEquals(false, $bouncer->safelyBounce(), 'Should not bounce if disabled');
769+
$this->assertEquals(false, $bouncer->run(), 'Should not bounce if disabled');
769770

770771
PHPUnitUtil::assertRegExp(
771772
$this,
@@ -789,7 +790,7 @@ public function testSafelyBounce()
789790
$error = '';
790791

791792
try {
792-
$bouncer->safelyBounce();
793+
$bouncer->run();
793794
} catch (BouncerException $e) {
794795
$error = $e->getMessage();
795796
}
@@ -822,7 +823,7 @@ public function testSafelyBounce()
822823
$error = '';
823824

824825
try {
825-
$bouncer->safelyBounce();
826+
$bouncer->run();
826827
} catch (BouncerException $e) {
827828
$error = $e->getMessage();
828829
}
@@ -845,7 +846,7 @@ public function testSafelyBounce()
845846
),
846847
$this->logger
847848
);
848-
$bouncer->safelyBounce();
849+
$bouncer->run();
849850
PHPUnitUtil::assertRegExp(
850851
$this,
851852
'/.*100.*X-Forwarded-for usage is disabled/',
@@ -862,7 +863,7 @@ public function testSafelyBounce()
862863
]
863864
), $this->logger
864865
);
865-
$bouncer->safelyBounce();
866+
$bouncer->run();
866867
PHPUnitUtil::assertRegExp(
867868
$this,
868869
'/.*100.*X-Forwarded-for usage is forced.*"x_forwarded_for_ip":"1.2.3.5"/',
@@ -877,7 +878,7 @@ public function testSafelyBounce()
877878
$this->configs
878879
), $this->logger
879880
);
880-
$bouncer->safelyBounce();
881+
$bouncer->run();
881882
PHPUnitUtil::assertRegExp(
882883
$this,
883884
'/.*300.*Detected IP is not allowed for X-Forwarded-for usage.*"x_forwarded_for_ip":"1.2.3.5"/',
@@ -892,7 +893,7 @@ public function testSafelyBounce()
892893
$this->configs
893894
), $this->logger
894895
);
895-
$bouncer->safelyBounce();
896+
$bouncer->run();
896897
PHPUnitUtil::assertRegExp(
897898
$this,
898899
'/.*100.*Detected IP is allowed for X-Forwarded-for usage.*"original_ip":"5.6.7.8","x_forwarded_for_ip":"127.0.0.10"/',

tests/Unit/StandaloneBouncerTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
* @covers \CrowdSecBouncer\AbstractBouncer::shouldTrustXforwardedFor
5353
* @covers \CrowdSecBouncer\StandaloneBouncer::getHttpRequestHeader
5454
* @covers \CrowdSecBouncer\StandaloneBouncer::getRemoteIp
55-
* @covers \CrowdSecBouncer\StandaloneBouncer::safelyBounce
55+
* @covers \CrowdSecBouncer\StandaloneBouncer::run
5656
* @covers \CrowdSecBouncer\StandaloneBouncer::shouldBounceCurrentIp
5757
*
5858
* @covers \CrowdSecBouncer\StandaloneBouncer::__construct
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/* eslint-disable no-undef */
2+
const { publicHomepageShouldBeAccessible } = require("../utils/helpers");
3+
4+
describe(`Should not display errors`, () => {
5+
it("Should not display error", async () => {
6+
await publicHomepageShouldBeAccessible();
7+
await expect(page).not.toHaveText("body", "Fatal error");
8+
});
9+
});
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/* eslint-disable no-undef */
2+
const { goToPublicPage } = require("../utils/helpers");
3+
4+
describe(`Should not display errors`, () => {
5+
it("Should display error (if settings ko or something wrong while bouncing)", async () => {
6+
await goToPublicPage();
7+
await expect(page).toHaveText("body", "Fatal error");
8+
});
9+
});

0 commit comments

Comments
 (0)