Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
2dot5
ClickHouse
提交
37ce6e26
C
ClickHouse
项目概览
2dot5
/
ClickHouse
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
C
ClickHouse
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
37ce6e26
编写于
3月 11, 2021
作者:
V
Vitaly Baranov
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add a new clause GRANTEES to commands CREATE USER and ALTER USER.
上级
d6e0342c
变更
15
隐藏空白更改
内联
并排
Showing
15 changed file
with
205 addition
and
21 deletion
+205
-21
src/Access/User.cpp
src/Access/User.cpp
+1
-1
src/Access/User.h
src/Access/User.h
+1
-0
src/Interpreters/InterpreterCreateUserQuery.cpp
src/Interpreters/InterpreterCreateUserQuery.cpp
+30
-7
src/Interpreters/InterpreterGrantQuery.cpp
src/Interpreters/InterpreterGrantQuery.cpp
+45
-0
src/Interpreters/InterpreterShowCreateAccessEntityQuery.cpp
src/Interpreters/InterpreterShowCreateAccessEntityQuery.cpp
+9
-0
src/Parsers/ASTCreateUserQuery.cpp
src/Parsers/ASTCreateUserQuery.cpp
+10
-0
src/Parsers/ASTCreateUserQuery.h
src/Parsers/ASTCreateUserQuery.h
+3
-0
src/Parsers/ASTRolesOrUsersSet.cpp
src/Parsers/ASTRolesOrUsersSet.cpp
+2
-1
src/Parsers/ASTRolesOrUsersSet.h
src/Parsers/ASTRolesOrUsersSet.h
+4
-3
src/Parsers/ParserCreateUserQuery.cpp
src/Parsers/ParserCreateUserQuery.cpp
+23
-0
src/Parsers/ParserCreateUserQuery.h
src/Parsers/ParserCreateUserQuery.h
+2
-0
src/Parsers/ParserRolesOrUsersSet.cpp
src/Parsers/ParserRolesOrUsersSet.cpp
+10
-2
src/Parsers/ParserRolesOrUsersSet.h
src/Parsers/ParserRolesOrUsersSet.h
+2
-0
src/Storages/System/StorageSystemUsers.cpp
src/Storages/System/StorageSystemUsers.cpp
+22
-6
tests/integration/test_grant_and_revoke/test.py
tests/integration/test_grant_and_revoke/test.py
+41
-1
未找到文件。
src/Access/User.cpp
浏览文件 @
37ce6e26
...
...
@@ -11,7 +11,7 @@ bool User::equal(const IAccessEntity & other) const
const
auto
&
other_user
=
typeid_cast
<
const
User
&>
(
other
);
return
(
authentication
==
other_user
.
authentication
)
&&
(
allowed_client_hosts
==
other_user
.
allowed_client_hosts
)
&&
(
access
==
other_user
.
access
)
&&
(
granted_roles
==
other_user
.
granted_roles
)
&&
(
default_roles
==
other_user
.
default_roles
)
&&
(
settings
==
other_user
.
settings
);
&&
(
settings
==
other_user
.
settings
)
&&
(
grantees
==
other_user
.
grantees
)
;
}
}
src/Access/User.h
浏览文件 @
37ce6e26
...
...
@@ -21,6 +21,7 @@ struct User : public IAccessEntity
GrantedRoles
granted_roles
;
RolesOrUsersSet
default_roles
=
RolesOrUsersSet
::
AllTag
{};
SettingsProfileElements
settings
;
RolesOrUsersSet
grantees
=
RolesOrUsersSet
::
AllTag
{};
bool
equal
(
const
IAccessEntity
&
other
)
const
override
;
std
::
shared_ptr
<
IAccessEntity
>
clone
()
const
override
{
return
cloneImpl
<
User
>
();
}
...
...
src/Interpreters/InterpreterCreateUserQuery.cpp
浏览文件 @
37ce6e26
...
...
@@ -20,7 +20,8 @@ namespace
const
ASTCreateUserQuery
&
query
,
const
std
::
shared_ptr
<
ASTUserNameWithHost
>
&
override_name
,
const
std
::
optional
<
RolesOrUsersSet
>
&
override_default_roles
,
const
std
::
optional
<
SettingsProfileElements
>
&
override_settings
)
const
std
::
optional
<
SettingsProfileElements
>
&
override_settings
,
const
std
::
optional
<
RolesOrUsersSet
>
&
override_grantees
)
{
if
(
override_name
)
user
.
setName
(
override_name
->
toString
());
...
...
@@ -62,6 +63,11 @@ namespace
user
.
settings
=
*
override_settings
;
else
if
(
query
.
settings
)
user
.
settings
=
*
query
.
settings
;
if
(
override_grantees
)
user
.
grantees
=
*
override_grantees
;
else
if
(
query
.
grantees
)
user
.
grantees
=
*
query
.
grantees
;
}
}
...
...
@@ -93,12 +99,17 @@ BlockIO InterpreterCreateUserQuery::execute()
if
(
query
.
alter
)
{
std
::
optional
<
RolesOrUsersSet
>
grantees_from_query
;
if
(
query
.
grantees
)
grantees_from_query
=
RolesOrUsersSet
{
*
query
.
grantees
,
access_control
};
auto
update_func
=
[
&
](
const
AccessEntityPtr
&
entity
)
->
AccessEntityPtr
{
auto
updated_user
=
typeid_cast
<
std
::
shared_ptr
<
User
>>
(
entity
->
clone
());
updateUserFromQueryImpl
(
*
updated_user
,
query
,
{},
default_roles_from_query
,
settings_from_query
);
updateUserFromQueryImpl
(
*
updated_user
,
query
,
{},
default_roles_from_query
,
settings_from_query
,
grantees_from_query
);
return
updated_user
;
};
Strings
names
=
query
.
names
->
toStrings
();
if
(
query
.
if_exists
)
{
...
...
@@ -114,16 +125,28 @@ BlockIO InterpreterCreateUserQuery::execute()
for
(
const
auto
&
name
:
*
query
.
names
)
{
auto
new_user
=
std
::
make_shared
<
User
>
();
updateUserFromQueryImpl
(
*
new_user
,
query
,
name
,
default_roles_from_query
,
settings_from_query
);
updateUserFromQueryImpl
(
*
new_user
,
query
,
name
,
default_roles_from_query
,
settings_from_query
,
RolesOrUsersSet
::
AllTag
{}
);
new_users
.
emplace_back
(
std
::
move
(
new_user
));
}
std
::
vector
<
UUID
>
ids
;
if
(
query
.
if_not_exists
)
access_control
.
tryInsert
(
new_users
);
ids
=
access_control
.
tryInsert
(
new_users
);
else
if
(
query
.
or_replace
)
access_control
.
insertOrReplace
(
new_users
);
ids
=
access_control
.
insertOrReplace
(
new_users
);
else
access_control
.
insert
(
new_users
);
ids
=
access_control
.
insert
(
new_users
);
if
(
query
.
grantees
)
{
RolesOrUsersSet
grantees_from_query
=
RolesOrUsersSet
{
*
query
.
grantees
,
access_control
};
access_control
.
update
(
ids
,
[
&
](
const
AccessEntityPtr
&
entity
)
->
AccessEntityPtr
{
auto
updated_user
=
typeid_cast
<
std
::
shared_ptr
<
User
>>
(
entity
->
clone
());
updated_user
->
grantees
=
grantees_from_query
;
return
updated_user
;
});
}
}
return
{};
...
...
@@ -132,7 +155,7 @@ BlockIO InterpreterCreateUserQuery::execute()
void
InterpreterCreateUserQuery
::
updateUserFromQuery
(
User
&
user
,
const
ASTCreateUserQuery
&
query
)
{
updateUserFromQueryImpl
(
user
,
query
,
{},
{},
{});
updateUserFromQueryImpl
(
user
,
query
,
{},
{},
{}
,
{}
);
}
}
src/Interpreters/InterpreterGrantQuery.cpp
浏览文件 @
37ce6e26
...
...
@@ -16,6 +16,7 @@ namespace DB
{
namespace
ErrorCodes
{
extern
const
int
ACCESS_DENIED
;
extern
const
int
LOGICAL_ERROR
;
}
...
...
@@ -65,6 +66,29 @@ namespace
updateFromQueryTemplate
(
*
role
,
query
,
roles_to_grant_or_revoke
);
}
void
checkGranteeIsAllowed
(
const
ContextAccess
&
access
,
const
UUID
&
grantee_id
,
const
IAccessEntity
&
grantee
)
{
auto
current_user
=
access
.
getUser
();
if
(
current_user
&&
!
current_user
->
grantees
.
match
(
grantee_id
))
throw
Exception
(
grantee
.
outputTypeAndName
()
+
" is not allowed as grantee"
,
ErrorCodes
::
ACCESS_DENIED
);
}
void
checkGranteesAreAllowed
(
const
AccessControlManager
&
access_control
,
const
ContextAccess
&
access
,
const
std
::
vector
<
UUID
>
&
grantee_ids
)
{
auto
current_user
=
access
.
getUser
();
if
(
!
current_user
||
(
current_user
->
grantees
==
RolesOrUsersSet
::
AllTag
{}))
return
;
for
(
const
auto
&
id
:
grantee_ids
)
{
auto
entity
=
access_control
.
tryRead
(
id
);
if
(
auto
role
=
typeid_cast
<
RolePtr
>
(
entity
))
checkGranteeIsAllowed
(
access
,
id
,
*
role
);
else
if
(
auto
user
=
typeid_cast
<
UserPtr
>
(
entity
))
checkGranteeIsAllowed
(
access
,
id
,
*
user
);
}
}
void
checkGrantOption
(
const
AccessControlManager
&
access_control
,
const
ContextAccess
&
access
,
...
...
@@ -80,11 +104,15 @@ namespace
if
(
!
query
.
is_revoke
)
{
access
.
checkGrantOption
(
elements
);
checkGranteesAreAllowed
(
access_control
,
access
,
grantees_from_query
);
return
;
}
if
(
access
.
hasGrantOption
(
elements
))
{
checkGranteesAreAllowed
(
access_control
,
access
,
grantees_from_query
);
return
;
}
/// Special case for the command REVOKE: it's possible that the current user doesn't have
/// the access granted with GRANT OPTION but it's still ok because the roles or users
...
...
@@ -99,9 +127,15 @@ namespace
{
auto
entity
=
access_control
.
tryRead
(
id
);
if
(
auto
role
=
typeid_cast
<
RolePtr
>
(
entity
))
{
checkGranteeIsAllowed
(
access
,
id
,
*
role
);
all_granted_access
.
makeUnion
(
role
->
access
);
}
else
if
(
auto
user
=
typeid_cast
<
UserPtr
>
(
entity
))
{
checkGranteeIsAllowed
(
access
,
id
,
*
user
);
all_granted_access
.
makeUnion
(
user
->
access
);
}
}
AccessRights
required_access
;
...
...
@@ -138,6 +172,7 @@ namespace
{
matching_ids
=
roles_from_query
.
getMatchingIDs
(
access_control
);
access
.
checkAdminOption
(
matching_ids
);
checkGranteesAreAllowed
(
access_control
,
access
,
grantees_from_query
);
return
matching_ids
;
}
...
...
@@ -145,7 +180,10 @@ namespace
{
matching_ids
=
roles_from_query
.
getMatchingIDs
();
if
(
access
.
hasAdminOption
(
matching_ids
))
{
checkGranteesAreAllowed
(
access_control
,
access
,
grantees_from_query
);
return
matching_ids
;
}
}
/// Special case for the command REVOKE: it's possible that the current user doesn't have the admin option
...
...
@@ -161,9 +199,15 @@ namespace
{
auto
entity
=
access_control
.
tryRead
(
id
);
if
(
auto
role
=
typeid_cast
<
RolePtr
>
(
entity
))
{
checkGranteeIsAllowed
(
access
,
id
,
*
role
);
all_granted_roles
.
makeUnion
(
role
->
granted_roles
);
}
else
if
(
auto
user
=
typeid_cast
<
UserPtr
>
(
entity
))
{
checkGranteeIsAllowed
(
access
,
id
,
*
user
);
all_granted_roles
.
makeUnion
(
user
->
granted_roles
);
}
}
const
auto
&
all_granted_roles_set
=
query
.
admin_option
?
all_granted_roles
.
getGrantedWithAdminOption
()
:
all_granted_roles
.
getGranted
();
...
...
@@ -206,6 +250,7 @@ BlockIO InterpreterGrantQuery::execute()
/// To execute the command GRANT the current user needs to have the access granted with GRANT OPTION.
auto
required_access
=
query
.
access_rights_elements
;
std
::
for_each
(
required_access
.
begin
(),
required_access
.
end
(),
[
&
](
AccessRightsElement
&
element
)
{
element
.
grant_option
=
true
;
});
checkGranteesAreAllowed
(
access_control
,
*
context
.
getAccess
(),
grantees
);
return
executeDDLQueryOnCluster
(
query_ptr
,
context
,
std
::
move
(
required_access
));
}
...
...
src/Interpreters/InterpreterShowCreateAccessEntityQuery.cpp
浏览文件 @
37ce6e26
...
...
@@ -73,6 +73,15 @@ namespace
query
->
settings
=
user
.
settings
.
toASTWithNames
(
*
manager
);
}
if
(
user
.
grantees
!=
RolesOrUsersSet
::
AllTag
{})
{
if
(
attach_mode
)
query
->
grantees
=
user
.
grantees
.
toAST
();
else
query
->
grantees
=
user
.
grantees
.
toASTWithNames
(
*
manager
);
query
->
grantees
->
use_keyword_any
=
true
;
}
return
query
;
}
...
...
src/Parsers/ASTCreateUserQuery.cpp
浏览文件 @
37ce6e26
...
...
@@ -203,6 +203,13 @@ namespace
format
.
ostr
<<
(
format
.
hilite
?
IAST
::
hilite_keyword
:
""
)
<<
" SETTINGS "
<<
(
format
.
hilite
?
IAST
::
hilite_none
:
""
);
settings
.
format
(
format
);
}
void
formatGrantees
(
const
ASTRolesOrUsersSet
&
grantees
,
const
IAST
::
FormatSettings
&
settings
)
{
settings
.
ostr
<<
(
settings
.
hilite
?
IAST
::
hilite_keyword
:
""
)
<<
" GRANTEES "
<<
(
settings
.
hilite
?
IAST
::
hilite_none
:
""
);
grantees
.
format
(
settings
);
}
}
...
...
@@ -260,5 +267,8 @@ void ASTCreateUserQuery::formatImpl(const FormatSettings & format, FormatState &
if
(
settings
&&
(
!
settings
->
empty
()
||
alter
))
formatSettings
(
*
settings
,
format
);
if
(
grantees
)
formatGrantees
(
*
grantees
,
format
);
}
}
src/Parsers/ASTCreateUserQuery.h
浏览文件 @
37ce6e26
...
...
@@ -17,6 +17,7 @@ class ASTSettingsProfileElements;
* [HOST {LOCAL | NAME 'name' | REGEXP 'name_regexp' | IP 'address' | LIKE 'pattern'} [,...] | ANY | NONE]
* [DEFAULT ROLE role [,...]]
* [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | PROFILE 'profile_name'] [,...]
* [GRANTEES {user | role | ANY | NONE} [,...] [EXCEPT {user | role} [,...]]]
*
* ALTER USER [IF EXISTS] name
* [RENAME TO new_name]
...
...
@@ -24,6 +25,7 @@ class ASTSettingsProfileElements;
* [[ADD|DROP] HOST {LOCAL | NAME 'name' | REGEXP 'name_regexp' | IP 'address' | LIKE 'pattern'} [,...] | ANY | NONE]
* [DEFAULT ROLE role [,...] | ALL | ALL EXCEPT role [,...] ]
* [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | PROFILE 'profile_name'] [,...]
* [GRANTEES {user | role | ANY | NONE} [,...] [EXCEPT {user | role} [,...]]]
*/
class
ASTCreateUserQuery
:
public
IAST
,
public
ASTQueryWithOnCluster
{
...
...
@@ -47,6 +49,7 @@ public:
std
::
shared_ptr
<
ASTRolesOrUsersSet
>
default_roles
;
std
::
shared_ptr
<
ASTSettingsProfileElements
>
settings
;
std
::
shared_ptr
<
ASTRolesOrUsersSet
>
grantees
;
String
getID
(
char
)
const
override
;
ASTPtr
clone
()
const
override
;
...
...
src/Parsers/ASTRolesOrUsersSet.cpp
浏览文件 @
37ce6e26
...
...
@@ -35,7 +35,8 @@ void ASTRolesOrUsersSet::formatImpl(const FormatSettings & settings, FormatState
{
if
(
std
::
exchange
(
need_comma
,
true
))
settings
.
ostr
<<
", "
;
settings
.
ostr
<<
(
settings
.
hilite
?
IAST
::
hilite_keyword
:
""
)
<<
"ALL"
<<
(
settings
.
hilite
?
IAST
::
hilite_none
:
""
);
settings
.
ostr
<<
(
settings
.
hilite
?
IAST
::
hilite_keyword
:
""
)
<<
(
use_keyword_any
?
"ANY"
:
"ALL"
)
<<
(
settings
.
hilite
?
IAST
::
hilite_none
:
""
);
}
else
{
...
...
src/Parsers/ASTRolesOrUsersSet.h
浏览文件 @
37ce6e26
...
...
@@ -20,9 +20,10 @@ public:
Strings
except_names
;
bool
except_current_user
=
false
;
bool
allow_users
=
true
;
/// whether this set can contain names of users
bool
allow_roles
=
true
;
/// whether this set can contain names of roles
bool
id_mode
=
false
;
/// whether this set keep UUIDs instead of names
bool
allow_users
=
true
;
/// whether this set can contain names of users
bool
allow_roles
=
true
;
/// whether this set can contain names of roles
bool
id_mode
=
false
;
/// whether this set keep UUIDs instead of names
bool
use_keyword_any
=
false
;
/// whether the keyword ANY should be used instead of the keyword ALL
bool
empty
()
const
{
return
names
.
empty
()
&&
!
current_user
&&
!
all
;
}
void
replaceCurrentUserTag
(
const
String
&
current_user_name
);
...
...
src/Parsers/ParserCreateUserQuery.cpp
浏览文件 @
37ce6e26
...
...
@@ -275,6 +275,24 @@ namespace
});
}
bool
parseGrantees
(
IParserBase
::
Pos
&
pos
,
Expected
&
expected
,
bool
id_mode
,
std
::
shared_ptr
<
ASTRolesOrUsersSet
>
&
grantees
)
{
return
IParserBase
::
wrapParseImpl
(
pos
,
[
&
]
{
if
(
!
ParserKeyword
{
"GRANTEES"
}.
ignore
(
pos
,
expected
))
return
false
;
ASTPtr
ast
;
ParserRolesOrUsersSet
grantees_p
;
grantees_p
.
allowAny
().
allowUsers
().
allowCurrentUser
().
allowRoles
().
useIDMode
(
id_mode
);
if
(
!
grantees_p
.
parse
(
pos
,
ast
,
expected
))
return
false
;
grantees
=
typeid_cast
<
std
::
shared_ptr
<
ASTRolesOrUsersSet
>>
(
ast
);
return
true
;
});
}
bool
parseOnCluster
(
IParserBase
::
Pos
&
pos
,
Expected
&
expected
,
String
&
cluster
)
{
return
IParserBase
::
wrapParseImpl
(
pos
,
[
&
]
...
...
@@ -330,6 +348,7 @@ bool ParserCreateUserQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expec
std
::
optional
<
AllowedClientHosts
>
remove_hosts
;
std
::
shared_ptr
<
ASTRolesOrUsersSet
>
default_roles
;
std
::
shared_ptr
<
ASTSettingsProfileElements
>
settings
;
std
::
shared_ptr
<
ASTRolesOrUsersSet
>
grantees
;
String
cluster
;
while
(
true
)
...
...
@@ -368,6 +387,9 @@ bool ParserCreateUserQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expec
if
(
cluster
.
empty
()
&&
parseOnCluster
(
pos
,
expected
,
cluster
))
continue
;
if
(
!
grantees
&&
parseGrantees
(
pos
,
expected
,
attach_mode
,
grantees
))
continue
;
if
(
alter
)
{
if
(
new_name
.
empty
()
&&
(
names
->
size
()
==
1
)
&&
parseRenameTo
(
pos
,
expected
,
new_name
))
...
...
@@ -422,6 +444,7 @@ bool ParserCreateUserQuery::parseImpl(Pos & pos, ASTPtr & node, Expected & expec
query
->
remove_hosts
=
std
::
move
(
remove_hosts
);
query
->
default_roles
=
std
::
move
(
default_roles
);
query
->
settings
=
std
::
move
(
settings
);
query
->
grantees
=
std
::
move
(
grantees
);
return
true
;
}
...
...
src/Parsers/ParserCreateUserQuery.h
浏览文件 @
37ce6e26
...
...
@@ -11,6 +11,7 @@ namespace DB
* [HOST {LOCAL | NAME 'name' | REGEXP 'name_regexp' | IP 'address' | LIKE 'pattern'} [,...] | ANY | NONE]
* [DEFAULT ROLE role [,...]]
* [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | PROFILE 'profile_name'] [,...]
* [GRANTEES {user | role | ANY | NONE} [,...] [EXCEPT {user | role} [,...]]]
*
* ALTER USER [IF EXISTS] name
* [RENAME TO new_name]
...
...
@@ -18,6 +19,7 @@ namespace DB
* [[ADD|DROP] HOST {LOCAL | NAME 'name' | REGEXP 'name_regexp' | IP 'address' | LIKE 'pattern'} [,...] | ANY | NONE]
* [DEFAULT ROLE role [,...] | ALL | ALL EXCEPT role [,...] ]
* [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | PROFILE 'profile_name'] [,...]
* [GRANTEES {user | role | ANY | NONE} [,...] [EXCEPT {user | role} [,...]]]
*/
class
ParserCreateUserQuery
:
public
IParserBase
{
...
...
src/Parsers/ParserRolesOrUsersSet.cpp
浏览文件 @
37ce6e26
...
...
@@ -40,6 +40,7 @@ namespace
Expected
&
expected
,
bool
id_mode
,
bool
allow_all
,
bool
allow_any
,
bool
allow_current_user
,
bool
&
all
,
Strings
&
names
,
...
...
@@ -61,6 +62,12 @@ namespace
return
true
;
}
if
(
allow_any
&&
ParserKeyword
{
"ANY"
}.
ignore
(
pos
,
expected
))
{
res_all
=
true
;
return
true
;
}
if
(
allow_current_user
&&
parseCurrentUserTag
(
pos
,
expected
))
{
res_current_user
=
true
;
...
...
@@ -99,7 +106,7 @@ namespace
return
false
;
bool
unused
;
return
parseBeforeExcept
(
pos
,
expected
,
id_mode
,
false
,
allow_current_user
,
unused
,
except_names
,
except_current_user
);
return
parseBeforeExcept
(
pos
,
expected
,
id_mode
,
false
,
false
,
allow_current_user
,
unused
,
except_names
,
except_current_user
);
});
}
}
...
...
@@ -113,7 +120,7 @@ bool ParserRolesOrUsersSet::parseImpl(Pos & pos, ASTPtr & node, Expected & expec
Strings
except_names
;
bool
except_current_user
=
false
;
if
(
!
parseBeforeExcept
(
pos
,
expected
,
id_mode
,
allow_all
,
allow_current_user
,
all
,
names
,
current_user
))
if
(
!
parseBeforeExcept
(
pos
,
expected
,
id_mode
,
allow_all
,
allow_
any
,
allow_
current_user
,
all
,
names
,
current_user
))
return
false
;
parseExceptAndAfterExcept
(
pos
,
expected
,
id_mode
,
allow_current_user
,
except_names
,
except_current_user
);
...
...
@@ -130,6 +137,7 @@ bool ParserRolesOrUsersSet::parseImpl(Pos & pos, ASTPtr & node, Expected & expec
result
->
allow_users
=
allow_users
;
result
->
allow_roles
=
allow_roles
;
result
->
id_mode
=
id_mode
;
result
->
use_keyword_any
=
all
&&
allow_any
&&
!
allow_all
;
node
=
result
;
return
true
;
}
...
...
src/Parsers/ParserRolesOrUsersSet.h
浏览文件 @
37ce6e26
...
...
@@ -13,6 +13,7 @@ class ParserRolesOrUsersSet : public IParserBase
{
public:
ParserRolesOrUsersSet
&
allowAll
(
bool
allow_all_
=
true
)
{
allow_all
=
allow_all_
;
return
*
this
;
}
ParserRolesOrUsersSet
&
allowAny
(
bool
allow_any_
=
true
)
{
allow_any
=
allow_any_
;
return
*
this
;
}
ParserRolesOrUsersSet
&
allowUsers
(
bool
allow_users_
=
true
)
{
allow_users
=
allow_users_
;
return
*
this
;
}
ParserRolesOrUsersSet
&
allowCurrentUser
(
bool
allow_current_user_
=
true
)
{
allow_current_user
=
allow_current_user_
;
return
*
this
;
}
ParserRolesOrUsersSet
&
allowRoles
(
bool
allow_roles_
=
true
)
{
allow_roles
=
allow_roles_
;
return
*
this
;
}
...
...
@@ -24,6 +25,7 @@ protected:
private:
bool
allow_all
=
false
;
bool
allow_any
=
false
;
bool
allow_users
=
false
;
bool
allow_current_user
=
false
;
bool
allow_roles
=
false
;
...
...
src/Storages/System/StorageSystemUsers.cpp
浏览文件 @
37ce6e26
...
...
@@ -47,6 +47,9 @@ NamesAndTypesList StorageSystemUsers::getNamesAndTypes()
{
"default_roles_all"
,
std
::
make_shared
<
DataTypeUInt8
>
()},
{
"default_roles_list"
,
std
::
make_shared
<
DataTypeArray
>
(
std
::
make_shared
<
DataTypeString
>
())},
{
"default_roles_except"
,
std
::
make_shared
<
DataTypeArray
>
(
std
::
make_shared
<
DataTypeString
>
())},
{
"grantees_any"
,
std
::
make_shared
<
DataTypeUInt8
>
()},
{
"grantees_list"
,
std
::
make_shared
<
DataTypeArray
>
(
std
::
make_shared
<
DataTypeString
>
())},
{
"grantees_except"
,
std
::
make_shared
<
DataTypeArray
>
(
std
::
make_shared
<
DataTypeString
>
())},
};
return
names_and_types
;
}
...
...
@@ -77,13 +80,19 @@ void StorageSystemUsers::fillData(MutableColumns & res_columns, const Context &
auto
&
column_default_roles_list_offsets
=
assert_cast
<
ColumnArray
&>
(
*
res_columns
[
column_index
++
]).
getOffsets
();
auto
&
column_default_roles_except
=
assert_cast
<
ColumnString
&>
(
assert_cast
<
ColumnArray
&>
(
*
res_columns
[
column_index
]).
getData
());
auto
&
column_default_roles_except_offsets
=
assert_cast
<
ColumnArray
&>
(
*
res_columns
[
column_index
++
]).
getOffsets
();
auto
&
column_grantees_any
=
assert_cast
<
ColumnUInt8
&>
(
*
res_columns
[
column_index
++
]).
getData
();
auto
&
column_grantees_list
=
assert_cast
<
ColumnString
&>
(
assert_cast
<
ColumnArray
&>
(
*
res_columns
[
column_index
]).
getData
());
auto
&
column_grantees_list_offsets
=
assert_cast
<
ColumnArray
&>
(
*
res_columns
[
column_index
++
]).
getOffsets
();
auto
&
column_grantees_except
=
assert_cast
<
ColumnString
&>
(
assert_cast
<
ColumnArray
&>
(
*
res_columns
[
column_index
]).
getData
());
auto
&
column_grantees_except_offsets
=
assert_cast
<
ColumnArray
&>
(
*
res_columns
[
column_index
++
]).
getOffsets
();
auto
add_row
=
[
&
](
const
String
&
name
,
const
UUID
&
id
,
const
String
&
storage_name
,
const
Authentication
&
authentication
,
const
AllowedClientHosts
&
allowed_hosts
,
const
RolesOrUsersSet
&
default_roles
)
const
RolesOrUsersSet
&
default_roles
,
const
RolesOrUsersSet
&
grantees
)
{
column_name
.
insertData
(
name
.
data
(),
name
.
length
());
column_id
.
push_back
(
id
);
...
...
@@ -156,14 +165,21 @@ void StorageSystemUsers::fillData(MutableColumns & res_columns, const Context &
auto
default_roles_ast
=
default_roles
.
toASTWithNames
(
access_control
);
column_default_roles_all
.
push_back
(
default_roles_ast
->
all
);
for
(
const
auto
&
role_name
:
default_roles_ast
->
names
)
column_default_roles_list
.
insertData
(
role_name
.
data
(),
role_name
.
length
());
column_default_roles_list_offsets
.
push_back
(
column_default_roles_list
.
size
());
for
(
const
auto
&
role_name
:
default_roles_ast
->
except_names
)
column_default_roles_except
.
insertData
(
role_name
.
data
(),
role_name
.
length
());
for
(
const
auto
&
except_name
:
default_roles_ast
->
except_names
)
column_default_roles_except
.
insertData
(
except_name
.
data
(),
except_name
.
length
());
column_default_roles_except_offsets
.
push_back
(
column_default_roles_except
.
size
());
auto
grantees_ast
=
grantees
.
toASTWithNames
(
access_control
);
column_grantees_any
.
push_back
(
grantees_ast
->
all
);
for
(
const
auto
&
grantee_name
:
grantees_ast
->
names
)
column_grantees_list
.
insertData
(
grantee_name
.
data
(),
grantee_name
.
length
());
column_grantees_list_offsets
.
push_back
(
column_grantees_list
.
size
());
for
(
const
auto
&
except_name
:
grantees_ast
->
except_names
)
column_grantees_except
.
insertData
(
except_name
.
data
(),
except_name
.
length
());
column_grantees_except_offsets
.
push_back
(
column_grantees_except
.
size
());
};
for
(
const
auto
&
id
:
ids
)
...
...
@@ -176,7 +192,7 @@ void StorageSystemUsers::fillData(MutableColumns & res_columns, const Context &
if
(
!
storage
)
continue
;
add_row
(
user
->
getName
(),
id
,
storage
->
getStorageName
(),
user
->
authentication
,
user
->
allowed_client_hosts
,
user
->
default_roles
);
add_row
(
user
->
getName
(),
id
,
storage
->
getStorageName
(),
user
->
authentication
,
user
->
allowed_client_hosts
,
user
->
default_roles
,
user
->
grantees
);
}
}
...
...
tests/integration/test_grant_and_revoke/test.py
浏览文件 @
37ce6e26
...
...
@@ -26,7 +26,7 @@ def cleanup_after_test():
try
:
yield
finally
:
instance
.
query
(
"DROP USER IF EXISTS A, B"
)
instance
.
query
(
"DROP USER IF EXISTS A, B
, C
"
)
instance
.
query
(
"DROP TABLE IF EXISTS test.view_1"
)
...
...
@@ -106,6 +106,46 @@ def test_revoke_requires_grant_option():
assert
instance
.
query
(
"SHOW GRANTS FOR B"
)
==
""
def
test_allowed_grantees
():
instance
.
query
(
"CREATE USER A"
)
instance
.
query
(
"CREATE USER B"
)
instance
.
query
(
'GRANT SELECT ON test.table TO A WITH GRANT OPTION'
)
instance
.
query
(
"GRANT SELECT ON test.table TO B"
,
user
=
'A'
)
assert
instance
.
query
(
"SELECT * FROM test.table"
,
user
=
'B'
)
==
"1
\t
5
\n
2
\t
10
\n
"
instance
.
query
(
"REVOKE SELECT ON test.table FROM B"
,
user
=
'A'
)
instance
.
query
(
'ALTER USER A GRANTEES NONE'
)
expected_error
=
"user `B` is not allowed as grantee"
assert
expected_error
in
instance
.
query_and_get_error
(
"GRANT SELECT ON test.table TO B"
,
user
=
'A'
)
instance
.
query
(
'ALTER USER A GRANTEES ANY EXCEPT B'
)
assert
instance
.
query
(
'SHOW CREATE USER A'
)
==
"CREATE USER A GRANTEES ANY EXCEPT B
\n
"
expected_error
=
"user `B` is not allowed as grantee"
assert
expected_error
in
instance
.
query_and_get_error
(
"GRANT SELECT ON test.table TO B"
,
user
=
'A'
)
instance
.
query
(
'ALTER USER A GRANTEES B'
)
instance
.
query
(
"GRANT SELECT ON test.table TO B"
,
user
=
'A'
)
assert
instance
.
query
(
"SELECT * FROM test.table"
,
user
=
'B'
)
==
"1
\t
5
\n
2
\t
10
\n
"
instance
.
query
(
"REVOKE SELECT ON test.table FROM B"
,
user
=
'A'
)
instance
.
query
(
'ALTER USER A GRANTEES ANY'
)
assert
instance
.
query
(
'SHOW CREATE USER A'
)
==
"CREATE USER A
\n
"
instance
.
query
(
"GRANT SELECT ON test.table TO B"
,
user
=
'A'
)
assert
instance
.
query
(
"SELECT * FROM test.table"
,
user
=
'B'
)
==
"1
\t
5
\n
2
\t
10
\n
"
instance
.
query
(
'ALTER USER A GRANTEES NONE'
)
expected_error
=
"user `B` is not allowed as grantee"
assert
expected_error
in
instance
.
query_and_get_error
(
"REVOKE SELECT ON test.table FROM B"
,
user
=
'A'
)
instance
.
query
(
"CREATE USER C GRANTEES ANY EXCEPT C"
)
assert
instance
.
query
(
'SHOW CREATE USER C'
)
==
"CREATE USER C GRANTEES ANY EXCEPT C
\n
"
instance
.
query
(
'GRANT SELECT ON test.table TO C WITH GRANT OPTION'
)
assert
instance
.
query
(
"SELECT * FROM test.table"
,
user
=
'C'
)
==
"1
\t
5
\n
2
\t
10
\n
"
expected_error
=
"user `C` is not allowed as grantee"
assert
expected_error
in
instance
.
query_and_get_error
(
"REVOKE SELECT ON test.table FROM C"
,
user
=
'C'
)
def
test_grant_all_on_table
():
instance
.
query
(
"CREATE USER A, B"
)
instance
.
query
(
"GRANT ALL ON test.table TO A WITH GRANT OPTION"
)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录