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