Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

24.8 Backport of #70332 - Passing external user roles from query originator to other nodes #542

Merged
merged 32 commits into from
Jan 21, 2025
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
6e48f8a
Merge pull request #63781 from ClickHouse/ft-chunked-protocol
yakov-olkhovskiy Aug 14, 2024
b48e249
Merge pull request #64448 from ClickHouse/pr-local-plan
devcrafter Sep 11, 2024
f1cf4fc
Merge pull request #69602 from ClickHouse/rm_explicit_initial_announc…
nickitat Sep 14, 2024
06a4050
Merge pull request #68424 from ClickHouse/adaptive_parallel_replicas
nickitat Sep 17, 2024
556c04a
Merge pull request #69744 from ClickHouse/fix_pr_protocol
nickitat Sep 19, 2024
bd014e1
Merge pull request #69706 from ClickHouse/pror_events_for_pr
nickitat Sep 19, 2024
19481de
Merge pull request #68355 from zvonand/tryfix-65762-again
Algunenano Sep 20, 2024
7e6b90c
Merge pull request #63151 from ClickHouse/parallel-replicas-beta
nikitamikhaylov Sep 25, 2024
611d1d4
Merge pull request #70332 from zvonand/ldap-remote-roles
pufit Nov 19, 2024
d2b3dc0
Merge pull request #72759 from zvonand/hotfix-72756
yariks5s Dec 6, 2024
3cf834b
fix build pt. 1
zvonand Dec 17, 2024
9d7b3d7
Merge pull request #65832 from CurtizJ/add-mutations-snapshot
CurtizJ Sep 5, 2024
1ec0a09
Merge branch 'customizations/24.8.8' into backports/24.8/remote-roles…
zvonand Dec 18, 2024
237858a
Merge branch 'customizations/24.8.8' into backports/24.8/remote-roles…
zvonand Dec 18, 2024
b0cbccb
remove non existing settings from settingschanges
zvonand Dec 18, 2024
ca5b435
Merge branch 'backports/24.8/remote-roles-push' of github.com:Altinit…
zvonand Dec 18, 2024
26b194b
Merge pull request #63781 from ClickHouse/ft-chunked-protocol
yakov-olkhovskiy Aug 14, 2024
14e8bd2
Merge pull request #64448 from ClickHouse/pr-local-plan
devcrafter Sep 11, 2024
049c2f6
Merge pull request #69602 from ClickHouse/rm_explicit_initial_announc…
nickitat Sep 14, 2024
cdc6380
Merge pull request #68424 from ClickHouse/adaptive_parallel_replicas
nickitat Sep 17, 2024
b5cf09b
Merge pull request #69744 from ClickHouse/fix_pr_protocol
nickitat Sep 19, 2024
95a19e9
Merge pull request #69706 from ClickHouse/pror_events_for_pr
nickitat Sep 19, 2024
2c94409
Merge pull request #68355 from zvonand/tryfix-65762-again
Algunenano Sep 20, 2024
72afb16
Merge pull request #63151 from ClickHouse/parallel-replicas-beta
nikitamikhaylov Sep 25, 2024
cc34cd2
Merge pull request #70332 from zvonand/ldap-remote-roles
pufit Nov 19, 2024
5103af7
Merge pull request #72759 from zvonand/hotfix-72756
yariks5s Dec 6, 2024
e283f07
fix build pt. 1
zvonand Dec 17, 2024
764d5bb
Merge pull request #65832 from CurtizJ/add-mutations-snapshot
CurtizJ Sep 5, 2024
a558b75
remove non existing settings from settingschanges
zvonand Dec 18, 2024
1a4645d
Merge branch 'customizations/24.8.11' into backports/24.8/remote-role…
zvonand Jan 16, 2025
c65cd3e
Merge branch 'backports/24.8/remote-roles-push' of github.com:Altinit…
zvonand Jan 20, 2025
2702361
fix typo
devcrafter Dec 24, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docker/test/stateful/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ function run_tests()
)
if [[ -n "$USE_PARALLEL_REPLICAS" ]] && [[ "$USE_PARALLEL_REPLICAS" -eq 1 ]]; then
TEST_ARGS+=(
--client="clickhouse-client --allow_experimental_parallel_reading_from_replicas=1 --parallel_replicas_for_non_replicated_merge_tree=1 --max_parallel_replicas=100 --cluster_for_parallel_replicas='parallel_replicas'"
--client="clickhouse-client --enable_parallel_replicas=1 --parallel_replicas_for_non_replicated_merge_tree=1 --max_parallel_replicas=100 --cluster_for_parallel_replicas='parallel_replicas'"
--no-parallel-replicas
)
fi
Expand Down
17 changes: 2 additions & 15 deletions docs/en/operations/settings/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -1588,25 +1588,12 @@ This setting is useful for any replicated table.

