
I’ve been asked a few times now if there is a way to use encrypted MySQL connections in Magento. Most of the time it is when merchants are selling medical products and HIPAA requirements come into play. I am not an expert in HIPAA, nor do I want to be, but with the cost of vulnerabilities on the rise it made sense to at least look into it and get a good answer on how to do it.
The answer, to my surprise, is that there is no way of doing it out of the box. The reason is actually very, very simple. The PDO options that allow you to initiate SSL on MySQL are passed in as numerical values. For example, the value for PDO::MYSQL_ATTR_SSL_KEY is 1007. Shouldn’t be a problem, right? Just pass in a numerical value for the config.
That works in the Zend Framework adapter, but it does not work for Magento. All database configurations are stored in the local.xml file and the XML specification does not allow numbers for XML node names. So no matter how you try to slice it it looks like getting the SSL settings into the Magento adapter will not work without a code change. The Internet seems to confirm this.
But that doesn’t mean that it can’t be done. So I wrote a quick Magento adapter that allows you to pass in the constant values. The implementation is about 10 lines of code and it’s super easy to test.
- Download the code from github.
- Configure MySQL – Note that when you create the server certificate you MUST use the IP address or hostname that you will be using in your Magento configuration
- Configure Magento
For step 3 first copy the Github code into your Magento installation. Then modify your configuration such as this
<config> <global> <resources> <default_setup> <connection> <host><![CDATA[127.0.0.1]]></host> <username><![CDATA[root]]></username> <password><![CDATA[]]></password> <dbname><![CDATA[magentoee_114]]></dbname> <initStatements><![CDATA[SET NAMES utf8]]></initStatements> <model><![CDATA[mysql4]]></model> <type><![CDATA[secure_pdo_mysql]]></type> <pdoType><![CDATA[]]></pdoType> <active>1</active> <secure_driver_options> <MYSQL_ATTR_SSL_KEY>/etc/mysql-ssl/client-key.pem</MYSQL_ATTR_SSL_KEY> <MYSQL_ATTR_SSL_CERT>/etc/mysql-ssl/client-cert.pem</MYSQL_ATTR_SSL_CERT> <MYSQL_ATTR_SSL_CA>/etc/mysql-ssl/ca.pem</MYSQL_ATTR_SSL_CA> </secure_driver_options> </connection> </default_setup> </resources> </global> </config>
The main difference is the node secure_driver_options. Internally, what the driver does is append that to PDO:: and gets the value of the constant. Then it adds it to the driver_options configuration array (notably absent since this adapter overwrites it) using the numerical values of the constants instead of node names.
Run the test script secure.mysql.test.php in your browser (or CLI).
There you go.
Note
- This is not an officially sanctioned Magento code example
- I have not tested it for performance, security, gremlins.
- I have built this as a proof of concept only
- Use at your own risk.
- If you find issues in the code, or a better implementation, feel free to contribute or let me know
Comments
Mitch Thompson
If you are trying to implement with azure on a later version of magento, simply change the Mysql.php to read:
public function __construct($config)
{
if ($config instanceof Zend_Config) {
$config = $config->toArray();
}
// Tells php data object to use SSL.
$config[‘driver_options’][PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = false;
$config[‘driver_options’][PDO::MYSQL_ATTR_SSL_CA] = ‘/etc/mysql/ssl/BaltimoreCyberTrustRoot.crt.pem’;
parent::__construct($config);
}
and change the local.xml entry to only include
This fixes compatibility issues with the latest version of magento as well (as of 1.9CE)
Dave Gogerly
Many Thanks Kevin and Mitch for this post. I have an installation of Magento CE edition 2.2.6. What confuses me is that the installation has the following Mysql.php files, which one am I supposed to edit please? Any help would be appreciated.
./vendor/magento/framework/Model/ResourceModel/Type/Db/Pdo/Mysql.php
./vendor/magento/framework/DB/Statement/Pdo/Mysql.php
./vendor/magento/framework/DB/Adapter/Pdo/Mysql.php
./vendor/magento/magento2-base/dev/tests/integration/framework/Magento/TestFramework/Db/Adapter/Mysql.php
./vendor/magento/magento2-base/dev/tests/integration/framework/Magento/TestFramework/Db/Mysql.php
./vendor/magento/zendframework1/library/Zend/Db/Adapter/Pdo/Mysql.php
./vendor/zendframework/zend-db/src/Sql/Platform/Mysql/Mysql.php
./vendor/zendframework/zend-db/src/Adapter/Platform/Mysql.php
./dev/tests/integration/framework/Magento/TestFramework/Db/Adapter/Mysql.php
./dev/tests/integration/framework/Magento/TestFramework/Db/Mysql.php
Kevin Schroeder
Dave, unfortunately, this code is for Magento 1. You should not edit any files in the /vendor directory. Instead, create a new library that extends the DB adapter and implements similar functionality for M2 as this one does for M1.
Aliza
This is actually helpful, thanks.