Support encrypted connections to MySQL/Maria and Postgres

This commit is contained in:
Alejandro Celaya 2024-12-18 09:47:21 +01:00
parent 83570f5c25
commit 4e7d09035a
2 changed files with 22 additions and 10 deletions

View File

@ -12,9 +12,10 @@ use function Shlinkio\Shlink\Core\ArrayUtils\contains;
return (static function (): array { return (static function (): array {
$driver = EnvVars::DB_DRIVER->loadFromEnv(); $driver = EnvVars::DB_DRIVER->loadFromEnv();
$useEncryption = (bool) EnvVars::DB_USE_ENCRYPTION->loadFromEnv();
$isMysqlCompatible = contains($driver, ['maria', 'mysql']); $isMysqlCompatible = contains($driver, ['maria', 'mysql']);
$resolveDriver = static fn () => match ($driver) { $doctrineDriver = match ($driver) {
'postgres' => 'pdo_pgsql', 'postgres' => 'pdo_pgsql',
'mssql' => 'pdo_sqlsrv', 'mssql' => 'pdo_sqlsrv',
default => 'pdo_mysql', default => 'pdo_mysql',
@ -23,31 +24,40 @@ return (static function (): array {
$value = $envVar->loadFromEnv(); $value = $envVar->loadFromEnv();
return $value === null ? null : (string) $value; return $value === null ? null : (string) $value;
}; };
$resolveCharset = static fn () => match ($driver) { $charset = match ($driver) {
// This does not determine charsets or collations in tables or columns, but the charset used in the data // This does not determine charsets or collations in tables or columns, but the charset used in the data
// flowing in the connection, so it has to match what has been set in the database. // flowing in the connection, so it has to match what has been set in the database.
'maria', 'mysql' => 'utf8mb4', 'maria', 'mysql' => 'utf8mb4',
'postgres' => 'utf8', 'postgres' => 'utf8',
default => null, default => null,
}; };
$driverOptions = match ($driver) {
$resolveConnection = static fn () => match ($driver) { 'mssql' => ['TrustServerCertificate' => 'true'],
'maria', 'mysql' => ! $useEncryption ? [] : [
1007 => true, // PDO::MYSQL_ATTR_SSL_KEY: Require using SSL
1014 => false, // PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT: Trust any certificate
],
'postgres' => ! $useEncryption ? [] : [
'sslmode' => 'require', // Require connections to be encrypted
'sslrootcert' => '', // Allow any certificate
],
default => [],
};
$connection = match ($driver) {
null, 'sqlite' => [ null, 'sqlite' => [
'driver' => 'pdo_sqlite', 'driver' => 'pdo_sqlite',
'path' => 'data/database.sqlite', 'path' => 'data/database.sqlite',
], ],
default => [ default => [
'driver' => $resolveDriver(), 'driver' => $doctrineDriver,
'dbname' => EnvVars::DB_NAME->loadFromEnv(), 'dbname' => EnvVars::DB_NAME->loadFromEnv(),
'user' => $readCredentialAsString(EnvVars::DB_USER), 'user' => $readCredentialAsString(EnvVars::DB_USER),
'password' => $readCredentialAsString(EnvVars::DB_PASSWORD), 'password' => $readCredentialAsString(EnvVars::DB_PASSWORD),
'host' => EnvVars::DB_HOST->loadFromEnv(), 'host' => EnvVars::DB_HOST->loadFromEnv(),
'port' => EnvVars::DB_PORT->loadFromEnv(), 'port' => EnvVars::DB_PORT->loadFromEnv(),
'unix_socket' => $isMysqlCompatible ? EnvVars::DB_UNIX_SOCKET->loadFromEnv() : null, 'unix_socket' => $isMysqlCompatible ? EnvVars::DB_UNIX_SOCKET->loadFromEnv() : null,
'charset' => $resolveCharset(), 'charset' => $charset,
'driverOptions' => $driver !== 'mssql' ? [] : [ 'driverOptions' => $driverOptions,
'TrustServerCertificate' => 'true',
],
], ],
}; };
@ -63,7 +73,7 @@ return (static function (): array {
Events::postFlush => [ShortUrlVisitsCountTracker::class, OrphanVisitsCountTracker::class], Events::postFlush => [ShortUrlVisitsCountTracker::class, OrphanVisitsCountTracker::class],
], ],
], ],
'connection' => $resolveConnection(), 'connection' => $connection,
], ],
]; ];

View File

@ -36,6 +36,7 @@ enum EnvVars: string
case DB_HOST = 'DB_HOST'; case DB_HOST = 'DB_HOST';
case DB_UNIX_SOCKET = 'DB_UNIX_SOCKET'; case DB_UNIX_SOCKET = 'DB_UNIX_SOCKET';
case DB_PORT = 'DB_PORT'; case DB_PORT = 'DB_PORT';
case DB_USE_ENCRYPTION = 'DB_USE_ENCRYPTION';
case GEOLITE_LICENSE_KEY = 'GEOLITE_LICENSE_KEY'; case GEOLITE_LICENSE_KEY = 'GEOLITE_LICENSE_KEY';
case CACHE_NAMESPACE = 'CACHE_NAMESPACE'; case CACHE_NAMESPACE = 'CACHE_NAMESPACE';
case REDIS_SERVERS = 'REDIS_SERVERS'; case REDIS_SERVERS = 'REDIS_SERVERS';
@ -147,6 +148,7 @@ enum EnvVars: string
'mssql' => '1433', 'mssql' => '1433',
default => '3306', default => '3306',
}, },
self::DB_USE_ENCRYPTION => false,
self::MERCURE_INTERNAL_HUB_URL => self::MERCURE_PUBLIC_HUB_URL->loadFromEnv(), self::MERCURE_INTERNAL_HUB_URL => self::MERCURE_PUBLIC_HUB_URL->loadFromEnv(),