summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZuul <zuul@review.opendev.org>2022-07-15 21:00:16 +0000
committerGerrit Code Review <review@openstack.org>2022-07-15 21:00:16 +0000
commitd145b503cadb9bb6e9938effb8170fdcd5680ec9 (patch)
tree86acc0dc7cab4448122c2c4d86ad3fe8701c17a5
parenta10db5d089a45da013f2b2875680ceb44d2ac562 (diff)
parent81c629676c06e798e5073b4361cffd269876c553 (diff)
downloadtooz-d145b503cadb9bb6e9938effb8170fdcd5680ec9.tar.gz
Merge "Add TLS support for MySQL driver"3.0.0
-rw-r--r--releasenotes/notes/mysql-tls-support-88941e2ebaf938b4.yaml33
-rw-r--r--tooz/drivers/mysql.py38
-rw-r--r--tooz/tests/test_mysql.py33
3 files changed, 103 insertions, 1 deletions
diff --git a/releasenotes/notes/mysql-tls-support-88941e2ebaf938b4.yaml b/releasenotes/notes/mysql-tls-support-88941e2ebaf938b4.yaml
new file mode 100644
index 0000000..e9bc306
--- /dev/null
+++ b/releasenotes/notes/mysql-tls-support-88941e2ebaf938b4.yaml
@@ -0,0 +1,33 @@
+---
+features:
+ - |
+ Added TLS support for MySQL driver.
+
+ The following TLS-related options now can be specifed in the MySQL
+ connection URL as query parameters
+
+ ``ssl_ca``
+ path to the CA bundle to use for verifying server certificate
+
+ ``ssl_capath``
+ path to folder with CA bundle files
+
+ ``ssl_cert``
+ path to client public key certificate file
+
+ ``ssl_key``
+ path to client private key file
+
+ ``ssl_check_hostname``
+ verify server hostname against its certificate,
+ accepted values are "true", "1", "yes" or "false", "0", "no"
+ (default is "true")
+
+ ``ssl_verify_mode``
+ whether to verify TLS connection
+ accepted values are "true", "1", "yes", "required" or
+ "false", "0", "no", "none", or
+ "optional"
+
+ ``ssl_cipher``
+ list of permissible ciphers for connection encryption
diff --git a/tooz/drivers/mysql.py b/tooz/drivers/mysql.py
index 5bc8892..491eecc 100644
--- a/tooz/drivers/mysql.py
+++ b/tooz/drivers/mysql.py
@@ -116,9 +116,23 @@ class MySQLDriver(coordination.CoordinationDriver):
The MySQL driver connection URI should look like::
- mysql://USERNAME:PASSWORD@HOST[:PORT]/DBNAME[?unix_socket=SOCKET_PATH]
+ mysql://USERNAME:PASSWORD@HOST[:PORT]/DBNAME[?OPTION1=VALUE1[&OPTION2=VALUE2[&...]]]
If not specified, PORT defaults to 3306.
+ Available options are:
+
+ ================== =======
+ Name Default
+ ================== =======
+ ssl_ca None
+ ssl_capath None
+ ssl_cert None
+ ssl_key None
+ ssl_cipher None
+ ssl_verify_mode None
+ ssl_check_hostname True
+ unix_socket None
+ ================== =======
.. _MySQL: http://dev.mysql.com/
"""
@@ -182,6 +196,26 @@ class MySQLDriver(coordination.CoordinationDriver):
username = parsed_url.username
password = parsed_url.password
unix_socket = options.get("unix_socket")
+ ssl_opt_names = (
+ "ca",
+ "capath",
+ "cert",
+ "key",
+ "cipher",
+ "verify_mode",
+ )
+ ssl_args = {}
+ for o in ssl_opt_names:
+ value = options.get("ssl_" + o)
+ if value:
+ ssl_args[o] = value
+ check_hostname = options.get("ssl_check_hostname")
+ if check_hostname is not None:
+ check_hostname = check_hostname.lower()
+ if check_hostname in ("true", "1", "yes"):
+ ssl_args["check_hostname"] = True
+ elif check_hostname in ("false", "0", "no"):
+ ssl_args["check_hostname"] = False
try:
if unix_socket:
@@ -190,6 +224,7 @@ class MySQLDriver(coordination.CoordinationDriver):
user=username,
passwd=password,
database=dbname,
+ ssl=ssl_args,
defer_connect=defer_connect)
else:
return pymysql.Connect(host=host,
@@ -197,6 +232,7 @@ class MySQLDriver(coordination.CoordinationDriver):
user=username,
passwd=password,
database=dbname,
+ ssl=ssl_args,
defer_connect=defer_connect)
except (pymysql.err.OperationalError, pymysql.err.InternalError) as e:
utils.raise_with_cause(coordination.ToozConnectionError,
diff --git a/tooz/tests/test_mysql.py b/tooz/tests/test_mysql.py
index 291f44a..735d9d0 100644
--- a/tooz/tests/test_mysql.py
+++ b/tooz/tests/test_mysql.py
@@ -14,6 +14,7 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
+from unittest import mock
from oslo_utils import encodeutils
from testtools import testcase
@@ -52,3 +53,35 @@ class TestMySQLDriver(testcase.TestCase):
def test_connect_failure_invalid_hostname_and_port_provided(self):
c = self._create_coordinator("mysql://invalidhost:54/test")
self.assertRaises(coordination.ToozConnectionError, c.start)
+
+ @mock.patch("pymysql.Connect")
+ def test_parsing_tls_settings(self, sql_mock):
+ c = self._create_coordinator(
+ "mysql://invalidhost:54/test"
+ "?ssl_ca=/ca/not/there"
+ "&ssl_capath=/capath/not/there"
+ "&ssl_check_hostname=False"
+ "&ssl_verify_mode=yes"
+ "&ssl_cert=/cert/not/there"
+ "&ssl_key=/key/not/there"
+ "&ssl_cipher=spam,ham"
+ )
+ c.start()
+ sql_mock.assert_called_once_with(
+ host="invalidhost",
+ port=54,
+ user=None,
+ passwd=None,
+ database="test",
+ defer_connect=False,
+ ssl=dict(
+ ca="/ca/not/there",
+ capath="/capath/not/there",
+ check_hostname=False,
+ verify_mode="yes",
+ cert="/cert/not/there",
+ key="/key/not/there",
+ cipher="spam,ham"
+ )
+
+ )