mirror of
https://github.com/dragonflydb/dragonfly
synced 2024-11-22 07:33:19 +00:00
fix(AclFamily): do not allow to delete default user (#1954)
* do not allow to delete default user * upon loading an acl file, if default does not exist create them * add test
This commit is contained in:
parent
8dd34b9ce3
commit
949cedf66c
@ -125,6 +125,11 @@ void AclFamily::EvictOpenConnectionsOnAllProactors(std::string_view user) {
|
||||
|
||||
void AclFamily::DelUser(CmdArgList args, ConnectionContext* cntx) {
|
||||
std::string_view username = facade::ToSV(args[0]);
|
||||
if (username == "default") {
|
||||
cntx->SendError("The'default' user cannot be removed");
|
||||
return;
|
||||
}
|
||||
|
||||
auto& registry = *registry_;
|
||||
if (!registry.RemoveUser(username)) {
|
||||
cntx->SendError(absl::StrCat("User ", username, " does not exist"));
|
||||
@ -255,6 +260,11 @@ std::optional<facade::ErrorReply> AclFamily::LoadToRegistryFromFile(std::string_
|
||||
commands.push_back(user.AclCommands());
|
||||
}
|
||||
|
||||
if (!registry.contains("default")) {
|
||||
auto& user = registry["default"];
|
||||
user.Update(registry_->DefaultUserUpdateRequest());
|
||||
}
|
||||
|
||||
if (!init) {
|
||||
StreamUpdatesToAllProactorConnections(usernames, categories, commands);
|
||||
}
|
||||
|
@ -44,6 +44,9 @@ TEST_F(AclFamilyTest, AclDelUser) {
|
||||
auto resp = Run({"ACL", "DELUSER"});
|
||||
EXPECT_THAT(resp, ErrArg("ERR wrong number of arguments for 'acl deluser' command"));
|
||||
|
||||
resp = Run({"ACL", "DELUSER", "default"});
|
||||
EXPECT_THAT(resp, ErrArg("ERR The'default' user cannot be removed"));
|
||||
|
||||
resp = Run({"ACL", "DELUSER", "NOTEXISTS"});
|
||||
EXPECT_THAT(resp, ErrArg("ERR User NOTEXISTS does not exist"));
|
||||
|
||||
|
@ -76,16 +76,20 @@ UserRegistry::UserWithWriteLock UserRegistry::MaybeAddAndUpdateWithLock(std::str
|
||||
return {std::move(lock), user, exists};
|
||||
}
|
||||
|
||||
void UserRegistry::Init() {
|
||||
// Add default user
|
||||
User::UpdateRequest UserRegistry::DefaultUserUpdateRequest() const {
|
||||
User::UpdateRequest::CommandsUpdateType tmp(NumberOfFamilies());
|
||||
size_t id = 0;
|
||||
for (auto& elem : tmp) {
|
||||
elem = {User::Sign::PLUS, id++, acl::ALL_COMMANDS};
|
||||
}
|
||||
std::pair<User::Sign, uint32_t> acl{User::Sign::PLUS, acl::ALL};
|
||||
User::UpdateRequest req{{}, {acl}, true, false, std::move(tmp)};
|
||||
MaybeAddAndUpdate("default", std::move(req));
|
||||
return {{}, {acl}, true, false, std::move(tmp)};
|
||||
}
|
||||
|
||||
void UserRegistry::Init() {
|
||||
// Add default user
|
||||
User::UpdateRequest::CommandsUpdateType tmp(NumberOfFamilies());
|
||||
MaybeAddAndUpdate("default", DefaultUserUpdateRequest());
|
||||
}
|
||||
|
||||
} // namespace dfly::acl
|
||||
|
@ -79,6 +79,8 @@ class UserRegistry {
|
||||
|
||||
UserWithWriteLock MaybeAddAndUpdateWithLock(std::string_view username, User::UpdateRequest req);
|
||||
|
||||
User::UpdateRequest DefaultUserUpdateRequest() const;
|
||||
|
||||
private:
|
||||
RegistryType registry_;
|
||||
mutable util::SharedMutex mu_;
|
||||
|
@ -344,9 +344,10 @@ async def test_good_acl_file(df_local_factory, tmp_dir):
|
||||
result = await client.execute_command("ACL LOAD")
|
||||
|
||||
result = await client.execute_command("ACL LIST")
|
||||
assert 2 == len(result)
|
||||
assert 3 == len(result)
|
||||
assert "user roy on ea71c25a7a60224 +@STRING +HSET" in result
|
||||
assert "user vlad off nopass +@STRING" in result
|
||||
assert "user default on nopass +@ALL +ALL" in result
|
||||
|
||||
await client.close()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user