diff --git a/auth/authentication_options.hh b/auth/authentication_options.hh index 8edfa151ea..ae9fe2bdf6 100644 --- a/auth/authentication_options.hh +++ b/auth/authentication_options.hh @@ -23,9 +23,11 @@ #include #include +#include #include #include +#include #include #include "seastarx.hh" @@ -50,4 +52,11 @@ inline bool any_authentication_options(const authentication_options& aos) noexce return aos.password || aos.options; } +class unsupported_authentication_option : public std::invalid_argument { +public: + explicit unsupported_authentication_option(authentication_option k) + : std::invalid_argument(sprint("The %s option is not supported.", k)) { + } +}; + } diff --git a/auth/service.cc b/auth/service.cc index 7cda72f2d1..f133c90931 100644 --- a/auth/service.cc +++ b/auth/service.cc @@ -291,6 +291,25 @@ bool is_enforcing(const service& ser) { return enforcing_authorizer || enforcing_authenticator; } +static void validate_authentication_options_are_supported( + const authentication_options& options, + const authentication_option_set& supported) { + const auto check = [&supported](authentication_option k) { + if (supported.count(k) == 0) { + throw unsupported_authentication_option(k); + } + }; + + if (options.password) { + check(authentication_option::password); + } + + if (options.options) { + check(authentication_option::options); + } +} + + future<> create_role( service& ser, const authenticated_user& performer, @@ -305,11 +324,14 @@ future<> create_role( return make_ready_future<>(); } - return ser.underlying_authenticator().create( - sstring(name), - options).handle_exception([&ser, &performer, &name](std::exception_ptr ep) { - // Roll-back. - return ser.underlying_role_manager().drop(performer, name).then([ep = std::move(ep)] { + return futurize_apply( + &validate_authentication_options_are_supported, + options, + ser.underlying_authenticator().supported_options()).then([&ser, name, &options] { + return ser.underlying_authenticator().create(sstring(name), options); + }).handle_exception([&ser, &performer, &name](std::exception_ptr ep) { + // Roll-back. + return ser.underlying_role_manager().drop(performer, name).then([ep = std::move(ep)] { std::rethrow_exception(ep); }); }); @@ -327,7 +349,12 @@ future<> alter_role( return make_ready_future<>(); } - return ser.underlying_authenticator().alter(sstring(name), options); + return futurize_apply( + &validate_authentication_options_are_supported, + options, + ser.underlying_authenticator().supported_options()).then([&ser, name, &options] { + return ser.underlying_authenticator().alter(sstring(name), options); + }); }); } diff --git a/auth/service.hh b/auth/service.hh index 0296014a03..3469e7bbae 100644 --- a/auth/service.hh +++ b/auth/service.hh @@ -183,6 +183,8 @@ bool is_enforcing(const service&); /// /// \returns an exceptional future with \ref role_already_exists if the user or role exists. /// +/// \returns an exceptional future with \ref unsupported_authentication_option if an unsupported option is included. +/// future<> create_role( service&, const authenticated_user& performer, @@ -195,6 +197,8 @@ future<> create_role( /// /// \returns an exceptional future with \ref nonexistant_role if the named role does not exist. /// +/// \returns an exceptional future with \ref unsupported_authentication_option if an unsupported option is included. +/// future<> alter_role( service&, const authenticated_user& performer, diff --git a/cql3/statements/role-management-statements.cc b/cql3/statements/role-management-statements.cc index 2b7c7991db..7e252b2ab5 100644 --- a/cql3/statements/role-management-statements.cc +++ b/cql3/statements/role-management-statements.cc @@ -122,6 +122,8 @@ create_role_statement::execute(distributed&, } return void_result_message(); + }).handle_exception_type([](const auth::unsupported_authentication_option& e) { + return make_exception_future(exceptions::invalid_request_exception(e.what())); }); }); } @@ -192,6 +194,8 @@ alter_role_statement::execute(distributed&, service::que return void_result_message(); }).handle_exception_type([](const auth::roles_argument_exception& e) { return make_exception_future(exceptions::invalid_request_exception(e.what())); + }).handle_exception_type([](const auth::unsupported_authentication_option& e) { + return make_exception_future(exceptions::invalid_request_exception(e.what())); }); }); }