/* * Copyright (C) 2017-present ScyllaDB */ /* * SPDX-License-Identifier: AGPL-3.0-or-later */ #pragma once #include #include #include #include #include #include #include #include "auth/resource.hh" #include "seastarx.hh" #include "exceptions/exceptions.hh" namespace auth { struct role_config final { bool is_superuser{false}; bool can_login{false}; }; /// /// Differential update for altering existing roles. /// struct role_config_update final { std::optional is_superuser{}; std::optional can_login{}; }; /// /// A logical argument error for a role-management operation. /// class roles_argument_exception : public exceptions::invalid_request_exception { public: using exceptions::invalid_request_exception::invalid_request_exception; }; class role_already_exists : public roles_argument_exception { public: explicit role_already_exists(std::string_view role_name) : roles_argument_exception(format("Role {} already exists.", role_name)) { } }; class nonexistant_role : public roles_argument_exception { public: explicit nonexistant_role(std::string_view role_name) : roles_argument_exception(format("Role {} doesn't exist.", role_name)) { } }; class role_already_included : public roles_argument_exception { public: role_already_included(std::string_view grantee_name, std::string_view role_name) : roles_argument_exception( format("{} already includes role {}.", grantee_name, role_name)) { } }; class revoke_ungranted_role : public roles_argument_exception { public: revoke_ungranted_role(std::string_view revokee_name, std::string_view role_name) : roles_argument_exception( format("{} was not granted role {}, so it cannot be revoked.", revokee_name, role_name)) { } }; using role_set = std::unordered_set; enum class recursive_role_query { yes, no }; /// /// Abstract client for managing roles. /// /// All state necessary for managing roles is stored externally to the client instance. /// /// All implementations should throw role-related exceptions as documented. Authorization is not addressed here, and /// access-control should never be enforced in implementations. /// class role_manager { public: // this type represents a mapping between a role and some attribute value. // i.e: given attribute name 'a' this map holds role name and it's assigned // value of 'a'. using attribute_vals = std::unordered_map; using ptr_type = std::unique_ptr; public: virtual ~role_manager() = default; virtual std::string_view qualified_java_name() const noexcept = 0; virtual const resource_set& protected_resources() const = 0; virtual future<> start() = 0; virtual future<> stop() = 0; /// /// \returns an exceptional future with \ref role_already_exists for a role that has previously been created. /// virtual future<> create(std::string_view role_name, const role_config&) = 0; /// /// \returns an exceptional future with \ref nonexistant_role if the role does not exist. /// virtual future<> drop(std::string_view role_name) = 0; /// /// \returns an exceptional future with \ref nonexistant_role if the role does not exist. /// virtual future<> alter(std::string_view role_name, const role_config_update&) = 0; /// /// Grant `role_name` to `grantee_name`. /// /// \returns an exceptional future with \ref nonexistant_role if either the role or the grantee do not exist. /// /// \returns an exceptional future with \ref role_already_included if granting the role would be redundant, or /// create a cycle. /// virtual future<> grant(std::string_view grantee_name, std::string_view role_name) = 0; /// /// Revoke `role_name` from `revokee_name`. /// /// \returns an exceptional future with \ref nonexistant_role if either the role or the revokee do not exist. /// /// \returns an exceptional future with \ref revoke_ungranted_role if the role was not granted. /// virtual future<> revoke(std::string_view revokee_name, std::string_view role_name) = 0; /// /// \returns an exceptional future with \ref nonexistant_role if the role does not exist. /// virtual future query_granted(std::string_view grantee, recursive_role_query) = 0; virtual future query_all() = 0; virtual future exists(std::string_view role_name) = 0; /// /// \returns an exceptional future with \ref nonexistant_role if the role does not exist. /// virtual future is_superuser(std::string_view role_name) = 0; /// /// \returns an exceptional future with \ref nonexistant_role if the role does not exist. /// virtual future can_login(std::string_view role_name) = 0; /// /// \returns the value of the named attribute, if one is set. /// virtual future> get_attribute(std::string_view role_name, std::string_view attribute_name) = 0; /// /// \returns a mapping of each role's value for the named attribute, if one is set for the role. /// virtual future query_attribute_for_all(std::string_view attribute_name) = 0; /// Sets `attribute_name` with `attribute_value` for `role_name`. /// \returns an exceptional future with nonexistant_role if the role does not exist. /// virtual future<> set_attribute(std::string_view role_name, std::string_view attribute_name, std::string_view attribute_value) = 0; /// Removes `attribute_name` for `role_name`. /// \returns an exceptional future with nonexistant_role if the role does not exist. /// \note: This is a no-op if the role does not have the named attribute set. /// virtual future<> remove_attribute(std::string_view role_name, std::string_view attribute_name) = 0; }; }