blob: d5049a0bcd49e9b95b80ad0d0e61578e98a8f431 [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
Jason M. Bills2d042d12023-03-28 15:32:45 -0700205// Fake configs; referenced configs on real BMC
Nan Zhoue48085d2022-10-25 00:07:04 +0000206inline 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)
Jason M. Bills2d042d12023-03-28 15:32:45 -0700225password [success=ok default=die] pam_faillock.so authsucc
226password [success=ok default=die] pam_pwquality.so debug
Nan Zhoue48085d2022-10-25 00:07:04 +0000227password [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)";
Jason M. Bills2d042d12023-03-28 15:32:45 -0700239inline constexpr const char* rawFailLockConfig = R"(
240deny=2
241unlock_time=3
242)";
243inline constexpr const char* rawPWQualityConfig = R"(
244enforce_for_root
245minlen=8
246difok=0
247lcredit=0
248ocredit=0
249dcredit=0
250ucredit=0
251)";
Nan Zhoue48085d2022-10-25 00:07:04 +0000252} // namespace
253
254void dumpStringToFile(const std::string& str, const std::string& filePath)
255{
256 std::ofstream outputFileStream;
257
258 outputFileStream.exceptions(std::ofstream::failbit | std::ofstream::badbit |
259 std::ofstream::eofbit);
260
261 outputFileStream.open(filePath, std::ios::out);
262 outputFileStream << str << "\n" << std::flush;
263 outputFileStream.close();
264}
265
266void removeFile(const std::string& filePath)
267{
268 std::filesystem::remove(filePath);
269}
270
271class UserMgrInTest : public testing::Test, public UserMgr
272{
273 public:
274 UserMgrInTest() : UserMgr(busInTest, objectRootInTest)
275 {
276 tempPamConfigFile = "/tmp/test-data-XXXXXX";
277 mktemp(tempPamConfigFile.data());
278 EXPECT_NO_THROW(dumpStringToFile(rawConfig, tempPamConfigFile));
Jason M. Bills2d042d12023-03-28 15:32:45 -0700279 tempFaillockConfigFile = "/tmp/test-data-XXXXXX";
280 mktemp(tempFaillockConfigFile.data());
281 EXPECT_NO_THROW(
282 dumpStringToFile(rawFailLockConfig, tempFaillockConfigFile));
283 tempPWQualityConfigFile = "/tmp/test-data-XXXXXX";
284 mktemp(tempPWQualityConfigFile.data());
285 EXPECT_NO_THROW(
286 dumpStringToFile(rawPWQualityConfig, tempPWQualityConfigFile));
Nan Zhoue48085d2022-10-25 00:07:04 +0000287 // Set config files to test files
288 pamPasswdConfigFile = tempPamConfigFile;
Jason M. Bills2d042d12023-03-28 15:32:45 -0700289 faillockConfigFile = tempFaillockConfigFile;
290 pwQualityConfigFile = tempPWQualityConfigFile;
Nan Zhou49c81362022-10-25 00:07:08 +0000291
292 ON_CALL(*this, executeUserAdd).WillByDefault(testing::Return());
293
294 ON_CALL(*this, executeUserDelete).WillByDefault(testing::Return());
295
Jayanth Othayothac921a52023-07-21 03:48:55 -0500296 ON_CALL(*this, executeUserClearFailRecords)
297 .WillByDefault(testing::Return());
298
Nan Zhou49c81362022-10-25 00:07:08 +0000299 ON_CALL(*this, getIpmiUsersCount).WillByDefault(testing::Return(0));
Nan Zhouf25443e2022-10-25 00:07:11 +0000300
301 ON_CALL(*this, executeUserRename).WillByDefault(testing::Return());
Nan Zhoufef63032022-10-25 00:07:12 +0000302
303 ON_CALL(*this, executeUserModify(testing::_, testing::_, testing::_))
304 .WillByDefault(testing::Return());
Nan Zhou6b6f2d82022-10-25 00:07:17 +0000305
306 ON_CALL(*this, executeUserModifyUserEnable)
307 .WillByDefault(testing::Return());
Nan Zhouda401fe2022-10-25 00:07:18 +0000308
309 ON_CALL(*this, executeGroupCreation(testing::_))
310 .WillByDefault(testing::Return());
311
312 ON_CALL(*this, executeGroupDeletion(testing::_))
313 .WillByDefault(testing::Return());
314
315 ON_CALL(*this, executeGroupCreation).WillByDefault(testing::Return());
316
317 ON_CALL(*this, executeGroupDeletion).WillByDefault(testing::Return());
Nan Zhoue48085d2022-10-25 00:07:04 +0000318 }
319
320 ~UserMgrInTest() override
321 {
322 EXPECT_NO_THROW(removeFile(tempPamConfigFile));
Jason M. Bills2d042d12023-03-28 15:32:45 -0700323 EXPECT_NO_THROW(removeFile(tempFaillockConfigFile));
324 EXPECT_NO_THROW(removeFile(tempPWQualityConfigFile));
Nan Zhoue48085d2022-10-25 00:07:04 +0000325 }
326
Nan Zhou49c81362022-10-25 00:07:08 +0000327 MOCK_METHOD(void, executeUserAdd, (const char*, const char*, bool, bool),
328 (override));
329
330 MOCK_METHOD(void, executeUserDelete, (const char*), (override));
331
Jayanth Othayothac921a52023-07-21 03:48:55 -0500332 MOCK_METHOD(void, executeUserClearFailRecords, (const char*), (override));
333
Nan Zhou49c81362022-10-25 00:07:08 +0000334 MOCK_METHOD(size_t, getIpmiUsersCount, (), (override));
335
Nan Zhouf25443e2022-10-25 00:07:11 +0000336 MOCK_METHOD(void, executeUserRename, (const char*, const char*),
337 (override));
338
Nan Zhoufef63032022-10-25 00:07:12 +0000339 MOCK_METHOD(void, executeUserModify, (const char*, const char*, bool),
340 (override));
341
Nan Zhou6b6f2d82022-10-25 00:07:17 +0000342 MOCK_METHOD(void, executeUserModifyUserEnable, (const char*, bool),
343 (override));
344
Nan Zhoua2953032022-11-11 21:50:32 +0000345 MOCK_METHOD(std::vector<std::string>, getFailedAttempt, (const char*),
346 (override));
347
Nan Zhouda401fe2022-10-25 00:07:18 +0000348 MOCK_METHOD(void, executeGroupCreation, (const char*), (override));
349
350 MOCK_METHOD(void, executeGroupDeletion, (const char*), (override));
351
Nan Zhoufef63032022-10-25 00:07:12 +0000352 protected:
Nan Zhoue48085d2022-10-25 00:07:04 +0000353 static sdbusplus::bus_t busInTest;
354 std::string tempPamConfigFile;
Jason M. Bills2d042d12023-03-28 15:32:45 -0700355 std::string tempFaillockConfigFile;
356 std::string tempPWQualityConfigFile;
Nan Zhoue48085d2022-10-25 00:07:04 +0000357};
358
359sdbusplus::bus_t UserMgrInTest::busInTest = sdbusplus::bus::new_default();
360
361TEST_F(UserMgrInTest, GetPamModuleArgValueOnSuccess)
362{
Jason M. Bills2d042d12023-03-28 15:32:45 -0700363 std::string remember;
364 EXPECT_EQ(getPamModuleArgValue("pam_pwhistory.so", "remember", remember),
365 0);
366 EXPECT_EQ(remember, "0");
367}
368
369TEST_F(UserMgrInTest, GetPamModuleConfValueOnSuccess)
370{
371 std::string minlen;
372 EXPECT_EQ(getPamModuleConfValue(tempPWQualityConfigFile, "minlen", minlen),
373 0);
374 EXPECT_EQ(minlen, "8");
375 std::string deny;
376 EXPECT_EQ(getPamModuleConfValue(tempFaillockConfigFile, "deny", deny), 0);
377 EXPECT_EQ(deny, "2");
Nan Zhoue48085d2022-10-25 00:07:04 +0000378}
379
380TEST_F(UserMgrInTest, SetPamModuleArgValueOnSuccess)
381{
Jason M. Bills2d042d12023-03-28 15:32:45 -0700382 EXPECT_EQ(setPamModuleArgValue("pam_pwhistory.so", "remember", "1"), 0);
383 std::string remember;
384 EXPECT_EQ(getPamModuleArgValue("pam_pwhistory.so", "remember", remember),
385 0);
386 EXPECT_EQ(remember, "1");
387}
388
389TEST_F(UserMgrInTest, SetPamModuleConfValueOnSuccess)
390{
391 EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
392 0);
393 std::string minlen;
394 EXPECT_EQ(getPamModuleConfValue(tempPWQualityConfigFile, "minlen", minlen),
395 0);
396 EXPECT_EQ(minlen, "16");
397
398 EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), 0);
399 std::string deny;
400 EXPECT_EQ(getPamModuleConfValue(tempFaillockConfigFile, "deny", deny), 0);
401 EXPECT_EQ(deny, "3");
Nan Zhoue48085d2022-10-25 00:07:04 +0000402}
403
404TEST_F(UserMgrInTest, GetPamModuleArgValueOnFailure)
405{
406 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPamConfigFile));
Jason M. Bills2d042d12023-03-28 15:32:45 -0700407 std::string remember;
408 EXPECT_EQ(getPamModuleArgValue("pam_pwhistory.so", "remember", remember),
409 -1);
Nan Zhoue48085d2022-10-25 00:07:04 +0000410
411 EXPECT_NO_THROW(removeFile(tempPamConfigFile));
Jason M. Bills2d042d12023-03-28 15:32:45 -0700412 EXPECT_EQ(getPamModuleArgValue("pam_pwhistory.so", "remember", remember),
413 -1);
414}
415
416TEST_F(UserMgrInTest, GetPamModuleConfValueOnFailure)
417{
418 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWQualityConfigFile));
419 std::string minlen;
420 EXPECT_EQ(getPamModuleConfValue(tempPWQualityConfigFile, "minlen", minlen),
421 -1);
422
423 EXPECT_NO_THROW(removeFile(tempPWQualityConfigFile));
424 EXPECT_EQ(getPamModuleConfValue(tempPWQualityConfigFile, "minlen", minlen),
425 -1);
426
427 EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
428 std::string deny;
429 EXPECT_EQ(getPamModuleConfValue(tempFaillockConfigFile, "deny", deny), -1);
430
431 EXPECT_NO_THROW(removeFile(tempFaillockConfigFile));
432 EXPECT_EQ(getPamModuleConfValue(tempFaillockConfigFile, "deny", deny), -1);
Nan Zhoue48085d2022-10-25 00:07:04 +0000433}
434
435TEST_F(UserMgrInTest, SetPamModuleArgValueOnFailure)
436{
437 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPamConfigFile));
Jason M. Bills2d042d12023-03-28 15:32:45 -0700438 EXPECT_EQ(setPamModuleArgValue("pam_pwhistory.so", "remember", "1"), -1);
Nan Zhoue48085d2022-10-25 00:07:04 +0000439
440 EXPECT_NO_THROW(removeFile(tempPamConfigFile));
Jason M. Bills2d042d12023-03-28 15:32:45 -0700441 EXPECT_EQ(setPamModuleArgValue("pam_pwhistory.so", "remember", "1"), -1);
442}
443
444TEST_F(UserMgrInTest, SetPamModuleConfValueOnFailure)
445{
446 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWQualityConfigFile));
447 EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
448 -1);
449
450 EXPECT_NO_THROW(removeFile(tempPWQualityConfigFile));
451 EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
452 -1);
453
454 EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
455 EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), -1);
456
457 EXPECT_NO_THROW(removeFile(tempFaillockConfigFile));
458 EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), -1);
Nan Zhoue48085d2022-10-25 00:07:04 +0000459}
460
Nan Zhou8a11d992022-10-25 00:07:06 +0000461TEST_F(UserMgrInTest, IsUserExistEmptyInputThrowsError)
462{
463 EXPECT_THROW(
464 isUserExist(""),
465 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
466}
467
468TEST_F(UserMgrInTest, ThrowForUserDoesNotExistThrowsError)
469{
470 EXPECT_THROW(throwForUserDoesNotExist("whatever"),
471 sdbusplus::xyz::openbmc_project::User::Common::Error::
472 UserNameDoesNotExist);
473}
474
475TEST_F(UserMgrInTest, ThrowForUserExistsThrowsError)
476{
477 EXPECT_THROW(
478 throwForUserExists("root"),
479 sdbusplus::xyz::openbmc_project::User::Common::Error::UserNameExists);
480}
481
Nan Zhou40e44972022-10-25 00:07:07 +0000482TEST_F(
483 UserMgrInTest,
484 ThrowForUserNameConstraintsExceedIpmiMaxUserNameLenThrowsUserNameGroupFail)
485{
486 std::string strWith17Chars(17, 'A');
487 EXPECT_THROW(throwForUserNameConstraints(strWith17Chars, {"ipmi"}),
488 sdbusplus::xyz::openbmc_project::User::Common::Error::
489 UserNameGroupFail);
490}
491
492TEST_F(
493 UserMgrInTest,
494 ThrowForUserNameConstraintsExceedSystemMaxUserNameLenThrowsInvalidArgument)
495{
496 std::string strWith31Chars(31, 'A');
497 EXPECT_THROW(
498 throwForUserNameConstraints(strWith31Chars, {}),
499 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
500}
501
502TEST_F(UserMgrInTest,
503 ThrowForUserNameConstraintsRegexMismatchThrowsInvalidArgument)
504{
505 std::string startWithNumber = "0ABC";
506 EXPECT_THROW(
507 throwForUserNameConstraints(startWithNumber, {"ipmi"}),
508 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
509}
510
Nan Zhou49c81362022-10-25 00:07:08 +0000511TEST_F(UserMgrInTest, UserAddNotRootFailedWithInternalFailure)
512{
513 EXPECT_THROW(
514 UserMgr::executeUserAdd("user0", "ipmi,ssh", true, true),
515 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
516}
517
518TEST_F(UserMgrInTest, UserDeleteNotRootFailedWithInternalFailure)
519{
520 EXPECT_THROW(
521 UserMgr::executeUserDelete("user0"),
522 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
523}
524
525TEST_F(UserMgrInTest,
526 ThrowForMaxGrpUserCountThrowsNoResourceWhenIpmiUserExceedLimit)
527{
528 EXPECT_CALL(*this, getIpmiUsersCount()).WillOnce(Return(ipmiMaxUsers));
529 EXPECT_THROW(
530 throwForMaxGrpUserCount({"ipmi"}),
531 sdbusplus::xyz::openbmc_project::User::Common::Error::NoResource);
532}
533
534TEST_F(UserMgrInTest, CreateUserThrowsInternalFailureWhenExecuteUserAddFails)
535{
536 EXPECT_CALL(*this, executeUserAdd)
537 .WillOnce(testing::Throw(
538 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
539 EXPECT_THROW(
540 createUser("whatever", {"redfish"}, "", true),
541 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
542}
543
544TEST_F(UserMgrInTest, DeleteUserThrowsInternalFailureWhenExecuteUserDeleteFails)
545{
546 std::string username = "user";
547 EXPECT_NO_THROW(
548 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
549 EXPECT_CALL(*this, executeUserDelete(testing::StrEq(username)))
550 .WillOnce(testing::Throw(
551 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()))
552 .WillOnce(testing::DoDefault());
553
554 EXPECT_THROW(
555 deleteUser(username),
556 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
557 EXPECT_NO_THROW(UserMgr::deleteUser(username));
558}
559
Jayanth Othayothac921a52023-07-21 03:48:55 -0500560TEST_F(UserMgrInTest,
561 DeleteUserThrowsInternalFailureWhenExecuteUserClearFailRecords)
562{
563 const char* username = "user";
564 EXPECT_NO_THROW(
565 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
566 EXPECT_CALL(*this, executeUserClearFailRecords(testing::StrEq(username)))
567 .WillOnce(testing::Throw(
568 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()))
569 .WillOnce(testing::DoDefault());
570
571 EXPECT_THROW(
572 deleteUser(username),
573 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
574 EXPECT_NO_THROW(UserMgr::deleteUser(username));
575}
576
Nan Zhou589aeb42022-10-25 00:07:09 +0000577TEST_F(UserMgrInTest, ThrowForInvalidPrivilegeThrowsWhenPrivilegeIsInvalid)
578{
579 EXPECT_THROW(
580 throwForInvalidPrivilege("whatever"),
581 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
582}
583
584TEST_F(UserMgrInTest, ThrowForInvalidPrivilegeNoThrowWhenPrivilegeIsValid)
585{
586 EXPECT_NO_THROW(throwForInvalidPrivilege("priv-admin"));
587 EXPECT_NO_THROW(throwForInvalidPrivilege("priv-operator"));
588 EXPECT_NO_THROW(throwForInvalidPrivilege("priv-user"));
Nan Zhou589aeb42022-10-25 00:07:09 +0000589}
590
Nan Zhouecf88762022-10-25 00:07:10 +0000591TEST_F(UserMgrInTest, ThrowForInvalidGroupsThrowsWhenGroupIsInvalid)
592{
593 EXPECT_THROW(
594 throwForInvalidGroups({"whatever"}),
595 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
596}
597
598TEST_F(UserMgrInTest, ThrowForInvalidGroupsNoThrowWhenGroupIsValid)
599{
600 EXPECT_NO_THROW(throwForInvalidGroups({"ipmi"}));
601 EXPECT_NO_THROW(throwForInvalidGroups({"ssh"}));
602 EXPECT_NO_THROW(throwForInvalidGroups({"redfish"}));
603 EXPECT_NO_THROW(throwForInvalidGroups({"web"}));
Ninad Palsule601d3db2023-03-09 10:27:37 -0600604 EXPECT_NO_THROW(throwForInvalidGroups({"hostconsole"}));
Nan Zhouecf88762022-10-25 00:07:10 +0000605}
606
Nan Zhouf25443e2022-10-25 00:07:11 +0000607TEST_F(UserMgrInTest, RenameUserOnSuccess)
608{
609 std::string username = "user001";
610 EXPECT_NO_THROW(
611 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
612 std::string newUsername = "user002";
613
614 EXPECT_NO_THROW(UserMgr::renameUser(username, newUsername));
615
616 // old username doesn't exist
617 EXPECT_THROW(getUserInfo(username),
618 sdbusplus::xyz::openbmc_project::User::Common::Error::
619 UserNameDoesNotExist);
620
621 UserInfoMap userInfo = getUserInfo(newUsername);
622 EXPECT_EQ(std::get<Privilege>(userInfo["UserPrivilege"]), "priv-user");
623 EXPECT_THAT(std::get<GroupList>(userInfo["UserGroups"]),
624 testing::UnorderedElementsAre("redfish", "ssh"));
625 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
626
627 EXPECT_NO_THROW(UserMgr::deleteUser(newUsername));
628}
629
630TEST_F(UserMgrInTest, RenameUserThrowsInternalFailureIfExecuteUserModifyFails)
631{
632 std::string username = "user001";
633 EXPECT_NO_THROW(
634 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
635 std::string newUsername = "user002";
636
637 EXPECT_CALL(*this, executeUserRename(testing::StrEq(username),
638 testing::StrEq(newUsername)))
639 .WillOnce(testing::Throw(
640 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
641 EXPECT_THROW(
642 UserMgr::renameUser(username, newUsername),
643 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
644
645 // The original user is unchanged
646 UserInfoMap userInfo = getUserInfo(username);
647 EXPECT_EQ(std::get<Privilege>(userInfo["UserPrivilege"]), "priv-user");
648 EXPECT_THAT(std::get<GroupList>(userInfo["UserGroups"]),
649 testing::UnorderedElementsAre("redfish", "ssh"));
650 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
651
652 EXPECT_NO_THROW(UserMgr::deleteUser(username));
653}
654
655TEST_F(UserMgrInTest, DefaultUserModifyFailedWithInternalFailure)
656{
657 EXPECT_THROW(
658 UserMgr::executeUserRename("user0", "user1"),
659 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
Nan Zhoufef63032022-10-25 00:07:12 +0000660 EXPECT_THROW(
661 UserMgr::executeUserModify("user0", "ssh", true),
662 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
663}
664
665TEST_F(UserMgrInTest, UpdateGroupsAndPrivOnSuccess)
666{
667 std::string username = "user001";
668 EXPECT_NO_THROW(
669 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
670 EXPECT_NO_THROW(
671 updateGroupsAndPriv(username, {"ipmi", "ssh"}, "priv-admin"));
672 UserInfoMap userInfo = getUserInfo(username);
673 EXPECT_EQ(std::get<Privilege>(userInfo["UserPrivilege"]), "priv-admin");
674 EXPECT_THAT(std::get<GroupList>(userInfo["UserGroups"]),
675 testing::UnorderedElementsAre("ipmi", "ssh"));
676 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
677 EXPECT_NO_THROW(UserMgr::deleteUser(username));
678}
679
680TEST_F(UserMgrInTest,
681 UpdateGroupsAndPrivThrowsInternalFailureIfExecuteUserModifyFail)
682{
683 std::string username = "user001";
684 EXPECT_NO_THROW(
685 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
686 EXPECT_CALL(*this, executeUserModify(testing::StrEq(username), testing::_,
687 testing::_))
688 .WillOnce(testing::Throw(
689 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
690 EXPECT_THROW(
691 updateGroupsAndPriv(username, {"ipmi", "ssh"}, "priv-admin"),
692 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
693 EXPECT_NO_THROW(UserMgr::deleteUser(username));
Nan Zhouf25443e2022-10-25 00:07:11 +0000694}
695
Nan Zhou18031012022-11-10 22:24:58 +0000696TEST_F(UserMgrInTest, MinPasswordLengthReturnsIfValueIsTheSame)
697{
698 initializeAccountPolicy();
699 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
700 UserMgr::minPasswordLength(8);
701 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
702}
703
704TEST_F(UserMgrInTest,
705 MinPasswordLengthRejectsTooShortPasswordWithInvalidArgument)
706{
707 initializeAccountPolicy();
708 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
709 EXPECT_THROW(
710 UserMgr::minPasswordLength(minPasswdLength - 1),
711 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
712 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
713}
714
715TEST_F(UserMgrInTest, MinPasswordLengthOnSuccess)
716{
717 initializeAccountPolicy();
718 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
719 UserMgr::minPasswordLength(16);
720 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 16);
721}
722
723TEST_F(UserMgrInTest, MinPasswordLengthOnFailure)
724{
Jason M. Bills2d042d12023-03-28 15:32:45 -0700725 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWQualityConfigFile));
Nan Zhou18031012022-11-10 22:24:58 +0000726 initializeAccountPolicy();
727 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
728 EXPECT_THROW(
729 UserMgr::minPasswordLength(16),
730 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
731 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
732}
733
Nan Zhoua6ce1fa2022-10-25 00:07:14 +0000734TEST_F(UserMgrInTest, RememberOldPasswordTimesReturnsIfValueIsTheSame)
735{
736 initializeAccountPolicy();
737 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 0);
738 UserMgr::rememberOldPasswordTimes(8);
739 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 8);
740 UserMgr::rememberOldPasswordTimes(8);
741 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 8);
742}
743
744TEST_F(UserMgrInTest, RememberOldPasswordTimesOnSuccess)
745{
746 initializeAccountPolicy();
747 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 0);
748 UserMgr::rememberOldPasswordTimes(16);
749 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 16);
750}
751
752TEST_F(UserMgrInTest, RememberOldPasswordTimesOnFailure)
753{
754 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPamConfigFile));
755 initializeAccountPolicy();
756 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 0);
757 EXPECT_THROW(
758 UserMgr::rememberOldPasswordTimes(16),
759 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
760 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 0);
761}
762
Nan Zhoucfabe6b2022-10-25 00:07:15 +0000763TEST_F(UserMgrInTest, MaxLoginAttemptBeforeLockoutReturnsIfValueIsTheSame)
764{
765 initializeAccountPolicy();
766 EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 2);
767 UserMgr::maxLoginAttemptBeforeLockout(2);
768 EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 2);
769}
770
771TEST_F(UserMgrInTest, MaxLoginAttemptBeforeLockoutOnSuccess)
772{
773 initializeAccountPolicy();
774 EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 2);
775 UserMgr::maxLoginAttemptBeforeLockout(16);
776 EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 16);
777}
778
779TEST_F(UserMgrInTest, MaxLoginAttemptBeforeLockoutOnFailure)
780{
Nan Zhoucfabe6b2022-10-25 00:07:15 +0000781 initializeAccountPolicy();
Jason M. Bills2d042d12023-03-28 15:32:45 -0700782 EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
Nan Zhoucfabe6b2022-10-25 00:07:15 +0000783 EXPECT_THROW(
784 UserMgr::maxLoginAttemptBeforeLockout(16),
785 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
Jason M. Bills2d042d12023-03-28 15:32:45 -0700786 EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 2);
Nan Zhoucfabe6b2022-10-25 00:07:15 +0000787}
788
Nan Zhou784aecd2022-10-25 00:07:16 +0000789TEST_F(UserMgrInTest, AccountUnlockTimeoutReturnsIfValueIsTheSame)
790{
791 initializeAccountPolicy();
792 EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 3);
793 UserMgr::accountUnlockTimeout(3);
794 EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 3);
795}
796
797TEST_F(UserMgrInTest, AccountUnlockTimeoutOnSuccess)
798{
799 initializeAccountPolicy();
800 EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 3);
801 UserMgr::accountUnlockTimeout(16);
802 EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 16);
803}
804
805TEST_F(UserMgrInTest, AccountUnlockTimeoutOnFailure)
806{
807 initializeAccountPolicy();
Jason M. Bills2d042d12023-03-28 15:32:45 -0700808 EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
Nan Zhou784aecd2022-10-25 00:07:16 +0000809 EXPECT_THROW(
810 UserMgr::accountUnlockTimeout(16),
811 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
812 EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 3);
813}
814
Nan Zhou6b6f2d82022-10-25 00:07:17 +0000815TEST_F(UserMgrInTest, UserEnableOnSuccess)
816{
817 std::string username = "user001";
818 EXPECT_NO_THROW(
819 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
820 UserInfoMap userInfo = getUserInfo(username);
821 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
822
823 EXPECT_NO_THROW(userEnable(username, false));
824
825 userInfo = getUserInfo(username);
826 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), false);
827
828 EXPECT_NO_THROW(UserMgr::deleteUser(username));
829}
830
Ninad Palsule601d3db2023-03-09 10:27:37 -0600831TEST_F(UserMgrInTest, CreateDeleteUserSuccessForHostConsole)
832{
833 std::string username = "user001";
834 EXPECT_NO_THROW(
835 UserMgr::createUser(username, {"hostconsole"}, "priv-user", true));
836 EXPECT_NO_THROW(UserMgr::deleteUser(username));
837 EXPECT_NO_THROW(
838 UserMgr::createUser(username, {"hostconsole"}, "priv-admin", true));
839 EXPECT_NO_THROW(UserMgr::deleteUser(username));
840 EXPECT_NO_THROW(
841 UserMgr::createUser(username, {"hostconsole"}, "priv-operator", true));
842 EXPECT_NO_THROW(UserMgr::deleteUser(username));
843}
844
Nan Zhou6b6f2d82022-10-25 00:07:17 +0000845TEST_F(UserMgrInTest, UserEnableThrowsInternalFailureIfExecuteUserModifyFail)
846{
847 std::string username = "user001";
848 EXPECT_NO_THROW(
849 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
850 UserInfoMap userInfo = getUserInfo(username);
851 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
852
853 EXPECT_CALL(*this, executeUserModifyUserEnable(testing::StrEq(username),
854 testing::Eq(false)))
855 .WillOnce(testing::Throw(
856 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
857 EXPECT_THROW(
858 userEnable(username, false),
859 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
860
861 userInfo = getUserInfo(username);
862 // Stay unchanged
863 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
864
865 EXPECT_NO_THROW(UserMgr::deleteUser(username));
866}
867
Nan Zhoua2953032022-11-11 21:50:32 +0000868TEST_F(
869 UserMgrInTest,
870 UserLockedForFailedAttemptReturnsFalseIfMaxLoginAttemptBeforeLockoutIsZero)
871{
872 EXPECT_FALSE(userLockedForFailedAttempt("whatever"));
873}
874
875TEST_F(UserMgrInTest, UserLockedForFailedAttemptZeroFailuresReturnsFalse)
876{
877 std::string username = "user001";
878 initializeAccountPolicy();
879 // Example output from BMC
Jason M. Bills2d042d12023-03-28 15:32:45 -0700880 // root:~# faillock --user root
881 // root:
882 // When Type Source Valid
883 std::vector<std::string> output = {"whatever",
884 "When Type Source Valid"};
Nan Zhoua2953032022-11-11 21:50:32 +0000885 EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
886 .WillOnce(testing::Return(output));
887
888 EXPECT_FALSE(userLockedForFailedAttempt(username));
889}
890
891TEST_F(UserMgrInTest, UserLockedForFailedAttemptFailIfGetFailedAttemptFail)
892{
893 std::string username = "user001";
894 initializeAccountPolicy();
895 EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
896 .WillOnce(testing::Throw(
897 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
898
899 EXPECT_THROW(
900 userLockedForFailedAttempt(username),
901 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
902}
903
904TEST_F(UserMgrInTest,
Nan Zhoua2953032022-11-11 21:50:32 +0000905 UserLockedForFailedAttemptThrowsInternalFailureIfWrongDateFormat)
906{
907 std::string username = "user001";
908 initializeAccountPolicy();
909
910 // Choose a date in the past.
911 std::vector<std::string> output = {"whatever",
Jason M. Bills2d042d12023-03-28 15:32:45 -0700912 "10/24/2002 00:00:00 type source V"};
Nan Zhoua2953032022-11-11 21:50:32 +0000913 EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
914 .WillOnce(testing::Return(output));
915
916 EXPECT_THROW(
917 userLockedForFailedAttempt(username),
918 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
919}
920
921TEST_F(UserMgrInTest,
922 UserLockedForFailedAttemptReturnsFalseIfLastFailTimeHasTimedOut)
923{
924 std::string username = "user001";
925 initializeAccountPolicy();
926
927 // Choose a date in the past.
928 std::vector<std::string> output = {"whatever",
Jason M. Bills2d042d12023-03-28 15:32:45 -0700929 "2002-10-24 00:00:00 type source V"};
Nan Zhoua2953032022-11-11 21:50:32 +0000930 EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
931 .WillOnce(testing::Return(output));
932
933 EXPECT_EQ(userLockedForFailedAttempt(username), false);
934}
935
Nan Zhouda401fe2022-10-25 00:07:18 +0000936TEST_F(UserMgrInTest, CheckAndThrowForDisallowedGroupCreationOnSuccess)
937{
938 // Base Redfish Roles
939 EXPECT_NO_THROW(
940 checkAndThrowForDisallowedGroupCreation("openbmc_rfr_Administrator"));
941 EXPECT_NO_THROW(
942 checkAndThrowForDisallowedGroupCreation("openbmc_rfr_Operator"));
943 EXPECT_NO_THROW(
944 checkAndThrowForDisallowedGroupCreation("openbmc_rfr_ReadOnly"));
945 // Base Redfish Privileges
946 EXPECT_NO_THROW(
947 checkAndThrowForDisallowedGroupCreation("openbmc_rfp_Login"));
948 EXPECT_NO_THROW(checkAndThrowForDisallowedGroupCreation(
949 "openbmc_rfp_ConfigureManager"));
950 EXPECT_NO_THROW(
951 checkAndThrowForDisallowedGroupCreation("openbmc_rfp_ConfigureUsers"));
952 EXPECT_NO_THROW(
953 checkAndThrowForDisallowedGroupCreation("openbmc_rfp_ConfigureSelf"));
954 EXPECT_NO_THROW(checkAndThrowForDisallowedGroupCreation(
955 "openbmc_rfp_ConfigureComponents"));
956 // OEM Redfish Roles
957 EXPECT_NO_THROW(
958 checkAndThrowForDisallowedGroupCreation("openbmc_orfr_PowerService"));
959 // OEM Redfish Privileges
960 EXPECT_NO_THROW(
961 checkAndThrowForDisallowedGroupCreation("openbmc_orfp_PowerService"));
962}
963
964TEST_F(UserMgrInTest,
965 CheckAndThrowForDisallowedGroupCreationThrowsIfGroupNameTooLong)
966{
967 std::string groupName(maxSystemGroupNameLength + 1, 'A');
968 EXPECT_THROW(
969 checkAndThrowForDisallowedGroupCreation(groupName),
970 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
971}
972
973TEST_F(
974 UserMgrInTest,
975 CheckAndThrowForDisallowedGroupCreationThrowsIfGroupNameHasDisallowedCharacters)
976{
Nan Zhouda401fe2022-10-25 00:07:18 +0000977 EXPECT_THROW(
978 checkAndThrowForDisallowedGroupCreation("openbmc_rfp_?owerService"),
979 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
980 EXPECT_THROW(
981 checkAndThrowForDisallowedGroupCreation("openbmc_rfp_-owerService"),
982 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
983}
984
985TEST_F(
986 UserMgrInTest,
987 CheckAndThrowForDisallowedGroupCreationThrowsIfGroupNameHasDisallowedPrefix)
988{
Nan Zhouda401fe2022-10-25 00:07:18 +0000989 EXPECT_THROW(
990 checkAndThrowForDisallowedGroupCreation("google_rfp_"),
991 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
992 EXPECT_THROW(
993 checkAndThrowForDisallowedGroupCreation("com_rfp_"),
994 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
995}
996
997TEST_F(UserMgrInTest, CheckAndThrowForMaxGroupCountOnSuccess)
998{
Ninad Palsule601d3db2023-03-09 10:27:37 -0600999 constexpr size_t predefGroupCount = 5;
1000
1001 EXPECT_THAT(allGroups().size(), predefGroupCount);
1002 for (size_t i = 0; i < maxSystemGroupCount - predefGroupCount; ++i)
Nan Zhouda401fe2022-10-25 00:07:18 +00001003 {
1004 std::string groupName = "openbmc_rfr_role";
1005 groupName += std::to_string(i);
1006 EXPECT_NO_THROW(createGroup(groupName));
1007 }
1008 EXPECT_THROW(
1009 createGroup("openbmc_rfr_AnotherRole"),
1010 sdbusplus::xyz::openbmc_project::User::Common::Error::NoResource);
Ninad Palsule601d3db2023-03-09 10:27:37 -06001011 for (size_t i = 0; i < maxSystemGroupCount - predefGroupCount; ++i)
Nan Zhouda401fe2022-10-25 00:07:18 +00001012 {
1013 std::string groupName = "openbmc_rfr_role";
1014 groupName += std::to_string(i);
1015 EXPECT_NO_THROW(deleteGroup(groupName));
1016 }
1017}
1018
1019TEST_F(UserMgrInTest, CheckAndThrowForGroupExist)
1020{
1021 std::string groupName = "openbmc_rfr_role";
1022 EXPECT_NO_THROW(createGroup(groupName));
1023 EXPECT_THROW(
1024 createGroup(groupName),
1025 sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1026 EXPECT_NO_THROW(deleteGroup(groupName));
1027}
1028
1029TEST_F(UserMgrInTest, ByDefaultAllGroupsArePredefinedGroups)
1030{
1031 EXPECT_THAT(allGroups(),
Ninad Palsule601d3db2023-03-09 10:27:37 -06001032 testing::UnorderedElementsAre("web", "redfish", "ipmi", "ssh",
1033 "hostconsole"));
1034}
1035
1036TEST_F(UserMgrInTest, AddGroupThrowsIfPreDefinedGroupAdd)
1037{
1038 EXPECT_THROW(
1039 createGroup("ipmi"),
1040 sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1041 EXPECT_THROW(
1042 createGroup("web"),
1043 sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1044 EXPECT_THROW(
1045 createGroup("redfish"),
1046 sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1047 EXPECT_THROW(
1048 createGroup("ssh"),
1049 sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1050 EXPECT_THROW(
1051 createGroup("hostconsole"),
1052 sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
Nan Zhouda401fe2022-10-25 00:07:18 +00001053}
1054
1055TEST_F(UserMgrInTest, DeleteGroupThrowsIfGroupIsNotAllowedToChange)
1056{
1057 EXPECT_THROW(
1058 deleteGroup("ipmi"),
1059 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1060 EXPECT_THROW(
1061 deleteGroup("web"),
1062 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1063 EXPECT_THROW(
1064 deleteGroup("redfish"),
1065 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1066 EXPECT_THROW(
1067 deleteGroup("ssh"),
1068 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
Ninad Palsule601d3db2023-03-09 10:27:37 -06001069 EXPECT_THROW(
1070 deleteGroup("hostconsole"),
1071 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
Nan Zhouda401fe2022-10-25 00:07:18 +00001072}
1073
1074TEST_F(UserMgrInTest,
1075 CreateGroupThrowsInternalFailureWhenExecuteGroupCreateFails)
1076{
1077 EXPECT_CALL(*this, executeGroupCreation)
1078 .WillOnce(testing::Throw(
1079 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
1080 EXPECT_THROW(
1081 createGroup("openbmc_rfr_role1"),
1082 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
1083}
1084
1085TEST_F(UserMgrInTest,
1086 DeleteGroupThrowsInternalFailureWhenExecuteGroupDeleteFails)
1087{
1088 std::string groupName = "openbmc_rfr_role1";
1089 EXPECT_NO_THROW(UserMgr::createGroup(groupName));
1090 EXPECT_CALL(*this, executeGroupDeletion(testing::StrEq(groupName)))
1091 .WillOnce(testing::Throw(
1092 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()))
1093 .WillOnce(testing::DoDefault());
1094
1095 EXPECT_THROW(
1096 deleteGroup(groupName),
1097 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
1098 EXPECT_NO_THROW(UserMgr::deleteGroup(groupName));
1099}
1100
1101TEST_F(UserMgrInTest, CheckAndThrowForGroupNotExist)
1102{
1103 EXPECT_THROW(deleteGroup("whatever"),
1104 sdbusplus::xyz::openbmc_project::User::Common::Error::
1105 GroupNameDoesNotExist);
1106}
1107
1108TEST(ReadAllGroupsOnSystemTest, OnlyReturnsPredefinedGroups)
1109{
1110 EXPECT_THAT(UserMgr::readAllGroupsOnSystem(),
Ninad Palsule601d3db2023-03-09 10:27:37 -06001111 testing::UnorderedElementsAre("web", "redfish", "ipmi", "ssh",
1112 "hostconsole"));
Nan Zhouda401fe2022-10-25 00:07:18 +00001113}
1114
raviteja-b8cc44052019-02-27 23:29:36 -06001115} // namespace user
1116} // namespace phosphor