Skip to content

Commit 35b6e9f

Browse files
committed
add redis and memcached connection checks
1 parent e758253 commit 35b6e9f

File tree

4 files changed

+108
-32
lines changed

4 files changed

+108
-32
lines changed

inc/admin/advanced-settings.php

Lines changed: 61 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<?php
22

3+
use CrowdSecBouncer\BouncerException;
34
use CrowdSecBouncer\Constants;
45

56
function adminAdvancedSettings()
@@ -53,31 +54,82 @@ function adminAdvancedSettings()
5354
<?php
5455
}, 'crowdsec_advanced_settings');
5556

57+
// Field "crowdsec_redis_dsn"
58+
addFieldString('crowdsec_redis_dsn', 'Redis DSN<br>(if applicable)', 'crowdsec_plugin_advanced_settings', 'crowdsec_advanced_settings', 'crowdsec_admin_advanced_cache', function ($input) {
59+
// TODO P1 block remove if cache set to redis
60+
// TODO P1 Display an error in all sections (settings and advanced) when a cache config can not work.
61+
return $input;
62+
}, '<p>Fill in this field only if you have chosen the Redis cache.<br>Example of DSN: redis://localhost:6379.', 'redis://...', '');
63+
64+
// Field "crowdsec_memcached_dsn"
65+
addFieldString('crowdsec_memcached_dsn', 'Memcached DSN<br>(if applicable)', 'crowdsec_plugin_advanced_settings', 'crowdsec_advanced_settings', 'crowdsec_admin_advanced_cache', function ($input) {
66+
// TODO P1 block remove if cache set to memcached
67+
// TODO P1 Display an error in all sections (settings and advanced) when a cache config can not work.
68+
return $input;
69+
}, '<p>Fill in this field only if you have chosen the Memcached cache.<br>Example of DSN: memcached://localhost:11211.', 'memcached://...', '');
70+
5671
// Field "crowdsec_cache_system"
5772
addFieldSelect('crowdsec_cache_system', 'Technology', 'crowdsec_plugin_advanced_settings', 'crowdsec_advanced_settings', 'crowdsec_admin_advanced_cache', function ($input) {
5873
if (!in_array($input, [CROWDSEC_CACHE_SYSTEM_PHPFS, CROWDSEC_CACHE_SYSTEM_REDIS, CROWDSEC_CACHE_SYSTEM_MEMCACHED])) {
5974
$input = CROWDSEC_CACHE_SYSTEM_PHPFS;
6075
add_settings_error('Technology', 'crowdsec_error', 'Technology: Incorrect cache technology selected.');
6176
}
6277

63-
6478
try {
6579
$bouncer = getBouncerInstance();
66-
$bouncer->clearCache();
80+
try {
81+
$bouncer->clearCache();
82+
} catch (BouncerException $e) {
83+
$cacheSystem = esc_attr(get_option('crowdsec_cache_system'));
84+
switch ($cacheSystem) {
85+
case CROWDSEC_CACHE_SYSTEM_MEMCACHED:
86+
throw new WordpressCrowdSecBouncerException('Unable to connect Memcached.'.
87+
' Please fix the Memcached DSN or select another cache technology.');
88+
break;
89+
90+
case CROWDSEC_CACHE_SYSTEM_REDIS:
91+
throw new WordpressCrowdSecBouncerException('Unable to connect Redis.'.
92+
' Please fix the Redis DSN or select another cache technology.');
93+
default:
94+
throw new WordpressCrowdSecBouncerException('Unable to connect the cache system: '.$e->getMessage());
95+
}
96+
}
97+
6798
$message = __('Cache system changed. Previous cache data has been cleared.');
99+
} catch (WordpressCrowdSecBouncerException $e) {
100+
}
68101

69-
// Update wp-cron schedule if stream mode is enabled
70-
if ((bool) get_option('crowdsec_stream_mode')) {
71-
$bouncer = getBouncerInstance($input); // Reload bouncer instance with the new cache system
72-
$result = $bouncer->warmBlocklistCacheUp();
73-
$message .= __(' As the stream mode is enabled, the cache has just been warmed up, '.($result > 0 ? 'there are now '.$result.' decisions' : 'there is now '.$result.' decision').' in cache.');
74-
scheduleBlocklistRefresh();
102+
try {
103+
// Reload bouncer instance with the new cache system and so test if dsn is correct.
104+
getCacheAdapterInstance($input);
105+
try {
106+
// Try the adapter connection (Redis or Memcached will crash if the connection is incorrect)
107+
$bouncer = getBouncerInstance($input);
108+
$bouncer->testConnection();
109+
} catch (BouncerException $e) {
110+
throw new WordpressCrowdSecBouncerException($e->getMessage());
75111
}
76-
AdminNotice::displaySuccess($message);
77112
} catch (WordpressCrowdSecBouncerException $e) {
78113
AdminNotice::displayError($e->getMessage());
79114
}
80115

116+
try {
117+
try {
118+
//Update wp-cron schedule if stream mode is enabled
119+
if ((bool) get_option('crowdsec_stream_mode')) {
120+
$bouncer = getBouncerInstance($input); // Reload bouncer instance with the new cache system
121+
$result = $bouncer->warmBlocklistCacheUp();
122+
$message = __('As the stream mode is enabled, the cache has just been warmed up, '.($result > 0 ? 'there are now '.$result.' decisions' : 'there is now '.$result.' decision').' in cache.');
123+
AdminNotice::displaySuccess($message);
124+
scheduleBlocklistRefresh();
125+
}
126+
} catch (WordpressCrowdSecBouncerException $e) {
127+
AdminNotice::displayError($e->getMessage());
128+
}
129+
} catch (BouncerException $e) {
130+
AdminNotice::displayError($e->getMessage());
131+
}
132+
81133
return $input;
82134
}, ((CROWDSEC_CACHE_SYSTEM_PHPFS === get_option('crowdsec_cache_system')) ?
83135
'<input style="margin-right:10px" type="button" value="Prune now" class="button button-secondary" onclick="document.getElementById(\'crowdsec_ation_prune_cache\').submit();">' : '').
@@ -87,20 +139,6 @@ function adminAdvancedSettings()
87139
CROWDSEC_CACHE_SYSTEM_MEMCACHED => 'Memcached',
88140
]);
89141

