@@ -44,7 +44,6 @@ struct TBaseSchemeReq: public TActorBootstrapped<TDerived> {
44
44
struct TPathToResolve {
45
45
const NKikimrSchemeOp::TModifyScheme& ModifyScheme;
46
46
ui32 RequireAccess = NACLib::EAccessRights::NoAccess;
47
- bool AllowedByLevel = true ;
48
47
49
48
// Params for NSchemeCache::TSchemeCacheNavigate::TEntry
50
49
TVector<TString> Path;
@@ -63,6 +62,7 @@ struct TBaseSchemeReq: public TActorBootstrapped<TDerived> {
63
62
bool CheckDatabaseAdministrator = false ;
64
63
bool IsClusterAdministrator = false ;
65
64
bool IsDatabaseAdministrator = false ;
65
+ NACLib::TSID DatabaseOwner;
66
66
67
67
TBaseSchemeReq (const TTxProxyServices &services, ui64 txid, TAutoPtr<TEvTxProxyReq::TEvSchemeRequest> request, const TIntrusivePtr<TTxProxyMon> &txProxyMon)
68
68
: Services(services)
@@ -1107,7 +1107,7 @@ struct TBaseSchemeReq: public TActorBootstrapped<TDerived> {
1107
1107
1108
1108
// Check admin restrictions and special cases
1109
1109
if (modifyScheme.GetOperationType () == NKikimrSchemeOp::ESchemeOpAlterLogin) {
1110
- // User management allowed to any user or (if configured so) to admins only
1110
+ // User management is allowed to any user or (if configured so) to admins only
1111
1111
if (checkAdmin && !isAdmin) {
1112
1112
const auto errString = MakeAccessDeniedError (ctx, " attempt to manage user" );
1113
1113
auto issue = MakeIssue (NKikimrIssues::TIssuesIds::ACCESS_DENIED, errString);
@@ -1116,25 +1116,55 @@ struct TBaseSchemeReq: public TActorBootstrapped<TDerived> {
1116
1116
}
1117
1117
allowACLBypass = checkAdmin && isAdmin;
1118
1118
1119
+ const auto & alterLogin = modifyScheme.GetAlterLogin ();
1120
+
1119
1121
// Any user can change their own password (but nothing else)
1120
- auto isUserChangesOwnPassword = [](const auto & modifyScheme, const NACLib::TSID& subjectSid) {
1121
- const auto & alter = modifyScheme.GetAlterLogin ();
1122
- if (alter.GetAlterCase () == NKikimrSchemeOp::TAlterLogin::kModifyUser ) {
1123
- const auto & targetUser = alter.GetModifyUser ();
1122
+ auto isUserChangesOwnPassword = [](const auto & alterLogin, const NACLib::TSID& subjectSid) {
1123
+ if (alterLogin.GetAlterCase () == NKikimrSchemeOp::TAlterLogin::kModifyUser ) {
1124
+ const auto & targetUser = alterLogin.GetModifyUser ();
1124
1125
if (targetUser.HasPassword () && !targetUser.HasCanLogin ()) {
1125
1126
return (subjectSid == targetUser.GetUser ());
1126
1127
}
1127
1128
}
1128
1129
return false ;
1129
1130
};
1130
- allowACLBypass = allowACLBypass || isUserChangesOwnPassword (modifyScheme, UserToken->GetUserSID ());
1131
+ allowACLBypass = allowACLBypass || isUserChangesOwnPassword (alterLogin, UserToken->GetUserSID ());
1132
+
1133
+ // Database admin is not allowed to manage group of database admins (its the privilege of cluster admins).
1134
+ if (IsDatabaseAdministrator) {
1135
+ TString group;
1136
+ switch (alterLogin.GetAlterCase ()) {
1137
+ case NKikimrSchemeOp::TAlterLogin::kAddGroupMembership :
1138
+ group = alterLogin.GetAddGroupMembership ().GetGroup ();
1139
+ break ;
1140
+ case NKikimrSchemeOp::TAlterLogin::kRemoveGroupMembership :
1141
+ group = alterLogin.GetRemoveGroupMembership ().GetGroup ();
1142
+ break ;
1143
+ case NKikimrSchemeOp::TAlterLogin::kRemoveGroup :
1144
+ group = alterLogin.GetRemoveGroup ().GetGroup ();
1145
+ break ;
1146
+ case NKikimrSchemeOp::TAlterLogin::kRenameGroup :
1147
+ group = alterLogin.GetRenameGroup ().GetGroup ();
1148
+ break ;
1149
+ default :
1150
+ break ;
1151
+ }
1152
+ if (!group.empty () && group == DatabaseOwner) {
1153
+ const auto errString = MakeAccessDeniedError (ctx, entry.Path , TStringBuilder ()
1154
+ << " attempt to administer database admin group by the database admin"
1155
+ );
1156
+ auto issue = MakeIssue (NKikimrIssues::TIssuesIds::ACCESS_DENIED, errString);
1157
+ ReportStatus (TEvTxUserProxy::TEvProposeTransactionStatus::EStatus::AccessDenied, nullptr , &issue, ctx);
1158
+ return false ;
1159
+ }
1160
+ }
1131
1161
1132
1162
} else if (modifyScheme.GetOperationType () == NKikimrSchemeOp::ESchemeOpModifyACL) {
1133
1163
// Only the owner of the schema object (path) can transfer their ownership away.
1134
1164
// Or admins (if configured so).
1135
1165
const auto & newOwner = modifyScheme.GetModifyACL ().GetNewOwner ();
1136
1166
if (!newOwner.empty ()) {
1137
- // That modifyACL is changing the owner
1167
+ // This modifyACL is changing the owner
1138
1168
auto isObjectOwner = [](const auto & userToken, const NACLib::TSID& owner) {
1139
1169
return userToken->IsExist (owner);
1140
1170
};
@@ -1150,6 +1180,18 @@ struct TBaseSchemeReq: public TActorBootstrapped<TDerived> {
1150
1180
ReportStatus (TEvTxUserProxy::TEvProposeTransactionStatus::EStatus::AccessDenied, nullptr , &issue, ctx);
1151
1181
return false ;
1152
1182
}
1183
+
1184
+ // Database admin is not allowed to change ownership of its own database
1185
+ if (IsDatabaseAdministrator && IsDB (entry)) {
1186
+ const auto errString = MakeAccessDeniedError (ctx, entry.Path , TStringBuilder ()
1187
+ << " attempt to change database ownership by the database admin"
1188
+ << " from " << owner
1189
+ << " to " << newOwner
1190
+ );
1191
+ auto issue = MakeIssue (NKikimrIssues::TIssuesIds::ACCESS_DENIED, errString);
1192
+ ReportStatus (TEvTxUserProxy::TEvProposeTransactionStatus::EStatus::AccessDenied, nullptr , &issue, ctx);
1193
+ return false ;
1194
+ }
1153
1195
}
1154
1196
1155
1197
// Admins can always change ACLs
@@ -1305,6 +1347,7 @@ struct TBaseSchemeReq: public TActorBootstrapped<TDerived> {
1305
1347
}
1306
1348
1307
1349
const auto & database = request.ResultSet .front ();
1350
+ DatabaseOwner = database.Self ->Info .GetOwner ();
1308
1351
IsDatabaseAdministrator = NKikimr::IsDatabaseAdministrator (&UserToken.value (), database.Self ->Info .GetOwner ());
1309
1352
1310
1353
LOG_DEBUG_S (ctx, NKikimrServices::TX_PROXY, " Actor# " << ctx.SelfID .ToString () << " txid# " << TxId
@@ -1314,6 +1357,7 @@ struct TBaseSchemeReq: public TActorBootstrapped<TDerived> {
1314
1357
<< " CheckDatabaseAdministrator: " << CheckDatabaseAdministrator
1315
1358
<< " IsClusterAdministrator: " << IsClusterAdministrator
1316
1359
<< " IsDatabaseAdministrator: " << IsDatabaseAdministrator
1360
+ << " DatabaseOwner: " << DatabaseOwner
1317
1361
);
1318
1362
1319
1363
static_cast <TDerived*>(this )->Start (ctx);
0 commit comments