blob: 9c825a48cf6824dff1c725d6eb053e0ed88a51aa [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
Jason M. Bills2d042d12023-03-28 15:32:45 -0700206inline constexpr const char* rawFailLockConfig = R"(
207deny=2
208unlock_time=3
209)";
Jason M. Bills3b280ec2023-08-15 16:15:48 -0700210inline constexpr const char* rawPWHistoryConfig = R"(
211enforce_for_root
212remember=0
213)";
Jason M. Bills2d042d12023-03-28 15:32:45 -0700214inline constexpr const char* rawPWQualityConfig = R"(
215enforce_for_root
216minlen=8
217difok=0
218lcredit=0
219ocredit=0
220dcredit=0
221ucredit=0
222)";
Nan Zhoue48085d2022-10-25 00:07:04 +0000223} // namespace
224
225void dumpStringToFile(const std::string& str, const std::string& filePath)
226{
227 std::ofstream outputFileStream;
228
229 outputFileStream.exceptions(std::ofstream::failbit | std::ofstream::badbit |
230 std::ofstream::eofbit);
231
232 outputFileStream.open(filePath, std::ios::out);
233 outputFileStream << str << "\n" << std::flush;
234 outputFileStream.close();
235}
236
237void removeFile(const std::string& filePath)
238{
239 std::filesystem::remove(filePath);
240}
241
242class UserMgrInTest : public testing::Test, public UserMgr
243{
244 public:
245 UserMgrInTest() : UserMgr(busInTest, objectRootInTest)
246 {
Jason M. Bills2d042d12023-03-28 15:32:45 -0700247 tempFaillockConfigFile = "/tmp/test-data-XXXXXX";
248 mktemp(tempFaillockConfigFile.data());
249 EXPECT_NO_THROW(
250 dumpStringToFile(rawFailLockConfig, tempFaillockConfigFile));
Jason M. Bills3b280ec2023-08-15 16:15:48 -0700251 tempPWHistoryConfigFile = "/tmp/test-data-XXXXXX";
252 mktemp(tempPWHistoryConfigFile.data());
253 EXPECT_NO_THROW(
254 dumpStringToFile(rawPWHistoryConfig, tempPWHistoryConfigFile));
Jason M. Bills2d042d12023-03-28 15:32:45 -0700255 tempPWQualityConfigFile = "/tmp/test-data-XXXXXX";
256 mktemp(tempPWQualityConfigFile.data());
257 EXPECT_NO_THROW(
258 dumpStringToFile(rawPWQualityConfig, tempPWQualityConfigFile));
Nan Zhoue48085d2022-10-25 00:07:04 +0000259 // Set config files to test files
Jason M. Bills2d042d12023-03-28 15:32:45 -0700260 faillockConfigFile = tempFaillockConfigFile;
Jason M. Bills3b280ec2023-08-15 16:15:48 -0700261 pwHistoryConfigFile = tempPWHistoryConfigFile;
Jason M. Bills2d042d12023-03-28 15:32:45 -0700262 pwQualityConfigFile = tempPWQualityConfigFile;
Nan Zhou49c81362022-10-25 00:07:08 +0000263
264 ON_CALL(*this, executeUserAdd).WillByDefault(testing::Return());
265
266 ON_CALL(*this, executeUserDelete).WillByDefault(testing::Return());
267
Jayanth Othayothac921a52023-07-21 03:48:55 -0500268 ON_CALL(*this, executeUserClearFailRecords)
269 .WillByDefault(testing::Return());
270
Nan Zhou49c81362022-10-25 00:07:08 +0000271 ON_CALL(*this, getIpmiUsersCount).WillByDefault(testing::Return(0));
Nan Zhouf25443e2022-10-25 00:07:11 +0000272
273 ON_CALL(*this, executeUserRename).WillByDefault(testing::Return());
Nan Zhoufef63032022-10-25 00:07:12 +0000274
275 ON_CALL(*this, executeUserModify(testing::_, testing::_, testing::_))
276 .WillByDefault(testing::Return());
Nan Zhou6b6f2d82022-10-25 00:07:17 +0000277
278 ON_CALL(*this, executeUserModifyUserEnable)
279 .WillByDefault(testing::Return());
Nan Zhouda401fe2022-10-25 00:07:18 +0000280
281 ON_CALL(*this, executeGroupCreation(testing::_))
282 .WillByDefault(testing::Return());
283
284 ON_CALL(*this, executeGroupDeletion(testing::_))
285 .WillByDefault(testing::Return());
286
287 ON_CALL(*this, executeGroupCreation).WillByDefault(testing::Return());
288
289 ON_CALL(*this, executeGroupDeletion).WillByDefault(testing::Return());
Nan Zhoue48085d2022-10-25 00:07:04 +0000290 }
291
292 ~UserMgrInTest() override
293 {
Jason M. Bills2d042d12023-03-28 15:32:45 -0700294 EXPECT_NO_THROW(removeFile(tempFaillockConfigFile));
Jason M. Bills3b280ec2023-08-15 16:15:48 -0700295 EXPECT_NO_THROW(removeFile(tempPWHistoryConfigFile));
Jason M. Bills2d042d12023-03-28 15:32:45 -0700296 EXPECT_NO_THROW(removeFile(tempPWQualityConfigFile));
Nan Zhoue48085d2022-10-25 00:07:04 +0000297 }
298
Nan Zhou49c81362022-10-25 00:07:08 +0000299 MOCK_METHOD(void, executeUserAdd, (const char*, const char*, bool, bool),
300 (override));
301
302 MOCK_METHOD(void, executeUserDelete, (const char*), (override));
303
Jayanth Othayothac921a52023-07-21 03:48:55 -0500304 MOCK_METHOD(void, executeUserClearFailRecords, (const char*), (override));
305
Nan Zhou49c81362022-10-25 00:07:08 +0000306 MOCK_METHOD(size_t, getIpmiUsersCount, (), (override));
307
Nan Zhouf25443e2022-10-25 00:07:11 +0000308 MOCK_METHOD(void, executeUserRename, (const char*, const char*),
309 (override));
310
Nan Zhoufef63032022-10-25 00:07:12 +0000311 MOCK_METHOD(void, executeUserModify, (const char*, const char*, bool),
312 (override));
313
Nan Zhou6b6f2d82022-10-25 00:07:17 +0000314 MOCK_METHOD(void, executeUserModifyUserEnable, (const char*, bool),
315 (override));
316
Nan Zhoua2953032022-11-11 21:50:32 +0000317 MOCK_METHOD(std::vector<std::string>, getFailedAttempt, (const char*),
318 (override));
319
Nan Zhouda401fe2022-10-25 00:07:18 +0000320 MOCK_METHOD(void, executeGroupCreation, (const char*), (override));
321
322 MOCK_METHOD(void, executeGroupDeletion, (const char*), (override));
323
Nan Zhoufef63032022-10-25 00:07:12 +0000324 protected:
Nan Zhoue48085d2022-10-25 00:07:04 +0000325 static sdbusplus::bus_t busInTest;
Jason M. Bills2d042d12023-03-28 15:32:45 -0700326 std::string tempFaillockConfigFile;
Jason M. Bills3b280ec2023-08-15 16:15:48 -0700327 std::string tempPWHistoryConfigFile;
Jason M. Bills2d042d12023-03-28 15:32:45 -0700328 std::string tempPWQualityConfigFile;
Nan Zhoue48085d2022-10-25 00:07:04 +0000329};
330
331sdbusplus::bus_t UserMgrInTest::busInTest = sdbusplus::bus::new_default();
332
Jason M. Bills2d042d12023-03-28 15:32:45 -0700333TEST_F(UserMgrInTest, GetPamModuleConfValueOnSuccess)
334{
335 std::string minlen;
336 EXPECT_EQ(getPamModuleConfValue(tempPWQualityConfigFile, "minlen", minlen),
337 0);
338 EXPECT_EQ(minlen, "8");
339 std::string deny;
340 EXPECT_EQ(getPamModuleConfValue(tempFaillockConfigFile, "deny", deny), 0);
341 EXPECT_EQ(deny, "2");
Jason M. Bills2d042d12023-03-28 15:32:45 -0700342 std::string remember;
Jason M. Bills3b280ec2023-08-15 16:15:48 -0700343 EXPECT_EQ(
344 getPamModuleConfValue(tempPWHistoryConfigFile, "remember", remember),
345 0);
346 EXPECT_EQ(remember, "0");
Jason M. Bills2d042d12023-03-28 15:32:45 -0700347}
348
349TEST_F(UserMgrInTest, SetPamModuleConfValueOnSuccess)
350{
351 EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
352 0);
353 std::string minlen;
354 EXPECT_EQ(getPamModuleConfValue(tempPWQualityConfigFile, "minlen", minlen),
355 0);
356 EXPECT_EQ(minlen, "16");
357
358 EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), 0);
359 std::string deny;
360 EXPECT_EQ(getPamModuleConfValue(tempFaillockConfigFile, "deny", deny), 0);
361 EXPECT_EQ(deny, "3");
Nan Zhoue48085d2022-10-25 00:07:04 +0000362
Jason M. Bills3b280ec2023-08-15 16:15:48 -0700363 EXPECT_EQ(setPamModuleConfValue(tempPWHistoryConfigFile, "remember", "1"),
364 0);
365 std::string remember;
366 EXPECT_EQ(
367 getPamModuleConfValue(tempPWHistoryConfigFile, "remember", remember),
368 0);
369 EXPECT_EQ(remember, "1");
Jason M. Bills17b88272023-05-22 14:24:02 -0700370}
371
372TEST_F(UserMgrInTest, SetPamModuleConfValueTempFileOnSuccess)
373{
374 EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
375 0);
376
377 std::string tmpFile = tempPWQualityConfigFile + "_tmp";
378 EXPECT_FALSE(std::filesystem::exists(tmpFile));
379
380 EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), 0);
381
382 tmpFile = tempFaillockConfigFile + "_tmp";
383 EXPECT_FALSE(std::filesystem::exists(tmpFile));
Jason M. Bills17b88272023-05-22 14:24:02 -0700384
Jason M. Bills3b280ec2023-08-15 16:15:48 -0700385 EXPECT_EQ(setPamModuleConfValue(tempPWHistoryConfigFile, "remember", "1"),
386 0);
Nan Zhoue48085d2022-10-25 00:07:04 +0000387
Jason M. Bills3b280ec2023-08-15 16:15:48 -0700388 tmpFile = tempPWHistoryConfigFile + "_tmp";
389 EXPECT_FALSE(std::filesystem::exists(tmpFile));
Jason M. Bills2d042d12023-03-28 15:32:45 -0700390}
391
392TEST_F(UserMgrInTest, GetPamModuleConfValueOnFailure)
393{
394 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWQualityConfigFile));
395 std::string minlen;
396 EXPECT_EQ(getPamModuleConfValue(tempPWQualityConfigFile, "minlen", minlen),
397 -1);
398
399 EXPECT_NO_THROW(removeFile(tempPWQualityConfigFile));
400 EXPECT_EQ(getPamModuleConfValue(tempPWQualityConfigFile, "minlen", minlen),
401 -1);
402
403 EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
404 std::string deny;
405 EXPECT_EQ(getPamModuleConfValue(tempFaillockConfigFile, "deny", deny), -1);
406
407 EXPECT_NO_THROW(removeFile(tempFaillockConfigFile));
408 EXPECT_EQ(getPamModuleConfValue(tempFaillockConfigFile, "deny", deny), -1);
Nan Zhoue48085d2022-10-25 00:07:04 +0000409
Jason M. Bills3b280ec2023-08-15 16:15:48 -0700410 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWHistoryConfigFile));
411 std::string remember;
412 EXPECT_EQ(
413 getPamModuleConfValue(tempPWHistoryConfigFile, "remember", remember),
414 -1);
Nan Zhoue48085d2022-10-25 00:07:04 +0000415
Jason M. Bills3b280ec2023-08-15 16:15:48 -0700416 EXPECT_NO_THROW(removeFile(tempPWHistoryConfigFile));
417 EXPECT_EQ(
418 getPamModuleConfValue(tempPWHistoryConfigFile, "remember", remember),
419 -1);
Jason M. Bills2d042d12023-03-28 15:32:45 -0700420}
421
422TEST_F(UserMgrInTest, SetPamModuleConfValueOnFailure)
423{
424 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWQualityConfigFile));
425 EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
426 -1);
427
428 EXPECT_NO_THROW(removeFile(tempPWQualityConfigFile));
429 EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
430 -1);
431
432 EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
433 EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), -1);
434
435 EXPECT_NO_THROW(removeFile(tempFaillockConfigFile));
436 EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), -1);
Nan Zhoue48085d2022-10-25 00:07:04 +0000437
Jason M. Bills3b280ec2023-08-15 16:15:48 -0700438 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWHistoryConfigFile));
439 EXPECT_EQ(setPamModuleConfValue(tempPWHistoryConfigFile, "remember", "1"),
440 -1);
Jason M. Bills17b88272023-05-22 14:24:02 -0700441
Jason M. Bills3b280ec2023-08-15 16:15:48 -0700442 EXPECT_NO_THROW(removeFile(tempPWHistoryConfigFile));
443 EXPECT_EQ(setPamModuleConfValue(tempPWHistoryConfigFile, "remember", "1"),
444 -1);
Jason M. Bills17b88272023-05-22 14:24:02 -0700445}
446
447TEST_F(UserMgrInTest, SetPamModuleConfValueTempFileOnFailure)
448{
449 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWQualityConfigFile));
450 EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
451 -1);
452
453 std::string tmpFile = tempPWQualityConfigFile + "_tmp";
454 EXPECT_FALSE(std::filesystem::exists(tmpFile));
455
456 EXPECT_NO_THROW(removeFile(tempPWQualityConfigFile));
457 EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
458 -1);
459
460 EXPECT_FALSE(std::filesystem::exists(tmpFile));
461
462 EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
463 EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), -1);
464
465 tmpFile = tempFaillockConfigFile + "_tmp";
466 EXPECT_FALSE(std::filesystem::exists(tmpFile));
467
468 EXPECT_NO_THROW(removeFile(tempFaillockConfigFile));
469 EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), -1);
470
471 EXPECT_FALSE(std::filesystem::exists(tmpFile));
Jason M. Bills3b280ec2023-08-15 16:15:48 -0700472
473 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWHistoryConfigFile));
474 EXPECT_EQ(setPamModuleConfValue(tempPWHistoryConfigFile, "remember", "1"),
475 -1);
476
477 tmpFile = tempPWHistoryConfigFile + "_tmp";
478 EXPECT_FALSE(std::filesystem::exists(tmpFile));
479
480 EXPECT_NO_THROW(removeFile(tempPWHistoryConfigFile));
481 EXPECT_EQ(setPamModuleConfValue(tempPWHistoryConfigFile, "remember", "1"),
482 -1);
483
484 EXPECT_FALSE(std::filesystem::exists(tmpFile));
Jason M. Bills17b88272023-05-22 14:24:02 -0700485}
486
Nan Zhou8a11d992022-10-25 00:07:06 +0000487TEST_F(UserMgrInTest, IsUserExistEmptyInputThrowsError)
488{
489 EXPECT_THROW(
490 isUserExist(""),
491 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
492}
493
494TEST_F(UserMgrInTest, ThrowForUserDoesNotExistThrowsError)
495{
496 EXPECT_THROW(throwForUserDoesNotExist("whatever"),
497 sdbusplus::xyz::openbmc_project::User::Common::Error::
498 UserNameDoesNotExist);
499}
500
501TEST_F(UserMgrInTest, ThrowForUserExistsThrowsError)
502{
503 EXPECT_THROW(
504 throwForUserExists("root"),
505 sdbusplus::xyz::openbmc_project::User::Common::Error::UserNameExists);
506}
507
Nan Zhou40e44972022-10-25 00:07:07 +0000508TEST_F(
509 UserMgrInTest,
510 ThrowForUserNameConstraintsExceedIpmiMaxUserNameLenThrowsUserNameGroupFail)
511{
512 std::string strWith17Chars(17, 'A');
513 EXPECT_THROW(throwForUserNameConstraints(strWith17Chars, {"ipmi"}),
514 sdbusplus::xyz::openbmc_project::User::Common::Error::
515 UserNameGroupFail);
516}
517
518TEST_F(
519 UserMgrInTest,
520 ThrowForUserNameConstraintsExceedSystemMaxUserNameLenThrowsInvalidArgument)
521{
522 std::string strWith31Chars(31, 'A');
523 EXPECT_THROW(
524 throwForUserNameConstraints(strWith31Chars, {}),
525 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
526}
527
528TEST_F(UserMgrInTest,
529 ThrowForUserNameConstraintsRegexMismatchThrowsInvalidArgument)
530{
531 std::string startWithNumber = "0ABC";
532 EXPECT_THROW(
533 throwForUserNameConstraints(startWithNumber, {"ipmi"}),
534 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
535}
536
Nan Zhou49c81362022-10-25 00:07:08 +0000537TEST_F(UserMgrInTest, UserAddNotRootFailedWithInternalFailure)
538{
539 EXPECT_THROW(
540 UserMgr::executeUserAdd("user0", "ipmi,ssh", true, true),
541 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
542}
543
544TEST_F(UserMgrInTest, UserDeleteNotRootFailedWithInternalFailure)
545{
546 EXPECT_THROW(
547 UserMgr::executeUserDelete("user0"),
548 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
549}
550
551TEST_F(UserMgrInTest,
552 ThrowForMaxGrpUserCountThrowsNoResourceWhenIpmiUserExceedLimit)
553{
554 EXPECT_CALL(*this, getIpmiUsersCount()).WillOnce(Return(ipmiMaxUsers));
555 EXPECT_THROW(
556 throwForMaxGrpUserCount({"ipmi"}),
557 sdbusplus::xyz::openbmc_project::User::Common::Error::NoResource);
558}
559
560TEST_F(UserMgrInTest, CreateUserThrowsInternalFailureWhenExecuteUserAddFails)
561{
562 EXPECT_CALL(*this, executeUserAdd)
563 .WillOnce(testing::Throw(
564 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
565 EXPECT_THROW(
566 createUser("whatever", {"redfish"}, "", true),
567 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
568}
569
570TEST_F(UserMgrInTest, DeleteUserThrowsInternalFailureWhenExecuteUserDeleteFails)
571{
572 std::string username = "user";
573 EXPECT_NO_THROW(
574 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
575 EXPECT_CALL(*this, executeUserDelete(testing::StrEq(username)))
576 .WillOnce(testing::Throw(
577 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()))
578 .WillOnce(testing::DoDefault());
579
580 EXPECT_THROW(
581 deleteUser(username),
582 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
583 EXPECT_NO_THROW(UserMgr::deleteUser(username));
584}
585
Jayanth Othayothac921a52023-07-21 03:48:55 -0500586TEST_F(UserMgrInTest,
587 DeleteUserThrowsInternalFailureWhenExecuteUserClearFailRecords)
588{
589 const char* username = "user";
590 EXPECT_NO_THROW(
591 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
592 EXPECT_CALL(*this, executeUserClearFailRecords(testing::StrEq(username)))
593 .WillOnce(testing::Throw(
594 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()))
595 .WillOnce(testing::DoDefault());
596
597 EXPECT_THROW(
598 deleteUser(username),
599 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
600 EXPECT_NO_THROW(UserMgr::deleteUser(username));
601}
602
Nan Zhou589aeb42022-10-25 00:07:09 +0000603TEST_F(UserMgrInTest, ThrowForInvalidPrivilegeThrowsWhenPrivilegeIsInvalid)
604{
605 EXPECT_THROW(
606 throwForInvalidPrivilege("whatever"),
607 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
608}
609
610TEST_F(UserMgrInTest, ThrowForInvalidPrivilegeNoThrowWhenPrivilegeIsValid)
611{
612 EXPECT_NO_THROW(throwForInvalidPrivilege("priv-admin"));
613 EXPECT_NO_THROW(throwForInvalidPrivilege("priv-operator"));
614 EXPECT_NO_THROW(throwForInvalidPrivilege("priv-user"));
Nan Zhou589aeb42022-10-25 00:07:09 +0000615}
616
Nan Zhouecf88762022-10-25 00:07:10 +0000617TEST_F(UserMgrInTest, ThrowForInvalidGroupsThrowsWhenGroupIsInvalid)
618{
619 EXPECT_THROW(
620 throwForInvalidGroups({"whatever"}),
621 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
622}
623
624TEST_F(UserMgrInTest, ThrowForInvalidGroupsNoThrowWhenGroupIsValid)
625{
626 EXPECT_NO_THROW(throwForInvalidGroups({"ipmi"}));
627 EXPECT_NO_THROW(throwForInvalidGroups({"ssh"}));
628 EXPECT_NO_THROW(throwForInvalidGroups({"redfish"}));
629 EXPECT_NO_THROW(throwForInvalidGroups({"web"}));
Ninad Palsule601d3db2023-03-09 10:27:37 -0600630 EXPECT_NO_THROW(throwForInvalidGroups({"hostconsole"}));
Nan Zhouecf88762022-10-25 00:07:10 +0000631}
632
Nan Zhouf25443e2022-10-25 00:07:11 +0000633TEST_F(UserMgrInTest, RenameUserOnSuccess)
634{
635 std::string username = "user001";
636 EXPECT_NO_THROW(
637 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
638 std::string newUsername = "user002";
639
640 EXPECT_NO_THROW(UserMgr::renameUser(username, newUsername));
641
642 // old username doesn't exist
643 EXPECT_THROW(getUserInfo(username),
644 sdbusplus::xyz::openbmc_project::User::Common::Error::
645 UserNameDoesNotExist);
646
647 UserInfoMap userInfo = getUserInfo(newUsername);
648 EXPECT_EQ(std::get<Privilege>(userInfo["UserPrivilege"]), "priv-user");
649 EXPECT_THAT(std::get<GroupList>(userInfo["UserGroups"]),
650 testing::UnorderedElementsAre("redfish", "ssh"));
651 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
652
653 EXPECT_NO_THROW(UserMgr::deleteUser(newUsername));
654}
655
656TEST_F(UserMgrInTest, RenameUserThrowsInternalFailureIfExecuteUserModifyFails)
657{
658 std::string username = "user001";
659 EXPECT_NO_THROW(
660 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
661 std::string newUsername = "user002";
662
663 EXPECT_CALL(*this, executeUserRename(testing::StrEq(username),
664 testing::StrEq(newUsername)))
665 .WillOnce(testing::Throw(
666 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
667 EXPECT_THROW(
668 UserMgr::renameUser(username, newUsername),
669 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
670
671 // The original user is unchanged
672 UserInfoMap userInfo = getUserInfo(username);
673 EXPECT_EQ(std::get<Privilege>(userInfo["UserPrivilege"]), "priv-user");
674 EXPECT_THAT(std::get<GroupList>(userInfo["UserGroups"]),
675 testing::UnorderedElementsAre("redfish", "ssh"));
676 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
677
678 EXPECT_NO_THROW(UserMgr::deleteUser(username));
679}
680
681TEST_F(UserMgrInTest, DefaultUserModifyFailedWithInternalFailure)
682{
683 EXPECT_THROW(
684 UserMgr::executeUserRename("user0", "user1"),
685 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
Nan Zhoufef63032022-10-25 00:07:12 +0000686 EXPECT_THROW(
687 UserMgr::executeUserModify("user0", "ssh", true),
688 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
689}
690
691TEST_F(UserMgrInTest, UpdateGroupsAndPrivOnSuccess)
692{
693 std::string username = "user001";
694 EXPECT_NO_THROW(
695 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
696 EXPECT_NO_THROW(
697 updateGroupsAndPriv(username, {"ipmi", "ssh"}, "priv-admin"));
698 UserInfoMap userInfo = getUserInfo(username);
699 EXPECT_EQ(std::get<Privilege>(userInfo["UserPrivilege"]), "priv-admin");
700 EXPECT_THAT(std::get<GroupList>(userInfo["UserGroups"]),
701 testing::UnorderedElementsAre("ipmi", "ssh"));
702 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
703 EXPECT_NO_THROW(UserMgr::deleteUser(username));
704}
705
706TEST_F(UserMgrInTest,
707 UpdateGroupsAndPrivThrowsInternalFailureIfExecuteUserModifyFail)
708{
709 std::string username = "user001";
710 EXPECT_NO_THROW(
711 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
712 EXPECT_CALL(*this, executeUserModify(testing::StrEq(username), testing::_,
713 testing::_))
714 .WillOnce(testing::Throw(
715 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
716 EXPECT_THROW(
717 updateGroupsAndPriv(username, {"ipmi", "ssh"}, "priv-admin"),
718 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
719 EXPECT_NO_THROW(UserMgr::deleteUser(username));
Nan Zhouf25443e2022-10-25 00:07:11 +0000720}
721
Nan Zhou18031012022-11-10 22:24:58 +0000722TEST_F(UserMgrInTest, MinPasswordLengthReturnsIfValueIsTheSame)
723{
724 initializeAccountPolicy();
725 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
726 UserMgr::minPasswordLength(8);
727 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
728}
729
730TEST_F(UserMgrInTest,
731 MinPasswordLengthRejectsTooShortPasswordWithInvalidArgument)
732{
733 initializeAccountPolicy();
734 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
735 EXPECT_THROW(
736 UserMgr::minPasswordLength(minPasswdLength - 1),
737 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
738 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
739}
740
741TEST_F(UserMgrInTest, MinPasswordLengthOnSuccess)
742{
743 initializeAccountPolicy();
744 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
745 UserMgr::minPasswordLength(16);
746 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 16);
747}
748
749TEST_F(UserMgrInTest, MinPasswordLengthOnFailure)
750{
Jason M. Bills2d042d12023-03-28 15:32:45 -0700751 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWQualityConfigFile));
Nan Zhou18031012022-11-10 22:24:58 +0000752 initializeAccountPolicy();
753 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
754 EXPECT_THROW(
755 UserMgr::minPasswordLength(16),
756 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
757 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
758}
759
Nan Zhoua6ce1fa2022-10-25 00:07:14 +0000760TEST_F(UserMgrInTest, RememberOldPasswordTimesReturnsIfValueIsTheSame)
761{
762 initializeAccountPolicy();
763 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 0);
764 UserMgr::rememberOldPasswordTimes(8);
765 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 8);
766 UserMgr::rememberOldPasswordTimes(8);
767 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 8);
768}
769
770TEST_F(UserMgrInTest, RememberOldPasswordTimesOnSuccess)
771{
772 initializeAccountPolicy();
773 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 0);
774 UserMgr::rememberOldPasswordTimes(16);
775 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 16);
776}
777
778TEST_F(UserMgrInTest, RememberOldPasswordTimesOnFailure)
779{
Jason M. Bills3b280ec2023-08-15 16:15:48 -0700780 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWHistoryConfigFile));
Nan Zhoua6ce1fa2022-10-25 00:07:14 +0000781 initializeAccountPolicy();
782 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 0);
783 EXPECT_THROW(
784 UserMgr::rememberOldPasswordTimes(16),
785 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
786 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 0);
787}
788
Nan Zhoucfabe6b2022-10-25 00:07:15 +0000789TEST_F(UserMgrInTest, MaxLoginAttemptBeforeLockoutReturnsIfValueIsTheSame)
790{
791 initializeAccountPolicy();
792 EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 2);
793 UserMgr::maxLoginAttemptBeforeLockout(2);
794 EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 2);
795}
796
797TEST_F(UserMgrInTest, MaxLoginAttemptBeforeLockoutOnSuccess)
798{
799 initializeAccountPolicy();
800 EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 2);
801 UserMgr::maxLoginAttemptBeforeLockout(16);
802 EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 16);
803}
804
805TEST_F(UserMgrInTest, MaxLoginAttemptBeforeLockoutOnFailure)
806{
Nan Zhoucfabe6b2022-10-25 00:07:15 +0000807 initializeAccountPolicy();
Jason M. Bills2d042d12023-03-28 15:32:45 -0700808 EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
Nan Zhoucfabe6b2022-10-25 00:07:15 +0000809 EXPECT_THROW(
810 UserMgr::maxLoginAttemptBeforeLockout(16),
811 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
Jason M. Bills2d042d12023-03-28 15:32:45 -0700812 EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 2);
Nan Zhoucfabe6b2022-10-25 00:07:15 +0000813}
814
Nan Zhou784aecd2022-10-25 00:07:16 +0000815TEST_F(UserMgrInTest, AccountUnlockTimeoutReturnsIfValueIsTheSame)
816{
817 initializeAccountPolicy();
818 EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 3);
819 UserMgr::accountUnlockTimeout(3);
820 EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 3);
821}
822
823TEST_F(UserMgrInTest, AccountUnlockTimeoutOnSuccess)
824{
825 initializeAccountPolicy();
826 EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 3);
827 UserMgr::accountUnlockTimeout(16);
828 EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 16);
829}
830
831TEST_F(UserMgrInTest, AccountUnlockTimeoutOnFailure)
832{
833 initializeAccountPolicy();
Jason M. Bills2d042d12023-03-28 15:32:45 -0700834 EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
Nan Zhou784aecd2022-10-25 00:07:16 +0000835 EXPECT_THROW(
836 UserMgr::accountUnlockTimeout(16),
837 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
838 EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 3);
839}
840
Nan Zhou6b6f2d82022-10-25 00:07:17 +0000841TEST_F(UserMgrInTest, UserEnableOnSuccess)
842{
843 std::string username = "user001";
844 EXPECT_NO_THROW(
845 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
846 UserInfoMap userInfo = getUserInfo(username);
847 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
848
849 EXPECT_NO_THROW(userEnable(username, false));
850
851 userInfo = getUserInfo(username);
852 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), false);
853
854 EXPECT_NO_THROW(UserMgr::deleteUser(username));
855}
856
Ninad Palsule601d3db2023-03-09 10:27:37 -0600857TEST_F(UserMgrInTest, CreateDeleteUserSuccessForHostConsole)
858{
859 std::string username = "user001";
860 EXPECT_NO_THROW(
861 UserMgr::createUser(username, {"hostconsole"}, "priv-user", true));
862 EXPECT_NO_THROW(UserMgr::deleteUser(username));
863 EXPECT_NO_THROW(
864 UserMgr::createUser(username, {"hostconsole"}, "priv-admin", true));
865 EXPECT_NO_THROW(UserMgr::deleteUser(username));
866 EXPECT_NO_THROW(
867 UserMgr::createUser(username, {"hostconsole"}, "priv-operator", true));
868 EXPECT_NO_THROW(UserMgr::deleteUser(username));
869}
870
Nan Zhou6b6f2d82022-10-25 00:07:17 +0000871TEST_F(UserMgrInTest, UserEnableThrowsInternalFailureIfExecuteUserModifyFail)
872{
873 std::string username = "user001";
874 EXPECT_NO_THROW(
875 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
876 UserInfoMap userInfo = getUserInfo(username);
877 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
878
879 EXPECT_CALL(*this, executeUserModifyUserEnable(testing::StrEq(username),
880 testing::Eq(false)))
881 .WillOnce(testing::Throw(
882 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
883 EXPECT_THROW(
884 userEnable(username, false),
885 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
886
887 userInfo = getUserInfo(username);
888 // Stay unchanged
889 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
890
891 EXPECT_NO_THROW(UserMgr::deleteUser(username));
892}
893
Nan Zhoua2953032022-11-11 21:50:32 +0000894TEST_F(
895 UserMgrInTest,
896 UserLockedForFailedAttemptReturnsFalseIfMaxLoginAttemptBeforeLockoutIsZero)
897{
898 EXPECT_FALSE(userLockedForFailedAttempt("whatever"));
899}
900
901TEST_F(UserMgrInTest, UserLockedForFailedAttemptZeroFailuresReturnsFalse)
902{
903 std::string username = "user001";
904 initializeAccountPolicy();
905 // Example output from BMC
Jason M. Bills2d042d12023-03-28 15:32:45 -0700906 // root:~# faillock --user root
907 // root:
908 // When Type Source Valid
909 std::vector<std::string> output = {"whatever",
910 "When Type Source Valid"};
Nan Zhoua2953032022-11-11 21:50:32 +0000911 EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
912 .WillOnce(testing::Return(output));
913
914 EXPECT_FALSE(userLockedForFailedAttempt(username));
915}
916
917TEST_F(UserMgrInTest, UserLockedForFailedAttemptFailIfGetFailedAttemptFail)
918{
919 std::string username = "user001";
920 initializeAccountPolicy();
921 EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
922 .WillOnce(testing::Throw(
923 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
924
925 EXPECT_THROW(
926 userLockedForFailedAttempt(username),
927 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
928}
929
930TEST_F(UserMgrInTest,
Nan Zhoua2953032022-11-11 21:50:32 +0000931 UserLockedForFailedAttemptThrowsInternalFailureIfWrongDateFormat)
932{
933 std::string username = "user001";
934 initializeAccountPolicy();
935
936 // Choose a date in the past.
937 std::vector<std::string> output = {"whatever",
Jason M. Bills2d042d12023-03-28 15:32:45 -0700938 "10/24/2002 00:00:00 type source V"};
Nan Zhoua2953032022-11-11 21:50:32 +0000939 EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
940 .WillOnce(testing::Return(output));
941
942 EXPECT_THROW(
943 userLockedForFailedAttempt(username),
944 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
945}
946
947TEST_F(UserMgrInTest,
948 UserLockedForFailedAttemptReturnsFalseIfLastFailTimeHasTimedOut)
949{
950 std::string username = "user001";
951 initializeAccountPolicy();
952
953 // Choose a date in the past.
954 std::vector<std::string> output = {"whatever",
Jason M. Bills2d042d12023-03-28 15:32:45 -0700955 "2002-10-24 00:00:00 type source V"};
Nan Zhoua2953032022-11-11 21:50:32 +0000956 EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
957 .WillOnce(testing::Return(output));
958
959 EXPECT_EQ(userLockedForFailedAttempt(username), false);
960}
961
Nan Zhouda401fe2022-10-25 00:07:18 +0000962TEST_F(UserMgrInTest, CheckAndThrowForDisallowedGroupCreationOnSuccess)
963{
964 // Base Redfish Roles
965 EXPECT_NO_THROW(
966 checkAndThrowForDisallowedGroupCreation("openbmc_rfr_Administrator"));
967 EXPECT_NO_THROW(
968 checkAndThrowForDisallowedGroupCreation("openbmc_rfr_Operator"));
969 EXPECT_NO_THROW(
970 checkAndThrowForDisallowedGroupCreation("openbmc_rfr_ReadOnly"));
971 // Base Redfish Privileges
972 EXPECT_NO_THROW(
973 checkAndThrowForDisallowedGroupCreation("openbmc_rfp_Login"));
974 EXPECT_NO_THROW(checkAndThrowForDisallowedGroupCreation(
975 "openbmc_rfp_ConfigureManager"));
976 EXPECT_NO_THROW(
977 checkAndThrowForDisallowedGroupCreation("openbmc_rfp_ConfigureUsers"));
978 EXPECT_NO_THROW(
979 checkAndThrowForDisallowedGroupCreation("openbmc_rfp_ConfigureSelf"));
980 EXPECT_NO_THROW(checkAndThrowForDisallowedGroupCreation(
981 "openbmc_rfp_ConfigureComponents"));
982 // OEM Redfish Roles
983 EXPECT_NO_THROW(
984 checkAndThrowForDisallowedGroupCreation("openbmc_orfr_PowerService"));
985 // OEM Redfish Privileges
986 EXPECT_NO_THROW(
987 checkAndThrowForDisallowedGroupCreation("openbmc_orfp_PowerService"));
988}
989
990TEST_F(UserMgrInTest,
991 CheckAndThrowForDisallowedGroupCreationThrowsIfGroupNameTooLong)
992{
993 std::string groupName(maxSystemGroupNameLength + 1, 'A');
994 EXPECT_THROW(
995 checkAndThrowForDisallowedGroupCreation(groupName),
996 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
997}
998
999TEST_F(
1000 UserMgrInTest,
1001 CheckAndThrowForDisallowedGroupCreationThrowsIfGroupNameHasDisallowedCharacters)
1002{
Nan Zhouda401fe2022-10-25 00:07:18 +00001003 EXPECT_THROW(
1004 checkAndThrowForDisallowedGroupCreation("openbmc_rfp_?owerService"),
1005 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1006 EXPECT_THROW(
1007 checkAndThrowForDisallowedGroupCreation("openbmc_rfp_-owerService"),
1008 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1009}
1010
1011TEST_F(
1012 UserMgrInTest,
1013 CheckAndThrowForDisallowedGroupCreationThrowsIfGroupNameHasDisallowedPrefix)
1014{
Nan Zhouda401fe2022-10-25 00:07:18 +00001015 EXPECT_THROW(
1016 checkAndThrowForDisallowedGroupCreation("google_rfp_"),
1017 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1018 EXPECT_THROW(
1019 checkAndThrowForDisallowedGroupCreation("com_rfp_"),
1020 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1021}
1022
1023TEST_F(UserMgrInTest, CheckAndThrowForMaxGroupCountOnSuccess)
1024{
Ninad Palsule601d3db2023-03-09 10:27:37 -06001025 constexpr size_t predefGroupCount = 5;
1026
1027 EXPECT_THAT(allGroups().size(), predefGroupCount);
1028 for (size_t i = 0; i < maxSystemGroupCount - predefGroupCount; ++i)
Nan Zhouda401fe2022-10-25 00:07:18 +00001029 {
1030 std::string groupName = "openbmc_rfr_role";
1031 groupName += std::to_string(i);
1032 EXPECT_NO_THROW(createGroup(groupName));
1033 }
1034 EXPECT_THROW(
1035 createGroup("openbmc_rfr_AnotherRole"),
1036 sdbusplus::xyz::openbmc_project::User::Common::Error::NoResource);
Ninad Palsule601d3db2023-03-09 10:27:37 -06001037 for (size_t i = 0; i < maxSystemGroupCount - predefGroupCount; ++i)
Nan Zhouda401fe2022-10-25 00:07:18 +00001038 {
1039 std::string groupName = "openbmc_rfr_role";
1040 groupName += std::to_string(i);
1041 EXPECT_NO_THROW(deleteGroup(groupName));
1042 }
1043}
1044
1045TEST_F(UserMgrInTest, CheckAndThrowForGroupExist)
1046{
1047 std::string groupName = "openbmc_rfr_role";
1048 EXPECT_NO_THROW(createGroup(groupName));
1049 EXPECT_THROW(
1050 createGroup(groupName),
1051 sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1052 EXPECT_NO_THROW(deleteGroup(groupName));
1053}
1054
1055TEST_F(UserMgrInTest, ByDefaultAllGroupsArePredefinedGroups)
1056{
1057 EXPECT_THAT(allGroups(),
Ninad Palsule601d3db2023-03-09 10:27:37 -06001058 testing::UnorderedElementsAre("web", "redfish", "ipmi", "ssh",
1059 "hostconsole"));
1060}
1061
1062TEST_F(UserMgrInTest, AddGroupThrowsIfPreDefinedGroupAdd)
1063{
1064 EXPECT_THROW(
1065 createGroup("ipmi"),
1066 sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1067 EXPECT_THROW(
1068 createGroup("web"),
1069 sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1070 EXPECT_THROW(
1071 createGroup("redfish"),
1072 sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1073 EXPECT_THROW(
1074 createGroup("ssh"),
1075 sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1076 EXPECT_THROW(
1077 createGroup("hostconsole"),
1078 sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
Nan Zhouda401fe2022-10-25 00:07:18 +00001079}
1080
1081TEST_F(UserMgrInTest, DeleteGroupThrowsIfGroupIsNotAllowedToChange)
1082{
1083 EXPECT_THROW(
1084 deleteGroup("ipmi"),
1085 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1086 EXPECT_THROW(
1087 deleteGroup("web"),
1088 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1089 EXPECT_THROW(
1090 deleteGroup("redfish"),
1091 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1092 EXPECT_THROW(
1093 deleteGroup("ssh"),
1094 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
Ninad Palsule601d3db2023-03-09 10:27:37 -06001095 EXPECT_THROW(
1096 deleteGroup("hostconsole"),
1097 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
Nan Zhouda401fe2022-10-25 00:07:18 +00001098}
1099
1100TEST_F(UserMgrInTest,
1101 CreateGroupThrowsInternalFailureWhenExecuteGroupCreateFails)
1102{
1103 EXPECT_CALL(*this, executeGroupCreation)
1104 .WillOnce(testing::Throw(
1105 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
1106 EXPECT_THROW(
1107 createGroup("openbmc_rfr_role1"),
1108 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
1109}
1110
1111TEST_F(UserMgrInTest,
1112 DeleteGroupThrowsInternalFailureWhenExecuteGroupDeleteFails)
1113{
1114 std::string groupName = "openbmc_rfr_role1";
1115 EXPECT_NO_THROW(UserMgr::createGroup(groupName));
1116 EXPECT_CALL(*this, executeGroupDeletion(testing::StrEq(groupName)))
1117 .WillOnce(testing::Throw(
1118 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()))
1119 .WillOnce(testing::DoDefault());
1120
1121 EXPECT_THROW(
1122 deleteGroup(groupName),
1123 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
1124 EXPECT_NO_THROW(UserMgr::deleteGroup(groupName));
1125}
1126
1127TEST_F(UserMgrInTest, CheckAndThrowForGroupNotExist)
1128{
1129 EXPECT_THROW(deleteGroup("whatever"),
1130 sdbusplus::xyz::openbmc_project::User::Common::Error::
1131 GroupNameDoesNotExist);
1132}
1133
1134TEST(ReadAllGroupsOnSystemTest, OnlyReturnsPredefinedGroups)
1135{
1136 EXPECT_THAT(UserMgr::readAllGroupsOnSystem(),
Ninad Palsule601d3db2023-03-09 10:27:37 -06001137 testing::UnorderedElementsAre("web", "redfish", "ipmi", "ssh",
1138 "hostconsole"));
Nan Zhouda401fe2022-10-25 00:07:18 +00001139}
1140
raviteja-b8cc44052019-02-27 23:29:36 -06001141} // namespace user
1142} // namespace phosphor