#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "common/kv/ITransaction.h" #include "common/utils/Coroutine.h" #include "common/utils/Result.h" #include "common/utils/StatusCode.h" #include "common/utils/UtcTime.h" #include "core/user/UserStore.h" #include "fbs/meta/Schema.h" #include "fbs/storage/Common.h" #include "gtest/gtest.h" #include "meta/components/SessionManager.h" #include "meta/store/Inode.h" #include "meta/store/MetaStore.h" #include "tests/GtestHelpers.h" #include "tests/meta/MetaTestBase.h" namespace hf3fs::meta::server { namespace { template class TestAuth : public MetaTestBase {}; using KVTypes = ::testing::Types; TYPED_TEST_SUITE(TestAuth, KVTypes); TYPED_TEST(TestAuth, Basic) { folly::coro::blockingWait([&]() -> CoTask { MockCluster::Config config; config.mock_meta().set_authenticate(true); auto cluster = this->createMockCluster(config); auto &meta = cluster.meta().getOperator(); flat::Uid rootId(0), aliceId(1), bobId(2), charlieId(3); UserAttr root, alic, bob, charlie; READ_WRITE_TRANSACTION_OK({ core::UserStore userStore; root = (co_await userStore.addUser(*txn, rootId, "root", {}, true)).value(); alic = (co_await userStore.addUser(*txn, aliceId, "alic", {flat::Gid(2), flat::Gid(1001)}, true)).value(); bob = (co_await userStore.addUser(*txn, bobId, "bob", {flat::Gid(1001)}, false)).value(); charlie = (co_await userStore.addUser(*txn, charlieId, "charlie", {}, false)).value(); }); std::vector> succ{ // root & sudoer can auth with any uid that exists {{rootId, root.gid, root.token}, {rootId, root.gid, root.groups, root.token}}, {{aliceId, alic.gid, root.token}, {aliceId, alic.gid, alic.groups, root.token}}, {{bobId, bob.gid, root.token}, {bobId, bob.gid, bob.groups, root.token}}, {{bobId, charlie.gid, root.token}, {bobId, charlie.gid, bob.groups, root.token}}, {{rootId, root.gid, alic.token}, {rootId, root.gid, root.groups, alic.token}}, {{aliceId, alic.gid, alic.token}, {aliceId, alic.gid, alic.groups, alic.token}}, {{bobId, bob.gid, alic.token}, {bobId, bob.gid, bob.groups, alic.token}}, {{bobId, charlie.gid, alic.token}, {bobId, charlie.gid, bob.groups, alic.token}}, // other user can only auth with self uid and gid {{bobId, bob.gid, bob.token}, {bobId, bob.gid, bob.groups, bob.token}}, {{charlieId, charlie.gid, charlie.token}, {charlieId, charlie.gid, charlie.groups, charlie.token}}, }; for (auto [req, expected] : succ) { auto result = co_await meta.authenticate(AuthReq(req)); CO_ASSERT_OK(result); const auto &actual = result->user; CO_ASSERT_EQ(actual, expected) << fmt::format("{} vs {}; ", actual, expected) << fmt::format("{} vs {}", fmt::join(actual.groups.begin(), actual.groups.end(), ","), fmt::join(expected.groups.begin(), expected.groups.end(), ",")); } std::vector fail{// don't allow unknown uid {flat::Uid(999), flat::Gid(0), root.token}, {flat::Uid(1024), flat::Gid(0), root.token}, // other user can only auth with self uid and gid {bobId, charlie.gid, bob.token}, {charlieId, bob.gid, bob.token}, {charlieId, bob.gid, charlie.token}, {bobId, charlie.gid, charlie.token}, // invalid token {bobId, bob.gid, ""}}; for (const auto &req : fail) { fmt::print("{}\n", req); auto result = co_await meta.authenticate(AuthReq(req)); CO_ASSERT_ERROR(result, StatusCode::kAuthenticationFail); } }()); } } // namespace } // namespace hf3fs::meta::server