mirror of
https://github.com/scylladb/scylladb.git
synced 2026-05-12 19:02:12 +00:00
auth: add service constructor with factory functors
Auth service can be initialized:
- [current] by passing instantiated authorizer, authenticator, role manager
- [current] by passing service_config, which then uses class registrator to instantiate authorizer, authenticator, role manager
- This approach is easy to use with sharded services
- [new] by passing factory functors which instantiate authorizer, authenticator, role manager
- This approach is also easy to use with sharded services
Refs SCYLLADB-409
This commit is contained in:
128
auth/service.cc
128
auth/service.cc
@@ -16,6 +16,8 @@
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
#include <seastar/core/future-util.hh>
|
||||
#include <seastar/core/shard_id.hh>
|
||||
#include <seastar/core/sharded.hh>
|
||||
@@ -23,8 +25,16 @@
|
||||
|
||||
#include "auth/allow_all_authenticator.hh"
|
||||
#include "auth/allow_all_authorizer.hh"
|
||||
#include "auth/certificate_authenticator.hh"
|
||||
#include "auth/common.hh"
|
||||
#include "auth/default_authorizer.hh"
|
||||
#include "auth/ldap_role_manager.hh"
|
||||
#include "auth/maintenance_socket_role_manager.hh"
|
||||
#include "auth/password_authenticator.hh"
|
||||
#include "auth/role_or_anonymous.hh"
|
||||
#include "auth/saslauthd_authenticator.hh"
|
||||
#include "auth/standard_role_manager.hh"
|
||||
#include "auth/transitional.hh"
|
||||
#include "cql3/functions/functions.hh"
|
||||
#include "cql3/query_processor.hh"
|
||||
#include "cql3/description.hh"
|
||||
@@ -191,6 +201,27 @@ service::service(
|
||||
used_by_maintenance_socket) {
|
||||
}
|
||||
|
||||
service::service(
|
||||
utils::loading_cache_config c,
|
||||
cql3::query_processor& qp,
|
||||
::service::raft_group0_client& g0,
|
||||
::service::migration_notifier& mn,
|
||||
authorizer_factory authorizer_factory,
|
||||
authenticator_factory authenticator_factory,
|
||||
role_manager_factory role_manager_factory,
|
||||
maintenance_socket_enabled used_by_maintenance_socket,
|
||||
cache& cache)
|
||||
: service(
|
||||
cache,
|
||||
qp,
|
||||
g0,
|
||||
mn,
|
||||
authorizer_factory(),
|
||||
authenticator_factory(),
|
||||
role_manager_factory(),
|
||||
used_by_maintenance_socket) {
|
||||
}
|
||||
|
||||
future<> service::create_legacy_keyspace_if_missing(::service::migration_manager& mm) const {
|
||||
SCYLLA_ASSERT(this_shard_id() == 0); // once_among_shards makes sure a function is executed on shard 0 only
|
||||
auto db = _qp.db();
|
||||
@@ -928,4 +959,101 @@ future<> migrate_to_auth_v2(db::system_keyspace& sys_ks, ::service::raft_group0_
|
||||
std::nullopt);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
std::string_view get_short_name(std::string_view name) {
|
||||
auto pos = name.find_last_of('.');
|
||||
if (pos == std::string_view::npos) {
|
||||
return name;
|
||||
}
|
||||
return name.substr(pos + 1);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
authorizer_factory make_authorizer_factory(
|
||||
std::string_view name,
|
||||
sharded<cql3::query_processor>& qp,
|
||||
::service::raft_group0_client& g0,
|
||||
sharded<::service::migration_manager>& mm) {
|
||||
std::string_view short_name = get_short_name(name);
|
||||
|
||||
if (boost::iequals(short_name, "AllowAllAuthorizer")) {
|
||||
return [&qp, &g0, &mm] {
|
||||
return std::make_unique<allow_all_authorizer>(qp.local(), g0, mm.local());
|
||||
};
|
||||
} else if (boost::iequals(short_name, "CassandraAuthorizer")) {
|
||||
return [&qp, &g0, &mm] {
|
||||
return std::make_unique<default_authorizer>(qp.local(), g0, mm.local());
|
||||
};
|
||||
} else if (boost::iequals(short_name, "TransitionalAuthorizer")) {
|
||||
return [&qp, &g0, &mm] {
|
||||
return std::make_unique<transitional_authorizer>(qp.local(), g0, mm.local());
|
||||
};
|
||||
}
|
||||
throw std::invalid_argument(fmt::format("Unknown authorizer: {}", name));
|
||||
}
|
||||
|
||||
authenticator_factory make_authenticator_factory(
|
||||
std::string_view name,
|
||||
sharded<cql3::query_processor>& qp,
|
||||
::service::raft_group0_client& g0,
|
||||
sharded<::service::migration_manager>& mm,
|
||||
sharded<cache>& auth_cache) {
|
||||
std::string_view short_name = get_short_name(name);
|
||||
|
||||
if (boost::iequals(short_name, "AllowAllAuthenticator")) {
|
||||
return [&qp, &g0, &mm, &auth_cache] {
|
||||
return std::make_unique<allow_all_authenticator>(qp.local(), g0, mm.local(), auth_cache.local());
|
||||
};
|
||||
} else if (boost::iequals(short_name, "PasswordAuthenticator")) {
|
||||
return [&qp, &g0, &mm, &auth_cache] {
|
||||
return std::make_unique<password_authenticator>(qp.local(), g0, mm.local(), auth_cache.local());
|
||||
};
|
||||
} else if (boost::iequals(short_name, "CertificateAuthenticator")) {
|
||||
return [&qp, &g0, &mm, &auth_cache] {
|
||||
return std::make_unique<certificate_authenticator>(qp.local(), g0, mm.local(), auth_cache.local());
|
||||
};
|
||||
} else if (boost::iequals(short_name, "SaslauthdAuthenticator")) {
|
||||
return [&qp, &g0, &mm, &auth_cache] {
|
||||
return std::make_unique<saslauthd_authenticator>(qp.local(), g0, mm.local(), auth_cache.local());
|
||||
};
|
||||
} else if (boost::iequals(short_name, "TransitionalAuthenticator")) {
|
||||
return [&qp, &g0, &mm, &auth_cache] {
|
||||
return std::make_unique<transitional_authenticator>(qp.local(), g0, mm.local(), auth_cache.local());
|
||||
};
|
||||
}
|
||||
throw std::invalid_argument(fmt::format("Unknown authenticator: {}", name));
|
||||
}
|
||||
|
||||
role_manager_factory make_role_manager_factory(
|
||||
std::string_view name,
|
||||
sharded<cql3::query_processor>& qp,
|
||||
::service::raft_group0_client& g0,
|
||||
sharded<::service::migration_manager>& mm,
|
||||
sharded<cache>& auth_cache) {
|
||||
std::string_view short_name = get_short_name(name);
|
||||
|
||||
if (boost::iequals(short_name, "CassandraRoleManager")) {
|
||||
return [&qp, &g0, &mm, &auth_cache] {
|
||||
return std::make_unique<standard_role_manager>(qp.local(), g0, mm.local(), auth_cache.local());
|
||||
};
|
||||
} else if (boost::iequals(short_name, "LDAPRoleManager")) {
|
||||
return [&qp, &g0, &mm, &auth_cache] {
|
||||
return std::make_unique<ldap_role_manager>(qp.local(), g0, mm.local(), auth_cache.local());
|
||||
};
|
||||
}
|
||||
throw std::invalid_argument(fmt::format("Unknown role manager: {}", name));
|
||||
}
|
||||
|
||||
role_manager_factory make_maintenance_socket_role_manager_factory(
|
||||
sharded<cql3::query_processor>& qp,
|
||||
::service::raft_group0_client& g0,
|
||||
sharded<::service::migration_manager>& mm,
|
||||
sharded<cache>& auth_cache) {
|
||||
return [&qp, &g0, &mm, &auth_cache] {
|
||||
return std::make_unique<maintenance_socket_role_manager>(qp.local(), g0, mm.local(), auth_cache.local());
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -50,6 +50,11 @@ struct service_config final {
|
||||
sstring role_manager_java_name;
|
||||
};
|
||||
|
||||
/// Factory function types for creating auth module instances on each shard.
|
||||
using authorizer_factory = std::function<std::unique_ptr<authorizer>()>;
|
||||
using authenticator_factory = std::function<std::unique_ptr<authenticator>()>;
|
||||
using role_manager_factory = std::function<std::unique_ptr<role_manager>()>;
|
||||
|
||||
///
|
||||
/// Due to poor (in this author's opinion) decisions of Apache Cassandra, certain choices of one role-manager,
|
||||
/// authenticator, or authorizer imply restrictions on the rest.
|
||||
@@ -120,6 +125,21 @@ public:
|
||||
maintenance_socket_enabled,
|
||||
cache&);
|
||||
|
||||
///
|
||||
/// This constructor is intended to be used when the class is sharded via \ref seastar::sharded. In that case, the
|
||||
/// arguments must be copyable, which is why we delay construction with instance-construction factories instead
|
||||
/// of the instances themselves.
|
||||
///
|
||||
service(
|
||||
cql3::query_processor&,
|
||||
::service::raft_group0_client&,
|
||||
::service::migration_notifier&,
|
||||
authorizer_factory,
|
||||
authenticator_factory,
|
||||
role_manager_factory,
|
||||
maintenance_socket_enabled,
|
||||
cache&);
|
||||
|
||||
future<> start(::service::migration_manager&, db::system_keyspace&);
|
||||
|
||||
future<> stop();
|
||||
@@ -396,4 +416,44 @@ future<> commit_mutations(service& ser, ::service::group0_batch&& mc);
|
||||
// Migrates data from old keyspace to new one which supports linearizable writes via raft.
|
||||
future<> migrate_to_auth_v2(db::system_keyspace& sys_ks, ::service::raft_group0_client& g0, start_operation_func_t start_operation_func, abort_source& as);
|
||||
|
||||
///
|
||||
/// Factory helper functions for creating auth module instances.
|
||||
/// These are intended for use with sharded<service>::start() where copyable arguments are required.
|
||||
/// The returned factories capture the sharded references and call .local() when invoked on each shard.
|
||||
///
|
||||
|
||||
/// Creates an authorizer factory for config-selectable authorizer types.
|
||||
/// @param name The authorizer class name (e.g., "CassandraAuthorizer", "AllowAllAuthorizer")
|
||||
authorizer_factory make_authorizer_factory(
|
||||
std::string_view name,
|
||||
sharded<cql3::query_processor>& qp,
|
||||
::service::raft_group0_client& g0,
|
||||
sharded<::service::migration_manager>& mm);
|
||||
|
||||
/// Creates an authenticator factory for config-selectable authenticator types.
|
||||
/// @param name The authenticator class name (e.g., "PasswordAuthenticator", "AllowAllAuthenticator")
|
||||
authenticator_factory make_authenticator_factory(
|
||||
std::string_view name,
|
||||
sharded<cql3::query_processor>& qp,
|
||||
::service::raft_group0_client& g0,
|
||||
sharded<::service::migration_manager>& mm,
|
||||
sharded<cache>& cache);
|
||||
|
||||
/// Creates a role_manager factory for config-selectable role manager types.
|
||||
/// @param name The role manager class name (e.g., "CassandraRoleManager")
|
||||
role_manager_factory make_role_manager_factory(
|
||||
std::string_view name,
|
||||
sharded<cql3::query_processor>& qp,
|
||||
::service::raft_group0_client& g0,
|
||||
sharded<::service::migration_manager>& mm,
|
||||
sharded<cache>& cache);
|
||||
|
||||
/// Creates a factory for the maintenance socket role manager.
|
||||
/// This role manager is not config-selectable and is only used for the maintenance socket.
|
||||
role_manager_factory make_maintenance_socket_role_manager_factory(
|
||||
sharded<cql3::query_processor>& qp,
|
||||
::service::raft_group0_client& g0,
|
||||
sharded<::service::migration_manager>& mm,
|
||||
sharded<cache>& cache);
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user