Skip to content

Commit d405adb

Browse files
ENGCOM-6218: Enable Magento 2 to connect MySQL through SSL. magento#25398
2 parents 8439b5a + dd51cb1 commit d405adb

File tree

13 files changed

+372
-16
lines changed

13 files changed

+372
-16
lines changed

lib/internal/Magento/Framework/Config/ConfigOptionsListConstants.php

+27-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ class ConfigOptionsListConstants
2121
const CONFIG_PATH_CRYPT_KEY = 'crypt/key';
2222
const CONFIG_PATH_SESSION_SAVE = 'session/save';
2323
const CONFIG_PATH_RESOURCE_DEFAULT_SETUP = 'resource/default_setup/connection';
24+
const CONFIG_PATH_DB_CONNECTION_DEFAULT_DRIVER_OPTIONS = 'db/connection/default/driver_options';
2425
const CONFIG_PATH_DB_CONNECTION_DEFAULT = 'db/connection/default';
2526
const CONFIG_PATH_DB_CONNECTIONS = 'db/connection';
2627
const CONFIG_PATH_DB_PREFIX = 'db/table_prefix';
@@ -64,6 +65,10 @@ class ConfigOptionsListConstants
6465
const INPUT_KEY_DB_MODEL = 'db-model';
6566
const INPUT_KEY_DB_INIT_STATEMENTS = 'db-init-statements';
6667
const INPUT_KEY_DB_ENGINE = 'db-engine';
68+
const INPUT_KEY_DB_SSL_KEY = 'db-ssl-key';
69+
const INPUT_KEY_DB_SSL_CERT = 'db-ssl-cert';
70+
const INPUT_KEY_DB_SSL_CA = 'db-ssl-ca';
71+
const INPUT_KEY_DB_SSL_VERIFY = 'db-ssl-verify';
6772
const INPUT_KEY_RESOURCE = 'resource';
6873
const INPUT_KEY_SKIP_DB_VALIDATION = 'skip-db-validation';
6974
const INPUT_KEY_CACHE_HOSTS = 'http-cache-hosts';
@@ -75,7 +80,11 @@ class ConfigOptionsListConstants
7580
const KEY_CACHE_FRONTEND = 'cache/frontend';
7681
const CONFIG_PATH_BACKEND_OPTIONS = 'backend_options';
7782

78-
/** @deprecated */
83+
/**
84+
* @deprecated
85+
*
86+
* Definition format constant.
87+
*/
7988
const INPUT_KEY_DEFINITION_FORMAT = 'definition-format';
8089

8190
/**#@+
@@ -104,6 +113,21 @@ class ConfigOptionsListConstants
104113
const KEY_MODEL = 'model';
105114
const KEY_INIT_STATEMENTS = 'initStatements';
106115
const KEY_ACTIVE = 'active';
116+
const KEY_DRIVER_OPTIONS = 'driver_options';
117+
/**#@-*/
118+
119+
/**#@+
120+
* Array keys for database driver options configurations
121+
*/
122+
const KEY_MYSQL_SSL_KEY = \PDO::MYSQL_ATTR_SSL_KEY;
123+
const KEY_MYSQL_SSL_CERT = \PDO::MYSQL_ATTR_SSL_CERT;
124+
const KEY_MYSQL_SSL_CA = \PDO::MYSQL_ATTR_SSL_CA;
125+
126+
/**
127+
* Constant \PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT cannot be used as it was introduced in PHP 7.1.4
128+
* and Magento 2 is currently supporting PHP 7.1.3.
129+
*/
130+
const KEY_MYSQL_SSL_VERIFY = 1014;
107131
/**#@-*/
108132

109133
/**
@@ -128,6 +152,8 @@ class ConfigOptionsListConstants
128152

129153
/**
130154
* Size of random string generated for store's encryption key
155+
* phpcs:disable
131156
*/
132157
const STORE_KEY_RANDOM_STRING_SIZE = SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES;
158+
//phpcs:enable
133159
}

setup/src/Magento/Setup/Controller/DatabaseCheck.php

