Skip to content

Commit

Permalink
feat(acl): add storage for acl keys
Browse files Browse the repository at this point in the history
  • Loading branch information
kostasrim committed Dec 5, 2023
1 parent 1900e49 commit 0135a99
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 4 deletions.
16 changes: 16 additions & 0 deletions src/facade/acl_commands_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,24 @@

#pragma once

#include <cstdint>
#include <limits>
#include <string>
#include <utility>
#include <vector>

namespace dfly::acl {
// Special flag/mask for all
constexpr uint32_t NONE = 0;
constexpr uint32_t ALL = std::numeric_limits<uint32_t>::max();

enum class KeyOp : int8_t { READ, WRITE, READ_WRITE };

using GlobType = std::pair<std::string, KeyOp>;

struct AclKeys {
std::vector<GlobType> key_globs;
bool all_keys = false;
};

} // namespace dfly::acl
26 changes: 26 additions & 0 deletions src/server/acl/user.cc
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ void User::Update(UpdateRequest&& req) {
UnsetAclCommands(index, bit_index);
}

if (!req.keys.empty()) {
SetKeyGlobs(std::move(req.keys));
}

if (req.is_active) {
SetIsActive(*req.is_active);
}
Expand Down Expand Up @@ -130,4 +134,26 @@ std::string_view User::Password() const {
return password_hash_ ? *password_hash_ : default_pass;
}

AclKeys User::Keys() const {
return keys_;
}

const AclKeys& User::KeysRef() const {
return keys_;
}

void User::SetKeyGlobs(std::vector<UpdateKey> keys) {
for (auto& key : keys) {
if (key.all_keys) {
keys_.key_globs.clear();
keys_.all_keys = true;
} else if (key.reset_keys) {
keys_.key_globs.clear();
keys_.all_keys = false;
} else {
keys_.key_globs.push_back({std::move(key.key), key.op});
}
}
}

} // namespace dfly::acl
22 changes: 20 additions & 2 deletions src/server/acl/user.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ class User final {
public:
enum class Sign : int8_t { PLUS, MINUS };

struct UpdateKey {
std::string key;
KeyOp op;
bool all_keys = false;
bool reset_keys = false;
};

struct UpdateRequest {
std::optional<std::string> password{};

Expand All @@ -36,6 +43,11 @@ class User final {
using CommandsValueType = std::tuple<Sign, size_t /*index*/, uint64_t /*bit*/>;
using CommandsUpdateType = std::vector<CommandsValueType>;
CommandsUpdateType commands;

// keys
std::vector<UpdateKey> keys;
bool reset_all_keys{false};
bool allow_all_keys{false};
};

/* Used for default user
Expand Down Expand Up @@ -66,6 +78,9 @@ class User final {
// its respective ID within the commands vector.
static size_t Selector(std::string_view);

AclKeys Keys() const;
const AclKeys& KeysRef() const;

private:
// For ACL categories
void SetAclCategories(uint32_t cat);
Expand All @@ -81,6 +96,9 @@ class User final {
// For passwords
void SetPasswordHash(std::string_view password, bool is_hashed);

// For ACL key globs
void SetKeyGlobs(std::vector<UpdateKey> keys);

// when optional is empty, the special `nopass` password is implied
// password hashed with xx64
std::optional<std::string> password_hash_;
Expand All @@ -91,8 +109,8 @@ class User final {
// on how this mapping is built during the startup/registration of commands
std::vector<uint64_t> commands_;

// we have at least 221 commands including a bunch of subcommands
// LARGE_BITFIELD_DATATYPE acl_commands_;
// Glob patterns for the keys that a user is allowed to read/write
AclKeys keys_;

// if the user is on/off
bool is_active_{false};
Expand Down
5 changes: 3 additions & 2 deletions src/server/acl/user_registry.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ UserRegistry::UserCredentials UserRegistry::GetCredentials(std::string_view user
if (it == registry_.end()) {
return {};
}
return {it->second.AclCategory(), it->second.AclCommands()};
return {it->second.AclCategory(), it->second.AclCommands(), it->second.Keys()};
}

bool UserRegistry::IsUserActive(std::string_view username) const {
Expand Down Expand Up @@ -86,7 +86,8 @@ User::UpdateRequest UserRegistry::DefaultUserUpdateRequest() const {
elem = {User::Sign::PLUS, id++, acl::ALL_COMMANDS};
}
std::pair<User::Sign, uint32_t> acl{User::Sign::PLUS, acl::ALL};
return {{}, {acl}, true, false, std::move(tmp)};
auto key = User::UpdateKey{"~*", KeyOp::READ_WRITE, true, false};
return {{}, {acl}, true, false, std::move(tmp), {std::move(key)}};
}

void UserRegistry::Init() {
Expand Down
1 change: 1 addition & 0 deletions src/server/acl/user_registry.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class UserRegistry {
struct UserCredentials {
uint32_t acl_categories{0};
std::vector<uint64_t> acl_commands;
AclKeys keys;
};

// Acquires a read lock
Expand Down

0 comments on commit 0135a99

Please sign in to comment.