From 4c9d377816970b92dfa4bfe52024eebb625b560a Mon Sep 17 00:00:00 2001 From: badaix Date: Mon, 10 Feb 2025 22:03:34 +0100 Subject: [PATCH] Update auth configi and tests --- server/server_settings.hpp | 31 ++++++++++++++++++ server/snapserver.cpp | 34 ++++++-------------- test/test_main.cpp | 65 ++++++++++++++++++++++++++++---------- 3 files changed, 89 insertions(+), 41 deletions(-) diff --git a/server/server_settings.hpp b/server/server_settings.hpp index e229445c..fe6dd2f1 100644 --- a/server/server_settings.hpp +++ b/server/server_settings.hpp @@ -20,9 +20,11 @@ // local headers +#include "common/snap_exception.hpp" #include "common/utils/string_utils.hpp" // standard headers +#include #include #include #include @@ -71,6 +73,35 @@ struct ServerSettings /// Authorization settings struct Authorization { + /// c'tor + Authorization() = default; + + /// c'tor + Authorization(const std::vector& conf_roles, const std::vector& conf_users) + { + for (const auto& role : conf_roles) + roles.emplace_back(std::make_shared(role)); + + auto empty_role = std::make_shared(); + for (const auto& conf_user : conf_users) + { + users.emplace_back(conf_user); + ServerSettings::Authorization::User& user = users.back(); + if (user.role_name.empty()) + { + user.role = empty_role; + } + else + { + const auto& role_iter = std::find_if(roles.begin(), roles.end(), [&](const auto& role) { return role->role == user.role_name; }); + if (role_iter != roles.end()) + user.role = *role_iter; + } + if (user.role == nullptr) + throw SnapException("Role '" + user.role_name + "' for user '" + user.name + "' not found"); + } + } + /// Role settings struct Role { diff --git a/server/snapserver.cpp b/server/snapserver.cpp index 25446010..e9ffdc1c 100644 --- a/server/snapserver.cpp +++ b/server/snapserver.cpp @@ -324,34 +324,20 @@ int main(int argc, char* argv[]) if (settings.auth.enabled) { + std::vector roles; for (size_t n = 0; n < roles_value->count(); ++n) - { - settings.auth.roles.emplace_back(std::make_shared(roles_value->value(n))); - const auto& role = settings.auth.roles.back(); - LOG(DEBUG, LOG_TAG) << "Role: " << role->role << ", permissions: " << utils::string::container_to_string(role->permissions) << "\n"; - } - - auto empty_role = std::make_shared(); + roles.push_back(roles_value->value(n)); + std::vector users; for (size_t n = 0; n < users_value->count(); ++n) - { - settings.auth.users.emplace_back(users_value->value(n)); - ServerSettings::Authorization::User& user = settings.auth.users.back(); - if (user.role_name.empty()) - { - user.role = empty_role; - } - else - { - const auto& role_iter = - find_if(settings.auth.roles.begin(), settings.auth.roles.end(), [&](const auto& role) { return role->role == user.role_name; }); - if (role_iter != settings.auth.roles.end()) - user.role = *role_iter; - } - if (user.role == nullptr) - throw SnapException("Role '" + user.role_name + "' for user '" + user.name + "' not found"); + users.push_back(users_value->value(n)); + settings.auth = ServerSettings::Authorization(roles, users); + + + for (const auto& role : settings.auth.roles) + LOG(DEBUG, LOG_TAG) << "Role: " << role->role << ", permissions: " << utils::string::container_to_string(role->permissions) << "\n"; + for (const auto& user : settings.auth.users) LOG(DEBUG, LOG_TAG) << "User: " << user.name << ", pw: " << user.password << ", role: " << user.role_name << "\n"; - } } #ifdef HAS_DAEMON diff --git a/test/test_main.cpp b/test/test_main.cpp index 7d608e06..053f74d0 100644 --- a/test/test_main.cpp +++ b/test/test_main.cpp @@ -19,10 +19,13 @@ // prototype/interface header file // local headers +#include "common/base64.h" #include "common/error_code.hpp" #include "common/stream_uri.hpp" #include "common/utils/string_utils.hpp" // #include "server/jwt.hpp" +#include "server/authinfo.hpp" +#include "server/server_settings.hpp" #include "server/streamreader/control_error.hpp" #include "server/streamreader/properties.hpp" @@ -30,6 +33,7 @@ #include // standard headers +#include #include #include #include @@ -717,17 +721,19 @@ TEST_CASE("WildcardMatch") REQUIRE(!wildcardMatch("*get*erver*", "Server.getToken")); } -#if 0 + TEST_CASE("Auth") { { - ServerSettings settings; - ServerSettings::User user("badaix:*:secret"); - REQUIRE(user.permissions.size() == 1); - REQUIRE(user.permissions[0] == "*"); - settings.users.push_back(user); + ServerSettings::Authorization auth_settings({"admin:*"}, {"badaix:secret:admin"}); + auth_settings.enabled = true; + REQUIRE(auth_settings.users.size() == 1); + REQUIRE(auth_settings.roles.size() == 1); + REQUIRE(auth_settings.users.front().role->role == "admin"); + REQUIRE(auth_settings.users.front().role->permissions.size() == 1); + REQUIRE(auth_settings.users.front().role->permissions.front() == "*"); - AuthInfo auth(settings); + AuthInfo auth(auth_settings); auto ec = auth.authenticateBasic(base64_encode("badaix:secret")); REQUIRE(!ec); REQUIRE(auth.isAuthenticated()); @@ -735,12 +741,14 @@ TEST_CASE("Auth") } { - ServerSettings settings; - ServerSettings::User user("badaix::secret"); - REQUIRE(user.permissions.empty()); - settings.users.push_back(user); + ServerSettings::Authorization auth_settings({"admin:"}, {"badaix:secret:admin"}); + auth_settings.enabled = true; + REQUIRE(auth_settings.users.size() == 1); + REQUIRE(auth_settings.roles.size() == 1); + REQUIRE(auth_settings.users.front().role->role == "admin"); + REQUIRE(auth_settings.users.front().role->permissions.empty()); - AuthInfo auth(settings); + AuthInfo auth(auth_settings); auto ec = auth.authenticateBasic(base64_encode("badaix:secret")); REQUIRE(!ec); REQUIRE(auth.isAuthenticated()); @@ -748,11 +756,29 @@ TEST_CASE("Auth") } { - ServerSettings settings; - ServerSettings::User user("badaix:*:secret"); - settings.users.push_back(user); + ServerSettings::Authorization auth_settings({}, {"badaix:secret:"}); + auth_settings.enabled = true; + REQUIRE(auth_settings.users.size() == 1); + REQUIRE(auth_settings.roles.empty()); + REQUIRE(auth_settings.users.front().role->permissions.empty()); - AuthInfo auth(settings); + AuthInfo auth(auth_settings); + auto ec = auth.authenticateBasic(base64_encode("badaix:secret")); + REQUIRE(!ec); + REQUIRE(auth.isAuthenticated()); + REQUIRE(!auth.hasPermission("stream")); + } + + { + ServerSettings::Authorization auth_settings({"admin:xxx,stream"}, {"badaix:secret:admin"}); + auth_settings.enabled = true; + REQUIRE(auth_settings.users.size() == 1); + REQUIRE(auth_settings.roles.size() == 1); + REQUIRE(auth_settings.users.front().role->permissions.size() == 2); + REQUIRE(auth_settings.users.front().role->permissions[0] == "xxx"); + REQUIRE(auth_settings.users.front().role->permissions[1] == "stream"); + + AuthInfo auth(auth_settings); auto ec = auth.authenticateBasic(base64_encode("badaix:wrong_password")); REQUIRE(ec == AuthErrc::wrong_password); REQUIRE(!auth.isAuthenticated()); @@ -762,6 +788,11 @@ TEST_CASE("Auth") REQUIRE(ec == AuthErrc::unknown_user); REQUIRE(!auth.isAuthenticated()); REQUIRE(!auth.hasPermission("stream")); + + ec = auth.authenticateBasic(base64_encode("badaix:secret")); + REQUIRE(!ec); + REQUIRE(auth.isAuthenticated()); + REQUIRE(auth.hasPermission("stream")); + REQUIRE(!auth.hasPermission("play")); } } -#endif