+35-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66
namespace Magento\Setup\Controller;
77

8+
use Magento\Framework\Config\ConfigOptionsListConstants;
89
use Magento\Setup\Validator\DbValidator;
910
use Zend\Json\Json;
1011
use Zend\Mvc\Controller\AbstractActionController;
@@ -40,12 +41,45 @@ public function indexAction()
4041
try {
4142
$params = Json::decode($this->getRequest()->getContent(), Json::TYPE_ARRAY);
4243
$password = isset($params['password']) ? $params['password'] : '';
43-
$this->dbValidator->checkDatabaseConnection($params['name'], $params['host'], $params['user'], $password);
44+
$driverOptions = [];
45+
if ($this->isDriverOptionsGiven($params)) {
46+
if (empty($params['driverOptionsSslVerify'])) {
47+
$params['driverOptionsSslVerify'] = 0;
48+
}
49+
$driverOptions = [
50+
ConfigOptionsListConstants::KEY_MYSQL_SSL_KEY => $params['driverOptionsSslKey'],
51+
ConfigOptionsListConstants::KEY_MYSQL_SSL_CERT => $params['driverOptionsSslCert'],
52+
ConfigOptionsListConstants::KEY_MYSQL_SSL_CA => $params['driverOptionsSslCa'],
53+
ConfigOptionsListConstants::KEY_MYSQL_SSL_VERIFY => (int) $params['driverOptionsSslVerify'],
54+
];
55+
}
56+
$this->dbValidator->checkDatabaseConnectionWithDriverOptions(
57+
$params['name'],
58+
$params['host'],
59+
$params['user'],
60+
$password,
61+
$driverOptions
62+
);
4463
$tablePrefix = isset($params['tablePrefix']) ? $params['tablePrefix'] : '';
4564
$this->dbValidator->checkDatabaseTablePrefix($tablePrefix);
4665
return new JsonModel(['success' => true]);
4766
} catch (\Exception $e) {
4867
return new JsonModel(['success' => false, 'error' => $e->getMessage()]);
4968
}
5069
}
70+
71+
/**
72+
* Is Driver Options Given
73+
*
74+
* @param array $params
75+
* @return bool
76+
*/
77+
private function isDriverOptionsGiven($params)
78+
{
79+
return !(
80+
empty($params['driverOptionsSslKey']) ||
81+
empty($params['driverOptionsSslCert']) ||
82+
empty($params['driverOptionsSslCa'])
83+
);
84+
}
5185
}

setup/src/Magento/Setup/Model/ConfigGenerator.php

+14-2
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,12 @@
1414
use Magento\Framework\Config\ConfigOptionsListConstants;
1515
use Magento\Framework\App\State;
1616
use Magento\Framework\Math\Random;
17+
use Magento\Setup\Model\ConfigOptionsList\DriverOptions;
1718

