diff --git a/tests/integration/test_replicated_merge_tree_encrypted_disk/__init__.py b/tests/integration/test_replicated_merge_tree_encrypted_disk/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/integration/test_replicated_merge_tree_encrypted_disk/configs/key_a.xml b/tests/integration/test_replicated_merge_tree_encrypted_disk/configs/key_a.xml new file mode 100644 index 00000000000..9d866c91f54 --- /dev/null +++ b/tests/integration/test_replicated_merge_tree_encrypted_disk/configs/key_a.xml @@ -0,0 +1,9 @@ + + + + + aaaaaaaaaaaaaaaa + + + + diff --git a/tests/integration/test_replicated_merge_tree_encrypted_disk/configs/key_b.xml b/tests/integration/test_replicated_merge_tree_encrypted_disk/configs/key_b.xml new file mode 100644 index 00000000000..c34283160a5 --- /dev/null +++ b/tests/integration/test_replicated_merge_tree_encrypted_disk/configs/key_b.xml @@ -0,0 +1,9 @@ + + + + + bbbbbbbbbbbbbbbb + + + + diff --git a/tests/integration/test_replicated_merge_tree_encrypted_disk/configs/remote_servers.xml b/tests/integration/test_replicated_merge_tree_encrypted_disk/configs/remote_servers.xml new file mode 100644 index 00000000000..84d16206080 --- /dev/null +++ b/tests/integration/test_replicated_merge_tree_encrypted_disk/configs/remote_servers.xml @@ -0,0 +1,16 @@ + + + + + + node1 + 9000 + + + node2 + 9000 + + + + + diff --git a/tests/integration/test_replicated_merge_tree_encrypted_disk/configs/storage.xml b/tests/integration/test_replicated_merge_tree_encrypted_disk/configs/storage.xml new file mode 100644 index 00000000000..312a009ed9a --- /dev/null +++ b/tests/integration/test_replicated_merge_tree_encrypted_disk/configs/storage.xml @@ -0,0 +1,25 @@ + + + + + local + /disk/ + + + encrypted + disk_local + encrypted/ + 0000000000000000 + + + + + +
+ disk_encrypted +
+
+
+
+
+
diff --git a/tests/integration/test_replicated_merge_tree_encrypted_disk/test.py b/tests/integration/test_replicated_merge_tree_encrypted_disk/test.py new file mode 100644 index 00000000000..bc5a419aaf2 --- /dev/null +++ b/tests/integration/test_replicated_merge_tree_encrypted_disk/test.py @@ -0,0 +1,87 @@ +import pytest +from helpers.cluster import ClickHouseCluster +from helpers.test_tools import assert_eq_with_retry, TSV +import os + + +SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__)) +cluster = ClickHouseCluster(__file__) + +node1 = cluster.add_instance("node1", + main_configs=["configs/remote_servers.xml", "configs/storage.xml"], + tmpfs=["/disk:size=100M"], + macros={'replica': 'node1'}, + with_zookeeper=True) + +node2 = cluster.add_instance("node2", + main_configs=["configs/remote_servers.xml", "configs/storage.xml"], + tmpfs=["/disk:size=100M"], + macros={'replica': 'node2'}, + with_zookeeper=True) + +@pytest.fixture(scope="module", autouse=True) +def start_cluster(): + try: + cluster.start() + yield + finally: + cluster.shutdown() + + +def copy_keys(instance, keys_file_name): + instance.copy_file_to_container(os.path.join(SCRIPT_DIR, f"configs/{keys_file_name}.xml"), "/etc/clickhouse-server/config.d/z_keys.xml") + instance.query("SYSTEM RELOAD CONFIG") + +def create_table(): + node1.query("DROP TABLE IF EXISTS tbl ON CLUSTER 'cluster' NO DELAY") + node1.query( + """ + CREATE TABLE tbl ON CLUSTER 'cluster' ( + id Int64, + str String + ) ENGINE=ReplicatedMergeTree('/clickhouse/tables/tbl/', '{replica}') + ORDER BY id + SETTINGS storage_policy='encrypted_policy' + """ + ) + +def insert_data(): + node1.query("INSERT INTO tbl VALUES (1, 'str1')") + node2.query("INSERT INTO tbl VALUES (1, 'str1')") # Test deduplication + node2.query("INSERT INTO tbl VALUES (2, 'str2')") + +def optimize_table(): + node1.query("OPTIMIZE TABLE tbl ON CLUSTER 'cluster' FINAL") + +def check_table(): + expected=[[1, 'str1'], [2, 'str2']] + assert node1.query("SELECT * FROM tbl ORDER BY id") == TSV(expected) + assert node2.query("SELECT * FROM tbl ORDER BY id") == TSV(expected) + assert node1.query("CHECK TABLE tbl") == "1\n" + assert node2.query("CHECK TABLE tbl") == "1\n" + + +# Actual tests: + +def test_same_keys(): + copy_keys(node1, 'key_a') + copy_keys(node2, 'key_a') + create_table() + + insert_data() + check_table() + + optimize_table() + check_table() + + +def test_different_keys(): + copy_keys(node1, 'key_a') + copy_keys(node2, 'key_b') + create_table() + + insert_data() + check_table() + + optimize_table() + check_table() diff --git a/tests/integration/test_replicated_merge_tree_encryption_codec/__init__.py b/tests/integration/test_replicated_merge_tree_encryption_codec/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/integration/test_replicated_merge_tree_encryption_codec/configs/encryption_codec.xml b/tests/integration/test_replicated_merge_tree_encryption_codec/configs/encryption_codec.xml new file mode 100644 index 00000000000..eb4f8abaa77 --- /dev/null +++ b/tests/integration/test_replicated_merge_tree_encryption_codec/configs/encryption_codec.xml @@ -0,0 +1,7 @@ + + + + 0000000000000000 + + + diff --git a/tests/integration/test_replicated_merge_tree_encryption_codec/configs/key_a.xml b/tests/integration/test_replicated_merge_tree_encryption_codec/configs/key_a.xml new file mode 100644 index 00000000000..a31978e7015 --- /dev/null +++ b/tests/integration/test_replicated_merge_tree_encryption_codec/configs/key_a.xml @@ -0,0 +1,7 @@ + + + + aaaaaaaaaaaaaaaa + + + diff --git a/tests/integration/test_replicated_merge_tree_encryption_codec/configs/key_a_and_b_current_a.xml b/tests/integration/test_replicated_merge_tree_encryption_codec/configs/key_a_and_b_current_a.xml new file mode 100644 index 00000000000..01ca9123ccb --- /dev/null +++ b/tests/integration/test_replicated_merge_tree_encryption_codec/configs/key_a_and_b_current_a.xml @@ -0,0 +1,10 @@ + + + + + aaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbb + 0 + + + diff --git a/tests/integration/test_replicated_merge_tree_encryption_codec/configs/key_a_and_b_current_b.xml b/tests/integration/test_replicated_merge_tree_encryption_codec/configs/key_a_and_b_current_b.xml new file mode 100644 index 00000000000..98cf6ced0c7 --- /dev/null +++ b/tests/integration/test_replicated_merge_tree_encryption_codec/configs/key_a_and_b_current_b.xml @@ -0,0 +1,10 @@ + + + + + aaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbb + 1 + + + diff --git a/tests/integration/test_replicated_merge_tree_encryption_codec/configs/key_a_and_nonce_x.xml b/tests/integration/test_replicated_merge_tree_encryption_codec/configs/key_a_and_nonce_x.xml new file mode 100644 index 00000000000..40c5adab19b --- /dev/null +++ b/tests/integration/test_replicated_merge_tree_encryption_codec/configs/key_a_and_nonce_x.xml @@ -0,0 +1,8 @@ + + + + aaaaaaaaaaaaaaaa + xxxxxxxxxxxx + + + diff --git a/tests/integration/test_replicated_merge_tree_encryption_codec/configs/key_a_and_nonce_y.xml b/tests/integration/test_replicated_merge_tree_encryption_codec/configs/key_a_and_nonce_y.xml new file mode 100644 index 00000000000..eadfb6e6733 --- /dev/null +++ b/tests/integration/test_replicated_merge_tree_encryption_codec/configs/key_a_and_nonce_y.xml @@ -0,0 +1,8 @@ + + + + aaaaaaaaaaaaaaaa + yyyyyyyyyyyy + + + diff --git a/tests/integration/test_replicated_merge_tree_encryption_codec/configs/key_b.xml b/tests/integration/test_replicated_merge_tree_encryption_codec/configs/key_b.xml new file mode 100644 index 00000000000..e336324f648 --- /dev/null +++ b/tests/integration/test_replicated_merge_tree_encryption_codec/configs/key_b.xml @@ -0,0 +1,7 @@ + + + + bbbbbbbbbbbbbbbb + + + diff --git a/tests/integration/test_replicated_merge_tree_encryption_codec/configs/remote_servers.xml b/tests/integration/test_replicated_merge_tree_encryption_codec/configs/remote_servers.xml new file mode 100644 index 00000000000..84d16206080 --- /dev/null +++ b/tests/integration/test_replicated_merge_tree_encryption_codec/configs/remote_servers.xml @@ -0,0 +1,16 @@ + + + + + + node1 + 9000 + + + node2 + 9000 + + + + + diff --git a/tests/integration/test_replicated_merge_tree_encryption_codec/test.py b/tests/integration/test_replicated_merge_tree_encryption_codec/test.py new file mode 100644 index 00000000000..3aec2259703 --- /dev/null +++ b/tests/integration/test_replicated_merge_tree_encryption_codec/test.py @@ -0,0 +1,110 @@ +import pytest +from helpers.cluster import ClickHouseCluster +from helpers.test_tools import assert_eq_with_retry, TSV +import os + + +SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__)) +cluster = ClickHouseCluster(__file__) + +node1 = cluster.add_instance("node1", + main_configs=["configs/remote_servers.xml", "configs/encryption_codec.xml"], + macros={'replica': 'node1'}, + with_zookeeper=True) + +node2 = cluster.add_instance("node2", + main_configs=["configs/remote_servers.xml", "configs/encryption_codec.xml"], + macros={'replica': 'node2'}, + with_zookeeper=True) + +@pytest.fixture(scope="module", autouse=True) +def start_cluster(): + try: + cluster.start() + yield + finally: + cluster.shutdown() + + +def copy_keys(instance, keys_file_name): + instance.copy_file_to_container(os.path.join(SCRIPT_DIR, f"configs/{keys_file_name}.xml"), "/etc/clickhouse-server/config.d/z_keys.xml") + instance.query("SYSTEM RELOAD CONFIG") + +def create_table(): + node1.query("DROP TABLE IF EXISTS tbl ON CLUSTER 'cluster' NO DELAY") + node1.query( + """ + CREATE TABLE tbl ON CLUSTER 'cluster' ( + id Int64, + str String Codec(AES_128_GCM_SIV) + ) ENGINE=ReplicatedMergeTree('/clickhouse/tables/tbl/', '{replica}') + ORDER BY id + """ + ) + +def insert_data(): + node1.query("INSERT INTO tbl VALUES (1, 'str1')") + node2.query("INSERT INTO tbl VALUES (1, 'str1')") # Test deduplication + node2.query("INSERT INTO tbl VALUES (2, 'str2')") + +def optimize_table(): + node1.query("OPTIMIZE TABLE tbl ON CLUSTER 'cluster' FINAL") + +def check_table(): + expected=[[1, 'str1'], [2, 'str2']] + assert node1.query("SELECT * FROM tbl ORDER BY id") == TSV(expected) + assert node2.query("SELECT * FROM tbl ORDER BY id") == TSV(expected) + assert node1.query("CHECK TABLE tbl") == "1\n" + assert node2.query("CHECK TABLE tbl") == "1\n" + + +# Actual tests: + +def test_same_keys(): + copy_keys(node1, 'key_a') + copy_keys(node2, 'key_a') + create_table() + + insert_data() + check_table() + + optimize_table() + check_table() + + +def test_different_keys(): + copy_keys(node1, 'key_a') + copy_keys(node2, 'key_b') + create_table() + + insert_data() + assert "BAD_DECRYPT" in node1.query_and_get_error("SELECT * FROM tbl") + assert "BAD_DECRYPT" in node2.query_and_get_error("SELECT * FROM tbl") + + # Hang? + #optimize_table() + #check_table() + + +def test_different_current_key_ids(): + copy_keys(node1, 'key_a_and_b_current_a') + copy_keys(node2, 'key_a_and_b_current_b') + create_table() + + insert_data() + check_table() + + optimize_table() + check_table() + + +def test_different_nonces(): + copy_keys(node1, 'key_a_and_nonce_x') + copy_keys(node2, 'key_a_and_nonce_y') + create_table() + + insert_data() + check_table() + + optimize_table() + check_table()