-
Notifications
You must be signed in to change notification settings - Fork 824
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
FIX Add back missing SSL support for database connections #10784
FIX Add back missing SSL support for database connections #10784
Conversation
src/Core/CoreKernel.php
Outdated
// Having only the key or cert without the other is bad configuration. | ||
if (isset($databaseConfig['ssl_key']) xor isset($databaseConfig['ssl_cert'])) { | ||
user_error('Database SSL cert and key must both be defined to use SSL in the database.', E_USER_WARNING); | ||
unset($databaseConfig['ssl_key']); | ||
unset($databaseConfig['ssl_cert']); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A warning instead of an exception because if a live environment is poorly configured this shouldn't necessarily break the entire site - but it should provide a warning in the logs.
Note that the previous implementation didn't even give a warning, so this is an improvement over what would have been here if SSL support had never been erroneously removed in the first place.
src/Core/CoreKernel.php
Outdated
} | ||
|
||
// Having only the key or cert without the other is bad configuration. | ||
if (isset($databaseConfig['ssl_key']) xor isset($databaseConfig['ssl_cert'])) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Must have either the CA, or both the key and cert, or all three.
This is mirrored in the original implementation: https://github.com/silverstripe/silverstripe-framework/pull/7233/files#diff-6b84b243cc8c7653ef8cadbb9fa5620f991f7454609aaea3f6527e45c3a5820eR128-R142
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you rewrite without xor
, it's very uncommon so many people would need to lookup what it means in order to read this code
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think xor
as a concept isn't by any means unusual - but I'll rewrite this as I don't feel any particular need to keep it. It'll just make the condition a little more convoluted but not to the extent that it would be worth me pushing back on.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
// Set SSL parameters if they exist. All parameters are required. | ||
if (array_key_exists('ssl_key', $databaseConfig) && | ||
array_key_exists('ssl_cert', $databaseConfig) && | ||
array_key_exists('ssl_ca', $databaseConfig) | ||
// Set SSL parameters if they exist. | ||
// Must have both the SSL cert and key, or the common authority, or preferably all three. | ||
if ((array_key_exists('ssl_key', $databaseConfig) && array_key_exists('ssl_cert', $databaseConfig)) | ||
|| array_key_exists('ssl_ca', $databaseConfig) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This works fine with just the CA, and with just the key and cert.
I'll create a separate card for testing this - I don't think there's any way for us to test it with a normal unit test. Instead, I think we'll have to update our CI to use an SSL connection to the db in at least one of the runs. Edit: silverstripe/gha-ci#68 |
src/Core/CoreKernel.php
Outdated
} | ||
|
||
// Having only the key or cert without the other is bad configuration. | ||
if (isset($databaseConfig['ssl_key']) xor isset($databaseConfig['ssl_cert'])) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you rewrite without xor
, it's very uncommon so many people would need to lookup what it means in order to read this code
$databaseConfig['ssl_key'], | ||
$databaseConfig['ssl_cert'], | ||
$databaseConfig['ssl_key'] ?? null, | ||
$databaseConfig['ssl_cert'] ?? null, | ||
$databaseConfig['ssl_ca'], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should ssl_ca
also have ?? null
? - we have that below in MySQLiConnector
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, yes it should.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
34f1d6f
to
b73c301
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested locally, confirmed it works with various combinations of key+cert, ca only, and key+cert+ca
Reinstates the SSL support for databases which was unintentionally partially removed at some stage.
Note for testing
You'll need to set up SSL for mysql, obviously. The official mysql docker image does already have SSL enabled, and has keys in the
/var/lib/mysql/
directory.You can copy the relevant files out of the container to your host with the following commands:
Note that if you go that route, you will most likely run into this error:
This is because PHP is trying to validate that the server's SSL cert is correct, and in checking the common name it finds that the common name which was set at the time the SSL cert was created doesn't match the host name your webserver docker container is using to access the database docker container.
You can bypass that validation for the purposes of testing this PR by making the following change in
vendor/silverstripe/framework/src/ORM/Connect/MySQLiConnector.php
:It says "don't verify server cert" but it actually only disables validating the common name.
You can, alternatively, either make it so that the host name your webserver is using to access the db container matches the common name of the existing cert, or go down the rabbit hole of creating new certs for the mysql instance to use.
Checking if you have a working SSL connection
Put this somewhere, e.g. in a page controller or in
_config.php
:The output when not using SSL:
The output when using SSL:
Issue
Follow on issues created