blob: 40751e9834fa76e7c297fe9ae1a0180a0ad2bc8d [file] [log] [blame]
raviteja-b8cc44052019-02-27 23:29:36 -06001#include "mock_user_mgr.hpp"
Nan Zhoue47c09d2022-10-25 00:06:41 +00002#include "user_mgr.hpp"
Patrick Williams9638afb2021-02-22 17:16:24 -06003
Ravi Teja417c0892020-08-22 08:04:01 -05004#include <sdbusplus/test/sdbus_mock.hpp>
Patrick Williams9638afb2021-02-22 17:16:24 -06005#include <xyz/openbmc_project/Common/error.hpp>
6#include <xyz/openbmc_project/User/Common/error.hpp>
7
8#include <exception>
Nan Zhoue48085d2022-10-25 00:07:04 +00009#include <filesystem>
10#include <fstream>
Nan Zhouda401fe2022-10-25 00:07:18 +000011#include <vector>
Patrick Williams9638afb2021-02-22 17:16:24 -060012
Nan Zhouda401fe2022-10-25 00:07:18 +000013#include <gmock/gmock.h>
Patrick Williams9638afb2021-02-22 17:16:24 -060014#include <gtest/gtest.h>
raviteja-b8cc44052019-02-27 23:29:36 -060015
16namespace phosphor
17{
18namespace user
19{
20
21using ::testing::Return;
Alexander Filippov75626582022-02-09 18:42:37 +030022using ::testing::Throw;
raviteja-b8cc44052019-02-27 23:29:36 -060023
24using InternalFailure =
25 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
Alexander Filippov75626582022-02-09 18:42:37 +030026using UserNameDoesNotExist =
27 sdbusplus::xyz::openbmc_project::User::Common::Error::UserNameDoesNotExist;
raviteja-b8cc44052019-02-27 23:29:36 -060028
29class TestUserMgr : public testing::Test
30{
31 public:
Nan Zhou78d85042022-08-29 17:50:22 +000032 sdbusplus::SdBusMock sdBusMock;
Patrick Williamsb3ef4e12022-07-22 19:26:55 -050033 sdbusplus::bus_t bus;
raviteja-b8cc44052019-02-27 23:29:36 -060034 MockManager mockManager;
35
36 TestUserMgr() :
Nan Zhou78d85042022-08-29 17:50:22 +000037 bus(sdbusplus::get_mocked_new(&sdBusMock)), mockManager(bus, objpath)
Patrick Williams9638afb2021-02-22 17:16:24 -060038 {}
raviteja-b8cc44052019-02-27 23:29:36 -060039
Patrick Williams9638afb2021-02-22 17:16:24 -060040 void createLocalUser(const std::string& userName,
raviteja-b8cc44052019-02-27 23:29:36 -060041 std::vector<std::string> groupNames,
Patrick Williams9638afb2021-02-22 17:16:24 -060042 const std::string& priv, bool enabled)
raviteja-b8cc44052019-02-27 23:29:36 -060043 {
P Dheeraj Srujan Kumarb01e2fe2021-12-13 09:43:28 +053044 sdbusplus::message::object_path tempObjPath(usersObjPath);
45 tempObjPath /= userName;
46 std::string userObj(tempObjPath);
raviteja-b8cc44052019-02-27 23:29:36 -060047 mockManager.usersList.emplace(
Nan Zhou78d85042022-08-29 17:50:22 +000048 userName, std::make_unique<phosphor::user::Users>(
raviteja-b8cc44052019-02-27 23:29:36 -060049 mockManager.bus, userObj.c_str(), groupNames, priv,
Nan Zhou78d85042022-08-29 17:50:22 +000050 enabled, mockManager));
raviteja-b8cc44052019-02-27 23:29:36 -060051 }
52
53 DbusUserObj createPrivilegeMapperDbusObject(void)
54 {
55 DbusUserObj object;
56 DbusUserObjValue objValue;
Ravi Teja5fe724a2019-05-07 05:14:42 -050057
Nan Zhou78d85042022-08-29 17:50:22 +000058 DbusUserObjPath objPath("/xyz/openbmc_project/user/ldap/openldap");
Ravi Teja5fe724a2019-05-07 05:14:42 -050059 DbusUserPropVariant enabled(true);
60 DbusUserObjProperties property = {std::make_pair("Enabled", enabled)};
61 std::string intf = "xyz.openbmc_project.Object.Enable";
62 objValue.emplace(intf, property);
Nan Zhou78d85042022-08-29 17:50:22 +000063 object.emplace(objPath, objValue);
Ravi Teja5fe724a2019-05-07 05:14:42 -050064
Nan Zhou78d85042022-08-29 17:50:22 +000065 DbusUserObjPath objectPath(
Ravi Teja5fe724a2019-05-07 05:14:42 -050066 "/xyz/openbmc_project/user/ldap/openldap/role_map/1");
67 std::string group = "ldapGroup";
68 std::string priv = "priv-admin";
raviteja-b8cc44052019-02-27 23:29:36 -060069 DbusUserObjProperties properties = {std::make_pair("GroupName", group),
70 std::make_pair("Privilege", priv)};
71 std::string interface = "xyz.openbmc_project.User.PrivilegeMapperEntry";
72
73 objValue.emplace(interface, properties);
Nan Zhou78d85042022-08-29 17:50:22 +000074 object.emplace(objectPath, objValue);
raviteja-b8cc44052019-02-27 23:29:36 -060075
76 return object;
77 }
Ravi Teja5fe724a2019-05-07 05:14:42 -050078
79 DbusUserObj createLdapConfigObjectWithoutPrivilegeMapper(void)
80 {
81 DbusUserObj object;
82 DbusUserObjValue objValue;
83
Nan Zhou78d85042022-08-29 17:50:22 +000084 DbusUserObjPath objPath("/xyz/openbmc_project/user/ldap/openldap");
Ravi Teja5fe724a2019-05-07 05:14:42 -050085 DbusUserPropVariant enabled(true);
86 DbusUserObjProperties property = {std::make_pair("Enabled", enabled)};
87 std::string intf = "xyz.openbmc_project.Object.Enable";
88 objValue.emplace(intf, property);
Nan Zhou78d85042022-08-29 17:50:22 +000089 object.emplace(objPath, objValue);
Ravi Teja5fe724a2019-05-07 05:14:42 -050090 return object;
91 }
raviteja-b8cc44052019-02-27 23:29:36 -060092};
93
94TEST_F(TestUserMgr, ldapEntryDoesNotExist)
95{
96 std::string userName = "user";
97 UserInfoMap userInfo;
98
Alexander Filippov75626582022-02-09 18:42:37 +030099 EXPECT_CALL(mockManager, getPrimaryGroup(userName))
100 .WillRepeatedly(Throw(UserNameDoesNotExist()));
101 EXPECT_THROW(userInfo = mockManager.getUserInfo(userName),
102 UserNameDoesNotExist);
raviteja-b8cc44052019-02-27 23:29:36 -0600103}
104
105TEST_F(TestUserMgr, localUser)
106{
107 UserInfoMap userInfo;
108 std::string userName = "testUser";
109 std::string privilege = "priv-admin";
110 std::vector<std::string> groups{"testGroup"};
111 // Create local user
112 createLocalUser(userName, groups, privilege, true);
113 EXPECT_CALL(mockManager, userLockedForFailedAttempt(userName)).Times(1);
114 userInfo = mockManager.getUserInfo(userName);
115
116 EXPECT_EQ(privilege, std::get<std::string>(userInfo["UserPrivilege"]));
117 EXPECT_EQ(groups,
118 std::get<std::vector<std::string>>(userInfo["UserGroups"]));
119 EXPECT_EQ(true, std::get<bool>(userInfo["UserEnabled"]));
120 EXPECT_EQ(false, std::get<bool>(userInfo["UserLockedForFailedAttempt"]));
Joseph Reynolds3ab6cc22020-03-03 14:09:03 -0600121 EXPECT_EQ(false, std::get<bool>(userInfo["UserPasswordExpired"]));
raviteja-b8cc44052019-02-27 23:29:36 -0600122 EXPECT_EQ(false, std::get<bool>(userInfo["RemoteUser"]));
123}
124
125TEST_F(TestUserMgr, ldapUserWithPrivMapper)
126{
127 UserInfoMap userInfo;
128 std::string userName = "ldapUser";
129 std::string ldapGroup = "ldapGroup";
Alexander Filippov75626582022-02-09 18:42:37 +0300130 gid_t primaryGid = 1000;
raviteja-b8cc44052019-02-27 23:29:36 -0600131
Alexander Filippov75626582022-02-09 18:42:37 +0300132 EXPECT_CALL(mockManager, getPrimaryGroup(userName))
133 .WillRepeatedly(Return(primaryGid));
raviteja-b8cc44052019-02-27 23:29:36 -0600134 // Create privilege mapper dbus object
135 DbusUserObj object = createPrivilegeMapperDbusObject();
136 EXPECT_CALL(mockManager, getPrivilegeMapperObject())
137 .WillRepeatedly(Return(object));
Alexander Filippov75626582022-02-09 18:42:37 +0300138 EXPECT_CALL(mockManager, isGroupMember(userName, primaryGid, ldapGroup))
139 .WillRepeatedly(Return(true));
raviteja-b8cc44052019-02-27 23:29:36 -0600140 userInfo = mockManager.getUserInfo(userName);
141 EXPECT_EQ(true, std::get<bool>(userInfo["RemoteUser"]));
142 EXPECT_EQ("priv-admin", std::get<std::string>(userInfo["UserPrivilege"]));
143}
144
145TEST_F(TestUserMgr, ldapUserWithoutPrivMapper)
146{
Alexander Filippov75626582022-02-09 18:42:37 +0300147 using ::testing::_;
148
raviteja-b8cc44052019-02-27 23:29:36 -0600149 UserInfoMap userInfo;
150 std::string userName = "ldapUser";
151 std::string ldapGroup = "ldapGroup";
Alexander Filippov75626582022-02-09 18:42:37 +0300152 gid_t primaryGid = 1000;
raviteja-b8cc44052019-02-27 23:29:36 -0600153
Alexander Filippov75626582022-02-09 18:42:37 +0300154 EXPECT_CALL(mockManager, getPrimaryGroup(userName))
155 .WillRepeatedly(Return(primaryGid));
Ravi Teja5fe724a2019-05-07 05:14:42 -0500156 // Create LDAP config object without privilege mapper
157 DbusUserObj object = createLdapConfigObjectWithoutPrivilegeMapper();
raviteja-b8cc44052019-02-27 23:29:36 -0600158 EXPECT_CALL(mockManager, getPrivilegeMapperObject())
159 .WillRepeatedly(Return(object));
Alexander Filippov75626582022-02-09 18:42:37 +0300160 EXPECT_CALL(mockManager, isGroupMember(_, _, _)).Times(0);
raviteja-b8cc44052019-02-27 23:29:36 -0600161 userInfo = mockManager.getUserInfo(userName);
162 EXPECT_EQ(true, std::get<bool>(userInfo["RemoteUser"]));
Jiaqing Zhao56862062022-05-31 19:16:09 +0800163 EXPECT_EQ("priv-user", std::get<std::string>(userInfo["UserPrivilege"]));
raviteja-b8cc44052019-02-27 23:29:36 -0600164}
Nan Zhoue47c09d2022-10-25 00:06:41 +0000165
166TEST(GetCSVFromVector, EmptyVectorReturnsEmptyString)
167{
168 EXPECT_EQ(getCSVFromVector({}), "");
169}
170
171TEST(GetCSVFromVector, ElementsAreJoinedByComma)
172{
173 EXPECT_EQ(getCSVFromVector(std::vector<std::string>{"123"}), "123");
174 EXPECT_EQ(getCSVFromVector(std::vector<std::string>{"123", "456"}),
175 "123,456");
176}
177
Nan Zhou332fb9d2022-10-25 00:07:03 +0000178TEST(RemoveStringFromCSV, WithoutDeleteStringReturnsFalse)
179{
180 std::string expected = "whatever,https";
181 std::string str = expected;
182 EXPECT_FALSE(removeStringFromCSV(str, "ssh"));
183 EXPECT_EQ(str, expected);
184
185 std::string empty;
186 EXPECT_FALSE(removeStringFromCSV(empty, "ssh"));
187}
188
189TEST(RemoveStringFromCSV, WithDeleteStringReturnsTrue)
190{
191 std::string expected = "whatever";
192 std::string str = "whatever,https";
193 EXPECT_TRUE(removeStringFromCSV(str, "https"));
194 EXPECT_EQ(str, expected);
195
196 str = "https";
197 EXPECT_TRUE(removeStringFromCSV(str, "https"));
198 EXPECT_EQ(str, "");
199}
200
Nan Zhoue48085d2022-10-25 00:07:04 +0000201namespace
202{
203inline constexpr const char* objectRootInTest = "/xyz/openbmc_project/user";
204
Jason M. Bills2d042d12023-03-28 15:32:45 -0700205// Fake configs; referenced configs on real BMC
Nan Zhoue48085d2022-10-25 00:07:04 +0000206inline constexpr const char* rawConfig = R"(
207#
208# /etc/pam.d/common-password - password-related modules common to all services
209#
210# This file is included from other service-specific PAM config files,
211# and should contain a list of modules that define the services to be
212# used to change user passwords. The default is pam_unix.
213
214# Explanation of pam_unix options:
215#
216# The "sha512" option enables salted SHA512 passwords. Without this option,
217# the default is Unix crypt. Prior releases used the option "md5".
218#
219# The "obscure" option replaces the old `OBSCURE_CHECKS_ENAB' option in
220# login.defs.
221#
222# See the pam_unix manpage for other options.
223
224# here are the per-package modules (the "Primary" block)
Jason M. Bills2d042d12023-03-28 15:32:45 -0700225password [success=ok default=die] pam_faillock.so authsucc
226password [success=ok default=die] pam_pwquality.so debug
Nan Zhoue48085d2022-10-25 00:07:04 +0000227password [success=ok default=die] pam_ipmicheck.so spec_grp_name=ipmi use_authtok
228password [success=ok ignore=ignore default=die] pam_pwhistory.so debug enforce_for_root remember=0 use_authtok
229password [success=ok default=die] pam_unix.so sha512 use_authtok
230password [success=1 default=die] pam_ipmisave.so spec_grp_name=ipmi spec_pass_file=/etc/ipmi_pass key_file=/etc/key_file
231# here's the fallback if no module succeeds
232password requisite pam_deny.so
233# prime the stack with a positive return value if there isn't one already;
234# this avoids us returning an error just because nothing sets a success code
235# since the modules above will each just jump around
236password required pam_permit.so
237# and here are more per-package modules (the "Additional" block)
238)";
Jason M. Bills2d042d12023-03-28 15:32:45 -0700239inline constexpr const char* rawFailLockConfig = R"(
240deny=2
241unlock_time=3
242)";
243inline constexpr const char* rawPWQualityConfig = R"(
244enforce_for_root
245minlen=8
246difok=0
247lcredit=0
248ocredit=0
249dcredit=0
250ucredit=0
251)";
Nan Zhoue48085d2022-10-25 00:07:04 +0000252} // namespace
253
254void dumpStringToFile(const std::string& str, const std::string& filePath)
255{
256 std::ofstream outputFileStream;
257
258 outputFileStream.exceptions(std::ofstream::failbit | std::ofstream::badbit |
259 std::ofstream::eofbit);
260
261 outputFileStream.open(filePath, std::ios::out);
262 outputFileStream << str << "\n" << std::flush;
263 outputFileStream.close();
264}
265
266void removeFile(const std::string& filePath)
267{
268 std::filesystem::remove(filePath);
269}
270
271class UserMgrInTest : public testing::Test, public UserMgr
272{
273 public:
274 UserMgrInTest() : UserMgr(busInTest, objectRootInTest)
275 {
276 tempPamConfigFile = "/tmp/test-data-XXXXXX";
277 mktemp(tempPamConfigFile.data());
278 EXPECT_NO_THROW(dumpStringToFile(rawConfig, tempPamConfigFile));
Jason M. Bills2d042d12023-03-28 15:32:45 -0700279 tempFaillockConfigFile = "/tmp/test-data-XXXXXX";
280 mktemp(tempFaillockConfigFile.data());
281 EXPECT_NO_THROW(
282 dumpStringToFile(rawFailLockConfig, tempFaillockConfigFile));
283 tempPWQualityConfigFile = "/tmp/test-data-XXXXXX";
284 mktemp(tempPWQualityConfigFile.data());
285 EXPECT_NO_THROW(
286 dumpStringToFile(rawPWQualityConfig, tempPWQualityConfigFile));
Nan Zhoue48085d2022-10-25 00:07:04 +0000287 // Set config files to test files
288 pamPasswdConfigFile = tempPamConfigFile;
Jason M. Bills2d042d12023-03-28 15:32:45 -0700289 faillockConfigFile = tempFaillockConfigFile;
290 pwQualityConfigFile = tempPWQualityConfigFile;
Nan Zhou49c81362022-10-25 00:07:08 +0000291
292 ON_CALL(*this, executeUserAdd).WillByDefault(testing::Return());
293
294 ON_CALL(*this, executeUserDelete).WillByDefault(testing::Return());
295
296 ON_CALL(*this, getIpmiUsersCount).WillByDefault(testing::Return(0));
Nan Zhouf25443e2022-10-25 00:07:11 +0000297
298 ON_CALL(*this, executeUserRename).WillByDefault(testing::Return());
Nan Zhoufef63032022-10-25 00:07:12 +0000299
300 ON_CALL(*this, executeUserModify(testing::_, testing::_, testing::_))
301 .WillByDefault(testing::Return());
Nan Zhou6b6f2d82022-10-25 00:07:17 +0000302
303 ON_CALL(*this, executeUserModifyUserEnable)
304 .WillByDefault(testing::Return());
Nan Zhouda401fe2022-10-25 00:07:18 +0000305
306 ON_CALL(*this, executeGroupCreation(testing::_))
307 .WillByDefault(testing::Return());
308
309 ON_CALL(*this, executeGroupDeletion(testing::_))
310 .WillByDefault(testing::Return());
311
312 ON_CALL(*this, executeGroupCreation).WillByDefault(testing::Return());
313
314 ON_CALL(*this, executeGroupDeletion).WillByDefault(testing::Return());
Nan Zhoue48085d2022-10-25 00:07:04 +0000315 }
316
317 ~UserMgrInTest() override
318 {
319 EXPECT_NO_THROW(removeFile(tempPamConfigFile));
Jason M. Bills2d042d12023-03-28 15:32:45 -0700320 EXPECT_NO_THROW(removeFile(tempFaillockConfigFile));
321 EXPECT_NO_THROW(removeFile(tempPWQualityConfigFile));
Nan Zhoue48085d2022-10-25 00:07:04 +0000322 }
323
Nan Zhou49c81362022-10-25 00:07:08 +0000324 MOCK_METHOD(void, executeUserAdd, (const char*, const char*, bool, bool),
325 (override));
326
327 MOCK_METHOD(void, executeUserDelete, (const char*), (override));
328
329 MOCK_METHOD(size_t, getIpmiUsersCount, (), (override));
330
Nan Zhouf25443e2022-10-25 00:07:11 +0000331 MOCK_METHOD(void, executeUserRename, (const char*, const char*),
332 (override));
333
Nan Zhoufef63032022-10-25 00:07:12 +0000334 MOCK_METHOD(void, executeUserModify, (const char*, const char*, bool),
335 (override));
336
Nan Zhou6b6f2d82022-10-25 00:07:17 +0000337 MOCK_METHOD(void, executeUserModifyUserEnable, (const char*, bool),
338 (override));
339
Nan Zhoua2953032022-11-11 21:50:32 +0000340 MOCK_METHOD(std::vector<std::string>, getFailedAttempt, (const char*),
341 (override));
342
Nan Zhouda401fe2022-10-25 00:07:18 +0000343 MOCK_METHOD(void, executeGroupCreation, (const char*), (override));
344
345 MOCK_METHOD(void, executeGroupDeletion, (const char*), (override));
346
Nan Zhoufef63032022-10-25 00:07:12 +0000347 protected:
Nan Zhoue48085d2022-10-25 00:07:04 +0000348 static sdbusplus::bus_t busInTest;
349 std::string tempPamConfigFile;
Jason M. Bills2d042d12023-03-28 15:32:45 -0700350 std::string tempFaillockConfigFile;
351 std::string tempPWQualityConfigFile;
Nan Zhoue48085d2022-10-25 00:07:04 +0000352};
353
354sdbusplus::bus_t UserMgrInTest::busInTest = sdbusplus::bus::new_default();
355
356TEST_F(UserMgrInTest, GetPamModuleArgValueOnSuccess)
357{
Jason M. Bills2d042d12023-03-28 15:32:45 -0700358 std::string remember;
359 EXPECT_EQ(getPamModuleArgValue("pam_pwhistory.so", "remember", remember),
360 0);
361 EXPECT_EQ(remember, "0");
362}
363
364TEST_F(UserMgrInTest, GetPamModuleConfValueOnSuccess)
365{
366 std::string minlen;
367 EXPECT_EQ(getPamModuleConfValue(tempPWQualityConfigFile, "minlen", minlen),
368 0);
369 EXPECT_EQ(minlen, "8");
370 std::string deny;
371 EXPECT_EQ(getPamModuleConfValue(tempFaillockConfigFile, "deny", deny), 0);
372 EXPECT_EQ(deny, "2");
Nan Zhoue48085d2022-10-25 00:07:04 +0000373}
374
375TEST_F(UserMgrInTest, SetPamModuleArgValueOnSuccess)
376{
Jason M. Bills2d042d12023-03-28 15:32:45 -0700377 EXPECT_EQ(setPamModuleArgValue("pam_pwhistory.so", "remember", "1"), 0);
378 std::string remember;
379 EXPECT_EQ(getPamModuleArgValue("pam_pwhistory.so", "remember", remember),
380 0);
381 EXPECT_EQ(remember, "1");
382}
383
384TEST_F(UserMgrInTest, SetPamModuleConfValueOnSuccess)
385{
386 EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
387 0);
388 std::string minlen;
389 EXPECT_EQ(getPamModuleConfValue(tempPWQualityConfigFile, "minlen", minlen),
390 0);
391 EXPECT_EQ(minlen, "16");
392
393 EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), 0);
394 std::string deny;
395 EXPECT_EQ(getPamModuleConfValue(tempFaillockConfigFile, "deny", deny), 0);
396 EXPECT_EQ(deny, "3");
Nan Zhoue48085d2022-10-25 00:07:04 +0000397}
398
399TEST_F(UserMgrInTest, GetPamModuleArgValueOnFailure)
400{
401 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPamConfigFile));
Jason M. Bills2d042d12023-03-28 15:32:45 -0700402 std::string remember;
403 EXPECT_EQ(getPamModuleArgValue("pam_pwhistory.so", "remember", remember),
404 -1);
Nan Zhoue48085d2022-10-25 00:07:04 +0000405
406 EXPECT_NO_THROW(removeFile(tempPamConfigFile));
Jason M. Bills2d042d12023-03-28 15:32:45 -0700407 EXPECT_EQ(getPamModuleArgValue("pam_pwhistory.so", "remember", remember),
408 -1);
409}
410
411TEST_F(UserMgrInTest, GetPamModuleConfValueOnFailure)
412{
413 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWQualityConfigFile));
414 std::string minlen;
415 EXPECT_EQ(getPamModuleConfValue(tempPWQualityConfigFile, "minlen", minlen),
416 -1);
417
418 EXPECT_NO_THROW(removeFile(tempPWQualityConfigFile));
419 EXPECT_EQ(getPamModuleConfValue(tempPWQualityConfigFile, "minlen", minlen),
420 -1);
421
422 EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
423 std::string deny;
424 EXPECT_EQ(getPamModuleConfValue(tempFaillockConfigFile, "deny", deny), -1);
425
426 EXPECT_NO_THROW(removeFile(tempFaillockConfigFile));
427 EXPECT_EQ(getPamModuleConfValue(tempFaillockConfigFile, "deny", deny), -1);
Nan Zhoue48085d2022-10-25 00:07:04 +0000428}
429
430TEST_F(UserMgrInTest, SetPamModuleArgValueOnFailure)
431{
432 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPamConfigFile));
Jason M. Bills2d042d12023-03-28 15:32:45 -0700433 EXPECT_EQ(setPamModuleArgValue("pam_pwhistory.so", "remember", "1"), -1);
Nan Zhoue48085d2022-10-25 00:07:04 +0000434
435 EXPECT_NO_THROW(removeFile(tempPamConfigFile));
Jason M. Bills2d042d12023-03-28 15:32:45 -0700436 EXPECT_EQ(setPamModuleArgValue("pam_pwhistory.so", "remember", "1"), -1);
437}
438
439TEST_F(UserMgrInTest, SetPamModuleConfValueOnFailure)
440{
441 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWQualityConfigFile));
442 EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
443 -1);
444
445 EXPECT_NO_THROW(removeFile(tempPWQualityConfigFile));
446 EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
447 -1);
448
449 EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
450 EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), -1);
451
452 EXPECT_NO_THROW(removeFile(tempFaillockConfigFile));
453 EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), -1);
Nan Zhoue48085d2022-10-25 00:07:04 +0000454}
455
Nan Zhou8a11d992022-10-25 00:07:06 +0000456TEST_F(UserMgrInTest, IsUserExistEmptyInputThrowsError)
457{
458 EXPECT_THROW(
459 isUserExist(""),
460 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
461}
462
463TEST_F(UserMgrInTest, ThrowForUserDoesNotExistThrowsError)
464{
465 EXPECT_THROW(throwForUserDoesNotExist("whatever"),
466 sdbusplus::xyz::openbmc_project::User::Common::Error::
467 UserNameDoesNotExist);
468}
469
470TEST_F(UserMgrInTest, ThrowForUserExistsThrowsError)
471{
472 EXPECT_THROW(
473 throwForUserExists("root"),
474 sdbusplus::xyz::openbmc_project::User::Common::Error::UserNameExists);
475}
476
Nan Zhou40e44972022-10-25 00:07:07 +0000477TEST_F(
478 UserMgrInTest,
479 ThrowForUserNameConstraintsExceedIpmiMaxUserNameLenThrowsUserNameGroupFail)
480{
481 std::string strWith17Chars(17, 'A');
482 EXPECT_THROW(throwForUserNameConstraints(strWith17Chars, {"ipmi"}),
483 sdbusplus::xyz::openbmc_project::User::Common::Error::
484 UserNameGroupFail);
485}
486
487TEST_F(
488 UserMgrInTest,
489 ThrowForUserNameConstraintsExceedSystemMaxUserNameLenThrowsInvalidArgument)
490{
491 std::string strWith31Chars(31, 'A');
492 EXPECT_THROW(
493 throwForUserNameConstraints(strWith31Chars, {}),
494 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
495}
496
497TEST_F(UserMgrInTest,
498 ThrowForUserNameConstraintsRegexMismatchThrowsInvalidArgument)
499{
500 std::string startWithNumber = "0ABC";
501 EXPECT_THROW(
502 throwForUserNameConstraints(startWithNumber, {"ipmi"}),
503 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
504}
505
Nan Zhou49c81362022-10-25 00:07:08 +0000506TEST_F(UserMgrInTest, UserAddNotRootFailedWithInternalFailure)
507{
508 EXPECT_THROW(
509 UserMgr::executeUserAdd("user0", "ipmi,ssh", true, true),
510 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
511}
512
513TEST_F(UserMgrInTest, UserDeleteNotRootFailedWithInternalFailure)
514{
515 EXPECT_THROW(
516 UserMgr::executeUserDelete("user0"),
517 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
518}
519
520TEST_F(UserMgrInTest,
521 ThrowForMaxGrpUserCountThrowsNoResourceWhenIpmiUserExceedLimit)
522{
523 EXPECT_CALL(*this, getIpmiUsersCount()).WillOnce(Return(ipmiMaxUsers));
524 EXPECT_THROW(
525 throwForMaxGrpUserCount({"ipmi"}),
526 sdbusplus::xyz::openbmc_project::User::Common::Error::NoResource);
527}
528
529TEST_F(UserMgrInTest, CreateUserThrowsInternalFailureWhenExecuteUserAddFails)
530{
531 EXPECT_CALL(*this, executeUserAdd)
532 .WillOnce(testing::Throw(
533 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
534 EXPECT_THROW(
535 createUser("whatever", {"redfish"}, "", true),
536 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
537}
538
539TEST_F(UserMgrInTest, DeleteUserThrowsInternalFailureWhenExecuteUserDeleteFails)
540{
541 std::string username = "user";
542 EXPECT_NO_THROW(
543 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
544 EXPECT_CALL(*this, executeUserDelete(testing::StrEq(username)))
545 .WillOnce(testing::Throw(
546 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()))
547 .WillOnce(testing::DoDefault());
548
549 EXPECT_THROW(
550 deleteUser(username),
551 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
552 EXPECT_NO_THROW(UserMgr::deleteUser(username));
553}
554
Nan Zhou589aeb42022-10-25 00:07:09 +0000555TEST_F(UserMgrInTest, ThrowForInvalidPrivilegeThrowsWhenPrivilegeIsInvalid)
556{
557 EXPECT_THROW(
558 throwForInvalidPrivilege("whatever"),
559 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
560}
561
562TEST_F(UserMgrInTest, ThrowForInvalidPrivilegeNoThrowWhenPrivilegeIsValid)
563{
564 EXPECT_NO_THROW(throwForInvalidPrivilege("priv-admin"));
565 EXPECT_NO_THROW(throwForInvalidPrivilege("priv-operator"));
566 EXPECT_NO_THROW(throwForInvalidPrivilege("priv-user"));
Nan Zhou589aeb42022-10-25 00:07:09 +0000567}
568
Nan Zhouecf88762022-10-25 00:07:10 +0000569TEST_F(UserMgrInTest, ThrowForInvalidGroupsThrowsWhenGroupIsInvalid)
570{
571 EXPECT_THROW(
572 throwForInvalidGroups({"whatever"}),
573 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
574}
575
576TEST_F(UserMgrInTest, ThrowForInvalidGroupsNoThrowWhenGroupIsValid)
577{
578 EXPECT_NO_THROW(throwForInvalidGroups({"ipmi"}));
579 EXPECT_NO_THROW(throwForInvalidGroups({"ssh"}));
580 EXPECT_NO_THROW(throwForInvalidGroups({"redfish"}));
581 EXPECT_NO_THROW(throwForInvalidGroups({"web"}));
582}
583
Nan Zhouf25443e2022-10-25 00:07:11 +0000584TEST_F(UserMgrInTest, RenameUserOnSuccess)
585{
586 std::string username = "user001";
587 EXPECT_NO_THROW(
588 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
589 std::string newUsername = "user002";
590
591 EXPECT_NO_THROW(UserMgr::renameUser(username, newUsername));
592
593 // old username doesn't exist
594 EXPECT_THROW(getUserInfo(username),
595 sdbusplus::xyz::openbmc_project::User::Common::Error::
596 UserNameDoesNotExist);
597
598 UserInfoMap userInfo = getUserInfo(newUsername);
599 EXPECT_EQ(std::get<Privilege>(userInfo["UserPrivilege"]), "priv-user");
600 EXPECT_THAT(std::get<GroupList>(userInfo["UserGroups"]),
601 testing::UnorderedElementsAre("redfish", "ssh"));
602 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
603
604 EXPECT_NO_THROW(UserMgr::deleteUser(newUsername));
605}
606
607TEST_F(UserMgrInTest, RenameUserThrowsInternalFailureIfExecuteUserModifyFails)
608{
609 std::string username = "user001";
610 EXPECT_NO_THROW(
611 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
612 std::string newUsername = "user002";
613
614 EXPECT_CALL(*this, executeUserRename(testing::StrEq(username),
615 testing::StrEq(newUsername)))
616 .WillOnce(testing::Throw(
617 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
618 EXPECT_THROW(
619 UserMgr::renameUser(username, newUsername),
620 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
621
622 // The original user is unchanged
623 UserInfoMap userInfo = getUserInfo(username);
624 EXPECT_EQ(std::get<Privilege>(userInfo["UserPrivilege"]), "priv-user");
625 EXPECT_THAT(std::get<GroupList>(userInfo["UserGroups"]),
626 testing::UnorderedElementsAre("redfish", "ssh"));
627 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
628
629 EXPECT_NO_THROW(UserMgr::deleteUser(username));
630}
631
632TEST_F(UserMgrInTest, DefaultUserModifyFailedWithInternalFailure)
633{
634 EXPECT_THROW(
635 UserMgr::executeUserRename("user0", "user1"),
636 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
Nan Zhoufef63032022-10-25 00:07:12 +0000637 EXPECT_THROW(
638 UserMgr::executeUserModify("user0", "ssh", true),
639 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
640}
641
642TEST_F(UserMgrInTest, UpdateGroupsAndPrivOnSuccess)
643{
644 std::string username = "user001";
645 EXPECT_NO_THROW(
646 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
647 EXPECT_NO_THROW(
648 updateGroupsAndPriv(username, {"ipmi", "ssh"}, "priv-admin"));
649 UserInfoMap userInfo = getUserInfo(username);
650 EXPECT_EQ(std::get<Privilege>(userInfo["UserPrivilege"]), "priv-admin");
651 EXPECT_THAT(std::get<GroupList>(userInfo["UserGroups"]),
652 testing::UnorderedElementsAre("ipmi", "ssh"));
653 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
654 EXPECT_NO_THROW(UserMgr::deleteUser(username));
655}
656
657TEST_F(UserMgrInTest,
658 UpdateGroupsAndPrivThrowsInternalFailureIfExecuteUserModifyFail)
659{
660 std::string username = "user001";
661 EXPECT_NO_THROW(
662 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
663 EXPECT_CALL(*this, executeUserModify(testing::StrEq(username), testing::_,
664 testing::_))
665 .WillOnce(testing::Throw(
666 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
667 EXPECT_THROW(
668 updateGroupsAndPriv(username, {"ipmi", "ssh"}, "priv-admin"),
669 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
670 EXPECT_NO_THROW(UserMgr::deleteUser(username));
Nan Zhouf25443e2022-10-25 00:07:11 +0000671}
672
Nan Zhou18031012022-11-10 22:24:58 +0000673TEST_F(UserMgrInTest, MinPasswordLengthReturnsIfValueIsTheSame)
674{
675 initializeAccountPolicy();
676 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
677 UserMgr::minPasswordLength(8);
678 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
679}
680
681TEST_F(UserMgrInTest,
682 MinPasswordLengthRejectsTooShortPasswordWithInvalidArgument)
683{
684 initializeAccountPolicy();
685 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
686 EXPECT_THROW(
687 UserMgr::minPasswordLength(minPasswdLength - 1),
688 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
689 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
690}
691
692TEST_F(UserMgrInTest, MinPasswordLengthOnSuccess)
693{
694 initializeAccountPolicy();
695 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
696 UserMgr::minPasswordLength(16);
697 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 16);
698}
699
700TEST_F(UserMgrInTest, MinPasswordLengthOnFailure)
701{
Jason M. Bills2d042d12023-03-28 15:32:45 -0700702 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWQualityConfigFile));
Nan Zhou18031012022-11-10 22:24:58 +0000703 initializeAccountPolicy();
704 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
705 EXPECT_THROW(
706 UserMgr::minPasswordLength(16),
707 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
708 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
709}
710
Nan Zhoua6ce1fa2022-10-25 00:07:14 +0000711TEST_F(UserMgrInTest, RememberOldPasswordTimesReturnsIfValueIsTheSame)
712{
713 initializeAccountPolicy();
714 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 0);
715 UserMgr::rememberOldPasswordTimes(8);
716 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 8);
717 UserMgr::rememberOldPasswordTimes(8);
718 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 8);
719}
720
721TEST_F(UserMgrInTest, RememberOldPasswordTimesOnSuccess)
722{
723 initializeAccountPolicy();
724 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 0);
725 UserMgr::rememberOldPasswordTimes(16);
726 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 16);
727}
728
729TEST_F(UserMgrInTest, RememberOldPasswordTimesOnFailure)
730{
731 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPamConfigFile));
732 initializeAccountPolicy();
733 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 0);
734 EXPECT_THROW(
735 UserMgr::rememberOldPasswordTimes(16),
736 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
737 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 0);
738}
739
Nan Zhoucfabe6b2022-10-25 00:07:15 +0000740TEST_F(UserMgrInTest, MaxLoginAttemptBeforeLockoutReturnsIfValueIsTheSame)
741{
742 initializeAccountPolicy();
743 EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 2);
744 UserMgr::maxLoginAttemptBeforeLockout(2);
745 EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 2);
746}
747
748TEST_F(UserMgrInTest, MaxLoginAttemptBeforeLockoutOnSuccess)
749{
750 initializeAccountPolicy();
751 EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 2);
752 UserMgr::maxLoginAttemptBeforeLockout(16);
753 EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 16);
754}
755
756TEST_F(UserMgrInTest, MaxLoginAttemptBeforeLockoutOnFailure)
757{
Nan Zhoucfabe6b2022-10-25 00:07:15 +0000758 initializeAccountPolicy();
Jason M. Bills2d042d12023-03-28 15:32:45 -0700759 EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
Nan Zhoucfabe6b2022-10-25 00:07:15 +0000760 EXPECT_THROW(
761 UserMgr::maxLoginAttemptBeforeLockout(16),
762 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
Jason M. Bills2d042d12023-03-28 15:32:45 -0700763 EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 2);
Nan Zhoucfabe6b2022-10-25 00:07:15 +0000764}
765
Nan Zhou784aecd2022-10-25 00:07:16 +0000766TEST_F(UserMgrInTest, AccountUnlockTimeoutReturnsIfValueIsTheSame)
767{
768 initializeAccountPolicy();
769 EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 3);
770 UserMgr::accountUnlockTimeout(3);
771 EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 3);
772}
773
774TEST_F(UserMgrInTest, AccountUnlockTimeoutOnSuccess)
775{
776 initializeAccountPolicy();
777 EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 3);
778 UserMgr::accountUnlockTimeout(16);
779 EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 16);
780}
781
782TEST_F(UserMgrInTest, AccountUnlockTimeoutOnFailure)
783{
784 initializeAccountPolicy();
Jason M. Bills2d042d12023-03-28 15:32:45 -0700785 EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
Nan Zhou784aecd2022-10-25 00:07:16 +0000786 EXPECT_THROW(
787 UserMgr::accountUnlockTimeout(16),
788 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
789 EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 3);
790}
791
Nan Zhou6b6f2d82022-10-25 00:07:17 +0000792TEST_F(UserMgrInTest, UserEnableOnSuccess)
793{
794 std::string username = "user001";
795 EXPECT_NO_THROW(
796 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
797 UserInfoMap userInfo = getUserInfo(username);
798 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
799
800 EXPECT_NO_THROW(userEnable(username, false));
801
802 userInfo = getUserInfo(username);
803 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), false);
804
805 EXPECT_NO_THROW(UserMgr::deleteUser(username));
806}
807
808TEST_F(UserMgrInTest, UserEnableThrowsInternalFailureIfExecuteUserModifyFail)
809{
810 std::string username = "user001";
811 EXPECT_NO_THROW(
812 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
813 UserInfoMap userInfo = getUserInfo(username);
814 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
815
816 EXPECT_CALL(*this, executeUserModifyUserEnable(testing::StrEq(username),
817 testing::Eq(false)))
818 .WillOnce(testing::Throw(
819 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
820 EXPECT_THROW(
821 userEnable(username, false),
822 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
823
824 userInfo = getUserInfo(username);
825 // Stay unchanged
826 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
827
828 EXPECT_NO_THROW(UserMgr::deleteUser(username));
829}
830
Nan Zhoua2953032022-11-11 21:50:32 +0000831TEST_F(
832 UserMgrInTest,
833 UserLockedForFailedAttemptReturnsFalseIfMaxLoginAttemptBeforeLockoutIsZero)
834{
835 EXPECT_FALSE(userLockedForFailedAttempt("whatever"));
836}
837
838TEST_F(UserMgrInTest, UserLockedForFailedAttemptZeroFailuresReturnsFalse)
839{
840 std::string username = "user001";
841 initializeAccountPolicy();
842 // Example output from BMC
Jason M. Bills2d042d12023-03-28 15:32:45 -0700843 // root:~# faillock --user root
844 // root:
845 // When Type Source Valid
846 std::vector<std::string> output = {"whatever",
847 "When Type Source Valid"};
Nan Zhoua2953032022-11-11 21:50:32 +0000848 EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
849 .WillOnce(testing::Return(output));
850
851 EXPECT_FALSE(userLockedForFailedAttempt(username));
852}
853
854TEST_F(UserMgrInTest, UserLockedForFailedAttemptFailIfGetFailedAttemptFail)
855{
856 std::string username = "user001";
857 initializeAccountPolicy();
858 EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
859 .WillOnce(testing::Throw(
860 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
861
862 EXPECT_THROW(
863 userLockedForFailedAttempt(username),
864 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
865}
866
867TEST_F(UserMgrInTest,
Nan Zhoua2953032022-11-11 21:50:32 +0000868 UserLockedForFailedAttemptThrowsInternalFailureIfWrongDateFormat)
869{
870 std::string username = "user001";
871 initializeAccountPolicy();
872
873 // Choose a date in the past.
874 std::vector<std::string> output = {"whatever",
Jason M. Bills2d042d12023-03-28 15:32:45 -0700875 "10/24/2002 00:00:00 type source V"};
Nan Zhoua2953032022-11-11 21:50:32 +0000876 EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
877 .WillOnce(testing::Return(output));
878
879 EXPECT_THROW(
880 userLockedForFailedAttempt(username),
881 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
882}
883
884TEST_F(UserMgrInTest,
885 UserLockedForFailedAttemptReturnsFalseIfLastFailTimeHasTimedOut)
886{
887 std::string username = "user001";
888 initializeAccountPolicy();
889
890 // Choose a date in the past.
891 std::vector<std::string> output = {"whatever",
Jason M. Bills2d042d12023-03-28 15:32:45 -0700892 "2002-10-24 00:00:00 type source V"};
Nan Zhoua2953032022-11-11 21:50:32 +0000893 EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
894 .WillOnce(testing::Return(output));
895
896 EXPECT_EQ(userLockedForFailedAttempt(username), false);
897}
898
Nan Zhouda401fe2022-10-25 00:07:18 +0000899TEST_F(UserMgrInTest, CheckAndThrowForDisallowedGroupCreationOnSuccess)
900{
901 // Base Redfish Roles
902 EXPECT_NO_THROW(
903 checkAndThrowForDisallowedGroupCreation("openbmc_rfr_Administrator"));
904 EXPECT_NO_THROW(
905 checkAndThrowForDisallowedGroupCreation("openbmc_rfr_Operator"));
906 EXPECT_NO_THROW(
907 checkAndThrowForDisallowedGroupCreation("openbmc_rfr_ReadOnly"));
908 // Base Redfish Privileges
909 EXPECT_NO_THROW(
910 checkAndThrowForDisallowedGroupCreation("openbmc_rfp_Login"));
911 EXPECT_NO_THROW(checkAndThrowForDisallowedGroupCreation(
912 "openbmc_rfp_ConfigureManager"));
913 EXPECT_NO_THROW(
914 checkAndThrowForDisallowedGroupCreation("openbmc_rfp_ConfigureUsers"));
915 EXPECT_NO_THROW(
916 checkAndThrowForDisallowedGroupCreation("openbmc_rfp_ConfigureSelf"));
917 EXPECT_NO_THROW(checkAndThrowForDisallowedGroupCreation(
918 "openbmc_rfp_ConfigureComponents"));
919 // OEM Redfish Roles
920 EXPECT_NO_THROW(
921 checkAndThrowForDisallowedGroupCreation("openbmc_orfr_PowerService"));
922 // OEM Redfish Privileges
923 EXPECT_NO_THROW(
924 checkAndThrowForDisallowedGroupCreation("openbmc_orfp_PowerService"));
925}
926
927TEST_F(UserMgrInTest,
928 CheckAndThrowForDisallowedGroupCreationThrowsIfGroupNameTooLong)
929{
930 std::string groupName(maxSystemGroupNameLength + 1, 'A');
931 EXPECT_THROW(
932 checkAndThrowForDisallowedGroupCreation(groupName),
933 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
934}
935
936TEST_F(
937 UserMgrInTest,
938 CheckAndThrowForDisallowedGroupCreationThrowsIfGroupNameHasDisallowedCharacters)
939{
Nan Zhouda401fe2022-10-25 00:07:18 +0000940 EXPECT_THROW(
941 checkAndThrowForDisallowedGroupCreation("openbmc_rfp_?owerService"),
942 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
943 EXPECT_THROW(
944 checkAndThrowForDisallowedGroupCreation("openbmc_rfp_-owerService"),
945 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
946}
947
948TEST_F(
949 UserMgrInTest,
950 CheckAndThrowForDisallowedGroupCreationThrowsIfGroupNameHasDisallowedPrefix)
951{
Nan Zhouda401fe2022-10-25 00:07:18 +0000952 EXPECT_THROW(
953 checkAndThrowForDisallowedGroupCreation("google_rfp_"),
954 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
955 EXPECT_THROW(
956 checkAndThrowForDisallowedGroupCreation("com_rfp_"),
957 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
958}
959
960TEST_F(UserMgrInTest, CheckAndThrowForMaxGroupCountOnSuccess)
961{
962 EXPECT_THAT(allGroups().size(), 4);
963 for (size_t i = 0; i < maxSystemGroupCount - 4; ++i)
964 {
965 std::string groupName = "openbmc_rfr_role";
966 groupName += std::to_string(i);
967 EXPECT_NO_THROW(createGroup(groupName));
968 }
969 EXPECT_THROW(
970 createGroup("openbmc_rfr_AnotherRole"),
971 sdbusplus::xyz::openbmc_project::User::Common::Error::NoResource);
972 for (size_t i = 0; i < maxSystemGroupCount - 4; ++i)
973 {
974 std::string groupName = "openbmc_rfr_role";
975 groupName += std::to_string(i);
976 EXPECT_NO_THROW(deleteGroup(groupName));
977 }
978}
979
980TEST_F(UserMgrInTest, CheckAndThrowForGroupExist)
981{
982 std::string groupName = "openbmc_rfr_role";
983 EXPECT_NO_THROW(createGroup(groupName));
984 EXPECT_THROW(
985 createGroup(groupName),
986 sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
987 EXPECT_NO_THROW(deleteGroup(groupName));
988}
989
990TEST_F(UserMgrInTest, ByDefaultAllGroupsArePredefinedGroups)
991{
992 EXPECT_THAT(allGroups(),
993 testing::UnorderedElementsAre("web", "redfish", "ipmi", "ssh"));
994}
995
996TEST_F(UserMgrInTest, DeleteGroupThrowsIfGroupIsNotAllowedToChange)
997{
998 EXPECT_THROW(
999 deleteGroup("ipmi"),
1000 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1001 EXPECT_THROW(
1002 deleteGroup("web"),
1003 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1004 EXPECT_THROW(
1005 deleteGroup("redfish"),
1006 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1007 EXPECT_THROW(
1008 deleteGroup("ssh"),
1009 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1010}
1011
1012TEST_F(UserMgrInTest,
1013 CreateGroupThrowsInternalFailureWhenExecuteGroupCreateFails)
1014{
1015 EXPECT_CALL(*this, executeGroupCreation)
1016 .WillOnce(testing::Throw(
1017 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
1018 EXPECT_THROW(
1019 createGroup("openbmc_rfr_role1"),
1020 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
1021}
1022
1023TEST_F(UserMgrInTest,
1024 DeleteGroupThrowsInternalFailureWhenExecuteGroupDeleteFails)
1025{
1026 std::string groupName = "openbmc_rfr_role1";
1027 EXPECT_NO_THROW(UserMgr::createGroup(groupName));
1028 EXPECT_CALL(*this, executeGroupDeletion(testing::StrEq(groupName)))
1029 .WillOnce(testing::Throw(
1030 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()))
1031 .WillOnce(testing::DoDefault());
1032
1033 EXPECT_THROW(
1034 deleteGroup(groupName),
1035 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
1036 EXPECT_NO_THROW(UserMgr::deleteGroup(groupName));
1037}
1038
1039TEST_F(UserMgrInTest, CheckAndThrowForGroupNotExist)
1040{
1041 EXPECT_THROW(deleteGroup("whatever"),
1042 sdbusplus::xyz::openbmc_project::User::Common::Error::
1043 GroupNameDoesNotExist);
1044}
1045
1046TEST(ReadAllGroupsOnSystemTest, OnlyReturnsPredefinedGroups)
1047{
1048 EXPECT_THAT(UserMgr::readAllGroupsOnSystem(),
1049 testing::UnorderedElementsAre("web", "redfish", "ipmi", "ssh"));
1050}
1051
raviteja-b8cc44052019-02-27 23:29:36 -06001052} // namespace user
1053} // namespace phosphor