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(std::ofstream::failbit | std::ofstream::badbit |
240 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).WillByDefault(testing::Return(true));
278 testing::Return();
279 });
280
281 ON_CALL(*this, executeUserAdd(testing::_, testing::_, testing::_,
282 testing::Eq(false)))
283 .WillByDefault([this]() {
284 ON_CALL(*this, isUserEnabled).WillByDefault(testing::Return(false));
285 testing::Return();
286 });
287
288 ON_CALL(*this, executeUserDelete).WillByDefault(testing::Return());
289
290 ON_CALL(*this, executeUserClearFailRecords)
291 .WillByDefault(testing::Return());
292
293 ON_CALL(*this, getIpmiUsersCount).WillByDefault(testing::Return(0));
294
295 ON_CALL(*this, executeUserRename).WillByDefault(testing::Return());
296
297 ON_CALL(*this, executeUserModify(testing::_, testing::_, testing::_))
298 .WillByDefault(testing::Return());
299
300 ON_CALL(*this,
301 executeUserModifyUserEnable(testing::_, testing::Eq(true)))
302 .WillByDefault([this]() {
303 ON_CALL(*this, isUserEnabled).WillByDefault(testing::Return(true));
304 testing::Return();
305 });
306
307 ON_CALL(*this,
308 executeUserModifyUserEnable(testing::_, testing::Eq(false)))
309 .WillByDefault([this]() {
310 ON_CALL(*this, isUserEnabled).WillByDefault(testing::Return(false));
311 testing::Return();
312 });
313
314 ON_CALL(*this, executeGroupCreation(testing::_))
315 .WillByDefault(testing::Return());
316
317 ON_CALL(*this, executeGroupDeletion(testing::_))
318 .WillByDefault(testing::Return());
319
320 ON_CALL(*this, executeGroupCreation).WillByDefault(testing::Return());
321
322 ON_CALL(*this, executeGroupDeletion).WillByDefault(testing::Return());
323 }
324
~UserMgrInTest()325 ~UserMgrInTest() override
326 {
327 EXPECT_NO_THROW(removeFile(tempFaillockConfigFile));
328 EXPECT_NO_THROW(removeFile(tempPWHistoryConfigFile));
329 EXPECT_NO_THROW(removeFile(tempPWQualityConfigFile));
330 }
331
332 MOCK_METHOD(void, executeUserAdd, (const char*, const char*, bool, bool),
333 (override));
334
335 MOCK_METHOD(void, executeUserDelete, (const char*), (override));
336
337 MOCK_METHOD(void, executeUserClearFailRecords, (const char*), (override));
338
339 MOCK_METHOD(size_t, getIpmiUsersCount, (), (override));
340
341 MOCK_METHOD(void, executeUserRename, (const char*, const char*),
342 (override));
343
344 MOCK_METHOD(void, executeUserModify, (const char*, const char*, bool),
345 (override));
346
347 MOCK_METHOD(void, executeUserModifyUserEnable, (const char*, bool),
348 (override));
349
350 MOCK_METHOD(std::vector<std::string>, getFailedAttempt, (const char*),
351 (override));
352
353 MOCK_METHOD(void, executeGroupCreation, (const char*), (override));
354
355 MOCK_METHOD(void, executeGroupDeletion, (const char*), (override));
356
357 MOCK_METHOD(bool, isUserEnabled, (const std::string& userName), (override));
358
359 protected:
360 static sdbusplus::bus_t busInTest;
361 std::string tempFaillockConfigFile;
362 std::string tempPWHistoryConfigFile;
363 std::string tempPWQualityConfigFile;
364 };
365
366 sdbusplus::bus_t UserMgrInTest::busInTest = sdbusplus::bus::new_default();
367
TEST_F(UserMgrInTest,GetPamModuleConfValueOnSuccess)368 TEST_F(UserMgrInTest, GetPamModuleConfValueOnSuccess)
369 {
370 std::string minlen;
371 EXPECT_EQ(getPamModuleConfValue(tempPWQualityConfigFile, "minlen", minlen),
372 0);
373 EXPECT_EQ(minlen, "8");
374 std::string deny;
375 EXPECT_EQ(getPamModuleConfValue(tempFaillockConfigFile, "deny", deny), 0);
376 EXPECT_EQ(deny, "2");
377 std::string remember;
378 EXPECT_EQ(
379 getPamModuleConfValue(tempPWHistoryConfigFile, "remember", remember),
380 0);
381 EXPECT_EQ(remember, "0");
382 }
383
TEST_F(UserMgrInTest,SetPamModuleConfValueOnSuccess)384 TEST_F(UserMgrInTest, SetPamModuleConfValueOnSuccess)
385 {
386 EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
387 0);
388 std::string minlen;
389 EXPECT_EQ(getPamModuleConfValue(tempPWQualityConfigFile, "minlen", minlen),
390 0);
391 EXPECT_EQ(minlen, "16");
392
393 EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), 0);
394 std::string deny;
395 EXPECT_EQ(getPamModuleConfValue(tempFaillockConfigFile, "deny", deny), 0);
396 EXPECT_EQ(deny, "3");
397
398 EXPECT_EQ(setPamModuleConfValue(tempPWHistoryConfigFile, "remember", "1"),
399 0);
400 std::string remember;
401 EXPECT_EQ(
402 getPamModuleConfValue(tempPWHistoryConfigFile, "remember", remember),
403 0);
404 EXPECT_EQ(remember, "1");
405 }
406
TEST_F(UserMgrInTest,SetPamModuleConfValueTempFileOnSuccess)407 TEST_F(UserMgrInTest, SetPamModuleConfValueTempFileOnSuccess)
408 {
409 EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
410 0);
411
412 std::string tmpFile = tempPWQualityConfigFile + "_tmp";
413 EXPECT_FALSE(std::filesystem::exists(tmpFile));
414
415 EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), 0);
416
417 tmpFile = tempFaillockConfigFile + "_tmp";
418 EXPECT_FALSE(std::filesystem::exists(tmpFile));
419
420 EXPECT_EQ(setPamModuleConfValue(tempPWHistoryConfigFile, "remember", "1"),
421 0);
422
423 tmpFile = tempPWHistoryConfigFile + "_tmp";
424 EXPECT_FALSE(std::filesystem::exists(tmpFile));
425 }
426
TEST_F(UserMgrInTest,GetPamModuleConfValueOnFailure)427 TEST_F(UserMgrInTest, GetPamModuleConfValueOnFailure)
428 {
429 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWQualityConfigFile));
430 std::string minlen;
431 EXPECT_EQ(getPamModuleConfValue(tempPWQualityConfigFile, "minlen", minlen),
432 -1);
433
434 EXPECT_NO_THROW(removeFile(tempPWQualityConfigFile));
435 EXPECT_EQ(getPamModuleConfValue(tempPWQualityConfigFile, "minlen", minlen),
436 -1);
437
438 EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
439 std::string deny;
440 EXPECT_EQ(getPamModuleConfValue(tempFaillockConfigFile, "deny", deny), -1);
441
442 EXPECT_NO_THROW(removeFile(tempFaillockConfigFile));
443 EXPECT_EQ(getPamModuleConfValue(tempFaillockConfigFile, "deny", deny), -1);
444
445 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWHistoryConfigFile));
446 std::string remember;
447 EXPECT_EQ(
448 getPamModuleConfValue(tempPWHistoryConfigFile, "remember", remember),
449 -1);
450
451 EXPECT_NO_THROW(removeFile(tempPWHistoryConfigFile));
452 EXPECT_EQ(
453 getPamModuleConfValue(tempPWHistoryConfigFile, "remember", remember),
454 -1);
455 }
456
TEST_F(UserMgrInTest,SetPamModuleConfValueOnFailure)457 TEST_F(UserMgrInTest, SetPamModuleConfValueOnFailure)
458 {
459 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWQualityConfigFile));
460 EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
461 -1);
462
463 EXPECT_NO_THROW(removeFile(tempPWQualityConfigFile));
464 EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
465 -1);
466
467 EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
468 EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), -1);
469
470 EXPECT_NO_THROW(removeFile(tempFaillockConfigFile));
471 EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), -1);
472
473 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWHistoryConfigFile));
474 EXPECT_EQ(setPamModuleConfValue(tempPWHistoryConfigFile, "remember", "1"),
475 -1);
476
477 EXPECT_NO_THROW(removeFile(tempPWHistoryConfigFile));
478 EXPECT_EQ(setPamModuleConfValue(tempPWHistoryConfigFile, "remember", "1"),
479 -1);
480 }
481
TEST_F(UserMgrInTest,SetPamModuleConfValueTempFileOnFailure)482 TEST_F(UserMgrInTest, SetPamModuleConfValueTempFileOnFailure)
483 {
484 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWQualityConfigFile));
485 EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
486 -1);
487
488 std::string tmpFile = tempPWQualityConfigFile + "_tmp";
489 EXPECT_FALSE(std::filesystem::exists(tmpFile));
490
491 EXPECT_NO_THROW(removeFile(tempPWQualityConfigFile));
492 EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
493 -1);
494
495 EXPECT_FALSE(std::filesystem::exists(tmpFile));
496
497 EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
498 EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), -1);
499
500 tmpFile = tempFaillockConfigFile + "_tmp";
501 EXPECT_FALSE(std::filesystem::exists(tmpFile));
502
503 EXPECT_NO_THROW(removeFile(tempFaillockConfigFile));
504 EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), -1);
505
506 EXPECT_FALSE(std::filesystem::exists(tmpFile));
507
508 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWHistoryConfigFile));
509 EXPECT_EQ(setPamModuleConfValue(tempPWHistoryConfigFile, "remember", "1"),
510 -1);
511
512 tmpFile = tempPWHistoryConfigFile + "_tmp";
513 EXPECT_FALSE(std::filesystem::exists(tmpFile));
514
515 EXPECT_NO_THROW(removeFile(tempPWHistoryConfigFile));
516 EXPECT_EQ(setPamModuleConfValue(tempPWHistoryConfigFile, "remember", "1"),
517 -1);
518
519 EXPECT_FALSE(std::filesystem::exists(tmpFile));
520 }
521
TEST_F(UserMgrInTest,IsUserExistEmptyInputThrowsError)522 TEST_F(UserMgrInTest, IsUserExistEmptyInputThrowsError)
523 {
524 EXPECT_THROW(
525 isUserExist(""),
526 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
527 }
528
TEST_F(UserMgrInTest,ThrowForUserDoesNotExistThrowsError)529 TEST_F(UserMgrInTest, ThrowForUserDoesNotExistThrowsError)
530 {
531 EXPECT_THROW(throwForUserDoesNotExist("whatever"),
532 sdbusplus::xyz::openbmc_project::User::Common::Error::
533 UserNameDoesNotExist);
534 }
535
TEST_F(UserMgrInTest,ThrowForUserExistsThrowsError)536 TEST_F(UserMgrInTest, ThrowForUserExistsThrowsError)
537 {
538 EXPECT_THROW(
539 throwForUserExists("root"),
540 sdbusplus::xyz::openbmc_project::User::Common::Error::UserNameExists);
541 }
542
TEST_F(UserMgrInTest,ThrowForUserNameConstraintsExceedIpmiMaxUserNameLenThrowsUserNameGroupFail)543 TEST_F(
544 UserMgrInTest,
545 ThrowForUserNameConstraintsExceedIpmiMaxUserNameLenThrowsUserNameGroupFail)
546 {
547 std::string strWith17Chars(17, 'A');
548 EXPECT_THROW(throwForUserNameConstraints(strWith17Chars, {"ipmi"}),
549 sdbusplus::xyz::openbmc_project::User::Common::Error::
550 UserNameGroupFail);
551 }
552
TEST_F(UserMgrInTest,ThrowForUserNameConstraintsExceedSystemMaxUserNameLenThrowsInvalidArgument)553 TEST_F(
554 UserMgrInTest,
555 ThrowForUserNameConstraintsExceedSystemMaxUserNameLenThrowsInvalidArgument)
556 {
557 std::string strWith31Chars(31, 'A');
558 EXPECT_THROW(
559 throwForUserNameConstraints(strWith31Chars, {}),
560 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
561 }
562
TEST_F(UserMgrInTest,ThrowForUserNameConstraintsRegexMismatchThrowsInvalidArgument)563 TEST_F(UserMgrInTest,
564 ThrowForUserNameConstraintsRegexMismatchThrowsInvalidArgument)
565 {
566 std::string startWithNumber = "0ABC";
567 std::string startWithDisallowedCharacter = "[test";
568 EXPECT_THROW(
569 throwForUserNameConstraints(startWithNumber, {"ipmi"}),
570 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
571 EXPECT_THROW(
572 throwForUserNameConstraints(startWithDisallowedCharacter, {"ipmi"}),
573 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
574 }
575
TEST_F(UserMgrInTest,UserAddNotRootFailedWithInternalFailure)576 TEST_F(UserMgrInTest, UserAddNotRootFailedWithInternalFailure)
577 {
578 EXPECT_THROW(
579 UserMgr::executeUserAdd("user0", "ipmi,ssh", true, true),
580 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
581 }
582
TEST_F(UserMgrInTest,UserDeleteNotRootFailedWithInternalFailure)583 TEST_F(UserMgrInTest, UserDeleteNotRootFailedWithInternalFailure)
584 {
585 EXPECT_THROW(
586 UserMgr::executeUserDelete("user0"),
587 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
588 }
589
TEST_F(UserMgrInTest,ThrowForMaxGrpUserCountThrowsNoResourceWhenIpmiUserExceedLimit)590 TEST_F(UserMgrInTest,
591 ThrowForMaxGrpUserCountThrowsNoResourceWhenIpmiUserExceedLimit)
592 {
593 EXPECT_CALL(*this, getIpmiUsersCount()).WillOnce(Return(ipmiMaxUsers));
594 EXPECT_THROW(
595 throwForMaxGrpUserCount({"ipmi"}),
596 sdbusplus::xyz::openbmc_project::User::Common::Error::NoResource);
597 }
598
TEST_F(UserMgrInTest,CreateUserThrowsInternalFailureWhenExecuteUserAddFails)599 TEST_F(UserMgrInTest, CreateUserThrowsInternalFailureWhenExecuteUserAddFails)
600 {
601 EXPECT_CALL(*this, executeUserAdd)
602 .WillOnce(testing::Throw(
603 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
604 EXPECT_THROW(
605 createUser("whatever", {"redfish"}, "", true),
606 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
607 }
608
TEST_F(UserMgrInTest,DeleteUserThrowsInternalFailureWhenExecuteUserDeleteFails)609 TEST_F(UserMgrInTest, DeleteUserThrowsInternalFailureWhenExecuteUserDeleteFails)
610 {
611 std::string username = "user";
612 EXPECT_NO_THROW(
613 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
614 EXPECT_CALL(*this, executeUserDelete(testing::StrEq(username)))
615 .WillOnce(testing::Throw(
616 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()))
617 .WillOnce(testing::DoDefault());
618
619 EXPECT_THROW(
620 deleteUser(username),
621 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
622 EXPECT_NO_THROW(UserMgr::deleteUser(username));
623 }
624
TEST_F(UserMgrInTest,DeleteUserThrowsInternalFailureWhenExecuteUserClearFailRecords)625 TEST_F(UserMgrInTest,
626 DeleteUserThrowsInternalFailureWhenExecuteUserClearFailRecords)
627 {
628 const char* username = "user";
629 EXPECT_NO_THROW(
630 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
631 EXPECT_CALL(*this, executeUserClearFailRecords(testing::StrEq(username)))
632 .WillOnce(testing::Throw(
633 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()))
634 .WillOnce(testing::DoDefault());
635
636 EXPECT_THROW(
637 deleteUser(username),
638 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
639 EXPECT_NO_THROW(UserMgr::deleteUser(username));
640 }
641
TEST_F(UserMgrInTest,ThrowForInvalidPrivilegeThrowsWhenPrivilegeIsInvalid)642 TEST_F(UserMgrInTest, ThrowForInvalidPrivilegeThrowsWhenPrivilegeIsInvalid)
643 {
644 EXPECT_THROW(
645 throwForInvalidPrivilege("whatever"),
646 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
647 }
648
TEST_F(UserMgrInTest,ThrowForInvalidPrivilegeNoThrowWhenPrivilegeIsValid)649 TEST_F(UserMgrInTest, ThrowForInvalidPrivilegeNoThrowWhenPrivilegeIsValid)
650 {
651 EXPECT_NO_THROW(throwForInvalidPrivilege("priv-admin"));
652 EXPECT_NO_THROW(throwForInvalidPrivilege("priv-operator"));
653 EXPECT_NO_THROW(throwForInvalidPrivilege("priv-user"));
654 }
655
TEST_F(UserMgrInTest,ThrowForInvalidGroupsThrowsWhenGroupIsInvalid)656 TEST_F(UserMgrInTest, ThrowForInvalidGroupsThrowsWhenGroupIsInvalid)
657 {
658 EXPECT_THROW(
659 throwForInvalidGroups({"whatever"}),
660 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
661 EXPECT_THROW(
662 throwForInvalidGroups({"web"}),
663 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
664 }
665
TEST_F(UserMgrInTest,ThrowForInvalidGroupsNoThrowWhenGroupIsValid)666 TEST_F(UserMgrInTest, ThrowForInvalidGroupsNoThrowWhenGroupIsValid)
667 {
668 EXPECT_NO_THROW(throwForInvalidGroups({"ipmi"}));
669 EXPECT_NO_THROW(throwForInvalidGroups({"ssh"}));
670 EXPECT_NO_THROW(throwForInvalidGroups({"redfish"}));
671 EXPECT_NO_THROW(throwForInvalidGroups({"hostconsole"}));
672 }
673
TEST_F(UserMgrInTest,RenameUserOnSuccess)674 TEST_F(UserMgrInTest, RenameUserOnSuccess)
675 {
676 std::string username = "user001";
677 EXPECT_NO_THROW(
678 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
679 std::string newUsername = "user002";
680
681 EXPECT_NO_THROW(UserMgr::renameUser(username, newUsername));
682
683 // old username doesn't exist
684 EXPECT_THROW(getUserInfo(username),
685 sdbusplus::xyz::openbmc_project::User::Common::Error::
686 UserNameDoesNotExist);
687
688 UserInfoMap userInfo = getUserInfo(newUsername);
689 EXPECT_EQ(std::get<Privilege>(userInfo["UserPrivilege"]), "priv-user");
690 EXPECT_THAT(std::get<GroupList>(userInfo["UserGroups"]),
691 testing::UnorderedElementsAre("redfish", "ssh"));
692 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
693
694 EXPECT_NO_THROW(UserMgr::deleteUser(newUsername));
695 }
696
TEST_F(UserMgrInTest,RenameUserThrowsInternalFailureIfExecuteUserModifyFails)697 TEST_F(UserMgrInTest, RenameUserThrowsInternalFailureIfExecuteUserModifyFails)
698 {
699 std::string username = "user001";
700 EXPECT_NO_THROW(
701 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
702 std::string newUsername = "user002";
703
704 EXPECT_CALL(*this, executeUserRename(testing::StrEq(username),
705 testing::StrEq(newUsername)))
706 .WillOnce(testing::Throw(
707 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
708 EXPECT_THROW(
709 UserMgr::renameUser(username, newUsername),
710 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
711
712 // The original user is unchanged
713 UserInfoMap userInfo = getUserInfo(username);
714 EXPECT_EQ(std::get<Privilege>(userInfo["UserPrivilege"]), "priv-user");
715 EXPECT_THAT(std::get<GroupList>(userInfo["UserGroups"]),
716 testing::UnorderedElementsAre("redfish", "ssh"));
717 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
718
719 EXPECT_NO_THROW(UserMgr::deleteUser(username));
720 }
721
TEST_F(UserMgrInTest,DefaultUserModifyFailedWithInternalFailure)722 TEST_F(UserMgrInTest, DefaultUserModifyFailedWithInternalFailure)
723 {
724 EXPECT_THROW(
725 UserMgr::executeUserRename("user0", "user1"),
726 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
727 EXPECT_THROW(
728 UserMgr::executeUserModify("user0", "ssh", true),
729 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
730 }
731
TEST_F(UserMgrInTest,UpdateGroupsAndPrivOnSuccess)732 TEST_F(UserMgrInTest, UpdateGroupsAndPrivOnSuccess)
733 {
734 std::string username = "user001";
735 EXPECT_NO_THROW(
736 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
737 EXPECT_NO_THROW(
738 updateGroupsAndPriv(username, {"ipmi", "ssh"}, "priv-admin"));
739 UserInfoMap userInfo = getUserInfo(username);
740 EXPECT_EQ(std::get<Privilege>(userInfo["UserPrivilege"]), "priv-admin");
741 EXPECT_THAT(std::get<GroupList>(userInfo["UserGroups"]),
742 testing::UnorderedElementsAre("ipmi", "ssh"));
743 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
744 EXPECT_NO_THROW(UserMgr::deleteUser(username));
745 }
746
TEST_F(UserMgrInTest,UpdateGroupsAndPrivThrowsInternalFailureIfExecuteUserModifyFail)747 TEST_F(UserMgrInTest,
748 UpdateGroupsAndPrivThrowsInternalFailureIfExecuteUserModifyFail)
749 {
750 std::string username = "user001";
751 EXPECT_NO_THROW(
752 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
753 EXPECT_CALL(*this, executeUserModify(testing::StrEq(username), testing::_,
754 testing::_))
755 .WillOnce(testing::Throw(
756 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
757 EXPECT_THROW(
758 updateGroupsAndPriv(username, {"ipmi", "ssh"}, "priv-admin"),
759 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
760 EXPECT_NO_THROW(UserMgr::deleteUser(username));
761 }
762
TEST_F(UserMgrInTest,MinPasswordLengthReturnsIfValueIsTheSame)763 TEST_F(UserMgrInTest, MinPasswordLengthReturnsIfValueIsTheSame)
764 {
765 initializeAccountPolicy();
766 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
767 UserMgr::minPasswordLength(8);
768 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
769 }
770
TEST_F(UserMgrInTest,MinPasswordLengthRejectsTooShortPasswordWithInvalidArgument)771 TEST_F(UserMgrInTest,
772 MinPasswordLengthRejectsTooShortPasswordWithInvalidArgument)
773 {
774 initializeAccountPolicy();
775 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
776 EXPECT_THROW(
777 UserMgr::minPasswordLength(minPasswdLength - 1),
778 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
779 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
780 }
781
TEST_F(UserMgrInTest,MinPasswordLengthOnSuccess)782 TEST_F(UserMgrInTest, MinPasswordLengthOnSuccess)
783 {
784 initializeAccountPolicy();
785 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
786 UserMgr::minPasswordLength(16);
787 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 16);
788 }
789
TEST_F(UserMgrInTest,MinPasswordLengthOnFailure)790 TEST_F(UserMgrInTest, MinPasswordLengthOnFailure)
791 {
792 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWQualityConfigFile));
793 initializeAccountPolicy();
794 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
795 EXPECT_THROW(
796 UserMgr::minPasswordLength(16),
797 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
798 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
799 }
800
TEST_F(UserMgrInTest,RememberOldPasswordTimesReturnsIfValueIsTheSame)801 TEST_F(UserMgrInTest, RememberOldPasswordTimesReturnsIfValueIsTheSame)
802 {
803 initializeAccountPolicy();
804 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 0);
805 UserMgr::rememberOldPasswordTimes(8);
806 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 8);
807 UserMgr::rememberOldPasswordTimes(8);
808 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 8);
809 }
810
TEST_F(UserMgrInTest,RememberOldPasswordTimesOnSuccess)811 TEST_F(UserMgrInTest, RememberOldPasswordTimesOnSuccess)
812 {
813 initializeAccountPolicy();
814 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 0);
815 UserMgr::rememberOldPasswordTimes(16);
816 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 16);
817 }
818
TEST_F(UserMgrInTest,RememberOldPasswordTimesOnFailure)819 TEST_F(UserMgrInTest, RememberOldPasswordTimesOnFailure)
820 {
821 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWHistoryConfigFile));
822 initializeAccountPolicy();
823 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 0);
824 EXPECT_THROW(
825 UserMgr::rememberOldPasswordTimes(16),
826 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
827 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 0);
828 }
829
TEST_F(UserMgrInTest,MaxLoginAttemptBeforeLockoutReturnsIfValueIsTheSame)830 TEST_F(UserMgrInTest, MaxLoginAttemptBeforeLockoutReturnsIfValueIsTheSame)
831 {
832 initializeAccountPolicy();
833 EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 2);
834 UserMgr::maxLoginAttemptBeforeLockout(2);
835 EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 2);
836 }
837
TEST_F(UserMgrInTest,MaxLoginAttemptBeforeLockoutOnSuccess)838 TEST_F(UserMgrInTest, MaxLoginAttemptBeforeLockoutOnSuccess)
839 {
840 initializeAccountPolicy();
841 EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 2);
842 UserMgr::maxLoginAttemptBeforeLockout(16);
843 EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 16);
844 }
845
TEST_F(UserMgrInTest,MaxLoginAttemptBeforeLockoutOnFailure)846 TEST_F(UserMgrInTest, MaxLoginAttemptBeforeLockoutOnFailure)
847 {
848 initializeAccountPolicy();
849 EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
850 EXPECT_THROW(
851 UserMgr::maxLoginAttemptBeforeLockout(16),
852 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
853 EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 2);
854 }
855
TEST_F(UserMgrInTest,AccountUnlockTimeoutReturnsIfValueIsTheSame)856 TEST_F(UserMgrInTest, AccountUnlockTimeoutReturnsIfValueIsTheSame)
857 {
858 initializeAccountPolicy();
859 EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 3);
860 UserMgr::accountUnlockTimeout(3);
861 EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 3);
862 }
863
TEST_F(UserMgrInTest,AccountUnlockTimeoutOnSuccess)864 TEST_F(UserMgrInTest, AccountUnlockTimeoutOnSuccess)
865 {
866 initializeAccountPolicy();
867 EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 3);
868 UserMgr::accountUnlockTimeout(16);
869 EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 16);
870 }
871
TEST_F(UserMgrInTest,AccountUnlockTimeoutOnFailure)872 TEST_F(UserMgrInTest, AccountUnlockTimeoutOnFailure)
873 {
874 initializeAccountPolicy();
875 EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
876 EXPECT_THROW(
877 UserMgr::accountUnlockTimeout(16),
878 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
879 EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 3);
880 }
881
TEST_F(UserMgrInTest,UserEnableOnSuccess)882 TEST_F(UserMgrInTest, UserEnableOnSuccess)
883 {
884 std::string username = "user001";
885 EXPECT_NO_THROW(
886 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
887 UserInfoMap userInfo = getUserInfo(username);
888 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
889
890 EXPECT_NO_THROW(userEnable(username, false));
891
892 userInfo = getUserInfo(username);
893 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), false);
894
895 EXPECT_NO_THROW(UserMgr::deleteUser(username));
896 }
897
TEST_F(UserMgrInTest,CreateDeleteUserSuccessForHostConsole)898 TEST_F(UserMgrInTest, CreateDeleteUserSuccessForHostConsole)
899 {
900 std::string username = "user001";
901 EXPECT_NO_THROW(
902 UserMgr::createUser(username, {"hostconsole"}, "priv-user", true));
903 EXPECT_NO_THROW(UserMgr::deleteUser(username));
904 EXPECT_NO_THROW(
905 UserMgr::createUser(username, {"hostconsole"}, "priv-admin", true));
906 EXPECT_NO_THROW(UserMgr::deleteUser(username));
907 EXPECT_NO_THROW(
908 UserMgr::createUser(username, {"hostconsole"}, "priv-operator", true));
909 EXPECT_NO_THROW(UserMgr::deleteUser(username));
910 }
911
TEST_F(UserMgrInTest,UserEnableThrowsInternalFailureIfExecuteUserModifyFail)912 TEST_F(UserMgrInTest, UserEnableThrowsInternalFailureIfExecuteUserModifyFail)
913 {
914 std::string username = "user001";
915 EXPECT_NO_THROW(
916 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
917 UserInfoMap userInfo = getUserInfo(username);
918 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
919
920 EXPECT_CALL(*this, executeUserModifyUserEnable(testing::StrEq(username),
921 testing::Eq(false)))
922 .WillOnce(testing::Throw(
923 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
924 EXPECT_THROW(
925 userEnable(username, false),
926 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
927
928 userInfo = getUserInfo(username);
929 // Stay unchanged
930 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
931
932 EXPECT_NO_THROW(UserMgr::deleteUser(username));
933 }
934
TEST_F(UserMgrInTest,UserLockedForFailedAttemptReturnsFalseIfMaxLoginAttemptBeforeLockoutIsZero)935 TEST_F(
936 UserMgrInTest,
937 UserLockedForFailedAttemptReturnsFalseIfMaxLoginAttemptBeforeLockoutIsZero)
938 {
939 EXPECT_FALSE(userLockedForFailedAttempt("whatever"));
940 }
941
TEST_F(UserMgrInTest,UserLockedForFailedAttemptZeroFailuresReturnsFalse)942 TEST_F(UserMgrInTest, UserLockedForFailedAttemptZeroFailuresReturnsFalse)
943 {
944 std::string username = "user001";
945 initializeAccountPolicy();
946 // Example output from BMC
947 // root:~# faillock --user root
948 // root:
949 // When Type Source Valid
950 std::vector<std::string> output = {"whatever",
951 "When Type Source Valid"};
952 EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
953 .WillOnce(testing::Return(output));
954
955 EXPECT_FALSE(userLockedForFailedAttempt(username));
956 }
957
TEST_F(UserMgrInTest,UserLockedForFailedAttemptFailIfGetFailedAttemptFail)958 TEST_F(UserMgrInTest, UserLockedForFailedAttemptFailIfGetFailedAttemptFail)
959 {
960 std::string username = "user001";
961 initializeAccountPolicy();
962 EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
963 .WillOnce(testing::Throw(
964 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
965
966 EXPECT_THROW(
967 userLockedForFailedAttempt(username),
968 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
969 }
970
TEST_F(UserMgrInTest,UserLockedForFailedAttemptThrowsInternalFailureIfWrongDateFormat)971 TEST_F(UserMgrInTest,
972 UserLockedForFailedAttemptThrowsInternalFailureIfWrongDateFormat)
973 {
974 std::string username = "user001";
975 initializeAccountPolicy();
976
977 // Choose a date in the past.
978 std::vector<std::string> output = {"whatever",
979 "10/24/2002 00:00:00 type source V"};
980 EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
981 .WillOnce(testing::Return(output));
982
983 EXPECT_THROW(
984 userLockedForFailedAttempt(username),
985 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
986 }
987
TEST_F(UserMgrInTest,UserLockedForFailedAttemptReturnsFalseIfLastFailTimeHasTimedOut)988 TEST_F(UserMgrInTest,
989 UserLockedForFailedAttemptReturnsFalseIfLastFailTimeHasTimedOut)
990 {
991 std::string username = "user001";
992 initializeAccountPolicy();
993
994 // Choose a date in the past.
995 std::vector<std::string> output = {"whatever",
996 "2002-10-24 00:00:00 type source V"};
997 EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
998 .WillOnce(testing::Return(output));
999
1000 EXPECT_EQ(userLockedForFailedAttempt(username), false);
1001 }
1002
TEST_F(UserMgrInTest,CheckAndThrowForDisallowedGroupCreationOnSuccess)1003 TEST_F(UserMgrInTest, CheckAndThrowForDisallowedGroupCreationOnSuccess)
1004 {
1005 // Base Redfish Roles
1006 EXPECT_NO_THROW(
1007 checkAndThrowForDisallowedGroupCreation("openbmc_rfr_Administrator"));
1008 EXPECT_NO_THROW(
1009 checkAndThrowForDisallowedGroupCreation("openbmc_rfr_Operator"));
1010 EXPECT_NO_THROW(
1011 checkAndThrowForDisallowedGroupCreation("openbmc_rfr_ReadOnly"));
1012 // Base Redfish Privileges
1013 EXPECT_NO_THROW(
1014 checkAndThrowForDisallowedGroupCreation("openbmc_rfp_Login"));
1015 EXPECT_NO_THROW(checkAndThrowForDisallowedGroupCreation(
1016 "openbmc_rfp_ConfigureManager"));
1017 EXPECT_NO_THROW(
1018 checkAndThrowForDisallowedGroupCreation("openbmc_rfp_ConfigureUsers"));
1019 EXPECT_NO_THROW(
1020 checkAndThrowForDisallowedGroupCreation("openbmc_rfp_ConfigureSelf"));
1021 EXPECT_NO_THROW(checkAndThrowForDisallowedGroupCreation(
1022 "openbmc_rfp_ConfigureComponents"));
1023 // OEM Redfish Roles
1024 EXPECT_NO_THROW(
1025 checkAndThrowForDisallowedGroupCreation("openbmc_orfr_PowerService"));
1026 // OEM Redfish Privileges
1027 EXPECT_NO_THROW(
1028 checkAndThrowForDisallowedGroupCreation("openbmc_orfp_PowerService"));
1029 }
1030
TEST_F(UserMgrInTest,CheckAndThrowForDisallowedGroupCreationThrowsIfGroupNameTooLong)1031 TEST_F(UserMgrInTest,
1032 CheckAndThrowForDisallowedGroupCreationThrowsIfGroupNameTooLong)
1033 {
1034 std::string groupName(maxSystemGroupNameLength + 1, 'A');
1035 EXPECT_THROW(
1036 checkAndThrowForDisallowedGroupCreation(groupName),
1037 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1038 }
1039
TEST_F(UserMgrInTest,CheckAndThrowForDisallowedGroupCreationThrowsIfGroupNameHasDisallowedCharacters)1040 TEST_F(
1041 UserMgrInTest,
1042 CheckAndThrowForDisallowedGroupCreationThrowsIfGroupNameHasDisallowedCharacters)
1043 {
1044 EXPECT_THROW(
1045 checkAndThrowForDisallowedGroupCreation("openbmc_rfp_?owerService"),
1046 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1047 EXPECT_THROW(
1048 checkAndThrowForDisallowedGroupCreation("openbmc_rfp_-owerService"),
1049 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1050 }
1051
TEST_F(UserMgrInTest,CheckAndThrowForDisallowedGroupCreationThrowsIfGroupNameHasDisallowedPrefix)1052 TEST_F(
1053 UserMgrInTest,
1054 CheckAndThrowForDisallowedGroupCreationThrowsIfGroupNameHasDisallowedPrefix)
1055 {
1056 EXPECT_THROW(
1057 checkAndThrowForDisallowedGroupCreation("google_rfp_"),
1058 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1059 EXPECT_THROW(
1060 checkAndThrowForDisallowedGroupCreation("com_rfp_"),
1061 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1062 }
1063
TEST_F(UserMgrInTest,CheckAndThrowForMaxGroupCountOnSuccess)1064 TEST_F(UserMgrInTest, CheckAndThrowForMaxGroupCountOnSuccess)
1065 {
1066 constexpr size_t predefGroupCount = 4;
1067
1068 EXPECT_THAT(allGroups().size(), predefGroupCount);
1069 for (size_t i = 0; i < maxSystemGroupCount - predefGroupCount; ++i)
1070 {
1071 std::string groupName = "openbmc_rfr_role";
1072 groupName += std::to_string(i);
1073 EXPECT_NO_THROW(createGroup(groupName));
1074 }
1075 EXPECT_THROW(
1076 createGroup("openbmc_rfr_AnotherRole"),
1077 sdbusplus::xyz::openbmc_project::User::Common::Error::NoResource);
1078 for (size_t i = 0; i < maxSystemGroupCount - predefGroupCount; ++i)
1079 {
1080 std::string groupName = "openbmc_rfr_role";
1081 groupName += std::to_string(i);
1082 EXPECT_NO_THROW(deleteGroup(groupName));
1083 }
1084 }
1085
TEST_F(UserMgrInTest,CheckAndThrowForGroupExist)1086 TEST_F(UserMgrInTest, CheckAndThrowForGroupExist)
1087 {
1088 std::string groupName = "openbmc_rfr_role";
1089 EXPECT_NO_THROW(createGroup(groupName));
1090 EXPECT_THROW(
1091 createGroup(groupName),
1092 sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1093 EXPECT_NO_THROW(deleteGroup(groupName));
1094 }
1095
TEST_F(UserMgrInTest,ByDefaultAllGroupsArePredefinedGroups)1096 TEST_F(UserMgrInTest, ByDefaultAllGroupsArePredefinedGroups)
1097 {
1098 EXPECT_THAT(allGroups(), testing::UnorderedElementsAre(
1099 "redfish", "ipmi", "ssh", "hostconsole"));
1100 }
1101
TEST_F(UserMgrInTest,AddGroupThrowsIfPreDefinedGroupAdd)1102 TEST_F(UserMgrInTest, AddGroupThrowsIfPreDefinedGroupAdd)
1103 {
1104 EXPECT_THROW(
1105 createGroup("ipmi"),
1106 sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1107 EXPECT_THROW(
1108 createGroup("redfish"),
1109 sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1110 EXPECT_THROW(
1111 createGroup("ssh"),
1112 sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1113 EXPECT_THROW(
1114 createGroup("hostconsole"),
1115 sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1116 }
1117
TEST_F(UserMgrInTest,DeleteGroupThrowsIfGroupIsNotAllowedToChange)1118 TEST_F(UserMgrInTest, DeleteGroupThrowsIfGroupIsNotAllowedToChange)
1119 {
1120 EXPECT_THROW(
1121 deleteGroup("ipmi"),
1122 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1123 EXPECT_THROW(
1124 deleteGroup("redfish"),
1125 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1126 EXPECT_THROW(
1127 deleteGroup("ssh"),
1128 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1129 EXPECT_THROW(
1130 deleteGroup("hostconsole"),
1131 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1132 }
1133
TEST_F(UserMgrInTest,CreateGroupThrowsInternalFailureWhenExecuteGroupCreateFails)1134 TEST_F(UserMgrInTest,
1135 CreateGroupThrowsInternalFailureWhenExecuteGroupCreateFails)
1136 {
1137 EXPECT_CALL(*this, executeGroupCreation)
1138 .WillOnce(testing::Throw(
1139 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
1140 EXPECT_THROW(
1141 createGroup("openbmc_rfr_role1"),
1142 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
1143 }
1144
TEST_F(UserMgrInTest,DeleteGroupThrowsInternalFailureWhenExecuteGroupDeleteFails)1145 TEST_F(UserMgrInTest,
1146 DeleteGroupThrowsInternalFailureWhenExecuteGroupDeleteFails)
1147 {
1148 std::string groupName = "openbmc_rfr_role1";
1149 EXPECT_NO_THROW(UserMgr::createGroup(groupName));
1150 EXPECT_CALL(*this, executeGroupDeletion(testing::StrEq(groupName)))
1151 .WillOnce(testing::Throw(
1152 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()))
1153 .WillOnce(testing::DoDefault());
1154
1155 EXPECT_THROW(
1156 deleteGroup(groupName),
1157 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
1158 EXPECT_NO_THROW(UserMgr::deleteGroup(groupName));
1159 }
1160
TEST_F(UserMgrInTest,CheckAndThrowForGroupNotExist)1161 TEST_F(UserMgrInTest, CheckAndThrowForGroupNotExist)
1162 {
1163 EXPECT_THROW(deleteGroup("whatever"),
1164 sdbusplus::xyz::openbmc_project::User::Common::Error::
1165 GroupNameDoesNotExist);
1166 }
1167
TEST(ReadAllGroupsOnSystemTest,OnlyReturnsPredefinedGroups)1168 TEST(ReadAllGroupsOnSystemTest, OnlyReturnsPredefinedGroups)
1169 {
1170 EXPECT_THAT(
1171 UserMgr::readAllGroupsOnSystem(),
1172 testing::UnorderedElementsAre("redfish", "ipmi", "ssh", "hostconsole"));
1173 }
1174
1175 } // namespace user
1176 } // namespace phosphor
1177