/* * Copyright (C) 2019 ScyllaDB */ /* * SPDX-License-Identifier: LicenseRef-ScyllaDB-Source-Available-1.1 */ #pragma once #include #include #include #include "ent/ldap/ldap_connection.hh" #include "standard_role_manager.hh" #include "auth/cache.hh" namespace auth { struct config; /// Queries an LDAP server for roles. /// /// Since LDAP grants and revokes roles, calling grant() and revoke() is disallowed. /// /// We query LDAP for a list of a particular user's roles, and the results must match roles that exist in the /// database. Furthermore, the user must have already authenticated to Scylla, meaning it, too, exists in the /// database. Therefore, some of the role_manager functionality is provided by a standard_role_manager under /// the hood. For example, listing all roles or checking if the user can login cannot currently be determined /// by querying LDAP, so they are delegated to the standard_role_manager. class ldap_role_manager : public role_manager { standard_role_manager _std_mgr; ::service::raft_group0_client& _group0_client; seastar::sstring _query_template; ///< LDAP URL dictating which query to make. seastar::sstring _target_attr; ///< LDAP entry attribute containing the Scylla role name. seastar::sstring _bind_name; ///< Username for LDAP simple bind. seastar::sstring _bind_password; ///< Password for LDAP simple bind. uint32_t _permissions_update_interval_in_ms; utils::observer _permissions_update_interval_in_ms_observer; mutable ldap_reuser _connection_factory; // Potentially modified by query_granted(). seastar::abort_source _as; cache& _cache; seastar::future<> _cache_pruner; public: ldap_role_manager( std::string_view query_template, ///< LDAP query template as described in Scylla documentation. std::string_view target_attr, ///< LDAP entry attribute containing the Scylla role name. std::string_view bind_name, ///< LDAP bind credentials. std::string_view bind_password, ///< LDAP bind credentials. uint32_t permissions_update_interval_in_ms, utils::observer permissions_update_interval_in_ms_observer, cql3::query_processor& qp, ///< Passed to standard_role_manager. ::service::raft_group0_client& rg0c, ///< Passed to standard_role_manager. ::service::migration_manager& mm, ///< Passed to standard_role_manager. cache& cache, ///< Passed to standard_role_manager. const config& cfg ///< Auth configuration. ); /// Retrieves LDAP configuration entries from cfg and invokes the other constructor. ldap_role_manager(cql3::query_processor& qp, ::service::raft_group0_client& rg0c, ::service::migration_manager& mm, cache& cache, const config& cfg); /// Thrown when query-template parsing fails. struct url_error : public std::runtime_error { using runtime_error::runtime_error; }; std::string_view qualified_java_name() const noexcept override; const resource_set& protected_resources() const override; future<> start() override; future<> stop() override; future<> create(std::string_view, const role_config&, ::service::group0_batch& mc) override; future<> drop(std::string_view, ::service::group0_batch& mc) override; future<> alter(std::string_view, const role_config_update&, ::service::group0_batch& mc) override; future<> grant(std::string_view, std::string_view, ::service::group0_batch& mc) override; future<> revoke(std::string_view, std::string_view, ::service::group0_batch& mc) override; future query_granted(std::string_view, recursive_role_query) override; future query_all_directly_granted(::service::query_state&) override; future query_all(::service::query_state&) override; future exists(std::string_view) override; future is_superuser(std::string_view) override; future can_login(std::string_view) override; future> get_attribute(std::string_view, std::string_view, ::service::query_state&) override; future query_attribute_for_all(std::string_view, ::service::query_state&) override; future<> set_attribute(std::string_view, std::string_view, std::string_view, ::service::group0_batch& mc) override; future<> remove_attribute(std::string_view, std::string_view, ::service::group0_batch& mc) override; future> describe_role_grants() override; private: /// Connects to the LDAP server indicated by _query_template and executes LDAP bind using _bind_name and /// _bind_password. Returns the resulting ldap_connection. future> connect(); /// Invokes connect() repeatedly with backoff, until it succeeds or retry limit is reached. future> reconnect(); /// Macro-expands _query_template, returning the result. sstring get_url(std::string_view user) const; /// Validates that {USER}, if present, is used only in the LDAP filter component. void validate_query_template() const; /// Used to auto-create roles returned by ldap. future<> create_role(std::string_view role_name); future<> ensure_superuser_is_created() override; }; } // namespace auth