90-
// Field "crowdsec_redis_dsn"
91-
addFieldString('crowdsec_redis_dsn', 'Redis DSN<br>(if applicable)', 'crowdsec_plugin_advanced_settings', 'crowdsec_advanced_settings', 'crowdsec_admin_advanced_cache', function ($input) {
92-
// TODO P1 block remove if cache set to redis
93-
// TODO P1 Display an error in all sections (settings and advanced) when a cache config can not work.
94-
return $input;
95-
}, '<p>Fill in this field only if you have chosen the Redis cache.<br>Example of DSN: redis://localhost:6379.', 'redis://...', '');
96-
97-
// Field "crowdsec_memcached_dsn"
98-
addFieldString('crowdsec_memcached_dsn', 'Memcached DSN<br>(if applicable)', 'crowdsec_plugin_advanced_settings', 'crowdsec_advanced_settings', 'crowdsec_admin_advanced_cache', function ($input) {
99-
// TODO P1 block remove if cache set to memcached
100-
// TODO P1 Display an error in all sections (settings and advanced) when a cache config can not work.
101-
return $input;
102-
}, '<p>Fill in this field only if you have chosen the Memcached cache.<br>Example of DSN: memcached://localhost:11211.', 'memcached://...', '');
103-
104142
// Field "crowdsec_clean_ip_cache_duration"
105143
addFieldString('crowdsec_clean_ip_cache_duration', 'Recheck clean IPs each', 'crowdsec_plugin_advanced_settings', 'crowdsec_advanced_settings', 'crowdsec_admin_advanced_cache', function ($input) {
106144
if ((int) $input <= 0) {

inc/admin/init.php

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,6 @@ function wrapBlockingErrorMessage(string $errorMessage)
2020
'<br>Important: Until you fix this problem, <strong>the website will not be protected against attacks</strong>.';
2121
}
2222

23-
if (false) {
24-
// TODO P1
25-
$message = wrapBlockingErrorMessage('Please fill the Redis DSN or select another cache technology.');
26-
AdminNotice::displayError($message);
27-
}
28-
2923
function clearBouncerCacheInAdminPage()
3024
{
3125
try {

inc/bouncer-instance.php

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
<?php
22

33
use CrowdSecBouncer\Bouncer;
4+
use CrowdSecBouncer\BouncerException;
45
use CrowdSecBouncer\Constants;
56
use Monolog\Handler\RotatingFileHandler;
67
use Monolog\Logger;
78
use Symfony\Component\Cache\Adapter\AbstractAdapter;
89
use Symfony\Component\Cache\Adapter\MemcachedAdapter;
910
use Symfony\Component\Cache\Adapter\PhpFilesAdapter;
1011
use Symfony\Component\Cache\Adapter\RedisAdapter;
12+
use Symfony\Component\Cache\Exception\InvalidArgumentException;
1113

1214
/** @var Logger|null */
1315
$crowdSecLogger = null;
@@ -71,9 +73,18 @@ function getCacheAdapterInstance(string $forcedCacheSystem = null): AbstractAdap
7173
' Please set a Redis DSN or select another cache technology.');
7274
}
7375

74-
$crowdSecCacheAdapterInstance = new RedisAdapter(RedisAdapter::createConnection($redisDsn));
76+
try {
77+
$crowdSecCacheAdapterInstance = new RedisAdapter(RedisAdapter::createConnection($redisDsn));
78+
} catch (InvalidArgumentException $e) {
79+
throw new WordpressCrowdSecBouncerException('Error when connecting to Redis.'.
80+
' Please fix the Redis DSN or select another cache technology.');
81+
}
82+
7583
break;
84+
default:
85+
throw new WordpressCrowdSecBouncerException('Unknow selected cache technology.');
7686
}
87+
7788
return $crowdSecCacheAdapterInstance;
7889
}
7990