An arbitrary integer expression that can be used to split work between replicas for a specific table.
The value can be any integer expression.
A query may be processed faster if it is executed on several servers in parallel but it depends on the used [parallel_replicas_custom_key](#parallel_replicas_custom_key)
and [parallel_replicas_custom_key_filter_type](#parallel_replicas_custom_key_filter_type).

Simple expressions using primary keys are preferred.

If the setting is used on a cluster that consists of a single shard with multiple replicas, those replicas will be converted into virtual shards.
Otherwise, it will behave same as for `SAMPLE` key, it will use multiple replicas of each shard.

## parallel_replicas_custom_key_filter_type {#parallel_replicas_custom_key_filter_type}

How to use `parallel_replicas_custom_key` expression for splitting work between replicas.

Possible values:

- `default` — Use the default implementation using modulo operation on the `parallel_replicas_custom_key`.
- `range` — Split the entire value space of the expression in the ranges. This type of filtering is useful if values of `parallel_replicas_custom_key` are uniformly spread across the entire integer space, e.g. hash values.

Default value: `default`.

## parallel_replicas_custom_key_range_lower {#parallel_replicas_custom_key_range_lower}

Allows the filter type `range` to split the work evenly between replicas based on the custom range `[parallel_replicas_custom_key_range_lower, INT_MAX]`.
Expand All @@ -1621,9 +1608,9 @@ Allows the filter type `range` to split the work evenly between replicas based o

When used in conjuction with [parallel_replicas_custom_key_range_lower](#parallel_replicas_custom_key_range_lower), it lets the filter evenly split the work over replicas for the range `[parallel_replicas_custom_key_range_lower, parallel_replicas_custom_key_range_upper]`.

Note: This setting will not cause any additional data to be filtered during query processing, rather it changes the points at which the range filter breaks up the range `[0, INT_MAX]` for parallel processing.
Note: This setting will not cause any additional data to be filtered during query processing, rather it changes the points at which the range filter breaks up the range `[0, INT_MAX]` for parallel processing

## allow_experimental_parallel_reading_from_replicas
## enable_parallel_replicas

Enables or disables sending SELECT queries to all replicas of a table (up to `max_parallel_replicas`). Reading is parallelized and coordinated dynamically. It will work for any kind of MergeTree table.

Expand Down
6 changes: 6 additions & 0 deletions docs/ru/operations/settings/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -4215,3 +4215,9 @@ SELECT toFloat64('1.7091'), toFloat64('1.5008753E7') SETTINGS precise_float_pars
│ 1.7091 │ 15008753 │
└─────────────────────┴──────────────────────────┘
```

## push_external_roles_in_interserver_queries

Позволяет передавать роли пользователя от инициатора запроса другим нодам при выполнении запроса.

Значение по умолчанию: `true`.
52 changes: 51 additions & 1 deletion programs/benchmark/Benchmark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ class Benchmark : public Poco::Util::Application
const String & default_database_,
const String & user_,
const String & password_,
const String & proto_send_chunked_,
const String & proto_recv_chunked_,
const String & quota_key_,
const String & stage,
bool randomize_,
Expand Down Expand Up @@ -128,7 +130,9 @@ class Benchmark : public Poco::Util::Application
connections.emplace_back(std::make_unique<ConnectionPool>(
concurrency,
cur_host, cur_port,
default_database_, user_, password_, quota_key_,
default_database_, user_, password_,
proto_send_chunked_, proto_recv_chunked_,
quota_key_,
/* cluster_= */ "",
/* cluster_secret_= */ "",
/* client_name_= */ std::string(DEFAULT_CLIENT_NAME),
Expand Down Expand Up @@ -662,6 +666,50 @@ int mainEntryClickHouseBenchmark(int argc, char ** argv)

Strings hosts = options.count("host") ? options["host"].as<Strings>() : Strings({"localhost"});

String proto_send_chunked {"notchunked"};
String proto_recv_chunked {"notchunked"};

if (options.count("proto_caps"))
{
std::string proto_caps_str = options["proto_caps"].as<std::string>();

std::vector<std::string_view> proto_caps;
splitInto<','>(proto_caps, proto_caps_str);

for (auto cap_str : proto_caps)
{
std::string direction;

if (cap_str.starts_with("send_"))
{
direction = "send";
cap_str = cap_str.substr(std::string_view("send_").size());
}
else if (cap_str.starts_with("recv_"))
{
direction = "recv";
cap_str = cap_str.substr(std::string_view("recv_").size());
}

if (cap_str != "chunked" && cap_str != "notchunked" && cap_str != "chunked_optional" && cap_str != "notchunked_optional")
throw Exception(ErrorCodes::BAD_ARGUMENTS, "proto_caps option is incorrect ({})", proto_caps_str);

if (direction.empty())
{
proto_send_chunked = cap_str;
proto_recv_chunked = cap_str;
}
else
{
if (direction == "send")
proto_send_chunked = cap_str;
else
proto_recv_chunked = cap_str;
}
}
}


Benchmark benchmark(
options["concurrency"].as<unsigned>(),
options["delay"].as<double>(),
Expand All @@ -673,6 +721,8 @@ int mainEntryClickHouseBenchmark(int argc, char ** argv)
options["database"].as<std::string>(),
options["user"].as<std::string>(),
options["password"].as<std::string>(),
proto_send_chunked,
proto_recv_chunked,
options["quota_key"].as<std::string>(),
options["stage"].as<std::string>(),
options.count("randomize"),
Expand Down
2 changes: 1 addition & 1 deletion programs/client/Client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ std::vector<String> Client::loadWarningMessages()
"" /* query_id */,
QueryProcessingStage::Complete,
&client_context->getSettingsRef(),
&client_context->getClientInfo(), false, {});
&client_context->getClientInfo(), false, {}, {});
while (true)
{
Packet packet = connection->receivePacket();
Expand Down
15 changes: 15 additions & 0 deletions programs/client/clickhouse-client.xml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,21 @@
<production>{display_name} \e[1;31m:)\e[0m </production> <!-- if it matched to the substring "production" in the server display name -->
</prompt_by_server_display_name>

<!-- Chunked capabilities for native protocol by client.
Can be enabled separately for send and receive channels.
Supported modes:
- chunked - client will only work with server supporting chunked protocol;
- chunked_optional - client prefer server to enable chunked protocol, but can switch to notchunked if server does not support this;
- notchunked - client will only work with server supporting notchunked protocol (current default);
- notchunked_optional - client prefer server notchunked protocol, but can switch to chunked if server does not support this.
-->
<!--
<proto_caps>
<send>chunked_optional</send>
<recv>chunked_optional</recv>
</proto_caps>
-->

<!--
Settings adjustable via command-line parameters
can take their defaults from that config file, see examples:
Expand Down
15 changes: 15 additions & 0 deletions programs/server/config.xml
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,21 @@
-->
<tcp_port>9000</tcp_port>

<!-- Chunked capabilities for native protocol by server.
Can be enabled separately for send and receive channels.
Supported modes:
- chunked - server requires from client to have chunked enabled;
- chunked_optional - server supports both chunked and notchunked protocol;
- notchunked - server requires from client notchunked protocol (current default);
- notchunked_optional - server supports both chunked and notchunked protocol.
-->
<!--
<proto_caps>
<send>notchunked_optional</send>
<recv>notchunked_optional</recv>
</proto_caps>
-->

<!-- Compatibility with MySQL protocol.
ClickHouse will pretend to be MySQL for applications connecting to this port.
-->
Expand Down
8 changes: 7 additions & 1 deletion src/Access/ContextAccess.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,13 @@ void ContextAccess::setUser(const UserPtr & user_) const
current_roles_with_admin_option = user->granted_roles.findGrantedWithAdminOption(*params.current_roles);
}

if (params.external_roles && !params.external_roles->empty())
{
current_roles.insert(current_roles.end(), params.external_roles->begin(), params.external_roles->end());
auto new_granted_with_admin_option = user->granted_roles.findGrantedWithAdminOption(*params.external_roles);
current_roles_with_admin_option.insert(current_roles_with_admin_option.end(), new_granted_with_admin_option.begin(), new_granted_with_admin_option.end());
}

subscription_for_roles_changes.reset();
enabled_roles = access_control->getEnabledRoles(current_roles, current_roles_with_admin_option);
subscription_for_roles_changes = enabled_roles->subscribeForChanges([weak_ptr = weak_from_this()](const std::shared_ptr<const EnabledRolesInfo> & roles_info_)
Expand Down Expand Up @@ -516,7 +523,6 @@ std::optional<QuotaUsage> ContextAccess::getQuotaUsage() const
return getQuota()->getUsage();
}


SettingsChanges ContextAccess::getDefaultSettings() const
{
std::lock_guard lock{mutex};
Expand Down
15 changes: 15 additions & 0 deletions src/Access/ContextAccessParams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@ ContextAccessParams::ContextAccessParams(
bool full_access_,
bool use_default_roles_,
const std::shared_ptr<const std::vector<UUID>> & current_roles_,
const std::shared_ptr<const std::vector<UUID>> & external_roles_,
const Settings & settings_,
const String & current_database_,
const ClientInfo & client_info_)
: user_id(user_id_)
, full_access(full_access_)
, use_default_roles(use_default_roles_)
, current_roles(current_roles_)
, external_roles(external_roles_)
, readonly(settings_.readonly)
, allow_ddl(settings_.allow_ddl)
, allow_introspection(settings_.allow_introspection_functions)
Expand Down Expand Up @@ -52,6 +54,17 @@ String ContextAccessParams::toString() const
}
out << "]";
}
if (external_roles && !external_roles->empty())
{
out << separator() << "external_roles = [";
for (size_t i = 0; i != external_roles->size(); ++i)
{
if (i)
out << ", ";
out << (*external_roles)[i];
}
out << "]";
}
if (readonly)
out << separator() << "readonly = " << readonly;
if (allow_ddl)
Expand Down Expand Up @@ -101,6 +114,7 @@ bool operator ==(const ContextAccessParams & left, const ContextAccessParams & r
CONTEXT_ACCESS_PARAMS_EQUALS(full_access)
CONTEXT_ACCESS_PARAMS_EQUALS(use_default_roles)
CONTEXT_ACCESS_PARAMS_EQUALS(current_roles)
CONTEXT_ACCESS_PARAMS_EQUALS(external_roles)
CONTEXT_ACCESS_PARAMS_EQUALS(readonly)
CONTEXT_ACCESS_PARAMS_EQUALS(allow_ddl)
CONTEXT_ACCESS_PARAMS_EQUALS(allow_introspection)
Expand Down Expand Up @@ -153,6 +167,7 @@ bool operator <(const ContextAccessParams & left, const ContextAccessParams & ri
CONTEXT_ACCESS_PARAMS_LESS(full_access)
CONTEXT_ACCESS_PARAMS_LESS(use_default_roles)
CONTEXT_ACCESS_PARAMS_LESS(current_roles)
CONTEXT_ACCESS_PARAMS_LESS(external_roles)
CONTEXT_ACCESS_PARAMS_LESS(readonly)
CONTEXT_ACCESS_PARAMS_LESS(allow_ddl)
CONTEXT_ACCESS_PARAMS_LESS(allow_introspection)
Expand Down
2 changes: 2 additions & 0 deletions src/Access/ContextAccessParams.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class ContextAccessParams
bool full_access_,
bool use_default_roles_,
const std::shared_ptr<const std::vector<UUID>> & current_roles_,
const std::shared_ptr<const std::vector<UUID>> & external_roles_,
const Settings & settings_,
const String & current_database_,
const ClientInfo & client_info_);
Expand All @@ -31,6 +32,7 @@ class ContextAccessParams

const bool use_default_roles;
const std::shared_ptr<const std::vector<UUID>> current_roles;
const std::shared_ptr<const std::vector<UUID>> external_roles;

const UInt64 readonly;
const bool allow_ddl;
Expand Down
7 changes: 5 additions & 2 deletions src/Access/LDAPAccessStorage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ namespace ErrorCodes
extern const int BAD_ARGUMENTS;
}


LDAPAccessStorage::LDAPAccessStorage(const String & storage_name_, AccessControl & access_control_, const Poco::Util::AbstractConfiguration & config, const String & prefix)
: IAccessStorage(storage_name_), access_control(access_control_), memory_storage(storage_name_, access_control.getChangesNotifier(), false)
{
Expand Down Expand Up @@ -191,8 +190,8 @@ void LDAPAccessStorage::applyRoleChangeNoLock(bool grant, const UUID & role_id,
}
else
{
granted_role_names.erase(role_id);
granted_role_ids.erase(role_name);
granted_role_names.erase(role_id);
}
}

Expand Down Expand Up @@ -320,6 +319,10 @@ std::set<String> LDAPAccessStorage::mapExternalRolesNoLock(const LDAPClient::Sea
{
std::set<String> role_names;

// If this node can't access LDAP server (or has not privileges to fetch roles) and gets empty list of external roles
if (external_roles.empty())
return role_names;

if (external_roles.size() != role_search_params.size())
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Unable to map external roles");

Expand Down
37 changes: 37 additions & 0 deletions src/Client/ClientApplicationBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ void ClientApplicationBase::init(int argc, char ** argv)

("config-file,C", po::value<std::string>(), "config-file path")

("proto_caps", po::value<std::string>(), "enable/disable chunked protocol: chunked_optional, notchunked, notchunked_optional, send_chunked, send_chunked_optional, send_notchunked, send_notchunked_optional, recv_chunked, recv_chunked_optional, recv_notchunked, recv_notchunked_optional")

("query,q", po::value<std::vector<std::string>>()->multitoken(), R"(Query. Can be specified multiple times (--query "SELECT 1" --query "SELECT 2") or once with multiple comma-separated queries (--query "SELECT 1; SELECT 2;"). In the latter case, INSERT queries with non-VALUE format must be separated by empty lines.)")
("queries-file", po::value<std::vector<std::string>>()->multitoken(), "file path with queries to execute; multiple files can be specified (--queries-file file1 file2...)")
("multiquery,n", "Obsolete, does nothing")
Expand Down Expand Up @@ -337,6 +339,41 @@ void ClientApplicationBase::init(int argc, char ** argv)
if (options.count("server_logs_file"))
server_logs_file = options["server_logs_file"].as<std::string>();

if (options.count("proto_caps"))
{
std::string proto_caps_str = options["proto_caps"].as<std::string>();

std::vector<std::string_view> proto_caps;
splitInto<','>(proto_caps, proto_caps_str);

for (auto cap_str : proto_caps)
{
std::string direction;

if (cap_str.starts_with("send_"))
{
direction = "send";
cap_str = cap_str.substr(std::string_view("send_").size());
}
else if (cap_str.starts_with("recv_"))
{
direction = "recv";
cap_str = cap_str.substr(std::string_view("recv_").size());
}

if (cap_str != "chunked" && cap_str != "notchunked" && cap_str != "chunked_optional" && cap_str != "notchunked_optional")
throw Exception(ErrorCodes::BAD_ARGUMENTS, "proto_caps option is incorrect ({})", proto_caps_str);

if (direction.empty())
{
config().setString("proto_caps.send", std::string(cap_str));
config().setString("proto_caps.recv", std::string(cap_str));
}
else
config().setString("proto_caps." + direction, std::string(cap_str));
}
}

query_processing_stage = QueryProcessingStage::fromString(options["stage"].as<std::string>());
query_kind = parseQueryKind(options["query_kind"].as<std::string>());
profile_events.print = options.count("print-profile-events");
Expand Down
Loading
Loading