diff options
Diffstat (limited to 'www/wiki/tests/integration/includes/shell/FirejailCommandTest.php')
-rw-r--r-- | www/wiki/tests/integration/includes/shell/FirejailCommandTest.php | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/www/wiki/tests/integration/includes/shell/FirejailCommandTest.php b/www/wiki/tests/integration/includes/shell/FirejailCommandTest.php new file mode 100644 index 00000000..1e008ee2 --- /dev/null +++ b/www/wiki/tests/integration/includes/shell/FirejailCommandTest.php @@ -0,0 +1,78 @@ +<?php + +use MediaWiki\Shell\FirejailCommand; +use MediaWiki\Shell\Shell; + +/** + * Integration tests to ensure that firejail actually prevents execution. + * Meant to run on vagrant, although will probably work on other setups + * as long as firejail and sudo has similar config. + * + * @group large + * @group Shell + * @covers FirejailCommand + */ +class FirejailCommandIntegrationTest extends PHPUnit\Framework\TestCase { + + public function setUp() { + parent::setUp(); + if ( Shell::command( 'which', 'firejail' )->execute()->getExitCode() ) { + $this->markTestSkipped( 'firejail not installed' ); + } elseif ( wfIsWindows() ) { + $this->markTestSkipped( 'test supports POSIX environments only' ); + } + } + + public function testSanity() { + // Make sure that firejail works at all. + $command = new FirejailCommand( 'firejail' ); + $command + ->unsafeParams( 'ls .' ) + ->restrict( Shell::RESTRICT_DEFAULT ); + $result = $command->execute(); + $this->assertSame( 0, $result->getExitCode() ); + } + + /** + * @coversNothing + * @dataProvider provideExecute + */ + public function testExecute( $testCommand, $flag ) { + if ( preg_match( '/^sudo /', $testCommand ) ) { + if ( Shell::command( 'sudo', '-n', 'ls', '/' )->execute()->getExitCode() ) { + $this->markTestSkipped( 'need passwordless sudo' ); + } + } + + $command = new FirejailCommand( 'firejail' ); + $command + ->unsafeParams( $testCommand ) + // If we don't restrict at all, firejail won't be invoked, + // so the test will give a false positive if firejail breaks + // the command for some non-flag-related reason. Instead, + // set some flag that won't get in the way. + ->restrict( $flag === Shell::NO_NETWORK ? Shell::PRIVATE_DEV : Shell::NO_NETWORK ); + $result = $command->execute(); + $this->assertSame( 0, $result->getExitCode(), 'sanity check' ); + + $command = new FirejailCommand( 'firejail' ); + $command + ->unsafeParams( $testCommand ) + ->restrict( $flag ); + $result = $command->execute(); + $this->assertNotSame( 0, $result->getExitCode(), 'real check' ); + } + + public function provideExecute() { + global $IP; + return [ + [ 'sudo -n ls /', Shell::NO_ROOT ], + [ 'sudo -n ls /', Shell::SECCOMP ], // not a great test but seems to work + [ 'ls /dev/cpu', Shell::PRIVATE_DEV ], + [ 'curl -fsSo /dev/null https://wikipedia.org/', Shell::NO_NETWORK ], + [ 'exec ls /', Shell::NO_EXECVE ], + [ "cat $IP/LocalSettings.php", Shell::NO_LOCALSETTINGS ], + ]; + } + +} |