@@ -131,8 +142,10 @@ function getBouncerInstance(string $forcedCacheSystem = null): Bouncer
131142
} catch (Symfony\Component\Cache\Exception\InvalidArgumentException $e) {
132143
throw new WordpressCrowdSecBouncerException($e->getMessage());
133144
}
134-
$bouncer = new Bouncer($cacheAdapter, $logger);
135-
$bouncer->configure([
145+
146+
try {
147+
$bouncer = new Bouncer($cacheAdapter, $logger);
148+
$bouncer->configure([
136149
'api_key' => $apiKey,
137150
'api_url' => $apiUrl,
138151
'api_user_agent' => CROWDSEC_BOUNCER_USER_AGENT,
@@ -142,6 +155,9 @@ function getBouncerInstance(string $forcedCacheSystem = null): Bouncer
142155
'cache_expiration_for_clean_ip' => $cleanIpCacheDuration,
143156
'cache_expiration_for_bad_ip' => $badIpCacheDuration,
144157
], $cacheAdapter);
158+
} catch (BouncerException $e) {
159+
throw new WordpressCrowdSecBouncerException($e->getMessage());
160+
}
145161

146162
return $bouncer;
147163
}

inc/templates/advanced-settings.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,33 @@
11
<div class="wrap">
22
<h1>CrowdSec Advanced Settings</h1>
3+
<script type="text/javascript">
4+
5+
jQuery(() => {
6+
const $cacheTechno = jQuery('[name=crowdsec_cache_system]');
7+
const $cacheTechnoDiv = $cacheTechno.parent().parent();
8+
const $redisDsnDiv = jQuery('[name=crowdsec_redis_dsn]').parent().parent();
9+
const $memcachedDsnDiv = jQuery('[name=crowdsec_memcached_dsn]').parent().parent();
10+
$cacheTechnoDiv.insertBefore($redisDsnDiv);
11+
12+
function updateDsnDisplay () {
13+
switch ($cacheTechno.val()) {
14+
case 'redis':
15+
$redisDsnDiv.show();
16+
$memcachedDsnDiv.hide();
17+
break;
18+
case 'memcached':
19+
$redisDsnDiv.hide();
20+
$memcachedDsnDiv.show();
21+
break;
22+
default:
23+
$redisDsnDiv.hide();
24+
$memcachedDsnDiv.hide();
25+
}
26+
}
27+
updateDsnDisplay();
28+
$cacheTechno.change(updateDsnDisplay);
29+
});
30+
</script>
331
<?php settings_errors(); ?>
432
<div class="tab-content">
533
<div id="tab-1" class="tab-pane active">

0 commit comments

Comments
 (0)