3
0
mirror of https://github.com/snipe/snipe-it.git synced 2026-08-18 11:15:42 +00:00
Files
snipe-it/tests/Unit/DatabaseSslConfigurationTest.php

161 lines
5.9 KiB
PHP

<?php
namespace Tests\Unit;
use PDO;
use Tests\TestCase;
/**
* Coverage for the PDO SSL options block in config/database.php. Loads the
* real config file under different env combinations rather than a hand-rolled
* simulator, so the tests would actually catch a regression in the file
* itself (which the earlier simulator-based version could not, see #19411).
*/
class DatabaseSslConfigurationTest extends TestCase
{
/**
* Set the env vars this test needs, re-require the config file, and
* return the fully-built connections array. Any env key not passed is
* unset so it doesn't leak in from the surrounding test env.
*
* @param array<string, string|null> $env
* @return array<string, mixed>
*/
private function loadDatabaseConfig(array $env): array
{
$keys = [
'DB_SSL',
'DB_SSL_IS_PAAS',
'DB_SSL_KEY_PATH',
'DB_SSL_CERT_PATH',
'DB_SSL_CA_PATH',
'DB_SSL_CIPHER',
'DB_SSL_VERIFY_SERVER',
];
foreach ($keys as $key) {
unset($_ENV[$key], $_SERVER[$key]);
putenv($key);
}
foreach ($env as $key => $value) {
if ($value === null) {
$_ENV[$key] = 'null';
$_SERVER[$key] = 'null';
putenv("$key=null");
} else {
$_ENV[$key] = $value;
$_SERVER[$key] = $value;
putenv("$key=$value");
}
}
return require base_path('config/database.php');
}
public function test_ssl_disabled_yields_no_pdo_options(): void
{
$config = $this->loadDatabaseConfig(['DB_SSL' => 'false']);
$this->assertSame([], $config['connections']['mysql']['options']);
$this->assertSame([], $config['connections']['mariadb']['options']);
}
public function test_ssl_enabled_paas_mode_includes_ca_and_verify_only(): void
{
$config = $this->loadDatabaseConfig([
'DB_SSL' => 'true',
'DB_SSL_IS_PAAS' => 'true',
'DB_SSL_CA_PATH' => '/path/to/ca.pem',
'DB_SSL_VERIFY_SERVER' => 'true',
]);
$options = $config['connections']['mysql']['options'];
$this->assertSame('/path/to/ca.pem', $options[PDO::MYSQL_ATTR_SSL_CA]);
$this->assertTrue($options[PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT]);
$this->assertArrayNotHasKey(PDO::MYSQL_ATTR_SSL_KEY, $options);
$this->assertArrayNotHasKey(PDO::MYSQL_ATTR_SSL_CERT, $options);
$this->assertArrayNotHasKey(PDO::MYSQL_ATTR_SSL_CIPHER, $options);
}
public function test_ssl_enabled_self_hosted_mode_includes_full_client_cert_set(): void
{
$config = $this->loadDatabaseConfig([
'DB_SSL' => 'true',
'DB_SSL_KEY_PATH' => '/path/to/key.pem',
'DB_SSL_CERT_PATH' => '/path/to/cert.pem',
'DB_SSL_CA_PATH' => '/path/to/ca.pem',
'DB_SSL_CIPHER' => 'ECDHE-RSA-AES256-GCM-SHA384',
]);
$options = $config['connections']['mysql']['options'];
$this->assertSame('/path/to/key.pem', $options[PDO::MYSQL_ATTR_SSL_KEY]);
$this->assertSame('/path/to/cert.pem', $options[PDO::MYSQL_ATTR_SSL_CERT]);
$this->assertSame('/path/to/ca.pem', $options[PDO::MYSQL_ATTR_SSL_CA]);
$this->assertSame('ECDHE-RSA-AES256-GCM-SHA384', $options[PDO::MYSQL_ATTR_SSL_CIPHER]);
}
public function test_null_cipher_is_omitted_not_passed_as_null(): void
{
// Regression for #19411. .env.example ships DB_SSL_CIPHER=null and
// the old code passed that through as PDO::MYSQL_ATTR_SSL_CIPHER =>
// null, which made libmysql / libmariadb fail with "Cannot connect
// to MySQL using SSL". A null cipher MUST be omitted so the driver
// negotiates a default.
$config = $this->loadDatabaseConfig([
'DB_SSL' => 'true',
'DB_SSL_KEY_PATH' => '/path/to/key.pem',
'DB_SSL_CERT_PATH' => '/path/to/cert.pem',
'DB_SSL_CA_PATH' => '/path/to/ca.pem',
'DB_SSL_CIPHER' => null,
]);
$options = $config['connections']['mysql']['options'];
$this->assertArrayNotHasKey(PDO::MYSQL_ATTR_SSL_CIPHER, $options);
}
public function test_null_paths_are_omitted_across_every_ssl_key(): void
{
// Same shape trap as CIPHER: any of the path envs left at the
// .env.example default of `null` would land as PDO::MYSQL_ATTR_SSL_*
// => null and break the SSL handshake. Every path key gets the
// omit-when-null treatment.
$config = $this->loadDatabaseConfig([
'DB_SSL' => 'true',
'DB_SSL_KEY_PATH' => null,
'DB_SSL_CERT_PATH' => null,
'DB_SSL_CA_PATH' => null,
'DB_SSL_CIPHER' => null,
]);
$options = $config['connections']['mysql']['options'];
$this->assertArrayNotHasKey(PDO::MYSQL_ATTR_SSL_KEY, $options);
$this->assertArrayNotHasKey(PDO::MYSQL_ATTR_SSL_CERT, $options);
$this->assertArrayNotHasKey(PDO::MYSQL_ATTR_SSL_CA, $options);
$this->assertArrayNotHasKey(PDO::MYSQL_ATTR_SSL_CIPHER, $options);
// VERIFY_SERVER_CERT is always included with a bool cast because
// both true and false are valid values.
$this->assertArrayHasKey(PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT, $options);
$this->assertFalse($options[PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT]);
}
public function test_mariadb_connection_shares_the_same_ssl_options(): void
{
$config = $this->loadDatabaseConfig([
'DB_SSL' => 'true',
'DB_SSL_KEY_PATH' => '/path/to/key.pem',
'DB_SSL_CERT_PATH' => '/path/to/cert.pem',
'DB_SSL_CA_PATH' => '/path/to/ca.pem',
]);
$this->assertSame(
$config['connections']['mysql']['options'],
$config['connections']['mariadb']['options']
);
}
}