1 #pragma once
2 
3 #include "config.h"
4 #include <xyz/openbmc_project/Object/Enable/server.hpp>
5 #include <xyz/openbmc_project/User/Ldap/Create/server.hpp>
6 #include <xyz/openbmc_project/User/Ldap/Config/server.hpp>
7 #include <xyz/openbmc_project/User/PrivilegeMapper/server.hpp>
8 #include <xyz/openbmc_project/Common/error.hpp>
9 #include "ldap_mapper_entry.hpp"
10 #include <phosphor-logging/log.hpp>
11 #include <phosphor-logging/elog.hpp>
12 #include <phosphor-logging/elog-errors.hpp>
13 #include <sdbusplus/bus.hpp>
14 #include <sdbusplus/server/object.hpp>
15 
16 #include <filesystem>
17 #include <set>
18 #include <string>
19 
20 namespace phosphor
21 {
22 namespace ldap
23 {
24 
25 using namespace phosphor::logging;
26 using namespace sdbusplus::xyz::openbmc_project::Common::Error;
27 using ConfigIface = sdbusplus::xyz::openbmc_project::User::Ldap::server::Config;
28 using EnableIface = sdbusplus::xyz::openbmc_project::Object::server::Enable;
29 using CreateIface = sdbusplus::server::object::object<
30     sdbusplus::xyz::openbmc_project::User::Ldap::server::Create>;
31 namespace fs = std::filesystem;
32 using MapperIface =
33     sdbusplus::xyz::openbmc_project::User::server::PrivilegeMapper;
34 
35 using Ifaces =
36     sdbusplus::server::object::object<ConfigIface, EnableIface, MapperIface>;
37 using ObjectPath = sdbusplus::message::object_path;
38 
39 namespace sdbusRule = sdbusplus::bus::match::rules;
40 
41 class ConfigMgr;
42 class MockConfigMgr;
43 
44 /** @class Config
45  *  @brief Configuration for LDAP.
46  *  @details concrete implementation of xyz.openbmc_project.User.Ldap.Config
47  *  API, in order to provide LDAP configuration.
48  */
49 class Config : public Ifaces
50 {
51   public:
52     Config() = delete;
53     ~Config() = default;
54     Config(const Config&) = delete;
55     Config& operator=(const Config&) = delete;
56     Config(Config&&) = default;
57     Config& operator=(Config&&) = default;
58 
59     /** @brief Constructor to put object onto bus at a D-Bus path.
60      *  @param[in] bus - Bus to attach to.
61      *  @param[in] path - The D-Bus object path to attach at.
62      *  @param[in] filePath - LDAP configuration file.
63      *  @param[in] caCertFile - LDAP's CA certificate file.
64      *  @param[in] certFile - LDAP's client certificate file.
65      *  @param[in] secureLDAP - Specifies whether to use SSL or not.
66      *  @param[in] lDAPServerURI - LDAP URI of the server.
67      *  @param[in] lDAPBindDN - distinguished name with which to bind.
68      *  @param[in] lDAPBaseDN -  distinguished name to use as search base.
69      *  @param[in] lDAPBindDNPassword - credentials with which to bind.
70      *  @param[in] lDAPSearchScope - the search scope.
71      *  @param[in] lDAPType - Specifies the LDAP server type which can be AD
72      *              or openLDAP.
73      *  @param[in] lDAPServiceEnabled - Specifies whether the service would be
74      *  enabled or not.
75      *  @param[in] groupNameAttribute - Specifies attribute name that contains
76      *             the name of the Group in the LDAP server.
77      *  @param[in] userNameAttribute - Specifies attribute name that contains
78      *             the username in the LDAP server.
79      *
80      *  @param[in] parent - parent of config object.
81      */
82 
83     Config(sdbusplus::bus::bus& bus, const char* path, const char* filePath,
84            const char* caCertFile, const char* certFile, bool secureLDAP,
85            std::string lDAPServerURI, std::string lDAPBindDN,
86            std::string lDAPBaseDN, std::string&& lDAPBindDNPassword,
87            ConfigIface::SearchScope lDAPSearchScope, ConfigIface::Type lDAPType,
88            bool lDAPServiceEnabled, std::string groupNameAttribute,
89            std::string userNameAttribute, ConfigMgr& parent);
90 
91     /** @brief Constructor to put object onto bus at a D-Bus path.
92      *  @param[in] bus - Bus to attach to.
93      *  @param[in] path - The D-Bus object path to attach at.
94      *  @param[in] filePath - LDAP configuration file.
95      *  @param[in] lDAPType - Specifies the LDAP server type which can be AD
96      *              or openLDAP.
97      *  @param[in] parent - parent of config object.
98      */
99     Config(sdbusplus::bus::bus& bus, const char* path, const char* filePath,
100            const char* caCertFile, const char* certFile,
101            ConfigIface::Type lDAPType, ConfigMgr& parent);
102 
103     using ConfigIface::groupNameAttribute;
104     using ConfigIface::lDAPBaseDN;
105     using ConfigIface::lDAPBindDN;
106     using ConfigIface::lDAPBindDNPassword;
107     using ConfigIface::lDAPSearchScope;
108     using ConfigIface::lDAPServerURI;
109     using ConfigIface::lDAPType;
110     using ConfigIface::setPropertyByName;
111     using ConfigIface::userNameAttribute;
112     using EnableIface::enabled;
113 
114     /** @brief Update the Server URI property.
115      *  @param[in] value - lDAPServerURI value to be updated.
116      *  @returns value of changed lDAPServerURI.
117      */
118     std::string lDAPServerURI(std::string value) override;
119 
120     /** @brief Update the BindDN property.
121      *  @param[in] value - lDAPBindDN value to be updated.
122      *  @returns value of changed lDAPBindDN.
123      */
124     std::string lDAPBindDN(std::string value) override;
125 
126     /** @brief Update the BaseDN property.
127      *  @param[in] value - lDAPBaseDN value to be updated.
128      *  @returns value of changed lDAPBaseDN.
129      */
130     std::string lDAPBaseDN(std::string value) override;
131 
132     /** @brief Update the Search scope property.
133      *  @param[in] value - lDAPSearchScope value to be updated.
134      *  @returns value of changed lDAPSearchScope.
135      */
136     ConfigIface::SearchScope
137         lDAPSearchScope(ConfigIface::SearchScope value) override;
138 
139     /** @brief Update the LDAP Type property.
140      *  @param[in] value - lDAPType value to be updated.
141      *  @returns value of changed lDAPType.
142      */
143     ConfigIface::Type lDAPType(ConfigIface::Type value) override;
144 
145     /** @brief Update the ldapServiceEnabled property.
146      *  @param[in] value - ldapServiceEnabled value to be updated.
147      *  @returns value of changed ldapServiceEnabled.
148      */
149     bool enabled(bool value) override;
150 
151     /** @brief Update the userNameAttribute property.
152      *  @param[in] value - userNameAttribute value to be updated.
153      *  @returns value of changed userNameAttribute.
154      */
155     std::string userNameAttribute(std::string value) override;
156 
157     /** @brief Update the groupNameAttribute property.
158      *  @param[in] value - groupNameAttribute value to be updated.
159      *  @returns value of changed groupNameAttribute.
160      */
161     std::string groupNameAttribute(std::string value) override;
162 
163     /** @brief Update the BindDNPasword property.
164      *  @param[in] value - lDAPBindDNPassword value to be updated.
165      *  @returns value of changed lDAPBindDNPassword.
166      */
167     std::string lDAPBindDNPassword(std::string value) override;
168 
169     /** @brief Function required by Cereal to perform deserialization.
170      *  @tparam Archive - Cereal archive type (binary in our case).
171      *  @param[in] archive - reference to Cereal archive.
172      *  @param[in] version - Class version that enables handling
173      *                       a serialized data across code levels
174      */
175     template <class Archive>
176     void load(Archive& archive, const std::uint32_t version);
177 
178     /** @brief Function required by Cereal to perform serialization.
179      *  @tparam Archive - Cereal archive type (binary in our case).
180      *  @param[in] archive - reference to Cereal archive.
181      *  @param[in] version - Class version that enables handling
182      *                       a serialized data across code levels
183      */
184     template <class Archive>
185     void save(Archive& archive, const std::uint32_t version) const;
186 
187     /** @brief Serialize and persist this object at the persist
188      *         location.
189      */
190     void serialize();
191 
192     /** @brief Deserialize LDAP config data from the persistent location
193      *         into this object
194      *  @return bool - true if the deserialization was successful, false
195      *                 otherwise.
196      */
197     bool deserialize();
198 
199     /** @brief enable or disable the service with the given value
200      *  @param[in] value - enable/disble
201      *  @returns value of changed status
202      */
203     bool enableService(bool value);
204 
205     /** @brief Creates a mapping for the group to the privilege
206      *
207      *  @param[in] groupName - Group Name to which the privilege needs to be
208      *                         assigned.
209      *  @param[in] privilege - The privilege role associated with the group.
210      *
211      *  @return On success return the D-Bus object path of the created privilege
212      *          mapper entry.
213      */
214     ObjectPath create(std::string groupName, std::string privilege) override;
215 
216     /** @brief Delete privilege mapping for LDAP group
217      *
218      *  This method deletes the privilege mapping
219      *
220      *  @param[in] id - id of the object which needs to be deleted.
221      */
222     void deletePrivilegeMapper(Id id);
223 
224     /** @brief Check if LDAP group privilege mapping requested is valid
225      *
226      *  Check if the privilege mapping already exists for the LDAP group name
227      *  and group name is empty.
228      *
229      *  @param[in] groupName - LDAP group name
230      *
231      *  @return throw exception if the conditions are not met.
232      */
233     void checkPrivilegeMapper(const std::string& groupName);
234 
235     /** @brief Check if the privilege level is a valid one
236      *
237      *  @param[in] privilege - Privilege level
238      *
239      *  @return throw exception if the conditions are not met.
240      */
241     void checkPrivilegeLevel(const std::string& privilege);
242 
243     /** @brief Construct LDAP mapper entry D-Bus objects from their persisted
244      *         representations.
245      */
246     void restoreRoleMapping();
247 
248   private:
249     bool secureLDAP;
250     std::string lDAPBindPassword{};
251     std::string tlsCacertFile{};
252     std::string tlsCertFile{};
253     std::string configFilePath{};
254     std::string objectPath{};
255     std::filesystem::path configPersistPath{};
256 
257     /** @brief Persistent sdbusplus D-Bus bus connection. */
258     sdbusplus::bus::bus& bus;
259 
260     /** @brief Create a new LDAP config file.
261      */
262     virtual void writeConfig();
263 
264     /** @brief reference to config manager object */
265     ConfigMgr& parent;
266 
267     /** @brief Id of the last privilege mapper entry */
268     Id entryId = 0;
269 
270     /** @brief container to hold privilege mapper objects */
271     std::map<Id, std::unique_ptr<LDAPMapperEntry>> PrivilegeMapperList;
272 
273     /** @brief available privileges container */
274     std::set<std::string> privMgr = {
275         "priv-admin",
276         "priv-operator",
277         "priv-user",
278         "priv-noaccess",
279     };
280 
281     /** @brief React to InterfaceAdded signal
282      *  @param[in] msg - sdbusplus message
283      */
284     void certificateInstalled(sdbusplus::message::message& msg);
285     sdbusplus::bus::match_t certificateInstalledSignal;
286 
287     sdbusplus::bus::match_t cacertificateInstalledSignal;
288 
289     /** @brief React to certificate changed signal
290      *  @param[in] msg - sdbusplus message
291      */
292     void certificateChanged(sdbusplus::message::message& msg);
293     sdbusplus::bus::match_t certificateChangedSignal;
294 
295     friend class MockConfigMgr;
296 };
297 
298 } // namespace ldap
299 } // namespace phosphor
300