#include "config.h" #include "phosphor-ldap-config/ldap_config.hpp" #include "phosphor-ldap-config/ldap_config_mgr.hpp" #include #include #include #include #include #include #include #include #include #include #include namespace phosphor { namespace ldap { namespace fs = std::filesystem; namespace ldap_base = sdbusplus::xyz::openbmc_project::User::Ldap::server; using Config = phosphor::ldap::Config; static constexpr const char* dbusPersistFile = "Config"; class TestLDAPConfig : public testing::Test { public: TestLDAPConfig() : bus(sdbusplus::bus::new_default()) { } void SetUp() override { using namespace phosphor::ldap; char tmpldap[] = "/tmp/ldap_test.XXXXXX"; dir = fs::path(mkdtemp(tmpldap)); fs::path tslCacertFilePath{TLS_CACERT_FILE}; tslCacertFile = tslCacertFilePath.filename().c_str(); fs::path confFilePath{LDAP_CONFIG_FILE}; ldapconfFile = confFilePath.filename().c_str(); std::fstream fs; fs.open(dir / defaultNslcdFile, std::fstream::out); fs.close(); fs.open(dir / nsSwitchFile, std::fstream::out); fs.close(); } void TearDown() override { fs::remove_all(dir); } protected: fs::path dir; std::string tslCacertFile; std::string ldapconfFile; sdbusplus::bus::bus bus; }; class MockConfigMgr : public phosphor::ldap::ConfigMgr { public: MockConfigMgr(sdbusplus::bus::bus& bus, const char* path, const char* filePath, const char* dbusPersistentFile, const char* caCertFile) : phosphor::ldap::ConfigMgr(bus, path, filePath, dbusPersistentFile, caCertFile) { } MOCK_METHOD1(restartService, void(const std::string& service)); MOCK_METHOD1(stopService, void(const std::string& service)); std::unique_ptr& getOpenLdapConfigPtr() { return openLDAPConfigPtr; } std::string configBindPassword() { return getADConfigPtr()->lDAPBindPassword; } std::unique_ptr& getADConfigPtr() { return ADConfigPtr; } void restore() { phosphor::ldap::ConfigMgr::restore(); return; } void createDefaultObjects() { phosphor::ldap::ConfigMgr::createDefaultObjects(); } friend class TestLDAPConfig; }; TEST_F(TestLDAPConfig, testCreate) { auto configFilePath = std::string(dir.c_str()) + "/" + ldapconfFile; auto tlsCacertfile = std::string(dir.c_str()) + "/" + tslCacertFile; auto dbusPersistentFilePath = std::string(dir.c_str()); if (fs::exists(configFilePath)) { fs::remove(configFilePath); } EXPECT_FALSE(fs::exists(configFilePath)); MockConfigMgr manager(bus, LDAP_CONFIG_ROOT, configFilePath.c_str(), dbusPersistentFilePath.c_str(), tlsCacertfile.c_str()); EXPECT_CALL(manager, stopService("nslcd.service")).Times(2); EXPECT_CALL(manager, restartService("nslcd.service")).Times(2); EXPECT_CALL(manager, restartService("nscd.service")).Times(2); manager.createConfig( "ldap://9.194.251.136/", "cn=Users,dc=com", "cn=Users,dc=corp", "MyLdap12", ldap_base::Create::SearchScope::sub, ldap_base::Create::Type::ActiveDirectory, "uid", "gid"); manager.getADConfigPtr()->enabled(true); manager.createConfig("ldap://9.194.251.137/", "cn=Users", "cn=Users,dc=test", "MyLdap123", ldap_base::Create::SearchScope::sub, ldap_base::Create::Type::OpenLdap, "uid", "gid"); manager.getOpenLdapConfigPtr()->enabled(false); // Below setting of username/groupname attr is to make sure // that in-active config should not call the start/stop service. manager.getOpenLdapConfigPtr()->userNameAttribute("abc"); EXPECT_EQ(manager.getOpenLdapConfigPtr()->userNameAttribute(), "abc"); manager.getOpenLdapConfigPtr()->groupNameAttribute("def"); EXPECT_EQ(manager.getOpenLdapConfigPtr()->groupNameAttribute(), "def"); EXPECT_TRUE(fs::exists(configFilePath)); EXPECT_EQ(manager.getADConfigPtr()->lDAPServerURI(), "ldap://9.194.251.136/"); EXPECT_EQ(manager.getADConfigPtr()->lDAPBindDN(), "cn=Users,dc=com"); EXPECT_EQ(manager.getADConfigPtr()->lDAPBaseDN(), "cn=Users,dc=corp"); EXPECT_EQ(manager.getADConfigPtr()->lDAPSearchScope(), ldap_base::Config::SearchScope::sub); EXPECT_EQ(manager.getADConfigPtr()->lDAPType(), ldap_base::Config::Type::ActiveDirectory); EXPECT_EQ(manager.getADConfigPtr()->userNameAttribute(), "uid"); EXPECT_EQ(manager.getADConfigPtr()->groupNameAttribute(), "gid"); EXPECT_EQ(manager.getADConfigPtr()->lDAPBindDNPassword(), ""); EXPECT_EQ(manager.configBindPassword(), "MyLdap12"); // change the password manager.getADConfigPtr()->lDAPBindDNPassword("MyLdap14"); EXPECT_EQ(manager.getADConfigPtr()->lDAPBindDNPassword(), ""); EXPECT_EQ(manager.configBindPassword(), "MyLdap14"); } TEST_F(TestLDAPConfig, testDefaultObject) { auto configFilePath = std::string(dir.c_str()) + "/" + ldapconfFile; auto tlsCacertfile = std::string(dir.c_str()) + "/" + tslCacertFile; auto dbusPersistentFilePath = std::string(dir.c_str()); if (fs::exists(configFilePath)) { fs::remove(configFilePath); } EXPECT_FALSE(fs::exists(configFilePath)); MockConfigMgr manager(bus, LDAP_CONFIG_ROOT, configFilePath.c_str(), dbusPersistentFilePath.c_str(), tlsCacertfile.c_str()); manager.createDefaultObjects(); EXPECT_NE(nullptr, manager.getADConfigPtr()); EXPECT_NE(nullptr, manager.getOpenLdapConfigPtr()); EXPECT_EQ(manager.getADConfigPtr()->lDAPType(), ldap_base::Config::Type::ActiveDirectory); EXPECT_EQ(manager.getOpenLdapConfigPtr()->lDAPType(), ldap_base::Config::Type::OpenLdap); } TEST_F(TestLDAPConfig, testRestores) { auto configFilePath = std::string(dir.c_str()) + "/" + ldapconfFile; auto tlsCacertfile = std::string(dir.c_str()) + "/" + tslCacertFile; auto dbusPersistentFilePath = std::string(dir.c_str()); if (fs::exists(configFilePath)) { fs::remove(configFilePath); } EXPECT_FALSE(fs::exists(configFilePath)); MockConfigMgr* managerPtr = new MockConfigMgr( bus, LDAP_CONFIG_ROOT, configFilePath.c_str(), dbusPersistentFilePath.c_str(), tlsCacertfile.c_str()); EXPECT_CALL(*managerPtr, stopService("nslcd.service")).Times(1); EXPECT_CALL(*managerPtr, restartService("nslcd.service")).Times(1); EXPECT_CALL(*managerPtr, restartService("nscd.service")).Times(1); managerPtr->createConfig( "ldap://9.194.251.138/", "cn=Users,dc=com", "cn=Users,dc=corp", "MyLdap12", ldap_base::Create::SearchScope::sub, ldap_base::Create::Type::ActiveDirectory, "uid", "gid"); managerPtr->getADConfigPtr()->enabled(false); EXPECT_FALSE(fs::exists(configFilePath)); EXPECT_FALSE(managerPtr->getADConfigPtr()->enabled()); managerPtr->getADConfigPtr()->enabled(true); EXPECT_TRUE(fs::exists(configFilePath)); // Restore from configFilePath managerPtr->restore(); // validate restored properties EXPECT_TRUE(managerPtr->getADConfigPtr()->enabled()); EXPECT_EQ(managerPtr->getADConfigPtr()->lDAPServerURI(), "ldap://9.194.251.138/"); EXPECT_EQ(managerPtr->getADConfigPtr()->lDAPBindDN(), "cn=Users,dc=com"); EXPECT_EQ(managerPtr->getADConfigPtr()->lDAPBaseDN(), "cn=Users,dc=corp"); EXPECT_EQ(managerPtr->getADConfigPtr()->lDAPSearchScope(), ldap_base::Config::SearchScope::sub); EXPECT_EQ(managerPtr->getADConfigPtr()->lDAPType(), ldap_base::Config::Type::ActiveDirectory); EXPECT_EQ(managerPtr->getADConfigPtr()->userNameAttribute(), "uid"); EXPECT_EQ(managerPtr->getADConfigPtr()->groupNameAttribute(), "gid"); EXPECT_EQ(managerPtr->getADConfigPtr()->lDAPBindDNPassword(), ""); EXPECT_EQ(managerPtr->configBindPassword(), "MyLdap12"); delete managerPtr; } TEST_F(TestLDAPConfig, testLDAPServerURI) { auto configFilePath = std::string(dir.c_str()) + "/" + ldapconfFile; auto tlsCacertfile = std::string(dir.c_str()) + "/" + tslCacertFile; auto dbusPersistentFilePath = std::string(dir.c_str()); if (fs::exists(configFilePath)) { fs::remove(configFilePath); } EXPECT_FALSE(fs::exists(configFilePath)); MockConfigMgr* managerPtr = new MockConfigMgr( bus, LDAP_CONFIG_ROOT, configFilePath.c_str(), dbusPersistentFilePath.c_str(), tlsCacertfile.c_str()); EXPECT_CALL(*managerPtr, stopService("nslcd.service")).Times(1); EXPECT_CALL(*managerPtr, restartService("nslcd.service")).Times(2); EXPECT_CALL(*managerPtr, restartService("nscd.service")).Times(1); managerPtr->createConfig( "ldap://9.194.251.138/", "cn=Users,dc=com", "cn=Users,dc=corp", "MyLdap12", ldap_base::Create::SearchScope::sub, ldap_base::Create::Type::ActiveDirectory, "attr1", "attr2"); managerPtr->getADConfigPtr()->enabled(true); // Change LDAP Server URI managerPtr->getADConfigPtr()->lDAPServerURI("ldap://9.194.251.139/"); EXPECT_EQ(managerPtr->getADConfigPtr()->lDAPServerURI(), "ldap://9.194.251.139/"); // Change LDAP Server URI to make it secure EXPECT_THROW( managerPtr->getADConfigPtr()->lDAPServerURI("ldaps://9.194.251.139/"), NoCACertificate); // check once again EXPECT_EQ(managerPtr->getADConfigPtr()->lDAPServerURI(), "ldap://9.194.251.139/"); managerPtr->restore(); // Check LDAP Server URI EXPECT_EQ(managerPtr->getADConfigPtr()->lDAPServerURI(), "ldap://9.194.251.139/"); delete managerPtr; } TEST_F(TestLDAPConfig, testLDAPBindDN) { auto configFilePath = std::string(dir.c_str()) + "/" + ldapconfFile; auto tlsCacertfile = std::string(dir.c_str()) + "/" + tslCacertFile; auto dbusPersistentFilePath = std::string(dir.c_str()); if (fs::exists(configFilePath)) { fs::remove(configFilePath); } EXPECT_FALSE(fs::exists(configFilePath)); MockConfigMgr* managerPtr = new MockConfigMgr( bus, LDAP_CONFIG_ROOT, configFilePath.c_str(), dbusPersistentFilePath.c_str(), tlsCacertfile.c_str()); EXPECT_CALL(*managerPtr, stopService("nslcd.service")).Times(1); EXPECT_CALL(*managerPtr, restartService("nslcd.service")).Times(2); EXPECT_CALL(*managerPtr, restartService("nscd.service")).Times(1); managerPtr->createConfig( "ldap://9.194.251.138/", "cn=Users,dc=com", "cn=Users,dc=corp", "MyLdap12", ldap_base::Create::SearchScope::sub, ldap_base::Create::Type::ActiveDirectory, "attr1", "attr2"); managerPtr->getADConfigPtr()->enabled(true); // Change LDAP BindDN managerPtr->getADConfigPtr()->lDAPBindDN( "cn=Administrator,cn=Users,dc=corp,dc=ibm,dc=com"); EXPECT_EQ(managerPtr->getADConfigPtr()->lDAPBindDN(), "cn=Administrator,cn=Users,dc=corp,dc=ibm,dc=com"); // Change LDAP BindDN EXPECT_THROW( { try { managerPtr->getADConfigPtr()->lDAPBindDN(""); } catch (const InvalidArgument& e) { throw; } }, InvalidArgument); managerPtr->restore(); // Check LDAP BindDN after restoring EXPECT_EQ(managerPtr->getADConfigPtr()->lDAPBindDN(), "cn=Administrator,cn=Users,dc=corp,dc=ibm,dc=com"); delete managerPtr; } TEST_F(TestLDAPConfig, testLDAPBaseDN) { auto configFilePath = std::string(dir.c_str()) + "/" + ldapconfFile; auto tlsCacertfile = std::string(dir.c_str()) + "/" + tslCacertFile; auto dbusPersistentFilePath = std::string(dir.c_str()); if (fs::exists(configFilePath)) { fs::remove(configFilePath); } EXPECT_FALSE(fs::exists(configFilePath)); MockConfigMgr* managerPtr = new MockConfigMgr( bus, LDAP_CONFIG_ROOT, configFilePath.c_str(), dbusPersistentFilePath.c_str(), tlsCacertfile.c_str()); EXPECT_CALL(*managerPtr, stopService("nslcd.service")).Times(1); EXPECT_CALL(*managerPtr, restartService("nslcd.service")).Times(2); EXPECT_CALL(*managerPtr, restartService("nscd.service")).Times(1); managerPtr->createConfig( "ldap://9.194.251.138/", "cn=Users,dc=com", "cn=Users,dc=corp", "MyLdap12", ldap_base::Create::SearchScope::sub, ldap_base::Create::Type::ActiveDirectory, "attr1", "attr2"); managerPtr->getADConfigPtr()->enabled(true); // Change LDAP BaseDN managerPtr->getADConfigPtr()->lDAPBaseDN( "cn=Administrator,cn=Users,dc=corp,dc=ibm,dc=com"); EXPECT_EQ(managerPtr->getADConfigPtr()->lDAPBaseDN(), "cn=Administrator,cn=Users,dc=corp,dc=ibm,dc=com"); // Change LDAP BaseDN EXPECT_THROW( { try { managerPtr->getADConfigPtr()->lDAPBaseDN(""); } catch (const InvalidArgument& e) { throw; } }, InvalidArgument); managerPtr->restore(); // Check LDAP BaseDN after restoring EXPECT_EQ(managerPtr->getADConfigPtr()->lDAPBaseDN(), "cn=Administrator,cn=Users,dc=corp,dc=ibm,dc=com"); delete managerPtr; } TEST_F(TestLDAPConfig, testSearchScope) { auto configFilePath = std::string(dir.c_str()) + "/" + ldapconfFile; auto tlsCacertfile = std::string(dir.c_str()) + "/" + tslCacertFile; auto dbusPersistentFilePath = std::string(dir.c_str()); if (fs::exists(configFilePath)) { fs::remove(configFilePath); } EXPECT_FALSE(fs::exists(configFilePath)); MockConfigMgr* managerPtr = new MockConfigMgr( bus, LDAP_CONFIG_ROOT, configFilePath.c_str(), dbusPersistentFilePath.c_str(), tlsCacertfile.c_str()); EXPECT_CALL(*managerPtr, stopService("nslcd.service")).Times(1); EXPECT_CALL(*managerPtr, restartService("nslcd.service")).Times(2); EXPECT_CALL(*managerPtr, restartService("nscd.service")).Times(1); managerPtr->createConfig( "ldap://9.194.251.138/", "cn=Users,dc=com", "cn=Users,dc=corp", "MyLdap12", ldap_base::Create::SearchScope::sub, ldap_base::Create::Type::ActiveDirectory, "attr1", "attr2"); managerPtr->getADConfigPtr()->enabled(true); // Change LDAP SearchScope managerPtr->getADConfigPtr()->lDAPSearchScope( ldap_base::Config::SearchScope::one); EXPECT_EQ(managerPtr->getADConfigPtr()->lDAPSearchScope(), ldap_base::Config::SearchScope::one); managerPtr->restore(); // Check LDAP SearchScope after restoring EXPECT_EQ(managerPtr->getADConfigPtr()->lDAPSearchScope(), ldap_base::Config::SearchScope::one); delete managerPtr; } TEST_F(TestLDAPConfig, testLDAPType) { auto configFilePath = std::string(dir.c_str()) + "/" + ldapconfFile; auto tlsCacertfile = std::string(dir.c_str()) + "/" + tslCacertFile; auto dbusPersistentFilePath = std::string(dir.c_str()); if (fs::exists(configFilePath)) { fs::remove(configFilePath); } EXPECT_FALSE(fs::exists(configFilePath)); MockConfigMgr* managerPtr = new MockConfigMgr( bus, LDAP_CONFIG_ROOT, configFilePath.c_str(), dbusPersistentFilePath.c_str(), tlsCacertfile.c_str()); EXPECT_CALL(*managerPtr, stopService("nslcd.service")).Times(1); EXPECT_CALL(*managerPtr, restartService("nslcd.service")).Times(1); EXPECT_CALL(*managerPtr, restartService("nscd.service")).Times(1); managerPtr->createConfig( "ldap://9.194.251.138/", "cn=Users,dc=com", "cn=Users,dc=corp", "MyLdap12", ldap_base::Create::SearchScope::sub, ldap_base::Create::Type::ActiveDirectory, "attr1", "attr2"); managerPtr->getADConfigPtr()->enabled(true); // Change LDAP type // will not be changed EXPECT_THROW(managerPtr->getADConfigPtr()->lDAPType( ldap_base::Config::Type::OpenLdap), NotAllowed); EXPECT_EQ(managerPtr->getADConfigPtr()->lDAPType(), ldap_base::Config::Type::ActiveDirectory); managerPtr->restore(); // Check LDAP type after restoring EXPECT_EQ(managerPtr->getADConfigPtr()->lDAPType(), ldap_base::Config::Type::ActiveDirectory); delete managerPtr; } TEST_F(TestLDAPConfig, filePermission) { auto configFilePath = std::string(dir.c_str()) + "/" + ldapconfFile; auto tlsCacertfile = std::string(dir.c_str()) + "/" + tslCacertFile; auto dbusPersistentFilePath = std::string(dir.c_str()); if (fs::exists(configFilePath)) { fs::remove(configFilePath); } EXPECT_FALSE(fs::exists(configFilePath)); MockConfigMgr* managerPtr = new MockConfigMgr( bus, LDAP_CONFIG_ROOT, configFilePath.c_str(), dbusPersistentFilePath.c_str(), tlsCacertfile.c_str()); EXPECT_CALL(*managerPtr, stopService("nslcd.service")).Times(1); EXPECT_CALL(*managerPtr, restartService("nslcd.service")).Times(1); EXPECT_CALL(*managerPtr, restartService("nscd.service")).Times(1); managerPtr->createConfig( "ldap://9.194.251.138/", "cn=Users,dc=com", "cn=Users,dc=corp", "MyLdap12", ldap_base::Create::SearchScope::sub, ldap_base::Create::Type::ActiveDirectory, "attr1", "attr2"); managerPtr->getADConfigPtr()->enabled(true); // Permission of the persistent file should be 640 // Others should not be allowed to read. auto permission = fs::perms::owner_read | fs::perms::owner_write | fs::perms::group_read; auto persistFilepath = std::string(dir.c_str()); persistFilepath += ADDbusObjectPath; persistFilepath += "/config"; EXPECT_EQ(fs::status(persistFilepath).permissions(), permission); delete managerPtr; } } // namespace ldap } // namespace phosphor