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