提交 3d0c26f5 编写于 作者: A alesapin

Fix ipv4 mask restrictions for users and add integration tests

上级 bf7401ce
...@@ -70,18 +70,20 @@ public: ...@@ -70,18 +70,20 @@ public:
else else
{ {
String addr(str, 0, pos - str.c_str()); String addr(str, 0, pos - str.c_str());
mask_address = toIPv6(Poco::Net::IPAddress(addr)); auto real_address = Poco::Net::IPAddress(addr);
String str_mask(str, addr.length() + 1, str.length() - addr.length() - 1); String str_mask(str, addr.length() + 1, str.length() - addr.length() - 1);
if (isDigits(str_mask)) if (isDigits(str_mask))
{ {
UInt8 prefix_bits = parse<UInt8>(pos + 1); UInt8 prefix_bits = parse<UInt8>(pos + 1);
construct(prefix_bits); construct(prefix_bits, real_address.family() == Poco::Net::AddressFamily::IPv4);
} }
else else
{ {
subnet_mask = netmaskToIPv6(Poco::Net::IPAddress(str_mask)); subnet_mask = netmaskToIPv6(Poco::Net::IPAddress(str_mask));
} }
mask_address = toIPv6(real_address);
} }
} }
...@@ -97,9 +99,9 @@ private: ...@@ -97,9 +99,9 @@ private:
subnet_mask = Poco::Net::IPAddress(128, Poco::Net::IPAddress::IPv6); subnet_mask = Poco::Net::IPAddress(128, Poco::Net::IPAddress::IPv6);
} }
void construct(UInt8 prefix_bits) void construct(UInt8 prefix_bits, bool is_ipv4)
{ {
prefix_bits = mask_address.family() == Poco::Net::IPAddress::IPv4 ? prefix_bits + 96 : prefix_bits; prefix_bits = is_ipv4 ? prefix_bits + 96 : prefix_bits;
subnet_mask = Poco::Net::IPAddress(prefix_bits, Poco::Net::IPAddress::IPv6); subnet_mask = Poco::Net::IPAddress(prefix_bits, Poco::Net::IPAddress::IPv6);
} }
......
...@@ -97,7 +97,7 @@ class ClickHouseCluster: ...@@ -97,7 +97,7 @@ class ClickHouseCluster:
cmd += " client" cmd += " client"
return cmd return cmd
def add_instance(self, name, config_dir=None, main_configs=[], user_configs=[], macros={}, with_zookeeper=False, with_mysql=False, with_kafka=False, clickhouse_path_dir=None, with_odbc_drivers=False, with_postgres=False, with_hdfs=False, hostname=None, env_variables={}, image="yandex/clickhouse-integration-test", stay_alive=False): def add_instance(self, name, config_dir=None, main_configs=[], user_configs=[], macros={}, with_zookeeper=False, with_mysql=False, with_kafka=False, clickhouse_path_dir=None, with_odbc_drivers=False, with_postgres=False, with_hdfs=False, hostname=None, env_variables={}, image="yandex/clickhouse-integration-test", stay_alive=False, ipv4_address=None, ipv6_address=None):
"""Add an instance to the cluster. """Add an instance to the cluster.
name - the name of the instance directory and the value of the 'instance' macro in ClickHouse. name - the name of the instance directory and the value of the 'instance' macro in ClickHouse.
...@@ -116,7 +116,8 @@ class ClickHouseCluster: ...@@ -116,7 +116,8 @@ class ClickHouseCluster:
instance = ClickHouseInstance( instance = ClickHouseInstance(
self, self.base_dir, name, config_dir, main_configs, user_configs, macros, with_zookeeper, self, self.base_dir, name, config_dir, main_configs, user_configs, macros, with_zookeeper,
self.zookeeper_config_path, with_mysql, with_kafka, self.base_configs_dir, self.server_bin_path, self.zookeeper_config_path, with_mysql, with_kafka, self.base_configs_dir, self.server_bin_path,
clickhouse_path_dir, with_odbc_drivers, hostname=hostname, env_variables=env_variables, image=image, stay_alive=stay_alive) clickhouse_path_dir, with_odbc_drivers, hostname=hostname, env_variables=env_variables, image=image,
stay_alive=stay_alive, ipv4_address=ipv4_address, ipv6_address=ipv6_address)
self.instances[name] = instance self.instances[name] = instance
self.base_cmd.extend(['--file', instance.docker_compose_path]) self.base_cmd.extend(['--file', instance.docker_compose_path])
...@@ -332,7 +333,7 @@ CLICKHOUSE_START_COMMAND = "clickhouse server --config-file=/etc/clickhouse-serv ...@@ -332,7 +333,7 @@ CLICKHOUSE_START_COMMAND = "clickhouse server --config-file=/etc/clickhouse-serv
CLICKHOUSE_STAY_ALIVE_COMMAND = 'bash -c "{} --daemon; tail -f /dev/null"'.format(CLICKHOUSE_START_COMMAND) CLICKHOUSE_STAY_ALIVE_COMMAND = 'bash -c "{} --daemon; tail -f /dev/null"'.format(CLICKHOUSE_START_COMMAND)
DOCKER_COMPOSE_TEMPLATE = ''' DOCKER_COMPOSE_TEMPLATE = '''
version: '2' version: '2.2'
services: services:
{name}: {name}:
image: {image} image: {image}
...@@ -347,6 +348,22 @@ services: ...@@ -347,6 +348,22 @@ services:
depends_on: {depends_on} depends_on: {depends_on}
env_file: env_file:
- {env_file} - {env_file}
{networks}
{app_net}
{ipv4_address}
{ipv6_address}
networks:
app_net:
driver: bridge
enable_ipv6: true
ipam:
driver: default
config:
- subnet: 10.5.0.0/12
gateway: 10.5.1.1
- subnet: 2001:3984:3989::/64
gateway: 2001:3984:3989::1
''' '''
class ClickHouseInstance: class ClickHouseInstance:
...@@ -354,7 +371,8 @@ class ClickHouseInstance: ...@@ -354,7 +371,8 @@ class ClickHouseInstance:
def __init__( def __init__(
self, cluster, base_path, name, custom_config_dir, custom_main_configs, custom_user_configs, macros, self, cluster, base_path, name, custom_config_dir, custom_main_configs, custom_user_configs, macros,
with_zookeeper, zookeeper_config_path, with_mysql, with_kafka, base_configs_dir, server_bin_path, with_zookeeper, zookeeper_config_path, with_mysql, with_kafka, base_configs_dir, server_bin_path,
clickhouse_path_dir, with_odbc_drivers, hostname=None, env_variables={}, image="yandex/clickhouse-integration-test", stay_alive=False): clickhouse_path_dir, with_odbc_drivers, hostname=None, env_variables={}, image="yandex/clickhouse-integration-test",
stay_alive=False, ipv4_address=None, ipv6_address=None):
self.name = name self.name = name
self.base_cmd = cluster.base_cmd[:] self.base_cmd = cluster.base_cmd[:]
...@@ -391,6 +409,8 @@ class ClickHouseInstance: ...@@ -391,6 +409,8 @@ class ClickHouseInstance:
self.default_timeout = 20.0 # 20 sec self.default_timeout = 20.0 # 20 sec
self.image = image self.image = image
self.stay_alive = stay_alive self.stay_alive = stay_alive
self.ipv4_address = ipv4_address
self.ipv6_address = ipv6_address
# Connects to the instance via clickhouse-client, sends a query (1st argument) and returns the answer # Connects to the instance via clickhouse-client, sends a query (1st argument) and returns the answer
def query(self, sql, stdin=None, timeout=None, settings=None, user=None, ignore_error=False): def query(self, sql, stdin=None, timeout=None, settings=None, user=None, ignore_error=False):
...@@ -609,6 +629,18 @@ class ClickHouseInstance: ...@@ -609,6 +629,18 @@ class ClickHouseInstance:
if self.stay_alive: if self.stay_alive:
entrypoint_cmd = CLICKHOUSE_STAY_ALIVE_COMMAND entrypoint_cmd = CLICKHOUSE_STAY_ALIVE_COMMAND
ipv4_address = ipv6_address = ""
if self.ipv4_address is None and self.ipv6_address is None:
networks = ""
app_net = ""
else:
networks = "networks:"
app_net = "app_net:"
if self.ipv4_address is not None:
ipv4_address = "ipv4_address: " + self.ipv4_address
if self.ipv6_address is not None:
ipv6_address = "ipv6_address: " + self.ipv6_address
with open(self.docker_compose_path, 'w') as docker_compose: with open(self.docker_compose_path, 'w') as docker_compose:
docker_compose.write(DOCKER_COMPOSE_TEMPLATE.format( docker_compose.write(DOCKER_COMPOSE_TEMPLATE.format(
image=self.image, image=self.image,
...@@ -623,6 +655,10 @@ class ClickHouseInstance: ...@@ -623,6 +655,10 @@ class ClickHouseInstance:
env_file=env_file, env_file=env_file,
odbc_ini_path=odbc_ini_path, odbc_ini_path=odbc_ini_path,
entrypoint_cmd=entrypoint_cmd, entrypoint_cmd=entrypoint_cmd,
networks=networks,
app_net=app_net,
ipv4_address=ipv4_address,
ipv6_address=ipv6_address,
)) ))
......
version: '2' version: '2.2'
services: services:
hdfs1: hdfs1:
image: sequenceiq/hadoop-docker:2.7.0 image: sequenceiq/hadoop-docker:2.7.0
......
version: '2' version: '2.2'
services: services:
kafka_zookeeper: kafka_zookeeper:
......
version: '2' version: '2.2'
services: services:
mysql1: mysql1:
image: mysql:5.7 image: mysql:5.7
......
version: '2' version: '2.2'
services: services:
postgres1: postgres1:
image: postgres image: postgres
......
version: '2' version: '2.2'
services: services:
zoo1: zoo1:
image: zookeeper image: zookeeper
......
<yandex>
<profiles>
<default>
<max_memory_usage>10000000000</max_memory_usage>
<use_uncompressed_cache>0</use_uncompressed_cache>
<load_balancing>random</load_balancing>
</default>
</profiles>
<users>
<default>
<password></password>
<networks incl="networks" replace="replace">
<ip>10.5.173.1</ip>
<ip>10.5.172.0/24</ip>
<ip>10.5.175.0/255.255.255.0</ip>
</networks>
<profile>default</profile>
<quota>default</quota>
</default>
</users>
<quotas>
<default>
</default>
</quotas>
</yandex>
<yandex>
<profiles>
<default>
<max_memory_usage>10000000000</max_memory_usage>
<use_uncompressed_cache>0</use_uncompressed_cache>
<load_balancing>random</load_balancing>
</default>
</profiles>
<users>
<default>
<password></password>
<networks incl="networks" replace="replace">
<ip>2001:3984:3989:0:0:0:1:1111</ip>
<ip>2001:3984:3989:0:0:0:0:0/112</ip>
</networks>
<profile>default</profile>
<quota>default</quota>
</default>
</users>
<quotas>
<default>
</default>
</quotas>
</yandex>
import time
import pytest
from helpers.cluster import ClickHouseCluster
from helpers.test_tools import assert_eq_with_retry
cluster = ClickHouseCluster(__file__)
node_ipv4 = cluster.add_instance('node_ipv4', config_dir="configs", user_configs=['configs/users_ipv4.xml'], ipv4_address='10.5.172.77')
client_ipv4_ok = cluster.add_instance('client_ipv4_ok', config_dir="configs", ipv4_address='10.5.172.10')
client_ipv4_ok_direct = cluster.add_instance('client_ipv4_ok_direct', config_dir="configs", ipv4_address='10.5.173.1')
client_ipv4_ok_full_mask = cluster.add_instance('client_ipv4_ok_full_mask', config_dir="configs", ipv4_address='10.5.175.77')
client_ipv4_bad = cluster.add_instance('client_ipv4_bad', config_dir="configs", ipv4_address='10.5.173.10')
node_ipv6 = cluster.add_instance('node_ipv6', config_dir="configs", main_configs=["configs/config_ipv6.xml"], user_configs=['configs/users_ipv6.xml'], ipv6_address='2001:3984:3989::1:1000')
client_ipv6_ok = cluster.add_instance('client_ipv6_ok', config_dir="configs", ipv6_address='2001:3984:3989::5555')
client_ipv6_ok_direct = cluster.add_instance('client_ipv6_ok_direct', config_dir="configs", ipv6_address='2001:3984:3989::1:1111')
client_ipv6_bad = cluster.add_instance('client_ipv6_bad', config_dir="configs", ipv6_address='2001:3984:3989::1:1112')
@pytest.fixture(scope="module")
def setup_cluster():
try:
cluster.start()
yield cluster
finally:
cluster.shutdown()
def test_ipv4(setup_cluster):
try:
client_ipv4_ok.exec_in_container(["bash", "-c", "/usr/bin/clickhouse client --host 10.5.172.77 --query 'select 1'"], privileged=True, user='root')
except Exception as ex:
assert False, "allowed client with 10.5.172.10 cannot connect to server with allowed mask '10.5.172.0/24'"
try:
client_ipv4_ok_direct.exec_in_container(["bash", "-c", "/usr/bin/clickhouse client --host 10.5.172.77 --query 'select 1'"], privileged=True, user='root')
except Exception as ex:
assert False, "allowed client with 10.5.173.1 cannot connect to server with allowed ip '10.5.173.1'"
try:
client_ipv4_ok_full_mask.exec_in_container(["bash", "-c", "/usr/bin/clickhouse client --host 10.5.172.77 --query 'select 1'"], privileged=True, user='root')
except Exception as ex:
assert False, "allowed client with 10.5.175.77 cannot connect to server with allowed ip '10.5.175.0/255.255.255.0'"
try:
client_ipv4_bad.exec_in_container(["bash", "-c", "/usr/bin/clickhouse client --host 10.5.172.77 --query 'select 1'"], privileged=True, user='root')
assert False, "restricted client with 10.5.173.10 can connect to server with allowed mask '10.5.172.0/24'"
except AssertionError:
raise
except Exception as ex:
print ex
def test_ipv6(setup_cluster):
try:
client_ipv6_ok.exec_in_container(["bash", "-c", "/usr/bin/clickhouse client --host 2001:3984:3989::1:1000 --query 'select 1'"], privileged=True, user='root')
except Exception as ex:
print ex
assert False, "allowed client with 2001:3984:3989:0:0:0:1:1111 cannot connect to server with allowed mask '2001:3984:3989:0:0:0:0:0/112'"
try:
client_ipv6_ok_direct.exec_in_container(["bash", "-c", "/usr/bin/clickhouse client --host 2001:3984:3989:0:0:0:1:1000 --query 'select 1'"], privileged=True, user='root')
except Exception as ex:
assert False, "allowed client with 2001:3984:3989:0:0:0:1:1111 cannot connect to server with allowed ip '2001:3984:3989:0:0:0:1:1111'"
try:
client_ipv6_bad.exec_in_container(["bash", "-c", "/usr/bin/clickhouse client --host 2001:3984:3989:0:0:0:1:1000 --query 'select 1'"], privileged=True, user='root')
assert False, "restricted client with 2001:3984:3989:0:0:0:1:1112 can connect to server with allowed mask '2001:3984:3989:0:0:0:0:0/112'"
except AssertionError:
raise
except Exception as ex:
print ex
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册