Harden permissions for sqlite runtime
This commit is contained in:
@@ -90,6 +90,7 @@ class UpgradeCommand extends Command
|
|||||||
try {
|
try {
|
||||||
$this->configureGitSafeDirectory();
|
$this->configureGitSafeDirectory();
|
||||||
$this->ensureGitRepository();
|
$this->ensureGitRepository();
|
||||||
|
$this->ensureWritableStorage();
|
||||||
$statusResult = $this->executeCommand('git status --porcelain');
|
$statusResult = $this->executeCommand('git status --porcelain');
|
||||||
if ($statusResult['exitCode'] !== 0) {
|
if ($statusResult['exitCode'] !== 0) {
|
||||||
throw new Exception($statusResult['output'] ?: 'Unable to read git status.');
|
throw new Exception($statusResult['output'] ?: 'Unable to read git status.');
|
||||||
@@ -317,6 +318,13 @@ class UpgradeCommand extends Command
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function ensureWritableStorage(): void
|
||||||
|
{
|
||||||
|
foreach ($this->getWritableStorageCommands() as $command) {
|
||||||
|
$this->executeCommand($command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected function getSafeDirectoryCommands(): array
|
protected function getSafeDirectoryCommands(): array
|
||||||
{
|
{
|
||||||
$directory = $this->basePath;
|
$directory = $this->basePath;
|
||||||
@@ -337,6 +345,28 @@ class UpgradeCommand extends Command
|
|||||||
return $commands;
|
return $commands;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function getWritableStorageCommands(): array
|
||||||
|
{
|
||||||
|
if (! $this->isRunningAsRoot() || ! $this->userExists('www-data')) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$paths = [
|
||||||
|
$this->basePath.'/database',
|
||||||
|
$this->basePath.'/storage',
|
||||||
|
$this->basePath.'/bootstrap/cache',
|
||||||
|
];
|
||||||
|
|
||||||
|
$escapedPaths = array_map('escapeshellarg', $paths);
|
||||||
|
$pathList = implode(' ', $escapedPaths);
|
||||||
|
|
||||||
|
return [
|
||||||
|
"chgrp -R www-data {$pathList}",
|
||||||
|
"chmod -R g+rwX {$pathList}",
|
||||||
|
"find {$pathList} -type d -exec chmod g+s {} +",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
protected function commandExists(string $command): bool
|
protected function commandExists(string $command): bool
|
||||||
{
|
{
|
||||||
$result = $this->executeCommand("command -v {$command}");
|
$result = $this->executeCommand("command -v {$command}");
|
||||||
|
|||||||
13
install.sh
13
install.sh
@@ -768,6 +768,19 @@ clone_jabali() {
|
|||||||
git config --system --add safe.directory "$JABALI_DIR" 2>/dev/null || true
|
git config --system --add safe.directory "$JABALI_DIR" 2>/dev/null || true
|
||||||
sudo -u $JABALI_USER git config --global --add safe.directory "$JABALI_DIR" 2>/dev/null || true
|
sudo -u $JABALI_USER git config --global --add safe.directory "$JABALI_DIR" 2>/dev/null || true
|
||||||
|
|
||||||
|
# Ensure runtime directories stay writable for PHP-FPM (default: www-data)
|
||||||
|
if id www-data &>/dev/null; then
|
||||||
|
chown -R $JABALI_USER:www-data \
|
||||||
|
"$JABALI_DIR/database" \
|
||||||
|
"$JABALI_DIR/storage" \
|
||||||
|
"$JABALI_DIR/bootstrap/cache" 2>/dev/null || true
|
||||||
|
chmod -R g+rwX \
|
||||||
|
"$JABALI_DIR/database" \
|
||||||
|
"$JABALI_DIR/storage" \
|
||||||
|
"$JABALI_DIR/bootstrap/cache" 2>/dev/null || true
|
||||||
|
find "$JABALI_DIR/database" "$JABALI_DIR/storage" "$JABALI_DIR/bootstrap/cache" -type d -exec chmod g+s {} + 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
# Read version from cloned VERSION file
|
# Read version from cloned VERSION file
|
||||||
if [[ -f "$JABALI_DIR/VERSION" ]]; then
|
if [[ -f "$JABALI_DIR/VERSION" ]]; then
|
||||||
source "$JABALI_DIR/VERSION"
|
source "$JABALI_DIR/VERSION"
|
||||||
|
|||||||
@@ -110,6 +110,40 @@ class UpgradeCommandTest extends TestCase
|
|||||||
'sudo -u www-data git config --global --add safe.directory '.base_path(),
|
'sudo -u www-data git config --global --add safe.directory '.base_path(),
|
||||||
], $command->exposesSafeDirectoryCommands());
|
], $command->exposesSafeDirectoryCommands());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function test_writable_storage_commands_for_non_root(): void
|
||||||
|
{
|
||||||
|
$command = new SafeDirectoryUpgradeCommand(false, true, true);
|
||||||
|
|
||||||
|
$this->assertSame([], $command->exposesWritableStorageCommands());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_writable_storage_commands_without_www_data(): void
|
||||||
|
{
|
||||||
|
$command = new SafeDirectoryUpgradeCommand(true, true, false);
|
||||||
|
|
||||||
|
$this->assertSame([], $command->exposesWritableStorageCommands());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_writable_storage_commands_for_root_with_www_data(): void
|
||||||
|
{
|
||||||
|
$command = new SafeDirectoryUpgradeCommand(true, true, true);
|
||||||
|
|
||||||
|
$paths = [
|
||||||
|
base_path().'/database',
|
||||||
|
base_path().'/storage',
|
||||||
|
base_path().'/bootstrap/cache',
|
||||||
|
];
|
||||||
|
|
||||||
|
$escaped = array_map('escapeshellarg', $paths);
|
||||||
|
$list = implode(' ', $escaped);
|
||||||
|
|
||||||
|
$this->assertSame([
|
||||||
|
"chgrp -R www-data {$list}",
|
||||||
|
"chmod -R g+rwX {$list}",
|
||||||
|
"find {$list} -type d -exec chmod g+s {} +",
|
||||||
|
], $command->exposesWritableStorageCommands());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TestableUpgradeCommand extends UpgradeCommand
|
class TestableUpgradeCommand extends UpgradeCommand
|
||||||
@@ -145,6 +179,11 @@ class SafeDirectoryUpgradeCommand extends UpgradeCommand
|
|||||||
return $this->getSafeDirectoryCommands();
|
return $this->getSafeDirectoryCommands();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function exposesWritableStorageCommands(): array
|
||||||
|
{
|
||||||
|
return $this->getWritableStorageCommands();
|
||||||
|
}
|
||||||
|
|
||||||
protected function isRunningAsRoot(): bool
|
protected function isRunningAsRoot(): bool
|
||||||
{
|
{
|
||||||
return $this->runningAsRoot;
|
return $this->runningAsRoot;
|
||||||
|
|||||||
Reference in New Issue
Block a user