1 #include "mock_user_mgr.hpp"
2 #include "user_mgr.hpp"
3
4 #include <unistd.h>
5
6 #include <sdbusplus/test/sdbus_mock.hpp>
7 #include <xyz/openbmc_project/Common/error.hpp>
8 #include <xyz/openbmc_project/User/Common/error.hpp>
9
10 #include <exception>
11 #include <filesystem>
12 #include <fstream>
13 #include <vector>
14
15 #include <gmock/gmock.h>
16 #include <gtest/gtest.h>
17
18 namespace phosphor
19 {
20 namespace user
21 {
22
23 using ::testing::Return;
24 using ::testing::Throw;
25
26 using InternalFailure =
27 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
28 using UserNameDoesNotExist =
29 sdbusplus::xyz::openbmc_project::User::Common::Error::UserNameDoesNotExist;
30
31 class TestUserMgr : public testing::Test
32 {
33 public:
34 sdbusplus::SdBusMock sdBusMock;
35 sdbusplus::bus_t bus;
36 MockManager mockManager;
37
TestUserMgr()38 TestUserMgr() :
39 bus(sdbusplus::get_mocked_new(&sdBusMock)), mockManager(bus, objpath)
40 {}
41
createLocalUser(const std::string & userName,std::vector<std::string> groupNames,const std::string & priv,bool enabled)42 void createLocalUser(const std::string& userName,
43 std::vector<std::string> groupNames,
44 const std::string& priv, bool enabled)
45 {
46 sdbusplus::message::object_path tempObjPath(usersObjPath);
47 tempObjPath /= userName;
48 std::string userObj(tempObjPath);
49 if (enabled)
50 {
51 ON_CALL(mockManager, isUserEnabled)
52 .WillByDefault(testing::Return(true));
53 }
54 else
55 {
56 ON_CALL(mockManager, isUserEnabled)
57 .WillByDefault(testing::Return(false));
58 }
59 mockManager.usersList.emplace(
60 userName, std::make_unique<phosphor::user::Users>(
61 mockManager.bus, userObj.c_str(), groupNames, priv,
62 enabled, mockManager));
63 }
64
createPrivilegeMapperDbusObject(void)65 DbusUserObj createPrivilegeMapperDbusObject(void)
66 {
67 DbusUserObj object;
68 DbusUserObjValue objValue;
69
70 DbusUserObjPath objPath("/xyz/openbmc_project/user/ldap/openldap");
71 DbusUserPropVariant enabled(true);
72 DbusUserObjProperties property = {std::make_pair("Enabled", enabled)};
73 std::string intf = "xyz.openbmc_project.Object.Enable";
74 objValue.emplace(intf, property);
75 object.emplace(objPath, objValue);
76
77 DbusUserObjPath objectPath(
78 "/xyz/openbmc_project/user/ldap/openldap/role_map/1");
79 std::string group = "ldapGroup";
80 std::string priv = "priv-admin";
81 DbusUserObjProperties properties = {std::make_pair("GroupName", group),
82 std::make_pair("Privilege", priv)};
83 std::string interface = "xyz.openbmc_project.User.PrivilegeMapperEntry";
84
85 objValue.emplace(interface, properties);
86 object.emplace(objectPath, objValue);
87
88 return object;
89 }
90
createLdapConfigObjectWithoutPrivilegeMapper(void)91 DbusUserObj createLdapConfigObjectWithoutPrivilegeMapper(void)
92 {
93 DbusUserObj object;
94 DbusUserObjValue objValue;
95
96 DbusUserObjPath objPath("/xyz/openbmc_project/user/ldap/openldap");
97 DbusUserPropVariant enabled(true);
98 DbusUserObjProperties property = {std::make_pair("Enabled", enabled)};
99 std::string intf = "xyz.openbmc_project.Object.Enable";
100 objValue.emplace(intf, property);
101 object.emplace(objPath, objValue);
102 return object;
103 }
104 };
105
TEST_F(TestUserMgr,ldapEntryDoesNotExist)106 TEST_F(TestUserMgr, ldapEntryDoesNotExist)
107 {
108 std::string userName = "user";
109 UserInfoMap userInfo;
110
111 EXPECT_CALL(mockManager, getPrimaryGroup(userName))
112 .WillRepeatedly(Throw(UserNameDoesNotExist()));
113 EXPECT_THROW(userInfo = mockManager.getUserInfo(userName),
114 UserNameDoesNotExist);
115 }
116
TEST_F(TestUserMgr,localUser)117 TEST_F(TestUserMgr, localUser)
118 {
119 UserInfoMap userInfo;
120 std::string userName = "testUser";
121 std::string privilege = "priv-admin";
122 std::vector<std::string> groups{"testGroup"};
123 // Create local user
124 createLocalUser(userName, groups, privilege, true);
125 EXPECT_CALL(mockManager, userLockedForFailedAttempt(userName)).Times(1);
126 userInfo = mockManager.getUserInfo(userName);
127
128 EXPECT_EQ(privilege, std::get<std::string>(userInfo["UserPrivilege"]));
129 EXPECT_EQ(groups,
130 std::get<std::vector<std::string>>(userInfo["UserGroups"]));
131 EXPECT_EQ(true, std::get<bool>(userInfo["UserEnabled"]));
132 EXPECT_EQ(false, std::get<bool>(userInfo["UserLockedForFailedAttempt"]));
133 EXPECT_EQ(false, std::get<bool>(userInfo["UserPasswordExpired"]));
134 EXPECT_EQ(false, std::get<bool>(userInfo["RemoteUser"]));
135 }
136
TEST_F(TestUserMgr,ldapUserWithPrivMapper)137 TEST_F(TestUserMgr, ldapUserWithPrivMapper)
138 {
139 UserInfoMap userInfo;
140 std::string userName = "ldapUser";
141 std::string ldapGroup = "ldapGroup";
142 gid_t primaryGid = 1000;
143
144 EXPECT_CALL(mockManager, getPrimaryGroup(userName))
145 .WillRepeatedly(Return(primaryGid));
146 // Create privilege mapper dbus object
147 DbusUserObj object = createPrivilegeMapperDbusObject();
148 EXPECT_CALL(mockManager, getPrivilegeMapperObject())
149 .WillRepeatedly(Return(object));
150 EXPECT_CALL(mockManager, isGroupMember(userName, primaryGid, ldapGroup))
151 .WillRepeatedly(Return(true));
152 userInfo = mockManager.getUserInfo(userName);
153 EXPECT_EQ(true, std::get<bool>(userInfo["RemoteUser"]));
154 EXPECT_EQ("priv-admin", std::get<std::string>(userInfo["UserPrivilege"]));
155 }
156
TEST_F(TestUserMgr,ldapUserWithoutPrivMapper)157 TEST_F(TestUserMgr, ldapUserWithoutPrivMapper)
158 {
159 using ::testing::_;
160
161 UserInfoMap userInfo;
162 std::string userName = "ldapUser";
163 std::string ldapGroup = "ldapGroup";
164 gid_t primaryGid = 1000;
165
166 EXPECT_CALL(mockManager, getPrimaryGroup(userName))
167 .WillRepeatedly(Return(primaryGid));
168 // Create LDAP config object without privilege mapper
169 DbusUserObj object = createLdapConfigObjectWithoutPrivilegeMapper();
170 EXPECT_CALL(mockManager, getPrivilegeMapperObject())
171 .WillRepeatedly(Return(object));
172 EXPECT_CALL(mockManager, isGroupMember(_, _, _)).Times(0);
173 userInfo = mockManager.getUserInfo(userName);
174 EXPECT_EQ(true, std::get<bool>(userInfo["RemoteUser"]));
175 EXPECT_EQ("priv-user", std::get<std::string>(userInfo["UserPrivilege"]));
176 }
177
TEST(GetCSVFromVector,EmptyVectorReturnsEmptyString)178 TEST(GetCSVFromVector, EmptyVectorReturnsEmptyString)
179 {
180 EXPECT_EQ(getCSVFromVector({}), "");
181 }
182
TEST(GetCSVFromVector,ElementsAreJoinedByComma)183 TEST(GetCSVFromVector, ElementsAreJoinedByComma)
184 {
185 EXPECT_EQ(getCSVFromVector(std::vector<std::string>{"123"}), "123");
186 EXPECT_EQ(getCSVFromVector(std::vector<std::string>{"123", "456"}),
187 "123,456");
188 }
189
TEST(RemoveStringFromCSV,WithoutDeleteStringReturnsFalse)190 TEST(RemoveStringFromCSV, WithoutDeleteStringReturnsFalse)
191 {
192 std::string expected = "whatever,https";
193 std::string str = expected;
194 EXPECT_FALSE(removeStringFromCSV(str, "ssh"));
195 EXPECT_EQ(str, expected);
196
197 std::string empty;
198 EXPECT_FALSE(removeStringFromCSV(empty, "ssh"));
199 }
200
TEST(RemoveStringFromCSV,WithDeleteStringReturnsTrue)201 TEST(RemoveStringFromCSV, WithDeleteStringReturnsTrue)
202 {
203 std::string expected = "whatever";
204 std::string str = "whatever,https";
205 EXPECT_TRUE(removeStringFromCSV(str, "https"));
206 EXPECT_EQ(str, expected);
207
208 str = "https";
209 EXPECT_TRUE(removeStringFromCSV(str, "https"));
210 EXPECT_EQ(str, "");
211 }
212
213 namespace
214 {
215 inline constexpr const char* objectRootInTest = "/xyz/openbmc_project/user";
216
217 // Fake configs; referenced configs on real BMC
218 inline constexpr const char* rawFailLockConfig = R"(
219 deny=2
220 unlock_time=3
221 )";
222 inline constexpr const char* rawPWHistoryConfig = R"(
223 enforce_for_root
224 remember=0
225 )";
226 inline constexpr const char* rawPWQualityConfig = R"(
227 enforce_for_root
228 minlen=8
229 difok=0
230 lcredit=0
231 ocredit=0
232 dcredit=0
233 ucredit=0
234 )";
235 } // namespace
236
dumpStringToFile(const std::string & str,const std::string & filePath)237 void dumpStringToFile(const std::string& str, const std::string& filePath)
238 {
239 std::ofstream outputFileStream;
240
241 outputFileStream.exceptions(
242 std::ofstream::failbit | std::ofstream::badbit | std::ofstream::eofbit);
243
244 outputFileStream.open(filePath, std::ios::out);
245 outputFileStream << str << "\n" << std::flush;
246 outputFileStream.close();
247 }
248
removeFile(const std::string & filePath)249 void removeFile(const std::string& filePath)
250 {
251 std::filesystem::remove(filePath);
252 }
253
254 class UserMgrInTest : public testing::Test, public UserMgr
255 {
256 public:
UserMgrInTest()257 UserMgrInTest() : UserMgr(busInTest, objectRootInTest)
258 {
259 {
260 tempFaillockConfigFile = tempFilePath;
261 int fd = mkstemp(tempFaillockConfigFile.data());
262 EXPECT_NE(-1, fd);
263 EXPECT_NO_THROW(
264 dumpStringToFile(rawFailLockConfig, tempFaillockConfigFile));
265 if (fd != -1)
266 {
267 close(fd);
268 }
269 }
270
271 {
272 tempPWHistoryConfigFile = tempFilePath;
273 int fd = mkstemp(tempPWHistoryConfigFile.data());
274 EXPECT_NE(-1, fd);
275 EXPECT_NO_THROW(
276 dumpStringToFile(rawPWHistoryConfig, tempPWHistoryConfigFile));
277 if (fd != -1)
278 {
279 close(fd);
280 }
281 }
282
283 {
284 tempPWQualityConfigFile = tempFilePath;
285 int fd = mkstemp(tempPWQualityConfigFile.data());
286 EXPECT_NE(-1, fd);
287 EXPECT_NO_THROW(
288 dumpStringToFile(rawPWQualityConfig, tempPWQualityConfigFile));
289 if (fd != -1)
290 {
291 close(fd);
292 }
293 }
294
295 // Set config files to test files
296 faillockConfigFile = tempFaillockConfigFile;
297 pwHistoryConfigFile = tempPWHistoryConfigFile;
298 pwQualityConfigFile = tempPWQualityConfigFile;
299
300 ON_CALL(*this, executeUserAdd(testing::_, testing::_, testing::_,
301 testing::Eq(true)))
302 .WillByDefault([this]() {
303 ON_CALL(*this, isUserEnabled)
304 .WillByDefault(testing::Return(true));
305 testing::Return();
306 });
307
308 ON_CALL(*this, executeUserAdd(testing::_, testing::_, testing::_,
309 testing::Eq(false)))
310 .WillByDefault([this]() {
311 ON_CALL(*this, isUserEnabled)
312 .WillByDefault(testing::Return(false));
313 testing::Return();
314 });
315
316 ON_CALL(*this, executeUserDelete).WillByDefault(testing::Return());
317
318 ON_CALL(*this, executeUserClearFailRecords)
319 .WillByDefault(testing::Return());
320
321 ON_CALL(*this, getIpmiUsersCount).WillByDefault(testing::Return(0));
322
323 ON_CALL(*this, executeUserRename).WillByDefault(testing::Return());
324
325 ON_CALL(*this, executeUserModify(testing::_, testing::_, testing::_))
326 .WillByDefault(testing::Return());
327
328 ON_CALL(*this,
329 executeUserModifyUserEnable(testing::_, testing::Eq(true)))
330 .WillByDefault([this]() {
331 ON_CALL(*this, isUserEnabled)
332 .WillByDefault(testing::Return(true));
333 testing::Return();
334 });
335
336 ON_CALL(*this,
337 executeUserModifyUserEnable(testing::_, testing::Eq(false)))
338 .WillByDefault([this]() {
339 ON_CALL(*this, isUserEnabled)
340 .WillByDefault(testing::Return(false));
341 testing::Return();
342 });
343
344 ON_CALL(*this, executeGroupCreation(testing::_))
345 .WillByDefault(testing::Return());
346
347 ON_CALL(*this, executeGroupDeletion(testing::_))
348 .WillByDefault(testing::Return());
349
350 ON_CALL(*this, executeGroupCreation).WillByDefault(testing::Return());
351
352 ON_CALL(*this, executeGroupDeletion).WillByDefault(testing::Return());
353 }
354
~UserMgrInTest()355 ~UserMgrInTest() override
356 {
357 EXPECT_NO_THROW(removeFile(tempFaillockConfigFile));
358 EXPECT_NO_THROW(removeFile(tempPWHistoryConfigFile));
359 EXPECT_NO_THROW(removeFile(tempPWQualityConfigFile));
360 }
361
362 MOCK_METHOD(void, executeUserAdd, (const char*, const char*, bool, bool),
363 (override));
364
365 MOCK_METHOD(void, executeUserDelete, (const char*), (override));
366
367 MOCK_METHOD(void, executeUserClearFailRecords, (const char*), (override));
368
369 MOCK_METHOD(size_t, getIpmiUsersCount, (), (override));
370
371 MOCK_METHOD(void, executeUserRename, (const char*, const char*),
372 (override));
373
374 MOCK_METHOD(void, executeUserModify, (const char*, const char*, bool),
375 (override));
376
377 MOCK_METHOD(void, executeUserModifyUserEnable, (const char*, bool),
378 (override));
379
380 MOCK_METHOD(std::vector<std::string>, getFailedAttempt, (const char*),
381 (override));
382
383 MOCK_METHOD(void, executeGroupCreation, (const char*), (override));
384
385 MOCK_METHOD(void, executeGroupDeletion, (const char*), (override));
386
387 MOCK_METHOD(bool, isUserEnabled, (const std::string& userName), (override));
388
389 protected:
390 static constexpr auto tempFilePath = "/tmp/test-data-XXXXXX";
391
392 static sdbusplus::bus_t busInTest;
393 std::string tempFaillockConfigFile;
394 std::string tempPWHistoryConfigFile;
395 std::string tempPWQualityConfigFile;
396 };
397
398 sdbusplus::bus_t UserMgrInTest::busInTest = sdbusplus::bus::new_default();
399
TEST_F(UserMgrInTest,GetPamModuleConfValueOnSuccess)400 TEST_F(UserMgrInTest, GetPamModuleConfValueOnSuccess)
401 {
402 std::string minlen;
403 EXPECT_EQ(getPamModuleConfValue(tempPWQualityConfigFile, "minlen", minlen),
404 0);
405 EXPECT_EQ(minlen, "8");
406 std::string deny;
407 EXPECT_EQ(getPamModuleConfValue(tempFaillockConfigFile, "deny", deny), 0);
408 EXPECT_EQ(deny, "2");
409 std::string remember;
410 EXPECT_EQ(
411 getPamModuleConfValue(tempPWHistoryConfigFile, "remember", remember),
412 0);
413 EXPECT_EQ(remember, "0");
414 }
415
TEST_F(UserMgrInTest,SetPamModuleConfValueOnSuccess)416 TEST_F(UserMgrInTest, SetPamModuleConfValueOnSuccess)
417 {
418 EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
419 0);
420 std::string minlen;
421 EXPECT_EQ(getPamModuleConfValue(tempPWQualityConfigFile, "minlen", minlen),
422 0);
423 EXPECT_EQ(minlen, "16");
424
425 EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), 0);
426 std::string deny;
427 EXPECT_EQ(getPamModuleConfValue(tempFaillockConfigFile, "deny", deny), 0);
428 EXPECT_EQ(deny, "3");
429
430 EXPECT_EQ(setPamModuleConfValue(tempPWHistoryConfigFile, "remember", "1"),
431 0);
432 std::string remember;
433 EXPECT_EQ(
434 getPamModuleConfValue(tempPWHistoryConfigFile, "remember", remember),
435 0);
436 EXPECT_EQ(remember, "1");
437 }
438
TEST_F(UserMgrInTest,SetPamModuleConfValueTempFileOnSuccess)439 TEST_F(UserMgrInTest, SetPamModuleConfValueTempFileOnSuccess)
440 {
441 EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
442 0);
443
444 std::string tmpFile = tempPWQualityConfigFile + "_tmp";
445 EXPECT_FALSE(std::filesystem::exists(tmpFile));
446
447 EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), 0);
448
449 tmpFile = tempFaillockConfigFile + "_tmp";
450 EXPECT_FALSE(std::filesystem::exists(tmpFile));
451
452 EXPECT_EQ(setPamModuleConfValue(tempPWHistoryConfigFile, "remember", "1"),
453 0);
454
455 tmpFile = tempPWHistoryConfigFile + "_tmp";
456 EXPECT_FALSE(std::filesystem::exists(tmpFile));
457 }
458
TEST_F(UserMgrInTest,GetPamModuleConfValueOnFailure)459 TEST_F(UserMgrInTest, GetPamModuleConfValueOnFailure)
460 {
461 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWQualityConfigFile));
462 std::string minlen;
463 EXPECT_EQ(getPamModuleConfValue(tempPWQualityConfigFile, "minlen", minlen),
464 -1);
465
466 EXPECT_NO_THROW(removeFile(tempPWQualityConfigFile));
467 EXPECT_EQ(getPamModuleConfValue(tempPWQualityConfigFile, "minlen", minlen),
468 -1);
469
470 EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
471 std::string deny;
472 EXPECT_EQ(getPamModuleConfValue(tempFaillockConfigFile, "deny", deny), -1);
473
474 EXPECT_NO_THROW(removeFile(tempFaillockConfigFile));
475 EXPECT_EQ(getPamModuleConfValue(tempFaillockConfigFile, "deny", deny), -1);
476
477 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWHistoryConfigFile));
478 std::string remember;
479 EXPECT_EQ(
480 getPamModuleConfValue(tempPWHistoryConfigFile, "remember", remember),
481 -1);
482
483 EXPECT_NO_THROW(removeFile(tempPWHistoryConfigFile));
484 EXPECT_EQ(
485 getPamModuleConfValue(tempPWHistoryConfigFile, "remember", remember),
486 -1);
487 }
488
TEST_F(UserMgrInTest,SetPamModuleConfValueOnFailure)489 TEST_F(UserMgrInTest, SetPamModuleConfValueOnFailure)
490 {
491 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWQualityConfigFile));
492 EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
493 -1);
494
495 EXPECT_NO_THROW(removeFile(tempPWQualityConfigFile));
496 EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
497 -1);
498
499 EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
500 EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), -1);
501
502 EXPECT_NO_THROW(removeFile(tempFaillockConfigFile));
503 EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), -1);
504
505 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWHistoryConfigFile));
506 EXPECT_EQ(setPamModuleConfValue(tempPWHistoryConfigFile, "remember", "1"),
507 -1);
508
509 EXPECT_NO_THROW(removeFile(tempPWHistoryConfigFile));
510 EXPECT_EQ(setPamModuleConfValue(tempPWHistoryConfigFile, "remember", "1"),
511 -1);
512 }
513
TEST_F(UserMgrInTest,SetPamModuleConfValueTempFileOnFailure)514 TEST_F(UserMgrInTest, SetPamModuleConfValueTempFileOnFailure)
515 {
516 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWQualityConfigFile));
517 EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
518 -1);
519
520 std::string tmpFile = tempPWQualityConfigFile + "_tmp";
521 EXPECT_FALSE(std::filesystem::exists(tmpFile));
522
523 EXPECT_NO_THROW(removeFile(tempPWQualityConfigFile));
524 EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
525 -1);
526
527 EXPECT_FALSE(std::filesystem::exists(tmpFile));
528
529 EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
530 EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), -1);
531
532 tmpFile = tempFaillockConfigFile + "_tmp";
533 EXPECT_FALSE(std::filesystem::exists(tmpFile));
534
535 EXPECT_NO_THROW(removeFile(tempFaillockConfigFile));
536 EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), -1);
537
538 EXPECT_FALSE(std::filesystem::exists(tmpFile));
539
540 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWHistoryConfigFile));
541 EXPECT_EQ(setPamModuleConfValue(tempPWHistoryConfigFile, "remember", "1"),
542 -1);
543
544 tmpFile = tempPWHistoryConfigFile + "_tmp";
545 EXPECT_FALSE(std::filesystem::exists(tmpFile));
546
547 EXPECT_NO_THROW(removeFile(tempPWHistoryConfigFile));
548 EXPECT_EQ(setPamModuleConfValue(tempPWHistoryConfigFile, "remember", "1"),
549 -1);
550
551 EXPECT_FALSE(std::filesystem::exists(tmpFile));
552 }
553
TEST_F(UserMgrInTest,IsUserExistEmptyInputThrowsError)554 TEST_F(UserMgrInTest, IsUserExistEmptyInputThrowsError)
555 {
556 EXPECT_THROW(
557 isUserExist(""),
558 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
559 }
560
TEST_F(UserMgrInTest,ThrowForUserDoesNotExistThrowsError)561 TEST_F(UserMgrInTest, ThrowForUserDoesNotExistThrowsError)
562 {
563 EXPECT_THROW(throwForUserDoesNotExist("whatever"),
564 sdbusplus::xyz::openbmc_project::User::Common::Error::
565 UserNameDoesNotExist);
566 }
567
TEST_F(UserMgrInTest,ThrowForUserExistsThrowsError)568 TEST_F(UserMgrInTest, ThrowForUserExistsThrowsError)
569 {
570 EXPECT_THROW(
571 throwForUserExists("root"),
572 sdbusplus::xyz::openbmc_project::User::Common::Error::UserNameExists);
573 }
574
TEST_F(UserMgrInTest,ThrowForUserNameConstraintsExceedIpmiMaxUserNameLenThrowsUserNameGroupFail)575 TEST_F(
576 UserMgrInTest,
577 ThrowForUserNameConstraintsExceedIpmiMaxUserNameLenThrowsUserNameGroupFail)
578 {
579 std::string strWith17Chars(17, 'A');
580 EXPECT_THROW(throwForUserNameConstraints(strWith17Chars, {"ipmi"}),
581 sdbusplus::xyz::openbmc_project::User::Common::Error::
582 UserNameGroupFail);
583 }
584
TEST_F(UserMgrInTest,ThrowForUserNameConstraintsExceedSystemMaxUserNameLenThrowsInvalidArgument)585 TEST_F(
586 UserMgrInTest,
587 ThrowForUserNameConstraintsExceedSystemMaxUserNameLenThrowsInvalidArgument)
588 {
589 std::string strWith31Chars(101, 'A');
590 EXPECT_THROW(
591 throwForUserNameConstraints(strWith31Chars, {}),
592 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
593 }
594
TEST_F(UserMgrInTest,ThrowForUserNameConstraintsRegexMismatchThrowsInvalidArgument)595 TEST_F(UserMgrInTest,
596 ThrowForUserNameConstraintsRegexMismatchThrowsInvalidArgument)
597 {
598 std::string startWithNumber = "0ABC";
599 std::string startWithDisallowedCharacter = "[test";
600 EXPECT_THROW(
601 throwForUserNameConstraints(startWithNumber, {"ipmi"}),
602 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
603 EXPECT_THROW(
604 throwForUserNameConstraints(startWithDisallowedCharacter, {"ipmi"}),
605 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
606 }
607
TEST_F(UserMgrInTest,UserAddNotRootFailedWithInternalFailure)608 TEST_F(UserMgrInTest, UserAddNotRootFailedWithInternalFailure)
609 {
610 EXPECT_THROW(
611 UserMgr::executeUserAdd("user0", "ipmi,ssh", true, true),
612 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
613 }
614
TEST_F(UserMgrInTest,UserDeleteNotRootFailedWithInternalFailure)615 TEST_F(UserMgrInTest, UserDeleteNotRootFailedWithInternalFailure)
616 {
617 EXPECT_THROW(
618 UserMgr::executeUserDelete("user0"),
619 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
620 }
621
TEST_F(UserMgrInTest,ThrowForMaxGrpUserCountThrowsNoResourceWhenIpmiUserExceedLimit)622 TEST_F(UserMgrInTest,
623 ThrowForMaxGrpUserCountThrowsNoResourceWhenIpmiUserExceedLimit)
624 {
625 EXPECT_CALL(*this, getIpmiUsersCount()).WillOnce(Return(ipmiMaxUsers));
626 EXPECT_THROW(
627 throwForMaxGrpUserCount({"ipmi"}),
628 sdbusplus::xyz::openbmc_project::User::Common::Error::NoResource);
629 }
630
TEST_F(UserMgrInTest,CreateUserThrowsInternalFailureWhenExecuteUserAddFails)631 TEST_F(UserMgrInTest, CreateUserThrowsInternalFailureWhenExecuteUserAddFails)
632 {
633 EXPECT_CALL(*this, executeUserAdd)
634 .WillOnce(testing::Throw(
635 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
636 EXPECT_THROW(
637 createUser("whatever", {"redfish"}, "", true),
638 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
639 }
640
TEST_F(UserMgrInTest,DeleteUserThrowsInternalFailureWhenExecuteUserDeleteFails)641 TEST_F(UserMgrInTest, DeleteUserThrowsInternalFailureWhenExecuteUserDeleteFails)
642 {
643 std::string username = "user";
644 EXPECT_NO_THROW(
645 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
646 EXPECT_CALL(*this, executeUserDelete(testing::StrEq(username)))
647 .WillOnce(testing::Throw(
648 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()))
649 .WillOnce(testing::DoDefault());
650
651 EXPECT_THROW(
652 deleteUser(username),
653 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
654 EXPECT_NO_THROW(UserMgr::deleteUser(username));
655 }
656
TEST_F(UserMgrInTest,DeleteUserThrowsInternalFailureWhenExecuteUserClearFailRecords)657 TEST_F(UserMgrInTest,
658 DeleteUserThrowsInternalFailureWhenExecuteUserClearFailRecords)
659 {
660 const char* username = "user";
661 EXPECT_NO_THROW(
662 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
663 EXPECT_CALL(*this, executeUserClearFailRecords(testing::StrEq(username)))
664 .WillOnce(testing::Throw(
665 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()))
666 .WillOnce(testing::DoDefault());
667
668 EXPECT_THROW(
669 deleteUser(username),
670 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
671 EXPECT_NO_THROW(UserMgr::deleteUser(username));
672 }
673
TEST_F(UserMgrInTest,ThrowForInvalidPrivilegeThrowsWhenPrivilegeIsInvalid)674 TEST_F(UserMgrInTest, ThrowForInvalidPrivilegeThrowsWhenPrivilegeIsInvalid)
675 {
676 EXPECT_THROW(
677 throwForInvalidPrivilege("whatever"),
678 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
679 }
680
TEST_F(UserMgrInTest,ThrowForInvalidPrivilegeNoThrowWhenPrivilegeIsValid)681 TEST_F(UserMgrInTest, ThrowForInvalidPrivilegeNoThrowWhenPrivilegeIsValid)
682 {
683 EXPECT_NO_THROW(throwForInvalidPrivilege("priv-admin"));
684 EXPECT_NO_THROW(throwForInvalidPrivilege("priv-operator"));
685 EXPECT_NO_THROW(throwForInvalidPrivilege("priv-user"));
686 }
687
TEST_F(UserMgrInTest,ThrowForInvalidGroupsThrowsWhenGroupIsInvalid)688 TEST_F(UserMgrInTest, ThrowForInvalidGroupsThrowsWhenGroupIsInvalid)
689 {
690 EXPECT_THROW(
691 throwForInvalidGroups({"whatever"}),
692 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
693 EXPECT_THROW(
694 throwForInvalidGroups({"web"}),
695 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
696 }
697
TEST_F(UserMgrInTest,ThrowForInvalidGroupsNoThrowWhenGroupIsValid)698 TEST_F(UserMgrInTest, ThrowForInvalidGroupsNoThrowWhenGroupIsValid)
699 {
700 EXPECT_NO_THROW(throwForInvalidGroups({"ipmi"}));
701 EXPECT_NO_THROW(throwForInvalidGroups({"ssh"}));
702 EXPECT_NO_THROW(throwForInvalidGroups({"redfish"}));
703 EXPECT_NO_THROW(throwForInvalidGroups({"hostconsole"}));
704 }
705
TEST_F(UserMgrInTest,RenameUserOnSuccess)706 TEST_F(UserMgrInTest, RenameUserOnSuccess)
707 {
708 std::string username = "user001";
709 EXPECT_NO_THROW(
710 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
711 std::string newUsername = "user002";
712
713 EXPECT_NO_THROW(UserMgr::renameUser(username, newUsername));
714
715 // old username doesn't exist
716 EXPECT_THROW(getUserInfo(username),
717 sdbusplus::xyz::openbmc_project::User::Common::Error::
718 UserNameDoesNotExist);
719
720 UserInfoMap userInfo = getUserInfo(newUsername);
721 EXPECT_EQ(std::get<Privilege>(userInfo["UserPrivilege"]), "priv-user");
722 EXPECT_THAT(std::get<GroupList>(userInfo["UserGroups"]),
723 testing::UnorderedElementsAre("redfish", "ssh"));
724 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
725
726 EXPECT_NO_THROW(UserMgr::deleteUser(newUsername));
727 }
728
TEST_F(UserMgrInTest,RenameUserThrowsInternalFailureIfExecuteUserModifyFails)729 TEST_F(UserMgrInTest, RenameUserThrowsInternalFailureIfExecuteUserModifyFails)
730 {
731 std::string username = "user001";
732 EXPECT_NO_THROW(
733 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
734 std::string newUsername = "user002";
735
736 EXPECT_CALL(*this, executeUserRename(testing::StrEq(username),
737 testing::StrEq(newUsername)))
738 .WillOnce(testing::Throw(
739 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
740 EXPECT_THROW(
741 UserMgr::renameUser(username, newUsername),
742 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
743
744 // The original user is unchanged
745 UserInfoMap userInfo = getUserInfo(username);
746 EXPECT_EQ(std::get<Privilege>(userInfo["UserPrivilege"]), "priv-user");
747 EXPECT_THAT(std::get<GroupList>(userInfo["UserGroups"]),
748 testing::UnorderedElementsAre("redfish", "ssh"));
749 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
750
751 EXPECT_NO_THROW(UserMgr::deleteUser(username));
752 }
753
TEST_F(UserMgrInTest,DefaultUserModifyFailedWithInternalFailure)754 TEST_F(UserMgrInTest, DefaultUserModifyFailedWithInternalFailure)
755 {
756 EXPECT_THROW(
757 UserMgr::executeUserRename("user0", "user1"),
758 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
759 EXPECT_THROW(
760 UserMgr::executeUserModify("user0", "ssh", true),
761 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
762 }
763
TEST_F(UserMgrInTest,UpdateGroupsAndPrivOnSuccess)764 TEST_F(UserMgrInTest, UpdateGroupsAndPrivOnSuccess)
765 {
766 std::string username = "user001";
767 EXPECT_NO_THROW(
768 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
769 EXPECT_NO_THROW(
770 updateGroupsAndPriv(username, {"ipmi", "ssh"}, "priv-admin"));
771 UserInfoMap userInfo = getUserInfo(username);
772 EXPECT_EQ(std::get<Privilege>(userInfo["UserPrivilege"]), "priv-admin");
773 EXPECT_THAT(std::get<GroupList>(userInfo["UserGroups"]),
774 testing::UnorderedElementsAre("ipmi", "ssh"));
775 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
776 EXPECT_NO_THROW(UserMgr::deleteUser(username));
777 }
778
TEST_F(UserMgrInTest,UpdateGroupsAndPrivThrowsInternalFailureIfExecuteUserModifyFail)779 TEST_F(UserMgrInTest,
780 UpdateGroupsAndPrivThrowsInternalFailureIfExecuteUserModifyFail)
781 {
782 std::string username = "user001";
783 EXPECT_NO_THROW(
784 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
785 EXPECT_CALL(*this, executeUserModify(testing::StrEq(username), testing::_,
786 testing::_))
787 .WillOnce(testing::Throw(
788 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
789 EXPECT_THROW(
790 updateGroupsAndPriv(username, {"ipmi", "ssh"}, "priv-admin"),
791 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
792 EXPECT_NO_THROW(UserMgr::deleteUser(username));
793 }
794
TEST_F(UserMgrInTest,MinPasswordLengthReturnsIfValueIsTheSame)795 TEST_F(UserMgrInTest, MinPasswordLengthReturnsIfValueIsTheSame)
796 {
797 initializeAccountPolicy();
798 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
799 UserMgr::minPasswordLength(8);
800 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
801 }
802
TEST_F(UserMgrInTest,MinPasswordLengthRejectsTooShortPasswordWithInvalidArgument)803 TEST_F(UserMgrInTest,
804 MinPasswordLengthRejectsTooShortPasswordWithInvalidArgument)
805 {
806 initializeAccountPolicy();
807 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
808 EXPECT_THROW(
809 UserMgr::minPasswordLength(minPasswdLength - 1),
810 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
811 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
812 }
813
TEST_F(UserMgrInTest,MinPasswordLengthOnSuccess)814 TEST_F(UserMgrInTest, MinPasswordLengthOnSuccess)
815 {
816 initializeAccountPolicy();
817 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
818 UserMgr::minPasswordLength(16);
819 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 16);
820 }
821
TEST_F(UserMgrInTest,MinPasswordLengthOnFailure)822 TEST_F(UserMgrInTest, MinPasswordLengthOnFailure)
823 {
824 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWQualityConfigFile));
825 initializeAccountPolicy();
826 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
827 EXPECT_THROW(
828 UserMgr::minPasswordLength(16),
829 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
830 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
831 }
832
TEST_F(UserMgrInTest,MinPasswordLengthGreaterThanMaxPasswordLength)833 TEST_F(UserMgrInTest, MinPasswordLengthGreaterThanMaxPasswordLength)
834 {
835 initializeAccountPolicy();
836
837 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
838 EXPECT_THROW(
839 UserMgr::minPasswordLength(maxPasswdLength + 1),
840 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
841 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
842 }
843
TEST_F(UserMgrInTest,RememberOldPasswordTimesReturnsIfValueIsTheSame)844 TEST_F(UserMgrInTest, RememberOldPasswordTimesReturnsIfValueIsTheSame)
845 {
846 initializeAccountPolicy();
847 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 0);
848 UserMgr::rememberOldPasswordTimes(8);
849 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 8);
850 UserMgr::rememberOldPasswordTimes(8);
851 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 8);
852 }
853
TEST_F(UserMgrInTest,RememberOldPasswordTimesOnSuccess)854 TEST_F(UserMgrInTest, RememberOldPasswordTimesOnSuccess)
855 {
856 initializeAccountPolicy();
857 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 0);
858 UserMgr::rememberOldPasswordTimes(16);
859 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 16);
860 }
861
TEST_F(UserMgrInTest,RememberOldPasswordTimesOnFailure)862 TEST_F(UserMgrInTest, RememberOldPasswordTimesOnFailure)
863 {
864 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWHistoryConfigFile));
865 initializeAccountPolicy();
866 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 0);
867 EXPECT_THROW(
868 UserMgr::rememberOldPasswordTimes(16),
869 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
870 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 0);
871 }
872
TEST_F(UserMgrInTest,MaxLoginAttemptBeforeLockoutReturnsIfValueIsTheSame)873 TEST_F(UserMgrInTest, MaxLoginAttemptBeforeLockoutReturnsIfValueIsTheSame)
874 {
875 initializeAccountPolicy();
876 EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 2);
877 UserMgr::maxLoginAttemptBeforeLockout(2);
878 EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 2);
879 }
880
TEST_F(UserMgrInTest,MaxLoginAttemptBeforeLockoutOnSuccess)881 TEST_F(UserMgrInTest, MaxLoginAttemptBeforeLockoutOnSuccess)
882 {
883 initializeAccountPolicy();
884 EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 2);
885 UserMgr::maxLoginAttemptBeforeLockout(16);
886 EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 16);
887 }
888
TEST_F(UserMgrInTest,MaxLoginAttemptBeforeLockoutOnFailure)889 TEST_F(UserMgrInTest, MaxLoginAttemptBeforeLockoutOnFailure)
890 {
891 initializeAccountPolicy();
892 EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
893 EXPECT_THROW(
894 UserMgr::maxLoginAttemptBeforeLockout(16),
895 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
896 EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 2);
897 }
898
TEST_F(UserMgrInTest,AccountUnlockTimeoutReturnsIfValueIsTheSame)899 TEST_F(UserMgrInTest, AccountUnlockTimeoutReturnsIfValueIsTheSame)
900 {
901 initializeAccountPolicy();
902 EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 3);
903 UserMgr::accountUnlockTimeout(3);
904 EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 3);
905 }
906
TEST_F(UserMgrInTest,AccountUnlockTimeoutOnSuccess)907 TEST_F(UserMgrInTest, AccountUnlockTimeoutOnSuccess)
908 {
909 initializeAccountPolicy();
910 EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 3);
911 UserMgr::accountUnlockTimeout(16);
912 EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 16);
913 }
914
TEST_F(UserMgrInTest,AccountUnlockTimeoutOnFailure)915 TEST_F(UserMgrInTest, AccountUnlockTimeoutOnFailure)
916 {
917 initializeAccountPolicy();
918 EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
919 EXPECT_THROW(
920 UserMgr::accountUnlockTimeout(16),
921 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
922 EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 3);
923 }
924
TEST_F(UserMgrInTest,UserEnableOnSuccess)925 TEST_F(UserMgrInTest, UserEnableOnSuccess)
926 {
927 std::string username = "user001";
928 EXPECT_NO_THROW(
929 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
930 UserInfoMap userInfo = getUserInfo(username);
931 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
932
933 EXPECT_NO_THROW(userEnable(username, false));
934
935 userInfo = getUserInfo(username);
936 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), false);
937
938 EXPECT_NO_THROW(UserMgr::deleteUser(username));
939 }
940
TEST_F(UserMgrInTest,CreateDeleteUserSuccessForHostConsole)941 TEST_F(UserMgrInTest, CreateDeleteUserSuccessForHostConsole)
942 {
943 std::string username = "user001";
944 EXPECT_NO_THROW(
945 UserMgr::createUser(username, {"hostconsole"}, "priv-user", true));
946 EXPECT_NO_THROW(UserMgr::deleteUser(username));
947 EXPECT_NO_THROW(
948 UserMgr::createUser(username, {"hostconsole"}, "priv-admin", true));
949 EXPECT_NO_THROW(UserMgr::deleteUser(username));
950 EXPECT_NO_THROW(
951 UserMgr::createUser(username, {"hostconsole"}, "priv-operator", true));
952 EXPECT_NO_THROW(UserMgr::deleteUser(username));
953 }
954
TEST_F(UserMgrInTest,UserEnableThrowsInternalFailureIfExecuteUserModifyFail)955 TEST_F(UserMgrInTest, UserEnableThrowsInternalFailureIfExecuteUserModifyFail)
956 {
957 std::string username = "user001";
958 EXPECT_NO_THROW(
959 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
960 UserInfoMap userInfo = getUserInfo(username);
961 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
962
963 EXPECT_CALL(*this, executeUserModifyUserEnable(testing::StrEq(username),
964 testing::Eq(false)))
965 .WillOnce(testing::Throw(
966 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
967 EXPECT_THROW(
968 userEnable(username, false),
969 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
970
971 userInfo = getUserInfo(username);
972 // Stay unchanged
973 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
974
975 EXPECT_NO_THROW(UserMgr::deleteUser(username));
976 }
977
TEST_F(UserMgrInTest,UserLockedForFailedAttemptReturnsFalseIfMaxLoginAttemptBeforeLockoutIsZero)978 TEST_F(
979 UserMgrInTest,
980 UserLockedForFailedAttemptReturnsFalseIfMaxLoginAttemptBeforeLockoutIsZero)
981 {
982 EXPECT_FALSE(userLockedForFailedAttempt("whatever"));
983 }
984
TEST_F(UserMgrInTest,UserLockedForFailedAttemptZeroFailuresReturnsFalse)985 TEST_F(UserMgrInTest, UserLockedForFailedAttemptZeroFailuresReturnsFalse)
986 {
987 std::string username = "user001";
988 initializeAccountPolicy();
989 // Example output from BMC
990 // root:~# faillock --user root
991 // root:
992 // When Type Source Valid
993 std::vector<std::string> output = {"whatever",
994 "When Type Source Valid"};
995 EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
996 .WillOnce(testing::Return(output));
997
998 EXPECT_FALSE(userLockedForFailedAttempt(username));
999 }
1000
TEST_F(UserMgrInTest,UserLockedForFailedAttemptFailIfGetFailedAttemptFail)1001 TEST_F(UserMgrInTest, UserLockedForFailedAttemptFailIfGetFailedAttemptFail)
1002 {
1003 std::string username = "user001";
1004 initializeAccountPolicy();
1005 EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
1006 .WillOnce(testing::Throw(
1007 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
1008
1009 EXPECT_THROW(
1010 userLockedForFailedAttempt(username),
1011 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
1012 }
1013
TEST_F(UserMgrInTest,UserLockedForFailedAttemptThrowsInternalFailureIfWrongDateFormat)1014 TEST_F(UserMgrInTest,
1015 UserLockedForFailedAttemptThrowsInternalFailureIfWrongDateFormat)
1016 {
1017 std::string username = "user001";
1018 initializeAccountPolicy();
1019
1020 // Choose a date in the past.
1021 std::vector<std::string> output = {"whatever",
1022 "10/24/2002 00:00:00 type source V"};
1023 EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
1024 .WillOnce(testing::Return(output));
1025
1026 EXPECT_THROW(
1027 userLockedForFailedAttempt(username),
1028 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
1029 }
1030
TEST_F(UserMgrInTest,UserLockedForFailedAttemptReturnsFalseIfLastFailTimeHasTimedOut)1031 TEST_F(UserMgrInTest,
1032 UserLockedForFailedAttemptReturnsFalseIfLastFailTimeHasTimedOut)
1033 {
1034 std::string username = "user001";
1035 initializeAccountPolicy();
1036
1037 // Choose a date in the past.
1038 std::vector<std::string> output = {"whatever",
1039 "2002-10-24 00:00:00 type source V"};
1040 EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
1041 .WillOnce(testing::Return(output));
1042
1043 EXPECT_EQ(userLockedForFailedAttempt(username), false);
1044 }
1045
TEST_F(UserMgrInTest,CheckAndThrowForDisallowedGroupCreationOnSuccess)1046 TEST_F(UserMgrInTest, CheckAndThrowForDisallowedGroupCreationOnSuccess)
1047 {
1048 // Base Redfish Roles
1049 EXPECT_NO_THROW(
1050 checkAndThrowForDisallowedGroupCreation("openbmc_rfr_Administrator"));
1051 EXPECT_NO_THROW(
1052 checkAndThrowForDisallowedGroupCreation("openbmc_rfr_Operator"));
1053 EXPECT_NO_THROW(
1054 checkAndThrowForDisallowedGroupCreation("openbmc_rfr_ReadOnly"));
1055 // Base Redfish Privileges
1056 EXPECT_NO_THROW(
1057 checkAndThrowForDisallowedGroupCreation("openbmc_rfp_Login"));
1058 EXPECT_NO_THROW(checkAndThrowForDisallowedGroupCreation(
1059 "openbmc_rfp_ConfigureManager"));
1060 EXPECT_NO_THROW(
1061 checkAndThrowForDisallowedGroupCreation("openbmc_rfp_ConfigureUsers"));
1062 EXPECT_NO_THROW(
1063 checkAndThrowForDisallowedGroupCreation("openbmc_rfp_ConfigureSelf"));
1064 EXPECT_NO_THROW(checkAndThrowForDisallowedGroupCreation(
1065 "openbmc_rfp_ConfigureComponents"));
1066 // OEM Redfish Roles
1067 EXPECT_NO_THROW(
1068 checkAndThrowForDisallowedGroupCreation("openbmc_orfr_PowerService"));
1069 // OEM Redfish Privileges
1070 EXPECT_NO_THROW(
1071 checkAndThrowForDisallowedGroupCreation("openbmc_orfp_PowerService"));
1072 }
1073
TEST_F(UserMgrInTest,CheckAndThrowForDisallowedGroupCreationThrowsIfGroupNameTooLong)1074 TEST_F(UserMgrInTest,
1075 CheckAndThrowForDisallowedGroupCreationThrowsIfGroupNameTooLong)
1076 {
1077 std::string groupName(maxSystemGroupNameLength + 1, 'A');
1078 EXPECT_THROW(
1079 checkAndThrowForDisallowedGroupCreation(groupName),
1080 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1081 }
1082
TEST_F(UserMgrInTest,CheckAndThrowForDisallowedGroupCreationThrowsIfGroupNameHasDisallowedCharacters)1083 TEST_F(
1084 UserMgrInTest,
1085 CheckAndThrowForDisallowedGroupCreationThrowsIfGroupNameHasDisallowedCharacters)
1086 {
1087 EXPECT_THROW(
1088 checkAndThrowForDisallowedGroupCreation("openbmc_rfp_?owerService"),
1089 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1090 EXPECT_THROW(
1091 checkAndThrowForDisallowedGroupCreation("openbmc_rfp_-owerService"),
1092 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1093 }
1094
TEST_F(UserMgrInTest,CheckAndThrowForDisallowedGroupCreationThrowsIfGroupNameHasDisallowedPrefix)1095 TEST_F(
1096 UserMgrInTest,
1097 CheckAndThrowForDisallowedGroupCreationThrowsIfGroupNameHasDisallowedPrefix)
1098 {
1099 EXPECT_THROW(
1100 checkAndThrowForDisallowedGroupCreation("google_rfp_"),
1101 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1102 EXPECT_THROW(
1103 checkAndThrowForDisallowedGroupCreation("com_rfp_"),
1104 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1105 }
1106
TEST_F(UserMgrInTest,CheckAndThrowForMaxGroupCountOnSuccess)1107 TEST_F(UserMgrInTest, CheckAndThrowForMaxGroupCountOnSuccess)
1108 {
1109 constexpr size_t predefGroupCount = 4;
1110
1111 EXPECT_THAT(allGroups().size(), predefGroupCount);
1112 for (size_t i = 0; i < maxSystemGroupCount - predefGroupCount; ++i)
1113 {
1114 std::string groupName = "openbmc_rfr_role";
1115 groupName += std::to_string(i);
1116 EXPECT_NO_THROW(createGroup(groupName));
1117 }
1118 EXPECT_THROW(
1119 createGroup("openbmc_rfr_AnotherRole"),
1120 sdbusplus::xyz::openbmc_project::User::Common::Error::NoResource);
1121 for (size_t i = 0; i < maxSystemGroupCount - predefGroupCount; ++i)
1122 {
1123 std::string groupName = "openbmc_rfr_role";
1124 groupName += std::to_string(i);
1125 EXPECT_NO_THROW(deleteGroup(groupName));
1126 }
1127 }
1128
TEST_F(UserMgrInTest,CheckAndThrowForGroupExist)1129 TEST_F(UserMgrInTest, CheckAndThrowForGroupExist)
1130 {
1131 std::string groupName = "openbmc_rfr_role";
1132 EXPECT_NO_THROW(createGroup(groupName));
1133 EXPECT_THROW(
1134 createGroup(groupName),
1135 sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1136 EXPECT_NO_THROW(deleteGroup(groupName));
1137 }
1138
TEST_F(UserMgrInTest,ByDefaultAllGroupsArePredefinedGroups)1139 TEST_F(UserMgrInTest, ByDefaultAllGroupsArePredefinedGroups)
1140 {
1141 EXPECT_THAT(allGroups(), testing::UnorderedElementsAre(
1142 "redfish", "ipmi", "ssh", "hostconsole"));
1143 }
1144
TEST_F(UserMgrInTest,AddGroupThrowsIfPreDefinedGroupAdd)1145 TEST_F(UserMgrInTest, AddGroupThrowsIfPreDefinedGroupAdd)
1146 {
1147 EXPECT_THROW(
1148 createGroup("ipmi"),
1149 sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1150 EXPECT_THROW(
1151 createGroup("redfish"),
1152 sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1153 EXPECT_THROW(
1154 createGroup("ssh"),
1155 sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1156 EXPECT_THROW(
1157 createGroup("hostconsole"),
1158 sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1159 }
1160
TEST_F(UserMgrInTest,DeleteGroupThrowsIfGroupIsNotAllowedToChange)1161 TEST_F(UserMgrInTest, DeleteGroupThrowsIfGroupIsNotAllowedToChange)
1162 {
1163 EXPECT_THROW(
1164 deleteGroup("ipmi"),
1165 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1166 EXPECT_THROW(
1167 deleteGroup("redfish"),
1168 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1169 EXPECT_THROW(
1170 deleteGroup("ssh"),
1171 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1172 EXPECT_THROW(
1173 deleteGroup("hostconsole"),
1174 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1175 }
1176
TEST_F(UserMgrInTest,CreateGroupThrowsInternalFailureWhenExecuteGroupCreateFails)1177 TEST_F(UserMgrInTest,
1178 CreateGroupThrowsInternalFailureWhenExecuteGroupCreateFails)
1179 {
1180 EXPECT_CALL(*this, executeGroupCreation)
1181 .WillOnce(testing::Throw(
1182 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
1183 EXPECT_THROW(
1184 createGroup("openbmc_rfr_role1"),
1185 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
1186 }
1187
TEST_F(UserMgrInTest,DeleteGroupThrowsInternalFailureWhenExecuteGroupDeleteFails)1188 TEST_F(UserMgrInTest,
1189 DeleteGroupThrowsInternalFailureWhenExecuteGroupDeleteFails)
1190 {
1191 std::string groupName = "openbmc_rfr_role1";
1192 EXPECT_NO_THROW(UserMgr::createGroup(groupName));
1193 EXPECT_CALL(*this, executeGroupDeletion(testing::StrEq(groupName)))
1194 .WillOnce(testing::Throw(
1195 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()))
1196 .WillOnce(testing::DoDefault());
1197
1198 EXPECT_THROW(
1199 deleteGroup(groupName),
1200 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
1201 EXPECT_NO_THROW(UserMgr::deleteGroup(groupName));
1202 }
1203
TEST_F(UserMgrInTest,CheckAndThrowForGroupNotExist)1204 TEST_F(UserMgrInTest, CheckAndThrowForGroupNotExist)
1205 {
1206 EXPECT_THROW(deleteGroup("whatever"),
1207 sdbusplus::xyz::openbmc_project::User::Common::Error::
1208 GroupNameDoesNotExist);
1209 }
1210
TEST(ReadAllGroupsOnSystemTest,OnlyReturnsPredefinedGroups)1211 TEST(ReadAllGroupsOnSystemTest, OnlyReturnsPredefinedGroups)
1212 {
1213 EXPECT_THAT(
1214 UserMgr::readAllGroupsOnSystem(),
1215 testing::UnorderedElementsAre("redfish", "ipmi", "ssh", "hostconsole"));
1216 }
1217
1218 } // namespace user
1219 } // namespace phosphor
1220