Skip to content

Commit f6c9ccb

Browse files
authored
security: database admin can not administer database admins (#14873)
1 parent c43686a commit f6c9ccb

File tree

1 file changed

+52
-8
lines changed

1 file changed

+52
-8
lines changed

ydb/core/tx/tx_proxy/schemereq.cpp

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ struct TBaseSchemeReq: public TActorBootstrapped<TDerived> {
4444
struct TPathToResolve {
4545
const NKikimrSchemeOp::TModifyScheme& ModifyScheme;
4646
ui32 RequireAccess = NACLib::EAccessRights::NoAccess;
47-
bool AllowedByLevel = true;
4847

4948
// Params for NSchemeCache::TSchemeCacheNavigate::TEntry
5049
TVector<TString> Path;
@@ -63,6 +62,7 @@ struct TBaseSchemeReq: public TActorBootstrapped<TDerived> {
6362
bool CheckDatabaseAdministrator = false;
6463
bool IsClusterAdministrator = false;
6564
bool IsDatabaseAdministrator = false;
65+
NACLib::TSID DatabaseOwner;
6666

6767
TBaseSchemeReq(const TTxProxyServices &services, ui64 txid, TAutoPtr<TEvTxProxyReq::TEvSchemeRequest> request, const TIntrusivePtr<TTxProxyMon> &txProxyMon)
6868
: Services(services)
@@ -1107,7 +1107,7 @@ struct TBaseSchemeReq: public TActorBootstrapped<TDerived> {
11071107

11081108
// Check admin restrictions and special cases
11091109
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
11111111
if (checkAdmin && !isAdmin) {
11121112
const auto errString = MakeAccessDeniedError(ctx, "attempt to manage user");
11131113
auto issue = MakeIssue(NKikimrIssues::TIssuesIds::ACCESS_DENIED, errString);
@@ -1116,25 +1116,55 @@ struct TBaseSchemeReq: public TActorBootstrapped<TDerived> {
11161116
}
11171117
allowACLBypass = checkAdmin && isAdmin;
11181118

1119+
const auto& alterLogin = modifyScheme.GetAlterLogin();
1120+
11191121
// 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();
11241125
if (targetUser.HasPassword() && !targetUser.HasCanLogin()) {
11251126
return (subjectSid == targetUser.GetUser());
11261127
}
11271128
}
11281129
return false;
11291130
};
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+
}
11311161

11321162
} else if (modifyScheme.GetOperationType() == NKikimrSchemeOp::ESchemeOpModifyACL) {
11331163
// Only the owner of the schema object (path) can transfer their ownership away.
11341164
// Or admins (if configured so).
11351165
const auto& newOwner = modifyScheme.GetModifyACL().GetNewOwner();
11361166
if (!newOwner.empty()) {
1137-
// That modifyACL is changing the owner
1167+
// This modifyACL is changing the owner
11381168
auto isObjectOwner = [](const auto& userToken, const NACLib::TSID& owner) {
11391169
return userToken->IsExist(owner);
11401170
};
@@ -1150,6 +1180,18 @@ struct TBaseSchemeReq: public TActorBootstrapped<TDerived> {
11501180
ReportStatus(TEvTxUserProxy::TEvProposeTransactionStatus::EStatus::AccessDenied, nullptr, &issue, ctx);
11511181
return false;
11521182
}
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+
}
11531195
}
11541196

11551197
// Admins can always change ACLs
@@ -1305,6 +1347,7 @@ struct TBaseSchemeReq: public TActorBootstrapped<TDerived> {
13051347
}
13061348

13071349
const auto& database = request.ResultSet.front();
1350+
DatabaseOwner = database.Self->Info.GetOwner();
13081351
IsDatabaseAdministrator = NKikimr::IsDatabaseAdministrator(&UserToken.value(), database.Self->Info.GetOwner());
13091352

13101353
LOG_DEBUG_S(ctx, NKikimrServices::TX_PROXY, "Actor# " << ctx.SelfID.ToString() << " txid# " << TxId
@@ -1314,6 +1357,7 @@ struct TBaseSchemeReq: public TActorBootstrapped<TDerived> {
13141357
<< " CheckDatabaseAdministrator: " << CheckDatabaseAdministrator
13151358
<< " IsClusterAdministrator: " << IsClusterAdministrator
13161359
<< " IsDatabaseAdministrator: " << IsDatabaseAdministrator
1360+
<< " DatabaseOwner: " << DatabaseOwner
13171361
);
13181362

13191363
static_cast<TDerived*>(this)->Start(ctx);

0 commit comments

Comments
 (0)