blob: d2ef4e0c3d4f3bc6996b8679088a205bc608f037 [file] [log] [blame]
Ratan Guptae1f4db62019-04-11 18:57:42 +05301#include "ldap_config_mgr.hpp"
Ratan Guptae1f4db62019-04-11 18:57:42 +05302
Patrick Williams9638afb2021-02-22 17:16:24 -06003#include "ldap_config.hpp"
Ratan Guptae1f4db62019-04-11 18:57:42 +05304#include "utils.hpp"
Patrick Williams9638afb2021-02-22 17:16:24 -06005
Ratan Guptae1f4db62019-04-11 18:57:42 +05306#include <filesystem>
7#include <fstream>
8#include <sstream>
9
10namespace phosphor
11{
12namespace ldap
13{
14
Alexander Filippov372c5662021-06-30 20:23:39 +030015constexpr auto nslcdService = "nslcd.service";
Ratan Guptae1f4db62019-04-11 18:57:42 +053016constexpr auto nscdService = "nscd.service";
Nan Zhou78d85042022-08-29 17:50:22 +000017constexpr auto ldapScheme = "ldap";
18constexpr auto ldapsScheme = "ldaps";
Ratan Guptae1f4db62019-04-11 18:57:42 +053019
Ratan Guptae1f4db62019-04-11 18:57:42 +053020using namespace sdbusplus::xyz::openbmc_project::Common::Error;
21namespace fs = std::filesystem;
22using Argument = xyz::openbmc_project::Common::InvalidArgument;
Ratan Guptac5481d12019-04-12 18:31:05 +053023using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
24using NotAllowedArgument = xyz::openbmc_project::Common::NotAllowed;
Ratan Guptae1f4db62019-04-11 18:57:42 +053025
26using Line = std::string;
27using Key = std::string;
28using Val = std::string;
29using ConfigInfo = std::map<Key, Val>;
30
31void ConfigMgr::startOrStopService(const std::string& service, bool start)
32{
33 if (start)
34 {
35 restartService(service);
36 }
37 else
38 {
39 stopService(service);
40 }
41}
42
43void ConfigMgr::restartService(const std::string& service)
44{
45 try
46 {
47 auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
48 SYSTEMD_INTERFACE, "RestartUnit");
49 method.append(service.c_str(), "replace");
50 bus.call_noreply(method);
51 }
Patrick Williamsb3ef4e12022-07-22 19:26:55 -050052 catch (const sdbusplus::exception_t& ex)
Ratan Guptae1f4db62019-04-11 18:57:42 +053053 {
Jiaqing Zhao11ec6662022-07-05 20:55:34 +080054 lg2::error("Failed to restart service {SERVICE}: {ERR}", "SERVICE",
55 service, "ERR", ex);
Ratan Guptae1f4db62019-04-11 18:57:42 +053056 elog<InternalFailure>();
57 }
58}
59void ConfigMgr::stopService(const std::string& service)
60{
61 try
62 {
63 auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
64 SYSTEMD_INTERFACE, "StopUnit");
65 method.append(service.c_str(), "replace");
66 bus.call_noreply(method);
67 }
Patrick Williamsb3ef4e12022-07-22 19:26:55 -050068 catch (const sdbusplus::exception_t& ex)
Ratan Guptae1f4db62019-04-11 18:57:42 +053069 {
Jiaqing Zhao11ec6662022-07-05 20:55:34 +080070 lg2::error("Failed to stop service {SERVICE}: {ERR}", "SERVICE",
71 service, "ERR", ex);
Ratan Guptae1f4db62019-04-11 18:57:42 +053072 elog<InternalFailure>();
73 }
74}
75
Ratan Guptae1f4db62019-04-11 18:57:42 +053076std::string ConfigMgr::createConfig(
Patrick Williamse6500a42021-05-01 05:58:23 -050077 std::string ldapServerURI, std::string ldapBindDN, std::string ldapBaseDN,
78 std::string ldapBindDNPassword, CreateIface::SearchScope ldapSearchScope,
79 CreateIface::Create::Type ldapType, std::string groupNameAttribute,
Ratan Guptae1f4db62019-04-11 18:57:42 +053080 std::string userNameAttribute)
81{
82 bool secureLDAP = false;
83
Nan Zhou78d85042022-08-29 17:50:22 +000084 if (isValidLDAPURI(ldapServerURI, ldapsScheme))
Ratan Guptae1f4db62019-04-11 18:57:42 +053085 {
86 secureLDAP = true;
87 }
Nan Zhou78d85042022-08-29 17:50:22 +000088 else if (isValidLDAPURI(ldapServerURI, ldapScheme))
Ratan Guptae1f4db62019-04-11 18:57:42 +053089 {
90 secureLDAP = false;
91 }
92 else
93 {
Jiaqing Zhao11ec6662022-07-05 20:55:34 +080094 lg2::error("Bad LDAP Server URI {URI}", "URI", ldapServerURI);
Patrick Williamse6500a42021-05-01 05:58:23 -050095 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ldapServerURI"),
96 Argument::ARGUMENT_VALUE(ldapServerURI.c_str()));
Ratan Guptae1f4db62019-04-11 18:57:42 +053097 }
98
99 if (secureLDAP && !fs::exists(tlsCacertFile.c_str()))
100 {
Jiaqing Zhao11ec6662022-07-05 20:55:34 +0800101 lg2::error("LDAP server CA certificate not found at {PATH}", "PATH",
102 tlsCacertFile);
Ratan Guptae1f4db62019-04-11 18:57:42 +0530103 elog<NoCACertificate>();
104 }
105
Patrick Williamse6500a42021-05-01 05:58:23 -0500106 if (ldapBindDN.empty())
Ratan Guptae1f4db62019-04-11 18:57:42 +0530107 {
Jiaqing Zhao11ec6662022-07-05 20:55:34 +0800108 lg2::error("'{BINDDN}' is not a valid LDAP BindDN", "BINDDN",
109 ldapBindDN);
Ratan Guptae1f4db62019-04-11 18:57:42 +0530110 elog<InvalidArgument>(Argument::ARGUMENT_NAME("LDAPBindDN"),
Patrick Williamse6500a42021-05-01 05:58:23 -0500111 Argument::ARGUMENT_VALUE(ldapBindDN.c_str()));
Ratan Guptae1f4db62019-04-11 18:57:42 +0530112 }
113
Patrick Williamse6500a42021-05-01 05:58:23 -0500114 if (ldapBaseDN.empty())
Ratan Guptae1f4db62019-04-11 18:57:42 +0530115 {
Jiaqing Zhao11ec6662022-07-05 20:55:34 +0800116 lg2::error("'{BASEDN}' is not a valid LDAP BaseDN", "BASEDN",
117 ldapBaseDN);
Ratan Guptae1f4db62019-04-11 18:57:42 +0530118 elog<InvalidArgument>(Argument::ARGUMENT_NAME("LDAPBaseDN"),
Patrick Williamse6500a42021-05-01 05:58:23 -0500119 Argument::ARGUMENT_VALUE(ldapBaseDN.c_str()));
Ratan Guptae1f4db62019-04-11 18:57:42 +0530120 }
121
Ratan Gupta27d4c012019-04-12 13:03:35 +0530122 // With current implementation we support only two default LDAP server.
123 // which will be always there but when the support comes for additional
124 // account providers then the create config would be used to create the
125 // additional config.
Ratan Guptae1f4db62019-04-11 18:57:42 +0530126
Ratan Gupta27d4c012019-04-12 13:03:35 +0530127 std::string objPath;
Ratan Guptae1f4db62019-04-11 18:57:42 +0530128
Patrick Williamse6500a42021-05-01 05:58:23 -0500129 if (static_cast<ConfigIface::Type>(ldapType) == ConfigIface::Type::OpenLdap)
Ratan Gupta27d4c012019-04-12 13:03:35 +0530130 {
131 openLDAPConfigPtr.reset(nullptr);
132 objPath = openLDAPDbusObjectPath;
133 openLDAPConfigPtr = std::make_unique<Config>(
134 bus, objPath.c_str(), configFilePath.c_str(), tlsCacertFile.c_str(),
Patrick Williamse6500a42021-05-01 05:58:23 -0500135 tlsCertFile.c_str(), secureLDAP, ldapServerURI, ldapBindDN,
136 ldapBaseDN, std::move(ldapBindDNPassword),
137 static_cast<ConfigIface::SearchScope>(ldapSearchScope),
138 static_cast<ConfigIface::Type>(ldapType), false, groupNameAttribute,
Ratan Gupta27d4c012019-04-12 13:03:35 +0530139 userNameAttribute, *this);
140 }
141 else
142 {
143 ADConfigPtr.reset(nullptr);
Nan Zhou78d85042022-08-29 17:50:22 +0000144 objPath = adDbusObjectPath;
Ratan Gupta27d4c012019-04-12 13:03:35 +0530145 ADConfigPtr = std::make_unique<Config>(
146 bus, objPath.c_str(), configFilePath.c_str(), tlsCacertFile.c_str(),
Patrick Williamse6500a42021-05-01 05:58:23 -0500147 tlsCertFile.c_str(), secureLDAP, ldapServerURI, ldapBindDN,
148 ldapBaseDN, std::move(ldapBindDNPassword),
149 static_cast<ConfigIface::SearchScope>(ldapSearchScope),
150 static_cast<ConfigIface::Type>(ldapType), false, groupNameAttribute,
Ratan Gupta27d4c012019-04-12 13:03:35 +0530151 userNameAttribute, *this);
152 }
Ratan Guptae1f4db62019-04-11 18:57:42 +0530153 restartService(nscdService);
154 return objPath;
155}
156
Ratan Gupta27d4c012019-04-12 13:03:35 +0530157void ConfigMgr::createDefaultObjects()
Ratan Guptae1f4db62019-04-11 18:57:42 +0530158{
Ratan Gupta27d4c012019-04-12 13:03:35 +0530159 if (!openLDAPConfigPtr)
Ratan Guptae1f4db62019-04-11 18:57:42 +0530160 {
Ratan Gupta27d4c012019-04-12 13:03:35 +0530161 openLDAPConfigPtr = std::make_unique<Config>(
162 bus, openLDAPDbusObjectPath.c_str(), configFilePath.c_str(),
Ratan Guptaab4fcb42019-04-29 19:39:51 +0530163 tlsCacertFile.c_str(), tlsCertFile.c_str(),
164 ConfigIface::Type::OpenLdap, *this);
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530165 openLDAPConfigPtr->emit_object_added();
Ratan Guptae1f4db62019-04-11 18:57:42 +0530166 }
Ratan Gupta27d4c012019-04-12 13:03:35 +0530167 if (!ADConfigPtr)
Ratan Guptae1f4db62019-04-11 18:57:42 +0530168 {
Ratan Gupta27d4c012019-04-12 13:03:35 +0530169 ADConfigPtr = std::make_unique<Config>(
Nan Zhou78d85042022-08-29 17:50:22 +0000170 bus, adDbusObjectPath.c_str(), configFilePath.c_str(),
Ratan Guptaab4fcb42019-04-29 19:39:51 +0530171 tlsCacertFile.c_str(), tlsCertFile.c_str(),
172 ConfigIface::Type::ActiveDirectory, *this);
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530173 ADConfigPtr->emit_object_added();
174 }
175}
176
Ratan Guptac5481d12019-04-12 18:31:05 +0530177bool ConfigMgr::enableService(Config& config, bool value)
178{
179 if (value)
180 {
181 if (openLDAPConfigPtr && openLDAPConfigPtr->enabled())
182 {
183 elog<NotAllowed>(NotAllowedArgument::REASON(
184 "OpenLDAP service is already active"));
185 }
186 if (ADConfigPtr && ADConfigPtr->enabled())
187 {
188 elog<NotAllowed>(NotAllowedArgument::REASON(
189 "ActiveDirectory service is already active"));
190 }
191 }
192 return config.enableService(value);
193}
194
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530195void ConfigMgr::restore()
196{
197 createDefaultObjects();
198 // Restore the ldap config and their mappings
199 if (ADConfigPtr->deserialize())
200 {
Ratan Gupta7b04c352019-04-12 21:46:29 +0530201 // Restore the role mappings
202 ADConfigPtr->restoreRoleMapping();
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530203 ADConfigPtr->emit_object_added();
204 }
205 if (openLDAPConfigPtr->deserialize())
206 {
Ratan Gupta7b04c352019-04-12 21:46:29 +0530207 // Restore the role mappings
208 openLDAPConfigPtr->restoreRoleMapping();
Ratan Gupta21e88cb2019-04-12 17:15:52 +0530209 openLDAPConfigPtr->emit_object_added();
Ratan Guptae1f4db62019-04-11 18:57:42 +0530210 }
Alexander Filippov372c5662021-06-30 20:23:39 +0300211
212 startOrStopService(phosphor::ldap::nslcdService,
213 ADConfigPtr->enabled() || openLDAPConfigPtr->enabled());
Ratan Guptae1f4db62019-04-11 18:57:42 +0530214}
Ratan Gupta27d4c012019-04-12 13:03:35 +0530215
Ratan Guptae1f4db62019-04-11 18:57:42 +0530216} // namespace ldap
217} // namespace phosphor