We introduce a way to create a role with explictly provided salted hash. The algorithm for creating a role with a password works like this: 1. The user issues a statement `CREATE ROLE <role> WITH PASSWORD = '<password>' <...>`. 2. Scylla produces a hash based on the value of `<password>`. 3. Scylla puts the produced hash in `system.roles`, in the column `salted_hash`. The newly introduced way to create a role is based on a new form of the create statement: `CREATE ROLE <role> WITH SALTED HASH = '<salted_hash>` The difference in the algorithm used for processing this statement is that we insert `<salted_hash>` into `system.roles` directly, without hashing it. The rationale for introducing this new statement is that we want to be able to restore roles. The original password isn't stored anywhere in the database (as intended), so we need to rely on the column `salted_hash`.
81 lines
1.8 KiB
C++
81 lines
1.8 KiB
C++
/*
|
|
* Copyright (C) 2018-present ScyllaDB
|
|
*/
|
|
|
|
/*
|
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <optional>
|
|
#include <stdexcept>
|
|
#include <unordered_map>
|
|
#include <unordered_set>
|
|
#include <variant>
|
|
|
|
#include <seastar/core/print.hh>
|
|
#include <seastar/core/sstring.hh>
|
|
|
|
#include "seastarx.hh"
|
|
|
|
namespace auth {
|
|
|
|
enum class authentication_option {
|
|
password,
|
|
salted_hash,
|
|
options
|
|
};
|
|
|
|
}
|
|
|
|
template <>
|
|
struct fmt::formatter<auth::authentication_option> : fmt::formatter<string_view> {
|
|
template <typename FormatContext>
|
|
auto format(const auth::authentication_option a, FormatContext& ctx) const {
|
|
using enum auth::authentication_option;
|
|
switch (a) {
|
|
case password:
|
|
return formatter<string_view>::format("PASSWORD", ctx);
|
|
case salted_hash:
|
|
return formatter<string_view>::format("SALTED HASH", ctx);
|
|
case options:
|
|
return formatter<string_view>::format("OPTIONS", ctx);
|
|
}
|
|
std::abort();
|
|
}
|
|
};
|
|
|
|
namespace auth {
|
|
|
|
using authentication_option_set = std::unordered_set<authentication_option>;
|
|
|
|
using custom_options = std::unordered_map<sstring, sstring>;
|
|
|
|
struct password_option {
|
|
sstring password;
|
|
};
|
|
|
|
/// Used exclusively for restoring roles.
|
|
struct salted_hash_option {
|
|
sstring salted_hash;
|
|
};
|
|
|
|
struct authentication_options final {
|
|
std::optional<std::variant<password_option, salted_hash_option>> credentials;
|
|
std::optional<custom_options> options;
|
|
};
|
|
|
|
inline bool any_authentication_options(const authentication_options& aos) noexcept {
|
|
return aos.options || aos.credentials;
|
|
}
|
|
|
|
class unsupported_authentication_option : public std::invalid_argument {
|
|
public:
|
|
explicit unsupported_authentication_option(authentication_option k)
|
|
: std::invalid_argument(format("The {} option is not supported.", k)) {
|
|
}
|
|
};
|
|
|
|
}
|