1 #include "config.h"
2 
3 #include "certificate.hpp"
4 #include "certs_manager.hpp"
5 #include "csr.hpp"
6 
7 #include <openssl/bio.h>
8 #include <openssl/ossl_typ.h>
9 #include <openssl/pem.h>
10 #include <openssl/x509.h>
11 #include <systemd/sd-event.h>
12 #include <unistd.h>
13 
14 #include <cstdint>
15 #include <cstdio>
16 #include <cstdlib>
17 #include <filesystem>
18 #include <fstream>
19 #include <iostream>
20 #include <iterator>
21 #include <memory>
22 #include <new>
23 #include <sdbusplus/bus.hpp>
24 #include <sdeventplus/event.hpp>
25 #include <string>
26 #include <unordered_set>
27 #include <utility>
28 #include <vector>
29 #include <xyz/openbmc_project/Certs/error.hpp>
30 #include <xyz/openbmc_project/Common/error.hpp>
31 
32 #include <gmock/gmock.h>
33 #include <gtest/gtest.h>
34 
35 namespace phosphor::certs
36 {
37 namespace
38 {
39 namespace fs = std::filesystem;
40 using ::sdbusplus::xyz::openbmc_project::Certs::Error::InvalidCertificate;
41 using ::sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
42 using ::testing::Eq;
43 using ::testing::Return;
44 // Compares two files; returns true only if the two are the same
45 bool compareFiles(const std::string& file1, const std::string& file2)
46 {
47     std::ifstream f1(file1, std::ifstream::binary | std::ifstream::ate);
48     std::ifstream f2(file2, std::ifstream::binary | std::ifstream::ate);
49 
50     if (f1.fail() || f2.fail())
51     {
52         return false; // file problem
53     }
54 
55     if (f1.tellg() != f2.tellg())
56     {
57         return false; // size mismatch
58     }
59 
60     // seek back to beginning and use std::equal to compare contents
61     f1.seekg(0, std::ifstream::beg);
62     f2.seekg(0, std::ifstream::beg);
63     return std::equal(std::istreambuf_iterator<char>(f1.rdbuf()),
64                       std::istreambuf_iterator<char>(),
65                       std::istreambuf_iterator<char>(f2.rdbuf()));
66 }
67 
68 /**
69  * Class to generate certificate file and test verification of certificate file
70  */
71 class TestCertificates : public ::testing::Test
72 {
73   public:
74     TestCertificates() : bus(sdbusplus::bus::new_default())
75     {
76     }
77     void SetUp() override
78     {
79         char dirTemplate[] = "/tmp/FakeCerts.XXXXXX";
80         auto dirPtr = mkdtemp(dirTemplate);
81         if (dirPtr == nullptr)
82         {
83             throw std::bad_alloc();
84         }
85         certDir = std::string(dirPtr) + "/certs";
86         fs::create_directories(certDir);
87 
88         createNewCertificate();
89     }
90 
91     void TearDown() override
92     {
93         fs::remove_all(certDir);
94         fs::remove(certificateFile);
95         fs::remove(CSRFile);
96         fs::remove(privateKeyFile);
97         fs::remove_all("demoCA");
98     }
99 
100     void createNewCertificate(bool setNewCertId = false)
101     {
102         certificateFile = "cert.pem";
103         CSRFile = "domain.csr";
104         privateKeyFile = "privkey.pem";
105         rsaPrivateKeyFilePath = certDir + "/.rsaprivkey.pem";
106         std::string cmd = "openssl req -x509 -sha256 -newkey rsa:2048 ";
107         cmd += "-keyout cert.pem -out cert.pem -days 365000 -nodes";
108         cmd += " -subj /O=openbmc-project.xyz/CN=localhost";
109 
110         if (setNewCertId)
111         {
112             cmd += std::to_string(certId++);
113         }
114 
115         auto val = std::system(cmd.c_str());
116         if (val)
117         {
118             std::cout << "COMMAND Error: " << val << std::endl;
119         }
120     }
121 
122     void createNeverExpiredRootCertificate()
123     {
124         // remove the old cert
125         fs::remove(certificateFile);
126 
127         // The following routines create a cert that has NotBefore
128         // set to 1970/01/01 and NotAfter set to 9999/12/31 via the
129         // OpenSSL CA application.
130         certificateFile = "cert.pem";
131         ASSERT_EQ(std::system("mkdir -p demoCA"), 0);
132         ASSERT_EQ(std::system("mkdir -p demoCA/private/"), 0);
133         ASSERT_EQ(std::system("mkdir -p demoCA/newcerts/"), 0);
134         ASSERT_EQ(std::system("touch demoCA/index.txt"), 0);
135         ASSERT_EQ(std::system("echo 1000 > demoCA/serial"), 0);
136         ASSERT_EQ(
137             std::system(
138                 "openssl req -x509 -sha256 -newkey rsa:2048 -keyout "
139                 "demoCA/private/cakey.pem -out demoCA/cacert.pem -nodes "
140                 "-subj /O=openbmc-project.xyz/C=US/ST=CA/CN=localhost-ca"),
141             0);
142         ASSERT_EQ(std::system(
143                       "openssl req -new -newkey rsa:2048 -nodes -keyout "
144                       "demoCA/server.key -out demoCA/server.csr -subj "
145                       "/O=openbmc-project.xyz/C=US/ST=CA/CN=localhost-server"),
146                   0);
147         ASSERT_EQ(
148             std::system(
149                 "openssl ca -batch -startdate 19700101000000Z -enddate "
150                 "99991231235959Z -out cert.pem -infiles demoCA/server.csr"),
151             0);
152     }
153 
154     bool compareFiles(const std::string& file1, const std::string& file2)
155     {
156         std::ifstream f1(file1, std::ifstream::binary | std::ifstream::ate);
157         std::ifstream f2(file2, std::ifstream::binary | std::ifstream::ate);
158 
159         if (f1.fail() || f2.fail())
160         {
161             return false; // file problem
162         }
163 
164         if (f1.tellg() != f2.tellg())
165         {
166             return false; // size mismatch
167         }
168 
169         // seek back to beginning and use std::equal to compare contents
170         f1.seekg(0, std::ifstream::beg);
171         f2.seekg(0, std::ifstream::beg);
172         return std::equal(std::istreambuf_iterator<char>(f1.rdbuf()),
173                           std::istreambuf_iterator<char>(),
174                           std::istreambuf_iterator<char>(f2.rdbuf()));
175     }
176 
177     std::string getCertSubjectNameHash(const std::string& certFilePath)
178     {
179         std::unique_ptr<X509, decltype(&::X509_free)> cert(X509_new(),
180                                                            ::X509_free);
181         if (!cert)
182         {
183             std::string();
184         }
185 
186         std::unique_ptr<BIO, decltype(&::BIO_free)> bioCert(
187             BIO_new_file(certFilePath.c_str(), "rb"), ::BIO_free);
188         if (!bioCert)
189         {
190             std::string();
191         }
192 
193         X509* x509 = cert.get();
194         if (!PEM_read_bio_X509(bioCert.get(), &x509, nullptr, nullptr))
195         {
196             std::string();
197         }
198 
199         unsigned long hash = X509_subject_name_hash(cert.get());
200         static constexpr auto AUTH_CERT_HASH_LENGTH = 9;
201         char hashBuf[AUTH_CERT_HASH_LENGTH];
202         sprintf(hashBuf, "%08lx", hash);
203         return std::string(hashBuf);
204     }
205 
206   protected:
207     sdbusplus::bus::bus bus;
208     std::string certificateFile, CSRFile, privateKeyFile, rsaPrivateKeyFilePath;
209 
210     std::string certDir;
211     uint64_t certId;
212 };
213 
214 class MainApp
215 {
216   public:
217     MainApp(phosphor::certs::Manager* manager,
218             phosphor::certs::CSR* csr = nullptr) :
219         manager(manager),
220         csr_(csr)
221     {
222     }
223     void install(std::string& path)
224     {
225         manager->install(path);
226     }
227     void delete_()
228     {
229         manager->deleteAll();
230     }
231 
232     std::string generateCSR(std::vector<std::string> alternativeNames,
233                             std::string challengePassword, std::string city,
234                             std::string commonName, std::string contactPerson,
235                             std::string country, std::string email,
236                             std::string givenName, std::string initials,
237                             int64_t keyBitLength, std::string keyCurveId,
238                             std::string keyPairAlgorithm,
239                             std::vector<std::string> keyUsage,
240                             std::string organization,
241                             std::string organizationalUnit, std::string state,
242                             std::string surname, std::string unstructuredName)
243     {
244         return (manager->generateCSR(
245             alternativeNames, challengePassword, city, commonName,
246             contactPerson, country, email, givenName, initials, keyBitLength,
247             keyCurveId, keyPairAlgorithm, keyUsage, organization,
248             organizationalUnit, state, surname, unstructuredName));
249     }
250     std::string csr()
251     {
252         return (csr_->csr());
253     }
254     phosphor::certs::Manager* manager;
255     phosphor::certs::CSR* csr_;
256 };
257 
258 class ManagerInTest : public phosphor::certs::Manager
259 {
260   public:
261     static constexpr std::string_view unitToRestartInTest =
262         "xyz.openbmc_project.awesome-service";
263     ManagerInTest(sdbusplus::bus::bus& bus, sdeventplus::Event& event,
264                   const char* path, CertificateType type,
265                   const std::string& unit, const std::string& installPath) :
266         Manager(bus, event, path, type, unit, installPath)
267     {
268     }
269 
270     MOCK_METHOD(void, reloadOrReset, (const std::string&), (override));
271 };
272 
273 /** @brief Check if server install routine is invoked for server setup
274  */
275 TEST_F(TestCertificates, InvokeServerInstall)
276 {
277     std::string endpoint("https");
278     CertificateType type = CertificateType::Server;
279     std::string installPath(certDir + "/" + certificateFile);
280     std::string verifyPath(installPath);
281     std::string verifyUnit(ManagerInTest::unitToRestartInTest);
282     auto objPath = std::string(objectNamePrefix) + '/' +
283                    certificateTypeToString(type) + '/' + endpoint;
284     auto event = sdeventplus::Event::get_default();
285     // Attach the bus to sd_event to service user requests
286     bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
287     ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit,
288                           installPath);
289     EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest)))
290         .WillOnce(Return());
291     MainApp mainApp(&manager);
292     mainApp.install(certificateFile);
293     EXPECT_TRUE(fs::exists(verifyPath));
294 }
295 
296 /** @brief Check if client install routine is invoked for client setup
297  */
298 TEST_F(TestCertificates, InvokeClientInstall)
299 {
300     std::string endpoint("ldap");
301     CertificateType type = CertificateType::Server;
302     std::string installPath(certDir + "/" + certificateFile);
303     std::string verifyPath(installPath);
304     std::string verifyUnit(ManagerInTest::unitToRestartInTest);
305     auto objPath = std::string(objectNamePrefix) + '/' +
306                    certificateTypeToString(type) + '/' + endpoint;
307     auto event = sdeventplus::Event::get_default();
308     // Attach the bus to sd_event to service user requests
309     bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
310     ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit,
311                           installPath);
312     EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest)))
313         .WillOnce(Return());
314     MainApp mainApp(&manager);
315     mainApp.install(certificateFile);
316     EXPECT_TRUE(fs::exists(verifyPath));
317 }
318 
319 /** @brief Check if storage install routine is invoked for storage setup
320  */
321 TEST_F(TestCertificates, InvokeAuthorityInstall)
322 {
323     std::string endpoint("ldap");
324     CertificateType type = CertificateType::Authority;
325     std::string verifyDir(certDir);
326     std::string verifyUnit(ManagerInTest::unitToRestartInTest);
327     auto objPath = std::string(objectNamePrefix) + '/' +
328                    certificateTypeToString(type) + '/' + endpoint;
329     auto event = sdeventplus::Event::get_default();
330     // Attach the bus to sd_event to service user requests
331     bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
332     ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit,
333                           verifyDir);
334     EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest)))
335         .WillOnce(Return());
336     MainApp mainApp(&manager);
337     // install the default certificate that's valid from today to 100 years
338     // later
339     mainApp.install(certificateFile);
340 
341     std::vector<std::unique_ptr<Certificate>>& certs =
342         manager.getCertificates();
343 
344     ASSERT_EQ(certs.size(), 1);
345     // check some attributes as well
346     EXPECT_EQ(certs.front()->validNotAfter() - certs.front()->validNotBefore(),
347               365000ULL * 24 * 3600);
348     EXPECT_EQ(certs.front()->subject(), "O=openbmc-project.xyz,CN=localhost");
349     EXPECT_EQ(certs.front()->issuer(), "O=openbmc-project.xyz,CN=localhost");
350 
351     std::string verifyPath =
352         verifyDir + "/" + getCertSubjectNameHash(certificateFile) + ".0";
353 
354     // Check that certificate has been created at installation directory
355     EXPECT_FALSE(fs::is_empty(verifyDir));
356     EXPECT_TRUE(fs::exists(verifyPath));
357 
358     // Check that installed cert is identical to input one
359     EXPECT_TRUE(compareFiles(certificateFile, verifyPath));
360 }
361 
362 /** @brief Check if storage install routine is invoked for storage setup
363  */
364 TEST_F(TestCertificates, InvokeAuthorityInstallNeverExpiredRootCert)
365 {
366     std::string endpoint("ldap");
367     CertificateType type = CertificateType::Authority;
368     std::string verifyDir(certDir);
369     std::string verifyUnit(ManagerInTest::unitToRestartInTest);
370     auto objPath = std::string(objectNamePrefix) + '/' +
371                    certificateTypeToString(type) + '/' + endpoint;
372     auto event = sdeventplus::Event::get_default();
373     // Attach the bus to sd_event to service user requests
374     bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
375     ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit,
376                           certDir);
377     EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest)))
378         .WillOnce(Return());
379     MainApp mainApp(&manager);
380 
381     // install the certificate that's valid from the Unix Epoch to Dec 31, 9999
382     createNeverExpiredRootCertificate();
383     mainApp.install(certificateFile);
384 
385     std::vector<std::unique_ptr<Certificate>>& certs =
386         manager.getCertificates();
387 
388     EXPECT_EQ(certs.front()->validNotBefore(), 0);
389     EXPECT_EQ(certs.front()->validNotAfter(), 253402300799ULL);
390 
391     std::string verifyPath =
392         verifyDir + "/" + getCertSubjectNameHash(certificateFile) + ".0";
393 
394     // Check that certificate has been created at installation directory
395     EXPECT_FALSE(fs::is_empty(verifyDir));
396     EXPECT_TRUE(fs::exists(verifyPath));
397 
398     // Check that installed cert is identical to input one
399     EXPECT_TRUE(compareFiles(certificateFile, verifyPath));
400 }
401 
402 /** @brief Check if in authority mode user can't install the same
403  * certificate twice.
404  */
405 TEST_F(TestCertificates, InvokeInstallSameCertTwice)
406 {
407     std::string endpoint("ldap");
408     CertificateType type = CertificateType::Authority;
409     std::string verifyDir(certDir);
410     std::string verifyUnit(ManagerInTest::unitToRestartInTest);
411     auto objPath = std::string(objectNamePrefix) + '/' +
412                    certificateTypeToString(type) + '/' + endpoint;
413     auto event = sdeventplus::Event::get_default();
414     // Attach the bus to sd_event to service user requests
415     bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
416     ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit,
417                           std::move(certDir));
418     EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest)))
419         .WillOnce(Return());
420     MainApp mainApp(&manager);
421     mainApp.install(certificateFile);
422 
423     std::vector<std::unique_ptr<Certificate>>& certs =
424         manager.getCertificates();
425 
426     EXPECT_FALSE(certs.empty());
427 
428     // Check that certificate has been created at installation directory
429     std::string verifyPath =
430         verifyDir + "/" + getCertSubjectNameHash(certificateFile) + ".0";
431     EXPECT_FALSE(fs::is_empty(verifyDir));
432     EXPECT_TRUE(fs::exists(verifyPath));
433 
434     // Check that installed cert is identical to input one
435     EXPECT_TRUE(compareFiles(certificateFile, verifyPath));
436 
437     using NotAllowed =
438         sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
439     EXPECT_THROW(
440         {
441             try
442             {
443                 // Try to install the same certificate second time
444                 mainApp.install(certificateFile);
445             }
446             catch (const NotAllowed& e)
447             {
448                 throw;
449             }
450         },
451         NotAllowed);
452 
453     // Check that the original certificate has been not removed
454     EXPECT_FALSE(fs::is_empty(verifyDir));
455     EXPECT_TRUE(fs::exists(verifyPath));
456 }
457 
458 /** @brief Check if in authority mode user can install a certificate with
459  * certain subject hash twice.
460  */
461 TEST_F(TestCertificates, InvokeInstallSameSubjectTwice)
462 {
463     std::string endpoint("ldap");
464     CertificateType type = CertificateType::Authority;
465     std::string verifyDir(certDir);
466     std::string verifyUnit(ManagerInTest::unitToRestartInTest);
467     auto objPath = std::string(objectNamePrefix) + '/' +
468                    certificateTypeToString(type) + '/' + endpoint;
469     auto event = sdeventplus::Event::get_default();
470     // Attach the bus to sd_event to service user requests
471     bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
472     ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit,
473                           certDir);
474     EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest)))
475         .WillOnce(Return())
476         .WillOnce(Return());
477     MainApp mainApp(&manager);
478     mainApp.install(certificateFile);
479 
480     std::vector<std::unique_ptr<Certificate>>& certs =
481         manager.getCertificates();
482 
483     EXPECT_FALSE(certs.empty());
484 
485     // Check that certificate has been created at installation directory
486     std::string verifyPath0 =
487         verifyDir + "/" + getCertSubjectNameHash(certificateFile) + ".0";
488     EXPECT_FALSE(fs::is_empty(verifyDir));
489     EXPECT_TRUE(fs::exists(verifyPath0));
490 
491     // Check that installed cert is identical to input one
492     EXPECT_TRUE(compareFiles(certificateFile, verifyPath0));
493 
494     // Prepare second certificate with the same subject
495     createNewCertificate();
496 
497     // Install second certificate
498     mainApp.install(certificateFile);
499 
500     // Expect there are exactly two certificates in the collection
501     EXPECT_EQ(certs.size(), 2);
502 
503     // Check that certificate has been created at installation directory
504     std::string verifyPath1 =
505         verifyDir + "/" + getCertSubjectNameHash(certificateFile) + ".1";
506     EXPECT_TRUE(fs::exists(verifyPath1));
507 
508     // Check that installed cert is identical to input one
509     EXPECT_TRUE(compareFiles(certificateFile, verifyPath1));
510 
511     // Check that the original/first certificate has been not removed
512     EXPECT_FALSE(fs::is_empty(verifyDir));
513     EXPECT_TRUE(fs::exists(verifyPath0));
514 }
515 
516 /** @brief Check if in authority mode user can't install more than
517  * maxNumAuthorityCertificates certificates.
518  */
519 TEST_F(TestCertificates, InvokeInstallAuthCertLimit)
520 {
521     std::string endpoint("ldap");
522     CertificateType type = CertificateType::Authority;
523     std::string verifyDir(certDir);
524     std::string verifyUnit(ManagerInTest::unitToRestartInTest);
525     auto objPath = std::string(objectNamePrefix) + '/' +
526                    certificateTypeToString(type) + '/' + endpoint;
527     auto event = sdeventplus::Event::get_default();
528     // Attach the bus to sd_event to service user requests
529     bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
530     ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit,
531                           certDir);
532     EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest)))
533         .WillRepeatedly(Return());
534     MainApp mainApp(&manager);
535 
536     std::vector<std::unique_ptr<Certificate>>& certs =
537         manager.getCertificates();
538 
539     std::vector<std::string> verifyPaths;
540 
541     // Prepare maximum number of ceritificates
542     for (std::size_t i = 0; i < maxNumAuthorityCertificates; ++i)
543     {
544         // Prepare new certificatate
545         createNewCertificate(true);
546 
547         // Install ceritificate
548         mainApp.install(certificateFile);
549 
550         // Check number of certificates in the collection
551         EXPECT_EQ(certs.size(), i + 1);
552 
553         // Check that certificate has been created at installation directory
554         std::string verifyPath =
555             verifyDir + "/" + getCertSubjectNameHash(certificateFile) + ".0";
556         EXPECT_FALSE(fs::is_empty(verifyDir));
557         EXPECT_TRUE(fs::exists(verifyPath));
558 
559         // Check that installed cert is identical to input one
560         EXPECT_TRUE(compareFiles(certificateFile, verifyPath));
561 
562         // Save current certificate file for later check
563         verifyPaths.push_back(verifyPath);
564     }
565 
566     // Prepare new certificatate
567     createNewCertificate(true);
568 
569     using NotAllowed =
570         sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
571     EXPECT_THROW(
572         {
573             try
574             {
575                 // Try to install one more certificate
576                 mainApp.install(certificateFile);
577             }
578             catch (const NotAllowed& e)
579             {
580                 throw;
581             }
582         },
583         NotAllowed);
584 
585     // Check that the original certificate has been not removed
586     EXPECT_FALSE(fs::is_empty(verifyDir));
587     for (size_t i = 0; i < maxNumAuthorityCertificates; ++i)
588     {
589         EXPECT_TRUE(fs::exists(verifyPaths[i]));
590     }
591 }
592 
593 /** @brief Compare the installed certificate with the copied certificate
594  */
595 TEST_F(TestCertificates, CompareInstalledCertificate)
596 {
597     std::string endpoint("ldap");
598     CertificateType type = CertificateType::Client;
599     std::string installPath(certDir + "/" + certificateFile);
600     std::string verifyPath(installPath);
601     std::string verifyUnit(ManagerInTest::unitToRestartInTest);
602     auto objPath = std::string(objectNamePrefix) + '/' +
603                    certificateTypeToString(type) + '/' + endpoint;
604     auto event = sdeventplus::Event::get_default();
605     // Attach the bus to sd_event to service user requests
606     bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
607     ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit,
608                           installPath);
609     EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest)))
610         .WillOnce(Return());
611     MainApp mainApp(&manager);
612     mainApp.install(certificateFile);
613     EXPECT_TRUE(fs::exists(verifyPath));
614     EXPECT_TRUE(compareFiles(verifyPath, certificateFile));
615 }
616 
617 /** @brief Check if install fails if certificate file is not found
618  */
619 TEST_F(TestCertificates, TestNoCertificateFile)
620 {
621     std::string endpoint("ldap");
622     CertificateType type = CertificateType::Client;
623     std::string installPath(certDir + "/" + certificateFile);
624     std::string verifyPath(installPath);
625     std::string verifyUnit(ManagerInTest::unitToRestartInTest);
626     auto objPath = std::string(objectNamePrefix) + '/' +
627                    certificateTypeToString(type) + '/' + endpoint;
628     std::string uploadFile = "nofile.pem";
629     EXPECT_THROW(
630         {
631             try
632             {
633                 auto event = sdeventplus::Event::get_default();
634                 // Attach the bus to sd_event to service user requests
635                 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
636                 ManagerInTest manager(bus, event, objPath.c_str(), type,
637                                       verifyUnit, installPath);
638                 MainApp mainApp(&manager);
639                 mainApp.install(uploadFile);
640             }
641             catch (const InternalFailure& e)
642             {
643                 throw;
644             }
645         },
646         InternalFailure);
647     EXPECT_FALSE(fs::exists(verifyPath));
648 }
649 
650 /** @brief Test replacing existing certificate
651  */
652 TEST_F(TestCertificates, TestReplaceCertificate)
653 {
654     std::string endpoint("ldap");
655     CertificateType type = CertificateType::Server;
656     std::string installPath(certDir + "/" + certificateFile);
657     std::string verifyPath(installPath);
658     std::string verifyUnit(ManagerInTest::unitToRestartInTest);
659     auto objPath = std::string(objectNamePrefix) + '/' +
660                    certificateTypeToString(type) + '/' + endpoint;
661     auto event = sdeventplus::Event::get_default();
662     // Attach the bus to sd_event to service user requests
663     bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
664     ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit,
665                           std::move(installPath));
666     EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest)))
667         .WillOnce(Return())
668         .WillOnce(Return());
669     MainApp mainApp(&manager);
670     mainApp.install(certificateFile);
671     EXPECT_TRUE(fs::exists(verifyPath));
672     std::vector<std::unique_ptr<Certificate>>& certs =
673         manager.getCertificates();
674     EXPECT_FALSE(certs.empty());
675     EXPECT_NE(certs[0], nullptr);
676     certs[0]->replace(certificateFile);
677     EXPECT_TRUE(fs::exists(verifyPath));
678 }
679 
680 /** @brief Test replacing existing certificate
681  */
682 TEST_F(TestCertificates, TestAuthorityReplaceCertificate)
683 {
684     std::string endpoint("ldap");
685     CertificateType type = CertificateType::Authority;
686     std::string verifyDir(certDir);
687     std::string verifyUnit(ManagerInTest::unitToRestartInTest);
688     auto objPath = std::string(objectNamePrefix) + '/' +
689                    certificateTypeToString(type) + '/' + endpoint;
690     auto event = sdeventplus::Event::get_default();
691     // Attach the bus to sd_event to service user requests
692     bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
693     ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit,
694                           certDir);
695     constexpr const unsigned int REPLACE_ITERATIONS = 10;
696     EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest)))
697         .Times(REPLACE_ITERATIONS + 1)
698         .WillRepeatedly(Return());
699     MainApp mainApp(&manager);
700     mainApp.install(certificateFile);
701 
702     std::vector<std::unique_ptr<Certificate>>& certs =
703         manager.getCertificates();
704 
705     for (unsigned int i = 0; i < REPLACE_ITERATIONS; i++)
706     {
707         // Certificate successfully installed
708         EXPECT_FALSE(certs.empty());
709 
710         std::string verifyPath =
711             verifyDir + "/" + getCertSubjectNameHash(certificateFile) + ".0";
712 
713         // Check that certificate has been created at installation directory
714         EXPECT_FALSE(fs::is_empty(verifyDir));
715         EXPECT_TRUE(fs::exists(verifyPath));
716 
717         // Check that installed cert is identical to input one
718         EXPECT_TRUE(compareFiles(certificateFile, verifyPath));
719 
720         // Create new certificate
721         createNewCertificate(true);
722 
723         certs[0]->replace(certificateFile);
724 
725         // Verify that old certificate has been removed
726         EXPECT_FALSE(fs::exists(verifyPath));
727     }
728 }
729 
730 /** @brief Test verifiing if delete function works.
731  */
732 TEST_F(TestCertificates, TestStorageDeleteCertificate)
733 {
734     std::string endpoint("ldap");
735     CertificateType type = CertificateType::Authority;
736     std::string verifyDir(certDir);
737     std::string verifyUnit((ManagerInTest::unitToRestartInTest));
738     auto objPath = std::string(objectNamePrefix) + '/' +
739                    certificateTypeToString(type) + '/' + endpoint;
740     auto event = sdeventplus::Event::get_default();
741     // Attach the bus to sd_event to service user requests
742     bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
743     ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit,
744                           certDir);
745     EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest)))
746         .WillRepeatedly(Return());
747     MainApp mainApp(&manager);
748 
749     // Check if certificate placeholder dir is empty
750     EXPECT_TRUE(fs::is_empty(verifyDir));
751     mainApp.install(certificateFile);
752 
753     // Create new certificate
754     createNewCertificate(true);
755     mainApp.install(certificateFile);
756 
757     createNewCertificate(true);
758     mainApp.install(certificateFile);
759 
760     std::vector<std::unique_ptr<Certificate>>& certs =
761         manager.getCertificates();
762 
763     // All 3 certificates successfully installed and added to manager
764     EXPECT_EQ(certs.size(), 3);
765 
766     // Check if certificate placeholder is not empty, there should be 3
767     // certificates
768     EXPECT_FALSE(fs::is_empty(verifyDir));
769 
770     certs[0]->delete_();
771     EXPECT_EQ(certs.size(), 2);
772 
773     certs[0]->delete_();
774     EXPECT_EQ(certs.size(), 1);
775 
776     certs[0]->delete_();
777     EXPECT_EQ(certs.size(), 0);
778 
779     // Check if certificate placeholder is empty.
780     EXPECT_TRUE(fs::is_empty(verifyDir));
781 }
782 
783 /** @brief Check if install fails if certificate file is empty
784  */
785 TEST_F(TestCertificates, TestEmptyCertificateFile)
786 {
787     std::string endpoint("ldap");
788     CertificateType type = CertificateType::Client;
789     std::string installPath(certDir + "/" + certificateFile);
790     std::string verifyPath(installPath);
791     std::string verifyUnit(ManagerInTest::unitToRestartInTest);
792     auto objPath = std::string(objectNamePrefix) + '/' +
793                    certificateTypeToString(type) + '/' + endpoint;
794     std::string emptyFile("emptycert.pem");
795     std::ofstream ofs;
796     ofs.open(emptyFile, std::ofstream::out);
797     ofs.close();
798     EXPECT_THROW(
799         {
800             try
801             {
802                 auto event = sdeventplus::Event::get_default();
803                 // Attach the bus to sd_event to service user requests
804                 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
805                 ManagerInTest manager(bus, event, objPath.c_str(), type,
806                                       verifyUnit, installPath);
807                 MainApp mainApp(&manager);
808                 mainApp.install(emptyFile);
809             }
810             catch (const InvalidCertificate& e)
811             {
812                 throw;
813             }
814         },
815         InvalidCertificate);
816     EXPECT_FALSE(fs::exists(verifyPath));
817     fs::remove(emptyFile);
818 }
819 
820 /** @brief Check if install fails if certificate file is corrupted
821  */
822 TEST_F(TestCertificates, TestInvalidCertificateFile)
823 {
824     std::string endpoint("ldap");
825     CertificateType type = CertificateType::Client;
826 
827     std::ofstream ofs;
828     ofs.open(certificateFile, std::ofstream::out);
829     ofs << "-----BEGIN CERTIFICATE-----";
830     ofs << "ADD_SOME_INVALID_DATA_INTO_FILE";
831     ofs << "-----END CERTIFICATE-----";
832     ofs.close();
833 
834     std::string installPath(certDir + "/" + certificateFile);
835     std::string verifyPath(installPath);
836     std::string verifyUnit(ManagerInTest::unitToRestartInTest);
837     auto objPath = std::string(objectNamePrefix) + '/' +
838                    certificateTypeToString(type) + '/' + endpoint;
839     EXPECT_THROW(
840         {
841             try
842             {
843                 auto event = sdeventplus::Event::get_default();
844                 // Attach the bus to sd_event to service user requests
845                 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
846                 ManagerInTest manager(bus, event, objPath.c_str(), type,
847                                       verifyUnit, installPath);
848                 MainApp mainApp(&manager);
849                 mainApp.install(certificateFile);
850             }
851             catch (const InvalidCertificate& e)
852             {
853                 throw;
854             }
855         },
856         InvalidCertificate);
857     EXPECT_FALSE(fs::exists(verifyPath));
858 }
859 
860 /**
861  * Class to generate private and certificate only file and test verification
862  */
863 class TestInvalidCertificate : public ::testing::Test
864 {
865   public:
866     TestInvalidCertificate() : bus(sdbusplus::bus::new_default())
867     {
868     }
869     void SetUp() override
870     {
871         char dirTemplate[] = "/tmp/FakeCerts.XXXXXX";
872         auto dirPtr = mkdtemp(dirTemplate);
873         if (dirPtr == nullptr)
874         {
875             throw std::bad_alloc();
876         }
877         certDir = std::string(dirPtr) + "/certs";
878         fs::create_directories(certDir);
879         certificateFile = "cert.pem";
880         keyFile = "key.pem";
881         std::string cmd = "openssl req -x509 -sha256 -newkey rsa:2048 ";
882         cmd += "-keyout key.pem -out cert.pem -days 3650 ";
883         cmd += "-subj "
884                "/O=openbmc-project.xyz/CN=localhost"
885                " -nodes";
886 
887         auto val = std::system(cmd.c_str());
888         if (val)
889         {
890             std::cout << "command Error: " << val << std::endl;
891         }
892     }
893     void TearDown() override
894     {
895         fs::remove_all(certDir);
896         fs::remove(certificateFile);
897         fs::remove(keyFile);
898     }
899 
900   protected:
901     sdbusplus::bus::bus bus;
902     std::string certificateFile;
903     std::string keyFile;
904     std::string certDir;
905 };
906 
907 /** @brief Check install fails if private key is missing in certificate file
908  */
909 TEST_F(TestInvalidCertificate, TestMissingPrivateKey)
910 {
911     std::string endpoint("ldap");
912     CertificateType type = CertificateType::Client;
913     std::string installPath(certDir + "/" + certificateFile);
914     std::string verifyPath(installPath);
915     std::string verifyUnit(ManagerInTest::unitToRestartInTest);
916     auto objPath = std::string(objectNamePrefix) + '/' +
917                    certificateTypeToString(type) + '/' + endpoint;
918     EXPECT_THROW(
919         {
920             try
921             {
922                 auto event = sdeventplus::Event::get_default();
923                 // Attach the bus to sd_event to service user requests
924                 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
925                 ManagerInTest manager(bus, event, objPath.c_str(), type,
926                                       verifyUnit, installPath);
927                 MainApp mainApp(&manager);
928                 mainApp.install(certificateFile);
929             }
930             catch (const InternalFailure& e)
931             {
932                 throw;
933             }
934         },
935         InternalFailure);
936     EXPECT_FALSE(fs::exists(verifyPath));
937 }
938 
939 /** @brief Check install fails if ceritificate is missing in certificate file
940  */
941 TEST_F(TestInvalidCertificate, TestMissingCeritificate)
942 {
943     std::string endpoint("ldap");
944     CertificateType type = CertificateType::Client;
945     std::string installPath(certDir + "/" + keyFile);
946     std::string verifyPath(installPath);
947     std::string verifyUnit(ManagerInTest::unitToRestartInTest);
948     auto objPath = std::string(objectNamePrefix) + '/' +
949                    certificateTypeToString(type) + '/' + endpoint;
950     EXPECT_THROW(
951         {
952             try
953             {
954                 auto event = sdeventplus::Event::get_default();
955                 // Attach the bus to sd_event to service user requests
956                 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
957                 ManagerInTest manager(bus, event, objPath.c_str(), type,
958                                       verifyUnit, installPath);
959                 MainApp mainApp(&manager);
960                 mainApp.install(keyFile);
961             }
962             catch (const InternalFailure& e)
963             {
964                 throw;
965             }
966         },
967         InvalidCertificate);
968     EXPECT_FALSE(fs::exists(verifyPath));
969 }
970 
971 /** @brief Check if error is thrown when multiple certificates are installed
972  *  At present only one certificate per service is allowed
973  */
974 TEST_F(TestCertificates, TestCertInstallNotAllowed)
975 {
976     using NotAllowed =
977         sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
978     std::string endpoint("ldap");
979     CertificateType type = CertificateType::Client;
980     std::string installPath(certDir + "/" + certificateFile);
981     std::string verifyPath(installPath);
982     std::string verifyUnit(ManagerInTest::unitToRestartInTest);
983     auto objPath = std::string(objectNamePrefix) + '/' +
984                    certificateTypeToString(type) + '/' + endpoint;
985     auto event = sdeventplus::Event::get_default();
986     // Attach the bus to sd_event to service user requests
987     bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
988     ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit,
989                           installPath);
990     MainApp mainApp(&manager);
991     mainApp.install(certificateFile);
992     EXPECT_TRUE(fs::exists(verifyPath));
993     EXPECT_THROW(
994         {
995             try
996             {
997                 // install second certificate
998                 mainApp.install(certificateFile);
999             }
1000             catch (const NotAllowed& e)
1001             {
1002                 throw;
1003             }
1004         },
1005         NotAllowed);
1006 }
1007 
1008 TEST_F(TestCertificates, TestGenerateCSR)
1009 {
1010     std::string endpoint("https");
1011     std::string unit;
1012     CertificateType type = CertificateType::Server;
1013     std::string installPath(certDir + "/" + certificateFile);
1014     std::string verifyPath(installPath);
1015     std::string CSRPath(certDir + "/" + CSRFile);
1016     std::string privateKeyPath(certDir + "/" + privateKeyFile);
1017     std::vector<std::string> alternativeNames{"localhost1", "localhost2"};
1018     std::string challengePassword("Password");
1019     std::string city("HYB");
1020     std::string commonName("abc.com");
1021     std::string contactPerson("Admin");
1022     std::string country("IN");
1023     std::string email("admin@in.ibm.com");
1024     std::string givenName("givenName");
1025     std::string initials("G");
1026     int64_t keyBitLength(2048);
1027     std::string keyCurveId("0");
1028     std::string keyPairAlgorithm("RSA");
1029     std::vector<std::string> keyUsage{"serverAuth", "clientAuth"};
1030     std::string organization("IBM");
1031     std::string organizationalUnit("orgUnit");
1032     std::string state("TS");
1033     std::string surname("surname");
1034     std::string unstructuredName("unstructuredName");
1035     auto objPath = std::string(objectNamePrefix) + '/' +
1036                    certificateTypeToString(type) + '/' + endpoint;
1037     auto event = sdeventplus::Event::get_default();
1038     // Attach the bus to sd_event to service user requests
1039     bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
1040     Manager manager(bus, event, objPath.c_str(), type, std::move(unit),
1041                     std::move(installPath));
1042     Status status;
1043     CSR csr(bus, objPath.c_str(), CSRPath.c_str(), status);
1044     MainApp mainApp(&manager, &csr);
1045     mainApp.generateCSR(alternativeNames, challengePassword, city, commonName,
1046                         contactPerson, country, email, givenName, initials,
1047                         keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage,
1048                         organization, organizationalUnit, state, surname,
1049                         unstructuredName);
1050     std::string csrData("");
1051     // generateCSR takes considerable time to create CSR and privateKey Files
1052     EXPECT_FALSE(fs::exists(CSRPath));
1053     EXPECT_FALSE(fs::exists(privateKeyPath));
1054     EXPECT_THROW(
1055         {
1056             try
1057             {
1058                 csrData = csr.csr();
1059             }
1060             catch (const InternalFailure& e)
1061             {
1062                 throw;
1063             }
1064         },
1065         InternalFailure);
1066     // wait for 10 sec to get CSR and privateKey Files generated
1067     sleep(10);
1068     EXPECT_TRUE(fs::exists(CSRPath));
1069     EXPECT_TRUE(fs::exists(privateKeyPath));
1070     csrData = csr.csr();
1071     ASSERT_NE("", csrData.c_str());
1072 }
1073 
1074 /** @brief Check if ECC key pair is generated when user is not given algorithm
1075  * type. At present RSA and EC key pair algorithm are supported
1076  */
1077 TEST_F(TestCertificates, TestGenerateCSRwithEmptyKeyPairAlgorithm)
1078 {
1079     std::string endpoint("https");
1080     std::string unit;
1081     CertificateType type = CertificateType::Server;
1082     std::string installPath(certDir + "/" + certificateFile);
1083     std::string verifyPath(installPath);
1084     std::string CSRPath(certDir + "/" + CSRFile);
1085     std::string privateKeyPath(certDir + "/" + privateKeyFile);
1086     std::vector<std::string> alternativeNames{"localhost1", "localhost2"};
1087     std::string challengePassword("Password");
1088     std::string city("HYB");
1089     std::string commonName("abc.com");
1090     std::string contactPerson("Admin");
1091     std::string country("IN");
1092     std::string email("admin@in.ibm.com");
1093     std::string givenName("givenName");
1094     std::string initials("G");
1095     int64_t keyBitLength(2048);
1096     std::string keyCurveId("");
1097     std::string keyPairAlgorithm("");
1098     std::vector<std::string> keyUsage{"serverAuth", "clientAuth"};
1099     std::string organization("IBM");
1100     std::string organizationalUnit("orgUnit");
1101     std::string state("TS");
1102     std::string surname("surname");
1103     std::string unstructuredName("unstructuredName");
1104     auto objPath = std::string(objectNamePrefix) + '/' +
1105                    certificateTypeToString(type) + '/' + endpoint;
1106     auto event = sdeventplus::Event::get_default();
1107     Manager manager(bus, event, objPath.c_str(), type, std::move(unit),
1108                     std::move(installPath));
1109     Status status;
1110     CSR csr(bus, objPath.c_str(), CSRPath.c_str(), status);
1111     MainApp mainApp(&manager, &csr);
1112     mainApp.generateCSR(alternativeNames, challengePassword, city, commonName,
1113                         contactPerson, country, email, givenName, initials,
1114                         keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage,
1115                         organization, organizationalUnit, state, surname,
1116                         unstructuredName);
1117     sleep(10);
1118     EXPECT_TRUE(fs::exists(CSRPath));
1119     EXPECT_TRUE(fs::exists(privateKeyPath));
1120 }
1121 
1122 /** @brief Check if error is thrown when giving un supported key pair
1123  * algorithm. At present RSA and EC key pair algorithm are supported
1124  */
1125 TEST_F(TestCertificates, TestGenerateCSRwithUnsupportedKeyPairAlgorithm)
1126 {
1127     std::string endpoint("https");
1128     std::string unit;
1129     CertificateType type = CertificateType::Server;
1130     std::string installPath(certDir + "/" + certificateFile);
1131     std::string verifyPath(installPath);
1132     std::string CSRPath(certDir + "/" + CSRFile);
1133     std::string privateKeyPath(certDir + "/" + privateKeyFile);
1134     std::vector<std::string> alternativeNames{"localhost1", "localhost2"};
1135     std::string challengePassword("Password");
1136     std::string city("HYB");
1137     std::string commonName("abc.com");
1138     std::string contactPerson("Admin");
1139     std::string country("IN");
1140     std::string email("admin@in.ibm.com");
1141     std::string givenName("givenName");
1142     std::string initials("G");
1143     int64_t keyBitLength(2048);
1144     std::string keyCurveId("secp521r1");
1145     std::string keyPairAlgorithm("UnSupportedAlgorithm");
1146     std::vector<std::string> keyUsage{"serverAuth", "clientAuth"};
1147     std::string organization("IBM");
1148     std::string organizationalUnit("orgUnit");
1149     std::string state("TS");
1150     std::string surname("surname");
1151     std::string unstructuredName("unstructuredName");
1152     auto objPath = std::string(objectNamePrefix) + '/' +
1153                    certificateTypeToString(type) + '/' + endpoint;
1154     auto event = sdeventplus::Event::get_default();
1155     Manager manager(bus, event, objPath.c_str(), type, std::move(unit),
1156                     std::move(installPath));
1157     Status status;
1158     CSR csr(bus, objPath.c_str(), CSRPath.c_str(), status);
1159     MainApp mainApp(&manager, &csr);
1160     mainApp.generateCSR(alternativeNames, challengePassword, city, commonName,
1161                         contactPerson, country, email, givenName, initials,
1162                         keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage,
1163                         organization, organizationalUnit, state, surname,
1164                         unstructuredName);
1165     EXPECT_FALSE(fs::exists(CSRPath));
1166     EXPECT_FALSE(fs::exists(privateKeyPath));
1167 }
1168 
1169 /** @brief Check if error is thrown when NID_undef is returned for given key
1170  * curve id
1171  */
1172 TEST_F(TestCertificates, TestECKeyGenerationwithNIDundefCase)
1173 {
1174     std::string endpoint("https");
1175     std::string unit;
1176     CertificateType type = CertificateType::Server;
1177     std::string installPath(certDir + "/" + certificateFile);
1178     std::string verifyPath(installPath);
1179     std::string CSRPath(certDir + "/" + CSRFile);
1180     std::string privateKeyPath(certDir + "/" + privateKeyFile);
1181     std::vector<std::string> alternativeNames{"localhost1", "localhost2"};
1182     std::string challengePassword("Password");
1183     std::string city("BLR");
1184     std::string commonName("abc.com");
1185     std::string contactPerson("Admin");
1186     std::string country("IN");
1187     std::string email("admin@in.ibm.com");
1188     std::string givenName("givenName");
1189     std::string initials("G");
1190     int64_t keyBitLength(2048);
1191     std::string keyCurveId("DummyCurveName");
1192     std::string keyPairAlgorithm("EC");
1193     std::vector<std::string> keyUsage{"serverAuth", "clientAuth"};
1194     std::string organization("IBM");
1195     std::string organizationalUnit("orgUnit");
1196     std::string state("TS");
1197     std::string surname("surname");
1198     std::string unstructuredName("unstructuredName");
1199     auto objPath = std::string(objectNamePrefix) + '/' +
1200                    certificateTypeToString(type) + '/' + endpoint;
1201     auto event = sdeventplus::Event::get_default();
1202     Manager manager(bus, event, objPath.c_str(), type, std::move(unit),
1203                     std::move(installPath));
1204     Status status;
1205     CSR csr(bus, objPath.c_str(), CSRPath.c_str(), status);
1206     MainApp mainApp(&manager, &csr);
1207     mainApp.generateCSR(alternativeNames, challengePassword, city, commonName,
1208                         contactPerson, country, email, givenName, initials,
1209                         keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage,
1210                         organization, organizationalUnit, state, surname,
1211                         unstructuredName);
1212     EXPECT_FALSE(fs::exists(CSRPath));
1213     EXPECT_FALSE(fs::exists(privateKeyPath));
1214 }
1215 
1216 /** @brief Check default Key Curve Id is used if given curve id is empty
1217  */
1218 TEST_F(TestCertificates, TestECKeyGenerationwithDefaultKeyCurveId)
1219 {
1220     std::string endpoint("https");
1221     std::string unit;
1222     CertificateType type = CertificateType::Server;
1223     std::string installPath(certDir + "/" + certificateFile);
1224     std::string verifyPath(installPath);
1225     std::string CSRPath(certDir + "/" + CSRFile);
1226     std::string privateKeyPath(certDir + "/" + privateKeyFile);
1227     std::vector<std::string> alternativeNames{"localhost1", "localhost2"};
1228     std::string challengePassword("Password");
1229     std::string city("BLR");
1230     std::string commonName("abc.com");
1231     std::string contactPerson("Admin");
1232     std::string country("IN");
1233     std::string email("admin@in.ibm.com");
1234     std::string givenName("givenName");
1235     std::string initials("G");
1236     int64_t keyBitLength(2048);
1237     std::string keyCurveId("");
1238     std::string keyPairAlgorithm("EC");
1239     std::vector<std::string> keyUsage{"serverAuth", "clientAuth"};
1240     std::string organization("IBM");
1241     std::string organizationalUnit("orgUnit");
1242     std::string state("TS");
1243     std::string surname("surname");
1244     std::string unstructuredName("unstructuredName");
1245     auto objPath = std::string(objectNamePrefix) + '/' +
1246                    certificateTypeToString(type) + '/' + endpoint;
1247     auto event = sdeventplus::Event::get_default();
1248     Manager manager(bus, event, objPath.c_str(), type, std::move(unit),
1249                     std::move(installPath));
1250     Status status;
1251     CSR csr(bus, objPath.c_str(), CSRPath.c_str(), status);
1252     MainApp mainApp(&manager, &csr);
1253     mainApp.generateCSR(alternativeNames, challengePassword, city, commonName,
1254                         contactPerson, country, email, givenName, initials,
1255                         keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage,
1256                         organization, organizationalUnit, state, surname,
1257                         unstructuredName);
1258     sleep(10);
1259     EXPECT_TRUE(fs::exists(CSRPath));
1260     EXPECT_TRUE(fs::exists(privateKeyPath));
1261 }
1262 
1263 /** @brief Check if error is not thrown to generate EC key pair
1264  */
1265 TEST_F(TestCertificates, TestECKeyGeneration)
1266 {
1267     std::string endpoint("https");
1268     std::string unit;
1269     CertificateType type = CertificateType::Server;
1270     std::string installPath(certDir + "/" + certificateFile);
1271     std::string verifyPath(installPath);
1272     std::string CSRPath(certDir + "/" + CSRFile);
1273     std::string privateKeyPath(certDir + "/" + privateKeyFile);
1274     std::vector<std::string> alternativeNames{"localhost1", "localhost2"};
1275     std::string challengePassword("Password");
1276     std::string city("BLR");
1277     std::string commonName("abc.com");
1278     std::string contactPerson("Admin");
1279     std::string country("IN");
1280     std::string email("admin@in.ibm.com");
1281     std::string givenName("givenName");
1282     std::string initials("G");
1283     int64_t keyBitLength(2048);
1284     std::string keyCurveId("secp521r1");
1285     std::string keyPairAlgorithm("EC");
1286     std::vector<std::string> keyUsage{"serverAuth", "clientAuth"};
1287     std::string organization("IBM");
1288     std::string organizationalUnit("orgUnit");
1289     std::string state("TS");
1290     std::string surname("surname");
1291     std::string unstructuredName("unstructuredName");
1292     auto objPath = std::string(objectNamePrefix) + '/' +
1293                    certificateTypeToString(type) + '/' + endpoint;
1294     auto event = sdeventplus::Event::get_default();
1295     Manager manager(bus, event, objPath.c_str(), type, std::move(unit),
1296                     std::move(installPath));
1297     Status status;
1298     CSR csr(bus, objPath.c_str(), CSRPath.c_str(), status);
1299     MainApp mainApp(&manager, &csr);
1300     mainApp.generateCSR(alternativeNames, challengePassword, city, commonName,
1301                         contactPerson, country, email, givenName, initials,
1302                         keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage,
1303                         organization, organizationalUnit, state, surname,
1304                         unstructuredName);
1305     std::cout << "CSRPath: " << CSRPath << std::endl
1306               << "privateKeyPath: " << privateKeyPath << std::endl;
1307     sleep(10);
1308     EXPECT_TRUE(fs::exists(CSRPath));
1309     EXPECT_TRUE(fs::exists(privateKeyPath));
1310 }
1311 
1312 /** @brief Check error is thrown if giving unsupported key bit length to
1313  * generate rsa key
1314  */
1315 TEST_F(TestCertificates, TestRSAKeyWithUnsupportedKeyBitLength)
1316 {
1317     std::string endpoint("https");
1318     std::string unit;
1319     CertificateType type = CertificateType::Server;
1320     std::string installPath(certDir + "/" + certificateFile);
1321     std::string verifyPath(installPath);
1322     std::string CSRPath(certDir + "/" + CSRFile);
1323     std::string privateKeyPath(certDir + "/" + privateKeyFile);
1324     std::vector<std::string> alternativeNames{"localhost1", "localhost2"};
1325     std::string challengePassword("Password");
1326     std::string city("BLR");
1327     std::string commonName("abc.com");
1328     std::string contactPerson("Admin");
1329     std::string country("IN");
1330     std::string email("admin@in.ibm.com");
1331     std::string givenName("givenName");
1332     std::string initials("G");
1333     int64_t keyBitLength(4096);
1334     std::string keyCurveId("secp521r1");
1335     std::string keyPairAlgorithm("RSA");
1336     std::vector<std::string> keyUsage{"serverAuth", "clientAuth"};
1337     std::string organization("IBM");
1338     std::string organizationalUnit("orgUnit");
1339     std::string state("TS");
1340     std::string surname("surname");
1341     std::string unstructuredName("unstructuredName");
1342     auto objPath = std::string(objectNamePrefix) + '/' +
1343                    certificateTypeToString(type) + '/' + endpoint;
1344     auto event = sdeventplus::Event::get_default();
1345     Manager manager(bus, event, objPath.c_str(), type, std::move(unit),
1346                     std::move(installPath));
1347     Status status;
1348     CSR csr(bus, objPath.c_str(), CSRPath.c_str(), status);
1349     MainApp mainApp(&manager, &csr);
1350     mainApp.generateCSR(alternativeNames, challengePassword, city, commonName,
1351                         contactPerson, country, email, givenName, initials,
1352                         keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage,
1353                         organization, organizationalUnit, state, surname,
1354                         unstructuredName);
1355     EXPECT_FALSE(fs::exists(CSRPath));
1356     EXPECT_FALSE(fs::exists(privateKeyPath));
1357 }
1358 
1359 /** @brief Check error is thrown if generated rsa key file is not present
1360  */
1361 TEST_F(TestCertificates, TestRSAKeyFileNotPresentCase)
1362 {
1363     std::string endpoint("https");
1364     std::string unit;
1365     CertificateType type = CertificateType::Server;
1366     std::string installPath(certDir + "/" + certificateFile);
1367     std::string verifyPath(installPath);
1368     std::string CSRPath(certDir + "/" + CSRFile);
1369     std::string privateKeyPath(certDir + "/" + privateKeyFile);
1370     std::vector<std::string> alternativeNames{"localhost1", "localhost2"};
1371     std::string challengePassword("Password");
1372     std::string city("BLR");
1373     std::string commonName("abc.com");
1374     std::string contactPerson("Admin");
1375     std::string country("IN");
1376     std::string email("admin@in.ibm.com");
1377     std::string givenName("givenName");
1378     std::string initials("G");
1379     int64_t keyBitLength(2048);
1380     std::string keyCurveId("secp521r1");
1381     std::string keyPairAlgorithm("RSA");
1382     std::vector<std::string> keyUsage{"serverAuth", "clientAuth"};
1383     std::string organization("IBM");
1384     std::string organizationalUnit("orgUnit");
1385     std::string state("TS");
1386     std::string surname("surname");
1387     std::string unstructuredName("unstructuredName");
1388     auto objPath = std::string(objectNamePrefix) + '/' +
1389                    certificateTypeToString(type) + '/' + endpoint;
1390     auto event = sdeventplus::Event::get_default();
1391     Manager manager(bus, event, objPath.c_str(), type, std::move(unit),
1392                     std::move(installPath));
1393 
1394     // Removing generated RSA key file
1395     fs::remove(rsaPrivateKeyFilePath);
1396 
1397     Status status;
1398     CSR csr(bus, objPath.c_str(), CSRPath.c_str(), status);
1399     MainApp mainApp(&manager, &csr);
1400     mainApp.generateCSR(alternativeNames, challengePassword, city, commonName,
1401                         contactPerson, country, email, givenName, initials,
1402                         keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage,
1403                         organization, organizationalUnit, state, surname,
1404                         unstructuredName);
1405     EXPECT_FALSE(fs::exists(CSRPath));
1406     EXPECT_FALSE(fs::exists(privateKeyPath));
1407 }
1408 
1409 /** @brief Check private key file is created from generated rsa key file is
1410  * `present
1411  */
1412 TEST_F(TestCertificates, TestRSAKeyFromRSAKeyFileIsWrittenIntoPrivateKeyFile)
1413 {
1414     std::string endpoint("https");
1415     std::string unit;
1416     CertificateType type = CertificateType::Server;
1417     std::string installPath(certDir + "/" + certificateFile);
1418     std::string verifyPath(installPath);
1419     std::string CSRPath(certDir + "/" + CSRFile);
1420     std::string privateKeyPath(certDir + "/" + privateKeyFile);
1421     std::vector<std::string> alternativeNames{"localhost1", "localhost2"};
1422     std::string challengePassword("Password");
1423     std::string city("BLR");
1424     std::string commonName("abc.com");
1425     std::string contactPerson("Admin");
1426     std::string country("IN");
1427     std::string email("admin@in.ibm.com");
1428     std::string givenName("givenName");
1429     std::string initials("G");
1430     int64_t keyBitLength(2048);
1431     std::string keyCurveId("secp521r1");
1432     std::string keyPairAlgorithm("RSA");
1433     std::vector<std::string> keyUsage{"serverAuth", "clientAuth"};
1434     std::string organization("IBM");
1435     std::string organizationalUnit("orgUnit");
1436     std::string state("TS");
1437     std::string surname("surname");
1438     std::string unstructuredName("unstructuredName");
1439     auto objPath = std::string(objectNamePrefix) + '/' +
1440                    certificateTypeToString(type) + '/' + endpoint;
1441     auto event = sdeventplus::Event::get_default();
1442     Manager manager(bus, event, objPath.c_str(), type, std::move(unit),
1443                     std::move(installPath));
1444     Status status;
1445     CSR csr(bus, objPath.c_str(), CSRPath.c_str(), status);
1446     MainApp mainApp(&manager, &csr);
1447     mainApp.generateCSR(alternativeNames, challengePassword, city, commonName,
1448                         contactPerson, country, email, givenName, initials,
1449                         keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage,
1450                         organization, organizationalUnit, state, surname,
1451                         unstructuredName);
1452     sleep(10);
1453     EXPECT_TRUE(fs::exists(CSRPath));
1454     EXPECT_TRUE(fs::exists(privateKeyPath));
1455 }
1456 
1457 /** @brief Check RSA key is generated during application startup*/
1458 TEST_F(TestCertificates, TestGenerateRSAPrivateKeyFile)
1459 {
1460     std::string endpoint("https");
1461     CertificateType type = CertificateType::Server;
1462     std::string installPath(certDir + "/" + certificateFile);
1463     std::string verifyUnit(ManagerInTest::unitToRestartInTest);
1464     auto objPath = std::string(objectNamePrefix) + '/' +
1465                    certificateTypeToString(type) + '/' + endpoint;
1466     auto event = sdeventplus::Event::get_default();
1467 
1468     EXPECT_FALSE(fs::exists(rsaPrivateKeyFilePath));
1469     Manager manager(bus, event, objPath.c_str(), type, verifyUnit, installPath);
1470     EXPECT_TRUE(fs::exists(rsaPrivateKeyFilePath));
1471 }
1472 
1473 /**
1474  * Class to test Authorities List installation and replacement
1475  */
1476 class AuthoritiesListTest : public testing::Test
1477 {
1478   public:
1479     AuthoritiesListTest() :
1480         bus(sdbusplus::bus::new_default()),
1481         authoritiesListFolder(
1482             Certificate::generateUniqueFilePath(fs::temp_directory_path()))
1483     {
1484         fs::create_directory(authoritiesListFolder);
1485         createAuthoritiesList(maxNumAuthorityCertificates);
1486     }
1487     ~AuthoritiesListTest() override
1488     {
1489         fs::remove_all(authoritiesListFolder);
1490     }
1491 
1492   protected:
1493     // Creates a testing authorities list which consists of |count| root
1494     // certificates
1495     void createAuthoritiesList(int count)
1496     {
1497         fs::path srcFolder = fs::temp_directory_path();
1498         srcFolder = Certificate::generateUniqueFilePath(srcFolder);
1499         fs::create_directory(srcFolder);
1500         createSingleAuthority(srcFolder, "root_0");
1501         sourceAuthoritiesListFile = srcFolder / "root_0_cert";
1502         for (int i = 1; i < count; ++i)
1503         {
1504             std::string name = "root_" + std::to_string(i);
1505             createSingleAuthority(srcFolder, name);
1506             appendContentFromFile(sourceAuthoritiesListFile,
1507                                   srcFolder / (name + "_cert"));
1508         }
1509     }
1510 
1511     // Creates a single self-signed root certificate in given |path|; the key
1512     // will be |path|/|cn|_key, the cert will be |path|/|cn|_cert, and the cn
1513     // will be "/O=openbmc-project.xyz/C=US/ST=CA/CN=|cn|"
1514     static void createSingleAuthority(const std::string& path,
1515                                       const std::string& cn)
1516     {
1517         std::string key = fs::path(path) / (cn + "_key");
1518         std::string cert = fs::path(path) / (cn + "_cert");
1519         std::string cmd = "openssl req -x509 -sha256 -newkey rsa:2048 -keyout ";
1520         cmd += key + " -out " + cert + " -nodes --days 365000 ";
1521         cmd += "-subj /O=openbmc-project.xyz/CN=" + cn;
1522         ASSERT_EQ(std::system(cmd.c_str()), 0);
1523     }
1524 
1525     // Appends the content of the |from| file to the |to| file.
1526     static void appendContentFromFile(const std::string& to,
1527                                       const std::string& from)
1528     {
1529         ASSERT_NO_THROW({
1530             std::ifstream inputCertFileStream;
1531             std::ofstream outputCertFileStream;
1532             inputCertFileStream.exceptions(std::ifstream::failbit |
1533                                            std::ifstream::badbit |
1534                                            std::ifstream::eofbit);
1535             outputCertFileStream.exceptions(std::ofstream::failbit |
1536                                             std::ofstream::badbit |
1537                                             std::ofstream::eofbit);
1538             inputCertFileStream.open(from);
1539             outputCertFileStream.open(to, std::ios::app);
1540             outputCertFileStream << inputCertFileStream.rdbuf() << std::flush;
1541             inputCertFileStream.close();
1542             outputCertFileStream.close();
1543         });
1544     }
1545 
1546     // Appends the content of the |from| buffer to the |to| file.
1547     static void setContentFromString(const std::string& to,
1548                                      const std::string& from)
1549     {
1550         ASSERT_NO_THROW({
1551             std::ofstream outputCertFileStream;
1552             outputCertFileStream.exceptions(std::ofstream::failbit |
1553                                             std::ofstream::badbit |
1554                                             std::ofstream::eofbit);
1555             outputCertFileStream.open(to, std::ios::out);
1556             outputCertFileStream << from << std::flush;
1557             outputCertFileStream.close();
1558         });
1559     }
1560 
1561     // Verifies the effect of InstallAll or ReplaceAll
1562     void verifyCertificates(std::vector<std::unique_ptr<Certificate>>& certs)
1563     {
1564         // The trust bundle file has been copied over
1565         EXPECT_FALSE(fs::is_empty(authoritiesListFolder));
1566         EXPECT_TRUE(
1567             compareFiles(authoritiesListFolder / defaultAuthoritiesListFileName,
1568                          sourceAuthoritiesListFile));
1569 
1570         ASSERT_EQ(certs.size(), maxNumAuthorityCertificates);
1571         // Check attributes and alias
1572         for (size_t i = 0; i < certs.size(); ++i)
1573         {
1574             std::string name = "root_" + std::to_string(i);
1575             EXPECT_EQ(certs[i]->subject(), "O=openbmc-project.xyz,CN=" + name);
1576             EXPECT_EQ(certs[i]->issuer(), "O=openbmc-project.xyz,CN=" + name);
1577             std::string symbolLink =
1578                 authoritiesListFolder /
1579                 (certs[i]->getCertId().substr(0, 8) + ".0");
1580             ASSERT_TRUE(fs::exists(symbolLink));
1581             compareFileAgainstString(symbolLink, certs[i]->certificateString());
1582         }
1583     }
1584 
1585     // Expects that the content of |path| file is |buffer|.
1586     static void compareFileAgainstString(const std::string& path,
1587                                          const std::string& buffer)
1588     {
1589         ASSERT_NO_THROW({
1590             std::ifstream inputCertFileStream;
1591             inputCertFileStream.exceptions(std::ifstream::failbit |
1592                                            std::ifstream::badbit |
1593                                            std::ifstream::eofbit);
1594             inputCertFileStream.open(path);
1595             std::stringstream read;
1596             read << inputCertFileStream.rdbuf();
1597             inputCertFileStream.close();
1598             EXPECT_EQ(read.str(), buffer);
1599         });
1600     };
1601 
1602     sdbusplus::bus::bus bus;
1603     fs::path authoritiesListFolder;
1604     fs::path sourceAuthoritiesListFile;
1605 };
1606 
1607 // Tests that the Authority Manager installs all the certificates in an
1608 // authorities list
1609 TEST_F(AuthoritiesListTest, InstallAll)
1610 {
1611     std::string endpoint("ldap");
1612     std::string verifyUnit(ManagerInTest::unitToRestartInTest);
1613     CertificateType type = CertificateType::Authority;
1614 
1615     std::string object = std::string(objectNamePrefix) + '/' +
1616                          certificateTypeToString(type) + '/' + endpoint;
1617     auto event = sdeventplus::Event::get_default();
1618     // Attach the bus to sd_event to service user requests
1619     bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
1620     ManagerInTest manager(bus, event, object.c_str(), type, verifyUnit,
1621                           authoritiesListFolder);
1622     EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest)))
1623         .WillOnce(Return());
1624     ASSERT_TRUE(manager.getCertificates().empty());
1625 
1626     std::vector<sdbusplus::message::object_path> objects =
1627         manager.installAll(sourceAuthoritiesListFile);
1628     for (size_t i = 0; i < manager.getCertificates().size(); ++i)
1629     {
1630         EXPECT_EQ(manager.getCertificates()[i]->getObjectPath(), objects[i]);
1631     }
1632     verifyCertificates(manager.getCertificates());
1633 }
1634 
1635 // Tests that the Authority Manager recovers from the authorities list persisted
1636 // in the installation path at boot up
1637 TEST_F(AuthoritiesListTest, RecoverAtBootUp)
1638 {
1639     std::string endpoint("ldap");
1640     std::string verifyUnit(ManagerInTest::unitToRestartInTest);
1641     CertificateType type = CertificateType::Authority;
1642 
1643     std::string object = std::string(objectNamePrefix) + '/' +
1644                          certificateTypeToString(type) + '/' + endpoint;
1645     auto event = sdeventplus::Event::get_default();
1646     // Attach the bus to sd_event to service user requests
1647     bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
1648 
1649     // Copy the trust bundle into the installation path before creating an
1650     // Authority Manager
1651     fs::copy_file(/*from=*/sourceAuthoritiesListFile,
1652                   authoritiesListFolder / defaultAuthoritiesListFileName);
1653     // Create some noise as well
1654     fs::copy_file(/*from=*/sourceAuthoritiesListFile,
1655                   authoritiesListFolder / "should_be_deleted");
1656 
1657     ManagerInTest manager(bus, event, object.c_str(), type, verifyUnit,
1658                           authoritiesListFolder);
1659 
1660     ASSERT_EQ(manager.getCertificates().size(), maxNumAuthorityCertificates);
1661 
1662     // Check attributes and alias
1663     std::unordered_set<std::string> expectedFiles = {authoritiesListFolder /
1664                                                      "trust_bundle"};
1665     std::vector<std::unique_ptr<Certificate>>& certs =
1666         manager.getCertificates();
1667     for (size_t i = 0; i < certs.size(); ++i)
1668     {
1669         std::string name = "root_" + std::to_string(i);
1670         EXPECT_EQ(certs[i]->subject(), "O=openbmc-project.xyz,CN=" + name);
1671         EXPECT_EQ(certs[i]->issuer(), "O=openbmc-project.xyz,CN=" + name);
1672         std::string symbolLink =
1673             authoritiesListFolder / (certs[i]->getCertId().substr(0, 8) + ".0");
1674         expectedFiles.insert(symbolLink);
1675         expectedFiles.insert(certs[i]->getCertFilePath());
1676         ASSERT_TRUE(fs::exists(symbolLink));
1677         compareFileAgainstString(symbolLink, certs[i]->certificateString());
1678     }
1679 
1680     // Check folder content
1681     for (auto& path : fs::directory_iterator(authoritiesListFolder))
1682     {
1683         EXPECT_NE(path, authoritiesListFolder / "should_be_deleted");
1684         expectedFiles.erase(path.path());
1685     }
1686     EXPECT_TRUE(expectedFiles.empty());
1687 }
1688 
1689 TEST_F(AuthoritiesListTest, InstallAndDelete)
1690 {
1691     std::string endpoint("ldap");
1692     std::string verifyUnit(ManagerInTest::unitToRestartInTest);
1693     CertificateType type = CertificateType::Authority;
1694 
1695     std::string object = std::string(objectNamePrefix) + '/' +
1696                          certificateTypeToString(type) + '/' + endpoint;
1697 
1698     auto event = sdeventplus::Event::get_default();
1699     // Attach the bus to sd_event to service user requests
1700     bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
1701     ManagerInTest manager(bus, event, object.c_str(), type, verifyUnit,
1702                           authoritiesListFolder);
1703     EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest)))
1704         .WillOnce(Return())
1705         .WillOnce(Return());
1706     ASSERT_TRUE(manager.getCertificates().empty());
1707     ASSERT_EQ(manager.installAll(sourceAuthoritiesListFile).size(),
1708               maxNumAuthorityCertificates);
1709     manager.deleteAll();
1710     EXPECT_TRUE(manager.getCertificates().empty());
1711     // Check folder content
1712     for (const fs::path& f : fs::directory_iterator(authoritiesListFolder))
1713     {
1714         EXPECT_THAT(f.filename(), testing::AnyOf(".", ".."));
1715     }
1716 }
1717 
1718 TEST_F(AuthoritiesListTest, InstallAllWrongManagerType)
1719 {
1720     std::string endpoint("ldap");
1721     CertificateType type = CertificateType::Server;
1722 
1723     std::string object = std::string(objectNamePrefix) + '/' +
1724                          certificateTypeToString(type) + '/' + endpoint;
1725 
1726     auto event = sdeventplus::Event::get_default();
1727     // Attach the bus to sd_event to service user requests
1728     bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
1729     ManagerInTest serverManager(bus, event, object.c_str(), type, "",
1730                                 authoritiesListFolder);
1731     EXPECT_THROW(serverManager.installAll(sourceAuthoritiesListFile),
1732                  sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed);
1733 
1734     type = CertificateType::Client;
1735     object = std::string(objectNamePrefix) + '/' +
1736              certificateTypeToString(type) + '/' + endpoint;
1737     ManagerInTest clientManager(bus, event, object.c_str(), type, "",
1738                                 authoritiesListFolder);
1739     EXPECT_THROW(clientManager.installAll(sourceAuthoritiesListFile),
1740                  sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed);
1741 }
1742 
1743 TEST_F(AuthoritiesListTest, InstallAllTwice)
1744 {
1745     std::string endpoint("ldap");
1746     std::string verifyUnit(ManagerInTest::unitToRestartInTest);
1747     CertificateType type = CertificateType::Authority;
1748 
1749     std::string object = std::string(objectNamePrefix) + '/' +
1750                          certificateTypeToString(type) + '/' + endpoint;
1751 
1752     auto event = sdeventplus::Event::get_default();
1753     // Attach the bus to sd_event to service user requests
1754     bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
1755     ManagerInTest manager(bus, event, object.c_str(), type, verifyUnit,
1756                           authoritiesListFolder);
1757     EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest)))
1758         .WillOnce(Return());
1759     ASSERT_TRUE(manager.getCertificates().empty());
1760 
1761     ASSERT_EQ(manager.installAll(sourceAuthoritiesListFile).size(),
1762               maxNumAuthorityCertificates);
1763     EXPECT_THROW(manager.installAll(sourceAuthoritiesListFile).size(),
1764                  sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed);
1765 }
1766 
1767 TEST_F(AuthoritiesListTest, InstallAllMissSourceFile)
1768 {
1769     std::string endpoint("ldap");
1770     std::string verifyUnit(ManagerInTest::unitToRestartInTest);
1771     CertificateType type = CertificateType::Authority;
1772 
1773     std::string object = std::string(objectNamePrefix) + '/' +
1774                          certificateTypeToString(type) + '/' + endpoint;
1775 
1776     auto event = sdeventplus::Event::get_default();
1777     // Attach the bus to sd_event to service user requests
1778     bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
1779     ManagerInTest manager(bus, event, object.c_str(), type, verifyUnit,
1780                           authoritiesListFolder);
1781 
1782     EXPECT_THROW(manager.installAll(authoritiesListFolder / "trust_bundle"),
1783                  InternalFailure);
1784 }
1785 
1786 TEST_F(AuthoritiesListTest, TooManyRootCertificates)
1787 {
1788     std::string endpoint("ldap");
1789     std::string verifyUnit(ManagerInTest::unitToRestartInTest);
1790     CertificateType type = CertificateType::Authority;
1791 
1792     std::string object = std::string(objectNamePrefix) + '/' +
1793                          certificateTypeToString(type) + '/' + endpoint;
1794 
1795     auto event = sdeventplus::Event::get_default();
1796     // Attach the bus to sd_event to service user requests
1797     bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
1798     ManagerInTest manager(bus, event, object.c_str(), type, verifyUnit,
1799                           authoritiesListFolder);
1800     createAuthoritiesList(maxNumAuthorityCertificates + 1);
1801     EXPECT_THROW(manager.installAll(sourceAuthoritiesListFile),
1802                  sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed);
1803 }
1804 
1805 TEST_F(AuthoritiesListTest, CertInWrongFormat)
1806 {
1807     std::string endpoint("ldap");
1808     std::string verifyUnit(ManagerInTest::unitToRestartInTest);
1809     CertificateType type = CertificateType::Authority;
1810 
1811     std::string object = std::string(objectNamePrefix) + '/' +
1812                          certificateTypeToString(type) + '/' + endpoint;
1813 
1814     auto event = sdeventplus::Event::get_default();
1815     // Attach the bus to sd_event to service user requests
1816     bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
1817 
1818     ManagerInTest manager(bus, event, object.c_str(), type, verifyUnit,
1819                           authoritiesListFolder);
1820 
1821     // Replace the authorities list with non-valid PEM encoded x509 certificate
1822     setContentFromString(sourceAuthoritiesListFile, "blah-blah");
1823     EXPECT_THROW(manager.installAll(sourceAuthoritiesListFile),
1824                  InvalidCertificate);
1825     setContentFromString(sourceAuthoritiesListFile,
1826                          "-----BEGIN CERTIFICATE-----");
1827     EXPECT_THROW(manager.installAll(sourceAuthoritiesListFile),
1828                  InvalidCertificate);
1829 }
1830 
1831 TEST_F(AuthoritiesListTest, ReplaceAll)
1832 {
1833     std::string endpoint("ldap");
1834     std::string verifyUnit(ManagerInTest::unitToRestartInTest);
1835     CertificateType type = CertificateType::Authority;
1836 
1837     std::string object = std::string(objectNamePrefix) + '/' +
1838                          certificateTypeToString(type) + '/' + endpoint;
1839 
1840     auto event = sdeventplus::Event::get_default();
1841     // Attach the bus to sd_event to service user requests
1842     bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
1843     ManagerInTest manager(bus, event, object.c_str(), type, verifyUnit,
1844                           authoritiesListFolder);
1845     EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest)))
1846         .WillOnce(Return())
1847         .WillOnce(Return());
1848     manager.installAll(sourceAuthoritiesListFile);
1849 
1850     // Replace the current list with a different list
1851     fs::remove_all(sourceAuthoritiesListFile.parent_path());
1852     createAuthoritiesList(maxNumAuthorityCertificates);
1853     std::vector<sdbusplus::message::object_path> objects =
1854         manager.replaceAll(sourceAuthoritiesListFile);
1855 
1856     for (size_t i = 0; i < manager.getCertificates().size(); ++i)
1857     {
1858         EXPECT_EQ(manager.getCertificates()[i]->getObjectPath(), objects[i]);
1859     }
1860     verifyCertificates(manager.getCertificates());
1861 }
1862 
1863 } // namespace
1864 } // namespace phosphor::certs
1865