db: auth: move auth tables to system keyspace
Separate keyspace which also behaves as system brings little benefit while creating some compatibility problems like schema digest mismatch during rollback. So we decided to move auth tables into system keyspace. Fixes https://github.com/scylladb/scylladb/issues/18098 Closes scylladb/scylladb#18769
This commit is contained in:
committed by
Avi Kivity
parent
56d523b071
commit
2ab143fb40
@@ -24,7 +24,6 @@
|
||||
#include "service/raft/group0_state_machine.hh"
|
||||
#include "timeout_config.hh"
|
||||
#include "db/config.hh"
|
||||
#include "db/system_auth_keyspace.hh"
|
||||
#include "utils/error_injection.hh"
|
||||
|
||||
namespace auth {
|
||||
@@ -41,14 +40,14 @@ constinit const std::string_view AUTH_PACKAGE_NAME("org.apache.cassandra.auth.")
|
||||
static logging::logger auth_log("auth");
|
||||
|
||||
bool legacy_mode(cql3::query_processor& qp) {
|
||||
return qp.auth_version < db::system_auth_keyspace::version_t::v2;
|
||||
return qp.auth_version < db::system_keyspace::auth_version_t::v2;
|
||||
}
|
||||
|
||||
std::string_view get_auth_ks_name(cql3::query_processor& qp) {
|
||||
if (legacy_mode(qp)) {
|
||||
return meta::legacy::AUTH_KS;
|
||||
}
|
||||
return db::system_auth_keyspace::NAME;
|
||||
return db::system_keyspace::NAME;
|
||||
}
|
||||
|
||||
// Func must support being invoked more than once.
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
*/
|
||||
|
||||
#include "auth/default_authorizer.hh"
|
||||
#include "db/system_auth_keyspace.hh"
|
||||
#include "db/system_keyspace.hh"
|
||||
|
||||
extern "C" {
|
||||
#include <crypt.h>
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
#include "db/config.hh"
|
||||
#include "db/consistency_level_type.hh"
|
||||
#include "db/functions/function_name.hh"
|
||||
#include "db/system_auth_keyspace.hh"
|
||||
#include "log.hh"
|
||||
#include "schema/schema_fwd.hh"
|
||||
#include <seastar/core/future.hh>
|
||||
@@ -633,7 +632,7 @@ future<> migrate_to_auth_v2(db::system_keyspace& sys_ks, ::service::raft_group0_
|
||||
}
|
||||
auto muts = co_await qp.get_mutations_internal(
|
||||
format("INSERT INTO {}.{} ({}) VALUES ({})",
|
||||
db::system_auth_keyspace::NAME,
|
||||
db::system_keyspace::NAME,
|
||||
cf_name,
|
||||
col_names_str,
|
||||
val_binders_str),
|
||||
@@ -648,7 +647,7 @@ future<> migrate_to_auth_v2(db::system_keyspace& sys_ks, ::service::raft_group0_
|
||||
}
|
||||
}
|
||||
co_yield co_await sys_ks.make_auth_version_mutation(ts,
|
||||
db::system_auth_keyspace::version_t::v2);
|
||||
db::system_keyspace::auth_version_t::v2);
|
||||
};
|
||||
co_await announce_mutations_with_batching(g0,
|
||||
start_operation_func,
|
||||
|
||||
@@ -1015,7 +1015,6 @@ scylla_core = (['message/messaging_service.cc',
|
||||
'cql3/result_set.cc',
|
||||
'cql3/prepare_context.cc',
|
||||
'db/consistency_level.cc',
|
||||
'db/system_auth_keyspace.cc',
|
||||
'db/system_keyspace.cc',
|
||||
'db/virtual_table.cc',
|
||||
'db/virtual_tables.cc',
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
#include "lang/wasm.hh"
|
||||
#include "service/raft/raft_group0_client.hh"
|
||||
#include "types/types.hh"
|
||||
#include "db/system_auth_keyspace.hh"
|
||||
|
||||
|
||||
namespace service {
|
||||
@@ -176,7 +175,7 @@ public:
|
||||
|
||||
wasm::manager& wasm() { return _wasm; }
|
||||
|
||||
db::system_auth_keyspace::version_t auth_version;
|
||||
db::system_keyspace::auth_version_t auth_version;
|
||||
|
||||
statements::prepared_statement::checked_weak_ptr get_prepared(const std::optional<auth::authenticated_user>& user, const prepared_cache_key_type& key) {
|
||||
if (user) {
|
||||
|
||||
@@ -2,7 +2,6 @@ add_library(db STATIC)
|
||||
target_sources(db
|
||||
PRIVATE
|
||||
consistency_level.cc
|
||||
system_auth_keyspace.cc
|
||||
system_keyspace.cc
|
||||
virtual_table.cc
|
||||
virtual_tables.cc
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include "gms/feature_service.hh"
|
||||
#include "partition_slice_builder.hh"
|
||||
#include "dht/i_partitioner.hh"
|
||||
#include "system_auth_keyspace.hh"
|
||||
#include "system_keyspace.hh"
|
||||
#include "query-result-set.hh"
|
||||
#include "query-result-writer.hh"
|
||||
@@ -235,7 +234,6 @@ future<> save_system_schema(cql3::query_processor& qp) {
|
||||
co_await save_system_schema_to_keyspace(qp, schema_tables::NAME);
|
||||
// #2514 - make sure "system" is written to system_schema.keyspaces.
|
||||
co_await save_system_schema_to_keyspace(qp, system_keyspace::NAME);
|
||||
co_await save_system_schema_to_keyspace(qp, system_auth_keyspace::NAME);
|
||||
}
|
||||
|
||||
namespace v3 {
|
||||
|
||||
@@ -1,141 +0,0 @@
|
||||
/*
|
||||
* Modified by ScyllaDB
|
||||
* Copyright (C) 2024-present ScyllaDB
|
||||
*/
|
||||
|
||||
/*
|
||||
* SPDX-License-Identifier: (AGPL-3.0-or-later and Apache-2.0)
|
||||
*/
|
||||
|
||||
#include "system_auth_keyspace.hh"
|
||||
#include "system_keyspace.hh"
|
||||
#include "db/schema_tables.hh"
|
||||
#include "schema/schema_builder.hh"
|
||||
#include "types/set.hh"
|
||||
|
||||
namespace db {
|
||||
|
||||
// all system auth tables use schema commitlog
|
||||
namespace {
|
||||
const auto set_use_schema_commitlog = schema_builder::register_static_configurator([](const sstring& ks_name, const sstring& cf_name, schema_static_props& props) {
|
||||
if (ks_name == system_auth_keyspace::NAME) {
|
||||
props.enable_schema_commitlog();
|
||||
}
|
||||
});
|
||||
} // anonymous namespace
|
||||
|
||||
namespace system_auth_keyspace {
|
||||
|
||||
// use the same gc setting as system_schema tables
|
||||
using days = std::chrono::duration<int, std::ratio<24 * 3600>>;
|
||||
// FIXME: in some cases time-based gc may cause data resurrection,
|
||||
// for more info see https://github.com/scylladb/scylladb/issues/15607
|
||||
static constexpr auto auth_gc_grace = std::chrono::duration_cast<std::chrono::seconds>(days(7)).count();
|
||||
|
||||
schema_ptr roles() {
|
||||
static thread_local auto schema = [] {
|
||||
schema_builder builder(generate_legacy_id(NAME, ROLES), NAME, ROLES,
|
||||
// partition key
|
||||
{{"role", utf8_type}},
|
||||
// clustering key
|
||||
{},
|
||||
// regular columns
|
||||
{
|
||||
{"can_login", boolean_type},
|
||||
{"is_superuser", boolean_type},
|
||||
{"member_of", set_type_impl::get_instance(utf8_type, true)},
|
||||
{"salted_hash", utf8_type}
|
||||
},
|
||||
// static columns
|
||||
{},
|
||||
// regular column name type
|
||||
utf8_type,
|
||||
// comment
|
||||
"roles for authentication and RBAC"
|
||||
);
|
||||
builder.set_gc_grace_seconds(auth_gc_grace);
|
||||
builder.with_version(system_keyspace::generate_schema_version(builder.uuid()));
|
||||
return builder.build();
|
||||
}();
|
||||
return schema;
|
||||
}
|
||||
|
||||
schema_ptr role_members() {
|
||||
static thread_local auto schema = [] {
|
||||
schema_builder builder(generate_legacy_id(NAME, ROLE_MEMBERS), NAME, ROLE_MEMBERS,
|
||||
// partition key
|
||||
{{"role", utf8_type}},
|
||||
// clustering key
|
||||
{{"member", utf8_type}},
|
||||
// regular columns
|
||||
{},
|
||||
// static columns
|
||||
{},
|
||||
// regular column name type
|
||||
utf8_type,
|
||||
// comment
|
||||
"joins users and their granted roles in RBAC"
|
||||
);
|
||||
builder.set_gc_grace_seconds(auth_gc_grace);
|
||||
builder.with_version(system_keyspace::generate_schema_version(builder.uuid()));
|
||||
return builder.build();
|
||||
}();
|
||||
return schema;
|
||||
}
|
||||
|
||||
schema_ptr role_attributes() {
|
||||
static thread_local auto schema = [] {
|
||||
schema_builder builder(generate_legacy_id(NAME, ROLE_ATTRIBUTES), NAME, ROLE_ATTRIBUTES,
|
||||
// partition key
|
||||
{{"role", utf8_type}},
|
||||
// clustering key
|
||||
{{"name", utf8_type}},
|
||||
// regular columns
|
||||
{
|
||||
{"value", utf8_type}
|
||||
},
|
||||
// static columns
|
||||
{},
|
||||
// regular column name type
|
||||
utf8_type,
|
||||
// comment
|
||||
"role permissions in RBAC"
|
||||
);
|
||||
builder.set_gc_grace_seconds(auth_gc_grace);
|
||||
builder.with_version(system_keyspace::generate_schema_version(builder.uuid()));
|
||||
return builder.build();
|
||||
}();
|
||||
return schema;
|
||||
}
|
||||
|
||||
schema_ptr role_permissions() {
|
||||
static thread_local auto schema = [] {
|
||||
schema_builder builder(generate_legacy_id(NAME, ROLE_PERMISSIONS), NAME, ROLE_PERMISSIONS,
|
||||
// partition key
|
||||
{{"role", utf8_type}},
|
||||
// clustering key
|
||||
{{"resource", utf8_type}},
|
||||
// regular columns
|
||||
{
|
||||
{"permissions", set_type_impl::get_instance(utf8_type, true)}
|
||||
},
|
||||
// static columns
|
||||
{},
|
||||
// regular column name type
|
||||
utf8_type,
|
||||
// comment
|
||||
"role permissions for CassandraAuthorizer"
|
||||
);
|
||||
builder.set_gc_grace_seconds(auth_gc_grace);
|
||||
builder.with_version(system_keyspace::generate_schema_version(builder.uuid()));
|
||||
return builder.build();
|
||||
}();
|
||||
return schema;
|
||||
}
|
||||
|
||||
std::vector<schema_ptr> all_tables() {
|
||||
return {roles(), role_members(), role_attributes(), role_permissions()};
|
||||
}
|
||||
|
||||
} // namespace system_auth_keyspace
|
||||
} // namespace db
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Modified by ScyllaDB
|
||||
* Copyright (C) 2024-present ScyllaDB
|
||||
*/
|
||||
|
||||
/*
|
||||
* SPDX-License-Identifier: (AGPL-3.0-or-later and Apache-2.0)
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "schema/schema_fwd.hh"
|
||||
#include <vector>
|
||||
|
||||
namespace db {
|
||||
|
||||
namespace system_auth_keyspace {
|
||||
enum class version_t: int64_t {
|
||||
v1 = 1,
|
||||
v2 = 2,
|
||||
};
|
||||
static constexpr auto NAME = "system_auth_v2";
|
||||
// tables
|
||||
static constexpr auto ROLES = "roles";
|
||||
static constexpr auto ROLE_MEMBERS = "role_members";
|
||||
static constexpr auto ROLE_ATTRIBUTES = "role_attributes";
|
||||
static constexpr auto ROLE_PERMISSIONS = "role_permissions";
|
||||
|
||||
|
||||
schema_ptr roles();
|
||||
schema_ptr role_members();
|
||||
schema_ptr role_attributes();
|
||||
schema_ptr role_permissions();
|
||||
|
||||
std::vector<schema_ptr> all_tables();
|
||||
}; // namespace system_auth_keyspace
|
||||
|
||||
} // namespace db
|
||||
@@ -18,7 +18,6 @@
|
||||
#include <seastar/core/on_internal_error.hh>
|
||||
#include "system_keyspace.hh"
|
||||
#include "cql3/untyped_result_set.hh"
|
||||
#include "db/system_auth_keyspace.hh"
|
||||
#include "thrift/server.hh"
|
||||
#include "cql3/query_processor.hh"
|
||||
#include "partition_slice_builder.hh"
|
||||
@@ -88,6 +87,10 @@ namespace {
|
||||
system_keyspace::SCYLLA_LOCAL,
|
||||
system_keyspace::COMMITLOG_CLEANUPS,
|
||||
system_keyspace::SERVICE_LEVELS_V2,
|
||||
system_keyspace::ROLES,
|
||||
system_keyspace::ROLE_MEMBERS,
|
||||
system_keyspace::ROLE_ATTRIBUTES,
|
||||
system_keyspace::ROLE_PERMISSIONS,
|
||||
system_keyspace::v3::CDC_LOCAL
|
||||
};
|
||||
if (ks_name == system_keyspace::NAME && tables.contains(cf_name)) {
|
||||
@@ -1139,6 +1142,103 @@ schema_ptr system_keyspace::service_levels_v2() {
|
||||
return schema;
|
||||
}
|
||||
|
||||
schema_ptr system_keyspace::roles() {
|
||||
static thread_local auto schema = [] {
|
||||
schema_builder builder(generate_legacy_id(NAME, ROLES), NAME, ROLES,
|
||||
// partition key
|
||||
{{"role", utf8_type}},
|
||||
// clustering key
|
||||
{},
|
||||
// regular columns
|
||||
{
|
||||
{"can_login", boolean_type},
|
||||
{"is_superuser", boolean_type},
|
||||
{"member_of", set_type_impl::get_instance(utf8_type, true)},
|
||||
{"salted_hash", utf8_type}
|
||||
},
|
||||
// static columns
|
||||
{},
|
||||
// regular column name type
|
||||
utf8_type,
|
||||
// comment
|
||||
"roles for authentication and RBAC"
|
||||
);
|
||||
builder.with_version(system_keyspace::generate_schema_version(builder.uuid()));
|
||||
return builder.build();
|
||||
}();
|
||||
return schema;
|
||||
}
|
||||
|
||||
schema_ptr system_keyspace::role_members() {
|
||||
static thread_local auto schema = [] {
|
||||
schema_builder builder(generate_legacy_id(NAME, ROLE_MEMBERS), NAME, ROLE_MEMBERS,
|
||||
// partition key
|
||||
{{"role", utf8_type}},
|
||||
// clustering key
|
||||
{{"member", utf8_type}},
|
||||
// regular columns
|
||||
{},
|
||||
// static columns
|
||||
{},
|
||||
// regular column name type
|
||||
utf8_type,
|
||||
// comment
|
||||
"joins users and their granted roles in RBAC"
|
||||
);
|
||||
builder.with_version(system_keyspace::generate_schema_version(builder.uuid()));
|
||||
return builder.build();
|
||||
}();
|
||||
return schema;
|
||||
}
|
||||
|
||||
schema_ptr system_keyspace::role_attributes() {
|
||||
static thread_local auto schema = [] {
|
||||
schema_builder builder(generate_legacy_id(NAME, ROLE_ATTRIBUTES), NAME, ROLE_ATTRIBUTES,
|
||||
// partition key
|
||||
{{"role", utf8_type}},
|
||||
// clustering key
|
||||
{{"name", utf8_type}},
|
||||
// regular columns
|
||||
{
|
||||
{"value", utf8_type}
|
||||
},
|
||||
// static columns
|
||||
{},
|
||||
// regular column name type
|
||||
utf8_type,
|
||||
// comment
|
||||
"role permissions in RBAC"
|
||||
);
|
||||
builder.with_version(system_keyspace::generate_schema_version(builder.uuid()));
|
||||
return builder.build();
|
||||
}();
|
||||
return schema;
|
||||
}
|
||||
|
||||
schema_ptr system_keyspace::role_permissions() {
|
||||
static thread_local auto schema = [] {
|
||||
schema_builder builder(generate_legacy_id(NAME, ROLE_PERMISSIONS), NAME, ROLE_PERMISSIONS,
|
||||
// partition key
|
||||
{{"role", utf8_type}},
|
||||
// clustering key
|
||||
{{"resource", utf8_type}},
|
||||
// regular columns
|
||||
{
|
||||
{"permissions", set_type_impl::get_instance(utf8_type, true)}
|
||||
},
|
||||
// static columns
|
||||
{},
|
||||
// regular column name type
|
||||
utf8_type,
|
||||
// comment
|
||||
"role permissions for CassandraAuthorizer"
|
||||
);
|
||||
builder.with_version(system_keyspace::generate_schema_version(builder.uuid()));
|
||||
return builder.build();
|
||||
}();
|
||||
return schema;
|
||||
}
|
||||
|
||||
schema_ptr system_keyspace::legacy::hints() {
|
||||
static thread_local auto schema = [] {
|
||||
schema_builder builder(generate_legacy_id(NAME, HINTS), NAME, HINTS,
|
||||
@@ -2130,10 +2230,16 @@ future<> system_keyspace::set_bootstrap_state(bootstrap_state state) {
|
||||
});
|
||||
}
|
||||
|
||||
std::vector<schema_ptr> system_keyspace::auth_tables() {
|
||||
return {roles(), role_members(), role_attributes(), role_permissions()};
|
||||
}
|
||||
|
||||
std::vector<schema_ptr> system_keyspace::all_tables(const db::config& cfg) {
|
||||
std::vector<schema_ptr> r;
|
||||
auto schema_tables = db::schema_tables::all_tables(schema_features::full());
|
||||
std::copy(schema_tables.begin(), schema_tables.end(), std::back_inserter(r));
|
||||
auto auth_tables = system_keyspace::auth_tables();
|
||||
std::copy(auth_tables.begin(), auth_tables.end(), std::back_inserter(r));
|
||||
r.insert(r.end(), { built_indexes(), hints(), batchlog(), paxos(), local(),
|
||||
peers(), peer_events(), range_xfers(),
|
||||
compactions_in_progress(), compaction_history(),
|
||||
@@ -2149,9 +2255,6 @@ std::vector<schema_ptr> system_keyspace::all_tables(const db::config& cfg) {
|
||||
topology(), cdc_generations_v3(), topology_requests(), service_levels_v2(),
|
||||
});
|
||||
|
||||
auto auth_tables = db::system_auth_keyspace::all_tables();
|
||||
std::copy(auth_tables.begin(), auth_tables.end(), std::back_inserter(r));
|
||||
|
||||
if (cfg.check_experimental(db::experimental_features_t::feature::BROADCAST_TABLES)) {
|
||||
r.insert(r.end(), {broadcast_kv_store()});
|
||||
}
|
||||
@@ -2691,17 +2794,17 @@ future<std::optional<mutation>> system_keyspace::get_group0_schema_version() {
|
||||
|
||||
static constexpr auto AUTH_VERSION_KEY = "auth_version";
|
||||
|
||||
future<system_auth_keyspace::version_t> system_keyspace::get_auth_version() {
|
||||
future<system_keyspace::auth_version_t> system_keyspace::get_auth_version() {
|
||||
auto str_opt = co_await get_scylla_local_param(AUTH_VERSION_KEY);
|
||||
if (!str_opt) {
|
||||
co_return db::system_auth_keyspace::version_t::v1;
|
||||
co_return auth_version_t::v1;
|
||||
}
|
||||
auto& str = *str_opt;
|
||||
if (str == "" || str == "1") {
|
||||
co_return db::system_auth_keyspace::version_t::v1;
|
||||
co_return auth_version_t::v1;
|
||||
}
|
||||
if (str == "2") {
|
||||
co_return db::system_auth_keyspace::version_t::v2;
|
||||
co_return auth_version_t::v2;
|
||||
}
|
||||
on_internal_error(slogger, fmt::format("unexpected auth_version in scylla_local got {}", str));
|
||||
}
|
||||
@@ -2719,7 +2822,7 @@ static service::query_state& internal_system_query_state() {
|
||||
return qs;
|
||||
};
|
||||
|
||||
future<mutation> system_keyspace::make_auth_version_mutation(api::timestamp_type ts, db::system_auth_keyspace::version_t version) {
|
||||
future<mutation> system_keyspace::make_auth_version_mutation(api::timestamp_type ts, db::system_keyspace::auth_version_t version) {
|
||||
static sstring query = format("INSERT INTO {}.{} (key, value) VALUES (?, ?);", db::system_keyspace::NAME, db::system_keyspace::SCYLLA_LOCAL);
|
||||
auto muts = co_await _qp.get_mutations_internal(query, internal_system_query_state(), ts, {AUTH_VERSION_KEY, std::to_string(int64_t(version))});
|
||||
if (muts.size() != 1) {
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include "db/system_auth_keyspace.hh"
|
||||
#include "gms/gossiper.hh"
|
||||
#include "schema/schema_fwd.hh"
|
||||
#include "utils/UUID.hh"
|
||||
@@ -180,6 +179,12 @@ public:
|
||||
static constexpr auto TABLETS = "tablets";
|
||||
static constexpr auto SERVICE_LEVELS_V2 = "service_levels_v2";
|
||||
|
||||
// auth
|
||||
static constexpr auto ROLES = "roles";
|
||||
static constexpr auto ROLE_MEMBERS = "role_members";
|
||||
static constexpr auto ROLE_ATTRIBUTES = "role_attributes";
|
||||
static constexpr auto ROLE_PERMISSIONS = "role_permissions";
|
||||
|
||||
struct v3 {
|
||||
static constexpr auto BATCHES = "batches";
|
||||
static constexpr auto PAXOS = "paxos";
|
||||
@@ -267,6 +272,12 @@ public:
|
||||
static schema_ptr tablets();
|
||||
static schema_ptr service_levels_v2();
|
||||
|
||||
// auth
|
||||
static schema_ptr roles();
|
||||
static schema_ptr role_members();
|
||||
static schema_ptr role_attributes();
|
||||
static schema_ptr role_permissions();
|
||||
|
||||
static table_schema_version generate_schema_version(table_id table_id, uint16_t offset = 0);
|
||||
|
||||
future<> build_bootstrap_info();
|
||||
@@ -310,7 +321,9 @@ public:
|
||||
template <typename T>
|
||||
future<std::optional<T>> get_scylla_local_param_as(const sstring& key);
|
||||
|
||||
static std::vector<schema_ptr> auth_tables();
|
||||
static std::vector<schema_ptr> all_tables(const db::config& cfg);
|
||||
|
||||
future<> make(
|
||||
locator::effective_replication_map_factory&,
|
||||
replica::database&);
|
||||
@@ -577,11 +590,16 @@ public:
|
||||
// returns the corresponding mutation. Otherwise returns nullopt.
|
||||
future<std::optional<mutation>> get_group0_schema_version();
|
||||
|
||||
enum class auth_version_t: int64_t {
|
||||
v1 = 1,
|
||||
v2 = 2,
|
||||
};
|
||||
|
||||
// If the `auth_version` key in `system.scylla_local` is present (either live or tombstone),
|
||||
// returns the corresponding mutation. Otherwise returns nullopt.
|
||||
future<std::optional<mutation>> get_auth_version_mutation();
|
||||
future<mutation> make_auth_version_mutation(api::timestamp_type ts, db::system_auth_keyspace::version_t version);
|
||||
future<system_auth_keyspace::version_t> get_auth_version();
|
||||
future<mutation> make_auth_version_mutation(api::timestamp_type ts, auth_version_t version);
|
||||
future<auth_version_t> get_auth_version();
|
||||
|
||||
future<> sstables_registry_create_entry(sstring location, sstring status, sstables::sstable_state state, sstables::entry_descriptor desc);
|
||||
future<> sstables_registry_update_entry_status(sstring location, sstables::generation_type gen, sstring status);
|
||||
|
||||
@@ -117,9 +117,9 @@ request. Alternator can then validate the authenticity and authorization of
|
||||
each request using a known list of authorized key pairs.
|
||||
|
||||
In the current implementation, the user stores the list of allowed key pairs
|
||||
in the `system_auth_v2.roles` table: The access key ID is the `role` column, and
|
||||
in the `system.roles` table: The access key ID is the `role` column, and
|
||||
the secret key is the `salted_hash`, i.e., the secret key can be found by
|
||||
`SELECT salted_hash from system_auth_v2.roles WHERE role = ID;`.
|
||||
`SELECT salted_hash from system.roles WHERE role = ID;`.
|
||||
|
||||
<!--- REMOVE IN FUTURE VERSIONS - Remove the note below in version 6.1 -->
|
||||
|
||||
|
||||
@@ -341,7 +341,7 @@ The `--authenticator` command lines option allows to provide the authenticator c
|
||||
|
||||
#### `--authorizer AUTHORIZER`
|
||||
|
||||
The `--authorizer` command lines option allows to provide the authorizer class ScyllaDB will use. By default ScyllaDB uses the `AllowAllAuthorizer` which allows any action to any user. The second option is using the `CassandraAuthorizer` parameter, which stores permissions in `system_auth_v2.permissions` table.
|
||||
The `--authorizer` command lines option allows to provide the authorizer class ScyllaDB will use. By default ScyllaDB uses the `AllowAllAuthorizer` which allows any action to any user. The second option is using the `CassandraAuthorizer` parameter, which stores permissions in `system.permissions` table.
|
||||
|
||||
**Since: 2.3**
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ There are two system tables that are used to facilitate the service level featur
|
||||
### Service Level Attachment Table
|
||||
|
||||
```
|
||||
CREATE TABLE system_auth_v2.role_attributes (
|
||||
CREATE TABLE system.role_attributes (
|
||||
role text,
|
||||
attribute_name text,
|
||||
attribute_value text,
|
||||
@@ -23,7 +23,7 @@ So for example in order to find out which `service_level` is attached to role `r
|
||||
one can run the following query:
|
||||
|
||||
```
|
||||
SELECT * FROM system_auth_v2.role_attributes WHERE role='r' and attribute_name='service_level'
|
||||
SELECT * FROM system.role_attributes WHERE role='r' and attribute_name='service_level'
|
||||
|
||||
```
|
||||
|
||||
@@ -157,4 +157,4 @@ The command displays a table with: option name, effective service level the valu
|
||||
----------------------+-------------------------+-------------
|
||||
workload_type | sl2 | batch
|
||||
timeout | sl1 | 2s
|
||||
```
|
||||
```
|
||||
|
||||
@@ -17,8 +17,8 @@ limitations while applying the procedure:
|
||||
retry, or the node refuses to boot on subsequent attempts, consult the
|
||||
:doc:`Handling Membership Change Failures </operating-scylla/procedures/cluster-management/handling-membership-change-failures>`
|
||||
document.
|
||||
* The ``system_auth`` keyspace has not been upgraded to ``system_auth_v2``.
|
||||
* The ``system_auth`` keyspace has not been upgraded to ``system``.
|
||||
As a result, if ``authenticator`` is set to ``PasswordAuthenticator``, you must
|
||||
increase the replication factor of the ``system_auth`` keyspace. It is
|
||||
recommended to set ``system_auth`` replication factor to the number of nodes
|
||||
in each DC.
|
||||
in each DC.
|
||||
|
||||
@@ -2,7 +2,7 @@ Reset Authenticator Password
|
||||
============================
|
||||
|
||||
This procedure describes what to do when a user loses his password and can not reset it with a superuser role.
|
||||
The procedure requires cluster downtime and as a result, all of the ``system_auth_v2`` data is deleted.
|
||||
The procedure requires cluster downtime and as a result, all auth data is deleted.
|
||||
|
||||
.. scylladb_include_flag:: system-auth-name-info.rst
|
||||
|
||||
@@ -15,11 +15,11 @@ Procedure
|
||||
|
||||
sudo systemctl stop scylla-server
|
||||
|
||||
| 2. Remove your tables under ``/var/lib/scylla/data/system_auth_v2/``.
|
||||
| 2. Remove system tables starting with ``role`` prefix from ``/var/lib/scylla/data/system`` directory.
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
rm -rf /var/lib/scylla/data/ssystem_auth_v2/
|
||||
rm -rf /var/lib/scylla/data/system/role*
|
||||
|
||||
| 3. Start Scylla nodes.
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#include "utils/lister.hh"
|
||||
#include "replica/database.hh"
|
||||
#include <seastar/core/future-util.hh>
|
||||
#include "db/system_auth_keyspace.hh"
|
||||
#include "db/system_keyspace.hh"
|
||||
#include "db/system_keyspace_sstables_registry.hh"
|
||||
#include "db/system_distributed_keyspace.hh"
|
||||
@@ -812,7 +811,6 @@ future<> database::drop_keyspace_on_all_shards(sharded<database>& sharded_db, co
|
||||
static bool is_system_table(const schema& s) {
|
||||
auto& k = s.ks_name();
|
||||
return k == db::system_keyspace::NAME ||
|
||||
k == db::system_auth_keyspace::NAME ||
|
||||
k == db::system_distributed_keyspace::NAME ||
|
||||
k == db::system_distributed_keyspace::NAME_EVERYWHERE;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#include "replica/global_table_ptr.hh"
|
||||
#include "db/config.hh"
|
||||
#include "db/extensions.hh"
|
||||
#include "db/system_auth_keyspace.hh"
|
||||
#include "db/system_keyspace.hh"
|
||||
#include "db/system_distributed_keyspace.hh"
|
||||
#include "db/schema_tables.hh"
|
||||
@@ -36,7 +35,7 @@
|
||||
extern logging::logger dblog;
|
||||
|
||||
static const std::unordered_set<std::string_view> system_keyspaces = {
|
||||
db::system_keyspace::NAME, db::system_auth_keyspace::NAME, db::schema_tables::NAME,
|
||||
db::system_keyspace::NAME, db::schema_tables::NAME,
|
||||
};
|
||||
|
||||
// Not super nice. Adding statefulness to the file.
|
||||
@@ -60,7 +59,6 @@ static const std::unordered_set<std::string_view> internal_keyspaces = {
|
||||
db::system_distributed_keyspace::NAME,
|
||||
db::system_distributed_keyspace::NAME_EVERYWHERE,
|
||||
db::system_keyspace::NAME,
|
||||
db::system_auth_keyspace::NAME,
|
||||
db::schema_tables::NAME,
|
||||
auth::meta::legacy::AUTH_KS,
|
||||
tracing::trace_keyspace_helper::KEYSPACE_NAME
|
||||
|
||||
@@ -1853,7 +1853,7 @@ class schema_ptr:
|
||||
return self.ptr[item]
|
||||
|
||||
def is_system(self):
|
||||
return self.ks_name in ["system", "system_schema", "system_distributed", "system_traces", "system_auth", "system_auth_v2", "audit"]
|
||||
return self.ks_name in ["system", "system_schema", "system_distributed", "system_traces", "system_auth", "audit"]
|
||||
|
||||
|
||||
class scylla_active_sstables(gdb.Command):
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
#include "service/raft/group0_state_machine.hh"
|
||||
#include "db/system_auth_keyspace.hh"
|
||||
#include "mutation/atomic_cell.hh"
|
||||
#include "cql3/selection/selection.hh"
|
||||
#include "dht/i_partitioner.hh"
|
||||
@@ -274,7 +273,7 @@ future<> group0_state_machine::transfer_snapshot(raft::server_id from_id, raft::
|
||||
std::optional<service::raft_snapshot> raft_snp;
|
||||
|
||||
if (_topology_change_enabled) {
|
||||
auto auth_tables = db::system_auth_keyspace::all_tables();
|
||||
auto auth_tables = db::system_keyspace::auth_tables();
|
||||
std::vector<table_id> tables;
|
||||
tables.reserve(3);
|
||||
tables.push_back(db::system_keyspace::topology()->id());
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
|
||||
#include "storage_service.hh"
|
||||
#include "compaction/task_manager_module.hh"
|
||||
#include "db/system_auth_keyspace.hh"
|
||||
#include "gc_clock.hh"
|
||||
#include "raft/raft.hh"
|
||||
#include "service/qos/raft_service_level_distributed_data_accessor.hh"
|
||||
@@ -651,7 +650,7 @@ future<> storage_service::topology_state_load() {
|
||||
co_await _qp.container().invoke_on_all([] (cql3::query_processor& qp) {
|
||||
// auth-v2 gets enabled when consistent topology changes are enabled
|
||||
// (see topology::upgrade_state_type::done above) as we use the same migration procedure
|
||||
qp.auth_version = db::system_auth_keyspace::version_t::v2;
|
||||
qp.auth_version = db::system_keyspace::auth_version_t::v2;
|
||||
});
|
||||
|
||||
co_await _sl_controller.invoke_on_all([this] (qos::service_level_controller& sl_controller) {
|
||||
@@ -1269,7 +1268,7 @@ future<> storage_service::raft_initialize_discovery_leader(const join_node_reque
|
||||
insert_join_request_mutations.emplace_back(std::move(sl_status_mutation));
|
||||
|
||||
insert_join_request_mutations.emplace_back(
|
||||
co_await _sys_ks.local().make_auth_version_mutation(guard.write_timestamp(), db::system_auth_keyspace::version_t::v2));
|
||||
co_await _sys_ks.local().make_auth_version_mutation(guard.write_timestamp(), db::system_keyspace::auth_version_t::v2));
|
||||
|
||||
topology_change change{std::move(insert_join_request_mutations)};
|
||||
group0_command g0_cmd = _group0->client().prepare_command(std::move(change), guard,
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
#include "auth/service.hh"
|
||||
#include "cdc/generation.hh"
|
||||
#include "db/system_auth_keyspace.hh"
|
||||
#include "db/system_distributed_keyspace.hh"
|
||||
#include "db/system_keyspace.hh"
|
||||
#include "dht/boot_strapper.hh"
|
||||
@@ -2505,7 +2504,7 @@ future<> topology_coordinator::build_coordinator_state(group0_guard guard) {
|
||||
co_await _group0.wait_for_all_nodes_to_finish_upgrade(_as);
|
||||
|
||||
auto auth_version = co_await _sys_ks.get_auth_version();
|
||||
if (auth_version < db::system_auth_keyspace::version_t::v2) {
|
||||
if (auth_version < db::system_keyspace::auth_version_t::v2) {
|
||||
rtlogger.info("migrating system_auth keyspace data");
|
||||
co_await auth::migrate_to_auth_v2(_sys_ks, _group0.client(),
|
||||
[this] (abort_source*) { return start_operation();}, _as);
|
||||
|
||||
@@ -19,7 +19,7 @@ async def test_auth_raft_command_split(manager: ManagerClient) -> None:
|
||||
servers = await manager.servers_add(3)
|
||||
cql, hosts = await manager.get_ready_cql(servers)
|
||||
|
||||
initial_perms = await cql.run_async("SELECT * FROM system_auth_v2.role_permissions")
|
||||
initial_perms = await cql.run_async("SELECT * FROM system.role_permissions")
|
||||
|
||||
shared_role = "shared_role_" + unique_name()
|
||||
await cql.run_async(f"CREATE ROLE {shared_role}")
|
||||
@@ -43,11 +43,11 @@ async def test_auth_raft_command_split(manager: ManagerClient) -> None:
|
||||
await asyncio.gather(*(read_barrier(cql, host) for host in hosts))
|
||||
|
||||
# confirm that deleted shared_role is not attached to any other role
|
||||
assert await cql.run_async(f"SELECT * FROM system_auth_v2.role_permissions WHERE resource = 'role/{shared_role}' ALLOW FILTERING") == []
|
||||
assert await cql.run_async(f"SELECT * FROM system.role_permissions WHERE resource = 'role/{shared_role}' ALLOW FILTERING") == []
|
||||
|
||||
# cleanup
|
||||
for user in users:
|
||||
await cql.run_async(f"DROP ROLE IF EXISTS {user}")
|
||||
await asyncio.gather(*(read_barrier(cql, host) for host in hosts))
|
||||
current_perms = await cql.run_async("SELECT * FROM system_auth_v2.role_permissions")
|
||||
current_perms = await cql.run_async("SELECT * FROM system.role_permissions")
|
||||
assert initial_perms == current_perms
|
||||
|
||||
@@ -90,18 +90,18 @@ async def check_auth_v2_data_migration(manager: ManagerClient, hosts):
|
||||
data = auth_data()
|
||||
|
||||
roles = set()
|
||||
for row in await cql.run_async("SELECT * FROM system_auth_v2.roles"):
|
||||
for row in await cql.run_async("SELECT * FROM system.roles"):
|
||||
member_of = frozenset(row.member_of) if row.member_of else None
|
||||
roles.add((row.role, row.can_login, row.is_superuser, member_of, row.salted_hash))
|
||||
assert roles == set(data[0]["rows"])
|
||||
|
||||
role_members = set()
|
||||
for row in await cql.run_async("SELECT * FROM system_auth_v2.role_members"):
|
||||
for row in await cql.run_async("SELECT * FROM system.role_members"):
|
||||
role_members.add((row.role, row.member))
|
||||
assert role_members == set(data[1]["rows"])
|
||||
|
||||
role_attributes = set()
|
||||
for row in await cql.run_async("SELECT * FROM system_auth_v2.role_attributes"):
|
||||
for row in await cql.run_async("SELECT * FROM system.role_attributes"):
|
||||
role_attributes.add((row.role, row.name, row.value))
|
||||
assert role_attributes == set(data[2]["rows"])
|
||||
|
||||
@@ -121,7 +121,7 @@ async def check_auth_v2_works(manager: ManagerClient, hosts):
|
||||
await asyncio.gather(*(read_barrier(cql, host) for host in hosts))
|
||||
# see warmup_v1_static_values for background about checks below
|
||||
# check if it was added to a new table
|
||||
assert len(await cql.run_async("SELECT role FROM system_auth_v2.roles WHERE role = 'user_after_migration'")) == 1
|
||||
assert len(await cql.run_async("SELECT role FROM system.roles WHERE role = 'user_after_migration'")) == 1
|
||||
# check whether list roles statement sees it also via new table (on all nodes)
|
||||
await asyncio.gather(*(cql.run_async("LIST ROLES OF user_after_migration", host=host) for host in hosts))
|
||||
await cql.run_async("DROP ROLE user_after_migration")
|
||||
@@ -158,7 +158,7 @@ async def test_auth_v2_migration(request, manager: ManagerClient):
|
||||
logging.info("Waiting until upgrade finishes")
|
||||
await asyncio.gather(*(wait_until_topology_upgrade_finishes(manager, h.address, time.time() + 60) for h in hosts))
|
||||
|
||||
logging.info("Checking migrated data in system_auth_v2")
|
||||
logging.info("Checking migrated data in system")
|
||||
await check_auth_v2_data_migration(manager, hosts)
|
||||
|
||||
logging.info("Checking auth statements after migration")
|
||||
|
||||
@@ -178,19 +178,19 @@ void require_table_protected(cql_test_env& env, const char* table) {
|
||||
|
||||
SEASTAR_TEST_CASE(roles_table_is_protected) {
|
||||
return do_with_cql_env_thread([] (cql_test_env& env) {
|
||||
require_table_protected(env, "system_auth_v2.roles");
|
||||
require_table_protected(env, "system.roles");
|
||||
}, auth_on());
|
||||
}
|
||||
|
||||
SEASTAR_TEST_CASE(role_members_table_is_protected) {
|
||||
return do_with_cql_env_thread([] (cql_test_env& env) {
|
||||
require_table_protected(env, "system_auth_v2.role_members");
|
||||
require_table_protected(env, "system.role_members");
|
||||
}, auth_on());
|
||||
}
|
||||
|
||||
SEASTAR_TEST_CASE(role_permissions_table_is_protected) {
|
||||
return do_with_cql_env_thread([] (cql_test_env& env) {
|
||||
require_table_protected(env, "system_auth_v2.role_permissions");
|
||||
require_table_protected(env, "system.role_permissions");
|
||||
}, auth_on());
|
||||
}
|
||||
|
||||
|
||||
@@ -151,7 +151,7 @@ def test_udf_permissions_serialization(cql):
|
||||
for permission in permissions:
|
||||
cql.execute(f"GRANT {permission} ON {resource} TO {user}")
|
||||
|
||||
permissions = {row.resource: row.permissions for row in cql.execute(f"SELECT * FROM system_auth_v2.role_permissions")}
|
||||
permissions = {row.resource: row.permissions for row in cql.execute(f"SELECT * FROM system.role_permissions")}
|
||||
assert permissions['functions'] == set(['ALTER', 'AUTHORIZE', 'CREATE', 'DROP', 'EXECUTE'])
|
||||
assert permissions[f'functions/{keyspace}'] == set(['ALTER', 'AUTHORIZE', 'CREATE', 'DROP', 'EXECUTE'])
|
||||
assert permissions[f'functions/{keyspace}/{div_fun}[org.apache.cassandra.db.marshal.LongType^org.apache.cassandra.db.marshal.Int32Type]'] == set(['ALTER', 'AUTHORIZE', 'DROP', 'EXECUTE'])
|
||||
@@ -552,4 +552,4 @@ def test_native_functions_always_exeutable(cql):
|
||||
assert list(user_session.execute(f"SELECT count(*) FROM {table}")) == [(3,)]
|
||||
assert list(user_session.execute(f"SELECT max(a) FROM {table}")) == [(84,)]
|
||||
assert list(user_session.execute(f"SELECT min(a) FROM {table}")) == [(3,)]
|
||||
assert list(user_session.execute(f"SELECT sum(a) FROM {table}")) == [(102,)]
|
||||
assert list(user_session.execute(f"SELECT sum(a) FROM {table}")) == [(102,)]
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
#include "db/large_data_handler.hh"
|
||||
#include "db/system_distributed_keyspace.hh"
|
||||
#include "db/schema_tables.hh"
|
||||
#include "db/system_auth_keyspace.hh"
|
||||
#include "db/system_keyspace.hh"
|
||||
#include "partition_slice_builder.hh"
|
||||
#include "readers/combined.hh"
|
||||
@@ -685,7 +684,6 @@ schema_ptr load_system_schema(const db::config& cfg, std::string_view keyspace,
|
||||
{db::system_distributed_keyspace::NAME, db::system_distributed_keyspace::all_distributed_tables()},
|
||||
{db::system_distributed_keyspace::NAME_EVERYWHERE, db::system_distributed_keyspace::all_everywhere_tables()},
|
||||
};
|
||||
schemas[db::system_auth_keyspace::NAME] = db::system_auth_keyspace::all_tables();
|
||||
auto ks_it = schemas.find(keyspace);
|
||||
if (ks_it == schemas.end()) {
|
||||
throw std::invalid_argument(fmt::format("unknown system keyspace: {}", keyspace));
|
||||
|
||||
@@ -45,7 +45,6 @@ future<schema_ptr> load_one_schema_from_file(const db::config& dbcfg, std::files
|
||||
/// Note that only schemas from builtin system tables are supported, i.e.,
|
||||
/// from the following keyspaces:
|
||||
/// * system
|
||||
/// * system_auth_v2
|
||||
/// * system_schema
|
||||
/// * system_distributed
|
||||
/// * system_distributed_everywhere
|
||||
|
||||
Reference in New Issue
Block a user