blob: c8f071975cf809024c78eb1022e018c7c359c8a0 [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"
5
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +01006#include <openssl/bio.h>
7#include <openssl/crypto.h>
8#include <openssl/err.h>
9#include <openssl/evp.h>
10#include <openssl/pem.h>
11#include <openssl/x509v3.h>
12
Marri Devender Rao947258d2018-09-25 10:52:24 -050013#include <algorithm>
Marri Devender Rao8841dbd2019-03-04 05:43:55 -060014#include <filesystem>
Marri Devender Rao947258d2018-09-25 10:52:24 -050015#include <fstream>
16#include <iterator>
Marri Devender Raof4682712019-03-19 05:00:28 -050017#include <sdeventplus/event.hpp>
Marri Devender Rao947258d2018-09-25 10:52:24 -050018#include <string>
Marri Devender Rao13bf74e2019-03-26 01:52:17 -050019#include <xyz/openbmc_project/Certs/error.hpp>
Marri Devender Rao947258d2018-09-25 10:52:24 -050020#include <xyz/openbmc_project/Common/error.hpp>
21
Marri Devender Rao947258d2018-09-25 10:52:24 -050022#include <gtest/gtest.h>
Marri Devender Rao8841dbd2019-03-04 05:43:55 -060023namespace fs = std::filesystem;
Marri Devender Rao947258d2018-09-25 10:52:24 -050024using InternalFailure =
25 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
Marri Devender Raoe6597c52018-10-01 06:36:55 -050026using InvalidCertificate =
Marri Devender Rao13bf74e2019-03-26 01:52:17 -050027 sdbusplus::xyz::openbmc_project::Certs::Error::InvalidCertificate;
Marri Devender Rao8841dbd2019-03-04 05:43:55 -060028using namespace phosphor::certs;
Marri Devender Raoe6597c52018-10-01 06:36:55 -050029
Marri Devender Raoddf64862018-10-03 07:11:02 -050030/**
31 * Class to generate certificate file and test verification of certificate file
32 */
Marri Devender Rao8841dbd2019-03-04 05:43:55 -060033class TestCertificates : public ::testing::Test
Marri Devender Rao947258d2018-09-25 10:52:24 -050034{
35 public:
Marri Devender Rao8841dbd2019-03-04 05:43:55 -060036 TestCertificates() : bus(sdbusplus::bus::new_default())
Marri Devender Rao947258d2018-09-25 10:52:24 -050037 {
38 }
39 void SetUp() override
40 {
41 char dirTemplate[] = "/tmp/FakeCerts.XXXXXX";
42 auto dirPtr = mkdtemp(dirTemplate);
43 if (dirPtr == NULL)
44 {
45 throw std::bad_alloc();
46 }
Zbigniew Lukwinskife590c42019-12-10 12:33:50 +010047 certDir = std::string(dirPtr) + "/certs";
48 fs::create_directories(certDir);
Kowalski, Kamildb029c92019-07-08 17:09:39 +020049
50 createNewCertificate();
Marri Devender Rao947258d2018-09-25 10:52:24 -050051 }
Kowalski, Kamildb029c92019-07-08 17:09:39 +020052
Marri Devender Rao947258d2018-09-25 10:52:24 -050053 void TearDown() override
54 {
55 fs::remove_all(certDir);
56 fs::remove(certificateFile);
Marri Devender Raof4682712019-03-19 05:00:28 -050057 fs::remove(CSRFile);
58 fs::remove(privateKeyFile);
Nan Zhoucf811c42021-12-02 14:56:17 -080059 fs::remove_all("demoCA");
Marri Devender Rao947258d2018-09-25 10:52:24 -050060 }
61
Kowalski, Kamildb029c92019-07-08 17:09:39 +020062 void createNewCertificate(bool setNewCertId = false)
63 {
64 certificateFile = "cert.pem";
65 CSRFile = "domain.csr";
66 privateKeyFile = "privkey.pem";
67 rsaPrivateKeyFilePath = certDir + "/.rsaprivkey.pem";
68 std::string cmd = "openssl req -x509 -sha256 -newkey rsa:2048 ";
Nan Zhoucf811c42021-12-02 14:56:17 -080069 cmd += "-keyout cert.pem -out cert.pem -days 365000 -nodes";
Kowalski, Kamildb029c92019-07-08 17:09:39 +020070 cmd += " -subj /O=openbmc-project.xyz/CN=localhost";
71
72 if (setNewCertId)
73 {
74 cmd += std::to_string(certId++);
75 }
76
77 auto val = std::system(cmd.c_str());
78 if (val)
79 {
80 std::cout << "COMMAND Error: " << val << std::endl;
81 }
82 }
83
Nan Zhoucf811c42021-12-02 14:56:17 -080084 void createNeverExpiredRootCertificate()
85 {
86 // remove the old cert
87 fs::remove(certificateFile);
88
89 // The following routines create a cert that has NotBefore
90 // set to 1970/01/01 and NotAfter set to 9999/12/31 via the
91 // OpenSSL CA application.
92 certificateFile = "cert.pem";
93 ASSERT_EQ(std::system("mkdir -p demoCA"), 0);
94 ASSERT_EQ(std::system("mkdir -p demoCA/private/"), 0);
95 ASSERT_EQ(std::system("mkdir -p demoCA/newcerts/"), 0);
96 ASSERT_EQ(std::system("touch demoCA/index.txt"), 0);
97 ASSERT_EQ(std::system("echo 1000 > demoCA/serial"), 0);
98 ASSERT_EQ(
99 std::system(
100 "openssl req -x509 -sha256 -newkey rsa:2048 -keyout "
101 "demoCA/private/cakey.pem -out demoCA/cacert.pem -nodes "
102 "-subj /O=openbmc-project.xyz/C=US/ST=CA/CN=localhost-ca"),
103 0);
104 ASSERT_EQ(std::system(
105 "openssl req -new -newkey rsa:2048 -nodes -keyout "
106 "demoCA/server.key -out demoCA/server.csr -subj "
107 "/O=openbmc-project.xyz/C=US/ST=CA/CN=localhost-server"),
108 0);
109 ASSERT_EQ(
110 std::system(
111 "openssl ca -batch -startdate 19700101000000Z -enddate "
112 "99991231235959Z -out cert.pem -infiles demoCA/server.csr"),
113 0);
114 }
115
Marri Devender Rao947258d2018-09-25 10:52:24 -0500116 bool compareFiles(const std::string& file1, const std::string& file2)
117 {
118 std::ifstream f1(file1, std::ifstream::binary | std::ifstream::ate);
119 std::ifstream f2(file2, std::ifstream::binary | std::ifstream::ate);
120
121 if (f1.fail() || f2.fail())
122 {
123 return false; // file problem
124 }
125
126 if (f1.tellg() != f2.tellg())
127 {
128 return false; // size mismatch
129 }
130
131 // seek back to beginning and use std::equal to compare contents
132 f1.seekg(0, std::ifstream::beg);
133 f2.seekg(0, std::ifstream::beg);
134 return std::equal(std::istreambuf_iterator<char>(f1.rdbuf()),
135 std::istreambuf_iterator<char>(),
136 std::istreambuf_iterator<char>(f2.rdbuf()));
137 }
138
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100139 std::string getCertSubjectNameHash(const std::string& certFilePath)
140 {
141 std::unique_ptr<X509, decltype(&::X509_free)> cert(X509_new(),
142 ::X509_free);
143 if (!cert)
144 {
145 std::string();
146 }
147
148 std::unique_ptr<BIO, decltype(&::BIO_free)> bioCert(
149 BIO_new_file(certFilePath.c_str(), "rb"), ::BIO_free);
150 if (!bioCert)
151 {
152 std::string();
153 }
154
155 X509* x509 = cert.get();
156 if (!PEM_read_bio_X509(bioCert.get(), &x509, nullptr, nullptr))
157 {
158 std::string();
159 }
160
161 unsigned long hash = X509_subject_name_hash(cert.get());
162 static constexpr auto AUTH_CERT_HASH_LENGTH = 9;
163 char hashBuf[AUTH_CERT_HASH_LENGTH];
164 sprintf(hashBuf, "%08lx", hash);
165 return std::string(hashBuf);
166 }
167
Marri Devender Rao947258d2018-09-25 10:52:24 -0500168 protected:
169 sdbusplus::bus::bus bus;
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -0500170 std::string certificateFile, CSRFile, privateKeyFile, rsaPrivateKeyFilePath;
Marri Devender Rao947258d2018-09-25 10:52:24 -0500171
172 std::string certDir;
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200173 uint64_t certId;
Marri Devender Rao947258d2018-09-25 10:52:24 -0500174};
175
176class MainApp
177{
178 public:
Marri Devender Raof4682712019-03-19 05:00:28 -0500179 MainApp(phosphor::certs::Manager* manager,
180 phosphor::certs::CSR* csr = nullptr) :
181 manager(manager),
Patrick Williamse129be32021-04-30 20:35:19 -0500182 csr_(csr)
Marri Devender Rao947258d2018-09-25 10:52:24 -0500183 {
184 }
185 void install(std::string& path)
186 {
187 manager->install(path);
188 }
Marri Devender Rao9abfae82018-10-03 08:10:35 -0500189 void delete_()
190 {
Zbigniew Kurzynskia3bb38f2019-09-17 13:34:25 +0200191 manager->deleteAll();
Marri Devender Rao9abfae82018-10-03 08:10:35 -0500192 }
Marri Devender Raof4682712019-03-19 05:00:28 -0500193
194 std::string generateCSR(std::vector<std::string> alternativeNames,
195 std::string challengePassword, std::string city,
196 std::string commonName, std::string contactPerson,
197 std::string country, std::string email,
198 std::string givenName, std::string initials,
199 int64_t keyBitLength, std::string keyCurveId,
200 std::string keyPairAlgorithm,
201 std::vector<std::string> keyUsage,
202 std::string organization,
203 std::string organizationalUnit, std::string state,
204 std::string surname, std::string unstructuredName)
205 {
206 return (manager->generateCSR(
207 alternativeNames, challengePassword, city, commonName,
208 contactPerson, country, email, givenName, initials, keyBitLength,
209 keyCurveId, keyPairAlgorithm, keyUsage, organization,
210 organizationalUnit, state, surname, unstructuredName));
211 }
Patrick Williamse129be32021-04-30 20:35:19 -0500212 std::string csr()
213 {
214 return (csr_->csr());
215 }
Marri Devender Rao947258d2018-09-25 10:52:24 -0500216 phosphor::certs::Manager* manager;
Patrick Williamse129be32021-04-30 20:35:19 -0500217 phosphor::certs::CSR* csr_;
Marri Devender Rao947258d2018-09-25 10:52:24 -0500218};
219
Marri Devender Rao947258d2018-09-25 10:52:24 -0500220/** @brief Check if server install routine is invoked for server setup
221 */
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600222TEST_F(TestCertificates, InvokeServerInstall)
Marri Devender Rao947258d2018-09-25 10:52:24 -0500223{
224 std::string endpoint("https");
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600225 std::string unit("");
Marri Devender Rao947258d2018-09-25 10:52:24 -0500226 std::string type("server");
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600227 std::string installPath(certDir + "/" + certificateFile);
228 std::string verifyPath(installPath);
229 UnitsToRestart verifyUnit(unit);
Marri Devender Rao947258d2018-09-25 10:52:24 -0500230 auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500231 auto event = sdeventplus::Event::get_default();
232 // Attach the bus to sd_event to service user requests
233 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
234 Manager manager(bus, event, objPath.c_str(), type, std::move(unit),
235 std::move(installPath));
236 MainApp mainApp(&manager);
237 mainApp.install(certificateFile);
Marri Devender Rao947258d2018-09-25 10:52:24 -0500238 EXPECT_TRUE(fs::exists(verifyPath));
239}
240
241/** @brief Check if client install routine is invoked for client setup
242 */
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600243TEST_F(TestCertificates, InvokeClientInstall)
Marri Devender Rao947258d2018-09-25 10:52:24 -0500244{
245 std::string endpoint("ldap");
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600246 std::string unit("");
247 std::string type("server");
248 std::string installPath(certDir + "/" + certificateFile);
249 std::string verifyPath(installPath);
250 UnitsToRestart verifyUnit(unit);
Marri Devender Rao947258d2018-09-25 10:52:24 -0500251 auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500252 auto event = sdeventplus::Event::get_default();
253 // Attach the bus to sd_event to service user requests
254 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
255 Manager manager(bus, event, objPath.c_str(), type, std::move(unit),
256 std::move(installPath));
257 MainApp mainApp(&manager);
258 mainApp.install(certificateFile);
Jayanth Othayothb50789c2018-10-09 07:13:54 -0500259 EXPECT_TRUE(fs::exists(verifyPath));
260}
261
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200262/** @brief Check if storage install routine is invoked for storage setup
Jayanth Othayothb50789c2018-10-09 07:13:54 -0500263 */
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600264TEST_F(TestCertificates, InvokeAuthorityInstall)
Jayanth Othayothb50789c2018-10-09 07:13:54 -0500265{
266 std::string endpoint("ldap");
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600267 std::string unit("");
Jayanth Othayothb50789c2018-10-09 07:13:54 -0500268 std::string type("authority");
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200269 std::string verifyDir(certDir);
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600270 UnitsToRestart verifyUnit(unit);
Jayanth Othayothb50789c2018-10-09 07:13:54 -0500271 auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500272 auto event = sdeventplus::Event::get_default();
273 // Attach the bus to sd_event to service user requests
274 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
275 Manager manager(bus, event, objPath.c_str(), type, std::move(unit),
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200276 std::move(certDir));
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500277 MainApp mainApp(&manager);
Nan Zhoucf811c42021-12-02 14:56:17 -0800278 // install the default certificate that's valid from today to 100 years
279 // later
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500280 mainApp.install(certificateFile);
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200281
282 std::vector<std::unique_ptr<Certificate>>& certs =
283 manager.getCertificates();
284
Nan Zhoucf811c42021-12-02 14:56:17 -0800285 ASSERT_EQ(certs.size(), 1);
286 // check some attributes as well
287 EXPECT_EQ(certs.front()->validNotAfter() - certs.front()->validNotBefore(),
288 365000ULL * 24 * 3600);
289 EXPECT_EQ(certs.front()->subject(), "O=openbmc-project.xyz,CN=localhost");
290 EXPECT_EQ(certs.front()->issuer(), "O=openbmc-project.xyz,CN=localhost");
291
292 std::string verifyPath =
293 verifyDir + "/" + getCertSubjectNameHash(certificateFile) + ".0";
294
295 // Check that certificate has been created at installation directory
296 EXPECT_FALSE(fs::is_empty(verifyDir));
297 EXPECT_TRUE(fs::exists(verifyPath));
298
299 // Check that installed cert is identical to input one
300 EXPECT_TRUE(compareFiles(certificateFile, verifyPath));
301}
302
303/** @brief Check if storage install routine is invoked for storage setup
304 */
305TEST_F(TestCertificates, InvokeAuthorityInstallNeverExpiredRootCert)
306{
307 std::string endpoint("ldap");
308 std::string unit("");
309 std::string type("authority");
310 std::string verifyDir(certDir);
311 UnitsToRestart verifyUnit(unit);
312 auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
313 auto event = sdeventplus::Event::get_default();
314 // Attach the bus to sd_event to service user requests
315 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
316 Manager manager(bus, event, objPath.c_str(), type, std::move(unit),
317 std::move(certDir));
318 MainApp mainApp(&manager);
319
320 // install the certificate that's valid from the Unix Epoch to Dec 31, 9999
321 createNeverExpiredRootCertificate();
322 mainApp.install(certificateFile);
323
324 std::vector<std::unique_ptr<Certificate>>& certs =
325 manager.getCertificates();
326
327 EXPECT_EQ(certs.front()->validNotBefore(), 0);
328 EXPECT_EQ(certs.front()->validNotAfter(), 253402300799ULL);
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200329
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100330 std::string verifyPath =
331 verifyDir + "/" + getCertSubjectNameHash(certificateFile) + ".0";
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200332
333 // Check that certificate has been created at installation directory
334 EXPECT_FALSE(fs::is_empty(verifyDir));
335 EXPECT_TRUE(fs::exists(verifyPath));
336
337 // Check that installed cert is identical to input one
338 EXPECT_TRUE(compareFiles(certificateFile, verifyPath));
339}
340
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100341/** @brief Check if in authority mode user can't install the same
342 * certificate twice.
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200343 */
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100344TEST_F(TestCertificates, InvokeInstallSameCertTwice)
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200345{
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200346 std::string endpoint("ldap");
347 std::string unit("");
348 std::string type("authority");
349 std::string verifyDir(certDir);
350 UnitsToRestart verifyUnit(unit);
351 auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
352 auto event = sdeventplus::Event::get_default();
353 // Attach the bus to sd_event to service user requests
354 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
355 Manager manager(bus, event, objPath.c_str(), type, std::move(unit),
356 std::move(certDir));
357 MainApp mainApp(&manager);
358 mainApp.install(certificateFile);
359
360 std::vector<std::unique_ptr<Certificate>>& certs =
361 manager.getCertificates();
362
363 EXPECT_FALSE(certs.empty());
364
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200365 // Check that certificate has been created at installation directory
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100366 std::string verifyPath =
367 verifyDir + "/" + getCertSubjectNameHash(certificateFile) + ".0";
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200368 EXPECT_FALSE(fs::is_empty(verifyDir));
369 EXPECT_TRUE(fs::exists(verifyPath));
370
371 // Check that installed cert is identical to input one
372 EXPECT_TRUE(compareFiles(certificateFile, verifyPath));
373
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100374 using NotAllowed =
375 sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200376 EXPECT_THROW(
377 {
378 try
379 {
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100380 // Try to install the same certificate second time
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200381 mainApp.install(certificateFile);
382 }
383 catch (const NotAllowed& e)
384 {
385 throw;
386 }
387 },
388 NotAllowed);
389
390 // Check that the original certificate has been not removed
391 EXPECT_FALSE(fs::is_empty(verifyDir));
Marri Devender Rao947258d2018-09-25 10:52:24 -0500392 EXPECT_TRUE(fs::exists(verifyPath));
393}
394
Zbigniew Lukwinski73d1fbf2020-01-15 15:31:12 +0100395/** @brief Check if in authority mode user can install a certificate with
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100396 * certain subject hash twice.
397 */
398TEST_F(TestCertificates, InvokeInstallSameSubjectTwice)
399{
400 std::string endpoint("ldap");
401 std::string unit("");
402 std::string type("authority");
403 std::string verifyDir(certDir);
404 UnitsToRestart verifyUnit(unit);
405 auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
406 auto event = sdeventplus::Event::get_default();
407 // Attach the bus to sd_event to service user requests
408 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
409 Manager manager(bus, event, objPath.c_str(), type, std::move(unit),
410 std::move(certDir));
411 MainApp mainApp(&manager);
412 mainApp.install(certificateFile);
413
414 std::vector<std::unique_ptr<Certificate>>& certs =
415 manager.getCertificates();
416
417 EXPECT_FALSE(certs.empty());
418
419 // Check that certificate has been created at installation directory
420 std::string verifyPath0 =
421 verifyDir + "/" + getCertSubjectNameHash(certificateFile) + ".0";
422 EXPECT_FALSE(fs::is_empty(verifyDir));
423 EXPECT_TRUE(fs::exists(verifyPath0));
424
425 // Check that installed cert is identical to input one
426 EXPECT_TRUE(compareFiles(certificateFile, verifyPath0));
427
428 // Prepare second certificate with the same subject
429 createNewCertificate();
430
Zbigniew Lukwinski73d1fbf2020-01-15 15:31:12 +0100431 // Install second certificate
432 mainApp.install(certificateFile);
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100433
434 // Expect there are exactly two certificates in the collection
Zbigniew Lukwinski73d1fbf2020-01-15 15:31:12 +0100435 EXPECT_EQ(certs.size(), 2);
436
437 // Check that certificate has been created at installation directory
438 std::string verifyPath1 =
439 verifyDir + "/" + getCertSubjectNameHash(certificateFile) + ".1";
440 EXPECT_TRUE(fs::exists(verifyPath1));
441
442 // Check that installed cert is identical to input one
443 EXPECT_TRUE(compareFiles(certificateFile, verifyPath1));
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100444
445 // Check that the original/first certificate has been not removed
446 EXPECT_FALSE(fs::is_empty(verifyDir));
447 EXPECT_TRUE(fs::exists(verifyPath0));
448}
449
450/** @brief Check if in authority mode user can't install more than
451 * AUTHORITY_CERTIFICATES_LIMIT certificates.
452 */
453TEST_F(TestCertificates, InvokeInstallAuthCertLimit)
454{
455 std::string endpoint("ldap");
456 std::string unit("");
457 std::string type("authority");
458 std::string verifyDir(certDir);
459 UnitsToRestart verifyUnit(unit);
460 auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
461 auto event = sdeventplus::Event::get_default();
462 // Attach the bus to sd_event to service user requests
463 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
464 Manager manager(bus, event, objPath.c_str(), type, std::move(unit),
465 std::move(certDir));
466 MainApp mainApp(&manager);
467
468 std::vector<std::unique_ptr<Certificate>>& certs =
469 manager.getCertificates();
470
471 std::vector<std::string> verifyPaths;
472
473 // Prepare maximum number of ceritificates
474 for (std::size_t i = 0; i < AUTHORITY_CERTIFICATES_LIMIT; ++i)
475 {
476 // Prepare new certificatate
477 createNewCertificate(true);
478
479 // Install ceritificate
480 mainApp.install(certificateFile);
481
482 // Check number of certificates in the collection
483 EXPECT_EQ(certs.size(), i + 1);
484
485 // Check that certificate has been created at installation directory
486 std::string verifyPath =
487 verifyDir + "/" + getCertSubjectNameHash(certificateFile) + ".0";
488 EXPECT_FALSE(fs::is_empty(verifyDir));
489 EXPECT_TRUE(fs::exists(verifyPath));
490
491 // Check that installed cert is identical to input one
492 EXPECT_TRUE(compareFiles(certificateFile, verifyPath));
493
494 // Save current certificate file for later check
495 verifyPaths.push_back(verifyPath);
496 }
497
498 // Prepare new certificatate
499 createNewCertificate(true);
500
501 using NotAllowed =
502 sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
503 EXPECT_THROW(
504 {
505 try
506 {
507 // Try to install one more certificate
508 mainApp.install(certificateFile);
509 }
510 catch (const NotAllowed& e)
511 {
512 throw;
513 }
514 },
515 NotAllowed);
516
517 // Check that the original certificate has been not removed
518 EXPECT_FALSE(fs::is_empty(verifyDir));
519 for (int i = 0; i < AUTHORITY_CERTIFICATES_LIMIT; ++i)
520 {
521 EXPECT_TRUE(fs::exists(verifyPaths[i]));
522 }
523}
524
Marri Devender Rao947258d2018-09-25 10:52:24 -0500525/** @brief Compare the installed certificate with the copied certificate
526 */
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600527TEST_F(TestCertificates, CompareInstalledCertificate)
Marri Devender Rao947258d2018-09-25 10:52:24 -0500528{
529 std::string endpoint("ldap");
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600530 std::string unit("");
Marri Devender Rao947258d2018-09-25 10:52:24 -0500531 std::string type("client");
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600532 std::string installPath(certDir + "/" + certificateFile);
533 std::string verifyPath(installPath);
534 UnitsToRestart verifyUnit(unit);
Marri Devender Rao947258d2018-09-25 10:52:24 -0500535 auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500536 auto event = sdeventplus::Event::get_default();
537 // Attach the bus to sd_event to service user requests
538 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
539 Manager manager(bus, event, objPath.c_str(), type, std::move(unit),
540 std::move(installPath));
541 MainApp mainApp(&manager);
542 mainApp.install(certificateFile);
Marri Devender Rao947258d2018-09-25 10:52:24 -0500543 EXPECT_TRUE(fs::exists(verifyPath));
544 EXPECT_TRUE(compareFiles(verifyPath, certificateFile));
545}
Marri Devender Raoe6597c52018-10-01 06:36:55 -0500546
547/** @brief Check if install fails if certificate file is not found
548 */
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600549TEST_F(TestCertificates, TestNoCertificateFile)
Marri Devender Raoe6597c52018-10-01 06:36:55 -0500550{
551 std::string endpoint("ldap");
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600552 std::string unit("");
Marri Devender Raoe6597c52018-10-01 06:36:55 -0500553 std::string type("client");
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600554 std::string installPath(certDir + "/" + certificateFile);
555 std::string verifyPath(installPath);
Jayanth Othayothb50789c2018-10-09 07:13:54 -0500556 std::string verifyUnit(unit);
Marri Devender Raoe6597c52018-10-01 06:36:55 -0500557 auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600558 std::string uploadFile = "nofile.pem";
Marri Devender Raoe6597c52018-10-01 06:36:55 -0500559 EXPECT_THROW(
560 {
561 try
562 {
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500563 auto event = sdeventplus::Event::get_default();
564 // Attach the bus to sd_event to service user requests
565 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
566 Manager manager(bus, event, objPath.c_str(), type,
567 std::move(unit), std::move(installPath));
568 MainApp mainApp(&manager);
569 mainApp.install(uploadFile);
Marri Devender Raoe6597c52018-10-01 06:36:55 -0500570 }
571 catch (const InternalFailure& e)
572 {
573 throw;
574 }
575 },
576 InternalFailure);
577 EXPECT_FALSE(fs::exists(verifyPath));
578}
579
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500580/** @brief Test replacing existing certificate
581 */
582TEST_F(TestCertificates, TestReplaceCertificate)
583{
584 std::string endpoint("ldap");
585 std::string unit("");
586 std::string type("server");
587 std::string installPath(certDir + "/" + certificateFile);
588 std::string verifyPath(installPath);
589 auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
590 auto event = sdeventplus::Event::get_default();
591 // Attach the bus to sd_event to service user requests
592 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
593 Manager manager(bus, event, objPath.c_str(), type, std::move(unit),
594 std::move(installPath));
595 MainApp mainApp(&manager);
596 mainApp.install(certificateFile);
597 EXPECT_TRUE(fs::exists(verifyPath));
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200598 std::vector<std::unique_ptr<Certificate>>& certs =
599 manager.getCertificates();
600 EXPECT_FALSE(certs.empty());
601 EXPECT_NE(certs[0], nullptr);
602 certs[0]->replace(certificateFile);
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500603 EXPECT_TRUE(fs::exists(verifyPath));
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200604}
605
606/** @brief Test replacing existing certificate
607 */
608TEST_F(TestCertificates, TestAuthorityReplaceCertificate)
609{
610 std::string endpoint("ldap");
611 std::string unit("");
612 std::string type("authority");
613 std::string verifyDir(certDir);
614 UnitsToRestart verifyUnit(unit);
615 auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
616 auto event = sdeventplus::Event::get_default();
617 // Attach the bus to sd_event to service user requests
618 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
619 Manager manager(bus, event, objPath.c_str(), type, std::move(unit),
620 std::move(certDir));
621 MainApp mainApp(&manager);
622 mainApp.install(certificateFile);
623
624 std::vector<std::unique_ptr<Certificate>>& certs =
625 manager.getCertificates();
626 constexpr const unsigned int REPLACE_ITERATIONS = 10;
627
628 for (unsigned int i = 0; i < REPLACE_ITERATIONS; i++)
629 {
630 // Certificate successfully installed
631 EXPECT_FALSE(certs.empty());
632
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100633 std::string verifyPath =
634 verifyDir + "/" + getCertSubjectNameHash(certificateFile) + ".0";
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200635
636 // Check that certificate has been created at installation directory
637 EXPECT_FALSE(fs::is_empty(verifyDir));
638 EXPECT_TRUE(fs::exists(verifyPath));
639
640 // Check that installed cert is identical to input one
641 EXPECT_TRUE(compareFiles(certificateFile, verifyPath));
642
643 // Create new certificate
644 createNewCertificate(true);
645
646 certs[0]->replace(certificateFile);
647
648 // Verify that old certificate has been removed
649 EXPECT_FALSE(fs::exists(verifyPath));
650 }
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500651}
652
Zbigniew Kurzynskia3bb38f2019-09-17 13:34:25 +0200653/** @brief Test verifiing if delete function works.
654 */
655TEST_F(TestCertificates, TestStorageDeleteCertificate)
656{
657 std::string endpoint("ldap");
658 std::string unit("");
659 std::string type("authority");
660 std::string verifyDir(certDir);
661 UnitsToRestart verifyUnit(unit);
662 auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
663 auto event = sdeventplus::Event::get_default();
664 // Attach the bus to sd_event to service user requests
665 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
666 Manager manager(bus, event, objPath.c_str(), type, std::move(unit),
667 std::move(certDir));
668 MainApp mainApp(&manager);
669
670 // Check if certificate placeholder dir is empty
671 EXPECT_TRUE(fs::is_empty(verifyDir));
672 mainApp.install(certificateFile);
673
674 // Create new certificate
675 createNewCertificate(true);
676 mainApp.install(certificateFile);
677
678 createNewCertificate(true);
679 mainApp.install(certificateFile);
680
681 std::vector<std::unique_ptr<Certificate>>& certs =
682 manager.getCertificates();
683
684 // All 3 certificates successfully installed and added to manager
685 EXPECT_EQ(certs.size(), 3);
686
687 // Check if certificate placeholder is not empty, there should be 3
688 // certificates
689 EXPECT_FALSE(fs::is_empty(verifyDir));
690
691 certs[0]->delete_();
692 EXPECT_EQ(certs.size(), 2);
693
694 certs[0]->delete_();
695 EXPECT_EQ(certs.size(), 1);
696
697 certs[0]->delete_();
698 EXPECT_EQ(certs.size(), 0);
699
700 // Check if certificate placeholder is empty.
701 EXPECT_TRUE(fs::is_empty(verifyDir));
702}
703
Marri Devender Raoe6597c52018-10-01 06:36:55 -0500704/** @brief Check if install fails if certificate file is empty
705 */
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600706TEST_F(TestCertificates, TestEmptyCertificateFile)
Marri Devender Raoe6597c52018-10-01 06:36:55 -0500707{
708 std::string endpoint("ldap");
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600709 std::string unit("");
Marri Devender Raoe6597c52018-10-01 06:36:55 -0500710 std::string type("client");
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600711 std::string installPath(certDir + "/" + certificateFile);
712 std::string verifyPath(installPath);
713 std::string verifyUnit(unit);
714 auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
Marri Devender Raoddf64862018-10-03 07:11:02 -0500715 std::string emptyFile("emptycert.pem");
Marri Devender Raoe6597c52018-10-01 06:36:55 -0500716 std::ofstream ofs;
717 ofs.open(emptyFile, std::ofstream::out);
718 ofs.close();
Marri Devender Raoe6597c52018-10-01 06:36:55 -0500719 EXPECT_THROW(
720 {
721 try
722 {
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500723 auto event = sdeventplus::Event::get_default();
724 // Attach the bus to sd_event to service user requests
725 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
726 Manager manager(bus, event, objPath.c_str(), type,
727 std::move(unit), std::move(installPath));
728 MainApp mainApp(&manager);
729 mainApp.install(emptyFile);
Marri Devender Raoe6597c52018-10-01 06:36:55 -0500730 }
731 catch (const InvalidCertificate& e)
732 {
733 throw;
734 }
735 },
736 InvalidCertificate);
737 EXPECT_FALSE(fs::exists(verifyPath));
738 fs::remove(emptyFile);
739}
740
Marri Devender Raoddf64862018-10-03 07:11:02 -0500741/** @brief Check if install fails if certificate file is corrupted
Marri Devender Raoe6597c52018-10-01 06:36:55 -0500742 */
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600743TEST_F(TestCertificates, TestInvalidCertificateFile)
Marri Devender Raoe6597c52018-10-01 06:36:55 -0500744{
745 std::string endpoint("ldap");
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600746 std::string unit("");
Marri Devender Raoe6597c52018-10-01 06:36:55 -0500747 std::string type("client");
748
Marri Devender Raoe6597c52018-10-01 06:36:55 -0500749 std::ofstream ofs;
Marri Devender Raoddf64862018-10-03 07:11:02 -0500750 ofs.open(certificateFile, std::ofstream::out);
751 ofs << "-----BEGIN CERTIFICATE-----";
752 ofs << "ADD_SOME_INVALID_DATA_INTO_FILE";
753 ofs << "-----END CERTIFICATE-----";
Marri Devender Raoe6597c52018-10-01 06:36:55 -0500754 ofs.close();
755
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600756 std::string installPath(certDir + "/" + certificateFile);
757 std::string verifyPath(installPath);
Jayanth Othayothb50789c2018-10-09 07:13:54 -0500758 std::string verifyUnit(unit);
Marri Devender Raoe6597c52018-10-01 06:36:55 -0500759 auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
Marri Devender Raoe6597c52018-10-01 06:36:55 -0500760 EXPECT_THROW(
761 {
762 try
763 {
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500764 auto event = sdeventplus::Event::get_default();
765 // Attach the bus to sd_event to service user requests
766 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
767 Manager manager(bus, event, objPath.c_str(), type,
768 std::move(unit), std::move(installPath));
769 MainApp mainApp(&manager);
770 mainApp.install(certificateFile);
Marri Devender Raoe6597c52018-10-01 06:36:55 -0500771 }
772 catch (const InvalidCertificate& e)
773 {
774 throw;
775 }
776 },
777 InvalidCertificate);
778 EXPECT_FALSE(fs::exists(verifyPath));
Marri Devender Raoe6597c52018-10-01 06:36:55 -0500779}
Marri Devender Raoddf64862018-10-03 07:11:02 -0500780
781/**
782 * Class to generate private and certificate only file and test verification
783 */
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600784class TestInvalidCertificate : public ::testing::Test
Marri Devender Raoddf64862018-10-03 07:11:02 -0500785{
786 public:
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600787 TestInvalidCertificate() : bus(sdbusplus::bus::new_default())
Marri Devender Raoddf64862018-10-03 07:11:02 -0500788 {
789 }
790 void SetUp() override
791 {
792 char dirTemplate[] = "/tmp/FakeCerts.XXXXXX";
793 auto dirPtr = mkdtemp(dirTemplate);
794 if (dirPtr == NULL)
795 {
796 throw std::bad_alloc();
797 }
Zbigniew Lukwinskife590c42019-12-10 12:33:50 +0100798 certDir = std::string(dirPtr) + "/certs";
799 fs::create_directories(certDir);
Marri Devender Raoddf64862018-10-03 07:11:02 -0500800 certificateFile = "cert.pem";
801 keyFile = "key.pem";
802 std::string cmd = "openssl req -x509 -sha256 -newkey rsa:2048 ";
803 cmd += "-keyout key.pem -out cert.pem -days 3650 ";
804 cmd += "-subj "
805 "/O=openbmc-project.xyz/CN=localhost"
806 " -nodes";
807
808 auto val = std::system(cmd.c_str());
809 if (val)
810 {
811 std::cout << "command Error: " << val << std::endl;
812 }
813 }
814 void TearDown() override
815 {
816 fs::remove_all(certDir);
817 fs::remove(certificateFile);
818 fs::remove(keyFile);
819 }
820
821 protected:
822 sdbusplus::bus::bus bus;
823 std::string certificateFile;
824 std::string keyFile;
825 std::string certDir;
826};
827
828/** @brief Check install fails if private key is missing in certificate file
829 */
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600830TEST_F(TestInvalidCertificate, TestMissingPrivateKey)
Marri Devender Raoddf64862018-10-03 07:11:02 -0500831{
832 std::string endpoint("ldap");
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600833 std::string unit("");
Marri Devender Raoddf64862018-10-03 07:11:02 -0500834 std::string type("client");
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600835 std::string installPath(certDir + "/" + certificateFile);
836 std::string verifyPath(installPath);
Jayanth Othayothb50789c2018-10-09 07:13:54 -0500837 std::string verifyUnit(unit);
Marri Devender Raoddf64862018-10-03 07:11:02 -0500838 auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600839 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);
846 Manager manager(bus, event, objPath.c_str(), type,
847 std::move(unit), std::move(installPath));
848 MainApp mainApp(&manager);
849 mainApp.install(certificateFile);
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600850 }
Marri Devender Raocd30c492019-06-12 01:40:17 -0500851 catch (const InternalFailure& e)
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600852 {
853 throw;
854 }
855 },
Marri Devender Raocd30c492019-06-12 01:40:17 -0500856 InternalFailure);
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600857 EXPECT_FALSE(fs::exists(verifyPath));
858}
859
860/** @brief Check install fails if ceritificate is missing in certificate file
861 */
862TEST_F(TestInvalidCertificate, TestMissingCeritificate)
863{
864 std::string endpoint("ldap");
865 std::string unit("");
866 std::string type("client");
867 std::string installPath(certDir + "/" + keyFile);
868 std::string verifyPath(installPath);
869 std::string verifyUnit(unit);
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600870 auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
871 EXPECT_THROW(
872 {
873 try
874 {
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500875 auto event = sdeventplus::Event::get_default();
876 // Attach the bus to sd_event to service user requests
877 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
878 Manager manager(bus, event, objPath.c_str(), type,
879 std::move(unit), std::move(installPath));
880 MainApp mainApp(&manager);
881 mainApp.install(keyFile);
Marri Devender Raoddf64862018-10-03 07:11:02 -0500882 }
Marri Devender Raocd30c492019-06-12 01:40:17 -0500883 catch (const InternalFailure& e)
Marri Devender Raoddf64862018-10-03 07:11:02 -0500884 {
885 throw;
886 }
887 },
888 InvalidCertificate);
889 EXPECT_FALSE(fs::exists(verifyPath));
890}
891
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600892/** @brief Check if error is thrown when multiple certificates are installed
893 * At present only one certificate per service is allowed
Marri Devender Raoddf64862018-10-03 07:11:02 -0500894 */
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600895TEST_F(TestCertificates, TestCertInstallNotAllowed)
Marri Devender Raoddf64862018-10-03 07:11:02 -0500896{
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600897 using NotAllowed =
898 sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
Marri Devender Raoddf64862018-10-03 07:11:02 -0500899 std::string endpoint("ldap");
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600900 std::string unit("");
Marri Devender Raoddf64862018-10-03 07:11:02 -0500901 std::string type("client");
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600902 std::string installPath(certDir + "/" + certificateFile);
903 std::string verifyPath(installPath);
Marri Devender Raoddf64862018-10-03 07:11:02 -0500904 auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
Marri Devender Raof4682712019-03-19 05:00:28 -0500905 auto event = sdeventplus::Event::get_default();
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500906 // Attach the bus to sd_event to service user requests
907 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
Marri Devender Raof4682712019-03-19 05:00:28 -0500908 Manager manager(bus, event, objPath.c_str(), type, std::move(unit),
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600909 std::move(installPath));
Marri Devender Raoddf64862018-10-03 07:11:02 -0500910 MainApp mainApp(&manager);
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600911 mainApp.install(certificateFile);
912 EXPECT_TRUE(fs::exists(verifyPath));
Marri Devender Raoddf64862018-10-03 07:11:02 -0500913 EXPECT_THROW(
914 {
915 try
916 {
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600917 // install second certificate
918 mainApp.install(certificateFile);
Marri Devender Raoddf64862018-10-03 07:11:02 -0500919 }
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600920 catch (const NotAllowed& e)
Marri Devender Raoddf64862018-10-03 07:11:02 -0500921 {
922 throw;
923 }
924 },
Marri Devender Rao8841dbd2019-03-04 05:43:55 -0600925 NotAllowed);
Marri Devender Rao9abfae82018-10-03 08:10:35 -0500926}
Marri Devender Raof4682712019-03-19 05:00:28 -0500927
928TEST_F(TestCertificates, TestGenerateCSR)
929{
930 std::string endpoint("https");
931 std::string unit("");
932 std::string type("Server");
933 std::string installPath(certDir + "/" + certificateFile);
934 std::string verifyPath(installPath);
935 std::string CSRPath(certDir + "/" + CSRFile);
936 std::string privateKeyPath(certDir + "/" + privateKeyFile);
937 std::vector<std::string> alternativeNames{"localhost1", "localhost2"};
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500938 std::string challengePassword("Password");
Marri Devender Raof4682712019-03-19 05:00:28 -0500939 std::string city("HYB");
940 std::string commonName("abc.com");
941 std::string contactPerson("Admin");
942 std::string country("IN");
943 std::string email("admin@in.ibm.com");
944 std::string givenName("givenName");
945 std::string initials("G");
946 int64_t keyBitLength(2048);
947 std::string keyCurveId("0");
948 std::string keyPairAlgorithm("RSA");
949 std::vector<std::string> keyUsage{"serverAuth", "clientAuth"};
950 std::string organization("IBM");
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500951 std::string organizationalUnit("orgUnit");
Marri Devender Raof4682712019-03-19 05:00:28 -0500952 std::string state("TS");
953 std::string surname("surname");
954 std::string unstructuredName("unstructuredName");
955 auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
956 auto event = sdeventplus::Event::get_default();
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500957 // Attach the bus to sd_event to service user requests
958 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
Marri Devender Raof4682712019-03-19 05:00:28 -0500959 Manager manager(bus, event, objPath.c_str(), type, std::move(unit),
960 std::move(installPath));
961 Status status;
962 CSR csr(bus, objPath.c_str(), CSRPath.c_str(), status);
963 MainApp mainApp(&manager, &csr);
964 mainApp.generateCSR(alternativeNames, challengePassword, city, commonName,
965 contactPerson, country, email, givenName, initials,
966 keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage,
967 organization, organizationalUnit, state, surname,
968 unstructuredName);
969 std::string csrData("");
970 // generateCSR takes considerable time to create CSR and privateKey Files
971 EXPECT_FALSE(fs::exists(CSRPath));
972 EXPECT_FALSE(fs::exists(privateKeyPath));
973 EXPECT_THROW(
974 {
975 try
976 {
Patrick Williamse129be32021-04-30 20:35:19 -0500977 csrData = csr.csr();
Marri Devender Raof4682712019-03-19 05:00:28 -0500978 }
979 catch (const InternalFailure& e)
980 {
981 throw;
982 }
983 },
984 InternalFailure);
985 // wait for 10 sec to get CSR and privateKey Files generated
986 sleep(10);
987 EXPECT_TRUE(fs::exists(CSRPath));
988 EXPECT_TRUE(fs::exists(privateKeyPath));
Patrick Williamse129be32021-04-30 20:35:19 -0500989 csrData = csr.csr();
Marri Devender Raof4682712019-03-19 05:00:28 -0500990 ASSERT_NE("", csrData.c_str());
991}
992
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500993/** @brief Check if ECC key pair is generated when user is not given algorithm
994 * type. At present RSA and EC key pair algorithm are supported
995 */
996TEST_F(TestCertificates, TestGenerateCSRwithEmptyKeyPairAlgorithm)
997{
998 std::string endpoint("https");
999 std::string unit("");
1000 std::string type("Server");
1001 std::string installPath(certDir + "/" + certificateFile);
1002 std::string verifyPath(installPath);
1003 std::string CSRPath(certDir + "/" + CSRFile);
1004 std::string privateKeyPath(certDir + "/" + privateKeyFile);
1005 std::vector<std::string> alternativeNames{"localhost1", "localhost2"};
1006 std::string challengePassword("Password");
1007 std::string city("HYB");
1008 std::string commonName("abc.com");
1009 std::string contactPerson("Admin");
1010 std::string country("IN");
1011 std::string email("admin@in.ibm.com");
1012 std::string givenName("givenName");
1013 std::string initials("G");
1014 int64_t keyBitLength(2048);
1015 std::string keyCurveId("");
1016 std::string keyPairAlgorithm("");
1017 std::vector<std::string> keyUsage{"serverAuth", "clientAuth"};
1018 std::string organization("IBM");
1019 std::string organizationalUnit("orgUnit");
1020 std::string state("TS");
1021 std::string surname("surname");
1022 std::string unstructuredName("unstructuredName");
Marri Devender Raof4682712019-03-19 05:00:28 -05001023 auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
1024 auto event = sdeventplus::Event::get_default();
1025 Manager manager(bus, event, objPath.c_str(), type, std::move(unit),
1026 std::move(installPath));
1027 Status status;
1028 CSR csr(bus, objPath.c_str(), CSRPath.c_str(), status);
1029 MainApp mainApp(&manager, &csr);
1030 mainApp.generateCSR(alternativeNames, challengePassword, city, commonName,
1031 contactPerson, country, email, givenName, initials,
1032 keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage,
1033 organization, organizationalUnit, state, surname,
1034 unstructuredName);
1035 sleep(10);
Ramesh Iyyar8a09b522019-06-07 05:23:29 -05001036 EXPECT_TRUE(fs::exists(CSRPath));
1037 EXPECT_TRUE(fs::exists(privateKeyPath));
1038}
1039
1040/** @brief Check if error is thrown when giving un supported key pair
1041 * algorithm. At present RSA and EC key pair algorithm are supported
1042 */
1043TEST_F(TestCertificates, TestGenerateCSRwithUnsupportedKeyPairAlgorithm)
1044{
1045 std::string endpoint("https");
1046 std::string unit("");
1047 std::string type("Server");
1048 std::string installPath(certDir + "/" + certificateFile);
1049 std::string verifyPath(installPath);
1050 std::string CSRPath(certDir + "/" + CSRFile);
1051 std::string privateKeyPath(certDir + "/" + privateKeyFile);
1052 std::vector<std::string> alternativeNames{"localhost1", "localhost2"};
1053 std::string challengePassword("Password");
1054 std::string city("HYB");
1055 std::string commonName("abc.com");
1056 std::string contactPerson("Admin");
1057 std::string country("IN");
1058 std::string email("admin@in.ibm.com");
1059 std::string givenName("givenName");
1060 std::string initials("G");
1061 int64_t keyBitLength(2048);
1062 std::string keyCurveId("secp521r1");
1063 std::string keyPairAlgorithm("UnSupportedAlgorithm");
1064 std::vector<std::string> keyUsage{"serverAuth", "clientAuth"};
1065 std::string organization("IBM");
1066 std::string organizationalUnit("orgUnit");
1067 std::string state("TS");
1068 std::string surname("surname");
1069 std::string unstructuredName("unstructuredName");
1070 auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
1071 auto event = sdeventplus::Event::get_default();
1072 Manager manager(bus, event, objPath.c_str(), type, std::move(unit),
1073 std::move(installPath));
1074 Status status;
1075 CSR csr(bus, objPath.c_str(), CSRPath.c_str(), status);
1076 MainApp mainApp(&manager, &csr);
1077 mainApp.generateCSR(alternativeNames, challengePassword, city, commonName,
1078 contactPerson, country, email, givenName, initials,
1079 keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage,
1080 organization, organizationalUnit, state, surname,
1081 unstructuredName);
Marri Devender Raof4682712019-03-19 05:00:28 -05001082 EXPECT_FALSE(fs::exists(CSRPath));
1083 EXPECT_FALSE(fs::exists(privateKeyPath));
1084}
Ramesh Iyyar8a09b522019-06-07 05:23:29 -05001085
1086/** @brief Check if error is thrown when NID_undef is returned for given key
1087 * curve id
1088 */
1089TEST_F(TestCertificates, TestECKeyGenerationwithNIDundefCase)
1090{
1091 std::string endpoint("https");
1092 std::string unit("");
1093 std::string type("Server");
1094 std::string installPath(certDir + "/" + certificateFile);
1095 std::string verifyPath(installPath);
1096 std::string CSRPath(certDir + "/" + CSRFile);
1097 std::string privateKeyPath(certDir + "/" + privateKeyFile);
1098 std::vector<std::string> alternativeNames{"localhost1", "localhost2"};
1099 std::string challengePassword("Password");
1100 std::string city("BLR");
1101 std::string commonName("abc.com");
1102 std::string contactPerson("Admin");
1103 std::string country("IN");
1104 std::string email("admin@in.ibm.com");
1105 std::string givenName("givenName");
1106 std::string initials("G");
1107 int64_t keyBitLength(2048);
1108 std::string keyCurveId("DummyCurveName");
1109 std::string keyPairAlgorithm("EC");
1110 std::vector<std::string> keyUsage{"serverAuth", "clientAuth"};
1111 std::string organization("IBM");
1112 std::string organizationalUnit("orgUnit");
1113 std::string state("TS");
1114 std::string surname("surname");
1115 std::string unstructuredName("unstructuredName");
1116 auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
1117 auto event = sdeventplus::Event::get_default();
1118 Manager manager(bus, event, objPath.c_str(), type, std::move(unit),
1119 std::move(installPath));
1120 Status status;
1121 CSR csr(bus, objPath.c_str(), CSRPath.c_str(), status);
1122 MainApp mainApp(&manager, &csr);
1123 mainApp.generateCSR(alternativeNames, challengePassword, city, commonName,
1124 contactPerson, country, email, givenName, initials,
1125 keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage,
1126 organization, organizationalUnit, state, surname,
1127 unstructuredName);
1128 EXPECT_FALSE(fs::exists(CSRPath));
1129 EXPECT_FALSE(fs::exists(privateKeyPath));
1130}
1131
1132/** @brief Check default Key Curve Id is used if given curve id is empty
1133 */
1134TEST_F(TestCertificates, TestECKeyGenerationwithDefaultKeyCurveId)
1135{
1136 std::string endpoint("https");
1137 std::string unit("");
1138 std::string type("Server");
1139 std::string installPath(certDir + "/" + certificateFile);
1140 std::string verifyPath(installPath);
1141 std::string CSRPath(certDir + "/" + CSRFile);
1142 std::string privateKeyPath(certDir + "/" + privateKeyFile);
1143 std::vector<std::string> alternativeNames{"localhost1", "localhost2"};
1144 std::string challengePassword("Password");
1145 std::string city("BLR");
1146 std::string commonName("abc.com");
1147 std::string contactPerson("Admin");
1148 std::string country("IN");
1149 std::string email("admin@in.ibm.com");
1150 std::string givenName("givenName");
1151 std::string initials("G");
1152 int64_t keyBitLength(2048);
1153 std::string keyCurveId("");
1154 std::string keyPairAlgorithm("EC");
1155 std::vector<std::string> keyUsage{"serverAuth", "clientAuth"};
1156 std::string organization("IBM");
1157 std::string organizationalUnit("orgUnit");
1158 std::string state("TS");
1159 std::string surname("surname");
1160 std::string unstructuredName("unstructuredName");
1161 auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
1162 auto event = sdeventplus::Event::get_default();
1163 Manager manager(bus, event, objPath.c_str(), type, std::move(unit),
1164 std::move(installPath));
1165 Status status;
1166 CSR csr(bus, objPath.c_str(), CSRPath.c_str(), status);
1167 MainApp mainApp(&manager, &csr);
1168 mainApp.generateCSR(alternativeNames, challengePassword, city, commonName,
1169 contactPerson, country, email, givenName, initials,
1170 keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage,
1171 organization, organizationalUnit, state, surname,
1172 unstructuredName);
1173 sleep(10);
1174 EXPECT_TRUE(fs::exists(CSRPath));
1175 EXPECT_TRUE(fs::exists(privateKeyPath));
1176}
1177
1178/** @brief Check if error is not thrown to generate EC key pair
1179 */
1180TEST_F(TestCertificates, TestECKeyGeneration)
1181{
1182 std::string endpoint("https");
1183 std::string unit("");
1184 std::string type("Server");
1185 std::string installPath(certDir + "/" + certificateFile);
1186 std::string verifyPath(installPath);
1187 std::string CSRPath(certDir + "/" + CSRFile);
1188 std::string privateKeyPath(certDir + "/" + privateKeyFile);
1189 std::vector<std::string> alternativeNames{"localhost1", "localhost2"};
1190 std::string challengePassword("Password");
1191 std::string city("BLR");
1192 std::string commonName("abc.com");
1193 std::string contactPerson("Admin");
1194 std::string country("IN");
1195 std::string email("admin@in.ibm.com");
1196 std::string givenName("givenName");
1197 std::string initials("G");
1198 int64_t keyBitLength(2048);
1199 std::string keyCurveId("secp521r1");
1200 std::string keyPairAlgorithm("EC");
1201 std::vector<std::string> keyUsage{"serverAuth", "clientAuth"};
1202 std::string organization("IBM");
1203 std::string organizationalUnit("orgUnit");
1204 std::string state("TS");
1205 std::string surname("surname");
1206 std::string unstructuredName("unstructuredName");
1207 auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
1208 auto event = sdeventplus::Event::get_default();
1209 Manager manager(bus, event, objPath.c_str(), type, std::move(unit),
1210 std::move(installPath));
1211 Status status;
1212 CSR csr(bus, objPath.c_str(), CSRPath.c_str(), status);
1213 MainApp mainApp(&manager, &csr);
1214 mainApp.generateCSR(alternativeNames, challengePassword, city, commonName,
1215 contactPerson, country, email, givenName, initials,
1216 keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage,
1217 organization, organizationalUnit, state, surname,
1218 unstructuredName);
1219 std::cout << "CSRPath: " << CSRPath << std::endl
1220 << "privateKeyPath: " << privateKeyPath << std::endl;
1221 sleep(10);
1222 EXPECT_TRUE(fs::exists(CSRPath));
1223 EXPECT_TRUE(fs::exists(privateKeyPath));
1224}
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -05001225
1226/** @brief Check error is thrown if giving unsupported ket bit length to
1227 * generate rsa key
1228 */
1229TEST_F(TestCertificates, TestRSAKeyWithUnsupportedKeyBitLength)
1230{
1231 std::string endpoint("https");
1232 std::string unit("");
1233 std::string type("Server");
1234 std::string installPath(certDir + "/" + certificateFile);
1235 std::string verifyPath(installPath);
1236 std::string CSRPath(certDir + "/" + CSRFile);
1237 std::string privateKeyPath(certDir + "/" + privateKeyFile);
1238 std::vector<std::string> alternativeNames{"localhost1", "localhost2"};
1239 std::string challengePassword("Password");
1240 std::string city("BLR");
1241 std::string commonName("abc.com");
1242 std::string contactPerson("Admin");
1243 std::string country("IN");
1244 std::string email("admin@in.ibm.com");
1245 std::string givenName("givenName");
1246 std::string initials("G");
1247 int64_t keyBitLength(4096);
1248 std::string keyCurveId("secp521r1");
1249 std::string keyPairAlgorithm("RSA");
1250 std::vector<std::string> keyUsage{"serverAuth", "clientAuth"};
1251 std::string organization("IBM");
1252 std::string organizationalUnit("orgUnit");
1253 std::string state("TS");
1254 std::string surname("surname");
1255 std::string unstructuredName("unstructuredName");
1256 auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
1257 auto event = sdeventplus::Event::get_default();
1258 Manager manager(bus, event, objPath.c_str(), type, std::move(unit),
1259 std::move(installPath));
1260 Status status;
1261 CSR csr(bus, objPath.c_str(), CSRPath.c_str(), status);
1262 MainApp mainApp(&manager, &csr);
1263 mainApp.generateCSR(alternativeNames, challengePassword, city, commonName,
1264 contactPerson, country, email, givenName, initials,
1265 keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage,
1266 organization, organizationalUnit, state, surname,
1267 unstructuredName);
1268 EXPECT_FALSE(fs::exists(CSRPath));
1269 EXPECT_FALSE(fs::exists(privateKeyPath));
1270}
1271
1272/** @brief Check error is thrown if generated rsa key file is not present
1273 */
1274TEST_F(TestCertificates, TestRSAKeyFileNotPresentCase)
1275{
1276 std::string endpoint("https");
1277 std::string unit("");
1278 std::string type("Server");
1279 std::string installPath(certDir + "/" + certificateFile);
1280 std::string verifyPath(installPath);
1281 std::string CSRPath(certDir + "/" + CSRFile);
1282 std::string privateKeyPath(certDir + "/" + privateKeyFile);
1283 std::vector<std::string> alternativeNames{"localhost1", "localhost2"};
1284 std::string challengePassword("Password");
1285 std::string city("BLR");
1286 std::string commonName("abc.com");
1287 std::string contactPerson("Admin");
1288 std::string country("IN");
1289 std::string email("admin@in.ibm.com");
1290 std::string givenName("givenName");
1291 std::string initials("G");
1292 int64_t keyBitLength(2048);
1293 std::string keyCurveId("secp521r1");
1294 std::string keyPairAlgorithm("RSA");
1295 std::vector<std::string> keyUsage{"serverAuth", "clientAuth"};
1296 std::string organization("IBM");
1297 std::string organizationalUnit("orgUnit");
1298 std::string state("TS");
1299 std::string surname("surname");
1300 std::string unstructuredName("unstructuredName");
1301 auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
1302 auto event = sdeventplus::Event::get_default();
1303 Manager manager(bus, event, objPath.c_str(), type, std::move(unit),
1304 std::move(installPath));
1305
1306 // Removing generated RSA key file
1307 fs::remove(rsaPrivateKeyFilePath);
1308
1309 Status status;
1310 CSR csr(bus, objPath.c_str(), CSRPath.c_str(), status);
1311 MainApp mainApp(&manager, &csr);
1312 mainApp.generateCSR(alternativeNames, challengePassword, city, commonName,
1313 contactPerson, country, email, givenName, initials,
1314 keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage,
1315 organization, organizationalUnit, state, surname,
1316 unstructuredName);
1317 EXPECT_FALSE(fs::exists(CSRPath));
1318 EXPECT_FALSE(fs::exists(privateKeyPath));
1319}
1320
1321/** @brief Check private key file is created from generated rsa key file is
1322 * `present
1323 */
1324TEST_F(TestCertificates, TestRSAKeyFromRSAKeyFileIsWrittenIntoPrivateKeyFile)
1325{
1326 std::string endpoint("https");
1327 std::string unit("");
1328 std::string type("Server");
1329 std::string installPath(certDir + "/" + certificateFile);
1330 std::string verifyPath(installPath);
1331 std::string CSRPath(certDir + "/" + CSRFile);
1332 std::string privateKeyPath(certDir + "/" + privateKeyFile);
1333 std::vector<std::string> alternativeNames{"localhost1", "localhost2"};
1334 std::string challengePassword("Password");
1335 std::string city("BLR");
1336 std::string commonName("abc.com");
1337 std::string contactPerson("Admin");
1338 std::string country("IN");
1339 std::string email("admin@in.ibm.com");
1340 std::string givenName("givenName");
1341 std::string initials("G");
1342 int64_t keyBitLength(2048);
1343 std::string keyCurveId("secp521r1");
1344 std::string keyPairAlgorithm("RSA");
1345 std::vector<std::string> keyUsage{"serverAuth", "clientAuth"};
1346 std::string organization("IBM");
1347 std::string organizationalUnit("orgUnit");
1348 std::string state("TS");
1349 std::string surname("surname");
1350 std::string unstructuredName("unstructuredName");
1351 auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
1352 auto event = sdeventplus::Event::get_default();
1353 Manager manager(bus, event, objPath.c_str(), type, std::move(unit),
1354 std::move(installPath));
1355 Status status;
1356 CSR csr(bus, objPath.c_str(), CSRPath.c_str(), status);
1357 MainApp mainApp(&manager, &csr);
1358 mainApp.generateCSR(alternativeNames, challengePassword, city, commonName,
1359 contactPerson, country, email, givenName, initials,
1360 keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage,
1361 organization, organizationalUnit, state, surname,
1362 unstructuredName);
1363 sleep(10);
1364 EXPECT_TRUE(fs::exists(CSRPath));
1365 EXPECT_TRUE(fs::exists(privateKeyPath));
1366}
1367
1368/** @brief Check RSA key is generted during application startup*/
1369TEST_F(TestCertificates, TestGenerateRSAPrivateKeyFile)
1370{
1371 std::string endpoint("https");
1372 std::string unit("");
1373 std::string type("Server");
1374 std::string installPath(certDir + "/" + certificateFile);
1375 auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
1376 auto event = sdeventplus::Event::get_default();
1377
1378 EXPECT_FALSE(fs::exists(rsaPrivateKeyFilePath));
1379 Manager manager(bus, event, objPath.c_str(), type, std::move(unit),
1380 std::move(installPath));
1381 EXPECT_TRUE(fs::exists(rsaPrivateKeyFilePath));
1382}