diff --git a/dbms/src/Interpreters/Cluster.cpp b/dbms/src/Interpreters/Cluster.cpp index 834a27f26a2..f9a6e4079c5 100644 --- a/dbms/src/Interpreters/Cluster.cpp +++ b/dbms/src/Interpreters/Cluster.cpp @@ -67,12 +67,13 @@ Cluster::Address::Address(const Poco::Util::AbstractConfiguration & config, cons } -Cluster::Address::Address(const String & host_port_, const String & user_, const String & password_, UInt16 clickhouse_port) +Cluster::Address::Address(const String & host_port_, const String & user_, const String & password_, UInt16 clickhouse_port, bool secure_) : user(user_), password(password_) { auto parsed_host_port = parseAddress(host_port_, clickhouse_port); host_name = parsed_host_port.first; port = parsed_host_port.second; + secure = secure_ ? Protocol::Secure::Enable : Protocol::Secure::Disable; initially_resolved_address = DNSResolver::instance().resolveAddress(parsed_host_port.first, parsed_host_port.second); is_local = isLocal(*this, initially_resolved_address, clickhouse_port); @@ -319,7 +320,7 @@ Cluster::Cluster(const Poco::Util::AbstractConfiguration & config, const Setting Cluster::Cluster(const Settings & settings, const std::vector> & names, - const String & username, const String & password, UInt16 clickhouse_port, bool treat_local_as_remote) + const String & username, const String & password, UInt16 clickhouse_port, bool treat_local_as_remote, bool secure) { UInt32 current_shard_num = 1; @@ -327,7 +328,7 @@ Cluster::Cluster(const Settings & settings, const std::vector> & names, const String & username, const String & password, - UInt16 clickhouse_port, bool treat_local_as_remote); + UInt16 clickhouse_port, bool treat_local_as_remote, bool secure = false); Cluster(const Cluster &) = delete; Cluster & operator=(const Cluster &) = delete; @@ -69,7 +69,7 @@ public: Address() = default; Address(const Poco::Util::AbstractConfiguration & config, const String & config_prefix); - Address(const String & host_port_, const String & user_, const String & password_, UInt16 clickhouse_port); + Address(const String & host_port_, const String & user_, const String & password_, UInt16 clickhouse_port, bool secure_ = false); /// Returns 'escaped_host_name:port' String toString() const; diff --git a/dbms/src/TableFunctions/TableFunctionRemote.cpp b/dbms/src/TableFunctions/TableFunctionRemote.cpp index 5f81a9c21ec..a41f1c89c49 100644 --- a/dbms/src/TableFunctions/TableFunctionRemote.cpp +++ b/dbms/src/TableFunctions/TableFunctionRemote.cpp @@ -12,6 +12,7 @@ #include #include #include +#include namespace DB @@ -152,7 +153,8 @@ StoragePtr TableFunctionRemote::executeImpl(const ASTPtr & ast_function, const C if (names.empty()) throw Exception("Shard list is empty after parsing first argument", ErrorCodes::BAD_ARGUMENTS); - cluster = std::make_shared(context.getSettings(), names, username, password, context.getTCPPort(), false); + auto maybe_secure_port = context.getTCPPortSecure(); + cluster = std::make_shared(context.getSettings(), names, username, password, (secure ? (maybe_secure_port ? *maybe_secure_port : DBMS_DEFAULT_SECURE_PORT) : context.getTCPPort()), false, secure); } auto structure_remote_table = getStructureOfRemoteTable(*cluster, remote_database, remote_table, context, remote_table_function_ptr); @@ -177,8 +179,8 @@ StoragePtr TableFunctionRemote::executeImpl(const ASTPtr & ast_function, const C } -TableFunctionRemote::TableFunctionRemote(const std::string & name_) - : name(name_) +TableFunctionRemote::TableFunctionRemote(const std::string & name_, bool secure) + : name{name_}, secure{secure} { is_cluster_function = name == "cluster"; @@ -193,6 +195,7 @@ TableFunctionRemote::TableFunctionRemote(const std::string & name_) void registerTableFunctionRemote(TableFunctionFactory & factory) { factory.registerFunction("remote", [] () -> TableFunctionPtr { return std::make_shared("remote"); }); + factory.registerFunction("remoteSecure", [] () -> TableFunctionPtr { return std::make_shared("remote", /* secure = */ true); }); factory.registerFunction("cluster", [] () -> TableFunctionPtr { return std::make_shared("cluster"); }); } diff --git a/dbms/src/TableFunctions/TableFunctionRemote.h b/dbms/src/TableFunctions/TableFunctionRemote.h index 526fecf74ed..c9019ab682b 100644 --- a/dbms/src/TableFunctions/TableFunctionRemote.h +++ b/dbms/src/TableFunctions/TableFunctionRemote.h @@ -16,7 +16,7 @@ namespace DB class TableFunctionRemote : public ITableFunction { public: - explicit TableFunctionRemote(const std::string & name_ = "remote"); + explicit TableFunctionRemote(const std::string & name_ = "remote", bool secure = false); std::string getName() const override { return name; } @@ -26,6 +26,7 @@ private: std::string name; bool is_cluster_function; std::string help_message; + bool secure; }; } diff --git a/dbms/tests/queries/0_stateless/00505_shard_secure.reference b/dbms/tests/queries/0_stateless/00505_shard_secure.reference new file mode 100644 index 00000000000..4521d575ff3 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00505_shard_secure.reference @@ -0,0 +1,10 @@ +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 diff --git a/dbms/tests/queries/0_stateless/00505_shard_secure.sh b/dbms/tests/queries/0_stateless/00505_shard_secure.sh new file mode 100755 index 00000000000..ecf74653e57 --- /dev/null +++ b/dbms/tests/queries/0_stateless/00505_shard_secure.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash + +# set -x + +CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +. $CURDIR/../shell_config.sh + +# Not default server config needed + +tcp_port_secure=`$CLICKHOUSE_EXTRACT_CONFIG -k tcp_port_secure 2>/dev/null` +if [ -z $tcp_port_secure ]; then + # Secure port disabled. Fake result + cat $CURDIR/00505_shard_secure.reference +else + + $CLICKHOUSE_CLIENT -q "SELECT * FROM remoteSecure('127.0.0.{1,2}', system.one);" + $CLICKHOUSE_CLIENT -q "SELECT * FROM remoteSecure('127.0.0.{1,2}:$CLICKHOUSE_PORT_TCP_SECURE', system.one);" + $CLICKHOUSE_CLIENT -q "SELECT * FROM remoteSecure('127.0.0.{1,2}', system.one);" + $CLICKHOUSE_CLIENT -q "SELECT * FROM remoteSecure(test_shard_localhost_secure, system.one);" + $CLICKHOUSE_CLIENT -q "SELECT * FROM remote(test_shard_localhost_secure, system.one);" + $CLICKHOUSE_CLIENT -q "SELECT * FROM remoteSecure(test_shard_localhost, system.one);" + $CLICKHOUSE_CLIENT -q "SELECT * FROM remote(test_shard_localhost, system.one);" + +fi diff --git a/docs/en/query_language/table_functions/remote.md b/docs/en/query_language/table_functions/remote.md index 90e9085573f..06d9876f1c7 100644 --- a/docs/en/query_language/table_functions/remote.md +++ b/docs/en/query_language/table_functions/remote.md @@ -1,5 +1,5 @@ -# remote +# remote, remoteSecure Allows you to access remote servers without creating a `Distributed` table. @@ -72,5 +72,6 @@ The `remote` table function can be useful in the following cases: If the user is not specified, `default` is used. If the password is not specified, an empty password is used. +`remoteSecure` - same as `remote` but with secured connection. Default port - `tcp_port_secure` from config or 9440. [Original article](https://clickhouse.yandex/docs/en/query_language/table_functions/remote/) diff --git a/docs/ru/query_language/table_functions/remote.md b/docs/ru/query_language/table_functions/remote.md index c3eeeed46e0..555a752a94e 100644 --- a/docs/ru/query_language/table_functions/remote.md +++ b/docs/ru/query_language/table_functions/remote.md @@ -1,5 +1,5 @@ -# remote +# remote, remoteSecure Позволяет обратиться к удалённым серверам без создания таблицы типа `Distributed`. @@ -72,4 +72,6 @@ example01-{01..02}-{1|2} Если пользователь не задан,то используется `default`. Если пароль не задан, то используется пустой пароль. +`remoteSecure` - аналогично функции `remote` но с соединением по шифрованому каналу. Порт по умолчанию - `tcp_port_secure` из конфига или 9440. + [Оригинальная статья](https://clickhouse.yandex/docs/ru/query_language/table_functions/remote/)