As far as I can tell, there is no way within civicrm core to enable SSL connections to a remote database. This would be a major concern for anyone running CiviCRM with separate web and database servers. I've 'solved' this issue for myself by making the changes to civicrm/civicrm/packages/DB/common.php and civicrm/civicrm/packages/DB/mysqli.php detailed here, but it's rather sloppy and may need to be re-done after an update. Would be very useful to be able to set a flag within civicrm.settings.php (or even the initial install page) to enable SSL.
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Child items ...
Show closed items
Linked items 0
Link issues together to show that they're related.
Learn more.
Looking at the patch in the se post it seems like a reasonable change. Since these are not packages we have written but rather ones we use it would be good to see if there are any upstream fixes before hacking one in
I don't think the issue is that upstream doesn't support it - it does already in mysqli.php via DB_Common::$options['ssl'], so no hack should be needed there. It's just that civi never sets $options['ssl'], so there's no way to set it at the moment without some kind of hack somewhere.
While the install page might be some work, in terms of supporting ssl my thinking would be it might be as simple as adding 3 lines in CRM_Core_DAO::init(), e.g.
if (defined('SOMETHING')) { $options['ssl'] = TRUE;}
@eileen Yes although then it might mess up PEAR DB's regex/parsing of the dsn since it doesn't do it that way and isn't expecting it in the dsn. If you want SSL it expects you to set it in $options.
Probably. The installer I'm not sure. Can you set php DEFINEs before the installer? It might be acceptable to use non-ssl for the install though since there's no private data at that point, unless mysql is set up to require/force SSL (which off the top of my head I'm not sure if you can do but probably).
So it should initiate SSL, but maybe those lines don't actually work against a mysql that requires ssl (which my dev laptop mysql doesn't - so it might have fallen back to non-ssl).
@DaveD I think I see the issue. The lines I had previously edited in mysqli.php are just below that https://github.com/civicrm/civicrm-packages/blob/5.15.1/DB/mysqli.php#L311-L319, where I had appended MYSQLI_CLIENT_SSL, which relies on the certs set in the mysql config. This is also matches the setup for wordpress which involves appending define( 'MYSQL_CLIENT_FLAGS', MYSQLI_CLIENT_SSL ); to the wordpress config file.
In any case, I reverted back to the changes you suggested and it appears to be triggering lines 301-310 in mysqli.php, but I believe that section requires values to be set for the individual cert files. I have tried various permutations of dsn within civicrm.settings.php, based off the PEAR DB Documentation, but all fail with the following error code:
Thanks @toddd I had looked at your previous use of the MYSQLI_CLIENT_SSL flag just it seemed like the lines above were the ones intended for ssl use. I agree that you should be able to set the key and cert etc params in the dsn.
I'm going to take a break from this for a bit.
Also making a note that to be a general solution in Civi there is also CIVICRM_LOGGING_DSN and also CIVICRM_UF_DSN. While it's likely if you're using ssl for one you'd use it for the others, and so probably not a blocker, if they're different then, well, they might be different. At that point it might be worth investigating whether it's true or not that adding made-up params to the dsn will confuse PEAR::DB's own use of it, so that the flag could be part of the dsn. i.e. would this line be a problem: https://github.com/civicrm/civicrm-packages/blob/5.15.1/DB/common.php#L735
It's a bit strange that the DB classes split SSL options across two spaces (eg $dsn['ca'] or $dsn['key'] vs $options['ssl']). The toggle should be determined by whoever sets the DSN. Maybe $options['ssl'] could be set by inspecting the the DSN? e.g. Riffing on Dave's snippet:
Have put up 2 minimal PRs. There may be another spot or two that's needed as noted in the previous PR like CRM_Utils_File, but this gets you into the civi dashboard at least.
Outside the scope here to fully describe but briefly create a server certificate and key and put appropriate entries in my.ini or equivalent.
To make sure you are using SSL to verify this is working you can do ALTER USER username@localhost REQUIRE SSL;. Obviously replace username and localhost as appropriate.
In drupal settings.php in the $databases array, add a pdo section:
// Simplest, and doesn't require a client certificate, but doesn't verify the server certificate.'database'=>'dbname','username'=>'user','password'=>'pass','host'=>'localhost','pdo'=>array(PDO::MYSQL_ATTR_SSL_CA=>true,PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT=>FALSE,),// OR //// Verifies the cert, but note that the DATABASE SERVER certificate would have to have a CN that matches exactly// the hostname you are using in $databases[...]['host'].'pdo'=>array(PDO::MYSQL_ATTR_SSL_CA=>'/path/to/ca.crt',),// OR //// Note the client certificate would have to be reachable from the WEB SERVER.'pdo'=>array(PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT=>FALSE,PDO::MYSQL_ATTR_SSL_KEY=>'/path/to/your.key',PDO::MYSQL_ATTR_SSL_CERT=>'/path/to/your.crt',// if self-signed and want to also verify server cert see below),// OR //// Ditto, and also the same note about hostname as above.'pdo'=>array(PDO::MYSQL_ATTR_SSL_CA=>'/path/to/ca.crt',// can be same as your.crt if self-signedPDO::MYSQL_ATTR_SSL_KEY=>'/path/to/your.key',PDO::MYSQL_ATTR_SSL_CERT=>'/path/to/your.crt',),
In civicrm.settings.php in the DSN's, either:
Any or all of key|cert|ca|capath|cipher as described in the pear docs, urlencoded, e.g. spaces in paths are %20 and slashes are %2F.
e.g. mysqli://user:pass@localhost/dbname?new_link=true&key=%2Fpath%2Fto%2Ffile.key&cert=%2Fpath%2Fto%2Ffile.crt&ca=%2Fpath%2Fto%2Fca.crt
// OR //
None of the above and instead use ssl=1 (which is not an official PEAR::DB option it's just something made up to make it work without client certificates). mysqli://user:pass@localhost/dbname?new_link=true&ssl=1