Skip to content

Commit d91e45b

Browse files
Merge pull request #98 from julienloizelet/feat/settings-refacto
feat(bouncer): Add configs attribute to Bouncer
2 parents 26a6906 + 4576ab9 commit d91e45b

File tree

5 files changed

+65
-50
lines changed

5 files changed

+65
-50
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/)
55
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
66

77

8+
## [0.24.0] - 2022-07-08
9+
10+
### Added
11+
- Add a `configs` attribute to Bouncer class
12+
813
## [0.23.0] - 2022-07-07
914

1015
### Added

src/AbstractBounce.php

Lines changed: 20 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -117,44 +117,37 @@ protected function initLoggerHelper(string $logDirectoryPath, string $loggerName
117117
/**
118118
* Handle X-Forwarded-For HTTP header to retrieve the IP to bounce
119119
*
120-
* @param $ip
121-
* @return false|mixed
120+
* @param string $ip
121+
* @param array $configs
122+
* @return string
122123
*/
123-
protected function handleForwardedFor($ip)
124+
protected function handleForwardedFor(string $ip, array $configs): string
124125
{
125-
if (empty($this->settings['forced_test_forwarded_ip'])) {
126+
$forwardedIp = null;
127+
if (empty($configs['forced_test_forwarded_ip'])) {
126128
$XForwardedForHeader = $this->getHttpRequestHeader('X-Forwarded-For');
127129
if (null !== $XForwardedForHeader) {
128130
$ipList = array_map('trim', array_values(array_filter(explode(',', $XForwardedForHeader))));
129131
$forwardedIp = end($ipList);
130-
if ($this->shouldTrustXforwardedFor($ip)) {
131-
$ip = $forwardedIp;
132-
} else {
133-
$this->logger->warning('', [
134-
'type' => 'NON_AUTHORIZED_X_FORWARDED_FOR_USAGE',
135-
'original_ip' => $ip,
136-
'x_forwarded_for_ip' => $forwardedIp,
137-
]);
138-
}
139132
}
140-
} else if ($this->settings['forced_test_forwarded_ip'] === Constants::X_FORWARDED_DISABLED) {
133+
} else if ($configs['forced_test_forwarded_ip'] === Constants::X_FORWARDED_DISABLED) {
141134
$this->logger->debug('', [
142135
'type' => 'DISABLED_X_FORWARDED_FOR_USAGE',
143136
'original_ip' => $ip,
144137
]);
145138
} else {
146-
$forwardedIp = $this->settings['forced_test_forwarded_ip'];
147-
if ($this->shouldTrustXforwardedFor($ip)) {
148-
$ip = $forwardedIp;
149-
} else {
150-
$this->logger->warning('', [
151-
'type' => 'NON_AUTHORIZED_TEST_X_FORWARDED_FOR_USAGE',
152-
'original_ip' => $ip,
153-
'x_forwarded_for_ip_for_test' => $forwardedIp,
154-
]);
155-
}
139+
$forwardedIp = (string) $configs['forced_test_forwarded_ip'];
156140
}
157141

142+
if (is_string($forwardedIp) && $this->shouldTrustXforwardedFor($ip)) {
143+
$ip = $forwardedIp;
144+
} else {
145+
$this->logger->warning('', [
146+
'type' => 'NON_AUTHORIZED_X_FORWARDED_FOR_USAGE',
147+
'original_ip' => $ip,
148+
'x_forwarded_for_ip' => is_string($forwardedIp) ? $forwardedIp : 'type not as expected',
149+
]);
150+
}
158151
return $ip;
159152
}
160153

@@ -171,9 +164,10 @@ protected function bounceCurrentIp(): void
171164
if (!$this->bouncer) {
172165
throw new BouncerException('Bouncer must be instantiated to bounce an IP.');
173166
}
167+
$configs = $this->bouncer->getConfigs();
174168
// Retrieve the current IP (even if it is a proxy IP) or a testing IP
175-
$ip = !empty($this->settings['forced_test_ip']) ? $this->settings['forced_test_ip'] : $this->getRemoteIp();
176-
$ip = $this->handleForwardedFor($ip);
169+
$ip = !empty($configs['forced_test_ip']) ? $configs['forced_test_ip'] : $this->getRemoteIp();
170+
$ip = $this->handleForwardedFor($ip, $configs);
177171
$remediation = $this->bouncer->getRemediationForIp($ip);
178172
$this->handleRemediation($remediation, $ip);
179173
} catch (Exception $e) {

src/Bouncer.php

Lines changed: 38 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,15 @@ class Bouncer
3737
/** @var int */
3838
private $maxRemediationLevelIndex = 0;
3939

40+
/** @var array */
41+
private $configs = [];
42+
4043
public function __construct(
4144
TagAwareAdapterInterface $cacheAdapter = null,
42-
LoggerInterface $logger = null,
43-
ApiCache $apiCache = null
44-
) {
45+
LoggerInterface $logger = null,
46+
ApiCache $apiCache = null
47+
)
48+
{
4549
if (!$logger) {
4650
$logger = new Logger('null');
4751
$logger->pushHandler(new NullHandler());
@@ -50,6 +54,16 @@ public function __construct(
5054
$this->apiCache = $apiCache ?: new ApiCache($logger, new ApiClient($logger), $cacheAdapter);
5155
}
5256

57+
/**
58+
* Retrieve Bouncer configurations
59+
*
60+
* @return array
61+
*/
62+
public function getConfigs(): array
63+
{
64+
return $this->configs;
65+
}
66+
5367
/**
5468
* Configure this instance.
5569
*
@@ -59,33 +73,33 @@ public function __construct(
5973
*/
6074
public function configure(array $config): void
6175
{
62-
// Process input configuration.
76+
// Process and validate input configuration.
6377
$configuration = new Configuration();
6478
$processor = new Processor();
65-
$finalConfig = $processor->processConfiguration($configuration, [$config]);
79+
$this->configs = $processor->processConfiguration($configuration, [$config]);
6680
/** @var int */
6781
$index = array_search(
68-
$finalConfig['max_remediation_level'],
82+
$this->configs['max_remediation_level'],
6983
Constants::ORDERED_REMEDIATIONS
7084
);
7185
$this->maxRemediationLevelIndex = $index;
7286
$cacheDurations = [
73-
'clean_ip_cache_duration' => $finalConfig['clean_ip_cache_duration'],
74-
'bad_ip_cache_duration' => $finalConfig['bad_ip_cache_duration'],
75-
'captcha_cache_duration' => $finalConfig['captcha_cache_duration'],
76-
'geolocation_cache_duration' => $finalConfig['geolocation_cache_duration'],
87+
'clean_ip_cache_duration' => $this->configs['clean_ip_cache_duration'],
88+
'bad_ip_cache_duration' => $this->configs['bad_ip_cache_duration'],
89+
'captcha_cache_duration' => $this->configs['captcha_cache_duration'],
90+
'geolocation_cache_duration' => $this->configs['geolocation_cache_duration'],
7791
];
7892

7993
// Configure Api Cache.
8094
$this->apiCache->configure(
81-
$finalConfig['stream_mode'],
82-
$finalConfig['api_url'],
83-
$finalConfig['api_timeout'],
84-
$finalConfig['api_user_agent'],
85-
$finalConfig['api_key'],
95+
$this->configs['stream_mode'],
96+
$this->configs['api_url'],
97+
$this->configs['api_timeout'],
98+
$this->configs['api_user_agent'],
99+
$this->configs['api_key'],
86100
$cacheDurations,
87-
$finalConfig['fallback_remediation'],
88-
$finalConfig['geolocation']
101+
$this->configs['fallback_remediation'],
102+
$this->configs['geolocation']
89103
);
90104
}
91105

@@ -115,7 +129,7 @@ private function capRemediationLevel(string $remediation): string
115129
*
116130
* @return string the remediation to apply (ex: 'ban', 'captcha', 'bypass')
117131
*
118-
* @throws InvalidArgumentException
132+
* @throws InvalidArgumentException|\Psr\Cache\CacheException
119133
*/
120134
public function getRemediationForIp(string $ip): string
121135
{
@@ -154,11 +168,12 @@ public static function getAccessForbiddenHtmlTemplate(array $config): string
154168
* The input $config should match the TemplateConfiguration input format.
155169
*/
156170
public static function getCaptchaHtmlTemplate(
157-
bool $error,
171+
bool $error,
158172
string $captchaImageSrc,
159173
string $captchaResolutionFormUrl,
160-
array $config
161-
): string {
174+
array $config
175+
): string
176+
{
162177
// Process template configuration.
163178
$configuration = new TemplateConfiguration();
164179
$processor = new Processor();
@@ -176,7 +191,7 @@ public static function getCaptchaHtmlTemplate(
176191
*
177192
* @return array "count": number of decisions added, "errors": decisions not added
178193
*
179-
* @throws InvalidArgumentException
194+
* @throws InvalidArgumentException|\Psr\Cache\CacheException
180195
*/
181196
public function warmBlocklistCacheUp(): array
182197
{
@@ -189,7 +204,7 @@ public function warmBlocklistCacheUp(): array
189204
*
190205
* @return array Number of deleted and new decisions, and errors when processing decisions
191206
*
192-
* @throws InvalidArgumentException
207+
* @throws InvalidArgumentException|\Psr\Cache\CacheException
193208
*/
194209
public function refreshBlocklistCache(): array
195210
{

src/Constants.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class Constants
2020
public const DEFAULT_LAPI_URL = 'http://localhost:8080';
2121

2222
/** @var string The last version of this library */
23-
public const VERSION = 'v0.23.0';
23+
public const VERSION = 'v0.24.0';
2424

2525
/** @var string The user agent used to send request to LAPI */
2626
public const BASE_USER_AGENT = 'PHP CrowdSec Bouncer/' . self::VERSION;

src/StandaloneBounce.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ public function getBouncerInstance(array $settings, bool $forceReload = false):
132132
if ($this->bouncer && !$forceReload) {
133133
return $this->bouncer;
134134
}
135+
$this->settings = array_merge($this->settings, $settings);
135136
$bouncingLevel = $this->getStringSettings('bouncing_level');
136137
$apiUserAgent = 'Standalone CrowdSec PHP Bouncer/' . Constants::VERSION;
137138
$apiTimeout = $this->getIntegerSettings('api_timeout');

0 commit comments

Comments
 (0)