Globinours/app/Services/SecurityService.php

97 lines
2.7 KiB
PHP

<?php
declare(strict_types=1);
final class SecurityService
{
public static function publicError(Throwable $e): string
{
$reference = strtoupper(substr(bin2hex(random_bytes(6)), 0, 10));
error_log(
'[Globinours ' .
$reference .
'] ' .
get_class($e) .
': ' .
$e->getMessage() .
' in ' .
$e->getFile() .
':' .
$e->getLine(),
);
return t('error.unexpected_reference', ['reference' => $reference]);
}
public static function hardenRuntimeFiles(): void
{
$root = dirname(__DIR__, 2);
$marker = $root . '/storage/.security-hardened';
if (is_file($marker) && filemtime($marker) > time() - 86400) {
return;
}
foreach (
[
$root . '/data',
$root . '/storage',
$root . '/data/private-media',
$root . '/data/medical-documents',
$root . '/data/grants',
$root . '/storage/backups',
$root . '/storage/logs',
$root . '/storage/asm3-imports',
]
as $dir
) {
if (is_dir($dir)) {
@chmod($dir, 0700);
}
}
foreach (
[
$root . '/.env',
$root . '/data/refuge.sqlite',
$root . '/data/refuge.sqlite-wal',
$root . '/data/refuge.sqlite-shm',
]
as $file
) {
if (is_file($file)) {
@chmod($file, 0600);
}
}
foreach (
[
'storage/backups/*',
'storage/logs/*',
'storage/reports/*',
'data/private-media/*',
'data/medical-documents/*',
'data/grants/*',
]
as $pattern
) {
foreach (glob($root . '/' . $pattern) ?: [] as $file) {
self::hardenTree($file);
}
}
@touch($marker);
@chmod($marker, 0600);
}
private static function hardenTree(string $path): void
{
if (is_file($path)) {
@chmod($path, 0600);
return;
}
if (!is_dir($path)) {
return;
}
@chmod($path, 0700);
$it = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS),
RecursiveIteratorIterator::SELF_FIRST,
);
foreach ($it as $item) {
@chmod($item->getPathname(), $item->isDir() ? 0700 : 0600);
}
}
}