Skip to content

Commit bb6d5d8

Browse files
committed
Support multiple roles via HTTP, update tests
1 parent f4af7e1 commit bb6d5d8

File tree

3 files changed

+133
-85
lines changed

3 files changed

+133
-85
lines changed

src/Server/HTTPHandler.cpp

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ namespace ErrorCodes
119119
extern const int WRONG_PASSWORD;
120120
extern const int REQUIRED_PASSWORD;
121121
extern const int AUTHENTICATION_FAILED;
122+
extern const int ACCESS_DENIED;
122123

123124
extern const int INVALID_SESSION_TIMEOUT;
124125
extern const int HTTP_LENGTH_REQUIRED;
@@ -196,7 +197,8 @@ static Poco::Net::HTTPResponse::HTTPStatus exceptionCodeToHTTPStatus(int excepti
196197
}
197198
else if (exception_code == ErrorCodes::UNKNOWN_USER ||
198199
exception_code == ErrorCodes::WRONG_PASSWORD ||
199-
exception_code == ErrorCodes::AUTHENTICATION_FAILED)
200+
exception_code == ErrorCodes::AUTHENTICATION_FAILED ||
201+
exception_code == ErrorCodes::ACCESS_DENIED)
200202
{
201203
return HTTPResponse::HTTP_FORBIDDEN;
202204
}
@@ -732,14 +734,24 @@ void HTTPHandler::processQuery(
732734
return false;
733735
};
734736

735-
if (params.has("role"))
737+
auto role_params_it = params.find("role");
738+
if (role_params_it != params.end())
736739
{
737-
auto role_name = params.get("role");
738-
auto role_id = context->getAccessControl().getID<Role>(role_name);
739-
if (context->getUser()->granted_roles.isGranted(role_id))
740-
context->setCurrentRoles(std::vector{role_id});
741-
else
742-
throw Exception(ErrorCodes::UNKNOWN_ROLE, "Role {} does not exist or not granted to the current user", role_name);
740+
std::vector<UUID> roles_ids;
741+
const auto & access_control = context->getAccessControl();
742+
const auto & user = context->getUser();
743+
for (; role_params_it != params.end(); role_params_it++)
744+
{
745+
if (role_params_it->first == "role")
746+
{
747+
auto role_id = access_control.getID<Role>(role_params_it->second);
748+
if (user->granted_roles.isGranted(role_id))
749+
roles_ids.push_back(role_id);
750+
else
751+
throw Exception(ErrorCodes::ACCESS_DENIED, "Role {} is not granted to the current user", role_params_it->second);
752+
}
753+
}
754+
context->setCurrentRoles(roles_ids);
743755
}
744756

745757
/// Settings can be overridden in the query.
Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,39 @@
1-
### Can query a table accessible by default without a role parameter
2-
42
3-
### Can query a table with granted access with a role parameter
4-
144
5-
### Can query a table when the role has special characters in the name
6-
144
7-
### Cannot query a table that requires a grant without a role parameter
1+
### Shows the default role when there are no role parameters
2+
03096_role_query_param_role_enabled_by_default
3+
### Shows a single role from the query parameters
4+
03096_role_query_param_role1
5+
### Shows multiple roles from the query parameters
6+
03096_role_query_param_role1
7+
03096_role_query_param_role2
8+
### Sets the default role alongside with another granted one
9+
03096_role_query_param_role1
10+
03096_role_query_param_role_enabled_by_default
11+
### Sets a role with special characters in the name
12+
03096_role_query_param_@!\\$
13+
### Sets a role with special characters in the name with another granted role
14+
03096_role_query_param_@!\\$
15+
03096_role_query_param_role1
16+
### Sets a role once when it's present in the query parameters multiple times
17+
03096_role_query_param_role1
18+
### Sets a role when there are other parameters in the query (before the role parameter)
19+
03096_role_query_param_role1
20+
max_result_rows 42
21+
### Sets a role when there are other parameters in the query (after the role parameter)
22+
03096_role_query_param_role1
23+
max_result_rows 42
24+
### Sets multiple roles when there are other parameters in the query
25+
03096_role_query_param_role1
26+
03096_role_query_param_role2
27+
max_result_rows 42
28+
### Cannot set a role that is not granted to the user (single parameter)
829
Code: 497
930
ACCESS_DENIED
10-
### Cannot query a table with a role that does not have a grant
31+
### Cannot set a role that is not granted to the user (multiple parameters)
1132
Code: 497
1233
ACCESS_DENIED
13-
### Cannot set a role that is not granted to the user
34+
### Cannot set a role that does not exist (single parameter)
1435
Code: 511
1536
UNKNOWN_ROLE
16-
### Cannot set a role that does not exist
37+
### Cannot set a role that does not exist (multiple parameters)
1738
Code: 511
1839
UNKNOWN_ROLE

