-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Allow secure connections using SSL on mysqli #2570
Conversation
@@ -63,6 +63,19 @@ public function __construct(array $params, $username, $password, array $driverOp | |||
|
|||
$this->_conn = mysqli_init(); | |||
|
|||
if (isset($driverOptions['ssl_key']) && | |||
isset($driverOptions['ssl_cert']) && | |||
isset($driverOptions['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.
Can you tell which of those 5 options are required at minimum to use this feature? I would like to have those evaluated and a MysqliException
being thrown if one of the required options is missing, so that misconfiguration is exposed to the user. Unfortunately the PHP docs only state Any unused SSL parameters may be given as NULL
. It doesn't give a word about which are definitely required.
Also we need test cases for all of the possibilities.
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.
Also please make them connection parameters instead of driver options. We have SSL related connection parameters in other drivers too. Those are more appropriate for connection parameters.
Then finally please document them in our docs (also which are required).
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.
As you say unfortunately PHP and MySQL docs are not clear respect about what minimum of parameters are mandatory about secure connections.
I think the common use is with key, cert and ca as mandatory parameter, but I've talk with various colleagues and we think is possible stablish a secure connection with only key and cert.
In conclusion mandatory fields must be key and cert.
@deeky666 Are you agree?
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.
@pgrau agreed. MySQL documentation also states that the ca
is only mandatory if also used on the server side so we have to make it optional. Making ssl_key
and ssl_cert
required is a good choice then.
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.
@deeky666 I think connection ssl parameters must be driver options as PDO library. Can you put an example of driver with ssl parameters instead driver options?
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.
@pgrau simply put them into $params
argument instead of $driverOptions
. $driverOptions
is exclusively used for \MYSQLI_*
constants so the SSL related parameters do not fit in there.
Example
$connection = \Doctrine\DBAL\DriverManager::getConnection(
array(
'dbname' => 'mydb',
'user' => 'user',
'password' => 'secret',
'host' => 'localhost',
'driver' => 'mysqli',
'ssl_key' => '/path/to/ssl_key',
'ssl_cert' => '/path/to/ssl_key',
'ssl_ca' => '/path/to/ssl_key',
// ...
)
);
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.
If we put ssl parameters as connection parameters against driver options will not run ok automatically in some php frameworks as Symfony.
Example:
[Symfony\Component\Config\Definition\Exception\InvalidConfigurationException]
Unrecognized options "ssl_key, ssl_cert, ssl_ca" under "doctrine.dbal.connections.bd1"
Are you sure do you prefer ssl parameters as connection parameters against driver options?
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.
The reason it does not work with Symfony is because the available connection parameters are defined in the DoctrineBundle. Changes would have to be done in the bundle, too then to allow using those parameters. So yes new connection parameters are still preferred over driver options.
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.
Ok! Now, it's time to develop it : )
@deeky666 I've done some changes. Can you review, please? |
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 also requires documentation of the newly supported connection parameters for mysqli
. Please see here
{ | ||
$matches = preg_grep('/^(ssl_)+(key|cert|ca|capath|cipher)$/', array_keys($params)); | ||
if ($matches && (false === array_search('ssl_key', $matches) || false === array_search('ssl_cert', $matches))) { | ||
throw new MysqliException('ssl_key and ssl_cert are mandatory for secure connections'); |
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.
It is weird to throw an exception in a boolean method, also this method is not really required. I think you do not need to make it more complicated than it is:
private function setSecureConnection(array $params)
{
if (! isset($params['ssl_key']) &&
! isset($params['ssl_cert']) &&
! isset($params['ssl_ca']) &&
! isset($params['ssl_capath']) &&
! isset($params['ssl_cipher'])
) {
return;
}
if (! isset($params['ssl_key']) ||
! isset($params['ssl_cert'])
) {
// exception
}
// $this->_conn->ssl_set()
}
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
/** | ||
* @dataProvider secureMissingParamsProvider | ||
*/ | ||
public function testItShouldReturnAnExceptionWhenMissingMandatorySecureParams(array $secureParams) |
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 please reword to testThrowsExceptionWhenMissingMandatorySecureParams
as we do not really test that an exception is "returned". Also "it should" convention is more of a BDD / PHPSpec one. We do not use it in PHPUnit ;)
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
{ | ||
$matches = preg_grep('/^(ssl_)+(key|cert|ca|capath|cipher)$/', array_keys($params)); | ||
if ($matches && (false === array_search('ssl_key', $matches) || false === array_search('ssl_cert', $matches))) { | ||
throw new MysqliException('ssl_key and ssl_cert are mandatory for secure connections'); |
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.
Also can we reword the exception message to something like "ssl_key" and "ssl_cert" parameters are mandatory when using secure connection parameters.
? I usually am not so picky about this but it can be confusing in certain circumstances, when it is not clear to the user that he used (or misused) one of the SSL connection parameters. This way it gets more obvious that SSL parameters are not mandatory for a mysqli connection in general, only if used explicitly.
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
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.
Nearly done. Just some last nitpicks.
|
||
if (! isset($params['ssl_key']) || ! isset($params['ssl_cert'])) { | ||
$msg = "\"ssl_key\" and \"ssl_cert\" parameters are mandatory when using secure connection parameters."; | ||
throw new MysqliException($msg); |
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.
Please don't do unnecessary string escaping. You can easily avoid that by using single quotes:
throw new MysqliException(
'"ssl_key" and "ssl_cert" parameters are mandatory when using secure connection parameters.'
);
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
public function testThrowsExceptionWhenMissingMandatorySecureParams(array $secureParams) | ||
{ | ||
$this->expectException(MysqliException::class); | ||
$msg = "\"ssl_key\" and \"ssl_cert\" parameters are mandatory when using secure connection parameters."; |
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.
See above.
@@ -263,4 +264,35 @@ public function ping() | |||
{ | |||
return $this->_conn->ping(); | |||
} | |||
|
|||
/** | |||
* Stablish a secure connection |
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.
Typo: Establish
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
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.
@deeky666 It's all ok?
Do you want I move php5 code to php7
Example:
php5:
$port = isset($params['port']) ? $params['port'] : ini_get('mysqli.default_port');
// Fallback to default MySQL port if not given.
if ( ! $port) {
$port = 3306;
}
$socket = isset($params['unix_socket']) ? $params['unix_socket'] : ini_get('mysqli.default_socket');
$dbname = isset($params['dbname']) ? $params['dbname'] : null;
$flags = isset($driverOptions[static::OPTION_FLAGS]) ? $driverOptions[static::OPTION_FLAGS] : null;
php7:
$port = $params['port'] ?? ini_get('mysqli.default_port') ?? 3306;
$socket = $params['unix_socket'] ?? ini_get('mysqli.default_socket');
$dbname = $params['dbname'] ?? null;
$flags = $driverOptions[static::OPTION_FLAGS] ?? null;
@@ -263,4 +264,35 @@ public function ping() | |||
{ | |||
return $this->_conn->ping(); | |||
} | |||
|
|||
/** | |||
* Stablish a secure connection |
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
|
||
if (! isset($params['ssl_key']) || ! isset($params['ssl_cert'])) { | ||
$msg = "\"ssl_key\" and \"ssl_cert\" parameters are mandatory when using secure connection parameters."; | ||
throw new MysqliException($msg); |
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
@pgrau no please don't convert any code to PHP7 that could potentially also be backported to DBAL |
@pgrau the patch looks good to me now. Can you please squash your commits? I'll merge afterwards. 👍 |
@deeky666 I squash all commits. |
The current driver has no option to allow the usage of SSL connections on mysql. I've used the same name params as mysql client. An example of mysql client usage would be: mysql --ssl-ca='path_to_ca.pem' --ssl-cert='path_to_client_cert.pem' --ssl-key='path_to_client_key.pem' refactor secure connection as params remove space add space refactor secure connection rename method rename method docs: add ssl params to use in mysqli driver rename test method refactor method setSecureConnection fix bug add comment to method remove string escaping
@pgrau seems you did some kind of merge instead of a squash. There are still 15 commits. You need to:
While rebasing you can select the commits to squash. |
@deeky666 please, see now. |
@pgrau thanks! :) |
The current driver has no option to allow the usage of SSL connections on mysql. I've used the same name params as mysql client.
An example of mysql client usage would be:
mysql --ssl-ca='path_to_ca.pem' --ssl-cert='path_to_client_cert.pem' --ssl-key='path_to_client_key.pem'