mirror of
https://github.com/scylladb/scylladb.git
synced 2026-04-22 01:20:39 +00:00
S3 client cannot perform anonymous multipart uploads into any real S3 buckets regardless of their configuration. Since multipart upload is essential part of the sstables backend, we need to implement the authorisation support for the client early. (side note): with minio anonymous multipart upload works, with aws s3 anonymous PUT and DELETE can be configured, it's exactly the combination of aws + multipart upload that does need authorization. Fortunately, the signature generation and signature checking code is symmetrical and we have the checking option already in alternator :) So what this patch does is just moves the alternator::get_signature() helper into utils/. A sad side effect of that is all tests now need to link with gnutls :( that is used to compute the hash value itself. Signed-off-by: Pavel Emelyanov <xemul@scylladb.com> Closes #13428
64 lines
3.0 KiB
C++
64 lines
3.0 KiB
C++
/*
|
|
* Copyright 2019-present ScyllaDB
|
|
*/
|
|
|
|
/*
|
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
|
*/
|
|
|
|
#include "alternator/error.hh"
|
|
#include "log.hh"
|
|
#include <string>
|
|
#include <string_view>
|
|
#include "bytes.hh"
|
|
#include "alternator/auth.hh"
|
|
#include <fmt/format.h>
|
|
#include "auth/common.hh"
|
|
#include "auth/password_authenticator.hh"
|
|
#include "auth/roles-metadata.hh"
|
|
#include "service/storage_proxy.hh"
|
|
#include "alternator/executor.hh"
|
|
#include "cql3/selection/selection.hh"
|
|
#include "query-result-set.hh"
|
|
#include "cql3/result_set.hh"
|
|
#include <seastar/core/coroutine.hh>
|
|
|
|
namespace alternator {
|
|
|
|
static logging::logger alogger("alternator-auth");
|
|
|
|
future<std::string> get_key_from_roles(service::storage_proxy& proxy, std::string username) {
|
|
schema_ptr schema = proxy.data_dictionary().find_schema("system_auth", "roles");
|
|
partition_key pk = partition_key::from_single_value(*schema, utf8_type->decompose(username));
|
|
dht::partition_range_vector partition_ranges{dht::partition_range(dht::decorate_key(*schema, pk))};
|
|
std::vector<query::clustering_range> bounds{query::clustering_range::make_open_ended_both_sides()};
|
|
const column_definition* salted_hash_col = schema->get_column_definition(bytes("salted_hash"));
|
|
if (!salted_hash_col) {
|
|
co_await coroutine::return_exception(api_error::unrecognized_client(format("Credentials cannot be fetched for: {}", username)));
|
|
}
|
|
auto selection = cql3::selection::selection::for_columns(schema, {salted_hash_col});
|
|
auto partition_slice = query::partition_slice(std::move(bounds), {}, query::column_id_vector{salted_hash_col->id}, selection->get_query_options());
|
|
auto command = ::make_lw_shared<query::read_command>(schema->id(), schema->version(), partition_slice,
|
|
proxy.get_max_result_size(partition_slice), query::tombstone_limit(proxy.get_tombstone_limit()));
|
|
auto cl = auth::password_authenticator::consistency_for_user(username);
|
|
|
|
service::client_state client_state{service::client_state::internal_tag()};
|
|
service::storage_proxy::coordinator_query_result qr = co_await proxy.query(schema, std::move(command), std::move(partition_ranges), cl,
|
|
service::storage_proxy::coordinator_query_options(executor::default_timeout(), empty_service_permit(), client_state));
|
|
|
|
cql3::selection::result_set_builder builder(*selection, gc_clock::now());
|
|
query::result_view::consume(*qr.query_result, partition_slice, cql3::selection::result_set_builder::visitor(builder, *schema, *selection));
|
|
|
|
auto result_set = builder.build();
|
|
if (result_set->empty()) {
|
|
co_await coroutine::return_exception(api_error::unrecognized_client(format("User not found: {}", username)));
|
|
}
|
|
const bytes_opt& salted_hash = result_set->rows().front().front(); // We only asked for 1 row and 1 column
|
|
if (!salted_hash) {
|
|
co_await coroutine::return_exception(api_error::unrecognized_client(format("No password found for user: {}", username)));
|
|
}
|
|
co_return value_cast<sstring>(utf8_type->deserialize(*salted_hash));
|
|
}
|
|
|
|
}
|