Skip to content

Commit

Permalink
FIX Allow logged in user with permissions to bypass basic auth
Browse files Browse the repository at this point in the history
  • Loading branch information
emteknetnz committed Jan 15, 2025
1 parent d33f344 commit f9c63fe
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 8 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
],
"require": {
"php": "^8.1",
"silverstripe/framework": "^5",
"silverstripe/framework": "^5.3",
"silverstripe/versioned": "^2",
"guzzlehttp/guzzle": "^7"
},
Expand Down
12 changes: 5 additions & 7 deletions src/EnvironmentChecker.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,11 @@ public function __construct($checkSuiteName, $title)
*/
public function init($permission = 'ADMIN')
{
$canAccess = $this->canAccess(null, $permission);
// Allow bypassing basic-auth check if the user is logged in with the required permission
if ($canAccess) {
return;
}
// if the environment supports it, provide a basic auth challenge and see if it matches configured credentials
if (Environment::getEnv('ENVCHECK_BASICAUTH_USERNAME')
&& Environment::getEnv('ENVCHECK_BASICAUTH_PASSWORD')
Expand All @@ -117,13 +122,6 @@ public function init($permission = 'ADMIN')
$response->addHeader('WWW-Authenticate', "Basic realm=\"Environment check\"");
throw new HTTPResponse_Exception($response);
}
} elseif (!$this->canAccess(null, $permission)) {
// Fail check with silverstripe login challenge
$result = Security::permissionFailure(
$this,
"You must have the {$permission} permission to access this check"
);
throw new HTTPResponse_Exception($result);
}
}

Expand Down
83 changes: 83 additions & 0 deletions tests/EnvironmentCheckerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace SilverStripe\EnvironmentCheck\Tests;

use ReflectionProperty;
use Monolog\Logger;
use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;
Expand All @@ -10,6 +11,9 @@
use SilverStripe\Dev\SapphireTest;
use SilverStripe\EnvironmentCheck\EnvironmentChecker;
use SilverStripe\EnvironmentCheck\EnvironmentCheckSuite;
use SilverStripe\Core\Environment;
use SilverStripe\Core\Kernel;
use SilverStripe\Control\HTTPResponse_Exception;

/**
* Class EnvironmentCheckerTest
Expand Down Expand Up @@ -94,4 +98,83 @@ public function testLogsWithErrors()

(new EnvironmentChecker('test suite', 'test'))->index();
}

public static function provideBasicAuthAdminBypass(): array
{
return [
'logged-out-valid-creds' => [
'user' => 'logged-out',
'validCreds' => true,
'expectedSuccess' => true,
],
'logged-out-invalid-creds' => [
'user' => 'logged-out',
'validCreds' => false,
'expectedSuccess' => false,
],
'non-admin-valid-creds' => [
'user' => 'non-admin',
'validCreds' => true,
'expectedSuccess' => true,
],
'non-admin-invalid-creds' => [
'user' => 'non-admin',
'validCreds' => false,
'expectedSuccess' => false,
],
'admin-valid-creds' => [
'user' => 'admin',
'validCreds' => true,
'expectedSuccess' => true,
],
'admin-invalid-creds' => [
'user' => 'admin',
'validCreds' => false,
'expectedSuccess' => true,
],
];
}

/**
* @dataProvider provideBasicAuthAdminBypass
*/
public function testBasicAuthAdminBypass(
string $user,
bool $validCreds,
bool $expectedSuccess,
): void {
// Pretend we're not using CLI which will bypass basic auth,
$reflectionCli = new ReflectionProperty(Environment::class, 'isCliOverride');
$reflectionCli->setAccessible(true);
$reflectionCli->setValue(false);
// Change from dev to test mode as dev mode will bypass basic auth
$kernel = Injector::inst()->get(Kernel::class);
$kernel->setEnvironment('test');
// Setup basic auth env variables
Environment::setEnv('ENVCHECK_BASICAUTH_USERNAME', 'test');
Environment::setEnv('ENVCHECK_BASICAUTH_PASSWORD', 'password');
// Log in or out
if ($user === 'admin') {
$this->logInWithPermission('ADMIN');
} elseif ($user === 'non-admin') {
$this->logInWithPermission('NOT_AN_ADMIN');
} else {
$this->logOut();
}
// Simulate passing in basic auth creds
$_SERVER['PHP_AUTH_USER'] = 'test';
$_SERVER['PHP_AUTH_PW'] = $validCreds ? 'password' : 'invalid';
// Run test
$checker = new EnvironmentChecker('test suite', 'test');
$success = null;
try {
$checker->init();
$success = true;
} catch (HTTPResponse_Exception $e) {
$success = false;
$response = $e->getResponse();
$this->assertEquals(401, $response->getStatusCode());
}
$this->assertSame($expectedSuccess, $success);
}
}

0 comments on commit f9c63fe

Please sign in to comment.