2021-07-20 15:07:54 +00:00
# include <Access/AccessEntityIO.h>
# include <Access/IAccessEntity.h>
# include <Access/IAccessStorage.h>
# include <Access/Quota.h>
# include <Access/Role.h>
# include <Access/RowPolicy.h>
# include <Access/SettingsProfile.h>
# include <Access/User.h>
# include <Core/Defines.h>
2021-11-26 16:19:47 +00:00
# include <IO/WriteHelpers.h>
2021-10-31 08:51:20 +00:00
# include <Interpreters/Access/InterpreterCreateQuotaQuery.h>
# include <Interpreters/Access/InterpreterCreateRoleQuery.h>
# include <Interpreters/Access/InterpreterCreateRowPolicyQuery.h>
# include <Interpreters/Access/InterpreterCreateSettingsProfileQuery.h>
# include <Interpreters/Access/InterpreterCreateUserQuery.h>
# include <Interpreters/Access/InterpreterGrantQuery.h>
# include <Interpreters/Access/InterpreterShowCreateAccessEntityQuery.h>
# include <Interpreters/Access/InterpreterShowGrantsQuery.h>
# include <Parsers/Access/ASTCreateQuotaQuery.h>
# include <Parsers/Access/ASTCreateRoleQuery.h>
# include <Parsers/Access/ASTCreateRowPolicyQuery.h>
# include <Parsers/Access/ASTCreateSettingsProfileQuery.h>
# include <Parsers/Access/ASTCreateUserQuery.h>
# include <Parsers/Access/ASTGrantQuery.h>
# include <Parsers/Access/ParserCreateQuotaQuery.h>
# include <Parsers/Access/ParserCreateRoleQuery.h>
# include <Parsers/Access/ParserCreateRowPolicyQuery.h>
# include <Parsers/Access/ParserCreateSettingsProfileQuery.h>
# include <Parsers/Access/ParserCreateUserQuery.h>
# include <Parsers/Access/ParserGrantQuery.h>
2022-03-16 13:21:52 +00:00
# include <Parsers/ASTSetQuery.h>
# include <Parsers/ParserSetQuery.h>
2021-07-20 15:07:54 +00:00
# include <Parsers/formatAST.h>
# include <Parsers/parseQuery.h>
# include <boost/range/algorithm/copy.hpp>
# include <boost/range/algorithm_ext/push_back.hpp>
namespace DB
{
namespace ErrorCodes
{
extern const int INCORRECT_ACCESS_ENTITY_DEFINITION ;
2022-03-16 13:21:52 +00:00
extern const int RBAC_VERSION_IS_TOO_NEW ;
2021-07-20 15:07:54 +00:00
}
2022-03-18 20:14:20 +00:00
extern const UInt64 RBAC_INITIAL_VERSION ;
extern const UInt64 RBAC_LATEST_VERSION ;
2021-07-20 15:07:54 +00:00
namespace
{
2022-03-16 13:21:52 +00:00
constexpr const char RBAC_VERSION_SETTING_NAME [ ] = " rbac_version " ;
2021-07-20 15:07:54 +00:00
/// Special parser for the 'ATTACH access entity' queries.
class ParserAttachAccessEntity : public IParserBase
{
protected :
const char * getName ( ) const override { return " ATTACH access entity query " ; }
bool parseImpl ( Pos & pos , ASTPtr & node , Expected & expected ) override
{
ParserCreateUserQuery create_user_p ;
ParserCreateRoleQuery create_role_p ;
ParserCreateRowPolicyQuery create_policy_p ;
ParserCreateQuotaQuery create_quota_p ;
ParserCreateSettingsProfileQuery create_profile_p ;
ParserGrantQuery grant_p ;
2022-03-16 13:21:52 +00:00
ParserSetQuery set_p ;
2021-07-20 15:07:54 +00:00
create_user_p . useAttachMode ( ) ;
create_role_p . useAttachMode ( ) ;
create_policy_p . useAttachMode ( ) ;
create_quota_p . useAttachMode ( ) ;
create_profile_p . useAttachMode ( ) ;
grant_p . useAttachMode ( ) ;
return create_user_p . parse ( pos , node , expected ) | | create_role_p . parse ( pos , node , expected )
| | create_policy_p . parse ( pos , node , expected ) | | create_quota_p . parse ( pos , node , expected )
2022-03-16 13:21:52 +00:00
| | create_profile_p . parse ( pos , node , expected ) | | grant_p . parse ( pos , node , expected )
| | set_p . parse ( pos , node , expected ) ;
2021-07-20 15:07:54 +00:00
}
} ;
}
String serializeAccessEntity ( const IAccessEntity & entity )
{
ASTs queries ;
2022-03-16 13:21:52 +00:00
{
/// Prepend the list with "SET rbac_version = ..." query.
auto set_rbac_version_query = std : : make_shared < ASTSetQuery > ( ) ;
2022-03-18 20:14:20 +00:00
set_rbac_version_query - > changes . emplace_back ( RBAC_VERSION_SETTING_NAME , RBAC_LATEST_VERSION ) ;
2022-03-16 13:21:52 +00:00
queries . push_back ( set_rbac_version_query ) ;
}
/// Build list of ATTACH queries.
2021-07-20 15:07:54 +00:00
queries . push_back ( InterpreterShowCreateAccessEntityQuery : : getAttachQuery ( entity ) ) ;
2021-11-18 20:54:18 +00:00
if ( ( entity . getType ( ) = = AccessEntityType : : USER ) | | ( entity . getType ( ) = = AccessEntityType : : ROLE ) )
2021-07-20 15:07:54 +00:00
boost : : range : : push_back ( queries , InterpreterShowGrantsQuery : : getAttachGrantQueries ( entity ) ) ;
/// Serialize the list of ATTACH queries to a string.
WriteBufferFromOwnString buf ;
for ( const ASTPtr & query : queries )
{
formatAST ( * query , buf , false , true ) ;
buf . write ( " ; \n " , 2 ) ;
}
return buf . str ( ) ;
}
2022-02-23 21:41:16 +00:00
AccessEntityPtr deserializeAccessEntityImpl ( const String & definition )
2021-07-20 15:07:54 +00:00
{
ASTs queries ;
ParserAttachAccessEntity parser ;
const char * begin = definition . data ( ) ; /// begin of current query
const char * pos = begin ; /// parser moves pos from begin to the end of current query
const char * end = begin + definition . size ( ) ;
while ( pos < end )
{
queries . emplace_back ( parseQueryAndMovePosition ( parser , pos , end , " " , true , 0 , DBMS_DEFAULT_MAX_PARSER_DEPTH ) ) ;
while ( isWhitespaceASCII ( * pos ) | | * pos = = ' ; ' )
+ + pos ;
}
2022-03-16 13:21:52 +00:00
/// Number of queries interpreted.
size_t query_index = 0 ;
2022-03-18 20:14:20 +00:00
/// If there is no "SET rbac_version = ..." query we assume that it's the initial version.
UInt64 rbac_version = RBAC_INITIAL_VERSION ;
2022-03-16 13:21:52 +00:00
2021-07-20 15:07:54 +00:00
/// Interpret the AST to build an access entity.
std : : shared_ptr < User > user ;
std : : shared_ptr < Role > role ;
std : : shared_ptr < RowPolicy > policy ;
std : : shared_ptr < Quota > quota ;
std : : shared_ptr < SettingsProfile > profile ;
AccessEntityPtr res ;
for ( const auto & query : queries )
{
2022-03-16 13:21:52 +00:00
if ( auto * set_query = query - > as < ASTSetQuery > ( ) )
{
if ( ( set_query - > changes . size ( ) ! = 1 ) | | ( set_query - > changes [ 0 ] . name ! = RBAC_VERSION_SETTING_NAME ) )
throw Exception ( ErrorCodes : : INCORRECT_ACCESS_ENTITY_DEFINITION , " SET query in this file is only allowed to set {} " , RBAC_VERSION_SETTING_NAME ) ;
if ( query_index ! = 0 )
throw Exception ( ErrorCodes : : INCORRECT_ACCESS_ENTITY_DEFINITION , " SET {} should be the first query in the file " , RBAC_VERSION_SETTING_NAME ) ;
rbac_version = set_query - > changes [ 0 ] . value . safeGet < UInt64 > ( ) ;
2022-03-18 20:14:20 +00:00
if ( rbac_version < RBAC_INITIAL_VERSION )
throw Exception ( ErrorCodes : : INCORRECT_ACCESS_ENTITY_DEFINITION , " {} must be >= {} " , RBAC_VERSION_SETTING_NAME , RBAC_INITIAL_VERSION ) ;
if ( rbac_version > RBAC_LATEST_VERSION )
throw Exception ( ErrorCodes : : RBAC_VERSION_IS_TOO_NEW , " {} must be <= {}, {} {} is too new " , RBAC_VERSION_SETTING_NAME , RBAC_LATEST_VERSION , RBAC_VERSION_SETTING_NAME , rbac_version ) ;
2022-03-16 13:21:52 +00:00
}
else if ( auto * create_user_query = query - > as < ASTCreateUserQuery > ( ) )
2021-07-20 15:07:54 +00:00
{
if ( res )
2022-02-23 21:41:16 +00:00
throw Exception ( " Two access entities attached in the same file " , ErrorCodes : : INCORRECT_ACCESS_ENTITY_DEFINITION ) ;
2021-07-20 15:07:54 +00:00
res = user = std : : make_unique < User > ( ) ;
2022-03-16 13:21:52 +00:00
InterpreterCreateUserQuery : : updateUserFromQuery ( * user , * create_user_query ) ;
2021-07-20 15:07:54 +00:00
}
else if ( auto * create_role_query = query - > as < ASTCreateRoleQuery > ( ) )
{
if ( res )
2022-02-23 21:41:16 +00:00
throw Exception ( " Two access entities attached in the same file " , ErrorCodes : : INCORRECT_ACCESS_ENTITY_DEFINITION ) ;
2021-07-20 15:07:54 +00:00
res = role = std : : make_unique < Role > ( ) ;
InterpreterCreateRoleQuery : : updateRoleFromQuery ( * role , * create_role_query ) ;
}
else if ( auto * create_policy_query = query - > as < ASTCreateRowPolicyQuery > ( ) )
{
if ( res )
2022-02-23 21:41:16 +00:00
throw Exception ( " Two access entities attached in the same file " , ErrorCodes : : INCORRECT_ACCESS_ENTITY_DEFINITION ) ;
2021-07-20 15:07:54 +00:00
res = policy = std : : make_unique < RowPolicy > ( ) ;
2022-03-18 20:14:20 +00:00
InterpreterCreateRowPolicyQuery : : updateRowPolicyFromQuery ( * policy , * create_policy_query , rbac_version ) ;
2021-07-20 15:07:54 +00:00
}
else if ( auto * create_quota_query = query - > as < ASTCreateQuotaQuery > ( ) )
{
if ( res )
2022-02-23 21:41:16 +00:00
throw Exception ( " Two access entities attached in the same file " , ErrorCodes : : INCORRECT_ACCESS_ENTITY_DEFINITION ) ;
2021-07-20 15:07:54 +00:00
res = quota = std : : make_unique < Quota > ( ) ;
InterpreterCreateQuotaQuery : : updateQuotaFromQuery ( * quota , * create_quota_query ) ;
}
else if ( auto * create_profile_query = query - > as < ASTCreateSettingsProfileQuery > ( ) )
{
if ( res )
2022-02-23 21:41:16 +00:00
throw Exception ( " Two access entities attached in the same file " , ErrorCodes : : INCORRECT_ACCESS_ENTITY_DEFINITION ) ;
2021-07-20 15:07:54 +00:00
res = profile = std : : make_unique < SettingsProfile > ( ) ;
InterpreterCreateSettingsProfileQuery : : updateSettingsProfileFromQuery ( * profile , * create_profile_query ) ;
}
else if ( auto * grant_query = query - > as < ASTGrantQuery > ( ) )
{
if ( ! user & & ! role )
2022-02-23 21:41:16 +00:00
throw Exception ( " A user or role should be attached before grant " , ErrorCodes : : INCORRECT_ACCESS_ENTITY_DEFINITION ) ;
2021-07-20 15:07:54 +00:00
if ( user )
InterpreterGrantQuery : : updateUserFromQuery ( * user , * grant_query ) ;
else
InterpreterGrantQuery : : updateRoleFromQuery ( * role , * grant_query ) ;
}
else
throw Exception ( " No interpreter found for query " + query - > getID ( ) , ErrorCodes : : INCORRECT_ACCESS_ENTITY_DEFINITION ) ;
2022-03-16 13:21:52 +00:00
+ + query_index ;
2021-07-20 15:07:54 +00:00
}
if ( ! res )
2022-02-23 21:41:16 +00:00
throw Exception ( " No access entities attached " , ErrorCodes : : INCORRECT_ACCESS_ENTITY_DEFINITION ) ;
2021-07-20 15:07:54 +00:00
return res ;
}
2022-02-23 21:41:16 +00:00
AccessEntityPtr deserializeAccessEntity ( const String & definition , const String & file_path )
{
if ( file_path . empty ( ) )
return deserializeAccessEntityImpl ( definition ) ;
try
{
return deserializeAccessEntityImpl ( definition ) ;
}
catch ( Exception & e )
{
e . addMessage ( " Could not parse " + file_path ) ;
e . rethrow ( ) ;
__builtin_unreachable ( ) ;
}
}
2021-07-20 15:07:54 +00:00
}