blob: 0bd5e1c84951c3130cc928c9670fbfc73810b898 [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
296 ON_CALL(*this, getIpmiUsersCount).WillByDefault(testing::Return(0));
Nan Zhouf25443e2022-10-25 00:07:11 +0000297
298 ON_CALL(*this, executeUserRename).WillByDefault(testing::Return());
Nan Zhoufef63032022-10-25 00:07:12 +0000299
300 ON_CALL(*this, executeUserModify(testing::_, testing::_, testing::_))
301 .WillByDefault(testing::Return());
Nan Zhou6b6f2d82022-10-25 00:07:17 +0000302
303 ON_CALL(*this, executeUserModifyUserEnable)
304 .WillByDefault(testing::Return());
Nan Zhouda401fe2022-10-25 00:07:18 +0000305
306 ON_CALL(*this, executeGroupCreation(testing::_))
307 .WillByDefault(testing::Return());
308
309 ON_CALL(*this, executeGroupDeletion(testing::_))
310 .WillByDefault(testing::Return());
311
312 ON_CALL(*this, executeGroupCreation).WillByDefault(testing::Return());
313
314 ON_CALL(*this, executeGroupDeletion).WillByDefault(testing::Return());
Nan Zhoue48085d2022-10-25 00:07:04 +0000315 }
316
317 ~UserMgrInTest() override
318 {
319 EXPECT_NO_THROW(removeFile(tempPamConfigFile));
Jason M. Bills2d042d12023-03-28 15:32:45 -0700320 EXPECT_NO_THROW(removeFile(tempFaillockConfigFile));
321 EXPECT_NO_THROW(removeFile(tempPWQualityConfigFile));
Nan Zhoue48085d2022-10-25 00:07:04 +0000322 }
323
Nan Zhou49c81362022-10-25 00:07:08 +0000324 MOCK_METHOD(void, executeUserAdd, (const char*, const char*, bool, bool),
325 (override));
326
327 MOCK_METHOD(void, executeUserDelete, (const char*), (override));
328
329 MOCK_METHOD(size_t, getIpmiUsersCount, (), (override));
330
Nan Zhouf25443e2022-10-25 00:07:11 +0000331 MOCK_METHOD(void, executeUserRename, (const char*, const char*),
332 (override));
333
Nan Zhoufef63032022-10-25 00:07:12 +0000334 MOCK_METHOD(void, executeUserModify, (const char*, const char*, bool),
335 (override));
336
Nan Zhou6b6f2d82022-10-25 00:07:17 +0000337 MOCK_METHOD(void, executeUserModifyUserEnable, (const char*, bool),
338 (override));
339
Nan Zhoua2953032022-11-11 21:50:32 +0000340 MOCK_METHOD(std::vector<std::string>, getFailedAttempt, (const char*),
341 (override));
342
Nan Zhouda401fe2022-10-25 00:07:18 +0000343 MOCK_METHOD(void, executeGroupCreation, (const char*), (override));
344
345 MOCK_METHOD(void, executeGroupDeletion, (const char*), (override));
346
Nan Zhoufef63032022-10-25 00:07:12 +0000347 protected:
Nan Zhoue48085d2022-10-25 00:07:04 +0000348 static sdbusplus::bus_t busInTest;
349 std::string tempPamConfigFile;
Jason M. Bills2d042d12023-03-28 15:32:45 -0700350 std::string tempFaillockConfigFile;
351 std::string tempPWQualityConfigFile;
Nan Zhoue48085d2022-10-25 00:07:04 +0000352};
353
354sdbusplus::bus_t UserMgrInTest::busInTest = sdbusplus::bus::new_default();
355
356TEST_F(UserMgrInTest, GetPamModuleArgValueOnSuccess)
357{
Jason M. Bills2d042d12023-03-28 15:32:45 -0700358 std::string remember;
359 EXPECT_EQ(getPamModuleArgValue("pam_pwhistory.so", "remember", remember),
360 0);
361 EXPECT_EQ(remember, "0");
362}
363
364TEST_F(UserMgrInTest, GetPamModuleConfValueOnSuccess)
365{
366 std::string minlen;
367 EXPECT_EQ(getPamModuleConfValue(tempPWQualityConfigFile, "minlen", minlen),
368 0);
369 EXPECT_EQ(minlen, "8");
370 std::string deny;
371 EXPECT_EQ(getPamModuleConfValue(tempFaillockConfigFile, "deny", deny), 0);
372 EXPECT_EQ(deny, "2");
Nan Zhoue48085d2022-10-25 00:07:04 +0000373}
374
375TEST_F(UserMgrInTest, SetPamModuleArgValueOnSuccess)
376{
Jason M. Bills2d042d12023-03-28 15:32:45 -0700377 EXPECT_EQ(setPamModuleArgValue("pam_pwhistory.so", "remember", "1"), 0);
378 std::string remember;
379 EXPECT_EQ(getPamModuleArgValue("pam_pwhistory.so", "remember", remember),
380 0);
381 EXPECT_EQ(remember, "1");
382}
383
384TEST_F(UserMgrInTest, SetPamModuleConfValueOnSuccess)
385{
386 EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
387 0);
388 std::string minlen;
389 EXPECT_EQ(getPamModuleConfValue(tempPWQualityConfigFile, "minlen", minlen),
390 0);
391 EXPECT_EQ(minlen, "16");
392
393 EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), 0);
394 std::string deny;
395 EXPECT_EQ(getPamModuleConfValue(tempFaillockConfigFile, "deny", deny), 0);
396 EXPECT_EQ(deny, "3");
Nan Zhoue48085d2022-10-25 00:07:04 +0000397}
398
399TEST_F(UserMgrInTest, GetPamModuleArgValueOnFailure)
400{
401 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPamConfigFile));
Jason M. Bills2d042d12023-03-28 15:32:45 -0700402 std::string remember;
403 EXPECT_EQ(getPamModuleArgValue("pam_pwhistory.so", "remember", remember),
404 -1);
Nan Zhoue48085d2022-10-25 00:07:04 +0000405
406 EXPECT_NO_THROW(removeFile(tempPamConfigFile));
Jason M. Bills2d042d12023-03-28 15:32:45 -0700407 EXPECT_EQ(getPamModuleArgValue("pam_pwhistory.so", "remember", remember),
408 -1);
409}
410
411TEST_F(UserMgrInTest, GetPamModuleConfValueOnFailure)
412{
413 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWQualityConfigFile));
414 std::string minlen;
415 EXPECT_EQ(getPamModuleConfValue(tempPWQualityConfigFile, "minlen", minlen),
416 -1);
417
418 EXPECT_NO_THROW(removeFile(tempPWQualityConfigFile));
419 EXPECT_EQ(getPamModuleConfValue(tempPWQualityConfigFile, "minlen", minlen),
420 -1);
421
422 EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
423 std::string deny;
424 EXPECT_EQ(getPamModuleConfValue(tempFaillockConfigFile, "deny", deny), -1);
425
426 EXPECT_NO_THROW(removeFile(tempFaillockConfigFile));
427 EXPECT_EQ(getPamModuleConfValue(tempFaillockConfigFile, "deny", deny), -1);
Nan Zhoue48085d2022-10-25 00:07:04 +0000428}
429
430TEST_F(UserMgrInTest, SetPamModuleArgValueOnFailure)
431{
432 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPamConfigFile));
Jason M. Bills2d042d12023-03-28 15:32:45 -0700433 EXPECT_EQ(setPamModuleArgValue("pam_pwhistory.so", "remember", "1"), -1);
Nan Zhoue48085d2022-10-25 00:07:04 +0000434
435 EXPECT_NO_THROW(removeFile(tempPamConfigFile));
Jason M. Bills2d042d12023-03-28 15:32:45 -0700436 EXPECT_EQ(setPamModuleArgValue("pam_pwhistory.so", "remember", "1"), -1);
437}
438
439TEST_F(UserMgrInTest, SetPamModuleConfValueOnFailure)
440{
441 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWQualityConfigFile));
442 EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
443 -1);
444
445 EXPECT_NO_THROW(removeFile(tempPWQualityConfigFile));
446 EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
447 -1);
448
449 EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
450 EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), -1);
451
452 EXPECT_NO_THROW(removeFile(tempFaillockConfigFile));
453 EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), -1);
Nan Zhoue48085d2022-10-25 00:07:04 +0000454}
455
Nan Zhou8a11d992022-10-25 00:07:06 +0000456TEST_F(UserMgrInTest, IsUserExistEmptyInputThrowsError)
457{
458 EXPECT_THROW(
459 isUserExist(""),
460 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
461}
462
463TEST_F(UserMgrInTest, ThrowForUserDoesNotExistThrowsError)
464{
465 EXPECT_THROW(throwForUserDoesNotExist("whatever"),
466 sdbusplus::xyz::openbmc_project::User::Common::Error::
467 UserNameDoesNotExist);
468}
469
470TEST_F(UserMgrInTest, ThrowForUserExistsThrowsError)
471{
472 EXPECT_THROW(
473 throwForUserExists("root"),
474 sdbusplus::xyz::openbmc_project::User::Common::Error::UserNameExists);
475}
476
Nan Zhou40e44972022-10-25 00:07:07 +0000477TEST_F(
478 UserMgrInTest,
479 ThrowForUserNameConstraintsExceedIpmiMaxUserNameLenThrowsUserNameGroupFail)
480{
481 std::string strWith17Chars(17, 'A');
482 EXPECT_THROW(throwForUserNameConstraints(strWith17Chars, {"ipmi"}),
483 sdbusplus::xyz::openbmc_project::User::Common::Error::
484 UserNameGroupFail);
485}
486
487TEST_F(
488 UserMgrInTest,
489 ThrowForUserNameConstraintsExceedSystemMaxUserNameLenThrowsInvalidArgument)
490{
491 std::string strWith31Chars(31, 'A');
492 EXPECT_THROW(
493 throwForUserNameConstraints(strWith31Chars, {}),
494 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
495}
496
497TEST_F(UserMgrInTest,
498 ThrowForUserNameConstraintsRegexMismatchThrowsInvalidArgument)
499{
500 std::string startWithNumber = "0ABC";
501 EXPECT_THROW(
502 throwForUserNameConstraints(startWithNumber, {"ipmi"}),
503 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
504}
505
Nan Zhou49c81362022-10-25 00:07:08 +0000506TEST_F(UserMgrInTest, UserAddNotRootFailedWithInternalFailure)
507{
508 EXPECT_THROW(
509 UserMgr::executeUserAdd("user0", "ipmi,ssh", true, true),
510 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
511}
512
513TEST_F(UserMgrInTest, UserDeleteNotRootFailedWithInternalFailure)
514{
515 EXPECT_THROW(
516 UserMgr::executeUserDelete("user0"),
517 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
518}
519
520TEST_F(UserMgrInTest,
521 ThrowForMaxGrpUserCountThrowsNoResourceWhenIpmiUserExceedLimit)
522{
523 EXPECT_CALL(*this, getIpmiUsersCount()).WillOnce(Return(ipmiMaxUsers));
524 EXPECT_THROW(
525 throwForMaxGrpUserCount({"ipmi"}),
526 sdbusplus::xyz::openbmc_project::User::Common::Error::NoResource);
527}
528
529TEST_F(UserMgrInTest, CreateUserThrowsInternalFailureWhenExecuteUserAddFails)
530{
531 EXPECT_CALL(*this, executeUserAdd)
532 .WillOnce(testing::Throw(
533 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
534 EXPECT_THROW(
535 createUser("whatever", {"redfish"}, "", true),
536 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
537}
538
539TEST_F(UserMgrInTest, DeleteUserThrowsInternalFailureWhenExecuteUserDeleteFails)
540{
541 std::string username = "user";
542 EXPECT_NO_THROW(
543 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
544 EXPECT_CALL(*this, executeUserDelete(testing::StrEq(username)))
545 .WillOnce(testing::Throw(
546 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()))
547 .WillOnce(testing::DoDefault());
548
549 EXPECT_THROW(
550 deleteUser(username),
551 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
552 EXPECT_NO_THROW(UserMgr::deleteUser(username));
553}
554
Nan Zhou589aeb42022-10-25 00:07:09 +0000555TEST_F(UserMgrInTest, ThrowForInvalidPrivilegeThrowsWhenPrivilegeIsInvalid)
556{
557 EXPECT_THROW(
558 throwForInvalidPrivilege("whatever"),
559 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
560}
561
562TEST_F(UserMgrInTest, ThrowForInvalidPrivilegeNoThrowWhenPrivilegeIsValid)
563{
564 EXPECT_NO_THROW(throwForInvalidPrivilege("priv-admin"));
565 EXPECT_NO_THROW(throwForInvalidPrivilege("priv-operator"));
566 EXPECT_NO_THROW(throwForInvalidPrivilege("priv-user"));
Nan Zhou589aeb42022-10-25 00:07:09 +0000567}
568
Nan Zhouecf88762022-10-25 00:07:10 +0000569TEST_F(UserMgrInTest, ThrowForInvalidGroupsThrowsWhenGroupIsInvalid)
570{
571 EXPECT_THROW(
572 throwForInvalidGroups({"whatever"}),
573 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
574}
575
576TEST_F(UserMgrInTest, ThrowForInvalidGroupsNoThrowWhenGroupIsValid)
577{
578 EXPECT_NO_THROW(throwForInvalidGroups({"ipmi"}));
579 EXPECT_NO_THROW(throwForInvalidGroups({"ssh"}));
580 EXPECT_NO_THROW(throwForInvalidGroups({"redfish"}));
581 EXPECT_NO_THROW(throwForInvalidGroups({"web"}));
Ninad Palsule601d3db2023-03-09 10:27:37 -0600582 EXPECT_NO_THROW(throwForInvalidGroups({"hostconsole"}));
Nan Zhouecf88762022-10-25 00:07:10 +0000583}
584
Nan Zhouf25443e2022-10-25 00:07:11 +0000585TEST_F(UserMgrInTest, RenameUserOnSuccess)
586{
587 std::string username = "user001";
588 EXPECT_NO_THROW(
589 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
590 std::string newUsername = "user002";
591
592 EXPECT_NO_THROW(UserMgr::renameUser(username, newUsername));
593
594 // old username doesn't exist
595 EXPECT_THROW(getUserInfo(username),
596 sdbusplus::xyz::openbmc_project::User::Common::Error::
597 UserNameDoesNotExist);
598
599 UserInfoMap userInfo = getUserInfo(newUsername);
600 EXPECT_EQ(std::get<Privilege>(userInfo["UserPrivilege"]), "priv-user");
601 EXPECT_THAT(std::get<GroupList>(userInfo["UserGroups"]),
602 testing::UnorderedElementsAre("redfish", "ssh"));
603 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
604
605 EXPECT_NO_THROW(UserMgr::deleteUser(newUsername));
606}
607
608TEST_F(UserMgrInTest, RenameUserThrowsInternalFailureIfExecuteUserModifyFails)
609{
610 std::string username = "user001";
611 EXPECT_NO_THROW(
612 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
613 std::string newUsername = "user002";
614
615 EXPECT_CALL(*this, executeUserRename(testing::StrEq(username),
616 testing::StrEq(newUsername)))
617 .WillOnce(testing::Throw(
618 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
619 EXPECT_THROW(
620 UserMgr::renameUser(username, newUsername),
621 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
622
623 // The original user is unchanged
624 UserInfoMap userInfo = getUserInfo(username);
625 EXPECT_EQ(std::get<Privilege>(userInfo["UserPrivilege"]), "priv-user");
626 EXPECT_THAT(std::get<GroupList>(userInfo["UserGroups"]),
627 testing::UnorderedElementsAre("redfish", "ssh"));
628 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
629
630 EXPECT_NO_THROW(UserMgr::deleteUser(username));
631}
632
633TEST_F(UserMgrInTest, DefaultUserModifyFailedWithInternalFailure)
634{
635 EXPECT_THROW(
636 UserMgr::executeUserRename("user0", "user1"),
637 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
Nan Zhoufef63032022-10-25 00:07:12 +0000638 EXPECT_THROW(
639 UserMgr::executeUserModify("user0", "ssh", true),
640 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
641}
642
643TEST_F(UserMgrInTest, UpdateGroupsAndPrivOnSuccess)
644{
645 std::string username = "user001";
646 EXPECT_NO_THROW(
647 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
648 EXPECT_NO_THROW(
649 updateGroupsAndPriv(username, {"ipmi", "ssh"}, "priv-admin"));
650 UserInfoMap userInfo = getUserInfo(username);
651 EXPECT_EQ(std::get<Privilege>(userInfo["UserPrivilege"]), "priv-admin");
652 EXPECT_THAT(std::get<GroupList>(userInfo["UserGroups"]),
653 testing::UnorderedElementsAre("ipmi", "ssh"));
654 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
655 EXPECT_NO_THROW(UserMgr::deleteUser(username));
656}
657
658TEST_F(UserMgrInTest,
659 UpdateGroupsAndPrivThrowsInternalFailureIfExecuteUserModifyFail)
660{
661 std::string username = "user001";
662 EXPECT_NO_THROW(
663 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
664 EXPECT_CALL(*this, executeUserModify(testing::StrEq(username), testing::_,
665 testing::_))
666 .WillOnce(testing::Throw(
667 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
668 EXPECT_THROW(
669 updateGroupsAndPriv(username, {"ipmi", "ssh"}, "priv-admin"),
670 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
671 EXPECT_NO_THROW(UserMgr::deleteUser(username));
Nan Zhouf25443e2022-10-25 00:07:11 +0000672}
673
Nan Zhou18031012022-11-10 22:24:58 +0000674TEST_F(UserMgrInTest, MinPasswordLengthReturnsIfValueIsTheSame)
675{
676 initializeAccountPolicy();
677 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
678 UserMgr::minPasswordLength(8);
679 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
680}
681
682TEST_F(UserMgrInTest,
683 MinPasswordLengthRejectsTooShortPasswordWithInvalidArgument)
684{
685 initializeAccountPolicy();
686 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
687 EXPECT_THROW(
688 UserMgr::minPasswordLength(minPasswdLength - 1),
689 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
690 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
691}
692
693TEST_F(UserMgrInTest, MinPasswordLengthOnSuccess)
694{
695 initializeAccountPolicy();
696 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
697 UserMgr::minPasswordLength(16);
698 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 16);
699}
700
701TEST_F(UserMgrInTest, MinPasswordLengthOnFailure)
702{
Jason M. Bills2d042d12023-03-28 15:32:45 -0700703 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWQualityConfigFile));
Nan Zhou18031012022-11-10 22:24:58 +0000704 initializeAccountPolicy();
705 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
706 EXPECT_THROW(
707 UserMgr::minPasswordLength(16),
708 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
709 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
710}
711
Nan Zhoua6ce1fa2022-10-25 00:07:14 +0000712TEST_F(UserMgrInTest, RememberOldPasswordTimesReturnsIfValueIsTheSame)
713{
714 initializeAccountPolicy();
715 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 0);
716 UserMgr::rememberOldPasswordTimes(8);
717 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 8);
718 UserMgr::rememberOldPasswordTimes(8);
719 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 8);
720}
721
722TEST_F(UserMgrInTest, RememberOldPasswordTimesOnSuccess)
723{
724 initializeAccountPolicy();
725 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 0);
726 UserMgr::rememberOldPasswordTimes(16);
727 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 16);
728}
729
730TEST_F(UserMgrInTest, RememberOldPasswordTimesOnFailure)
731{
732 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPamConfigFile));
733 initializeAccountPolicy();
734 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 0);
735 EXPECT_THROW(
736 UserMgr::rememberOldPasswordTimes(16),
737 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
738 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 0);
739}
740
Nan Zhoucfabe6b2022-10-25 00:07:15 +0000741TEST_F(UserMgrInTest, MaxLoginAttemptBeforeLockoutReturnsIfValueIsTheSame)
742{
743 initializeAccountPolicy();
744 EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 2);
745 UserMgr::maxLoginAttemptBeforeLockout(2);
746 EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 2);
747}
748
749TEST_F(UserMgrInTest, MaxLoginAttemptBeforeLockoutOnSuccess)
750{
751 initializeAccountPolicy();
752 EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 2);
753 UserMgr::maxLoginAttemptBeforeLockout(16);
754 EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 16);
755}
756
757TEST_F(UserMgrInTest, MaxLoginAttemptBeforeLockoutOnFailure)
758{
Nan Zhoucfabe6b2022-10-25 00:07:15 +0000759 initializeAccountPolicy();
Jason M. Bills2d042d12023-03-28 15:32:45 -0700760 EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
Nan Zhoucfabe6b2022-10-25 00:07:15 +0000761 EXPECT_THROW(
762 UserMgr::maxLoginAttemptBeforeLockout(16),
763 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
Jason M. Bills2d042d12023-03-28 15:32:45 -0700764 EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 2);
Nan Zhoucfabe6b2022-10-25 00:07:15 +0000765}
766
Nan Zhou784aecd2022-10-25 00:07:16 +0000767TEST_F(UserMgrInTest, AccountUnlockTimeoutReturnsIfValueIsTheSame)
768{
769 initializeAccountPolicy();
770 EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 3);
771 UserMgr::accountUnlockTimeout(3);
772 EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 3);
773}
774
775TEST_F(UserMgrInTest, AccountUnlockTimeoutOnSuccess)
776{
777 initializeAccountPolicy();
778 EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 3);
779 UserMgr::accountUnlockTimeout(16);
780 EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 16);
781}
782
783TEST_F(UserMgrInTest, AccountUnlockTimeoutOnFailure)
784{
785 initializeAccountPolicy();
Jason M. Bills2d042d12023-03-28 15:32:45 -0700786 EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
Nan Zhou784aecd2022-10-25 00:07:16 +0000787 EXPECT_THROW(
788 UserMgr::accountUnlockTimeout(16),
789 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
790 EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 3);
791}
792
Nan Zhou6b6f2d82022-10-25 00:07:17 +0000793TEST_F(UserMgrInTest, UserEnableOnSuccess)
794{
795 std::string username = "user001";
796 EXPECT_NO_THROW(
797 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
798 UserInfoMap userInfo = getUserInfo(username);
799 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
800
801 EXPECT_NO_THROW(userEnable(username, false));
802
803 userInfo = getUserInfo(username);
804 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), false);
805
806 EXPECT_NO_THROW(UserMgr::deleteUser(username));
807}
808
Ninad Palsule601d3db2023-03-09 10:27:37 -0600809TEST_F(UserMgrInTest, CreateDeleteUserSuccessForHostConsole)
810{
811 std::string username = "user001";
812 EXPECT_NO_THROW(
813 UserMgr::createUser(username, {"hostconsole"}, "priv-user", true));
814 EXPECT_NO_THROW(UserMgr::deleteUser(username));
815 EXPECT_NO_THROW(
816 UserMgr::createUser(username, {"hostconsole"}, "priv-admin", true));
817 EXPECT_NO_THROW(UserMgr::deleteUser(username));
818 EXPECT_NO_THROW(
819 UserMgr::createUser(username, {"hostconsole"}, "priv-operator", true));
820 EXPECT_NO_THROW(UserMgr::deleteUser(username));
821}
822
Nan Zhou6b6f2d82022-10-25 00:07:17 +0000823TEST_F(UserMgrInTest, UserEnableThrowsInternalFailureIfExecuteUserModifyFail)
824{
825 std::string username = "user001";
826 EXPECT_NO_THROW(
827 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
828 UserInfoMap userInfo = getUserInfo(username);
829 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
830
831 EXPECT_CALL(*this, executeUserModifyUserEnable(testing::StrEq(username),
832 testing::Eq(false)))
833 .WillOnce(testing::Throw(
834 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
835 EXPECT_THROW(
836 userEnable(username, false),
837 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
838
839 userInfo = getUserInfo(username);
840 // Stay unchanged
841 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
842
843 EXPECT_NO_THROW(UserMgr::deleteUser(username));
844}
845
Nan Zhoua2953032022-11-11 21:50:32 +0000846TEST_F(
847 UserMgrInTest,
848 UserLockedForFailedAttemptReturnsFalseIfMaxLoginAttemptBeforeLockoutIsZero)
849{
850 EXPECT_FALSE(userLockedForFailedAttempt("whatever"));
851}
852
853TEST_F(UserMgrInTest, UserLockedForFailedAttemptZeroFailuresReturnsFalse)
854{
855 std::string username = "user001";
856 initializeAccountPolicy();
857 // Example output from BMC
Jason M. Bills2d042d12023-03-28 15:32:45 -0700858 // root:~# faillock --user root
859 // root:
860 // When Type Source Valid
861 std::vector<std::string> output = {"whatever",
862 "When Type Source Valid"};
Nan Zhoua2953032022-11-11 21:50:32 +0000863 EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
864 .WillOnce(testing::Return(output));
865
866 EXPECT_FALSE(userLockedForFailedAttempt(username));
867}
868
869TEST_F(UserMgrInTest, UserLockedForFailedAttemptFailIfGetFailedAttemptFail)
870{
871 std::string username = "user001";
872 initializeAccountPolicy();
873 EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
874 .WillOnce(testing::Throw(
875 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
876
877 EXPECT_THROW(
878 userLockedForFailedAttempt(username),
879 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
880}
881
882TEST_F(UserMgrInTest,
Nan Zhoua2953032022-11-11 21:50:32 +0000883 UserLockedForFailedAttemptThrowsInternalFailureIfWrongDateFormat)
884{
885 std::string username = "user001";
886 initializeAccountPolicy();
887
888 // Choose a date in the past.
889 std::vector<std::string> output = {"whatever",
Jason M. Bills2d042d12023-03-28 15:32:45 -0700890 "10/24/2002 00:00:00 type source V"};
Nan Zhoua2953032022-11-11 21:50:32 +0000891 EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
892 .WillOnce(testing::Return(output));
893
894 EXPECT_THROW(
895 userLockedForFailedAttempt(username),
896 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
897}
898
899TEST_F(UserMgrInTest,
900 UserLockedForFailedAttemptReturnsFalseIfLastFailTimeHasTimedOut)
901{
902 std::string username = "user001";
903 initializeAccountPolicy();
904
905 // Choose a date in the past.
906 std::vector<std::string> output = {"whatever",
Jason M. Bills2d042d12023-03-28 15:32:45 -0700907 "2002-10-24 00:00:00 type source V"};
Nan Zhoua2953032022-11-11 21:50:32 +0000908 EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
909 .WillOnce(testing::Return(output));
910
911 EXPECT_EQ(userLockedForFailedAttempt(username), false);
912}
913
Nan Zhouda401fe2022-10-25 00:07:18 +0000914TEST_F(UserMgrInTest, CheckAndThrowForDisallowedGroupCreationOnSuccess)
915{
916 // Base Redfish Roles
917 EXPECT_NO_THROW(
918 checkAndThrowForDisallowedGroupCreation("openbmc_rfr_Administrator"));
919 EXPECT_NO_THROW(
920 checkAndThrowForDisallowedGroupCreation("openbmc_rfr_Operator"));
921 EXPECT_NO_THROW(
922 checkAndThrowForDisallowedGroupCreation("openbmc_rfr_ReadOnly"));
923 // Base Redfish Privileges
924 EXPECT_NO_THROW(
925 checkAndThrowForDisallowedGroupCreation("openbmc_rfp_Login"));
926 EXPECT_NO_THROW(checkAndThrowForDisallowedGroupCreation(
927 "openbmc_rfp_ConfigureManager"));
928 EXPECT_NO_THROW(
929 checkAndThrowForDisallowedGroupCreation("openbmc_rfp_ConfigureUsers"));
930 EXPECT_NO_THROW(
931 checkAndThrowForDisallowedGroupCreation("openbmc_rfp_ConfigureSelf"));
932 EXPECT_NO_THROW(checkAndThrowForDisallowedGroupCreation(
933 "openbmc_rfp_ConfigureComponents"));
934 // OEM Redfish Roles
935 EXPECT_NO_THROW(
936 checkAndThrowForDisallowedGroupCreation("openbmc_orfr_PowerService"));
937 // OEM Redfish Privileges
938 EXPECT_NO_THROW(
939 checkAndThrowForDisallowedGroupCreation("openbmc_orfp_PowerService"));
940}
941
942TEST_F(UserMgrInTest,
943 CheckAndThrowForDisallowedGroupCreationThrowsIfGroupNameTooLong)
944{
945 std::string groupName(maxSystemGroupNameLength + 1, 'A');
946 EXPECT_THROW(
947 checkAndThrowForDisallowedGroupCreation(groupName),
948 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
949}
950
951TEST_F(
952 UserMgrInTest,
953 CheckAndThrowForDisallowedGroupCreationThrowsIfGroupNameHasDisallowedCharacters)
954{
Nan Zhouda401fe2022-10-25 00:07:18 +0000955 EXPECT_THROW(
956 checkAndThrowForDisallowedGroupCreation("openbmc_rfp_?owerService"),
957 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
958 EXPECT_THROW(
959 checkAndThrowForDisallowedGroupCreation("openbmc_rfp_-owerService"),
960 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
961}
962
963TEST_F(
964 UserMgrInTest,
965 CheckAndThrowForDisallowedGroupCreationThrowsIfGroupNameHasDisallowedPrefix)
966{
Nan Zhouda401fe2022-10-25 00:07:18 +0000967 EXPECT_THROW(
968 checkAndThrowForDisallowedGroupCreation("google_rfp_"),
969 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
970 EXPECT_THROW(
971 checkAndThrowForDisallowedGroupCreation("com_rfp_"),
972 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
973}
974
975TEST_F(UserMgrInTest, CheckAndThrowForMaxGroupCountOnSuccess)
976{
Ninad Palsule601d3db2023-03-09 10:27:37 -0600977 constexpr size_t predefGroupCount = 5;
978
979 EXPECT_THAT(allGroups().size(), predefGroupCount);
980 for (size_t i = 0; i < maxSystemGroupCount - predefGroupCount; ++i)
Nan Zhouda401fe2022-10-25 00:07:18 +0000981 {
982 std::string groupName = "openbmc_rfr_role";
983 groupName += std::to_string(i);
984 EXPECT_NO_THROW(createGroup(groupName));
985 }
986 EXPECT_THROW(
987 createGroup("openbmc_rfr_AnotherRole"),
988 sdbusplus::xyz::openbmc_project::User::Common::Error::NoResource);
Ninad Palsule601d3db2023-03-09 10:27:37 -0600989 for (size_t i = 0; i < maxSystemGroupCount - predefGroupCount; ++i)
Nan Zhouda401fe2022-10-25 00:07:18 +0000990 {
991 std::string groupName = "openbmc_rfr_role";
992 groupName += std::to_string(i);
993 EXPECT_NO_THROW(deleteGroup(groupName));
994 }
995}
996
997TEST_F(UserMgrInTest, CheckAndThrowForGroupExist)
998{
999 std::string groupName = "openbmc_rfr_role";
1000 EXPECT_NO_THROW(createGroup(groupName));
1001 EXPECT_THROW(
1002 createGroup(groupName),
1003 sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1004 EXPECT_NO_THROW(deleteGroup(groupName));
1005}
1006
1007TEST_F(UserMgrInTest, ByDefaultAllGroupsArePredefinedGroups)
1008{
1009 EXPECT_THAT(allGroups(),
Ninad Palsule601d3db2023-03-09 10:27:37 -06001010 testing::UnorderedElementsAre("web", "redfish", "ipmi", "ssh",
1011 "hostconsole"));
1012}
1013
1014TEST_F(UserMgrInTest, AddGroupThrowsIfPreDefinedGroupAdd)
1015{
1016 EXPECT_THROW(
1017 createGroup("ipmi"),
1018 sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1019 EXPECT_THROW(
1020 createGroup("web"),
1021 sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1022 EXPECT_THROW(
1023 createGroup("redfish"),
1024 sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1025 EXPECT_THROW(
1026 createGroup("ssh"),
1027 sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1028 EXPECT_THROW(
1029 createGroup("hostconsole"),
1030 sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
Nan Zhouda401fe2022-10-25 00:07:18 +00001031}
1032
1033TEST_F(UserMgrInTest, DeleteGroupThrowsIfGroupIsNotAllowedToChange)
1034{
1035 EXPECT_THROW(
1036 deleteGroup("ipmi"),
1037 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1038 EXPECT_THROW(
1039 deleteGroup("web"),
1040 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1041 EXPECT_THROW(
1042 deleteGroup("redfish"),
1043 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1044 EXPECT_THROW(
1045 deleteGroup("ssh"),
1046 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
Ninad Palsule601d3db2023-03-09 10:27:37 -06001047 EXPECT_THROW(
1048 deleteGroup("hostconsole"),
1049 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
Nan Zhouda401fe2022-10-25 00:07:18 +00001050}
1051
1052TEST_F(UserMgrInTest,
1053 CreateGroupThrowsInternalFailureWhenExecuteGroupCreateFails)
1054{
1055 EXPECT_CALL(*this, executeGroupCreation)
1056 .WillOnce(testing::Throw(
1057 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
1058 EXPECT_THROW(
1059 createGroup("openbmc_rfr_role1"),
1060 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
1061}
1062
1063TEST_F(UserMgrInTest,
1064 DeleteGroupThrowsInternalFailureWhenExecuteGroupDeleteFails)
1065{
1066 std::string groupName = "openbmc_rfr_role1";
1067 EXPECT_NO_THROW(UserMgr::createGroup(groupName));
1068 EXPECT_CALL(*this, executeGroupDeletion(testing::StrEq(groupName)))
1069 .WillOnce(testing::Throw(
1070 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()))
1071 .WillOnce(testing::DoDefault());
1072
1073 EXPECT_THROW(
1074 deleteGroup(groupName),
1075 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
1076 EXPECT_NO_THROW(UserMgr::deleteGroup(groupName));
1077}
1078
1079TEST_F(UserMgrInTest, CheckAndThrowForGroupNotExist)
1080{
1081 EXPECT_THROW(deleteGroup("whatever"),
1082 sdbusplus::xyz::openbmc_project::User::Common::Error::
1083 GroupNameDoesNotExist);
1084}
1085
1086TEST(ReadAllGroupsOnSystemTest, OnlyReturnsPredefinedGroups)
1087{
1088 EXPECT_THAT(UserMgr::readAllGroupsOnSystem(),
Ninad Palsule601d3db2023-03-09 10:27:37 -06001089 testing::UnorderedElementsAre("web", "redfish", "ipmi", "ssh",
1090 "hostconsole"));
Nan Zhouda401fe2022-10-25 00:07:18 +00001091}
1092
raviteja-b8cc44052019-02-27 23:29:36 -06001093} // namespace user
1094} // namespace phosphor