/* * Copyright (C) 2016 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 . */ #include #include #include #include #include #include #include #include #include #include "test/lib/cql_test_env.hh" #include "test/lib/cql_assertions.hh" #include "auth/allow_all_authenticator.hh" #include "auth/authenticator.hh" #include "auth/password_authenticator.hh" #include "auth/service.hh" #include "auth/authenticated_user.hh" #include "auth/resource.hh" #include "db/config.hh" #include "cql3/query_processor.hh" SEASTAR_TEST_CASE(test_default_authenticator) { return do_with_cql_env([](cql_test_env& env) { auto& a = env.local_auth_service().underlying_authenticator(); BOOST_REQUIRE(!a.require_authentication()); BOOST_REQUIRE_EQUAL(a.qualified_java_name(), auth::allow_all_authenticator_name()); return make_ready_future(); }); } SEASTAR_TEST_CASE(test_password_authenticator_attributes) { auto cfg = make_shared(); cfg->authenticator(auth::password_authenticator_name()); return do_with_cql_env([](cql_test_env& env) { auto& a = env.local_auth_service().underlying_authenticator(); BOOST_REQUIRE(a.require_authentication()); BOOST_REQUIRE_EQUAL(a.qualified_java_name(), auth::password_authenticator_name()); return make_ready_future(); }, cfg); } static future authenticate(cql_test_env& env, std::string_view username, std::string_view password) { auto& c = env.local_client_state(); auto& a = env.local_auth_service().underlying_authenticator(); return do_with( auth::authenticator::credentials_map{ {auth::authenticator::USERNAME_KEY, sstring(username)}, {auth::authenticator::PASSWORD_KEY, sstring(password)}}, [&a, &c, username](const auto& credentials) { return a.authenticate(credentials).then([&c, username](auth::authenticated_user u) { c.set_login(std::move(u)); return c.check_user_can_login().then([&c] { return *c.user(); }); }); }); } template future<> require_throws(seastar::future fut) { return fut.then_wrapped([](auto completed_fut) { try { completed_fut.get(); BOOST_FAIL("Required an exception to be thrown"); } catch (const Exception&) { // Ok. } }); } SEASTAR_TEST_CASE(test_password_authenticator_operations) { auto cfg = make_shared(); cfg->authenticator(auth::password_authenticator_name()); /** * Not using seastar::async due to apparent ASan bug. * Enjoy the slightly less readable code. */ return do_with_cql_env([](cql_test_env& env) { static const sstring username("fisk"); static const sstring password("notter"); // check non-existing user return require_throws( authenticate(env, username, password)).then([&env] { return do_with(auth::role_config{}, auth::authentication_options{}, [&env](auto& config, auto& options) { config.can_login = true; options.password = password; return auth::create_role(env.local_auth_service(), username, config, options).then([&env] { return authenticate(env, username, password).then([](auth::authenticated_user user) { BOOST_REQUIRE(!auth::is_anonymous(user)); BOOST_REQUIRE_EQUAL(*user.name, username); }); }); }); }).then([&env] { return require_throws(authenticate(env, username, "hejkotte")); }).then([&env] { // // A role must be explicitly marked as being allowed to log in. // return do_with( auth::role_config_update{}, auth::authentication_options{}, [&env](auto& config_update, const auto& options) { config_update.can_login = false; return auth::alter_role(env.local_auth_service(), username, config_update, options).then([&env] { return require_throws(authenticate(env, username, password)); }); }); }).then([&env] { // sasl auto& a = env.local_auth_service().underlying_authenticator(); auto sasl = a.new_sasl_challenge(); BOOST_REQUIRE(!sasl->is_complete()); bytes b; int8_t i = 0; b.append(&i, 1); b.insert(b.end(), username.begin(), username.end()); b.append(&i, 1); b.insert(b.end(), password.begin(), password.end()); sasl->evaluate_response(b); BOOST_REQUIRE(sasl->is_complete()); return sasl->get_authenticated_user().then([](auth::authenticated_user user) { BOOST_REQUIRE(!auth::is_anonymous(user)); BOOST_REQUIRE_EQUAL(*user.name, username); }); }).then([&env] { // check deleted user return auth::drop_role(env.local_auth_service(), username).then([&env] { return require_throws(authenticate(env, username, password)); }); }); }, cfg); }