blob: f07b00c1e311b724d7a80fcf26d070df7cc84865 [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);
Denis Zlobine8edab52023-09-06 12:26:45 +000047 if (enabled)
48 {
49 ON_CALL(mockManager, isUserEnabled)
50 .WillByDefault(testing::Return(true));
51 }
52 else
53 {
54 ON_CALL(mockManager, isUserEnabled)
55 .WillByDefault(testing::Return(false));
56 }
raviteja-b8cc44052019-02-27 23:29:36 -060057 mockManager.usersList.emplace(
Nan Zhou78d85042022-08-29 17:50:22 +000058 userName, std::make_unique<phosphor::user::Users>(
raviteja-b8cc44052019-02-27 23:29:36 -060059 mockManager.bus, userObj.c_str(), groupNames, priv,
Nan Zhou78d85042022-08-29 17:50:22 +000060 enabled, mockManager));
raviteja-b8cc44052019-02-27 23:29:36 -060061 }
62
63 DbusUserObj createPrivilegeMapperDbusObject(void)
64 {
65 DbusUserObj object;
66 DbusUserObjValue objValue;
Ravi Teja5fe724a2019-05-07 05:14:42 -050067
Nan Zhou78d85042022-08-29 17:50:22 +000068 DbusUserObjPath objPath("/xyz/openbmc_project/user/ldap/openldap");
Ravi Teja5fe724a2019-05-07 05:14:42 -050069 DbusUserPropVariant enabled(true);
70 DbusUserObjProperties property = {std::make_pair("Enabled", enabled)};
71 std::string intf = "xyz.openbmc_project.Object.Enable";
72 objValue.emplace(intf, property);
Nan Zhou78d85042022-08-29 17:50:22 +000073 object.emplace(objPath, objValue);
Ravi Teja5fe724a2019-05-07 05:14:42 -050074
Nan Zhou78d85042022-08-29 17:50:22 +000075 DbusUserObjPath objectPath(
Ravi Teja5fe724a2019-05-07 05:14:42 -050076 "/xyz/openbmc_project/user/ldap/openldap/role_map/1");
77 std::string group = "ldapGroup";
78 std::string priv = "priv-admin";
raviteja-b8cc44052019-02-27 23:29:36 -060079 DbusUserObjProperties properties = {std::make_pair("GroupName", group),
80 std::make_pair("Privilege", priv)};
81 std::string interface = "xyz.openbmc_project.User.PrivilegeMapperEntry";
82
83 objValue.emplace(interface, properties);
Nan Zhou78d85042022-08-29 17:50:22 +000084 object.emplace(objectPath, objValue);
raviteja-b8cc44052019-02-27 23:29:36 -060085
86 return object;
87 }
Ravi Teja5fe724a2019-05-07 05:14:42 -050088
89 DbusUserObj createLdapConfigObjectWithoutPrivilegeMapper(void)
90 {
91 DbusUserObj object;
92 DbusUserObjValue objValue;
93
Nan Zhou78d85042022-08-29 17:50:22 +000094 DbusUserObjPath objPath("/xyz/openbmc_project/user/ldap/openldap");
Ravi Teja5fe724a2019-05-07 05:14:42 -050095 DbusUserPropVariant enabled(true);
96 DbusUserObjProperties property = {std::make_pair("Enabled", enabled)};
97 std::string intf = "xyz.openbmc_project.Object.Enable";
98 objValue.emplace(intf, property);
Nan Zhou78d85042022-08-29 17:50:22 +000099 object.emplace(objPath, objValue);
Ravi Teja5fe724a2019-05-07 05:14:42 -0500100 return object;
101 }
raviteja-b8cc44052019-02-27 23:29:36 -0600102};
103
104TEST_F(TestUserMgr, ldapEntryDoesNotExist)
105{
106 std::string userName = "user";
107 UserInfoMap userInfo;
108
Alexander Filippov75626582022-02-09 18:42:37 +0300109 EXPECT_CALL(mockManager, getPrimaryGroup(userName))
110 .WillRepeatedly(Throw(UserNameDoesNotExist()));
111 EXPECT_THROW(userInfo = mockManager.getUserInfo(userName),
112 UserNameDoesNotExist);
raviteja-b8cc44052019-02-27 23:29:36 -0600113}
114
115TEST_F(TestUserMgr, localUser)
116{
117 UserInfoMap userInfo;
118 std::string userName = "testUser";
119 std::string privilege = "priv-admin";
120 std::vector<std::string> groups{"testGroup"};
121 // Create local user
122 createLocalUser(userName, groups, privilege, true);
123 EXPECT_CALL(mockManager, userLockedForFailedAttempt(userName)).Times(1);
124 userInfo = mockManager.getUserInfo(userName);
125
126 EXPECT_EQ(privilege, std::get<std::string>(userInfo["UserPrivilege"]));
127 EXPECT_EQ(groups,
128 std::get<std::vector<std::string>>(userInfo["UserGroups"]));
129 EXPECT_EQ(true, std::get<bool>(userInfo["UserEnabled"]));
130 EXPECT_EQ(false, std::get<bool>(userInfo["UserLockedForFailedAttempt"]));
Joseph Reynolds3ab6cc22020-03-03 14:09:03 -0600131 EXPECT_EQ(false, std::get<bool>(userInfo["UserPasswordExpired"]));
raviteja-b8cc44052019-02-27 23:29:36 -0600132 EXPECT_EQ(false, std::get<bool>(userInfo["RemoteUser"]));
133}
134
135TEST_F(TestUserMgr, ldapUserWithPrivMapper)
136{
137 UserInfoMap userInfo;
138 std::string userName = "ldapUser";
139 std::string ldapGroup = "ldapGroup";
Alexander Filippov75626582022-02-09 18:42:37 +0300140 gid_t primaryGid = 1000;
raviteja-b8cc44052019-02-27 23:29:36 -0600141
Alexander Filippov75626582022-02-09 18:42:37 +0300142 EXPECT_CALL(mockManager, getPrimaryGroup(userName))
143 .WillRepeatedly(Return(primaryGid));
raviteja-b8cc44052019-02-27 23:29:36 -0600144 // Create privilege mapper dbus object
145 DbusUserObj object = createPrivilegeMapperDbusObject();
146 EXPECT_CALL(mockManager, getPrivilegeMapperObject())
147 .WillRepeatedly(Return(object));
Alexander Filippov75626582022-02-09 18:42:37 +0300148 EXPECT_CALL(mockManager, isGroupMember(userName, primaryGid, ldapGroup))
149 .WillRepeatedly(Return(true));
raviteja-b8cc44052019-02-27 23:29:36 -0600150 userInfo = mockManager.getUserInfo(userName);
151 EXPECT_EQ(true, std::get<bool>(userInfo["RemoteUser"]));
152 EXPECT_EQ("priv-admin", std::get<std::string>(userInfo["UserPrivilege"]));
153}
154
155TEST_F(TestUserMgr, ldapUserWithoutPrivMapper)
156{
Alexander Filippov75626582022-02-09 18:42:37 +0300157 using ::testing::_;
158
raviteja-b8cc44052019-02-27 23:29:36 -0600159 UserInfoMap userInfo;
160 std::string userName = "ldapUser";
161 std::string ldapGroup = "ldapGroup";
Alexander Filippov75626582022-02-09 18:42:37 +0300162 gid_t primaryGid = 1000;
raviteja-b8cc44052019-02-27 23:29:36 -0600163
Alexander Filippov75626582022-02-09 18:42:37 +0300164 EXPECT_CALL(mockManager, getPrimaryGroup(userName))
165 .WillRepeatedly(Return(primaryGid));
Ravi Teja5fe724a2019-05-07 05:14:42 -0500166 // Create LDAP config object without privilege mapper
167 DbusUserObj object = createLdapConfigObjectWithoutPrivilegeMapper();
raviteja-b8cc44052019-02-27 23:29:36 -0600168 EXPECT_CALL(mockManager, getPrivilegeMapperObject())
169 .WillRepeatedly(Return(object));
Alexander Filippov75626582022-02-09 18:42:37 +0300170 EXPECT_CALL(mockManager, isGroupMember(_, _, _)).Times(0);
raviteja-b8cc44052019-02-27 23:29:36 -0600171 userInfo = mockManager.getUserInfo(userName);
172 EXPECT_EQ(true, std::get<bool>(userInfo["RemoteUser"]));
Jiaqing Zhao56862062022-05-31 19:16:09 +0800173 EXPECT_EQ("priv-user", std::get<std::string>(userInfo["UserPrivilege"]));
raviteja-b8cc44052019-02-27 23:29:36 -0600174}
Nan Zhoue47c09d2022-10-25 00:06:41 +0000175
176TEST(GetCSVFromVector, EmptyVectorReturnsEmptyString)
177{
178 EXPECT_EQ(getCSVFromVector({}), "");
179}
180
181TEST(GetCSVFromVector, ElementsAreJoinedByComma)
182{
183 EXPECT_EQ(getCSVFromVector(std::vector<std::string>{"123"}), "123");
184 EXPECT_EQ(getCSVFromVector(std::vector<std::string>{"123", "456"}),
185 "123,456");
186}
187
Nan Zhou332fb9d2022-10-25 00:07:03 +0000188TEST(RemoveStringFromCSV, WithoutDeleteStringReturnsFalse)
189{
190 std::string expected = "whatever,https";
191 std::string str = expected;
192 EXPECT_FALSE(removeStringFromCSV(str, "ssh"));
193 EXPECT_EQ(str, expected);
194
195 std::string empty;
196 EXPECT_FALSE(removeStringFromCSV(empty, "ssh"));
197}
198
199TEST(RemoveStringFromCSV, WithDeleteStringReturnsTrue)
200{
201 std::string expected = "whatever";
202 std::string str = "whatever,https";
203 EXPECT_TRUE(removeStringFromCSV(str, "https"));
204 EXPECT_EQ(str, expected);
205
206 str = "https";
207 EXPECT_TRUE(removeStringFromCSV(str, "https"));
208 EXPECT_EQ(str, "");
209}
210
Nan Zhoue48085d2022-10-25 00:07:04 +0000211namespace
212{
213inline constexpr const char* objectRootInTest = "/xyz/openbmc_project/user";
214
Jason M. Bills2d042d12023-03-28 15:32:45 -0700215// Fake configs; referenced configs on real BMC
Jason M. Bills2d042d12023-03-28 15:32:45 -0700216inline constexpr const char* rawFailLockConfig = R"(
217deny=2
218unlock_time=3
219)";
Jason M. Bills3b280ec2023-08-15 16:15:48 -0700220inline constexpr const char* rawPWHistoryConfig = R"(
221enforce_for_root
222remember=0
223)";
Jason M. Bills2d042d12023-03-28 15:32:45 -0700224inline constexpr const char* rawPWQualityConfig = R"(
225enforce_for_root
226minlen=8
227difok=0
228lcredit=0
229ocredit=0
230dcredit=0
231ucredit=0
232)";
Nan Zhoue48085d2022-10-25 00:07:04 +0000233} // namespace
234
235void dumpStringToFile(const std::string& str, const std::string& filePath)
236{
237 std::ofstream outputFileStream;
238
Patrick Williams16c2b682024-08-16 15:20:56 -0400239 outputFileStream.exceptions(
240 std::ofstream::failbit | std::ofstream::badbit | std::ofstream::eofbit);
Nan Zhoue48085d2022-10-25 00:07:04 +0000241
242 outputFileStream.open(filePath, std::ios::out);
243 outputFileStream << str << "\n" << std::flush;
244 outputFileStream.close();
245}
246
247void removeFile(const std::string& filePath)
248{
249 std::filesystem::remove(filePath);
250}
251
252class UserMgrInTest : public testing::Test, public UserMgr
253{
254 public:
255 UserMgrInTest() : UserMgr(busInTest, objectRootInTest)
256 {
Jason M. Bills2d042d12023-03-28 15:32:45 -0700257 tempFaillockConfigFile = "/tmp/test-data-XXXXXX";
258 mktemp(tempFaillockConfigFile.data());
259 EXPECT_NO_THROW(
260 dumpStringToFile(rawFailLockConfig, tempFaillockConfigFile));
Jason M. Bills3b280ec2023-08-15 16:15:48 -0700261 tempPWHistoryConfigFile = "/tmp/test-data-XXXXXX";
262 mktemp(tempPWHistoryConfigFile.data());
263 EXPECT_NO_THROW(
264 dumpStringToFile(rawPWHistoryConfig, tempPWHistoryConfigFile));
Jason M. Bills2d042d12023-03-28 15:32:45 -0700265 tempPWQualityConfigFile = "/tmp/test-data-XXXXXX";
266 mktemp(tempPWQualityConfigFile.data());
267 EXPECT_NO_THROW(
268 dumpStringToFile(rawPWQualityConfig, tempPWQualityConfigFile));
Nan Zhoue48085d2022-10-25 00:07:04 +0000269 // Set config files to test files
Jason M. Bills2d042d12023-03-28 15:32:45 -0700270 faillockConfigFile = tempFaillockConfigFile;
Jason M. Bills3b280ec2023-08-15 16:15:48 -0700271 pwHistoryConfigFile = tempPWHistoryConfigFile;
Jason M. Bills2d042d12023-03-28 15:32:45 -0700272 pwQualityConfigFile = tempPWQualityConfigFile;
Nan Zhou49c81362022-10-25 00:07:08 +0000273
Denis Zlobine8edab52023-09-06 12:26:45 +0000274 ON_CALL(*this, executeUserAdd(testing::_, testing::_, testing::_,
275 testing::Eq(true)))
Patrick Williamscb20ea82023-10-20 11:19:13 -0500276 .WillByDefault([this]() {
Patrick Williams16c2b682024-08-16 15:20:56 -0400277 ON_CALL(*this, isUserEnabled)
278 .WillByDefault(testing::Return(true));
279 testing::Return();
280 });
Denis Zlobine8edab52023-09-06 12:26:45 +0000281
282 ON_CALL(*this, executeUserAdd(testing::_, testing::_, testing::_,
283 testing::Eq(false)))
Patrick Williamscb20ea82023-10-20 11:19:13 -0500284 .WillByDefault([this]() {
Patrick Williams16c2b682024-08-16 15:20:56 -0400285 ON_CALL(*this, isUserEnabled)
286 .WillByDefault(testing::Return(false));
287 testing::Return();
288 });
Nan Zhou49c81362022-10-25 00:07:08 +0000289
290 ON_CALL(*this, executeUserDelete).WillByDefault(testing::Return());
291
Jayanth Othayothac921a52023-07-21 03:48:55 -0500292 ON_CALL(*this, executeUserClearFailRecords)
293 .WillByDefault(testing::Return());
294
Nan Zhou49c81362022-10-25 00:07:08 +0000295 ON_CALL(*this, getIpmiUsersCount).WillByDefault(testing::Return(0));
Nan Zhouf25443e2022-10-25 00:07:11 +0000296
297 ON_CALL(*this, executeUserRename).WillByDefault(testing::Return());
Nan Zhoufef63032022-10-25 00:07:12 +0000298
299 ON_CALL(*this, executeUserModify(testing::_, testing::_, testing::_))
300 .WillByDefault(testing::Return());
Nan Zhou6b6f2d82022-10-25 00:07:17 +0000301
Denis Zlobine8edab52023-09-06 12:26:45 +0000302 ON_CALL(*this,
303 executeUserModifyUserEnable(testing::_, testing::Eq(true)))
Patrick Williamscb20ea82023-10-20 11:19:13 -0500304 .WillByDefault([this]() {
Patrick Williams16c2b682024-08-16 15:20:56 -0400305 ON_CALL(*this, isUserEnabled)
306 .WillByDefault(testing::Return(true));
307 testing::Return();
308 });
Denis Zlobine8edab52023-09-06 12:26:45 +0000309
310 ON_CALL(*this,
311 executeUserModifyUserEnable(testing::_, testing::Eq(false)))
Patrick Williamscb20ea82023-10-20 11:19:13 -0500312 .WillByDefault([this]() {
Patrick Williams16c2b682024-08-16 15:20:56 -0400313 ON_CALL(*this, isUserEnabled)
314 .WillByDefault(testing::Return(false));
315 testing::Return();
316 });
Nan Zhouda401fe2022-10-25 00:07:18 +0000317
318 ON_CALL(*this, executeGroupCreation(testing::_))
319 .WillByDefault(testing::Return());
320
321 ON_CALL(*this, executeGroupDeletion(testing::_))
322 .WillByDefault(testing::Return());
323
324 ON_CALL(*this, executeGroupCreation).WillByDefault(testing::Return());
325
326 ON_CALL(*this, executeGroupDeletion).WillByDefault(testing::Return());
Nan Zhoue48085d2022-10-25 00:07:04 +0000327 }
328
329 ~UserMgrInTest() override
330 {
Jason M. Bills2d042d12023-03-28 15:32:45 -0700331 EXPECT_NO_THROW(removeFile(tempFaillockConfigFile));
Jason M. Bills3b280ec2023-08-15 16:15:48 -0700332 EXPECT_NO_THROW(removeFile(tempPWHistoryConfigFile));
Jason M. Bills2d042d12023-03-28 15:32:45 -0700333 EXPECT_NO_THROW(removeFile(tempPWQualityConfigFile));
Nan Zhoue48085d2022-10-25 00:07:04 +0000334 }
335
Nan Zhou49c81362022-10-25 00:07:08 +0000336 MOCK_METHOD(void, executeUserAdd, (const char*, const char*, bool, bool),
337 (override));
338
339 MOCK_METHOD(void, executeUserDelete, (const char*), (override));
340
Jayanth Othayothac921a52023-07-21 03:48:55 -0500341 MOCK_METHOD(void, executeUserClearFailRecords, (const char*), (override));
342
Nan Zhou49c81362022-10-25 00:07:08 +0000343 MOCK_METHOD(size_t, getIpmiUsersCount, (), (override));
344
Nan Zhouf25443e2022-10-25 00:07:11 +0000345 MOCK_METHOD(void, executeUserRename, (const char*, const char*),
346 (override));
347
Nan Zhoufef63032022-10-25 00:07:12 +0000348 MOCK_METHOD(void, executeUserModify, (const char*, const char*, bool),
349 (override));
350
Nan Zhou6b6f2d82022-10-25 00:07:17 +0000351 MOCK_METHOD(void, executeUserModifyUserEnable, (const char*, bool),
352 (override));
353
Nan Zhoua2953032022-11-11 21:50:32 +0000354 MOCK_METHOD(std::vector<std::string>, getFailedAttempt, (const char*),
355 (override));
356
Nan Zhouda401fe2022-10-25 00:07:18 +0000357 MOCK_METHOD(void, executeGroupCreation, (const char*), (override));
358
359 MOCK_METHOD(void, executeGroupDeletion, (const char*), (override));
360
Denis Zlobine8edab52023-09-06 12:26:45 +0000361 MOCK_METHOD(bool, isUserEnabled, (const std::string& userName), (override));
362
Nan Zhoufef63032022-10-25 00:07:12 +0000363 protected:
Nan Zhoue48085d2022-10-25 00:07:04 +0000364 static sdbusplus::bus_t busInTest;
Jason M. Bills2d042d12023-03-28 15:32:45 -0700365 std::string tempFaillockConfigFile;
Jason M. Bills3b280ec2023-08-15 16:15:48 -0700366 std::string tempPWHistoryConfigFile;
Jason M. Bills2d042d12023-03-28 15:32:45 -0700367 std::string tempPWQualityConfigFile;
Nan Zhoue48085d2022-10-25 00:07:04 +0000368};
369
370sdbusplus::bus_t UserMgrInTest::busInTest = sdbusplus::bus::new_default();
371
Jason M. Bills2d042d12023-03-28 15:32:45 -0700372TEST_F(UserMgrInTest, GetPamModuleConfValueOnSuccess)
373{
374 std::string minlen;
375 EXPECT_EQ(getPamModuleConfValue(tempPWQualityConfigFile, "minlen", minlen),
376 0);
377 EXPECT_EQ(minlen, "8");
378 std::string deny;
379 EXPECT_EQ(getPamModuleConfValue(tempFaillockConfigFile, "deny", deny), 0);
380 EXPECT_EQ(deny, "2");
Jason M. Bills2d042d12023-03-28 15:32:45 -0700381 std::string remember;
Jason M. Bills3b280ec2023-08-15 16:15:48 -0700382 EXPECT_EQ(
383 getPamModuleConfValue(tempPWHistoryConfigFile, "remember", remember),
384 0);
385 EXPECT_EQ(remember, "0");
Jason M. Bills2d042d12023-03-28 15:32:45 -0700386}
387
388TEST_F(UserMgrInTest, SetPamModuleConfValueOnSuccess)
389{
390 EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
391 0);
392 std::string minlen;
393 EXPECT_EQ(getPamModuleConfValue(tempPWQualityConfigFile, "minlen", minlen),
394 0);
395 EXPECT_EQ(minlen, "16");
396
397 EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), 0);
398 std::string deny;
399 EXPECT_EQ(getPamModuleConfValue(tempFaillockConfigFile, "deny", deny), 0);
400 EXPECT_EQ(deny, "3");
Nan Zhoue48085d2022-10-25 00:07:04 +0000401
Jason M. Bills3b280ec2023-08-15 16:15:48 -0700402 EXPECT_EQ(setPamModuleConfValue(tempPWHistoryConfigFile, "remember", "1"),
403 0);
404 std::string remember;
405 EXPECT_EQ(
406 getPamModuleConfValue(tempPWHistoryConfigFile, "remember", remember),
407 0);
408 EXPECT_EQ(remember, "1");
Jason M. Bills17b88272023-05-22 14:24:02 -0700409}
410
411TEST_F(UserMgrInTest, SetPamModuleConfValueTempFileOnSuccess)
412{
413 EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
414 0);
415
416 std::string tmpFile = tempPWQualityConfigFile + "_tmp";
417 EXPECT_FALSE(std::filesystem::exists(tmpFile));
418
419 EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), 0);
420
421 tmpFile = tempFaillockConfigFile + "_tmp";
422 EXPECT_FALSE(std::filesystem::exists(tmpFile));
Jason M. Bills17b88272023-05-22 14:24:02 -0700423
Jason M. Bills3b280ec2023-08-15 16:15:48 -0700424 EXPECT_EQ(setPamModuleConfValue(tempPWHistoryConfigFile, "remember", "1"),
425 0);
Nan Zhoue48085d2022-10-25 00:07:04 +0000426
Jason M. Bills3b280ec2023-08-15 16:15:48 -0700427 tmpFile = tempPWHistoryConfigFile + "_tmp";
428 EXPECT_FALSE(std::filesystem::exists(tmpFile));
Jason M. Bills2d042d12023-03-28 15:32:45 -0700429}
430
431TEST_F(UserMgrInTest, GetPamModuleConfValueOnFailure)
432{
433 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWQualityConfigFile));
434 std::string minlen;
435 EXPECT_EQ(getPamModuleConfValue(tempPWQualityConfigFile, "minlen", minlen),
436 -1);
437
438 EXPECT_NO_THROW(removeFile(tempPWQualityConfigFile));
439 EXPECT_EQ(getPamModuleConfValue(tempPWQualityConfigFile, "minlen", minlen),
440 -1);
441
442 EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
443 std::string deny;
444 EXPECT_EQ(getPamModuleConfValue(tempFaillockConfigFile, "deny", deny), -1);
445
446 EXPECT_NO_THROW(removeFile(tempFaillockConfigFile));
447 EXPECT_EQ(getPamModuleConfValue(tempFaillockConfigFile, "deny", deny), -1);
Nan Zhoue48085d2022-10-25 00:07:04 +0000448
Jason M. Bills3b280ec2023-08-15 16:15:48 -0700449 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWHistoryConfigFile));
450 std::string remember;
451 EXPECT_EQ(
452 getPamModuleConfValue(tempPWHistoryConfigFile, "remember", remember),
453 -1);
Nan Zhoue48085d2022-10-25 00:07:04 +0000454
Jason M. Bills3b280ec2023-08-15 16:15:48 -0700455 EXPECT_NO_THROW(removeFile(tempPWHistoryConfigFile));
456 EXPECT_EQ(
457 getPamModuleConfValue(tempPWHistoryConfigFile, "remember", remember),
458 -1);
Jason M. Bills2d042d12023-03-28 15:32:45 -0700459}
460
461TEST_F(UserMgrInTest, SetPamModuleConfValueOnFailure)
462{
463 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWQualityConfigFile));
464 EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
465 -1);
466
467 EXPECT_NO_THROW(removeFile(tempPWQualityConfigFile));
468 EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
469 -1);
470
471 EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
472 EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), -1);
473
474 EXPECT_NO_THROW(removeFile(tempFaillockConfigFile));
475 EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), -1);
Nan Zhoue48085d2022-10-25 00:07:04 +0000476
Jason M. Bills3b280ec2023-08-15 16:15:48 -0700477 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWHistoryConfigFile));
478 EXPECT_EQ(setPamModuleConfValue(tempPWHistoryConfigFile, "remember", "1"),
479 -1);
Jason M. Bills17b88272023-05-22 14:24:02 -0700480
Jason M. Bills3b280ec2023-08-15 16:15:48 -0700481 EXPECT_NO_THROW(removeFile(tempPWHistoryConfigFile));
482 EXPECT_EQ(setPamModuleConfValue(tempPWHistoryConfigFile, "remember", "1"),
483 -1);
Jason M. Bills17b88272023-05-22 14:24:02 -0700484}
485
486TEST_F(UserMgrInTest, SetPamModuleConfValueTempFileOnFailure)
487{
488 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWQualityConfigFile));
489 EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
490 -1);
491
492 std::string tmpFile = tempPWQualityConfigFile + "_tmp";
493 EXPECT_FALSE(std::filesystem::exists(tmpFile));
494
495 EXPECT_NO_THROW(removeFile(tempPWQualityConfigFile));
496 EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
497 -1);
498
499 EXPECT_FALSE(std::filesystem::exists(tmpFile));
500
501 EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
502 EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), -1);
503
504 tmpFile = tempFaillockConfigFile + "_tmp";
505 EXPECT_FALSE(std::filesystem::exists(tmpFile));
506
507 EXPECT_NO_THROW(removeFile(tempFaillockConfigFile));
508 EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), -1);
509
510 EXPECT_FALSE(std::filesystem::exists(tmpFile));
Jason M. Bills3b280ec2023-08-15 16:15:48 -0700511
512 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWHistoryConfigFile));
513 EXPECT_EQ(setPamModuleConfValue(tempPWHistoryConfigFile, "remember", "1"),
514 -1);
515
516 tmpFile = tempPWHistoryConfigFile + "_tmp";
517 EXPECT_FALSE(std::filesystem::exists(tmpFile));
518
519 EXPECT_NO_THROW(removeFile(tempPWHistoryConfigFile));
520 EXPECT_EQ(setPamModuleConfValue(tempPWHistoryConfigFile, "remember", "1"),
521 -1);
522
523 EXPECT_FALSE(std::filesystem::exists(tmpFile));
Jason M. Bills17b88272023-05-22 14:24:02 -0700524}
525
Nan Zhou8a11d992022-10-25 00:07:06 +0000526TEST_F(UserMgrInTest, IsUserExistEmptyInputThrowsError)
527{
528 EXPECT_THROW(
529 isUserExist(""),
530 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
531}
532
533TEST_F(UserMgrInTest, ThrowForUserDoesNotExistThrowsError)
534{
535 EXPECT_THROW(throwForUserDoesNotExist("whatever"),
536 sdbusplus::xyz::openbmc_project::User::Common::Error::
537 UserNameDoesNotExist);
538}
539
540TEST_F(UserMgrInTest, ThrowForUserExistsThrowsError)
541{
542 EXPECT_THROW(
543 throwForUserExists("root"),
544 sdbusplus::xyz::openbmc_project::User::Common::Error::UserNameExists);
545}
546
Nan Zhou40e44972022-10-25 00:07:07 +0000547TEST_F(
548 UserMgrInTest,
549 ThrowForUserNameConstraintsExceedIpmiMaxUserNameLenThrowsUserNameGroupFail)
550{
551 std::string strWith17Chars(17, 'A');
552 EXPECT_THROW(throwForUserNameConstraints(strWith17Chars, {"ipmi"}),
553 sdbusplus::xyz::openbmc_project::User::Common::Error::
554 UserNameGroupFail);
555}
556
557TEST_F(
558 UserMgrInTest,
559 ThrowForUserNameConstraintsExceedSystemMaxUserNameLenThrowsInvalidArgument)
560{
561 std::string strWith31Chars(31, 'A');
562 EXPECT_THROW(
563 throwForUserNameConstraints(strWith31Chars, {}),
564 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
565}
566
567TEST_F(UserMgrInTest,
568 ThrowForUserNameConstraintsRegexMismatchThrowsInvalidArgument)
569{
570 std::string startWithNumber = "0ABC";
nichanghao.nchd9adc732024-01-17 20:24:17 +0800571 std::string startWithDisallowedCharacter = "[test";
Nan Zhou40e44972022-10-25 00:07:07 +0000572 EXPECT_THROW(
573 throwForUserNameConstraints(startWithNumber, {"ipmi"}),
574 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
nichanghao.nchd9adc732024-01-17 20:24:17 +0800575 EXPECT_THROW(
576 throwForUserNameConstraints(startWithDisallowedCharacter, {"ipmi"}),
577 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
Nan Zhou40e44972022-10-25 00:07:07 +0000578}
579
Nan Zhou49c81362022-10-25 00:07:08 +0000580TEST_F(UserMgrInTest, UserAddNotRootFailedWithInternalFailure)
581{
582 EXPECT_THROW(
583 UserMgr::executeUserAdd("user0", "ipmi,ssh", true, true),
584 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
585}
586
587TEST_F(UserMgrInTest, UserDeleteNotRootFailedWithInternalFailure)
588{
589 EXPECT_THROW(
590 UserMgr::executeUserDelete("user0"),
591 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
592}
593
594TEST_F(UserMgrInTest,
595 ThrowForMaxGrpUserCountThrowsNoResourceWhenIpmiUserExceedLimit)
596{
597 EXPECT_CALL(*this, getIpmiUsersCount()).WillOnce(Return(ipmiMaxUsers));
598 EXPECT_THROW(
599 throwForMaxGrpUserCount({"ipmi"}),
600 sdbusplus::xyz::openbmc_project::User::Common::Error::NoResource);
601}
602
603TEST_F(UserMgrInTest, CreateUserThrowsInternalFailureWhenExecuteUserAddFails)
604{
605 EXPECT_CALL(*this, executeUserAdd)
606 .WillOnce(testing::Throw(
607 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
608 EXPECT_THROW(
609 createUser("whatever", {"redfish"}, "", true),
610 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
611}
612
613TEST_F(UserMgrInTest, DeleteUserThrowsInternalFailureWhenExecuteUserDeleteFails)
614{
615 std::string username = "user";
616 EXPECT_NO_THROW(
617 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
618 EXPECT_CALL(*this, executeUserDelete(testing::StrEq(username)))
619 .WillOnce(testing::Throw(
620 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()))
621 .WillOnce(testing::DoDefault());
622
623 EXPECT_THROW(
624 deleteUser(username),
625 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
626 EXPECT_NO_THROW(UserMgr::deleteUser(username));
627}
628
Jayanth Othayothac921a52023-07-21 03:48:55 -0500629TEST_F(UserMgrInTest,
630 DeleteUserThrowsInternalFailureWhenExecuteUserClearFailRecords)
631{
632 const char* username = "user";
633 EXPECT_NO_THROW(
634 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
635 EXPECT_CALL(*this, executeUserClearFailRecords(testing::StrEq(username)))
636 .WillOnce(testing::Throw(
637 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()))
638 .WillOnce(testing::DoDefault());
639
640 EXPECT_THROW(
641 deleteUser(username),
642 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
643 EXPECT_NO_THROW(UserMgr::deleteUser(username));
644}
645
Nan Zhou589aeb42022-10-25 00:07:09 +0000646TEST_F(UserMgrInTest, ThrowForInvalidPrivilegeThrowsWhenPrivilegeIsInvalid)
647{
648 EXPECT_THROW(
649 throwForInvalidPrivilege("whatever"),
650 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
651}
652
653TEST_F(UserMgrInTest, ThrowForInvalidPrivilegeNoThrowWhenPrivilegeIsValid)
654{
655 EXPECT_NO_THROW(throwForInvalidPrivilege("priv-admin"));
656 EXPECT_NO_THROW(throwForInvalidPrivilege("priv-operator"));
657 EXPECT_NO_THROW(throwForInvalidPrivilege("priv-user"));
Nan Zhou589aeb42022-10-25 00:07:09 +0000658}
659
Nan Zhouecf88762022-10-25 00:07:10 +0000660TEST_F(UserMgrInTest, ThrowForInvalidGroupsThrowsWhenGroupIsInvalid)
661{
662 EXPECT_THROW(
663 throwForInvalidGroups({"whatever"}),
664 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
Ravi Teja4e2c06e2024-04-20 23:18:34 -0500665 EXPECT_THROW(
666 throwForInvalidGroups({"web"}),
667 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
Nan Zhouecf88762022-10-25 00:07:10 +0000668}
669
670TEST_F(UserMgrInTest, ThrowForInvalidGroupsNoThrowWhenGroupIsValid)
671{
672 EXPECT_NO_THROW(throwForInvalidGroups({"ipmi"}));
673 EXPECT_NO_THROW(throwForInvalidGroups({"ssh"}));
674 EXPECT_NO_THROW(throwForInvalidGroups({"redfish"}));
Ninad Palsule601d3db2023-03-09 10:27:37 -0600675 EXPECT_NO_THROW(throwForInvalidGroups({"hostconsole"}));
Nan Zhouecf88762022-10-25 00:07:10 +0000676}
677
Nan Zhouf25443e2022-10-25 00:07:11 +0000678TEST_F(UserMgrInTest, RenameUserOnSuccess)
679{
680 std::string username = "user001";
681 EXPECT_NO_THROW(
682 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
683 std::string newUsername = "user002";
684
685 EXPECT_NO_THROW(UserMgr::renameUser(username, newUsername));
686
687 // old username doesn't exist
688 EXPECT_THROW(getUserInfo(username),
689 sdbusplus::xyz::openbmc_project::User::Common::Error::
690 UserNameDoesNotExist);
691
692 UserInfoMap userInfo = getUserInfo(newUsername);
693 EXPECT_EQ(std::get<Privilege>(userInfo["UserPrivilege"]), "priv-user");
694 EXPECT_THAT(std::get<GroupList>(userInfo["UserGroups"]),
695 testing::UnorderedElementsAre("redfish", "ssh"));
696 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
697
698 EXPECT_NO_THROW(UserMgr::deleteUser(newUsername));
699}
700
701TEST_F(UserMgrInTest, RenameUserThrowsInternalFailureIfExecuteUserModifyFails)
702{
703 std::string username = "user001";
704 EXPECT_NO_THROW(
705 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
706 std::string newUsername = "user002";
707
708 EXPECT_CALL(*this, executeUserRename(testing::StrEq(username),
709 testing::StrEq(newUsername)))
710 .WillOnce(testing::Throw(
711 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
712 EXPECT_THROW(
713 UserMgr::renameUser(username, newUsername),
714 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
715
716 // The original user is unchanged
717 UserInfoMap userInfo = getUserInfo(username);
718 EXPECT_EQ(std::get<Privilege>(userInfo["UserPrivilege"]), "priv-user");
719 EXPECT_THAT(std::get<GroupList>(userInfo["UserGroups"]),
720 testing::UnorderedElementsAre("redfish", "ssh"));
721 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
722
723 EXPECT_NO_THROW(UserMgr::deleteUser(username));
724}
725
726TEST_F(UserMgrInTest, DefaultUserModifyFailedWithInternalFailure)
727{
728 EXPECT_THROW(
729 UserMgr::executeUserRename("user0", "user1"),
730 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
Nan Zhoufef63032022-10-25 00:07:12 +0000731 EXPECT_THROW(
732 UserMgr::executeUserModify("user0", "ssh", true),
733 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
734}
735
736TEST_F(UserMgrInTest, UpdateGroupsAndPrivOnSuccess)
737{
738 std::string username = "user001";
739 EXPECT_NO_THROW(
740 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
741 EXPECT_NO_THROW(
742 updateGroupsAndPriv(username, {"ipmi", "ssh"}, "priv-admin"));
743 UserInfoMap userInfo = getUserInfo(username);
744 EXPECT_EQ(std::get<Privilege>(userInfo["UserPrivilege"]), "priv-admin");
745 EXPECT_THAT(std::get<GroupList>(userInfo["UserGroups"]),
746 testing::UnorderedElementsAre("ipmi", "ssh"));
747 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
748 EXPECT_NO_THROW(UserMgr::deleteUser(username));
749}
750
751TEST_F(UserMgrInTest,
752 UpdateGroupsAndPrivThrowsInternalFailureIfExecuteUserModifyFail)
753{
754 std::string username = "user001";
755 EXPECT_NO_THROW(
756 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
757 EXPECT_CALL(*this, executeUserModify(testing::StrEq(username), testing::_,
758 testing::_))
759 .WillOnce(testing::Throw(
760 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
761 EXPECT_THROW(
762 updateGroupsAndPriv(username, {"ipmi", "ssh"}, "priv-admin"),
763 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
764 EXPECT_NO_THROW(UserMgr::deleteUser(username));
Nan Zhouf25443e2022-10-25 00:07:11 +0000765}
766
Nan Zhou18031012022-11-10 22:24:58 +0000767TEST_F(UserMgrInTest, MinPasswordLengthReturnsIfValueIsTheSame)
768{
769 initializeAccountPolicy();
770 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
771 UserMgr::minPasswordLength(8);
772 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
773}
774
775TEST_F(UserMgrInTest,
776 MinPasswordLengthRejectsTooShortPasswordWithInvalidArgument)
777{
778 initializeAccountPolicy();
779 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
780 EXPECT_THROW(
781 UserMgr::minPasswordLength(minPasswdLength - 1),
782 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
783 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
784}
785
786TEST_F(UserMgrInTest, MinPasswordLengthOnSuccess)
787{
788 initializeAccountPolicy();
789 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
790 UserMgr::minPasswordLength(16);
791 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 16);
792}
793
794TEST_F(UserMgrInTest, MinPasswordLengthOnFailure)
795{
Jason M. Bills2d042d12023-03-28 15:32:45 -0700796 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWQualityConfigFile));
Nan Zhou18031012022-11-10 22:24:58 +0000797 initializeAccountPolicy();
798 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
799 EXPECT_THROW(
800 UserMgr::minPasswordLength(16),
801 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
802 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
803}
804
Nan Zhoua6ce1fa2022-10-25 00:07:14 +0000805TEST_F(UserMgrInTest, RememberOldPasswordTimesReturnsIfValueIsTheSame)
806{
807 initializeAccountPolicy();
808 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 0);
809 UserMgr::rememberOldPasswordTimes(8);
810 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 8);
811 UserMgr::rememberOldPasswordTimes(8);
812 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 8);
813}
814
815TEST_F(UserMgrInTest, RememberOldPasswordTimesOnSuccess)
816{
817 initializeAccountPolicy();
818 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 0);
819 UserMgr::rememberOldPasswordTimes(16);
820 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 16);
821}
822
823TEST_F(UserMgrInTest, RememberOldPasswordTimesOnFailure)
824{
Jason M. Bills3b280ec2023-08-15 16:15:48 -0700825 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWHistoryConfigFile));
Nan Zhoua6ce1fa2022-10-25 00:07:14 +0000826 initializeAccountPolicy();
827 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 0);
828 EXPECT_THROW(
829 UserMgr::rememberOldPasswordTimes(16),
830 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
831 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 0);
832}
833
Nan Zhoucfabe6b2022-10-25 00:07:15 +0000834TEST_F(UserMgrInTest, MaxLoginAttemptBeforeLockoutReturnsIfValueIsTheSame)
835{
836 initializeAccountPolicy();
837 EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 2);
838 UserMgr::maxLoginAttemptBeforeLockout(2);
839 EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 2);
840}
841
842TEST_F(UserMgrInTest, MaxLoginAttemptBeforeLockoutOnSuccess)
843{
844 initializeAccountPolicy();
845 EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 2);
846 UserMgr::maxLoginAttemptBeforeLockout(16);
847 EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 16);
848}
849
850TEST_F(UserMgrInTest, MaxLoginAttemptBeforeLockoutOnFailure)
851{
Nan Zhoucfabe6b2022-10-25 00:07:15 +0000852 initializeAccountPolicy();
Jason M. Bills2d042d12023-03-28 15:32:45 -0700853 EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
Nan Zhoucfabe6b2022-10-25 00:07:15 +0000854 EXPECT_THROW(
855 UserMgr::maxLoginAttemptBeforeLockout(16),
856 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
Jason M. Bills2d042d12023-03-28 15:32:45 -0700857 EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 2);
Nan Zhoucfabe6b2022-10-25 00:07:15 +0000858}
859
Nan Zhou784aecd2022-10-25 00:07:16 +0000860TEST_F(UserMgrInTest, AccountUnlockTimeoutReturnsIfValueIsTheSame)
861{
862 initializeAccountPolicy();
863 EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 3);
864 UserMgr::accountUnlockTimeout(3);
865 EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 3);
866}
867
868TEST_F(UserMgrInTest, AccountUnlockTimeoutOnSuccess)
869{
870 initializeAccountPolicy();
871 EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 3);
872 UserMgr::accountUnlockTimeout(16);
873 EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 16);
874}
875
876TEST_F(UserMgrInTest, AccountUnlockTimeoutOnFailure)
877{
878 initializeAccountPolicy();
Jason M. Bills2d042d12023-03-28 15:32:45 -0700879 EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
Nan Zhou784aecd2022-10-25 00:07:16 +0000880 EXPECT_THROW(
881 UserMgr::accountUnlockTimeout(16),
882 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
883 EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 3);
884}
885
Nan Zhou6b6f2d82022-10-25 00:07:17 +0000886TEST_F(UserMgrInTest, UserEnableOnSuccess)
887{
888 std::string username = "user001";
889 EXPECT_NO_THROW(
890 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
891 UserInfoMap userInfo = getUserInfo(username);
892 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
893
894 EXPECT_NO_THROW(userEnable(username, false));
895
896 userInfo = getUserInfo(username);
897 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), false);
898
899 EXPECT_NO_THROW(UserMgr::deleteUser(username));
900}
901
Ninad Palsule601d3db2023-03-09 10:27:37 -0600902TEST_F(UserMgrInTest, CreateDeleteUserSuccessForHostConsole)
903{
904 std::string username = "user001";
905 EXPECT_NO_THROW(
906 UserMgr::createUser(username, {"hostconsole"}, "priv-user", true));
907 EXPECT_NO_THROW(UserMgr::deleteUser(username));
908 EXPECT_NO_THROW(
909 UserMgr::createUser(username, {"hostconsole"}, "priv-admin", true));
910 EXPECT_NO_THROW(UserMgr::deleteUser(username));
911 EXPECT_NO_THROW(
912 UserMgr::createUser(username, {"hostconsole"}, "priv-operator", true));
913 EXPECT_NO_THROW(UserMgr::deleteUser(username));
914}
915
Nan Zhou6b6f2d82022-10-25 00:07:17 +0000916TEST_F(UserMgrInTest, UserEnableThrowsInternalFailureIfExecuteUserModifyFail)
917{
918 std::string username = "user001";
919 EXPECT_NO_THROW(
920 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
921 UserInfoMap userInfo = getUserInfo(username);
922 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
923
924 EXPECT_CALL(*this, executeUserModifyUserEnable(testing::StrEq(username),
925 testing::Eq(false)))
926 .WillOnce(testing::Throw(
927 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
928 EXPECT_THROW(
929 userEnable(username, false),
930 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
931
932 userInfo = getUserInfo(username);
933 // Stay unchanged
934 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
935
936 EXPECT_NO_THROW(UserMgr::deleteUser(username));
937}
938
Nan Zhoua2953032022-11-11 21:50:32 +0000939TEST_F(
940 UserMgrInTest,
941 UserLockedForFailedAttemptReturnsFalseIfMaxLoginAttemptBeforeLockoutIsZero)
942{
943 EXPECT_FALSE(userLockedForFailedAttempt("whatever"));
944}
945
946TEST_F(UserMgrInTest, UserLockedForFailedAttemptZeroFailuresReturnsFalse)
947{
948 std::string username = "user001";
949 initializeAccountPolicy();
950 // Example output from BMC
Jason M. Bills2d042d12023-03-28 15:32:45 -0700951 // root:~# faillock --user root
952 // root:
953 // When Type Source Valid
954 std::vector<std::string> output = {"whatever",
955 "When Type Source Valid"};
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_FALSE(userLockedForFailedAttempt(username));
960}
961
962TEST_F(UserMgrInTest, UserLockedForFailedAttemptFailIfGetFailedAttemptFail)
963{
964 std::string username = "user001";
965 initializeAccountPolicy();
966 EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
967 .WillOnce(testing::Throw(
968 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
969
970 EXPECT_THROW(
971 userLockedForFailedAttempt(username),
972 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
973}
974
975TEST_F(UserMgrInTest,
Nan Zhoua2953032022-11-11 21:50:32 +0000976 UserLockedForFailedAttemptThrowsInternalFailureIfWrongDateFormat)
977{
978 std::string username = "user001";
979 initializeAccountPolicy();
980
981 // Choose a date in the past.
982 std::vector<std::string> output = {"whatever",
Jason M. Bills2d042d12023-03-28 15:32:45 -0700983 "10/24/2002 00:00:00 type source V"};
Nan Zhoua2953032022-11-11 21:50:32 +0000984 EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
985 .WillOnce(testing::Return(output));
986
987 EXPECT_THROW(
988 userLockedForFailedAttempt(username),
989 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
990}
991
992TEST_F(UserMgrInTest,
993 UserLockedForFailedAttemptReturnsFalseIfLastFailTimeHasTimedOut)
994{
995 std::string username = "user001";
996 initializeAccountPolicy();
997
998 // Choose a date in the past.
999 std::vector<std::string> output = {"whatever",
Jason M. Bills2d042d12023-03-28 15:32:45 -07001000 "2002-10-24 00:00:00 type source V"};
Nan Zhoua2953032022-11-11 21:50:32 +00001001 EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
1002 .WillOnce(testing::Return(output));
1003
1004 EXPECT_EQ(userLockedForFailedAttempt(username), false);
1005}
1006
Nan Zhouda401fe2022-10-25 00:07:18 +00001007TEST_F(UserMgrInTest, CheckAndThrowForDisallowedGroupCreationOnSuccess)
1008{
1009 // Base Redfish Roles
1010 EXPECT_NO_THROW(
1011 checkAndThrowForDisallowedGroupCreation("openbmc_rfr_Administrator"));
1012 EXPECT_NO_THROW(
1013 checkAndThrowForDisallowedGroupCreation("openbmc_rfr_Operator"));
1014 EXPECT_NO_THROW(
1015 checkAndThrowForDisallowedGroupCreation("openbmc_rfr_ReadOnly"));
1016 // Base Redfish Privileges
1017 EXPECT_NO_THROW(
1018 checkAndThrowForDisallowedGroupCreation("openbmc_rfp_Login"));
1019 EXPECT_NO_THROW(checkAndThrowForDisallowedGroupCreation(
1020 "openbmc_rfp_ConfigureManager"));
1021 EXPECT_NO_THROW(
1022 checkAndThrowForDisallowedGroupCreation("openbmc_rfp_ConfigureUsers"));
1023 EXPECT_NO_THROW(
1024 checkAndThrowForDisallowedGroupCreation("openbmc_rfp_ConfigureSelf"));
1025 EXPECT_NO_THROW(checkAndThrowForDisallowedGroupCreation(
1026 "openbmc_rfp_ConfigureComponents"));
1027 // OEM Redfish Roles
1028 EXPECT_NO_THROW(
1029 checkAndThrowForDisallowedGroupCreation("openbmc_orfr_PowerService"));
1030 // OEM Redfish Privileges
1031 EXPECT_NO_THROW(
1032 checkAndThrowForDisallowedGroupCreation("openbmc_orfp_PowerService"));
1033}
1034
1035TEST_F(UserMgrInTest,
1036 CheckAndThrowForDisallowedGroupCreationThrowsIfGroupNameTooLong)
1037{
1038 std::string groupName(maxSystemGroupNameLength + 1, 'A');
1039 EXPECT_THROW(
1040 checkAndThrowForDisallowedGroupCreation(groupName),
1041 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1042}
1043
1044TEST_F(
1045 UserMgrInTest,
1046 CheckAndThrowForDisallowedGroupCreationThrowsIfGroupNameHasDisallowedCharacters)
1047{
Nan Zhouda401fe2022-10-25 00:07:18 +00001048 EXPECT_THROW(
1049 checkAndThrowForDisallowedGroupCreation("openbmc_rfp_?owerService"),
1050 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1051 EXPECT_THROW(
1052 checkAndThrowForDisallowedGroupCreation("openbmc_rfp_-owerService"),
1053 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1054}
1055
1056TEST_F(
1057 UserMgrInTest,
1058 CheckAndThrowForDisallowedGroupCreationThrowsIfGroupNameHasDisallowedPrefix)
1059{
Nan Zhouda401fe2022-10-25 00:07:18 +00001060 EXPECT_THROW(
1061 checkAndThrowForDisallowedGroupCreation("google_rfp_"),
1062 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1063 EXPECT_THROW(
1064 checkAndThrowForDisallowedGroupCreation("com_rfp_"),
1065 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1066}
1067
1068TEST_F(UserMgrInTest, CheckAndThrowForMaxGroupCountOnSuccess)
1069{
Ravi Teja4e2c06e2024-04-20 23:18:34 -05001070 constexpr size_t predefGroupCount = 4;
Ninad Palsule601d3db2023-03-09 10:27:37 -06001071
1072 EXPECT_THAT(allGroups().size(), predefGroupCount);
1073 for (size_t i = 0; i < maxSystemGroupCount - predefGroupCount; ++i)
Nan Zhouda401fe2022-10-25 00:07:18 +00001074 {
1075 std::string groupName = "openbmc_rfr_role";
1076 groupName += std::to_string(i);
1077 EXPECT_NO_THROW(createGroup(groupName));
1078 }
1079 EXPECT_THROW(
1080 createGroup("openbmc_rfr_AnotherRole"),
1081 sdbusplus::xyz::openbmc_project::User::Common::Error::NoResource);
Ninad Palsule601d3db2023-03-09 10:27:37 -06001082 for (size_t i = 0; i < maxSystemGroupCount - predefGroupCount; ++i)
Nan Zhouda401fe2022-10-25 00:07:18 +00001083 {
1084 std::string groupName = "openbmc_rfr_role";
1085 groupName += std::to_string(i);
1086 EXPECT_NO_THROW(deleteGroup(groupName));
1087 }
1088}
1089
1090TEST_F(UserMgrInTest, CheckAndThrowForGroupExist)
1091{
1092 std::string groupName = "openbmc_rfr_role";
1093 EXPECT_NO_THROW(createGroup(groupName));
1094 EXPECT_THROW(
1095 createGroup(groupName),
1096 sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1097 EXPECT_NO_THROW(deleteGroup(groupName));
1098}
1099
1100TEST_F(UserMgrInTest, ByDefaultAllGroupsArePredefinedGroups)
1101{
Ravi Teja4e2c06e2024-04-20 23:18:34 -05001102 EXPECT_THAT(allGroups(), testing::UnorderedElementsAre(
1103 "redfish", "ipmi", "ssh", "hostconsole"));
Ninad Palsule601d3db2023-03-09 10:27:37 -06001104}
1105
1106TEST_F(UserMgrInTest, AddGroupThrowsIfPreDefinedGroupAdd)
1107{
1108 EXPECT_THROW(
1109 createGroup("ipmi"),
1110 sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1111 EXPECT_THROW(
Ninad Palsule601d3db2023-03-09 10:27:37 -06001112 createGroup("redfish"),
1113 sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1114 EXPECT_THROW(
1115 createGroup("ssh"),
1116 sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1117 EXPECT_THROW(
1118 createGroup("hostconsole"),
1119 sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
Nan Zhouda401fe2022-10-25 00:07:18 +00001120}
1121
1122TEST_F(UserMgrInTest, DeleteGroupThrowsIfGroupIsNotAllowedToChange)
1123{
1124 EXPECT_THROW(
1125 deleteGroup("ipmi"),
1126 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1127 EXPECT_THROW(
Nan Zhouda401fe2022-10-25 00:07:18 +00001128 deleteGroup("redfish"),
1129 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1130 EXPECT_THROW(
1131 deleteGroup("ssh"),
1132 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
Ninad Palsule601d3db2023-03-09 10:27:37 -06001133 EXPECT_THROW(
1134 deleteGroup("hostconsole"),
1135 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
Nan Zhouda401fe2022-10-25 00:07:18 +00001136}
1137
1138TEST_F(UserMgrInTest,
1139 CreateGroupThrowsInternalFailureWhenExecuteGroupCreateFails)
1140{
1141 EXPECT_CALL(*this, executeGroupCreation)
1142 .WillOnce(testing::Throw(
1143 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
1144 EXPECT_THROW(
1145 createGroup("openbmc_rfr_role1"),
1146 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
1147}
1148
1149TEST_F(UserMgrInTest,
1150 DeleteGroupThrowsInternalFailureWhenExecuteGroupDeleteFails)
1151{
1152 std::string groupName = "openbmc_rfr_role1";
1153 EXPECT_NO_THROW(UserMgr::createGroup(groupName));
1154 EXPECT_CALL(*this, executeGroupDeletion(testing::StrEq(groupName)))
1155 .WillOnce(testing::Throw(
1156 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()))
1157 .WillOnce(testing::DoDefault());
1158
1159 EXPECT_THROW(
1160 deleteGroup(groupName),
1161 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
1162 EXPECT_NO_THROW(UserMgr::deleteGroup(groupName));
1163}
1164
1165TEST_F(UserMgrInTest, CheckAndThrowForGroupNotExist)
1166{
1167 EXPECT_THROW(deleteGroup("whatever"),
1168 sdbusplus::xyz::openbmc_project::User::Common::Error::
1169 GroupNameDoesNotExist);
1170}
1171
1172TEST(ReadAllGroupsOnSystemTest, OnlyReturnsPredefinedGroups)
1173{
Ravi Teja4e2c06e2024-04-20 23:18:34 -05001174 EXPECT_THAT(
1175 UserMgr::readAllGroupsOnSystem(),
1176 testing::UnorderedElementsAre("redfish", "ipmi", "ssh", "hostconsole"));
Nan Zhouda401fe2022-10-25 00:07:18 +00001177}
1178
raviteja-b8cc44052019-02-27 23:29:36 -06001179} // namespace user
1180} // namespace phosphor