This change appears quite large, but is logically fairly simple. Previously, the `auth` module was structured around global state in a number of ways: - There existed global instances for the authenticator and the authorizer, which were accessed pervasively throughout the system through `auth::authenticator::get()` and `auth::authorizer::get()`, respectively. These instances needed to be initialized before they could be used with `auth::authenticator::setup(sstring type_name)` and `auth::authorizer::setup(sstring type_name)`. - The implementation of the `auth::auth` functions and the authenticator and authorizer depended on resources accessed globally through `cql3::get_local_query_processor()` and `service::get_local_migration_manager()`. - CQL statements would check for access and manage users through static functions in `auth::auth`. These functions would access the global authenticator and authorizer instances and depended on the necessary systems being started before they were used. This change eliminates global state from all of these. The specific changes are: - Move out `allow_all_authenticator` and `allow_all_authorizer` into their own files so that they're constructed like any other authenticator or authorizer. - Delete `auth.hh` and `auth.cc`. Constants and helper functions useful for implementing functionality in the `auth` module have moved to `common.hh`. - Remove silent global dependency in `auth::authenticated_user::is_super()` on the auth* service in favour of a new function `auth::is_super_user()` with an explicit auth* service argument. - Remove global authenticator and authorizer instances, as well as the `setup()` functions. - Expose dependency on the auth* service in `auth::authorizer::authorize()` and `auth::authorizer::list()`, which is necessary to check for superuser status. - Add an explicit `service::migration_manager` argument to the authenticators and authorizers so they can announce metadata tables. - The permissions cache now requires an auth* service reference instead of just an authorizer since authorizing also requires this. - The permissions cache configuration can now easily be created from the DB configuration. - Move the static functions in `auth::auth` to the new `auth::service`. Where possible, previously static resources like the `delayed_tasks` are now members. - Validating `cql3::user_options` requires an authenticator, which was previously accessed globally. - Instances of the auth* service are accessed through `external` instances of `client_state` instead of globally. This includes several CQL statements including `alter_user_statement`, `create_user_statement`, `drop_user_statement`, `grant_statement`, `list_permissions_statement`, `permissions_altering_statement`, and `revoke_statement`. For `internal` `client_state`, this is `nullptr`. - Since the `cql_server` is responsible for instantiating connections and each connection gets a new `client_state`, the `cql_server` is instantiated with a reference to the auth* service. - Similarly, the Thrift server is now also instantiated with a reference to the auth* service. - Since the storage service is responsible for instantiating and starting the sharded servers, it is instantiated with the sharded auth* service which it threads through. All relevant factory functions have been updated. - The storage service is still responsible for starting the auth* service it has been provided, and shutting it down. - The `cql_test_env` is now instantiated with an instance of the auth* service, and can be accessed through a member function. - All unit tests have been updated and pass. Fixes #2929.
155 lines
5.6 KiB
C++
155 lines
5.6 KiB
C++
/*
|
|
* Copyright (C) 2015 ScyllaDB
|
|
*/
|
|
|
|
/*
|
|
* This file is part of Scylla.
|
|
*
|
|
* Scylla is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Affero General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* Scylla is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with Scylla. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "init.hh"
|
|
#include "message/messaging_service.hh"
|
|
#include "gms/failure_detector.hh"
|
|
#include "gms/gossiper.hh"
|
|
#include "service/storage_service.hh"
|
|
#include "to_string.hh"
|
|
#include "gms/inet_address.hh"
|
|
|
|
logging::logger startlog("init");
|
|
|
|
//
|
|
// NOTE: there functions are (temporarily)
|
|
// duplicated in cql_test_env.cc
|
|
// until proper shutdown is done.
|
|
|
|
void init_storage_service(distributed<database>& db, sharded<auth::service>& auth_service) {
|
|
service::init_storage_service(db, auth_service).get();
|
|
// #293 - do not stop anything
|
|
//engine().at_exit([] { return service::deinit_storage_service(); });
|
|
}
|
|
|
|
void init_ms_fd_gossiper(sstring listen_address_in
|
|
, uint16_t storage_port
|
|
, uint16_t ssl_storage_port
|
|
, bool tcp_nodelay_inter_dc
|
|
, sstring ms_encrypt_what
|
|
, sstring ms_trust_store
|
|
, sstring ms_cert
|
|
, sstring ms_key
|
|
, sstring ms_tls_prio
|
|
, bool ms_client_auth
|
|
, sstring ms_compress
|
|
, db::seed_provider_type seed_provider
|
|
, sstring cluster_name
|
|
, double phi
|
|
, bool sltba)
|
|
{
|
|
const auto listen = gms::inet_address::lookup(listen_address_in).get0();
|
|
|
|
using encrypt_what = netw::messaging_service::encrypt_what;
|
|
using compress_what = netw::messaging_service::compress_what;
|
|
using tcp_nodelay_what = netw::messaging_service::tcp_nodelay_what;
|
|
using namespace seastar::tls;
|
|
|
|
encrypt_what ew = encrypt_what::none;
|
|
if (ms_encrypt_what == "all") {
|
|
ew = encrypt_what::all;
|
|
} else if (ms_encrypt_what == "dc") {
|
|
ew = encrypt_what::dc;
|
|
} else if (ms_encrypt_what == "rack") {
|
|
ew = encrypt_what::rack;
|
|
}
|
|
|
|
compress_what cw = compress_what::none;
|
|
if (ms_compress == "all") {
|
|
cw = compress_what::all;
|
|
} else if (ms_compress == "dc") {
|
|
cw = compress_what::dc;
|
|
}
|
|
|
|
tcp_nodelay_what tndw = tcp_nodelay_what::all;
|
|
if (!tcp_nodelay_inter_dc) {
|
|
tndw = tcp_nodelay_what::local;
|
|
}
|
|
|
|
future<> f = make_ready_future<>();
|
|
std::shared_ptr<credentials_builder> creds;
|
|
|
|
if (ew != encrypt_what::none) {
|
|
creds = std::make_shared<credentials_builder>();
|
|
creds->set_dh_level(dh_params::level::MEDIUM);
|
|
|
|
creds->set_x509_key_file(ms_cert, ms_key, x509_crt_format::PEM).get();
|
|
if (ms_trust_store.empty()) {
|
|
creds->set_system_trust().get();
|
|
} else {
|
|
creds->set_x509_trust_file(ms_trust_store, x509_crt_format::PEM).get();
|
|
}
|
|
|
|
if (!ms_tls_prio.empty()) {
|
|
creds->set_priority_string(ms_tls_prio);
|
|
}
|
|
if (ms_client_auth) {
|
|
creds->set_client_auth(seastar::tls::client_auth::REQUIRE);
|
|
}
|
|
}
|
|
|
|
// Init messaging_service
|
|
// Delay listening messaging_service until gossip message handlers are registered
|
|
bool listen_now = false;
|
|
netw::get_messaging_service().start(listen, storage_port, ew, cw, tndw, ssl_storage_port, creds, sltba, listen_now).get();
|
|
|
|
// #293 - do not stop anything
|
|
//engine().at_exit([] { return netw::get_messaging_service().stop(); });
|
|
// Init failure_detector
|
|
gms::get_failure_detector().start(std::move(phi)).get();
|
|
// #293 - do not stop anything
|
|
//engine().at_exit([]{ return gms::get_failure_detector().stop(); });
|
|
// Init gossiper
|
|
std::set<gms::inet_address> seeds;
|
|
if (seed_provider.parameters.count("seeds") > 0) {
|
|
size_t begin = 0;
|
|
size_t next = 0;
|
|
sstring seeds_str = seed_provider.parameters.find("seeds")->second;
|
|
while (begin < seeds_str.length() && begin != (next=seeds_str.find(",",begin))) {
|
|
auto seed = boost::trim_copy(seeds_str.substr(begin,next-begin));
|
|
try {
|
|
seeds.emplace(gms::inet_address::lookup(seed).get0());
|
|
} catch (...) {
|
|
startlog.error("Bad configuration: invalid value in 'seeds': '{}': {}", seed, std::current_exception());
|
|
throw bad_configuration_error();
|
|
}
|
|
begin = next+1;
|
|
}
|
|
}
|
|
if (seeds.empty()) {
|
|
seeds.emplace(gms::inet_address("127.0.0.1"));
|
|
}
|
|
auto broadcast_address = utils::fb_utilities::get_broadcast_address();
|
|
if (broadcast_address != listen && seeds.count(listen)) {
|
|
print("Use broadcast_address instead of listen_address for seeds list: seeds=%s, listen_address=%s, broadcast_address=%s\n",
|
|
to_string(seeds), listen_address_in, broadcast_address);
|
|
throw std::runtime_error("Use broadcast_address for seeds list");
|
|
}
|
|
gms::get_gossiper().start().get();
|
|
auto& gossiper = gms::get_local_gossiper();
|
|
gossiper.set_seeds(seeds);
|
|
// #293 - do not stop anything
|
|
//engine().at_exit([]{ return gms::get_gossiper().stop(); });
|
|
gms::get_gossiper().invoke_on_all([cluster_name](gms::gossiper& g) {
|
|
g.set_cluster_name(cluster_name);
|
|
});
|
|
}
|