tests/queries/0_stateless/03096_http_interface_role_query_param.sh

Lines changed: 82 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -7,81 +7,96 @@ CUR_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
77
TEST_USER="03096_role_query_param_user"
88
TEST_USER_AUTH="$TEST_USER:"
99

10-
TEST_ROLE="03096_role_query_param_role"
10+
TEST_ROLE1="03096_role_query_param_role1"
11+
TEST_ROLE2="03096_role_query_param_role2"
1112
TEST_ROLE_ENABLED_BY_DEFAULT="03096_role_query_param_role_enabled_by_default"
1213
TEST_ROLE_NOT_GRANTED="03096_role_query_param_role_not_granted"
1314
TEST_ROLE_SPECIAL_CHARS="\`03096_role_query_param_@!\\$\`" # = CREATE ROLE `03096_role_query_param_@!\$`
1415
TEST_ROLE_SPECIAL_CHARS_URLENCODED="03096_role_query_param_%40!%5C%24"
1516

16-
TEST_DB="03096_role_query_param_db"
17-
TEST_TABLE="03096_role_query_param_table"
18-
TEST_TABLE_ENABLED_BY_DEFAULT="03096_role_query_param_table_enabled_by_default"
19-
20-
TEST_TABLE_QUERY="SELECT * FROM $TEST_DB.$TEST_TABLE"
21-
TEST_TABLE_ENABLED_BY_DEFAULT_QUERY="SELECT * FROM $TEST_DB.$TEST_TABLE_ENABLED_BY_DEFAULT"
22-
23-
$CLICKHOUSE_CLIENT -q "DROP USER IF EXISTS $TEST_USER"
24-
$CLICKHOUSE_CLIENT -q "DROP ROLE IF EXISTS $TEST_ROLE"
25-
$CLICKHOUSE_CLIENT -q "DROP ROLE IF EXISTS $TEST_ROLE_ENABLED_BY_DEFAULT"
26-
$CLICKHOUSE_CLIENT -q "DROP ROLE IF EXISTS $TEST_ROLE_NOT_GRANTED"
27-
$CLICKHOUSE_CLIENT -q "DROP ROLE IF EXISTS $TEST_ROLE_SPECIAL_CHARS"
28-
$CLICKHOUSE_CLIENT -q "DROP DATABASE IF EXISTS $TEST_DB"
29-
30-
$CLICKHOUSE_CLIENT -q "CREATE DATABASE $TEST_DB"
31-
$CLICKHOUSE_CLIENT -q "CREATE TABLE $TEST_DB.$TEST_TABLE_ENABLED_BY_DEFAULT (i Int32) ENGINE = Memory"
32-
$CLICKHOUSE_CLIENT -q "INSERT INTO $TEST_DB.$TEST_TABLE_ENABLED_BY_DEFAULT VALUES (42)"
33-
$CLICKHOUSE_CLIENT -q "CREATE TABLE $TEST_DB.$TEST_TABLE (i Int32) ENGINE = Memory"
34-
$CLICKHOUSE_CLIENT -q "INSERT INTO $TEST_DB.$TEST_TABLE VALUES (144)"
35-
36-
$CLICKHOUSE_CLIENT -q "CREATE USER $TEST_USER NOT IDENTIFIED"
37-
38-
$CLICKHOUSE_CLIENT -q "CREATE ROLE $TEST_ROLE_ENABLED_BY_DEFAULT"
39-
$CLICKHOUSE_CLIENT -q "GRANT SELECT ON $TEST_DB.$TEST_TABLE_ENABLED_BY_DEFAULT TO $TEST_ROLE_ENABLED_BY_DEFAULT"
40-
$CLICKHOUSE_CLIENT -q "GRANT $TEST_ROLE_ENABLED_BY_DEFAULT TO $TEST_USER"
41-
$CLICKHOUSE_CLIENT -q "SET DEFAULT ROLE $TEST_ROLE_ENABLED_BY_DEFAULT TO $TEST_USER"
42-
43-
$CLICKHOUSE_CLIENT -q "CREATE ROLE $TEST_ROLE"
44-
$CLICKHOUSE_CLIENT -q "GRANT SELECT ON $TEST_DB.$TEST_TABLE TO $TEST_ROLE"
45-
$CLICKHOUSE_CLIENT -q "GRANT $TEST_ROLE TO $TEST_USER"
46-
47-
$CLICKHOUSE_CLIENT -q "CREATE ROLE $TEST_ROLE_SPECIAL_CHARS"
48-
$CLICKHOUSE_CLIENT -q "GRANT SELECT ON $TEST_DB.$TEST_TABLE TO $TEST_ROLE_SPECIAL_CHARS"
49-
$CLICKHOUSE_CLIENT -q "GRANT $TEST_ROLE_SPECIAL_CHARS TO $TEST_USER"
50-
51-
$CLICKHOUSE_CLIENT -q "CREATE ROLE $TEST_ROLE_NOT_GRANTED"
52-
53-
echo "### Can query a table accessible by default without a role parameter"
54-
$CLICKHOUSE_CURL -u $TEST_USER_AUTH -sS "$CLICKHOUSE_URL" --data-binary "$TEST_TABLE_ENABLED_BY_DEFAULT_QUERY"
55-
56-
echo "### Can query a table with granted access with a role parameter"
57-
$CLICKHOUSE_CURL -u $TEST_USER_AUTH -sS "$CLICKHOUSE_URL&role=$TEST_ROLE" --data-binary "$TEST_TABLE_QUERY"
58-
59-
echo "### Can query a table when the role has special characters in the name"
60-
$CLICKHOUSE_CURL -u $TEST_USER_AUTH -sS "$CLICKHOUSE_URL&role=$TEST_ROLE_SPECIAL_CHARS_URLENCODED" --data-binary "$TEST_TABLE_QUERY"
61-
62-
echo "### Cannot query a table that requires a grant without a role parameter"
63-
OUT=$($CLICKHOUSE_CURL -u $TEST_USER_AUTH -sS "$CLICKHOUSE_URL" --data-binary "$TEST_TABLE_QUERY")
17+
CHANGED_SETTING_NAME="max_result_rows"
18+
CHANGED_SETTING_VALUE="42"
19+
20+
SHOW_CURRENT_ROLES_QUERY="SELECT role_name FROM system.current_roles ORDER BY role_name ASC"
21+
SHOW_CHANGED_SETTINGS_QUERY="SELECT name, value FROM system.settings WHERE changed = 1 AND name = '$CHANGED_SETTING_NAME' ORDER BY name ASC"
22+
23+
$CLICKHOUSE_CLIENT -n --query "
24+
DROP USER IF EXISTS $TEST_USER;
25+
DROP ROLE IF EXISTS $TEST_ROLE1;
26+
DROP ROLE IF EXISTS $TEST_ROLE2;
27+
DROP ROLE IF EXISTS $TEST_ROLE_ENABLED_BY_DEFAULT;
28+
DROP ROLE IF EXISTS $TEST_ROLE_NOT_GRANTED;
29+
DROP ROLE IF EXISTS $TEST_ROLE_SPECIAL_CHARS;
30+
CREATE USER $TEST_USER NOT IDENTIFIED;
31+
CREATE ROLE $TEST_ROLE_ENABLED_BY_DEFAULT;
32+
GRANT $TEST_ROLE_ENABLED_BY_DEFAULT TO $TEST_USER;
33+
SET DEFAULT ROLE $TEST_ROLE_ENABLED_BY_DEFAULT TO $TEST_USER;
34+
CREATE ROLE $TEST_ROLE1;
35+
GRANT $TEST_ROLE1 TO $TEST_USER;
36+
CREATE ROLE $TEST_ROLE2;
37+
GRANT $TEST_ROLE2 TO $TEST_USER;
38+
CREATE ROLE $TEST_ROLE_SPECIAL_CHARS;
39+
GRANT $TEST_ROLE_SPECIAL_CHARS TO $TEST_USER;
40+
CREATE ROLE $TEST_ROLE_NOT_GRANTED;
41+
"
42+
43+
echo "### Shows the default role when there are no role parameters"
44+
$CLICKHOUSE_CURL -u $TEST_USER_AUTH -sS "$CLICKHOUSE_URL" --data-binary "$SHOW_CURRENT_ROLES_QUERY"
45+
46+
echo "### Shows a single role from the query parameters"
47+
$CLICKHOUSE_CURL -u $TEST_USER_AUTH -sS "$CLICKHOUSE_URL&role=$TEST_ROLE1" --data-binary "$SHOW_CURRENT_ROLES_QUERY"
48+
49+
echo "### Shows multiple roles from the query parameters"
50+
$CLICKHOUSE_CURL -u $TEST_USER_AUTH -sS "$CLICKHOUSE_URL&role=$TEST_ROLE1&role=$TEST_ROLE2" --data-binary "$SHOW_CURRENT_ROLES_QUERY"
51+
52+
echo "### Sets the default role alongside with another granted one"
53+
$CLICKHOUSE_CURL -u $TEST_USER_AUTH -sS "$CLICKHOUSE_URL&role=$TEST_ROLE_ENABLED_BY_DEFAULT&role=$TEST_ROLE1" --data-binary "$SHOW_CURRENT_ROLES_QUERY"
54+
55+
echo "### Sets a role with special characters in the name"
56+
$CLICKHOUSE_CURL -u $TEST_USER_AUTH -sS "$CLICKHOUSE_URL&role=$TEST_ROLE_SPECIAL_CHARS_URLENCODED" --data-binary "$SHOW_CURRENT_ROLES_QUERY"
57+
58+
echo "### Sets a role with special characters in the name with another granted role"
59+
$CLICKHOUSE_CURL -u $TEST_USER_AUTH -sS "$CLICKHOUSE_URL&role=$TEST_ROLE_SPECIAL_CHARS_URLENCODED&role=$TEST_ROLE1" --data-binary "$SHOW_CURRENT_ROLES_QUERY"
60+
61+
echo "### Sets a role once when it's present in the query parameters multiple times"
62+
$CLICKHOUSE_CURL -u $TEST_USER_AUTH -sS "$CLICKHOUSE_URL&role=$TEST_ROLE1&role=$TEST_ROLE1" --data-binary "$SHOW_CURRENT_ROLES_QUERY"
63+
64+
echo "### Sets a role when there are other parameters in the query (before the role parameter)"
65+
$CLICKHOUSE_CURL -u $TEST_USER_AUTH -sS "$CLICKHOUSE_URL&$CHANGED_SETTING_NAME=$CHANGED_SETTING_VALUE&role=$TEST_ROLE1" --data-binary "$SHOW_CURRENT_ROLES_QUERY"
66+
$CLICKHOUSE_CURL -u $TEST_USER_AUTH -sS "$CLICKHOUSE_URL&$CHANGED_SETTING_NAME=$CHANGED_SETTING_VALUE&role=$TEST_ROLE1" --data-binary "$SHOW_CHANGED_SETTINGS_QUERY"
67+
68+
echo "### Sets a role when there are other parameters in the query (after the role parameter)"
69+
$CLICKHOUSE_CURL -u $TEST_USER_AUTH -sS "$CLICKHOUSE_URL&role=$TEST_ROLE1&$CHANGED_SETTING_NAME=$CHANGED_SETTING_VALUE" --data-binary "$SHOW_CURRENT_ROLES_QUERY"
70+
$CLICKHOUSE_CURL -u $TEST_USER_AUTH -sS "$CLICKHOUSE_URL&role=$TEST_ROLE1&$CHANGED_SETTING_NAME=$CHANGED_SETTING_VALUE" --data-binary "$SHOW_CHANGED_SETTINGS_QUERY"
71+
72+
echo "### Sets multiple roles when there are other parameters in the query"
73+
$CLICKHOUSE_CURL -u $TEST_USER_AUTH -sS "$CLICKHOUSE_URL&role=$TEST_ROLE1&$CHANGED_SETTING_NAME=$CHANGED_SETTING_VALUE&role=$TEST_ROLE2" --data-binary "$SHOW_CURRENT_ROLES_QUERY"
74+
$CLICKHOUSE_CURL -u $TEST_USER_AUTH -sS "$CLICKHOUSE_URL&role=$TEST_ROLE1&$CHANGED_SETTING_NAME=$CHANGED_SETTING_VALUE&role=$TEST_ROLE2" --data-binary "$SHOW_CHANGED_SETTINGS_QUERY"
75+
76+
echo "### Cannot set a role that is not granted to the user (single parameter)"
77+
OUT=$($CLICKHOUSE_CURL -u $TEST_USER_AUTH -sS "$CLICKHOUSE_URL&role=$TEST_ROLE_NOT_GRANTED" --data-binary "$SHOW_CURRENT_ROLES_QUERY")
6478
echo -ne $OUT | grep -o "Code: 497" || echo "expected code 497, got: $OUT"
6579
echo -ne $OUT | grep -o "ACCESS_DENIED" || echo "expected ACCESS_DENIED error, got: $OUT"
6680