1819
/**
1920
* Creates deployment config data based on user input array
2021
*
21-
* This class introduced to break down {@see Magento\Setup\Model\ConfigOptionsList::createConfig}
22+
* This class introduced to break down {@see \Magento\Setup\Model\ConfigOptionsList::createConfig}
2223
*/
2324
class ConfigGenerator
2425
{
@@ -62,24 +63,32 @@ class ConfigGenerator
6263
*/
6364
private $cryptKeyGenerator;
6465

66+
/**
67+
* @var DriverOptions
68+
*/
69+
private $driverOptions;
70+
6571
/**
6672
* Constructor
6773
*
6874
* @param Random $random Deprecated since 100.2.0
6975
* @param DeploymentConfig $deploymentConfig
7076
* @param ConfigDataFactory|null $configDataFactory
7177
* @param CryptKeyGeneratorInterface|null $cryptKeyGenerator
78+
* @param DriverOptions|null $driverOptions
7279
*/
7380
public function __construct(
7481
Random $random,
7582
DeploymentConfig $deploymentConfig,
7683
ConfigDataFactory $configDataFactory = null,
77-
CryptKeyGeneratorInterface $cryptKeyGenerator = null
84+
CryptKeyGeneratorInterface $cryptKeyGenerator = null,
85+
DriverOptions $driverOptions = null
7886
) {
7987
$this->random = $random;
8088
$this->deploymentConfig = $deploymentConfig;
8189
$this->configDataFactory = $configDataFactory ?? ObjectManager::getInstance()->get(ConfigDataFactory::class);
8290
$this->cryptKeyGenerator = $cryptKeyGenerator ?? ObjectManager::getInstance()->get(CryptKeyGenerator::class);
91+
$this->driverOptions = $driverOptions ?? ObjectManager::getInstance()->get(DriverOptions::class);
8392
}
8493

8594
/**
@@ -181,6 +190,9 @@ public function createDbConfig(array $data)
181190
$configData->set($dbConnectionPrefix . ConfigOptionsListConstants::KEY_ACTIVE, '1');
182191
}
183192

193+
$driverOptions = $this->driverOptions->getDriverOptions($data);
194+
$configData->set($dbConnectionPrefix . ConfigOptionsListConstants::KEY_DRIVER_OPTIONS, $driverOptions);
195+
184196
return $configData;
185197
}
186198

setup/src/Magento/Setup/Model/ConfigOptionsList.php

+45-3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
declare(strict_types=1);
67

78
namespace Magento\Setup\Model;
89

@@ -12,6 +13,7 @@
1213
use Magento\Framework\Setup\ConfigOptionsListInterface;
1314
use Magento\Framework\Setup\Option\FlagConfigOption;
1415
use Magento\Framework\Setup\Option\TextConfigOption;
16+
use Magento\Setup\Model\ConfigOptionsList\DriverOptions;
1517
use Magento\Setup\Validator\DbValidator;
1618

1719
/**
@@ -53,17 +55,24 @@ class ConfigOptionsList implements ConfigOptionsListInterface
5355
\Magento\Setup\Model\ConfigOptionsList\Lock::class,
5456
];
5557

58+
/**
59+
* @var DriverOptions
60+
*/
61+
private $driverOptions;
62+
5663
/**
5764
* Constructor
5865
*
5966
* @param ConfigGenerator $configGenerator
6067
* @param DbValidator $dbValidator
6168
* @param KeyValidator|null $encryptionKeyValidator
69+
* @param DriverOptions|null $driverOptions
6270
*/
6371
public function __construct(
6472
ConfigGenerator $configGenerator,
6573
DbValidator $dbValidator,
66-
KeyValidator $encryptionKeyValidator = null
74+
KeyValidator $encryptionKeyValidator = null,
75+
DriverOptions $driverOptions = null
6776
) {
6877
$this->configGenerator = $configGenerator;
6978
$this->dbValidator = $dbValidator;
@@ -72,6 +81,7 @@ public function __construct(
7281
$this->configOptionsCollection[] = $objectManager->get($className);
7382
}
7483
$this->encryptionKeyValidator = $encryptionKeyValidator ?: $objectManager->get(KeyValidator::class);
84+
$this->driverOptions = $driverOptions ?? $objectManager->get(DriverOptions::class);
7585
}
7686

7787
/**
@@ -162,6 +172,36 @@ public function getOptions()
162172
ConfigOptionsListConstants::CONFIG_PATH_CACHE_HOSTS,
163173
'http Cache hosts'
164174
),
175+
new TextConfigOption(
176+
ConfigOptionsListConstants::INPUT_KEY_DB_SSL_KEY,
177+
TextConfigOption::FRONTEND_WIZARD_TEXT,
178+
ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTION_DEFAULT_DRIVER_OPTIONS .
179+
'/' . ConfigOptionsListConstants::KEY_MYSQL_SSL_KEY,
180+
'Full path of client key file in order to establish db connection through SSL',
181+
''
182+
),
183+
new TextConfigOption(
184+
ConfigOptionsListConstants::INPUT_KEY_DB_SSL_CERT,
185+
TextConfigOption::FRONTEND_WIZARD_TEXT,
186+
ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTION_DEFAULT_DRIVER_OPTIONS .
187+
'/' . ConfigOptionsListConstants::KEY_MYSQL_SSL_CERT,
188+
'Full path of client certificate file in order to establish db connection through SSL',
189+
''
190+
),
191+
new TextConfigOption(
192+
ConfigOptionsListConstants::INPUT_KEY_DB_SSL_CA,
193+
TextConfigOption::FRONTEND_WIZARD_TEXT,
194+
ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTION_DEFAULT_DRIVER_OPTIONS .
195+
'/' . ConfigOptionsListConstants::KEY_MYSQL_SSL_CA,
196+
'Full path of server certificate file in order to establish db connection through SSL',
197+
''
198+
),
199+
new FlagConfigOption(
200+
ConfigOptionsListConstants::INPUT_KEY_DB_SSL_VERIFY,
201+
ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTION_DEFAULT_DRIVER_OPTIONS .
202+
'/' . ConfigOptionsListConstants::KEY_MYSQL_SSL_VERIFY,
203+
'Verify server certification'
204+
),
165205
];
166206

167207
foreach ($this->configOptionsCollection as $configOptionsList) {
@@ -349,12 +389,14 @@ private function validateDbSettings(array $options, DeploymentConfig $deployment
349389
) {
350390
try {
351391
$options = $this->getDbSettings($options, $deploymentConfig);
392+
$driverOptions = $this->driverOptions->getDriverOptions($options);
352393

353-
$this->dbValidator->checkDatabaseConnection(
394+
$this->dbValidator->checkDatabaseConnectionWithDriverOptions(
354395
$options[ConfigOptionsListConstants::INPUT_KEY_DB_NAME],
355396
$options[ConfigOptionsListConstants::INPUT_KEY_DB_HOST],
356397
$options[ConfigOptionsListConstants::INPUT_KEY_DB_USER],
357-
$options[ConfigOptionsListConstants::INPUT_KEY_DB_PASSWORD]
398+
$options[ConfigOptionsListConstants::INPUT_KEY_DB_PASSWORD],
399+
$driverOptions
358400
);
359401
} catch (\Exception $exception) {
360402
$errors[] = $exception->getMessage();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Setup\Model\ConfigOptionsList;
9+
10+
use Magento\Framework\Config\ConfigOptionsListConstants;
11+
12+
/**
13+
* Mysql driver options.
14+
*/
15+
class DriverOptions
16+
{
17+
/**
18+
* Get mysql driver options.
19+
*
20+
* @param array $options
21+
* @return array
22+
*/
23+
public function getDriverOptions(array $options): array
24+
{
25+
$driverOptionKeys = [
26+
ConfigOptionsListConstants::KEY_MYSQL_SSL_KEY => ConfigOptionsListConstants::INPUT_KEY_DB_SSL_KEY,
27+
ConfigOptionsListConstants::KEY_MYSQL_SSL_CERT => ConfigOptionsListConstants::INPUT_KEY_DB_SSL_CERT,
28+
ConfigOptionsListConstants::KEY_MYSQL_SSL_CA => ConfigOptionsListConstants::INPUT_KEY_DB_SSL_CA,
29+
ConfigOptionsListConstants::KEY_MYSQL_SSL_VERIFY => ConfigOptionsListConstants::INPUT_KEY_DB_SSL_VERIFY
30+
];
31+
$driverOptions = [];
32+
foreach ($driverOptionKeys as $configKey => $driverOptionKey) {
33+
if ($this->optionExists($options, $driverOptionKey)) {
34+
$driverOptions[$configKey] = $options[$driverOptionKey];
35+
}
36+
}
37+
return $driverOptions;
38+
}
39+
40+
/**
41+
* Verify if option exists.
42+
*
43+
* @param array $options
44+
* @param string $driverOptionKey
45+
* @return bool
46+
*/
47+
private function optionExists($options, $driverOptionKey): bool
48+
{
49+
return $options[$driverOptionKey] === false || !empty($options[$driverOptionKey]);
50+
}
51+
}

setup/src/Magento/Setup/Model/Installer.php

+28-2
Original file line numberDiff line numberDiff line change
@@ -1375,7 +1375,32 @@ private function deleteDeploymentConfig()
13751375
*/
13761376
private function assertDbAccessible()
13771377
{
1378-
$this->dbValidator->checkDatabaseConnection(
1378+
$driverOptionKeys = [
1379+
ConfigOptionsListConstants::KEY_MYSQL_SSL_KEY =>
1380+
ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTION_DEFAULT_DRIVER_OPTIONS . '/' .
1381+
ConfigOptionsListConstants::KEY_MYSQL_SSL_KEY,
1382+
1383+
ConfigOptionsListConstants::KEY_MYSQL_SSL_CERT =>
1384+
ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTION_DEFAULT_DRIVER_OPTIONS . '/' .
1385+
ConfigOptionsListConstants::KEY_MYSQL_SSL_CERT,
1386+
1387+
ConfigOptionsListConstants::KEY_MYSQL_SSL_CA =>
1388+
ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTION_DEFAULT_DRIVER_OPTIONS . '/' .
1389+
ConfigOptionsListConstants::KEY_MYSQL_SSL_CA,
1390+
1391+
ConfigOptionsListConstants::KEY_MYSQL_SSL_VERIFY =>
1392+
ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTION_DEFAULT_DRIVER_OPTIONS . '/' .
1393+
ConfigOptionsListConstants::KEY_MYSQL_SSL_VERIFY
1394+
];
1395+
$driverOptions = [];
1396+
foreach ($driverOptionKeys as $driverOptionKey => $driverOptionConfig) {
1397+
$config = $this->deploymentConfig->get($driverOptionConfig);
1398+
if ($config !== null) {
1399+
$driverOptions[$driverOptionKey] = $config;
1400+
}
1401+
}
1402+
1403+
$this->dbValidator->checkDatabaseConnectionWithDriverOptions(
13791404
$this->deploymentConfig->get(
13801405
ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTION_DEFAULT .
13811406
'/' . ConfigOptionsListConstants::KEY_NAME
@@ -1391,7 +1416,8 @@ private function assertDbAccessible()
13911416
$this->deploymentConfig->get(
13921417
ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTION_DEFAULT .
13931418
'/' . ConfigOptionsListConstants::KEY_PASSWORD
1394-
)
1419+
),
1420+
$driverOptions
13951421
);
13961422
$prefix = $this->deploymentConfig->get(
13971423
ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTION_DEFAULT .

setup/src/Magento/Setup/Model/RequestDataConverter.php

+8
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,14 @@ private function convertDeploymentConfigForm(array $source)
5151
isset($source['db']['tablePrefix']) ? $source['db']['tablePrefix'] : '';
5252
$result[BackendConfigOptionsList::INPUT_KEY_BACKEND_FRONTNAME] = isset($source['config']['address']['admin'])
5353
? $source['config']['address']['admin'] : '';
54+
$result[SetupConfigOptionsList::INPUT_KEY_DB_SSL_KEY] = isset($source['db']['driverOptionsSslKey'])
55+
? $source['db']['driverOptionsSslKey'] : '';
56+
$result[SetupConfigOptionsList::INPUT_KEY_DB_SSL_CERT] = isset($source['db']['driverOptionsSslCert'])
57+
? $source['db']['driverOptionsSslCert'] : '';
58+
$result[SetupConfigOptionsList::INPUT_KEY_DB_SSL_CA] = isset($source['db']['driverOptionsSslCa'])
59+
? $source['db']['driverOptionsSslCa'] : '';
60+
$result[SetupConfigOptionsList::INPUT_KEY_DB_SSL_VERIFY] = isset($source['db']['driverOptionsSslVerify'])
61+
? $source['db']['driverOptionsSslVerify'] : '';
5462
$result[SetupConfigOptionsList::INPUT_KEY_ENCRYPTION_KEY] = isset($source['config']['encrypt']['key'])
5563
? $source['config']['encrypt']['key'] : null;
5664
$result[SetupConfigOptionsList::INPUT_KEY_SESSION_SAVE] = isset($source['config']['sessionSave']['type'])

0 commit comments

Comments
 (0)