ClickHouse/tests/integration/test_reload_client_certificate/test.py

198 lines
5.5 KiB
Python
Raw Normal View History

2024-10-25 11:38:58 +00:00
import os
import threading
import time
2024-10-25 13:52:07 +00:00
import pytest
2024-10-25 11:38:58 +00:00
from helpers.cluster import ClickHouseCluster
TEST_DIR = os.path.dirname(__file__)
cluster = ClickHouseCluster(
__file__,
zookeeper_certfile=os.path.join(TEST_DIR, "configs_secure", "first_client.crt"),
zookeeper_keyfile=os.path.join(TEST_DIR, "configs_secure", "first_client.key"),
)
node1 = cluster.add_instance(
"node1",
main_configs=[
"configs_secure/first_client.crt",
"configs_secure/first_client.key",
"configs_secure/second_client.crt",
"configs_secure/second_client.key",
"configs_secure/third_client.crt",
"configs_secure/third_client.key",
"configs_secure/conf.d/remote_servers.xml",
"configs_secure/conf.d/ssl_conf.xml",
"configs/zookeeper_config_with_ssl.xml",
],
with_zookeeper_secure=True,
)
2024-10-25 12:33:23 +00:00
2024-10-25 11:38:58 +00:00
node2 = cluster.add_instance(
"node2",
main_configs=[
"configs_secure/first_client.crt",
"configs_secure/first_client.key",
"configs_secure/second_client.crt",
"configs_secure/second_client.key",
"configs_secure/third_client.crt",
"configs_secure/third_client.key",
"configs_secure/conf.d/remote_servers.xml",
"configs_secure/conf.d/ssl_conf.xml",
"configs/zookeeper_config_with_ssl.xml",
],
with_zookeeper_secure=True,
)
nodes = [node1, node2]
2024-10-25 13:52:07 +00:00
2024-10-25 11:38:58 +00:00
@pytest.fixture(scope="module", autouse=True)
def started_cluster():
try:
cluster.start()
yield cluster
finally:
cluster.shutdown()
2024-10-25 13:52:07 +00:00
2024-10-25 11:38:58 +00:00
def secure_connection_test(started_cluster):
2024-10-25 12:33:23 +00:00
# No asserts, connection works
2024-10-25 13:52:07 +00:00
2024-10-25 11:38:58 +00:00
node1.query("SELECT count() FROM system.zookeeper WHERE path = '/'")
node2.query("SELECT count() FROM system.zookeeper WHERE path = '/'")
threads_number = 4
2024-10-25 16:28:05 +00:00
iterations = 4
2024-10-25 11:38:58 +00:00
threads = []
2024-10-25 12:33:23 +00:00
# Just checking for race conditions
2024-10-25 13:52:07 +00:00
2024-10-25 11:38:58 +00:00
for _ in range(threads_number):
threads.append(
threading.Thread(
2024-10-25 13:52:07 +00:00
target=lambda: [
node1.query("SELECT count() FROM system.zookeeper WHERE path = '/'")
for _ in range(iterations)
]
2024-10-25 11:38:58 +00:00
)
)
for thread in threads:
thread.start()
for thread in threads:
thread.join()
2024-10-25 13:52:07 +00:00
2024-10-25 11:38:58 +00:00
def change_config_to_key(name):
"""
2024-10-25 13:52:07 +00:00
Generate config with certificate/key name from args.
Reload config.
2024-10-25 11:38:58 +00:00
"""
for node in nodes:
node.exec_in_container(
[
"bash",
"-c",
"""cat > /etc/clickhouse-server/config.d/ssl_conf.xml << EOF
<clickhouse>
<openSSL>
<client>
<certificateFile>/etc/clickhouse-server/config.d/{cur_name}_client.crt</certificateFile>
<privateKeyFile>/etc/clickhouse-server/config.d/{cur_name}_client.key</privateKeyFile>
<loadDefaultCAFile>true</loadDefaultCAFile>
<cacheSessions>true</cacheSessions>
<disableProtocols>sslv2,sslv3</disableProtocols>
<preferServerCiphers>true</preferServerCiphers>
<verificationMode>none</verificationMode>
<invalidCertificateHandler>
<name>RejectCertificateHandler</name>
</invalidCertificateHandler>
</client>
</openSSL>
</clickhouse>
2024-10-25 13:52:07 +00:00
EOF""".format(
cur_name=name
),
2024-10-25 11:38:58 +00:00
]
)
node.exec_in_container(
2024-10-25 13:52:07 +00:00
["bash", "-c", "touch /etc/clickhouse-server/config.d/ssl_conf.xml"],
2024-10-25 11:38:58 +00:00
)
2024-10-25 13:52:07 +00:00
2024-10-25 12:33:23 +00:00
def check_reload_successful(node, cert_name):
2024-10-25 13:52:07 +00:00
return node.grep_in_log(
f"Reloaded certificate (/etc/clickhouse-server/config.d/{cert_name}_client.crt)"
)
2024-10-25 11:38:58 +00:00
def check_error_handshake(node):
return node.count_in_log("Code: 210.")
2024-10-25 13:52:07 +00:00
2024-10-25 11:38:58 +00:00
def clean_logs():
for node in nodes:
node.exec_in_container(
[
"bash",
"-c",
"echo -n > /var/log/clickhouse-server/clickhouse-server.log",
]
)
2024-10-25 13:52:07 +00:00
2024-10-25 12:33:23 +00:00
def check_certificate_switch(first, second):
2024-10-27 15:36:05 +00:00
# Set first certificate
2024-10-25 13:52:07 +00:00
2024-10-25 11:38:58 +00:00
change_config_to_key(first)
2024-10-28 22:52:33 +00:00
# Restart zookeeper to reload the session
2024-10-25 13:52:07 +00:00
2024-10-28 22:52:33 +00:00
cluster.stop_zookeeper_nodes(["zoo1", "zoo2", "zoo3"])
cluster.start_zookeeper_nodes(["zoo1", "zoo2", "zoo3"])
cluster.wait_zookeeper_nodes_to_start(["zoo1", "zoo2", "zoo3"])
clean_logs()
2024-10-25 11:38:58 +00:00
2024-10-28 22:52:33 +00:00
# Change certificate
2024-10-25 13:52:07 +00:00
2024-10-28 22:52:33 +00:00
change_config_to_key(second)
2024-10-25 11:38:58 +00:00
2024-10-28 22:52:33 +00:00
# Time to log
2024-10-25 13:52:07 +00:00
2024-10-28 22:52:33 +00:00
time.sleep(10)
2024-10-25 11:38:58 +00:00
2024-10-28 22:52:33 +00:00
# Check information about client certificates reloading in log Clickhouse
2024-10-25 13:52:07 +00:00
2024-10-28 22:52:33 +00:00
reload_successful = any(check_reload_successful(node, second) for node in nodes)
2024-10-25 11:38:58 +00:00
2024-10-28 22:52:33 +00:00
# Restart zookeeper to reload the session and clean logs for new check
2024-10-25 13:52:07 +00:00
2024-10-28 22:52:33 +00:00
cluster.stop_zookeeper_nodes(["zoo1", "zoo2", "zoo3"])
cluster.start_zookeeper_nodes(["zoo1", "zoo2", "zoo3"])
2024-10-25 11:38:58 +00:00
clean_logs()
2024-10-28 22:52:33 +00:00
cluster.wait_zookeeper_nodes_to_start(["zoo1", "zoo2", "zoo3"])
2024-10-25 11:38:58 +00:00
if second == "second":
2024-10-25 16:28:05 +00:00
try:
secure_connection_test(started_cluster)
assert False
except:
assert True
2024-10-25 11:38:58 +00:00
else:
2024-10-25 13:52:07 +00:00
secure_connection_test(started_cluster)
2024-10-25 11:38:58 +00:00
error_handshake = any(check_error_handshake(node) == "0\n" for node in nodes)
2024-10-25 16:28:05 +00:00
assert reload_successful and error_handshake
2024-10-25 11:38:58 +00:00
2024-10-25 13:52:07 +00:00
2024-10-25 11:38:58 +00:00
def test_wrong_cn_cert():
"""Checking the certificate reload with an incorrect CN, the expected behavior is Code: 210."""
check_certificate_switch("first", "second")
2024-10-25 13:52:07 +00:00
2024-10-25 11:38:58 +00:00
def test_correct_cn_cert():
"""Replacement with a valid certificate, the expected behavior is to restore the connection with Zookeeper."""
2024-10-25 13:52:07 +00:00
check_certificate_switch("second", "third")