blob: 85a8b0ac5cb0ec8558208d30f79471f3f095712f [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
239 outputFileStream.exceptions(std::ofstream::failbit | std::ofstream::badbit |
240 std::ofstream::eofbit);
241
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]() {
Denis Zlobine8edab52023-09-06 12:26:45 +0000277 ON_CALL(*this, isUserEnabled).WillByDefault(testing::Return(true));
278 testing::Return();
Patrick Williamscb20ea82023-10-20 11:19:13 -0500279 });
Denis Zlobine8edab52023-09-06 12:26:45 +0000280
281 ON_CALL(*this, executeUserAdd(testing::_, testing::_, testing::_,
282 testing::Eq(false)))
Patrick Williamscb20ea82023-10-20 11:19:13 -0500283 .WillByDefault([this]() {
Denis Zlobine8edab52023-09-06 12:26:45 +0000284 ON_CALL(*this, isUserEnabled).WillByDefault(testing::Return(false));
285 testing::Return();
Patrick Williamscb20ea82023-10-20 11:19:13 -0500286 });
Nan Zhou49c81362022-10-25 00:07:08 +0000287
288 ON_CALL(*this, executeUserDelete).WillByDefault(testing::Return());
289
Jayanth Othayothac921a52023-07-21 03:48:55 -0500290 ON_CALL(*this, executeUserClearFailRecords)
291 .WillByDefault(testing::Return());
292
Nan Zhou49c81362022-10-25 00:07:08 +0000293 ON_CALL(*this, getIpmiUsersCount).WillByDefault(testing::Return(0));
Nan Zhouf25443e2022-10-25 00:07:11 +0000294
295 ON_CALL(*this, executeUserRename).WillByDefault(testing::Return());
Nan Zhoufef63032022-10-25 00:07:12 +0000296
297 ON_CALL(*this, executeUserModify(testing::_, testing::_, testing::_))
298 .WillByDefault(testing::Return());
Nan Zhou6b6f2d82022-10-25 00:07:17 +0000299
Denis Zlobine8edab52023-09-06 12:26:45 +0000300 ON_CALL(*this,
301 executeUserModifyUserEnable(testing::_, testing::Eq(true)))
Patrick Williamscb20ea82023-10-20 11:19:13 -0500302 .WillByDefault([this]() {
Denis Zlobine8edab52023-09-06 12:26:45 +0000303 ON_CALL(*this, isUserEnabled).WillByDefault(testing::Return(true));
304 testing::Return();
Patrick Williamscb20ea82023-10-20 11:19:13 -0500305 });
Denis Zlobine8edab52023-09-06 12:26:45 +0000306
307 ON_CALL(*this,
308 executeUserModifyUserEnable(testing::_, testing::Eq(false)))
Patrick Williamscb20ea82023-10-20 11:19:13 -0500309 .WillByDefault([this]() {
Denis Zlobine8edab52023-09-06 12:26:45 +0000310 ON_CALL(*this, isUserEnabled).WillByDefault(testing::Return(false));
311 testing::Return();
Patrick Williamscb20ea82023-10-20 11:19:13 -0500312 });
Nan Zhouda401fe2022-10-25 00:07:18 +0000313
314 ON_CALL(*this, executeGroupCreation(testing::_))
315 .WillByDefault(testing::Return());
316
317 ON_CALL(*this, executeGroupDeletion(testing::_))
318 .WillByDefault(testing::Return());
319
320 ON_CALL(*this, executeGroupCreation).WillByDefault(testing::Return());
321
322 ON_CALL(*this, executeGroupDeletion).WillByDefault(testing::Return());
Nan Zhoue48085d2022-10-25 00:07:04 +0000323 }
324
325 ~UserMgrInTest() override
326 {
Jason M. Bills2d042d12023-03-28 15:32:45 -0700327 EXPECT_NO_THROW(removeFile(tempFaillockConfigFile));
Jason M. Bills3b280ec2023-08-15 16:15:48 -0700328 EXPECT_NO_THROW(removeFile(tempPWHistoryConfigFile));
Jason M. Bills2d042d12023-03-28 15:32:45 -0700329 EXPECT_NO_THROW(removeFile(tempPWQualityConfigFile));
Nan Zhoue48085d2022-10-25 00:07:04 +0000330 }
331
Nan Zhou49c81362022-10-25 00:07:08 +0000332 MOCK_METHOD(void, executeUserAdd, (const char*, const char*, bool, bool),
333 (override));
334
335 MOCK_METHOD(void, executeUserDelete, (const char*), (override));
336
Jayanth Othayothac921a52023-07-21 03:48:55 -0500337 MOCK_METHOD(void, executeUserClearFailRecords, (const char*), (override));
338
Nan Zhou49c81362022-10-25 00:07:08 +0000339 MOCK_METHOD(size_t, getIpmiUsersCount, (), (override));
340
Nan Zhouf25443e2022-10-25 00:07:11 +0000341 MOCK_METHOD(void, executeUserRename, (const char*, const char*),
342 (override));
343
Nan Zhoufef63032022-10-25 00:07:12 +0000344 MOCK_METHOD(void, executeUserModify, (const char*, const char*, bool),
345 (override));
346
Nan Zhou6b6f2d82022-10-25 00:07:17 +0000347 MOCK_METHOD(void, executeUserModifyUserEnable, (const char*, bool),
348 (override));
349
Nan Zhoua2953032022-11-11 21:50:32 +0000350 MOCK_METHOD(std::vector<std::string>, getFailedAttempt, (const char*),
351 (override));
352
Nan Zhouda401fe2022-10-25 00:07:18 +0000353 MOCK_METHOD(void, executeGroupCreation, (const char*), (override));
354
355 MOCK_METHOD(void, executeGroupDeletion, (const char*), (override));
356
Denis Zlobine8edab52023-09-06 12:26:45 +0000357 MOCK_METHOD(bool, isUserEnabled, (const std::string& userName), (override));
358
Nan Zhoufef63032022-10-25 00:07:12 +0000359 protected:
Nan Zhoue48085d2022-10-25 00:07:04 +0000360 static sdbusplus::bus_t busInTest;
Jason M. Bills2d042d12023-03-28 15:32:45 -0700361 std::string tempFaillockConfigFile;
Jason M. Bills3b280ec2023-08-15 16:15:48 -0700362 std::string tempPWHistoryConfigFile;
Jason M. Bills2d042d12023-03-28 15:32:45 -0700363 std::string tempPWQualityConfigFile;
Nan Zhoue48085d2022-10-25 00:07:04 +0000364};
365
366sdbusplus::bus_t UserMgrInTest::busInTest = sdbusplus::bus::new_default();
367
Jason M. Bills2d042d12023-03-28 15:32:45 -0700368TEST_F(UserMgrInTest, GetPamModuleConfValueOnSuccess)
369{
370 std::string minlen;
371 EXPECT_EQ(getPamModuleConfValue(tempPWQualityConfigFile, "minlen", minlen),
372 0);
373 EXPECT_EQ(minlen, "8");
374 std::string deny;
375 EXPECT_EQ(getPamModuleConfValue(tempFaillockConfigFile, "deny", deny), 0);
376 EXPECT_EQ(deny, "2");
Jason M. Bills2d042d12023-03-28 15:32:45 -0700377 std::string remember;
Jason M. Bills3b280ec2023-08-15 16:15:48 -0700378 EXPECT_EQ(
379 getPamModuleConfValue(tempPWHistoryConfigFile, "remember", remember),
380 0);
381 EXPECT_EQ(remember, "0");
Jason M. Bills2d042d12023-03-28 15:32:45 -0700382}
383
384TEST_F(UserMgrInTest, SetPamModuleConfValueOnSuccess)
385{
386 EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
387 0);
388 std::string minlen;
389 EXPECT_EQ(getPamModuleConfValue(tempPWQualityConfigFile, "minlen", minlen),
390 0);
391 EXPECT_EQ(minlen, "16");
392
393 EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), 0);
394 std::string deny;
395 EXPECT_EQ(getPamModuleConfValue(tempFaillockConfigFile, "deny", deny), 0);
396 EXPECT_EQ(deny, "3");
Nan Zhoue48085d2022-10-25 00:07:04 +0000397
Jason M. Bills3b280ec2023-08-15 16:15:48 -0700398 EXPECT_EQ(setPamModuleConfValue(tempPWHistoryConfigFile, "remember", "1"),
399 0);
400 std::string remember;
401 EXPECT_EQ(
402 getPamModuleConfValue(tempPWHistoryConfigFile, "remember", remember),
403 0);
404 EXPECT_EQ(remember, "1");
Jason M. Bills17b88272023-05-22 14:24:02 -0700405}
406
407TEST_F(UserMgrInTest, SetPamModuleConfValueTempFileOnSuccess)
408{
409 EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
410 0);
411
412 std::string tmpFile = tempPWQualityConfigFile + "_tmp";
413 EXPECT_FALSE(std::filesystem::exists(tmpFile));
414
415 EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), 0);
416
417 tmpFile = tempFaillockConfigFile + "_tmp";
418 EXPECT_FALSE(std::filesystem::exists(tmpFile));
Jason M. Bills17b88272023-05-22 14:24:02 -0700419
Jason M. Bills3b280ec2023-08-15 16:15:48 -0700420 EXPECT_EQ(setPamModuleConfValue(tempPWHistoryConfigFile, "remember", "1"),
421 0);
Nan Zhoue48085d2022-10-25 00:07:04 +0000422
Jason M. Bills3b280ec2023-08-15 16:15:48 -0700423 tmpFile = tempPWHistoryConfigFile + "_tmp";
424 EXPECT_FALSE(std::filesystem::exists(tmpFile));
Jason M. Bills2d042d12023-03-28 15:32:45 -0700425}
426
427TEST_F(UserMgrInTest, GetPamModuleConfValueOnFailure)
428{
429 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWQualityConfigFile));
430 std::string minlen;
431 EXPECT_EQ(getPamModuleConfValue(tempPWQualityConfigFile, "minlen", minlen),
432 -1);
433
434 EXPECT_NO_THROW(removeFile(tempPWQualityConfigFile));
435 EXPECT_EQ(getPamModuleConfValue(tempPWQualityConfigFile, "minlen", minlen),
436 -1);
437
438 EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
439 std::string deny;
440 EXPECT_EQ(getPamModuleConfValue(tempFaillockConfigFile, "deny", deny), -1);
441
442 EXPECT_NO_THROW(removeFile(tempFaillockConfigFile));
443 EXPECT_EQ(getPamModuleConfValue(tempFaillockConfigFile, "deny", deny), -1);
Nan Zhoue48085d2022-10-25 00:07:04 +0000444
Jason M. Bills3b280ec2023-08-15 16:15:48 -0700445 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWHistoryConfigFile));
446 std::string remember;
447 EXPECT_EQ(
448 getPamModuleConfValue(tempPWHistoryConfigFile, "remember", remember),
449 -1);
Nan Zhoue48085d2022-10-25 00:07:04 +0000450
Jason M. Bills3b280ec2023-08-15 16:15:48 -0700451 EXPECT_NO_THROW(removeFile(tempPWHistoryConfigFile));
452 EXPECT_EQ(
453 getPamModuleConfValue(tempPWHistoryConfigFile, "remember", remember),
454 -1);
Jason M. Bills2d042d12023-03-28 15:32:45 -0700455}
456
457TEST_F(UserMgrInTest, SetPamModuleConfValueOnFailure)
458{
459 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWQualityConfigFile));
460 EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
461 -1);
462
463 EXPECT_NO_THROW(removeFile(tempPWQualityConfigFile));
464 EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
465 -1);
466
467 EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
468 EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), -1);
469
470 EXPECT_NO_THROW(removeFile(tempFaillockConfigFile));
471 EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), -1);
Nan Zhoue48085d2022-10-25 00:07:04 +0000472
Jason M. Bills3b280ec2023-08-15 16:15:48 -0700473 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWHistoryConfigFile));
474 EXPECT_EQ(setPamModuleConfValue(tempPWHistoryConfigFile, "remember", "1"),
475 -1);
Jason M. Bills17b88272023-05-22 14:24:02 -0700476
Jason M. Bills3b280ec2023-08-15 16:15:48 -0700477 EXPECT_NO_THROW(removeFile(tempPWHistoryConfigFile));
478 EXPECT_EQ(setPamModuleConfValue(tempPWHistoryConfigFile, "remember", "1"),
479 -1);
Jason M. Bills17b88272023-05-22 14:24:02 -0700480}
481
482TEST_F(UserMgrInTest, SetPamModuleConfValueTempFileOnFailure)
483{
484 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWQualityConfigFile));
485 EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
486 -1);
487
488 std::string tmpFile = tempPWQualityConfigFile + "_tmp";
489 EXPECT_FALSE(std::filesystem::exists(tmpFile));
490
491 EXPECT_NO_THROW(removeFile(tempPWQualityConfigFile));
492 EXPECT_EQ(setPamModuleConfValue(tempPWQualityConfigFile, "minlen", "16"),
493 -1);
494
495 EXPECT_FALSE(std::filesystem::exists(tmpFile));
496
497 EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
498 EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), -1);
499
500 tmpFile = tempFaillockConfigFile + "_tmp";
501 EXPECT_FALSE(std::filesystem::exists(tmpFile));
502
503 EXPECT_NO_THROW(removeFile(tempFaillockConfigFile));
504 EXPECT_EQ(setPamModuleConfValue(tempFaillockConfigFile, "deny", "3"), -1);
505
506 EXPECT_FALSE(std::filesystem::exists(tmpFile));
Jason M. Bills3b280ec2023-08-15 16:15:48 -0700507
508 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWHistoryConfigFile));
509 EXPECT_EQ(setPamModuleConfValue(tempPWHistoryConfigFile, "remember", "1"),
510 -1);
511
512 tmpFile = tempPWHistoryConfigFile + "_tmp";
513 EXPECT_FALSE(std::filesystem::exists(tmpFile));
514
515 EXPECT_NO_THROW(removeFile(tempPWHistoryConfigFile));
516 EXPECT_EQ(setPamModuleConfValue(tempPWHistoryConfigFile, "remember", "1"),
517 -1);
518
519 EXPECT_FALSE(std::filesystem::exists(tmpFile));
Jason M. Bills17b88272023-05-22 14:24:02 -0700520}
521
Nan Zhou8a11d992022-10-25 00:07:06 +0000522TEST_F(UserMgrInTest, IsUserExistEmptyInputThrowsError)
523{
524 EXPECT_THROW(
525 isUserExist(""),
526 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
527}
528
529TEST_F(UserMgrInTest, ThrowForUserDoesNotExistThrowsError)
530{
531 EXPECT_THROW(throwForUserDoesNotExist("whatever"),
532 sdbusplus::xyz::openbmc_project::User::Common::Error::
533 UserNameDoesNotExist);
534}
535
536TEST_F(UserMgrInTest, ThrowForUserExistsThrowsError)
537{
538 EXPECT_THROW(
539 throwForUserExists("root"),
540 sdbusplus::xyz::openbmc_project::User::Common::Error::UserNameExists);
541}
542
Nan Zhou40e44972022-10-25 00:07:07 +0000543TEST_F(
544 UserMgrInTest,
545 ThrowForUserNameConstraintsExceedIpmiMaxUserNameLenThrowsUserNameGroupFail)
546{
547 std::string strWith17Chars(17, 'A');
548 EXPECT_THROW(throwForUserNameConstraints(strWith17Chars, {"ipmi"}),
549 sdbusplus::xyz::openbmc_project::User::Common::Error::
550 UserNameGroupFail);
551}
552
553TEST_F(
554 UserMgrInTest,
555 ThrowForUserNameConstraintsExceedSystemMaxUserNameLenThrowsInvalidArgument)
556{
557 std::string strWith31Chars(31, 'A');
558 EXPECT_THROW(
559 throwForUserNameConstraints(strWith31Chars, {}),
560 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
561}
562
563TEST_F(UserMgrInTest,
564 ThrowForUserNameConstraintsRegexMismatchThrowsInvalidArgument)
565{
566 std::string startWithNumber = "0ABC";
567 EXPECT_THROW(
568 throwForUserNameConstraints(startWithNumber, {"ipmi"}),
569 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
570}
571
Nan Zhou49c81362022-10-25 00:07:08 +0000572TEST_F(UserMgrInTest, UserAddNotRootFailedWithInternalFailure)
573{
574 EXPECT_THROW(
575 UserMgr::executeUserAdd("user0", "ipmi,ssh", true, true),
576 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
577}
578
579TEST_F(UserMgrInTest, UserDeleteNotRootFailedWithInternalFailure)
580{
581 EXPECT_THROW(
582 UserMgr::executeUserDelete("user0"),
583 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
584}
585
586TEST_F(UserMgrInTest,
587 ThrowForMaxGrpUserCountThrowsNoResourceWhenIpmiUserExceedLimit)
588{
589 EXPECT_CALL(*this, getIpmiUsersCount()).WillOnce(Return(ipmiMaxUsers));
590 EXPECT_THROW(
591 throwForMaxGrpUserCount({"ipmi"}),
592 sdbusplus::xyz::openbmc_project::User::Common::Error::NoResource);
593}
594
595TEST_F(UserMgrInTest, CreateUserThrowsInternalFailureWhenExecuteUserAddFails)
596{
597 EXPECT_CALL(*this, executeUserAdd)
598 .WillOnce(testing::Throw(
599 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
600 EXPECT_THROW(
601 createUser("whatever", {"redfish"}, "", true),
602 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
603}
604
605TEST_F(UserMgrInTest, DeleteUserThrowsInternalFailureWhenExecuteUserDeleteFails)
606{
607 std::string username = "user";
608 EXPECT_NO_THROW(
609 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
610 EXPECT_CALL(*this, executeUserDelete(testing::StrEq(username)))
611 .WillOnce(testing::Throw(
612 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()))
613 .WillOnce(testing::DoDefault());
614
615 EXPECT_THROW(
616 deleteUser(username),
617 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
618 EXPECT_NO_THROW(UserMgr::deleteUser(username));
619}
620
Jayanth Othayothac921a52023-07-21 03:48:55 -0500621TEST_F(UserMgrInTest,
622 DeleteUserThrowsInternalFailureWhenExecuteUserClearFailRecords)
623{
624 const char* username = "user";
625 EXPECT_NO_THROW(
626 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
627 EXPECT_CALL(*this, executeUserClearFailRecords(testing::StrEq(username)))
628 .WillOnce(testing::Throw(
629 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()))
630 .WillOnce(testing::DoDefault());
631
632 EXPECT_THROW(
633 deleteUser(username),
634 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
635 EXPECT_NO_THROW(UserMgr::deleteUser(username));
636}
637
Nan Zhou589aeb42022-10-25 00:07:09 +0000638TEST_F(UserMgrInTest, ThrowForInvalidPrivilegeThrowsWhenPrivilegeIsInvalid)
639{
640 EXPECT_THROW(
641 throwForInvalidPrivilege("whatever"),
642 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
643}
644
645TEST_F(UserMgrInTest, ThrowForInvalidPrivilegeNoThrowWhenPrivilegeIsValid)
646{
647 EXPECT_NO_THROW(throwForInvalidPrivilege("priv-admin"));
648 EXPECT_NO_THROW(throwForInvalidPrivilege("priv-operator"));
649 EXPECT_NO_THROW(throwForInvalidPrivilege("priv-user"));
Nan Zhou589aeb42022-10-25 00:07:09 +0000650}
651
Nan Zhouecf88762022-10-25 00:07:10 +0000652TEST_F(UserMgrInTest, ThrowForInvalidGroupsThrowsWhenGroupIsInvalid)
653{
654 EXPECT_THROW(
655 throwForInvalidGroups({"whatever"}),
656 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
657}
658
659TEST_F(UserMgrInTest, ThrowForInvalidGroupsNoThrowWhenGroupIsValid)
660{
661 EXPECT_NO_THROW(throwForInvalidGroups({"ipmi"}));
662 EXPECT_NO_THROW(throwForInvalidGroups({"ssh"}));
663 EXPECT_NO_THROW(throwForInvalidGroups({"redfish"}));
664 EXPECT_NO_THROW(throwForInvalidGroups({"web"}));
Ninad Palsule601d3db2023-03-09 10:27:37 -0600665 EXPECT_NO_THROW(throwForInvalidGroups({"hostconsole"}));
Nan Zhouecf88762022-10-25 00:07:10 +0000666}
667
Nan Zhouf25443e2022-10-25 00:07:11 +0000668TEST_F(UserMgrInTest, RenameUserOnSuccess)
669{
670 std::string username = "user001";
671 EXPECT_NO_THROW(
672 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
673 std::string newUsername = "user002";
674
675 EXPECT_NO_THROW(UserMgr::renameUser(username, newUsername));
676
677 // old username doesn't exist
678 EXPECT_THROW(getUserInfo(username),
679 sdbusplus::xyz::openbmc_project::User::Common::Error::
680 UserNameDoesNotExist);
681
682 UserInfoMap userInfo = getUserInfo(newUsername);
683 EXPECT_EQ(std::get<Privilege>(userInfo["UserPrivilege"]), "priv-user");
684 EXPECT_THAT(std::get<GroupList>(userInfo["UserGroups"]),
685 testing::UnorderedElementsAre("redfish", "ssh"));
686 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
687
688 EXPECT_NO_THROW(UserMgr::deleteUser(newUsername));
689}
690
691TEST_F(UserMgrInTest, RenameUserThrowsInternalFailureIfExecuteUserModifyFails)
692{
693 std::string username = "user001";
694 EXPECT_NO_THROW(
695 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
696 std::string newUsername = "user002";
697
698 EXPECT_CALL(*this, executeUserRename(testing::StrEq(username),
699 testing::StrEq(newUsername)))
700 .WillOnce(testing::Throw(
701 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
702 EXPECT_THROW(
703 UserMgr::renameUser(username, newUsername),
704 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
705
706 // The original user is unchanged
707 UserInfoMap userInfo = getUserInfo(username);
708 EXPECT_EQ(std::get<Privilege>(userInfo["UserPrivilege"]), "priv-user");
709 EXPECT_THAT(std::get<GroupList>(userInfo["UserGroups"]),
710 testing::UnorderedElementsAre("redfish", "ssh"));
711 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
712
713 EXPECT_NO_THROW(UserMgr::deleteUser(username));
714}
715
716TEST_F(UserMgrInTest, DefaultUserModifyFailedWithInternalFailure)
717{
718 EXPECT_THROW(
719 UserMgr::executeUserRename("user0", "user1"),
720 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
Nan Zhoufef63032022-10-25 00:07:12 +0000721 EXPECT_THROW(
722 UserMgr::executeUserModify("user0", "ssh", true),
723 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
724}
725
726TEST_F(UserMgrInTest, UpdateGroupsAndPrivOnSuccess)
727{
728 std::string username = "user001";
729 EXPECT_NO_THROW(
730 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
731 EXPECT_NO_THROW(
732 updateGroupsAndPriv(username, {"ipmi", "ssh"}, "priv-admin"));
733 UserInfoMap userInfo = getUserInfo(username);
734 EXPECT_EQ(std::get<Privilege>(userInfo["UserPrivilege"]), "priv-admin");
735 EXPECT_THAT(std::get<GroupList>(userInfo["UserGroups"]),
736 testing::UnorderedElementsAre("ipmi", "ssh"));
737 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
738 EXPECT_NO_THROW(UserMgr::deleteUser(username));
739}
740
741TEST_F(UserMgrInTest,
742 UpdateGroupsAndPrivThrowsInternalFailureIfExecuteUserModifyFail)
743{
744 std::string username = "user001";
745 EXPECT_NO_THROW(
746 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
747 EXPECT_CALL(*this, executeUserModify(testing::StrEq(username), testing::_,
748 testing::_))
749 .WillOnce(testing::Throw(
750 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
751 EXPECT_THROW(
752 updateGroupsAndPriv(username, {"ipmi", "ssh"}, "priv-admin"),
753 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
754 EXPECT_NO_THROW(UserMgr::deleteUser(username));
Nan Zhouf25443e2022-10-25 00:07:11 +0000755}
756
Nan Zhou18031012022-11-10 22:24:58 +0000757TEST_F(UserMgrInTest, MinPasswordLengthReturnsIfValueIsTheSame)
758{
759 initializeAccountPolicy();
760 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
761 UserMgr::minPasswordLength(8);
762 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
763}
764
765TEST_F(UserMgrInTest,
766 MinPasswordLengthRejectsTooShortPasswordWithInvalidArgument)
767{
768 initializeAccountPolicy();
769 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
770 EXPECT_THROW(
771 UserMgr::minPasswordLength(minPasswdLength - 1),
772 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
773 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
774}
775
776TEST_F(UserMgrInTest, MinPasswordLengthOnSuccess)
777{
778 initializeAccountPolicy();
779 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
780 UserMgr::minPasswordLength(16);
781 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 16);
782}
783
784TEST_F(UserMgrInTest, MinPasswordLengthOnFailure)
785{
Jason M. Bills2d042d12023-03-28 15:32:45 -0700786 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWQualityConfigFile));
Nan Zhou18031012022-11-10 22:24:58 +0000787 initializeAccountPolicy();
788 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
789 EXPECT_THROW(
790 UserMgr::minPasswordLength(16),
791 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
792 EXPECT_EQ(AccountPolicyIface::minPasswordLength(), 8);
793}
794
Nan Zhoua6ce1fa2022-10-25 00:07:14 +0000795TEST_F(UserMgrInTest, RememberOldPasswordTimesReturnsIfValueIsTheSame)
796{
797 initializeAccountPolicy();
798 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 0);
799 UserMgr::rememberOldPasswordTimes(8);
800 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 8);
801 UserMgr::rememberOldPasswordTimes(8);
802 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 8);
803}
804
805TEST_F(UserMgrInTest, RememberOldPasswordTimesOnSuccess)
806{
807 initializeAccountPolicy();
808 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 0);
809 UserMgr::rememberOldPasswordTimes(16);
810 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 16);
811}
812
813TEST_F(UserMgrInTest, RememberOldPasswordTimesOnFailure)
814{
Jason M. Bills3b280ec2023-08-15 16:15:48 -0700815 EXPECT_NO_THROW(dumpStringToFile("whatever", tempPWHistoryConfigFile));
Nan Zhoua6ce1fa2022-10-25 00:07:14 +0000816 initializeAccountPolicy();
817 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 0);
818 EXPECT_THROW(
819 UserMgr::rememberOldPasswordTimes(16),
820 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
821 EXPECT_EQ(AccountPolicyIface::rememberOldPasswordTimes(), 0);
822}
823
Nan Zhoucfabe6b2022-10-25 00:07:15 +0000824TEST_F(UserMgrInTest, MaxLoginAttemptBeforeLockoutReturnsIfValueIsTheSame)
825{
826 initializeAccountPolicy();
827 EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 2);
828 UserMgr::maxLoginAttemptBeforeLockout(2);
829 EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 2);
830}
831
832TEST_F(UserMgrInTest, MaxLoginAttemptBeforeLockoutOnSuccess)
833{
834 initializeAccountPolicy();
835 EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 2);
836 UserMgr::maxLoginAttemptBeforeLockout(16);
837 EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 16);
838}
839
840TEST_F(UserMgrInTest, MaxLoginAttemptBeforeLockoutOnFailure)
841{
Nan Zhoucfabe6b2022-10-25 00:07:15 +0000842 initializeAccountPolicy();
Jason M. Bills2d042d12023-03-28 15:32:45 -0700843 EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
Nan Zhoucfabe6b2022-10-25 00:07:15 +0000844 EXPECT_THROW(
845 UserMgr::maxLoginAttemptBeforeLockout(16),
846 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
Jason M. Bills2d042d12023-03-28 15:32:45 -0700847 EXPECT_EQ(AccountPolicyIface::maxLoginAttemptBeforeLockout(), 2);
Nan Zhoucfabe6b2022-10-25 00:07:15 +0000848}
849
Nan Zhou784aecd2022-10-25 00:07:16 +0000850TEST_F(UserMgrInTest, AccountUnlockTimeoutReturnsIfValueIsTheSame)
851{
852 initializeAccountPolicy();
853 EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 3);
854 UserMgr::accountUnlockTimeout(3);
855 EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 3);
856}
857
858TEST_F(UserMgrInTest, AccountUnlockTimeoutOnSuccess)
859{
860 initializeAccountPolicy();
861 EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 3);
862 UserMgr::accountUnlockTimeout(16);
863 EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 16);
864}
865
866TEST_F(UserMgrInTest, AccountUnlockTimeoutOnFailure)
867{
868 initializeAccountPolicy();
Jason M. Bills2d042d12023-03-28 15:32:45 -0700869 EXPECT_NO_THROW(dumpStringToFile("whatever", tempFaillockConfigFile));
Nan Zhou784aecd2022-10-25 00:07:16 +0000870 EXPECT_THROW(
871 UserMgr::accountUnlockTimeout(16),
872 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
873 EXPECT_EQ(AccountPolicyIface::accountUnlockTimeout(), 3);
874}
875
Nan Zhou6b6f2d82022-10-25 00:07:17 +0000876TEST_F(UserMgrInTest, UserEnableOnSuccess)
877{
878 std::string username = "user001";
879 EXPECT_NO_THROW(
880 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
881 UserInfoMap userInfo = getUserInfo(username);
882 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
883
884 EXPECT_NO_THROW(userEnable(username, false));
885
886 userInfo = getUserInfo(username);
887 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), false);
888
889 EXPECT_NO_THROW(UserMgr::deleteUser(username));
890}
891
Ninad Palsule601d3db2023-03-09 10:27:37 -0600892TEST_F(UserMgrInTest, CreateDeleteUserSuccessForHostConsole)
893{
894 std::string username = "user001";
895 EXPECT_NO_THROW(
896 UserMgr::createUser(username, {"hostconsole"}, "priv-user", true));
897 EXPECT_NO_THROW(UserMgr::deleteUser(username));
898 EXPECT_NO_THROW(
899 UserMgr::createUser(username, {"hostconsole"}, "priv-admin", true));
900 EXPECT_NO_THROW(UserMgr::deleteUser(username));
901 EXPECT_NO_THROW(
902 UserMgr::createUser(username, {"hostconsole"}, "priv-operator", true));
903 EXPECT_NO_THROW(UserMgr::deleteUser(username));
904}
905
Nan Zhou6b6f2d82022-10-25 00:07:17 +0000906TEST_F(UserMgrInTest, UserEnableThrowsInternalFailureIfExecuteUserModifyFail)
907{
908 std::string username = "user001";
909 EXPECT_NO_THROW(
910 UserMgr::createUser(username, {"redfish", "ssh"}, "priv-user", true));
911 UserInfoMap userInfo = getUserInfo(username);
912 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
913
914 EXPECT_CALL(*this, executeUserModifyUserEnable(testing::StrEq(username),
915 testing::Eq(false)))
916 .WillOnce(testing::Throw(
917 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
918 EXPECT_THROW(
919 userEnable(username, false),
920 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
921
922 userInfo = getUserInfo(username);
923 // Stay unchanged
924 EXPECT_EQ(std::get<UserEnabled>(userInfo["UserEnabled"]), true);
925
926 EXPECT_NO_THROW(UserMgr::deleteUser(username));
927}
928
Nan Zhoua2953032022-11-11 21:50:32 +0000929TEST_F(
930 UserMgrInTest,
931 UserLockedForFailedAttemptReturnsFalseIfMaxLoginAttemptBeforeLockoutIsZero)
932{
933 EXPECT_FALSE(userLockedForFailedAttempt("whatever"));
934}
935
936TEST_F(UserMgrInTest, UserLockedForFailedAttemptZeroFailuresReturnsFalse)
937{
938 std::string username = "user001";
939 initializeAccountPolicy();
940 // Example output from BMC
Jason M. Bills2d042d12023-03-28 15:32:45 -0700941 // root:~# faillock --user root
942 // root:
943 // When Type Source Valid
944 std::vector<std::string> output = {"whatever",
945 "When Type Source Valid"};
Nan Zhoua2953032022-11-11 21:50:32 +0000946 EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
947 .WillOnce(testing::Return(output));
948
949 EXPECT_FALSE(userLockedForFailedAttempt(username));
950}
951
952TEST_F(UserMgrInTest, UserLockedForFailedAttemptFailIfGetFailedAttemptFail)
953{
954 std::string username = "user001";
955 initializeAccountPolicy();
956 EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
957 .WillOnce(testing::Throw(
958 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
959
960 EXPECT_THROW(
961 userLockedForFailedAttempt(username),
962 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
963}
964
965TEST_F(UserMgrInTest,
Nan Zhoua2953032022-11-11 21:50:32 +0000966 UserLockedForFailedAttemptThrowsInternalFailureIfWrongDateFormat)
967{
968 std::string username = "user001";
969 initializeAccountPolicy();
970
971 // Choose a date in the past.
972 std::vector<std::string> output = {"whatever",
Jason M. Bills2d042d12023-03-28 15:32:45 -0700973 "10/24/2002 00:00:00 type source V"};
Nan Zhoua2953032022-11-11 21:50:32 +0000974 EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
975 .WillOnce(testing::Return(output));
976
977 EXPECT_THROW(
978 userLockedForFailedAttempt(username),
979 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
980}
981
982TEST_F(UserMgrInTest,
983 UserLockedForFailedAttemptReturnsFalseIfLastFailTimeHasTimedOut)
984{
985 std::string username = "user001";
986 initializeAccountPolicy();
987
988 // Choose a date in the past.
989 std::vector<std::string> output = {"whatever",
Jason M. Bills2d042d12023-03-28 15:32:45 -0700990 "2002-10-24 00:00:00 type source V"};
Nan Zhoua2953032022-11-11 21:50:32 +0000991 EXPECT_CALL(*this, getFailedAttempt(testing::StrEq(username.c_str())))
992 .WillOnce(testing::Return(output));
993
994 EXPECT_EQ(userLockedForFailedAttempt(username), false);
995}
996
Nan Zhouda401fe2022-10-25 00:07:18 +0000997TEST_F(UserMgrInTest, CheckAndThrowForDisallowedGroupCreationOnSuccess)
998{
999 // Base Redfish Roles
1000 EXPECT_NO_THROW(
1001 checkAndThrowForDisallowedGroupCreation("openbmc_rfr_Administrator"));
1002 EXPECT_NO_THROW(
1003 checkAndThrowForDisallowedGroupCreation("openbmc_rfr_Operator"));
1004 EXPECT_NO_THROW(
1005 checkAndThrowForDisallowedGroupCreation("openbmc_rfr_ReadOnly"));
1006 // Base Redfish Privileges
1007 EXPECT_NO_THROW(
1008 checkAndThrowForDisallowedGroupCreation("openbmc_rfp_Login"));
1009 EXPECT_NO_THROW(checkAndThrowForDisallowedGroupCreation(
1010 "openbmc_rfp_ConfigureManager"));
1011 EXPECT_NO_THROW(
1012 checkAndThrowForDisallowedGroupCreation("openbmc_rfp_ConfigureUsers"));
1013 EXPECT_NO_THROW(
1014 checkAndThrowForDisallowedGroupCreation("openbmc_rfp_ConfigureSelf"));
1015 EXPECT_NO_THROW(checkAndThrowForDisallowedGroupCreation(
1016 "openbmc_rfp_ConfigureComponents"));
1017 // OEM Redfish Roles
1018 EXPECT_NO_THROW(
1019 checkAndThrowForDisallowedGroupCreation("openbmc_orfr_PowerService"));
1020 // OEM Redfish Privileges
1021 EXPECT_NO_THROW(
1022 checkAndThrowForDisallowedGroupCreation("openbmc_orfp_PowerService"));
1023}
1024
1025TEST_F(UserMgrInTest,
1026 CheckAndThrowForDisallowedGroupCreationThrowsIfGroupNameTooLong)
1027{
1028 std::string groupName(maxSystemGroupNameLength + 1, 'A');
1029 EXPECT_THROW(
1030 checkAndThrowForDisallowedGroupCreation(groupName),
1031 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1032}
1033
1034TEST_F(
1035 UserMgrInTest,
1036 CheckAndThrowForDisallowedGroupCreationThrowsIfGroupNameHasDisallowedCharacters)
1037{
Nan Zhouda401fe2022-10-25 00:07:18 +00001038 EXPECT_THROW(
1039 checkAndThrowForDisallowedGroupCreation("openbmc_rfp_?owerService"),
1040 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1041 EXPECT_THROW(
1042 checkAndThrowForDisallowedGroupCreation("openbmc_rfp_-owerService"),
1043 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1044}
1045
1046TEST_F(
1047 UserMgrInTest,
1048 CheckAndThrowForDisallowedGroupCreationThrowsIfGroupNameHasDisallowedPrefix)
1049{
Nan Zhouda401fe2022-10-25 00:07:18 +00001050 EXPECT_THROW(
1051 checkAndThrowForDisallowedGroupCreation("google_rfp_"),
1052 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1053 EXPECT_THROW(
1054 checkAndThrowForDisallowedGroupCreation("com_rfp_"),
1055 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1056}
1057
1058TEST_F(UserMgrInTest, CheckAndThrowForMaxGroupCountOnSuccess)
1059{
Ninad Palsule601d3db2023-03-09 10:27:37 -06001060 constexpr size_t predefGroupCount = 5;
1061
1062 EXPECT_THAT(allGroups().size(), predefGroupCount);
1063 for (size_t i = 0; i < maxSystemGroupCount - predefGroupCount; ++i)
Nan Zhouda401fe2022-10-25 00:07:18 +00001064 {
1065 std::string groupName = "openbmc_rfr_role";
1066 groupName += std::to_string(i);
1067 EXPECT_NO_THROW(createGroup(groupName));
1068 }
1069 EXPECT_THROW(
1070 createGroup("openbmc_rfr_AnotherRole"),
1071 sdbusplus::xyz::openbmc_project::User::Common::Error::NoResource);
Ninad Palsule601d3db2023-03-09 10:27:37 -06001072 for (size_t i = 0; i < maxSystemGroupCount - predefGroupCount; ++i)
Nan Zhouda401fe2022-10-25 00:07:18 +00001073 {
1074 std::string groupName = "openbmc_rfr_role";
1075 groupName += std::to_string(i);
1076 EXPECT_NO_THROW(deleteGroup(groupName));
1077 }
1078}
1079
1080TEST_F(UserMgrInTest, CheckAndThrowForGroupExist)
1081{
1082 std::string groupName = "openbmc_rfr_role";
1083 EXPECT_NO_THROW(createGroup(groupName));
1084 EXPECT_THROW(
1085 createGroup(groupName),
1086 sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1087 EXPECT_NO_THROW(deleteGroup(groupName));
1088}
1089
1090TEST_F(UserMgrInTest, ByDefaultAllGroupsArePredefinedGroups)
1091{
1092 EXPECT_THAT(allGroups(),
Ninad Palsule601d3db2023-03-09 10:27:37 -06001093 testing::UnorderedElementsAre("web", "redfish", "ipmi", "ssh",
1094 "hostconsole"));
1095}
1096
1097TEST_F(UserMgrInTest, AddGroupThrowsIfPreDefinedGroupAdd)
1098{
1099 EXPECT_THROW(
1100 createGroup("ipmi"),
1101 sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1102 EXPECT_THROW(
1103 createGroup("web"),
1104 sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1105 EXPECT_THROW(
1106 createGroup("redfish"),
1107 sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1108 EXPECT_THROW(
1109 createGroup("ssh"),
1110 sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
1111 EXPECT_THROW(
1112 createGroup("hostconsole"),
1113 sdbusplus::xyz::openbmc_project::User::Common::Error::GroupNameExists);
Nan Zhouda401fe2022-10-25 00:07:18 +00001114}
1115
1116TEST_F(UserMgrInTest, DeleteGroupThrowsIfGroupIsNotAllowedToChange)
1117{
1118 EXPECT_THROW(
1119 deleteGroup("ipmi"),
1120 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1121 EXPECT_THROW(
1122 deleteGroup("web"),
1123 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1124 EXPECT_THROW(
1125 deleteGroup("redfish"),
1126 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
1127 EXPECT_THROW(
1128 deleteGroup("ssh"),
1129 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
Ninad Palsule601d3db2023-03-09 10:27:37 -06001130 EXPECT_THROW(
1131 deleteGroup("hostconsole"),
1132 sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument);
Nan Zhouda401fe2022-10-25 00:07:18 +00001133}
1134
1135TEST_F(UserMgrInTest,
1136 CreateGroupThrowsInternalFailureWhenExecuteGroupCreateFails)
1137{
1138 EXPECT_CALL(*this, executeGroupCreation)
1139 .WillOnce(testing::Throw(
1140 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()));
1141 EXPECT_THROW(
1142 createGroup("openbmc_rfr_role1"),
1143 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
1144}
1145
1146TEST_F(UserMgrInTest,
1147 DeleteGroupThrowsInternalFailureWhenExecuteGroupDeleteFails)
1148{
1149 std::string groupName = "openbmc_rfr_role1";
1150 EXPECT_NO_THROW(UserMgr::createGroup(groupName));
1151 EXPECT_CALL(*this, executeGroupDeletion(testing::StrEq(groupName)))
1152 .WillOnce(testing::Throw(
1153 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure()))
1154 .WillOnce(testing::DoDefault());
1155
1156 EXPECT_THROW(
1157 deleteGroup(groupName),
1158 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure);
1159 EXPECT_NO_THROW(UserMgr::deleteGroup(groupName));
1160}
1161
1162TEST_F(UserMgrInTest, CheckAndThrowForGroupNotExist)
1163{
1164 EXPECT_THROW(deleteGroup("whatever"),
1165 sdbusplus::xyz::openbmc_project::User::Common::Error::
1166 GroupNameDoesNotExist);
1167}
1168
1169TEST(ReadAllGroupsOnSystemTest, OnlyReturnsPredefinedGroups)
1170{
1171 EXPECT_THAT(UserMgr::readAllGroupsOnSystem(),
Ninad Palsule601d3db2023-03-09 10:27:37 -06001172 testing::UnorderedElementsAre("web", "redfish", "ipmi", "ssh",
1173 "hostconsole"));
Nan Zhouda401fe2022-10-25 00:07:18 +00001174}
1175
raviteja-b8cc44052019-02-27 23:29:36 -06001176} // namespace user
1177} // namespace phosphor