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