blob: 6ab7ae91ff1f81a67fedd23ba0d978249ba99b73 [file] [log] [blame]
Marri Devender Rao13bf74e2019-03-26 01:52:17 -05001#include "config.h"
2
Marri Devender Rao8841dbd2019-03-04 05:43:55 -06003#include "certificate.hpp"
Marri Devender Rao947258d2018-09-25 10:52:24 -05004#include "certs_manager.hpp"
Nan Zhou014be0b2021-12-28 18:00:14 -08005#include "csr.hpp"
Marri Devender Rao947258d2018-09-25 10:52:24 -05006
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +01007#include <openssl/bio.h>
Nan Zhou014be0b2021-12-28 18:00:14 -08008#include <openssl/ossl_typ.h>
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +01009#include <openssl/pem.h>
Nan Zhou014be0b2021-12-28 18:00:14 -080010#include <openssl/x509.h>
11#include <systemd/sd-event.h>
12#include <unistd.h>
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +010013
Nan Zhou014be0b2021-12-28 18:00:14 -080014#include <cstdint>
15#include <cstdio>
16#include <cstdlib>
Marri Devender Rao8841dbd2019-03-04 05:43:55 -060017#include <filesystem>
Marri Devender Rao947258d2018-09-25 10:52:24 -050018#include <fstream>
Nan Zhou014be0b2021-12-28 18:00:14 -080019#include <iostream>
Marri Devender Rao947258d2018-09-25 10:52:24 -050020#include <iterator>
Nan Zhou014be0b2021-12-28 18:00:14 -080021#include <memory>
22#include <new>
23#include <sdbusplus/bus.hpp>
Marri Devender Raof4682712019-03-19 05:00:28 -050024#include <sdeventplus/event.hpp>
Marri Devender Rao947258d2018-09-25 10:52:24 -050025#include <string>
Nan Zhou6ec13c82021-12-30 11:34:50 -080026#include <unordered_set>
Nan Zhou014be0b2021-12-28 18:00:14 -080027#include <utility>
28#include <vector>
Marri Devender Rao13bf74e2019-03-26 01:52:17 -050029#include <xyz/openbmc_project/Certs/error.hpp>
Marri Devender Rao947258d2018-09-25 10:52:24 -050030#include <xyz/openbmc_project/Common/error.hpp>
31
Nan Zhou6ec13c82021-12-30 11:34:50 -080032#include <gmock/gmock.h>
Marri Devender Rao947258d2018-09-25 10:52:24 -050033#include <gtest/gtest.h>
Nan Zhoue1289ad2021-12-28 11:02:56 -080034
35namespace phosphor::certs
36{
37namespace
38{
Marri Devender Rao8841dbd2019-03-04 05:43:55 -060039namespace fs = std::filesystem;
Nan Zhoucf06ccd2021-12-28 16:25:45 -080040using ::sdbusplus::xyz::openbmc_project::Certs::Error::InvalidCertificate;
41using ::sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
Nan Zhou6ec13c82021-12-30 11:34:50 -080042using ::testing::Eq;
43using ::testing::Return;
44// Compares two files; returns true only if the two are the same
45bool 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}
Marri Devender Raoe6597c52018-10-01 06:36:55 -050067
Marri Devender Raoddf64862018-10-03 07:11:02 -050068/**
69 * Class to generate certificate file and test verification of certificate file
70 */
Marri Devender Rao8841dbd2019-03-04 05:43:55 -060071class TestCertificates : public ::testing::Test
Marri Devender Rao947258d2018-09-25 10:52:24 -050072{
73 public:
Marri Devender Rao8841dbd2019-03-04 05:43:55 -060074 TestCertificates() : bus(sdbusplus::bus::new_default())
Marri Devender Rao947258d2018-09-25 10:52:24 -050075 {
76 }
77 void SetUp() override
78 {
79 char dirTemplate[] = "/tmp/FakeCerts.XXXXXX";
80 auto dirPtr = mkdtemp(dirTemplate);
Nan Zhoucfb58022021-12-28 11:02:26 -080081 if (dirPtr == nullptr)
Marri Devender Rao947258d2018-09-25 10:52:24 -050082 {
83 throw std::bad_alloc();
84 }
Zbigniew Lukwinskife590c42019-12-10 12:33:50 +010085 certDir = std::string(dirPtr) + "/certs";
86 fs::create_directories(certDir);
Kowalski, Kamildb029c92019-07-08 17:09:39 +020087
88 createNewCertificate();
Marri Devender Rao947258d2018-09-25 10:52:24 -050089 }
Kowalski, Kamildb029c92019-07-08 17:09:39 +020090
Marri Devender Rao947258d2018-09-25 10:52:24 -050091 void TearDown() override
92 {
93 fs::remove_all(certDir);
94 fs::remove(certificateFile);
Marri Devender Raof4682712019-03-19 05:00:28 -050095 fs::remove(CSRFile);
96 fs::remove(privateKeyFile);
Nan Zhoucf811c42021-12-02 14:56:17 -080097 fs::remove_all("demoCA");
Marri Devender Rao947258d2018-09-25 10:52:24 -050098 }
99
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200100 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 ";
Nan Zhoucf811c42021-12-02 14:56:17 -0800107 cmd += "-keyout cert.pem -out cert.pem -days 365000 -nodes";
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200108 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
Nan Zhoucf811c42021-12-02 14:56:17 -0800122 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
Marri Devender Rao947258d2018-09-25 10:52:24 -0500154 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
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100177 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
Marri Devender Rao947258d2018-09-25 10:52:24 -0500206 protected:
Patrick Williamsb3dbfb32022-07-22 19:26:57 -0500207 sdbusplus::bus_t bus;
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -0500208 std::string certificateFile, CSRFile, privateKeyFile, rsaPrivateKeyFilePath;
Marri Devender Rao947258d2018-09-25 10:52:24 -0500209
210 std::string certDir;
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200211 uint64_t certId;
Marri Devender Rao947258d2018-09-25 10:52:24 -0500212};
213
214class MainApp
215{
216 public:
Marri Devender Raof4682712019-03-19 05:00:28 -0500217 MainApp(phosphor::certs::Manager* manager,
218 phosphor::certs::CSR* csr = nullptr) :
219 manager(manager),
Patrick Williamse129be32021-04-30 20:35:19 -0500220 csr_(csr)
Marri Devender Rao947258d2018-09-25 10:52:24 -0500221 {
222 }
223 void install(std::string& path)
224 {
225 manager->install(path);
226 }
Marri Devender Rao9abfae82018-10-03 08:10:35 -0500227 void delete_()
228 {
Zbigniew Kurzynskia3bb38f2019-09-17 13:34:25 +0200229 manager->deleteAll();
Marri Devender Rao9abfae82018-10-03 08:10:35 -0500230 }
Marri Devender Raof4682712019-03-19 05:00:28 -0500231
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 }
Patrick Williamse129be32021-04-30 20:35:19 -0500250 std::string csr()
251 {
252 return (csr_->csr());
253 }
Marri Devender Rao947258d2018-09-25 10:52:24 -0500254 phosphor::certs::Manager* manager;
Patrick Williamse129be32021-04-30 20:35:19 -0500255 phosphor::certs::CSR* csr_;
Marri Devender Rao947258d2018-09-25 10:52:24 -0500256};
257
Nan Zhou6ec13c82021-12-30 11:34:50 -0800258class ManagerInTest : public phosphor::certs::Manager
259{
260 public:
261 static constexpr std::string_view unitToRestartInTest =
262 "xyz.openbmc_project.awesome-service";
Patrick Williamsb3dbfb32022-07-22 19:26:57 -0500263 ManagerInTest(sdbusplus::bus_t& bus, sdeventplus::Event& event,
Nan Zhou6ec13c82021-12-30 11:34:50 -0800264 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
Marri Devender Rao947258d2018-09-25 10:52:24 -0500273/** @brief Check if server install routine is invoked for server setup
274 */
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600275TEST_F(TestCertificates, InvokeServerInstall)
Marri Devender Rao947258d2018-09-25 10:52:24 -0500276{
277 std::string endpoint("https");
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800278 CertificateType type = CertificateType::Server;
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600279 std::string installPath(certDir + "/" + certificateFile);
280 std::string verifyPath(installPath);
Nan Zhou6ec13c82021-12-30 11:34:50 -0800281 std::string verifyUnit(ManagerInTest::unitToRestartInTest);
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800282 auto objPath = std::string(objectNamePrefix) + '/' +
283 certificateTypeToString(type) + '/' + endpoint;
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500284 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);
Nan Zhou6ec13c82021-12-30 11:34:50 -0800287 ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit,
288 installPath);
289 EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest)))
290 .WillOnce(Return());
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500291 MainApp mainApp(&manager);
292 mainApp.install(certificateFile);
Marri Devender Rao947258d2018-09-25 10:52:24 -0500293 EXPECT_TRUE(fs::exists(verifyPath));
294}
295
296/** @brief Check if client install routine is invoked for client setup
297 */
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600298TEST_F(TestCertificates, InvokeClientInstall)
Marri Devender Rao947258d2018-09-25 10:52:24 -0500299{
300 std::string endpoint("ldap");
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800301 CertificateType type = CertificateType::Server;
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600302 std::string installPath(certDir + "/" + certificateFile);
303 std::string verifyPath(installPath);
Nan Zhou6ec13c82021-12-30 11:34:50 -0800304 std::string verifyUnit(ManagerInTest::unitToRestartInTest);
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800305 auto objPath = std::string(objectNamePrefix) + '/' +
306 certificateTypeToString(type) + '/' + endpoint;
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500307 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);
Nan Zhou6ec13c82021-12-30 11:34:50 -0800310 ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit,
311 installPath);
312 EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest)))
313 .WillOnce(Return());
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500314 MainApp mainApp(&manager);
315 mainApp.install(certificateFile);
Jayanth Othayothb50789c2018-10-09 07:13:54 -0500316 EXPECT_TRUE(fs::exists(verifyPath));
317}
318
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200319/** @brief Check if storage install routine is invoked for storage setup
Jayanth Othayothb50789c2018-10-09 07:13:54 -0500320 */
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600321TEST_F(TestCertificates, InvokeAuthorityInstall)
Jayanth Othayothb50789c2018-10-09 07:13:54 -0500322{
323 std::string endpoint("ldap");
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800324 CertificateType type = CertificateType::Authority;
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200325 std::string verifyDir(certDir);
Nan Zhou6ec13c82021-12-30 11:34:50 -0800326 std::string verifyUnit(ManagerInTest::unitToRestartInTest);
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800327 auto objPath = std::string(objectNamePrefix) + '/' +
328 certificateTypeToString(type) + '/' + endpoint;
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500329 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);
Nan Zhou6ec13c82021-12-30 11:34:50 -0800332 ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit,
333 verifyDir);
334 EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest)))
335 .WillOnce(Return());
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500336 MainApp mainApp(&manager);
Nan Zhoucf811c42021-12-02 14:56:17 -0800337 // install the default certificate that's valid from today to 100 years
338 // later
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500339 mainApp.install(certificateFile);
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200340
341 std::vector<std::unique_ptr<Certificate>>& certs =
342 manager.getCertificates();
343
Nan Zhoucf811c42021-12-02 14:56:17 -0800344 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 */
364TEST_F(TestCertificates, InvokeAuthorityInstallNeverExpiredRootCert)
365{
366 std::string endpoint("ldap");
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800367 CertificateType type = CertificateType::Authority;
Nan Zhoucf811c42021-12-02 14:56:17 -0800368 std::string verifyDir(certDir);
Nan Zhou6ec13c82021-12-30 11:34:50 -0800369 std::string verifyUnit(ManagerInTest::unitToRestartInTest);
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800370 auto objPath = std::string(objectNamePrefix) + '/' +
371 certificateTypeToString(type) + '/' + endpoint;
Nan Zhoucf811c42021-12-02 14:56:17 -0800372 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);
Nan Zhou6ec13c82021-12-30 11:34:50 -0800375 ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit,
376 certDir);
377 EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest)))
378 .WillOnce(Return());
Nan Zhoucf811c42021-12-02 14:56:17 -0800379 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);
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200390
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100391 std::string verifyPath =
392 verifyDir + "/" + getCertSubjectNameHash(certificateFile) + ".0";
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200393
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
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100402/** @brief Check if in authority mode user can't install the same
403 * certificate twice.
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200404 */
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100405TEST_F(TestCertificates, InvokeInstallSameCertTwice)
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200406{
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200407 std::string endpoint("ldap");
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800408 CertificateType type = CertificateType::Authority;
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200409 std::string verifyDir(certDir);
Nan Zhou6ec13c82021-12-30 11:34:50 -0800410 std::string verifyUnit(ManagerInTest::unitToRestartInTest);
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800411 auto objPath = std::string(objectNamePrefix) + '/' +
412 certificateTypeToString(type) + '/' + endpoint;
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200413 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);
Nan Zhou6ec13c82021-12-30 11:34:50 -0800416 ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit,
417 std::move(certDir));
418 EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest)))
419 .WillOnce(Return());
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200420 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
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200428 // Check that certificate has been created at installation directory
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100429 std::string verifyPath =
430 verifyDir + "/" + getCertSubjectNameHash(certificateFile) + ".0";
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200431 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
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100437 using NotAllowed =
438 sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200439 EXPECT_THROW(
440 {
441 try
442 {
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100443 // Try to install the same certificate second time
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200444 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));
Marri Devender Rao947258d2018-09-25 10:52:24 -0500455 EXPECT_TRUE(fs::exists(verifyPath));
456}
457
Zbigniew Lukwinski73d1fbf2020-01-15 15:31:12 +0100458/** @brief Check if in authority mode user can install a certificate with
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100459 * certain subject hash twice.
460 */
461TEST_F(TestCertificates, InvokeInstallSameSubjectTwice)
462{
463 std::string endpoint("ldap");
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800464 CertificateType type = CertificateType::Authority;
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100465 std::string verifyDir(certDir);
Nan Zhou6ec13c82021-12-30 11:34:50 -0800466 std::string verifyUnit(ManagerInTest::unitToRestartInTest);
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800467 auto objPath = std::string(objectNamePrefix) + '/' +
468 certificateTypeToString(type) + '/' + endpoint;
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100469 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);
Nan Zhou6ec13c82021-12-30 11:34:50 -0800472 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());
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100477 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
Zbigniew Lukwinski73d1fbf2020-01-15 15:31:12 +0100497 // Install second certificate
498 mainApp.install(certificateFile);
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100499
500 // Expect there are exactly two certificates in the collection
Zbigniew Lukwinski73d1fbf2020-01-15 15:31:12 +0100501 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));
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100510
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
Nan Zhou718eef32021-12-28 11:03:30 -0800517 * maxNumAuthorityCertificates certificates.
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100518 */
519TEST_F(TestCertificates, InvokeInstallAuthCertLimit)
520{
521 std::string endpoint("ldap");
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800522 CertificateType type = CertificateType::Authority;
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100523 std::string verifyDir(certDir);
Nan Zhou6ec13c82021-12-30 11:34:50 -0800524 std::string verifyUnit(ManagerInTest::unitToRestartInTest);
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800525 auto objPath = std::string(objectNamePrefix) + '/' +
526 certificateTypeToString(type) + '/' + endpoint;
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100527 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);
Nan Zhou6ec13c82021-12-30 11:34:50 -0800530 ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit,
531 certDir);
532 EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest)))
533 .WillRepeatedly(Return());
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100534 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
Nan Zhou718eef32021-12-28 11:03:30 -0800542 for (std::size_t i = 0; i < maxNumAuthorityCertificates; ++i)
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100543 {
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));
Nan Zhou718eef32021-12-28 11:03:30 -0800587 for (size_t i = 0; i < maxNumAuthorityCertificates; ++i)
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100588 {
589 EXPECT_TRUE(fs::exists(verifyPaths[i]));
590 }
591}
592
Marri Devender Rao947258d2018-09-25 10:52:24 -0500593/** @brief Compare the installed certificate with the copied certificate
594 */
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600595TEST_F(TestCertificates, CompareInstalledCertificate)
Marri Devender Rao947258d2018-09-25 10:52:24 -0500596{
597 std::string endpoint("ldap");
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800598 CertificateType type = CertificateType::Client;
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600599 std::string installPath(certDir + "/" + certificateFile);
600 std::string verifyPath(installPath);
Nan Zhou6ec13c82021-12-30 11:34:50 -0800601 std::string verifyUnit(ManagerInTest::unitToRestartInTest);
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800602 auto objPath = std::string(objectNamePrefix) + '/' +
603 certificateTypeToString(type) + '/' + endpoint;
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500604 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);
Nan Zhou6ec13c82021-12-30 11:34:50 -0800607 ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit,
608 installPath);
609 EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest)))
610 .WillOnce(Return());
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500611 MainApp mainApp(&manager);
612 mainApp.install(certificateFile);
Marri Devender Rao947258d2018-09-25 10:52:24 -0500613 EXPECT_TRUE(fs::exists(verifyPath));
614 EXPECT_TRUE(compareFiles(verifyPath, certificateFile));
615}
Marri Devender Raoe6597c52018-10-01 06:36:55 -0500616
617/** @brief Check if install fails if certificate file is not found
618 */
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600619TEST_F(TestCertificates, TestNoCertificateFile)
Marri Devender Raoe6597c52018-10-01 06:36:55 -0500620{
621 std::string endpoint("ldap");
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800622 CertificateType type = CertificateType::Client;
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600623 std::string installPath(certDir + "/" + certificateFile);
624 std::string verifyPath(installPath);
Nan Zhou6ec13c82021-12-30 11:34:50 -0800625 std::string verifyUnit(ManagerInTest::unitToRestartInTest);
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800626 auto objPath = std::string(objectNamePrefix) + '/' +
627 certificateTypeToString(type) + '/' + endpoint;
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600628 std::string uploadFile = "nofile.pem";
Marri Devender Raoe6597c52018-10-01 06:36:55 -0500629 EXPECT_THROW(
630 {
631 try
632 {
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500633 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);
Nan Zhou6ec13c82021-12-30 11:34:50 -0800636 ManagerInTest manager(bus, event, objPath.c_str(), type,
637 verifyUnit, installPath);
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500638 MainApp mainApp(&manager);
639 mainApp.install(uploadFile);
Marri Devender Raoe6597c52018-10-01 06:36:55 -0500640 }
641 catch (const InternalFailure& e)
642 {
643 throw;
644 }
645 },
646 InternalFailure);
647 EXPECT_FALSE(fs::exists(verifyPath));
648}
649
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500650/** @brief Test replacing existing certificate
651 */
652TEST_F(TestCertificates, TestReplaceCertificate)
653{
654 std::string endpoint("ldap");
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800655 CertificateType type = CertificateType::Server;
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500656 std::string installPath(certDir + "/" + certificateFile);
657 std::string verifyPath(installPath);
Nan Zhou6ec13c82021-12-30 11:34:50 -0800658 std::string verifyUnit(ManagerInTest::unitToRestartInTest);
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800659 auto objPath = std::string(objectNamePrefix) + '/' +
660 certificateTypeToString(type) + '/' + endpoint;
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500661 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);
Nan Zhou6ec13c82021-12-30 11:34:50 -0800664 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());
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500669 MainApp mainApp(&manager);
670 mainApp.install(certificateFile);
671 EXPECT_TRUE(fs::exists(verifyPath));
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200672 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);
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500677 EXPECT_TRUE(fs::exists(verifyPath));
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200678}
679
680/** @brief Test replacing existing certificate
681 */
682TEST_F(TestCertificates, TestAuthorityReplaceCertificate)
683{
684 std::string endpoint("ldap");
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800685 CertificateType type = CertificateType::Authority;
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200686 std::string verifyDir(certDir);
Nan Zhou6ec13c82021-12-30 11:34:50 -0800687 std::string verifyUnit(ManagerInTest::unitToRestartInTest);
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800688 auto objPath = std::string(objectNamePrefix) + '/' +
689 certificateTypeToString(type) + '/' + endpoint;
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200690 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);
Nan Zhou6ec13c82021-12-30 11:34:50 -0800693 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());
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200699 MainApp mainApp(&manager);
700 mainApp.install(certificateFile);
701
702 std::vector<std::unique_ptr<Certificate>>& certs =
703 manager.getCertificates();
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200704
705 for (unsigned int i = 0; i < REPLACE_ITERATIONS; i++)
706 {
707 // Certificate successfully installed
708 EXPECT_FALSE(certs.empty());
709
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100710 std::string verifyPath =
711 verifyDir + "/" + getCertSubjectNameHash(certificateFile) + ".0";
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200712
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 }
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500728}
729
Zbigniew Kurzynskia3bb38f2019-09-17 13:34:25 +0200730/** @brief Test verifiing if delete function works.
731 */
732TEST_F(TestCertificates, TestStorageDeleteCertificate)
733{
734 std::string endpoint("ldap");
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800735 CertificateType type = CertificateType::Authority;
Zbigniew Kurzynskia3bb38f2019-09-17 13:34:25 +0200736 std::string verifyDir(certDir);
Nan Zhou6ec13c82021-12-30 11:34:50 -0800737 std::string verifyUnit((ManagerInTest::unitToRestartInTest));
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800738 auto objPath = std::string(objectNamePrefix) + '/' +
739 certificateTypeToString(type) + '/' + endpoint;
Zbigniew Kurzynskia3bb38f2019-09-17 13:34:25 +0200740 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);
Nan Zhou6ec13c82021-12-30 11:34:50 -0800743 ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit,
744 certDir);
745 EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest)))
746 .WillRepeatedly(Return());
Zbigniew Kurzynskia3bb38f2019-09-17 13:34:25 +0200747 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
Marri Devender Raoe6597c52018-10-01 06:36:55 -0500783/** @brief Check if install fails if certificate file is empty
784 */
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600785TEST_F(TestCertificates, TestEmptyCertificateFile)
Marri Devender Raoe6597c52018-10-01 06:36:55 -0500786{
787 std::string endpoint("ldap");
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800788 CertificateType type = CertificateType::Client;
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600789 std::string installPath(certDir + "/" + certificateFile);
790 std::string verifyPath(installPath);
Nan Zhou6ec13c82021-12-30 11:34:50 -0800791 std::string verifyUnit(ManagerInTest::unitToRestartInTest);
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800792 auto objPath = std::string(objectNamePrefix) + '/' +
793 certificateTypeToString(type) + '/' + endpoint;
Marri Devender Raoddf64862018-10-03 07:11:02 -0500794 std::string emptyFile("emptycert.pem");
Marri Devender Raoe6597c52018-10-01 06:36:55 -0500795 std::ofstream ofs;
796 ofs.open(emptyFile, std::ofstream::out);
797 ofs.close();
Marri Devender Raoe6597c52018-10-01 06:36:55 -0500798 EXPECT_THROW(
799 {
800 try
801 {
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500802 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);
Nan Zhou6ec13c82021-12-30 11:34:50 -0800805 ManagerInTest manager(bus, event, objPath.c_str(), type,
806 verifyUnit, installPath);
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500807 MainApp mainApp(&manager);
808 mainApp.install(emptyFile);
Marri Devender Raoe6597c52018-10-01 06:36:55 -0500809 }
810 catch (const InvalidCertificate& e)
811 {
812 throw;
813 }
814 },
815 InvalidCertificate);
816 EXPECT_FALSE(fs::exists(verifyPath));
817 fs::remove(emptyFile);
818}
819
Marri Devender Raoddf64862018-10-03 07:11:02 -0500820/** @brief Check if install fails if certificate file is corrupted
Marri Devender Raoe6597c52018-10-01 06:36:55 -0500821 */
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600822TEST_F(TestCertificates, TestInvalidCertificateFile)
Marri Devender Raoe6597c52018-10-01 06:36:55 -0500823{
824 std::string endpoint("ldap");
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800825 CertificateType type = CertificateType::Client;
Marri Devender Raoe6597c52018-10-01 06:36:55 -0500826
Marri Devender Raoe6597c52018-10-01 06:36:55 -0500827 std::ofstream ofs;
Marri Devender Raoddf64862018-10-03 07:11:02 -0500828 ofs.open(certificateFile, std::ofstream::out);
829 ofs << "-----BEGIN CERTIFICATE-----";
830 ofs << "ADD_SOME_INVALID_DATA_INTO_FILE";
831 ofs << "-----END CERTIFICATE-----";
Marri Devender Raoe6597c52018-10-01 06:36:55 -0500832 ofs.close();
833
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600834 std::string installPath(certDir + "/" + certificateFile);
835 std::string verifyPath(installPath);
Nan Zhou6ec13c82021-12-30 11:34:50 -0800836 std::string verifyUnit(ManagerInTest::unitToRestartInTest);
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800837 auto objPath = std::string(objectNamePrefix) + '/' +
838 certificateTypeToString(type) + '/' + endpoint;
Marri Devender Raoe6597c52018-10-01 06:36:55 -0500839 EXPECT_THROW(
840 {
841 try
842 {
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500843 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);
Nan Zhou6ec13c82021-12-30 11:34:50 -0800846 ManagerInTest manager(bus, event, objPath.c_str(), type,
847 verifyUnit, installPath);
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500848 MainApp mainApp(&manager);
849 mainApp.install(certificateFile);
Marri Devender Raoe6597c52018-10-01 06:36:55 -0500850 }
851 catch (const InvalidCertificate& e)
852 {
853 throw;
854 }
855 },
856 InvalidCertificate);
857 EXPECT_FALSE(fs::exists(verifyPath));
Marri Devender Raoe6597c52018-10-01 06:36:55 -0500858}
Marri Devender Raoddf64862018-10-03 07:11:02 -0500859
860/**
861 * Class to generate private and certificate only file and test verification
862 */
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600863class TestInvalidCertificate : public ::testing::Test
Marri Devender Raoddf64862018-10-03 07:11:02 -0500864{
865 public:
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600866 TestInvalidCertificate() : bus(sdbusplus::bus::new_default())
Marri Devender Raoddf64862018-10-03 07:11:02 -0500867 {
868 }
869 void SetUp() override
870 {
871 char dirTemplate[] = "/tmp/FakeCerts.XXXXXX";
872 auto dirPtr = mkdtemp(dirTemplate);
Nan Zhoucfb58022021-12-28 11:02:26 -0800873 if (dirPtr == nullptr)
Marri Devender Raoddf64862018-10-03 07:11:02 -0500874 {
875 throw std::bad_alloc();
876 }
Zbigniew Lukwinskife590c42019-12-10 12:33:50 +0100877 certDir = std::string(dirPtr) + "/certs";
878 fs::create_directories(certDir);
Marri Devender Raoddf64862018-10-03 07:11:02 -0500879 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:
Patrick Williamsb3dbfb32022-07-22 19:26:57 -0500901 sdbusplus::bus_t bus;
Marri Devender Raoddf64862018-10-03 07:11:02 -0500902 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 */
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600909TEST_F(TestInvalidCertificate, TestMissingPrivateKey)
Marri Devender Raoddf64862018-10-03 07:11:02 -0500910{
911 std::string endpoint("ldap");
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800912 CertificateType type = CertificateType::Client;
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600913 std::string installPath(certDir + "/" + certificateFile);
914 std::string verifyPath(installPath);
Nan Zhou6ec13c82021-12-30 11:34:50 -0800915 std::string verifyUnit(ManagerInTest::unitToRestartInTest);
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800916 auto objPath = std::string(objectNamePrefix) + '/' +
917 certificateTypeToString(type) + '/' + endpoint;
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600918 EXPECT_THROW(
919 {
920 try
921 {
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500922 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);
Nan Zhou6ec13c82021-12-30 11:34:50 -0800925 ManagerInTest manager(bus, event, objPath.c_str(), type,
926 verifyUnit, installPath);
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500927 MainApp mainApp(&manager);
928 mainApp.install(certificateFile);
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600929 }
Marri Devender Raocd30c492019-06-12 01:40:17 -0500930 catch (const InternalFailure& e)
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600931 {
932 throw;
933 }
934 },
Marri Devender Raocd30c492019-06-12 01:40:17 -0500935 InternalFailure);
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600936 EXPECT_FALSE(fs::exists(verifyPath));
937}
938
939/** @brief Check install fails if ceritificate is missing in certificate file
940 */
941TEST_F(TestInvalidCertificate, TestMissingCeritificate)
942{
943 std::string endpoint("ldap");
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800944 CertificateType type = CertificateType::Client;
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600945 std::string installPath(certDir + "/" + keyFile);
946 std::string verifyPath(installPath);
Nan Zhou6ec13c82021-12-30 11:34:50 -0800947 std::string verifyUnit(ManagerInTest::unitToRestartInTest);
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800948 auto objPath = std::string(objectNamePrefix) + '/' +
949 certificateTypeToString(type) + '/' + endpoint;
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600950 EXPECT_THROW(
951 {
952 try
953 {
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500954 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);
Nan Zhou6ec13c82021-12-30 11:34:50 -0800957 ManagerInTest manager(bus, event, objPath.c_str(), type,
958 verifyUnit, installPath);
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500959 MainApp mainApp(&manager);
960 mainApp.install(keyFile);
Marri Devender Raoddf64862018-10-03 07:11:02 -0500961 }
Marri Devender Raocd30c492019-06-12 01:40:17 -0500962 catch (const InternalFailure& e)
Marri Devender Raoddf64862018-10-03 07:11:02 -0500963 {
964 throw;
965 }
966 },
967 InvalidCertificate);
968 EXPECT_FALSE(fs::exists(verifyPath));
969}
970
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600971/** @brief Check if error is thrown when multiple certificates are installed
972 * At present only one certificate per service is allowed
Marri Devender Raoddf64862018-10-03 07:11:02 -0500973 */
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600974TEST_F(TestCertificates, TestCertInstallNotAllowed)
Marri Devender Raoddf64862018-10-03 07:11:02 -0500975{
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600976 using NotAllowed =
977 sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
Marri Devender Raoddf64862018-10-03 07:11:02 -0500978 std::string endpoint("ldap");
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800979 CertificateType type = CertificateType::Client;
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600980 std::string installPath(certDir + "/" + certificateFile);
981 std::string verifyPath(installPath);
Nan Zhou6ec13c82021-12-30 11:34:50 -0800982 std::string verifyUnit(ManagerInTest::unitToRestartInTest);
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800983 auto objPath = std::string(objectNamePrefix) + '/' +
984 certificateTypeToString(type) + '/' + endpoint;
Marri Devender Raof4682712019-03-19 05:00:28 -0500985 auto event = sdeventplus::Event::get_default();
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500986 // Attach the bus to sd_event to service user requests
987 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
Nan Zhou6ec13c82021-12-30 11:34:50 -0800988 ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit,
989 installPath);
Marri Devender Raoddf64862018-10-03 07:11:02 -0500990 MainApp mainApp(&manager);
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600991 mainApp.install(certificateFile);
992 EXPECT_TRUE(fs::exists(verifyPath));
Marri Devender Raoddf64862018-10-03 07:11:02 -0500993 EXPECT_THROW(
994 {
995 try
996 {
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600997 // install second certificate
998 mainApp.install(certificateFile);
Marri Devender Raoddf64862018-10-03 07:11:02 -0500999 }
Marri Devender Rao8841dbd2019-03-04 05:43:55 -06001000 catch (const NotAllowed& e)
Marri Devender Raoddf64862018-10-03 07:11:02 -05001001 {
1002 throw;
1003 }
1004 },
Marri Devender Rao8841dbd2019-03-04 05:43:55 -06001005 NotAllowed);
Marri Devender Rao9abfae82018-10-03 08:10:35 -05001006}
Marri Devender Raof4682712019-03-19 05:00:28 -05001007
1008TEST_F(TestCertificates, TestGenerateCSR)
1009{
1010 std::string endpoint("https");
Nan Zhoucf06ccd2021-12-28 16:25:45 -08001011 std::string unit;
1012 CertificateType type = CertificateType::Server;
Marri Devender Raof4682712019-03-19 05:00:28 -05001013 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"};
Ramesh Iyyar8a09b522019-06-07 05:23:29 -05001018 std::string challengePassword("Password");
Marri Devender Raof4682712019-03-19 05:00:28 -05001019 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");
Ramesh Iyyar8a09b522019-06-07 05:23:29 -05001031 std::string organizationalUnit("orgUnit");
Marri Devender Raof4682712019-03-19 05:00:28 -05001032 std::string state("TS");
1033 std::string surname("surname");
1034 std::string unstructuredName("unstructuredName");
Nan Zhoucf06ccd2021-12-28 16:25:45 -08001035 auto objPath = std::string(objectNamePrefix) + '/' +
1036 certificateTypeToString(type) + '/' + endpoint;
Marri Devender Raof4682712019-03-19 05:00:28 -05001037 auto event = sdeventplus::Event::get_default();
Marri Devender Raoffad1ef2019-06-03 04:54:12 -05001038 // Attach the bus to sd_event to service user requests
1039 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
Marri Devender Raof4682712019-03-19 05:00:28 -05001040 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 {
Patrick Williamse129be32021-04-30 20:35:19 -05001058 csrData = csr.csr();
Marri Devender Raof4682712019-03-19 05:00:28 -05001059 }
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));
Patrick Williamse129be32021-04-30 20:35:19 -05001070 csrData = csr.csr();
Marri Devender Raof4682712019-03-19 05:00:28 -05001071 ASSERT_NE("", csrData.c_str());
1072}
1073
Ramesh Iyyar8a09b522019-06-07 05:23:29 -05001074/** @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 */
1077TEST_F(TestCertificates, TestGenerateCSRwithEmptyKeyPairAlgorithm)
1078{
1079 std::string endpoint("https");
Nan Zhoucf06ccd2021-12-28 16:25:45 -08001080 std::string unit;
1081 CertificateType type = CertificateType::Server;
Ramesh Iyyar8a09b522019-06-07 05:23:29 -05001082 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");
Nan Zhoucf06ccd2021-12-28 16:25:45 -08001104 auto objPath = std::string(objectNamePrefix) + '/' +
1105 certificateTypeToString(type) + '/' + endpoint;
Marri Devender Raof4682712019-03-19 05:00:28 -05001106 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);
Ramesh Iyyar8a09b522019-06-07 05:23:29 -05001118 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 */
1125TEST_F(TestCertificates, TestGenerateCSRwithUnsupportedKeyPairAlgorithm)
1126{
1127 std::string endpoint("https");
Nan Zhoucf06ccd2021-12-28 16:25:45 -08001128 std::string unit;
1129 CertificateType type = CertificateType::Server;
Ramesh Iyyar8a09b522019-06-07 05:23:29 -05001130 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");
Nan Zhoucf06ccd2021-12-28 16:25:45 -08001152 auto objPath = std::string(objectNamePrefix) + '/' +
1153 certificateTypeToString(type) + '/' + endpoint;
Ramesh Iyyar8a09b522019-06-07 05:23:29 -05001154 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);
Marri Devender Raof4682712019-03-19 05:00:28 -05001165 EXPECT_FALSE(fs::exists(CSRPath));
1166 EXPECT_FALSE(fs::exists(privateKeyPath));
1167}
Ramesh Iyyar8a09b522019-06-07 05:23:29 -05001168
1169/** @brief Check if error is thrown when NID_undef is returned for given key
1170 * curve id
1171 */
1172TEST_F(TestCertificates, TestECKeyGenerationwithNIDundefCase)
1173{
1174 std::string endpoint("https");
Nan Zhoucf06ccd2021-12-28 16:25:45 -08001175 std::string unit;
1176 CertificateType type = CertificateType::Server;
Ramesh Iyyar8a09b522019-06-07 05:23:29 -05001177 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");
Nan Zhoucf06ccd2021-12-28 16:25:45 -08001199 auto objPath = std::string(objectNamePrefix) + '/' +
1200 certificateTypeToString(type) + '/' + endpoint;
Ramesh Iyyar8a09b522019-06-07 05:23:29 -05001201 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 */
1218TEST_F(TestCertificates, TestECKeyGenerationwithDefaultKeyCurveId)
1219{
1220 std::string endpoint("https");
Nan Zhoucf06ccd2021-12-28 16:25:45 -08001221 std::string unit;
1222 CertificateType type = CertificateType::Server;
Ramesh Iyyar8a09b522019-06-07 05:23:29 -05001223 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");
Nan Zhoucf06ccd2021-12-28 16:25:45 -08001245 auto objPath = std::string(objectNamePrefix) + '/' +
1246 certificateTypeToString(type) + '/' + endpoint;
Ramesh Iyyar8a09b522019-06-07 05:23:29 -05001247 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 */
1265TEST_F(TestCertificates, TestECKeyGeneration)
1266{
1267 std::string endpoint("https");
Nan Zhoucf06ccd2021-12-28 16:25:45 -08001268 std::string unit;
1269 CertificateType type = CertificateType::Server;
Ramesh Iyyar8a09b522019-06-07 05:23:29 -05001270 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");
Nan Zhoucf06ccd2021-12-28 16:25:45 -08001292 auto objPath = std::string(objectNamePrefix) + '/' +
1293 certificateTypeToString(type) + '/' + endpoint;
Ramesh Iyyar8a09b522019-06-07 05:23:29 -05001294 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}
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -05001311
Nan Zhoubf3cf752021-12-28 11:02:07 -08001312/** @brief Check error is thrown if giving unsupported key bit length to
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -05001313 * generate rsa key
1314 */
1315TEST_F(TestCertificates, TestRSAKeyWithUnsupportedKeyBitLength)
1316{
1317 std::string endpoint("https");
Nan Zhoucf06ccd2021-12-28 16:25:45 -08001318 std::string unit;
1319 CertificateType type = CertificateType::Server;
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -05001320 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");
Nan Zhoucf06ccd2021-12-28 16:25:45 -08001342 auto objPath = std::string(objectNamePrefix) + '/' +
1343 certificateTypeToString(type) + '/' + endpoint;
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -05001344 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 */
1361TEST_F(TestCertificates, TestRSAKeyFileNotPresentCase)
1362{
1363 std::string endpoint("https");
Nan Zhoucf06ccd2021-12-28 16:25:45 -08001364 std::string unit;
1365 CertificateType type = CertificateType::Server;
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -05001366 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");
Nan Zhoucf06ccd2021-12-28 16:25:45 -08001388 auto objPath = std::string(objectNamePrefix) + '/' +
1389 certificateTypeToString(type) + '/' + endpoint;
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -05001390 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 */
1412TEST_F(TestCertificates, TestRSAKeyFromRSAKeyFileIsWrittenIntoPrivateKeyFile)
1413{
1414 std::string endpoint("https");
Nan Zhoucf06ccd2021-12-28 16:25:45 -08001415 std::string unit;
1416 CertificateType type = CertificateType::Server;
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -05001417 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");
Nan Zhoucf06ccd2021-12-28 16:25:45 -08001439 auto objPath = std::string(objectNamePrefix) + '/' +
1440 certificateTypeToString(type) + '/' + endpoint;
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -05001441 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
Nan Zhoubf3cf752021-12-28 11:02:07 -08001457/** @brief Check RSA key is generated during application startup*/
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -05001458TEST_F(TestCertificates, TestGenerateRSAPrivateKeyFile)
1459{
1460 std::string endpoint("https");
Nan Zhoucf06ccd2021-12-28 16:25:45 -08001461 CertificateType type = CertificateType::Server;
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -05001462 std::string installPath(certDir + "/" + certificateFile);
Nan Zhou6ec13c82021-12-30 11:34:50 -08001463 std::string verifyUnit(ManagerInTest::unitToRestartInTest);
Nan Zhoucf06ccd2021-12-28 16:25:45 -08001464 auto objPath = std::string(objectNamePrefix) + '/' +
1465 certificateTypeToString(type) + '/' + endpoint;
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -05001466 auto event = sdeventplus::Event::get_default();
1467
1468 EXPECT_FALSE(fs::exists(rsaPrivateKeyFilePath));
Nan Zhou6ec13c82021-12-30 11:34:50 -08001469 Manager manager(bus, event, objPath.c_str(), type, verifyUnit, installPath);
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -05001470 EXPECT_TRUE(fs::exists(rsaPrivateKeyFilePath));
1471}
Nan Zhou6ec13c82021-12-30 11:34:50 -08001472
1473/**
1474 * Class to test Authorities List installation and replacement
1475 */
1476class 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
Patrick Williamsb3dbfb32022-07-22 19:26:57 -05001602 sdbusplus::bus_t bus;
Nan Zhou6ec13c82021-12-30 11:34:50 -08001603 fs::path authoritiesListFolder;
1604 fs::path sourceAuthoritiesListFile;
1605};
1606
1607// Tests that the Authority Manager installs all the certificates in an
1608// authorities list
1609TEST_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
1637TEST_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
1689TEST_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
1718TEST_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
1743TEST_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
1767TEST_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
1786TEST_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
1805TEST_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
1831TEST_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
Nan Zhoue1289ad2021-12-28 11:02:56 -08001863} // namespace
1864} // namespace phosphor::certs