67-
echo "### Cannot query a table with a role that does not have a grant"
68-
OUT=$($CLICKHOUSE_CURL -u $TEST_USER_AUTH -sS "$CLICKHOUSE_URL&role=$TEST_ROLE" --data-binary "$TEST_TABLE_ENABLED_BY_DEFAULT_QUERY")
81+
echo "### Cannot set a role that is not granted to the user (multiple parameters)"
82+
OUT=$($CLICKHOUSE_CURL -u $TEST_USER_AUTH -sS "$CLICKHOUSE_URL&role=$TEST_ROLE1&role=$TEST_ROLE_NOT_GRANTED" --data-binary "$SHOW_CURRENT_ROLES_QUERY")
6983
echo -ne $OUT | grep -o "Code: 497" || echo "expected code 497, got: $OUT"
7084
echo -ne $OUT | grep -o "ACCESS_DENIED" || echo "expected ACCESS_DENIED error, got: $OUT"
7185

72-
echo "### Cannot set a role that is not granted to the user"
73-
OUT=$($CLICKHOUSE_CURL -u $TEST_USER_AUTH -sS "$CLICKHOUSE_URL&role=$TEST_ROLE_NOT_GRANTED" --data-binary "$TEST_TABLE_QUERY")
74-
echo -ne $OUT | grep -o "Code: 511" || echo "expected code 511, got: $OUT"
75-
echo -ne $OUT | grep -o "UNKNOWN_ROLE" || echo "expected UNKNOWN_ROLE error, got: $OUT"
76-
77-
echo "### Cannot set a role that does not exist"
78-
OUT=$($CLICKHOUSE_CURL -u $TEST_USER_AUTH -sS "$CLICKHOUSE_URL&role=aaaaaaaaaa" --data-binary "$TEST_TABLE_QUERY")
79-
echo -ne $OUT | grep -o "Code: 511" || echo "expected code 511, got: $OUT"
80-
echo -ne $OUT | grep -o "UNKNOWN_ROLE" || echo "expected UNKNOWN_ROLE error, got: $OUT"
81-
82-
$CLICKHOUSE_CLIENT -q "DROP USER $TEST_USER"
83-
$CLICKHOUSE_CLIENT -q "DROP ROLE $TEST_ROLE"
84-
$CLICKHOUSE_CLIENT -q "DROP ROLE $TEST_ROLE_ENABLED_BY_DEFAULT"
85-
$CLICKHOUSE_CLIENT -q "DROP ROLE $TEST_ROLE_NOT_GRANTED"
86-
$CLICKHOUSE_CLIENT -q "DROP ROLE $TEST_ROLE_SPECIAL_CHARS"
87-
$CLICKHOUSE_CLIENT -q "DROP DATABASE $TEST_DB"
86+
echo "### Cannot set a role that does not exist (single parameter)"
87+
OUT=$($CLICKHOUSE_CURL -u $TEST_USER_AUTH -sS "$CLICKHOUSE_URL&role=aaaaaaaaaaa" --data-binary "$SHOW_CURRENT_ROLES_QUERY")
88+
echo -ne $OUT | grep -o "Code: 511" || echo "expected code 511, got: $OUT"
89+
echo -ne $OUT | grep -o "UNKNOWN_ROLE" || echo "expected UNKNOWN_ROLE error, got: $OUT"
90+
91+
echo "### Cannot set a role that does not exist (multiple parameters)"
92+
OUT=$($CLICKHOUSE_CURL -u $TEST_USER_AUTH -sS "$CLICKHOUSE_URL&role=$TEST_ROLE1&role=aaaaaaaaaaa" --data-binary "$SHOW_CURRENT_ROLES_QUERY")
93+
echo -ne $OUT | grep -o "Code: 511" || echo "expected code 511, got: $OUT"
94+
echo -ne $OUT | grep -o "UNKNOWN_ROLE" || echo "expected UNKNOWN_ROLE error, got: $OUT"
95+
96+
$CLICKHOUSE_CLIENT -n --query "
97+
DROP USER $TEST_USER;
98+
DROP ROLE $TEST_ROLE1;
99+
DROP ROLE $TEST_ROLE_ENABLED_BY_DEFAULT;
100+
DROP ROLE $TEST_ROLE_NOT_GRANTED;
101+
DROP ROLE $TEST_ROLE_SPECIAL_CHARS;
102+
"

0 commit comments

Comments
 (0)