xref: /openbmc/phosphor-user-manager/test/user_mgr_test.cpp (revision 9ca8692dedc633c6d2857f0a8dda8a3437ed50f9)
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