diff --git a/auth/service.cc b/auth/service.cc index 0476e20c91..4053145928 100644 --- a/auth/service.cc +++ b/auth/service.cc @@ -16,6 +16,8 @@ #include #include +#include + #include #include #include @@ -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& 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(qp.local(), g0, mm.local()); + }; + } else if (boost::iequals(short_name, "CassandraAuthorizer")) { + return [&qp, &g0, &mm] { + return std::make_unique(qp.local(), g0, mm.local()); + }; + } else if (boost::iequals(short_name, "TransitionalAuthorizer")) { + return [&qp, &g0, &mm] { + return std::make_unique(qp.local(), g0, mm.local()); + }; + } + throw std::invalid_argument(fmt::format("Unknown authorizer: {}", name)); +} + +authenticator_factory make_authenticator_factory( + std::string_view name, + sharded& qp, + ::service::raft_group0_client& g0, + sharded<::service::migration_manager>& mm, + sharded& 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(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(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(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(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(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& qp, + ::service::raft_group0_client& g0, + sharded<::service::migration_manager>& mm, + sharded& 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(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(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& qp, + ::service::raft_group0_client& g0, + sharded<::service::migration_manager>& mm, + sharded& auth_cache) { + return [&qp, &g0, &mm, &auth_cache] { + return std::make_unique(qp.local(), g0, mm.local(), auth_cache.local()); + }; +} + } diff --git a/auth/service.hh b/auth/service.hh index 38a6ef932d..ccfc9a13f5 100644 --- a/auth/service.hh +++ b/auth/service.hh @@ -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()>; +using authenticator_factory = std::function()>; +using role_manager_factory = std::function()>; + /// /// 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::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& 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& qp, + ::service::raft_group0_client& g0, + sharded<::service::migration_manager>& mm, + sharded& 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& qp, + ::service::raft_group0_client& g0, + sharded<::service::migration_manager>& mm, + sharded& 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& qp, + ::service::raft_group0_client& g0, + sharded<::service::migration_manager>& mm, + sharded& cache); + }