Skip to content

Commit bed3ffb

Browse files
committed
feat(admin): Show an error when the admin is throttled
Signed-off-by: Joas Schilling <[email protected]>
1 parent 124588d commit bed3ffb

File tree

4 files changed

+84
-0
lines changed

4 files changed

+84
-0
lines changed

apps/settings/lib/Controller/CheckSetupController.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@
9090
use OCP\IURLGenerator;
9191
use OCP\Lock\ILockingProvider;
9292
use OCP\Notification\IManager;
93+
use OCP\Security\Bruteforce\IThrottler;
9394
use OCP\Security\ISecureRandom;
9495
use Psr\Log\LoggerInterface;
9596

@@ -123,6 +124,8 @@ class CheckSetupController extends Controller {
123124
private $iniGetWrapper;
124125
/** @var IDBConnection */
125126
private $connection;
127+
/** @var IThrottler */
128+
private $throttler;
126129
/** @var ITempManager */
127130
private $tempManager;
128131
/** @var IManager */
@@ -148,6 +151,7 @@ public function __construct($AppName,
148151
ISecureRandom $secureRandom,
149152
IniGetWrapper $iniGetWrapper,
150153
IDBConnection $connection,
154+
IThrottler $throttler,
151155
ITempManager $tempManager,
152156
IManager $manager,
153157
IAppManager $appManager,
@@ -162,6 +166,7 @@ public function __construct($AppName,
162166
$this->logger = $logger;
163167
$this->dispatcher = $dispatcher;
164168
$this->db = $db;
169+
$this->throttler = $throttler;
165170
$this->lockingProvider = $lockingProvider;
166171
$this->dateTimeFormatter = $dateTimeFormatter;
167172
$this->memoryInfo = $memoryInfo;
@@ -920,6 +925,8 @@ public function check() {
920925
'cronInfo' => $this->getLastCronInfo(),
921926
'cronErrors' => $this->getCronErrors(),
922927
'isFairUseOfFreePushService' => $this->isFairUseOfFreePushService(),
928+
'isBruteforceThrottled' => $this->throttler->getAttempts($this->request->getRemoteAddress()) !== 0,
929+
'bruteforceRemoteAddress' => $this->request->getRemoteAddress(),
923930
'serverHasInternetConnectionProblems' => $this->hasInternetConnectivityProblems(),
924931
'isMemcacheConfigured' => $this->isMemcacheConfigured(),
925932
'memcacheDocs' => $this->urlGenerator->linkToDocs('admin-performance'),

apps/settings/tests/Controller/CheckSetupControllerTest.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
use OCP\IURLGenerator;
6060
use OCP\Lock\ILockingProvider;
6161
use OCP\Notification\IManager;
62+
use OCP\Security\Bruteforce\IThrottler;
6263
use PHPUnit\Framework\MockObject\MockObject;
6364
use Psr\Http\Message\ResponseInterface;
6465
use Psr\Log\LoggerInterface;
@@ -143,6 +144,7 @@ protected function setUp(): void {
143144
$this->logger = $this->getMockBuilder(LoggerInterface::class)->getMock();
144145
$this->db = $this->getMockBuilder(Connection::class)
145146
->disableOriginalConstructor()->getMock();
147+
$this->throttler = $this->createMock(IThrottler::class);
146148
$this->lockingProvider = $this->getMockBuilder(ILockingProvider::class)->getMock();
147149
$this->dateTimeFormatter = $this->getMockBuilder(IDateTimeFormatter::class)->getMock();
148150
$this->memoryInfo = $this->getMockBuilder(MemoryInfo::class)
@@ -174,6 +176,7 @@ protected function setUp(): void {
174176
$this->secureRandom,
175177
$this->iniGetWrapper,
176178
$this->connection,
179+
$this->throttler,
177180
$this->tempManager,
178181
$this->notificationManager,
179182
$this->appManager,
@@ -659,6 +662,8 @@ public function testCheck() {
659662
'isFairUseOfFreePushService' => false,
660663
'temporaryDirectoryWritable' => false,
661664
\OCA\Settings\SetupChecks\LdapInvalidUuids::class => ['pass' => true, 'description' => 'Invalid UUIDs of LDAP users or groups have been found. Please review your "Override UUID detection" settings in the Expert part of the LDAP configuration and use "occ ldap:update-uuid" to update them.', 'severity' => 'warning'],
665+
'isBruteforceThrottled' => false,
666+
'bruteforceRemoteAddress' => '',
662667
]
663668
);
664669
$this->assertEquals($expected, $this->checkSetupController->check());
@@ -683,6 +688,7 @@ public function testGetCurlVersion() {
683688
$this->secureRandom,
684689
$this->iniGetWrapper,
685690
$this->connection,
691+
$this->throttler,
686692
$this->tempManager,
687693
$this->notificationManager,
688694
$this->appManager,
@@ -1410,6 +1416,7 @@ public function testIsMysqlUsedWithoutUTF8MB4(string $db, bool $useUTF8MB4, bool
14101416
$this->secureRandom,
14111417
$this->iniGetWrapper,
14121418
$this->connection,
1419+
$this->throttler,
14131420
$this->tempManager,
14141421
$this->notificationManager,
14151422
$this->appManager,
@@ -1464,6 +1471,7 @@ public function testIsEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed(string $m
14641471
$this->secureRandom,
14651472
$this->iniGetWrapper,
14661473
$this->connection,
1474+
$this->throttler,
14671475
$this->tempManager,
14681476
$this->notificationManager,
14691477
$this->appManager,

core/js/setupchecks.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,14 @@
215215
type: OC.SetupChecks.MESSAGE_TYPE_INFO
216216
});
217217
}
218+
if (data.isBruteforceThrottled) {
219+
messages.push({
220+
msg: t('core', 'Your remote address was identified as "{remoteAddress}" and is bruteforce throttled at the moment slowing down the performance of various requests. If the remote address is not your address this can be an indication that a proxy is not configured correctly. Further information can be found in the {linkstart}documentation ↗{linkend}.', { remoteAddress: data.bruteforceRemoteAddress })
221+
.replace('{linkstart}', '<a target="_blank" rel="noreferrer noopener" class="external" href="' + data.reverseProxyDocs + '">')
222+
.replace('{linkend}', '</a>'),
223+
type: OC.SetupChecks.MESSAGE_TYPE_ERROR
224+
});
225+
}
218226
if(!data.hasWorkingFileLocking) {
219227
messages.push({
220228
msg: t('core', 'Transactional file locking is disabled, this might lead to issues with race conditions. Enable "filelocking.enabled" in config.php to avoid these problems. See the {linkstart}documentation ↗{linkend} for more information.')

core/js/tests/specs/setupchecksSpec.js

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -814,6 +814,67 @@ describe('OC.SetupChecks tests', function() {
814814
});
815815
});
816816

817+
it('should return an error if the admin IP is bruteforce throttled', function(done) {
818+
var async = OC.SetupChecks.checkSetup();
819+
820+
suite.server.requests[0].respond(
821+
200,
822+
{
823+
'Content-Type': 'application/json',
824+
},
825+
JSON.stringify({
826+
hasFileinfoInstalled: true,
827+
isGetenvServerWorking: true,
828+
isReadOnlyConfig: false,
829+
wasEmailTestSuccessful: true,
830+
hasWorkingFileLocking: true,
831+
hasDBFileLocking: false,
832+
hasValidTransactionIsolationLevel: true,
833+
suggestedOverwriteCliURL: '',
834+
isRandomnessSecure: true,
835+
isFairUseOfFreePushService: true,
836+
isBruteforceThrottled: true,
837+
bruteforceRemoteAddress: '::1',
838+
serverHasInternetConnectionProblems: false,
839+
isMemcacheConfigured: true,
840+
forwardedForHeadersWorking: true,
841+
reverseProxyDocs: 'https://docs.nextcloud.com/foo/bar.html',
842+
isCorrectMemcachedPHPModuleInstalled: true,
843+
hasPassedCodeIntegrityCheck: true,
844+
OpcacheSetupRecommendations: [],
845+
isSettimelimitAvailable: true,
846+
hasFreeTypeSupport: true,
847+
missingIndexes: [],
848+
missingPrimaryKeys: [],
849+
missingColumns: [],
850+
cronErrors: [],
851+
cronInfo: {
852+
diffInSeconds: 0
853+
},
854+
isMemoryLimitSufficient: true,
855+
appDirsWithDifferentOwner: [],
856+
isImagickEnabled: true,
857+
areWebauthnExtensionsEnabled: true,
858+
is64bit: true,
859+
recommendedPHPModules: [],
860+
pendingBigIntConversionColumns: [],
861+
isMysqlUsedWithoutUTF8MB4: false,
862+
isDefaultPhoneRegionSet: true,
863+
isEnoughTempSpaceAvailableIfS3PrimaryStorageIsUsed: true,
864+
reverseProxyGeneratedURL: 'https://server',
865+
temporaryDirectoryWritable: true,
866+
})
867+
);
868+
869+
async.done(function( data, s, x ){
870+
expect(data).toEqual([{
871+
msg: 'Your remote address was identified as "::1" and is bruteforce throttled at the moment slowing down the performance of various requests. If the remote address is not your address this can be an indication that a proxy is not configured correctly. Further information can be found in the <a target="_blank" rel="noreferrer noopener" class="external" href="https://docs.nextcloud.com/foo/bar.html">documentation ↗</a>.',
872+
type: OC.SetupChecks.MESSAGE_TYPE_ERROR
873+
}]);
874+
done();
875+
});
876+
});
877+
817878
it('should return an error if set_time_limit is unavailable', function(done) {
818879
var async = OC.SetupChecks.checkSetup();
819880

0 commit comments

Comments
 (0)