113bf74e4SMarri Devender Rao #include "config.h" 213bf74e4SMarri Devender Rao 38841dbd6SMarri Devender Rao #include "certificate.hpp" 4947258dcSMarri Devender Rao #include "certs_manager.hpp" 5014be0bfSNan Zhou #include "csr.hpp" 6947258dcSMarri Devender Rao 72f3563ccSZbigniew Lukwinski #include <openssl/bio.h> 8014be0bfSNan Zhou #include <openssl/ossl_typ.h> 92f3563ccSZbigniew Lukwinski #include <openssl/pem.h> 10014be0bfSNan Zhou #include <openssl/x509.h> 11014be0bfSNan Zhou #include <systemd/sd-event.h> 12014be0bfSNan Zhou #include <unistd.h> 132f3563ccSZbigniew Lukwinski 14223e4604SPatrick Williams #include <sdbusplus/bus.hpp> 15223e4604SPatrick Williams #include <sdeventplus/event.hpp> 16223e4604SPatrick Williams #include <xyz/openbmc_project/Certs/error.hpp> 17223e4604SPatrick Williams #include <xyz/openbmc_project/Common/error.hpp> 18223e4604SPatrick Williams 19014be0bfSNan Zhou #include <cstdint> 20014be0bfSNan Zhou #include <cstdio> 21014be0bfSNan Zhou #include <cstdlib> 228841dbd6SMarri Devender Rao #include <filesystem> 23947258dcSMarri Devender Rao #include <fstream> 24014be0bfSNan Zhou #include <iostream> 25947258dcSMarri Devender Rao #include <iterator> 26014be0bfSNan Zhou #include <memory> 27014be0bfSNan Zhou #include <new> 28947258dcSMarri Devender Rao #include <string> 296ec13c8fSNan Zhou #include <unordered_set> 30014be0bfSNan Zhou #include <utility> 31014be0bfSNan Zhou #include <vector> 32947258dcSMarri Devender Rao 336ec13c8fSNan Zhou #include <gmock/gmock.h> 34947258dcSMarri Devender Rao #include <gtest/gtest.h> 35e1289adfSNan Zhou 36e1289adfSNan Zhou namespace phosphor::certs 37e1289adfSNan Zhou { 38e1289adfSNan Zhou namespace 39e1289adfSNan Zhou { 408841dbd6SMarri Devender Rao namespace fs = std::filesystem; 41cf06ccdcSNan Zhou using ::sdbusplus::xyz::openbmc_project::Certs::Error::InvalidCertificate; 42cf06ccdcSNan Zhou using ::sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; 436ec13c8fSNan Zhou using ::testing::Eq; 446ec13c8fSNan Zhou using ::testing::Return; 456ec13c8fSNan Zhou // Compares two files; returns true only if the two are the same 466ec13c8fSNan Zhou bool compareFiles(const std::string& file1, const std::string& file2) 476ec13c8fSNan Zhou { 486ec13c8fSNan Zhou std::ifstream f1(file1, std::ifstream::binary | std::ifstream::ate); 496ec13c8fSNan Zhou std::ifstream f2(file2, std::ifstream::binary | std::ifstream::ate); 506ec13c8fSNan Zhou 516ec13c8fSNan Zhou if (f1.fail() || f2.fail()) 526ec13c8fSNan Zhou { 536ec13c8fSNan Zhou return false; // file problem 546ec13c8fSNan Zhou } 556ec13c8fSNan Zhou 566ec13c8fSNan Zhou if (f1.tellg() != f2.tellg()) 576ec13c8fSNan Zhou { 586ec13c8fSNan Zhou return false; // size mismatch 596ec13c8fSNan Zhou } 606ec13c8fSNan Zhou 616ec13c8fSNan Zhou // seek back to beginning and use std::equal to compare contents 626ec13c8fSNan Zhou f1.seekg(0, std::ifstream::beg); 636ec13c8fSNan Zhou f2.seekg(0, std::ifstream::beg); 646ec13c8fSNan Zhou return std::equal(std::istreambuf_iterator<char>(f1.rdbuf()), 656ec13c8fSNan Zhou std::istreambuf_iterator<char>(), 666ec13c8fSNan Zhou std::istreambuf_iterator<char>(f2.rdbuf())); 676ec13c8fSNan Zhou } 68e6597c5bSMarri Devender Rao 69ddf64866SMarri Devender Rao /** 70ddf64866SMarri Devender Rao * Class to generate certificate file and test verification of certificate file 71ddf64866SMarri Devender Rao */ 728841dbd6SMarri Devender Rao class TestCertificates : public ::testing::Test 73947258dcSMarri Devender Rao { 74947258dcSMarri Devender Rao public: 75223e4604SPatrick Williams TestCertificates() : bus(sdbusplus::bus::new_default()) {} 76947258dcSMarri Devender Rao void SetUp() override 77947258dcSMarri Devender Rao { 78947258dcSMarri Devender Rao char dirTemplate[] = "/tmp/FakeCerts.XXXXXX"; 79947258dcSMarri Devender Rao auto dirPtr = mkdtemp(dirTemplate); 80cfb5802aSNan Zhou if (dirPtr == nullptr) 81947258dcSMarri Devender Rao { 82947258dcSMarri Devender Rao throw std::bad_alloc(); 83947258dcSMarri Devender Rao } 84fe590c4eSZbigniew Lukwinski certDir = std::string(dirPtr) + "/certs"; 85fe590c4eSZbigniew Lukwinski fs::create_directories(certDir); 86db029c95SKowalski, Kamil 87db029c95SKowalski, Kamil createNewCertificate(); 88947258dcSMarri Devender Rao } 89db029c95SKowalski, Kamil 90947258dcSMarri Devender Rao void TearDown() override 91947258dcSMarri Devender Rao { 92947258dcSMarri Devender Rao fs::remove_all(certDir); 93947258dcSMarri Devender Rao fs::remove(certificateFile); 94f4682712SMarri Devender Rao fs::remove(CSRFile); 95f4682712SMarri Devender Rao fs::remove(privateKeyFile); 96cf811c43SNan Zhou fs::remove_all("demoCA"); 97947258dcSMarri Devender Rao } 98947258dcSMarri Devender Rao 99db029c95SKowalski, Kamil void createNewCertificate(bool setNewCertId = false) 100db029c95SKowalski, Kamil { 101db029c95SKowalski, Kamil certificateFile = "cert.pem"; 102db029c95SKowalski, Kamil CSRFile = "domain.csr"; 103db029c95SKowalski, Kamil privateKeyFile = "privkey.pem"; 104db029c95SKowalski, Kamil rsaPrivateKeyFilePath = certDir + "/.rsaprivkey.pem"; 105db029c95SKowalski, Kamil std::string cmd = "openssl req -x509 -sha256 -newkey rsa:2048 "; 106cf811c43SNan Zhou cmd += "-keyout cert.pem -out cert.pem -days 365000 -nodes"; 107db029c95SKowalski, Kamil cmd += " -subj /O=openbmc-project.xyz/CN=localhost"; 108db029c95SKowalski, Kamil 109db029c95SKowalski, Kamil if (setNewCertId) 110db029c95SKowalski, Kamil { 111db029c95SKowalski, Kamil cmd += std::to_string(certId++); 112db029c95SKowalski, Kamil } 113db029c95SKowalski, Kamil 114db029c95SKowalski, Kamil auto val = std::system(cmd.c_str()); 115db029c95SKowalski, Kamil if (val) 116db029c95SKowalski, Kamil { 117db029c95SKowalski, Kamil std::cout << "COMMAND Error: " << val << std::endl; 118db029c95SKowalski, Kamil } 119db029c95SKowalski, Kamil } 120db029c95SKowalski, Kamil 121cf811c43SNan Zhou void createNeverExpiredRootCertificate() 122cf811c43SNan Zhou { 123cf811c43SNan Zhou // remove the old cert 124cf811c43SNan Zhou fs::remove(certificateFile); 125cf811c43SNan Zhou 126cf811c43SNan Zhou // The following routines create a cert that has NotBefore 127cf811c43SNan Zhou // set to 1970/01/01 and NotAfter set to 9999/12/31 via the 128cf811c43SNan Zhou // OpenSSL CA application. 129cf811c43SNan Zhou certificateFile = "cert.pem"; 130cf811c43SNan Zhou ASSERT_EQ(std::system("mkdir -p demoCA"), 0); 131cf811c43SNan Zhou ASSERT_EQ(std::system("mkdir -p demoCA/private/"), 0); 132cf811c43SNan Zhou ASSERT_EQ(std::system("mkdir -p demoCA/newcerts/"), 0); 133cf811c43SNan Zhou ASSERT_EQ(std::system("touch demoCA/index.txt"), 0); 134cf811c43SNan Zhou ASSERT_EQ(std::system("echo 1000 > demoCA/serial"), 0); 135cf811c43SNan Zhou ASSERT_EQ( 136cf811c43SNan Zhou std::system( 137cf811c43SNan Zhou "openssl req -x509 -sha256 -newkey rsa:2048 -keyout " 138cf811c43SNan Zhou "demoCA/private/cakey.pem -out demoCA/cacert.pem -nodes " 139cf811c43SNan Zhou "-subj /O=openbmc-project.xyz/C=US/ST=CA/CN=localhost-ca"), 140cf811c43SNan Zhou 0); 141cf811c43SNan Zhou ASSERT_EQ(std::system( 142cf811c43SNan Zhou "openssl req -new -newkey rsa:2048 -nodes -keyout " 143cf811c43SNan Zhou "demoCA/server.key -out demoCA/server.csr -subj " 144cf811c43SNan Zhou "/O=openbmc-project.xyz/C=US/ST=CA/CN=localhost-server"), 145cf811c43SNan Zhou 0); 146cf811c43SNan Zhou ASSERT_EQ( 147cf811c43SNan Zhou std::system( 148cf811c43SNan Zhou "openssl ca -batch -startdate 19700101000000Z -enddate " 149cf811c43SNan Zhou "99991231235959Z -out cert.pem -infiles demoCA/server.csr"), 150cf811c43SNan Zhou 0); 151cf811c43SNan Zhou } 152cf811c43SNan Zhou 153947258dcSMarri Devender Rao bool compareFiles(const std::string& file1, const std::string& file2) 154947258dcSMarri Devender Rao { 155947258dcSMarri Devender Rao std::ifstream f1(file1, std::ifstream::binary | std::ifstream::ate); 156947258dcSMarri Devender Rao std::ifstream f2(file2, std::ifstream::binary | std::ifstream::ate); 157947258dcSMarri Devender Rao 158947258dcSMarri Devender Rao if (f1.fail() || f2.fail()) 159947258dcSMarri Devender Rao { 160947258dcSMarri Devender Rao return false; // file problem 161947258dcSMarri Devender Rao } 162947258dcSMarri Devender Rao 163947258dcSMarri Devender Rao if (f1.tellg() != f2.tellg()) 164947258dcSMarri Devender Rao { 165947258dcSMarri Devender Rao return false; // size mismatch 166947258dcSMarri Devender Rao } 167947258dcSMarri Devender Rao 168947258dcSMarri Devender Rao // seek back to beginning and use std::equal to compare contents 169947258dcSMarri Devender Rao f1.seekg(0, std::ifstream::beg); 170947258dcSMarri Devender Rao f2.seekg(0, std::ifstream::beg); 171947258dcSMarri Devender Rao return std::equal(std::istreambuf_iterator<char>(f1.rdbuf()), 172947258dcSMarri Devender Rao std::istreambuf_iterator<char>(), 173947258dcSMarri Devender Rao std::istreambuf_iterator<char>(f2.rdbuf())); 174947258dcSMarri Devender Rao } 175947258dcSMarri Devender Rao 1762f3563ccSZbigniew Lukwinski std::string getCertSubjectNameHash(const std::string& certFilePath) 1772f3563ccSZbigniew Lukwinski { 1782f3563ccSZbigniew Lukwinski std::unique_ptr<X509, decltype(&::X509_free)> cert(X509_new(), 1792f3563ccSZbigniew Lukwinski ::X509_free); 1802f3563ccSZbigniew Lukwinski if (!cert) 1812f3563ccSZbigniew Lukwinski { 1822f3563ccSZbigniew Lukwinski std::string(); 1832f3563ccSZbigniew Lukwinski } 1842f3563ccSZbigniew Lukwinski 1852f3563ccSZbigniew Lukwinski std::unique_ptr<BIO, decltype(&::BIO_free)> bioCert( 1862f3563ccSZbigniew Lukwinski BIO_new_file(certFilePath.c_str(), "rb"), ::BIO_free); 1872f3563ccSZbigniew Lukwinski if (!bioCert) 1882f3563ccSZbigniew Lukwinski { 1892f3563ccSZbigniew Lukwinski std::string(); 1902f3563ccSZbigniew Lukwinski } 1912f3563ccSZbigniew Lukwinski 1922f3563ccSZbigniew Lukwinski X509* x509 = cert.get(); 1932f3563ccSZbigniew Lukwinski if (!PEM_read_bio_X509(bioCert.get(), &x509, nullptr, nullptr)) 1942f3563ccSZbigniew Lukwinski { 1952f3563ccSZbigniew Lukwinski std::string(); 1962f3563ccSZbigniew Lukwinski } 1972f3563ccSZbigniew Lukwinski 1982f3563ccSZbigniew Lukwinski unsigned long hash = X509_subject_name_hash(cert.get()); 199e3d47cd4SNan Zhou static constexpr auto authCertHashLength = 9; 200e3d47cd4SNan Zhou char hashBuf[authCertHashLength]; 2012f3563ccSZbigniew Lukwinski sprintf(hashBuf, "%08lx", hash); 2022f3563ccSZbigniew Lukwinski return std::string(hashBuf); 2032f3563ccSZbigniew Lukwinski } 2042f3563ccSZbigniew Lukwinski 205947258dcSMarri Devender Rao protected: 206b3dbfb37SPatrick Williams sdbusplus::bus_t bus; 207c6e58c7eSRamesh Iyyar std::string certificateFile, CSRFile, privateKeyFile, rsaPrivateKeyFilePath; 208947258dcSMarri Devender Rao 209947258dcSMarri Devender Rao std::string certDir; 210db029c95SKowalski, Kamil uint64_t certId; 211947258dcSMarri Devender Rao }; 212947258dcSMarri Devender Rao 213947258dcSMarri Devender Rao class MainApp 214947258dcSMarri Devender Rao { 215947258dcSMarri Devender Rao public: 216f4682712SMarri Devender Rao MainApp(phosphor::certs::Manager* manager, 217f4682712SMarri Devender Rao phosphor::certs::CSR* csr = nullptr) : 218f4682712SMarri Devender Rao manager(manager), 219e129be3bSPatrick Williams csr_(csr) 220223e4604SPatrick Williams {} 221947258dcSMarri Devender Rao void install(std::string& path) 222947258dcSMarri Devender Rao { 223947258dcSMarri Devender Rao manager->install(path); 224947258dcSMarri Devender Rao } 225f4682712SMarri Devender Rao 226f4682712SMarri Devender Rao std::string generateCSR(std::vector<std::string> alternativeNames, 227f4682712SMarri Devender Rao std::string challengePassword, std::string city, 228f4682712SMarri Devender Rao std::string commonName, std::string contactPerson, 229f4682712SMarri Devender Rao std::string country, std::string email, 230f4682712SMarri Devender Rao std::string givenName, std::string initials, 231f4682712SMarri Devender Rao int64_t keyBitLength, std::string keyCurveId, 232f4682712SMarri Devender Rao std::string keyPairAlgorithm, 233f4682712SMarri Devender Rao std::vector<std::string> keyUsage, 234f4682712SMarri Devender Rao std::string organization, 235f4682712SMarri Devender Rao std::string organizationalUnit, std::string state, 236f4682712SMarri Devender Rao std::string surname, std::string unstructuredName) 237f4682712SMarri Devender Rao { 238f4682712SMarri Devender Rao return (manager->generateCSR( 239f4682712SMarri Devender Rao alternativeNames, challengePassword, city, commonName, 240f4682712SMarri Devender Rao contactPerson, country, email, givenName, initials, keyBitLength, 241f4682712SMarri Devender Rao keyCurveId, keyPairAlgorithm, keyUsage, organization, 242f4682712SMarri Devender Rao organizationalUnit, state, surname, unstructuredName)); 243f4682712SMarri Devender Rao } 244e129be3bSPatrick Williams std::string csr() 245e129be3bSPatrick Williams { 246e129be3bSPatrick Williams return (csr_->csr()); 247e129be3bSPatrick Williams } 248947258dcSMarri Devender Rao phosphor::certs::Manager* manager; 249e129be3bSPatrick Williams phosphor::certs::CSR* csr_; 250947258dcSMarri Devender Rao }; 251947258dcSMarri Devender Rao 2526ec13c8fSNan Zhou class ManagerInTest : public phosphor::certs::Manager 2536ec13c8fSNan Zhou { 2546ec13c8fSNan Zhou public: 2556ec13c8fSNan Zhou static constexpr std::string_view unitToRestartInTest = 2566ec13c8fSNan Zhou "xyz.openbmc_project.awesome-service"; 257b3dbfb37SPatrick Williams ManagerInTest(sdbusplus::bus_t& bus, sdeventplus::Event& event, 2586ec13c8fSNan Zhou const char* path, CertificateType type, 2596ec13c8fSNan Zhou const std::string& unit, const std::string& installPath) : 2606ec13c8fSNan Zhou Manager(bus, event, path, type, unit, installPath) 261223e4604SPatrick Williams {} 2626ec13c8fSNan Zhou 2636ec13c8fSNan Zhou MOCK_METHOD(void, reloadOrReset, (const std::string&), (override)); 2646ec13c8fSNan Zhou }; 2656ec13c8fSNan Zhou 266947258dcSMarri Devender Rao /** @brief Check if server install routine is invoked for server setup 267947258dcSMarri Devender Rao */ 2688841dbd6SMarri Devender Rao TEST_F(TestCertificates, InvokeServerInstall) 269947258dcSMarri Devender Rao { 270947258dcSMarri Devender Rao std::string endpoint("https"); 271e3d47cd4SNan Zhou CertificateType type = CertificateType::server; 2728841dbd6SMarri Devender Rao std::string installPath(certDir + "/" + certificateFile); 2738841dbd6SMarri Devender Rao std::string verifyPath(installPath); 2746ec13c8fSNan Zhou std::string verifyUnit(ManagerInTest::unitToRestartInTest); 275cf06ccdcSNan Zhou auto objPath = std::string(objectNamePrefix) + '/' + 276cf06ccdcSNan Zhou certificateTypeToString(type) + '/' + endpoint; 277ffad1ef1SMarri Devender Rao auto event = sdeventplus::Event::get_default(); 278ffad1ef1SMarri Devender Rao // Attach the bus to sd_event to service user requests 279ffad1ef1SMarri Devender Rao bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 2806ec13c8fSNan Zhou ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit, 2816ec13c8fSNan Zhou installPath); 2826ec13c8fSNan Zhou EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest))) 2836ec13c8fSNan Zhou .WillOnce(Return()); 284ffad1ef1SMarri Devender Rao MainApp mainApp(&manager); 285ffad1ef1SMarri Devender Rao mainApp.install(certificateFile); 286947258dcSMarri Devender Rao EXPECT_TRUE(fs::exists(verifyPath)); 287947258dcSMarri Devender Rao } 288947258dcSMarri Devender Rao 289947258dcSMarri Devender Rao /** @brief Check if client install routine is invoked for client setup 290947258dcSMarri Devender Rao */ 2918841dbd6SMarri Devender Rao TEST_F(TestCertificates, InvokeClientInstall) 292947258dcSMarri Devender Rao { 293947258dcSMarri Devender Rao std::string endpoint("ldap"); 294e3d47cd4SNan Zhou CertificateType type = CertificateType::server; 2958841dbd6SMarri Devender Rao std::string installPath(certDir + "/" + certificateFile); 2968841dbd6SMarri Devender Rao std::string verifyPath(installPath); 2976ec13c8fSNan Zhou std::string verifyUnit(ManagerInTest::unitToRestartInTest); 298cf06ccdcSNan Zhou auto objPath = std::string(objectNamePrefix) + '/' + 299cf06ccdcSNan Zhou certificateTypeToString(type) + '/' + endpoint; 300ffad1ef1SMarri Devender Rao auto event = sdeventplus::Event::get_default(); 301ffad1ef1SMarri Devender Rao // Attach the bus to sd_event to service user requests 302ffad1ef1SMarri Devender Rao bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 3036ec13c8fSNan Zhou ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit, 3046ec13c8fSNan Zhou installPath); 3056ec13c8fSNan Zhou EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest))) 3066ec13c8fSNan Zhou .WillOnce(Return()); 307ffad1ef1SMarri Devender Rao MainApp mainApp(&manager); 308ffad1ef1SMarri Devender Rao mainApp.install(certificateFile); 309b50789ceSJayanth Othayoth EXPECT_TRUE(fs::exists(verifyPath)); 310b50789ceSJayanth Othayoth } 311b50789ceSJayanth Othayoth 312db029c95SKowalski, Kamil /** @brief Check if storage install routine is invoked for storage setup 313b50789ceSJayanth Othayoth */ 3148841dbd6SMarri Devender Rao TEST_F(TestCertificates, InvokeAuthorityInstall) 315b50789ceSJayanth Othayoth { 316*2e8fa88eSMichal Orzel std::string endpoint("truststore"); 317e3d47cd4SNan Zhou CertificateType type = CertificateType::authority; 318db029c95SKowalski, Kamil std::string verifyDir(certDir); 3196ec13c8fSNan Zhou std::string verifyUnit(ManagerInTest::unitToRestartInTest); 320cf06ccdcSNan Zhou auto objPath = std::string(objectNamePrefix) + '/' + 321cf06ccdcSNan Zhou certificateTypeToString(type) + '/' + endpoint; 322ffad1ef1SMarri Devender Rao auto event = sdeventplus::Event::get_default(); 323ffad1ef1SMarri Devender Rao // Attach the bus to sd_event to service user requests 324ffad1ef1SMarri Devender Rao bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 3256ec13c8fSNan Zhou ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit, 3266ec13c8fSNan Zhou verifyDir); 3276ec13c8fSNan Zhou EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest))) 3286ec13c8fSNan Zhou .WillOnce(Return()); 329ffad1ef1SMarri Devender Rao MainApp mainApp(&manager); 330cf811c43SNan Zhou // install the default certificate that's valid from today to 100 years 331cf811c43SNan Zhou // later 332ffad1ef1SMarri Devender Rao mainApp.install(certificateFile); 333db029c95SKowalski, Kamil 334db029c95SKowalski, Kamil std::vector<std::unique_ptr<Certificate>>& certs = 335db029c95SKowalski, Kamil manager.getCertificates(); 336db029c95SKowalski, Kamil 337cf811c43SNan Zhou ASSERT_EQ(certs.size(), 1); 338cf811c43SNan Zhou // check some attributes as well 339cf811c43SNan Zhou EXPECT_EQ(certs.front()->validNotAfter() - certs.front()->validNotBefore(), 340cf811c43SNan Zhou 365000ULL * 24 * 3600); 341cf811c43SNan Zhou EXPECT_EQ(certs.front()->subject(), "O=openbmc-project.xyz,CN=localhost"); 342cf811c43SNan Zhou EXPECT_EQ(certs.front()->issuer(), "O=openbmc-project.xyz,CN=localhost"); 343cf811c43SNan Zhou 344223e4604SPatrick Williams std::string verifyPath = verifyDir + "/" + 345223e4604SPatrick Williams getCertSubjectNameHash(certificateFile) + ".0"; 346cf811c43SNan Zhou 347cf811c43SNan Zhou // Check that certificate has been created at installation directory 348cf811c43SNan Zhou EXPECT_FALSE(fs::is_empty(verifyDir)); 349cf811c43SNan Zhou EXPECT_TRUE(fs::exists(verifyPath)); 350cf811c43SNan Zhou 351cf811c43SNan Zhou // Check that installed cert is identical to input one 352cf811c43SNan Zhou EXPECT_TRUE(compareFiles(certificateFile, verifyPath)); 353cf811c43SNan Zhou } 354cf811c43SNan Zhou 355cf811c43SNan Zhou /** @brief Check if storage install routine is invoked for storage setup 356cf811c43SNan Zhou */ 357cf811c43SNan Zhou TEST_F(TestCertificates, InvokeAuthorityInstallNeverExpiredRootCert) 358cf811c43SNan Zhou { 359*2e8fa88eSMichal Orzel std::string endpoint("truststore"); 360e3d47cd4SNan Zhou CertificateType type = CertificateType::authority; 361cf811c43SNan Zhou std::string verifyDir(certDir); 3626ec13c8fSNan Zhou std::string verifyUnit(ManagerInTest::unitToRestartInTest); 363cf06ccdcSNan Zhou auto objPath = std::string(objectNamePrefix) + '/' + 364cf06ccdcSNan Zhou certificateTypeToString(type) + '/' + endpoint; 365cf811c43SNan Zhou auto event = sdeventplus::Event::get_default(); 366cf811c43SNan Zhou // Attach the bus to sd_event to service user requests 367cf811c43SNan Zhou bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 3686ec13c8fSNan Zhou ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit, 3696ec13c8fSNan Zhou certDir); 3706ec13c8fSNan Zhou EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest))) 3716ec13c8fSNan Zhou .WillOnce(Return()); 372cf811c43SNan Zhou MainApp mainApp(&manager); 373cf811c43SNan Zhou 374cf811c43SNan Zhou // install the certificate that's valid from the Unix Epoch to Dec 31, 9999 375cf811c43SNan Zhou createNeverExpiredRootCertificate(); 376cf811c43SNan Zhou mainApp.install(certificateFile); 377cf811c43SNan Zhou 378cf811c43SNan Zhou std::vector<std::unique_ptr<Certificate>>& certs = 379cf811c43SNan Zhou manager.getCertificates(); 380cf811c43SNan Zhou 381cf811c43SNan Zhou EXPECT_EQ(certs.front()->validNotBefore(), 0); 382cf811c43SNan Zhou EXPECT_EQ(certs.front()->validNotAfter(), 253402300799ULL); 383db029c95SKowalski, Kamil 384223e4604SPatrick Williams std::string verifyPath = verifyDir + "/" + 385223e4604SPatrick Williams getCertSubjectNameHash(certificateFile) + ".0"; 386db029c95SKowalski, Kamil 387db029c95SKowalski, Kamil // Check that certificate has been created at installation directory 388db029c95SKowalski, Kamil EXPECT_FALSE(fs::is_empty(verifyDir)); 389db029c95SKowalski, Kamil EXPECT_TRUE(fs::exists(verifyPath)); 390db029c95SKowalski, Kamil 391db029c95SKowalski, Kamil // Check that installed cert is identical to input one 392db029c95SKowalski, Kamil EXPECT_TRUE(compareFiles(certificateFile, verifyPath)); 393db029c95SKowalski, Kamil } 394db029c95SKowalski, Kamil 3952f3563ccSZbigniew Lukwinski /** @brief Check if in authority mode user can't install the same 3962f3563ccSZbigniew Lukwinski * certificate twice. 397db029c95SKowalski, Kamil */ 3982f3563ccSZbigniew Lukwinski TEST_F(TestCertificates, InvokeInstallSameCertTwice) 399db029c95SKowalski, Kamil { 400*2e8fa88eSMichal Orzel std::string endpoint("truststore"); 401e3d47cd4SNan Zhou CertificateType type = CertificateType::authority; 402db029c95SKowalski, Kamil std::string verifyDir(certDir); 4036ec13c8fSNan Zhou std::string verifyUnit(ManagerInTest::unitToRestartInTest); 404cf06ccdcSNan Zhou auto objPath = std::string(objectNamePrefix) + '/' + 405cf06ccdcSNan Zhou certificateTypeToString(type) + '/' + endpoint; 406db029c95SKowalski, Kamil auto event = sdeventplus::Event::get_default(); 407db029c95SKowalski, Kamil // Attach the bus to sd_event to service user requests 408db029c95SKowalski, Kamil bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 4096ec13c8fSNan Zhou ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit, 410db029c95SKowalski, Kamil std::move(certDir)); 4116ec13c8fSNan Zhou EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest))) 4126ec13c8fSNan Zhou .WillOnce(Return()); 413db029c95SKowalski, Kamil MainApp mainApp(&manager); 414db029c95SKowalski, Kamil mainApp.install(certificateFile); 415db029c95SKowalski, Kamil 416db029c95SKowalski, Kamil std::vector<std::unique_ptr<Certificate>>& certs = 417db029c95SKowalski, Kamil manager.getCertificates(); 418db029c95SKowalski, Kamil 419db029c95SKowalski, Kamil EXPECT_FALSE(certs.empty()); 420db029c95SKowalski, Kamil 421db029c95SKowalski, Kamil // Check that certificate has been created at installation directory 422223e4604SPatrick Williams std::string verifyPath = verifyDir + "/" + 423223e4604SPatrick Williams getCertSubjectNameHash(certificateFile) + ".0"; 424db029c95SKowalski, Kamil EXPECT_FALSE(fs::is_empty(verifyDir)); 425db029c95SKowalski, Kamil EXPECT_TRUE(fs::exists(verifyPath)); 426db029c95SKowalski, Kamil 427db029c95SKowalski, Kamil // Check that installed cert is identical to input one 428db029c95SKowalski, Kamil EXPECT_TRUE(compareFiles(certificateFile, verifyPath)); 429db029c95SKowalski, Kamil 4302f3563ccSZbigniew Lukwinski using NotAllowed = 4312f3563ccSZbigniew Lukwinski sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed; 432db029c95SKowalski, Kamil EXPECT_THROW( 433db029c95SKowalski, Kamil { 434db029c95SKowalski, Kamil try 435db029c95SKowalski, Kamil { 4362f3563ccSZbigniew Lukwinski // Try to install the same certificate second time 437db029c95SKowalski, Kamil mainApp.install(certificateFile); 438db029c95SKowalski, Kamil } 439db029c95SKowalski, Kamil catch (const NotAllowed& e) 440db029c95SKowalski, Kamil { 441db029c95SKowalski, Kamil throw; 442db029c95SKowalski, Kamil } 443db029c95SKowalski, Kamil }, 444db029c95SKowalski, Kamil NotAllowed); 445db029c95SKowalski, Kamil 446db029c95SKowalski, Kamil // Check that the original certificate has been not removed 447db029c95SKowalski, Kamil EXPECT_FALSE(fs::is_empty(verifyDir)); 448947258dcSMarri Devender Rao EXPECT_TRUE(fs::exists(verifyPath)); 449947258dcSMarri Devender Rao } 450947258dcSMarri Devender Rao 45173d1fbf3SZbigniew Lukwinski /** @brief Check if in authority mode user can install a certificate with 4522f3563ccSZbigniew Lukwinski * certain subject hash twice. 4532f3563ccSZbigniew Lukwinski */ 4542f3563ccSZbigniew Lukwinski TEST_F(TestCertificates, InvokeInstallSameSubjectTwice) 4552f3563ccSZbigniew Lukwinski { 456*2e8fa88eSMichal Orzel std::string endpoint("truststore"); 457e3d47cd4SNan Zhou CertificateType type = CertificateType::authority; 4582f3563ccSZbigniew Lukwinski std::string verifyDir(certDir); 4596ec13c8fSNan Zhou std::string verifyUnit(ManagerInTest::unitToRestartInTest); 460cf06ccdcSNan Zhou auto objPath = std::string(objectNamePrefix) + '/' + 461cf06ccdcSNan Zhou certificateTypeToString(type) + '/' + endpoint; 4622f3563ccSZbigniew Lukwinski auto event = sdeventplus::Event::get_default(); 4632f3563ccSZbigniew Lukwinski // Attach the bus to sd_event to service user requests 4642f3563ccSZbigniew Lukwinski bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 4656ec13c8fSNan Zhou ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit, 4666ec13c8fSNan Zhou certDir); 4676ec13c8fSNan Zhou EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest))) 4686ec13c8fSNan Zhou .WillOnce(Return()) 4696ec13c8fSNan Zhou .WillOnce(Return()); 4702f3563ccSZbigniew Lukwinski MainApp mainApp(&manager); 4712f3563ccSZbigniew Lukwinski mainApp.install(certificateFile); 4722f3563ccSZbigniew Lukwinski 4732f3563ccSZbigniew Lukwinski std::vector<std::unique_ptr<Certificate>>& certs = 4742f3563ccSZbigniew Lukwinski manager.getCertificates(); 4752f3563ccSZbigniew Lukwinski 4762f3563ccSZbigniew Lukwinski EXPECT_FALSE(certs.empty()); 4772f3563ccSZbigniew Lukwinski 4782f3563ccSZbigniew Lukwinski // Check that certificate has been created at installation directory 479223e4604SPatrick Williams std::string verifyPath0 = verifyDir + "/" + 480223e4604SPatrick Williams getCertSubjectNameHash(certificateFile) + ".0"; 4812f3563ccSZbigniew Lukwinski EXPECT_FALSE(fs::is_empty(verifyDir)); 4822f3563ccSZbigniew Lukwinski EXPECT_TRUE(fs::exists(verifyPath0)); 4832f3563ccSZbigniew Lukwinski 4842f3563ccSZbigniew Lukwinski // Check that installed cert is identical to input one 4852f3563ccSZbigniew Lukwinski EXPECT_TRUE(compareFiles(certificateFile, verifyPath0)); 4862f3563ccSZbigniew Lukwinski 4872f3563ccSZbigniew Lukwinski // Prepare second certificate with the same subject 4882f3563ccSZbigniew Lukwinski createNewCertificate(); 4892f3563ccSZbigniew Lukwinski 4902f3563ccSZbigniew Lukwinski // Install second certificate 4912f3563ccSZbigniew Lukwinski mainApp.install(certificateFile); 4922f3563ccSZbigniew Lukwinski 4932f3563ccSZbigniew Lukwinski // Expect there are exactly two certificates in the collection 49473d1fbf3SZbigniew Lukwinski EXPECT_EQ(certs.size(), 2); 49573d1fbf3SZbigniew Lukwinski 49673d1fbf3SZbigniew Lukwinski // Check that certificate has been created at installation directory 497223e4604SPatrick Williams std::string verifyPath1 = verifyDir + "/" + 498223e4604SPatrick Williams getCertSubjectNameHash(certificateFile) + ".1"; 49973d1fbf3SZbigniew Lukwinski EXPECT_TRUE(fs::exists(verifyPath1)); 50073d1fbf3SZbigniew Lukwinski 50173d1fbf3SZbigniew Lukwinski // Check that installed cert is identical to input one 50273d1fbf3SZbigniew Lukwinski EXPECT_TRUE(compareFiles(certificateFile, verifyPath1)); 5032f3563ccSZbigniew Lukwinski 5042f3563ccSZbigniew Lukwinski // Check that the original/first certificate has been not removed 5052f3563ccSZbigniew Lukwinski EXPECT_FALSE(fs::is_empty(verifyDir)); 5062f3563ccSZbigniew Lukwinski EXPECT_TRUE(fs::exists(verifyPath0)); 5072f3563ccSZbigniew Lukwinski } 5082f3563ccSZbigniew Lukwinski 5092f3563ccSZbigniew Lukwinski /** @brief Check if in authority mode user can't install more than 510718eef37SNan Zhou * maxNumAuthorityCertificates certificates. 5112f3563ccSZbigniew Lukwinski */ 5122f3563ccSZbigniew Lukwinski TEST_F(TestCertificates, InvokeInstallAuthCertLimit) 5132f3563ccSZbigniew Lukwinski { 514*2e8fa88eSMichal Orzel std::string endpoint("truststore"); 515e3d47cd4SNan Zhou CertificateType type = CertificateType::authority; 5162f3563ccSZbigniew Lukwinski std::string verifyDir(certDir); 5176ec13c8fSNan Zhou std::string verifyUnit(ManagerInTest::unitToRestartInTest); 518cf06ccdcSNan Zhou auto objPath = std::string(objectNamePrefix) + '/' + 519cf06ccdcSNan Zhou certificateTypeToString(type) + '/' + endpoint; 5202f3563ccSZbigniew Lukwinski auto event = sdeventplus::Event::get_default(); 5212f3563ccSZbigniew Lukwinski // Attach the bus to sd_event to service user requests 5222f3563ccSZbigniew Lukwinski bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 5236ec13c8fSNan Zhou ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit, 5246ec13c8fSNan Zhou certDir); 5256ec13c8fSNan Zhou EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest))) 5266ec13c8fSNan Zhou .WillRepeatedly(Return()); 5272f3563ccSZbigniew Lukwinski MainApp mainApp(&manager); 5282f3563ccSZbigniew Lukwinski 5292f3563ccSZbigniew Lukwinski std::vector<std::unique_ptr<Certificate>>& certs = 5302f3563ccSZbigniew Lukwinski manager.getCertificates(); 5312f3563ccSZbigniew Lukwinski 5322f3563ccSZbigniew Lukwinski std::vector<std::string> verifyPaths; 5332f3563ccSZbigniew Lukwinski 5342f3563ccSZbigniew Lukwinski // Prepare maximum number of ceritificates 535718eef37SNan Zhou for (std::size_t i = 0; i < maxNumAuthorityCertificates; ++i) 5362f3563ccSZbigniew Lukwinski { 5372f3563ccSZbigniew Lukwinski // Prepare new certificatate 5382f3563ccSZbigniew Lukwinski createNewCertificate(true); 5392f3563ccSZbigniew Lukwinski 5402f3563ccSZbigniew Lukwinski // Install ceritificate 5412f3563ccSZbigniew Lukwinski mainApp.install(certificateFile); 5422f3563ccSZbigniew Lukwinski 5432f3563ccSZbigniew Lukwinski // Check number of certificates in the collection 5442f3563ccSZbigniew Lukwinski EXPECT_EQ(certs.size(), i + 1); 5452f3563ccSZbigniew Lukwinski 5462f3563ccSZbigniew Lukwinski // Check that certificate has been created at installation directory 547223e4604SPatrick Williams std::string verifyPath = verifyDir + "/" + 548223e4604SPatrick Williams getCertSubjectNameHash(certificateFile) + ".0"; 5492f3563ccSZbigniew Lukwinski EXPECT_FALSE(fs::is_empty(verifyDir)); 5502f3563ccSZbigniew Lukwinski EXPECT_TRUE(fs::exists(verifyPath)); 5512f3563ccSZbigniew Lukwinski 5522f3563ccSZbigniew Lukwinski // Check that installed cert is identical to input one 5532f3563ccSZbigniew Lukwinski EXPECT_TRUE(compareFiles(certificateFile, verifyPath)); 5542f3563ccSZbigniew Lukwinski 5552f3563ccSZbigniew Lukwinski // Save current certificate file for later check 5562f3563ccSZbigniew Lukwinski verifyPaths.push_back(verifyPath); 5572f3563ccSZbigniew Lukwinski } 5582f3563ccSZbigniew Lukwinski 5592f3563ccSZbigniew Lukwinski // Prepare new certificatate 5602f3563ccSZbigniew Lukwinski createNewCertificate(true); 5612f3563ccSZbigniew Lukwinski 5622f3563ccSZbigniew Lukwinski using NotAllowed = 5632f3563ccSZbigniew Lukwinski sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed; 5642f3563ccSZbigniew Lukwinski EXPECT_THROW( 5652f3563ccSZbigniew Lukwinski { 5662f3563ccSZbigniew Lukwinski try 5672f3563ccSZbigniew Lukwinski { 5682f3563ccSZbigniew Lukwinski // Try to install one more certificate 5692f3563ccSZbigniew Lukwinski mainApp.install(certificateFile); 5702f3563ccSZbigniew Lukwinski } 5712f3563ccSZbigniew Lukwinski catch (const NotAllowed& e) 5722f3563ccSZbigniew Lukwinski { 5732f3563ccSZbigniew Lukwinski throw; 5742f3563ccSZbigniew Lukwinski } 5752f3563ccSZbigniew Lukwinski }, 5762f3563ccSZbigniew Lukwinski NotAllowed); 5772f3563ccSZbigniew Lukwinski 5782f3563ccSZbigniew Lukwinski // Check that the original certificate has been not removed 5792f3563ccSZbigniew Lukwinski EXPECT_FALSE(fs::is_empty(verifyDir)); 580718eef37SNan Zhou for (size_t i = 0; i < maxNumAuthorityCertificates; ++i) 5812f3563ccSZbigniew Lukwinski { 5822f3563ccSZbigniew Lukwinski EXPECT_TRUE(fs::exists(verifyPaths[i])); 5832f3563ccSZbigniew Lukwinski } 5842f3563ccSZbigniew Lukwinski } 5852f3563ccSZbigniew Lukwinski 586947258dcSMarri Devender Rao /** @brief Compare the installed certificate with the copied certificate 587947258dcSMarri Devender Rao */ 5888841dbd6SMarri Devender Rao TEST_F(TestCertificates, CompareInstalledCertificate) 589947258dcSMarri Devender Rao { 590947258dcSMarri Devender Rao std::string endpoint("ldap"); 591e3d47cd4SNan Zhou CertificateType type = CertificateType::client; 5928841dbd6SMarri Devender Rao std::string installPath(certDir + "/" + certificateFile); 5938841dbd6SMarri Devender Rao std::string verifyPath(installPath); 5946ec13c8fSNan Zhou std::string verifyUnit(ManagerInTest::unitToRestartInTest); 595cf06ccdcSNan Zhou auto objPath = std::string(objectNamePrefix) + '/' + 596cf06ccdcSNan Zhou certificateTypeToString(type) + '/' + endpoint; 597ffad1ef1SMarri Devender Rao auto event = sdeventplus::Event::get_default(); 598ffad1ef1SMarri Devender Rao // Attach the bus to sd_event to service user requests 599ffad1ef1SMarri Devender Rao bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 6006ec13c8fSNan Zhou ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit, 6016ec13c8fSNan Zhou installPath); 6026ec13c8fSNan Zhou EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest))) 6036ec13c8fSNan Zhou .WillOnce(Return()); 604ffad1ef1SMarri Devender Rao MainApp mainApp(&manager); 605ffad1ef1SMarri Devender Rao mainApp.install(certificateFile); 606947258dcSMarri Devender Rao EXPECT_TRUE(fs::exists(verifyPath)); 607947258dcSMarri Devender Rao EXPECT_TRUE(compareFiles(verifyPath, certificateFile)); 608947258dcSMarri Devender Rao } 609e6597c5bSMarri Devender Rao 610e6597c5bSMarri Devender Rao /** @brief Check if install fails if certificate file is not found 611e6597c5bSMarri Devender Rao */ 6128841dbd6SMarri Devender Rao TEST_F(TestCertificates, TestNoCertificateFile) 613e6597c5bSMarri Devender Rao { 614e6597c5bSMarri Devender Rao std::string endpoint("ldap"); 615e3d47cd4SNan Zhou CertificateType type = CertificateType::client; 6168841dbd6SMarri Devender Rao std::string installPath(certDir + "/" + certificateFile); 6178841dbd6SMarri Devender Rao std::string verifyPath(installPath); 6186ec13c8fSNan Zhou std::string verifyUnit(ManagerInTest::unitToRestartInTest); 619cf06ccdcSNan Zhou auto objPath = std::string(objectNamePrefix) + '/' + 620cf06ccdcSNan Zhou certificateTypeToString(type) + '/' + endpoint; 6218841dbd6SMarri Devender Rao std::string uploadFile = "nofile.pem"; 622e6597c5bSMarri Devender Rao EXPECT_THROW( 623e6597c5bSMarri Devender Rao { 624e6597c5bSMarri Devender Rao try 625e6597c5bSMarri Devender Rao { 626ffad1ef1SMarri Devender Rao auto event = sdeventplus::Event::get_default(); 627ffad1ef1SMarri Devender Rao // Attach the bus to sd_event to service user requests 628ffad1ef1SMarri Devender Rao bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 6296ec13c8fSNan Zhou ManagerInTest manager(bus, event, objPath.c_str(), type, 6306ec13c8fSNan Zhou verifyUnit, installPath); 631ffad1ef1SMarri Devender Rao MainApp mainApp(&manager); 632ffad1ef1SMarri Devender Rao mainApp.install(uploadFile); 633e6597c5bSMarri Devender Rao } 634e6597c5bSMarri Devender Rao catch (const InternalFailure& e) 635e6597c5bSMarri Devender Rao { 636e6597c5bSMarri Devender Rao throw; 637e6597c5bSMarri Devender Rao } 638e6597c5bSMarri Devender Rao }, 639e6597c5bSMarri Devender Rao InternalFailure); 640e6597c5bSMarri Devender Rao EXPECT_FALSE(fs::exists(verifyPath)); 641e6597c5bSMarri Devender Rao } 642e6597c5bSMarri Devender Rao 643ffad1ef1SMarri Devender Rao /** @brief Test replacing existing certificate 644ffad1ef1SMarri Devender Rao */ 645ffad1ef1SMarri Devender Rao TEST_F(TestCertificates, TestReplaceCertificate) 646ffad1ef1SMarri Devender Rao { 647ffad1ef1SMarri Devender Rao std::string endpoint("ldap"); 648e3d47cd4SNan Zhou CertificateType type = CertificateType::server; 649ffad1ef1SMarri Devender Rao std::string installPath(certDir + "/" + certificateFile); 650ffad1ef1SMarri Devender Rao std::string verifyPath(installPath); 6516ec13c8fSNan Zhou std::string verifyUnit(ManagerInTest::unitToRestartInTest); 652cf06ccdcSNan Zhou auto objPath = std::string(objectNamePrefix) + '/' + 653cf06ccdcSNan Zhou certificateTypeToString(type) + '/' + endpoint; 654ffad1ef1SMarri Devender Rao auto event = sdeventplus::Event::get_default(); 655ffad1ef1SMarri Devender Rao // Attach the bus to sd_event to service user requests 656ffad1ef1SMarri Devender Rao bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 6576ec13c8fSNan Zhou ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit, 658ffad1ef1SMarri Devender Rao std::move(installPath)); 6596ec13c8fSNan Zhou EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest))) 6606ec13c8fSNan Zhou .WillOnce(Return()) 6616ec13c8fSNan Zhou .WillOnce(Return()); 662ffad1ef1SMarri Devender Rao MainApp mainApp(&manager); 663ffad1ef1SMarri Devender Rao mainApp.install(certificateFile); 664ffad1ef1SMarri Devender Rao EXPECT_TRUE(fs::exists(verifyPath)); 665db029c95SKowalski, Kamil std::vector<std::unique_ptr<Certificate>>& certs = 666db029c95SKowalski, Kamil manager.getCertificates(); 667db029c95SKowalski, Kamil EXPECT_FALSE(certs.empty()); 668db029c95SKowalski, Kamil EXPECT_NE(certs[0], nullptr); 669db029c95SKowalski, Kamil certs[0]->replace(certificateFile); 670ffad1ef1SMarri Devender Rao EXPECT_TRUE(fs::exists(verifyPath)); 671db029c95SKowalski, Kamil } 672db029c95SKowalski, Kamil 673db029c95SKowalski, Kamil /** @brief Test replacing existing certificate 674db029c95SKowalski, Kamil */ 675db029c95SKowalski, Kamil TEST_F(TestCertificates, TestAuthorityReplaceCertificate) 676db029c95SKowalski, Kamil { 677*2e8fa88eSMichal Orzel std::string endpoint("truststore"); 678e3d47cd4SNan Zhou CertificateType type = CertificateType::authority; 679db029c95SKowalski, Kamil std::string verifyDir(certDir); 6806ec13c8fSNan Zhou std::string verifyUnit(ManagerInTest::unitToRestartInTest); 681cf06ccdcSNan Zhou auto objPath = std::string(objectNamePrefix) + '/' + 682cf06ccdcSNan Zhou certificateTypeToString(type) + '/' + endpoint; 683db029c95SKowalski, Kamil auto event = sdeventplus::Event::get_default(); 684db029c95SKowalski, Kamil // Attach the bus to sd_event to service user requests 685db029c95SKowalski, Kamil bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 6866ec13c8fSNan Zhou ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit, 6876ec13c8fSNan Zhou certDir); 688e3d47cd4SNan Zhou constexpr const unsigned int replaceIterations = 10; 6896ec13c8fSNan Zhou EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest))) 690e3d47cd4SNan Zhou .Times(replaceIterations + 1) 6916ec13c8fSNan Zhou .WillRepeatedly(Return()); 692db029c95SKowalski, Kamil MainApp mainApp(&manager); 693db029c95SKowalski, Kamil mainApp.install(certificateFile); 694db029c95SKowalski, Kamil 695db029c95SKowalski, Kamil std::vector<std::unique_ptr<Certificate>>& certs = 696db029c95SKowalski, Kamil manager.getCertificates(); 697db029c95SKowalski, Kamil 698e3d47cd4SNan Zhou for (unsigned int i = 0; i < replaceIterations; i++) 699db029c95SKowalski, Kamil { 700db029c95SKowalski, Kamil // Certificate successfully installed 701db029c95SKowalski, Kamil EXPECT_FALSE(certs.empty()); 702db029c95SKowalski, Kamil 703223e4604SPatrick Williams std::string verifyPath = verifyDir + "/" + 704223e4604SPatrick Williams getCertSubjectNameHash(certificateFile) + ".0"; 705db029c95SKowalski, Kamil 706db029c95SKowalski, Kamil // Check that certificate has been created at installation directory 707db029c95SKowalski, Kamil EXPECT_FALSE(fs::is_empty(verifyDir)); 708ffad1ef1SMarri Devender Rao EXPECT_TRUE(fs::exists(verifyPath)); 709db029c95SKowalski, Kamil 710db029c95SKowalski, Kamil // Check that installed cert is identical to input one 711db029c95SKowalski, Kamil EXPECT_TRUE(compareFiles(certificateFile, verifyPath)); 712db029c95SKowalski, Kamil 713db029c95SKowalski, Kamil // Create new certificate 714db029c95SKowalski, Kamil createNewCertificate(true); 715db029c95SKowalski, Kamil 716db029c95SKowalski, Kamil certs[0]->replace(certificateFile); 717db029c95SKowalski, Kamil 718db029c95SKowalski, Kamil // Verify that old certificate has been removed 719db029c95SKowalski, Kamil EXPECT_FALSE(fs::exists(verifyPath)); 720db029c95SKowalski, Kamil } 721ffad1ef1SMarri Devender Rao } 722ffad1ef1SMarri Devender Rao 723a3bb38fbSZbigniew Kurzynski /** @brief Test verifiing if delete function works. 724a3bb38fbSZbigniew Kurzynski */ 725a3bb38fbSZbigniew Kurzynski TEST_F(TestCertificates, TestStorageDeleteCertificate) 726a3bb38fbSZbigniew Kurzynski { 727*2e8fa88eSMichal Orzel std::string endpoint("truststore"); 728e3d47cd4SNan Zhou CertificateType type = CertificateType::authority; 729a3bb38fbSZbigniew Kurzynski std::string verifyDir(certDir); 7306ec13c8fSNan Zhou std::string verifyUnit((ManagerInTest::unitToRestartInTest)); 731cf06ccdcSNan Zhou auto objPath = std::string(objectNamePrefix) + '/' + 732cf06ccdcSNan Zhou certificateTypeToString(type) + '/' + endpoint; 733a3bb38fbSZbigniew Kurzynski auto event = sdeventplus::Event::get_default(); 734a3bb38fbSZbigniew Kurzynski // Attach the bus to sd_event to service user requests 735a3bb38fbSZbigniew Kurzynski bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 7366ec13c8fSNan Zhou ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit, 7376ec13c8fSNan Zhou certDir); 7386ec13c8fSNan Zhou EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest))) 7396ec13c8fSNan Zhou .WillRepeatedly(Return()); 740a3bb38fbSZbigniew Kurzynski MainApp mainApp(&manager); 741a3bb38fbSZbigniew Kurzynski 742a3bb38fbSZbigniew Kurzynski // Check if certificate placeholder dir is empty 743a3bb38fbSZbigniew Kurzynski EXPECT_TRUE(fs::is_empty(verifyDir)); 744a3bb38fbSZbigniew Kurzynski mainApp.install(certificateFile); 745a3bb38fbSZbigniew Kurzynski 746a3bb38fbSZbigniew Kurzynski // Create new certificate 747a3bb38fbSZbigniew Kurzynski createNewCertificate(true); 748a3bb38fbSZbigniew Kurzynski mainApp.install(certificateFile); 749a3bb38fbSZbigniew Kurzynski 750a3bb38fbSZbigniew Kurzynski createNewCertificate(true); 751a3bb38fbSZbigniew Kurzynski mainApp.install(certificateFile); 752a3bb38fbSZbigniew Kurzynski 753a3bb38fbSZbigniew Kurzynski std::vector<std::unique_ptr<Certificate>>& certs = 754a3bb38fbSZbigniew Kurzynski manager.getCertificates(); 755a3bb38fbSZbigniew Kurzynski 756a3bb38fbSZbigniew Kurzynski // All 3 certificates successfully installed and added to manager 757a3bb38fbSZbigniew Kurzynski EXPECT_EQ(certs.size(), 3); 758a3bb38fbSZbigniew Kurzynski 759a3bb38fbSZbigniew Kurzynski // Check if certificate placeholder is not empty, there should be 3 760a3bb38fbSZbigniew Kurzynski // certificates 761a3bb38fbSZbigniew Kurzynski EXPECT_FALSE(fs::is_empty(verifyDir)); 762a3bb38fbSZbigniew Kurzynski 763a3bb38fbSZbigniew Kurzynski certs[0]->delete_(); 764a3bb38fbSZbigniew Kurzynski EXPECT_EQ(certs.size(), 2); 765a3bb38fbSZbigniew Kurzynski 766a3bb38fbSZbigniew Kurzynski certs[0]->delete_(); 767a3bb38fbSZbigniew Kurzynski EXPECT_EQ(certs.size(), 1); 768a3bb38fbSZbigniew Kurzynski 769a3bb38fbSZbigniew Kurzynski certs[0]->delete_(); 770a3bb38fbSZbigniew Kurzynski EXPECT_EQ(certs.size(), 0); 771a3bb38fbSZbigniew Kurzynski 772a3bb38fbSZbigniew Kurzynski // Check if certificate placeholder is empty. 773a3bb38fbSZbigniew Kurzynski EXPECT_TRUE(fs::is_empty(verifyDir)); 774a3bb38fbSZbigniew Kurzynski } 775a3bb38fbSZbigniew Kurzynski 776e6597c5bSMarri Devender Rao /** @brief Check if install fails if certificate file is empty 777e6597c5bSMarri Devender Rao */ 7788841dbd6SMarri Devender Rao TEST_F(TestCertificates, TestEmptyCertificateFile) 779e6597c5bSMarri Devender Rao { 780e6597c5bSMarri Devender Rao std::string endpoint("ldap"); 781e3d47cd4SNan Zhou CertificateType type = CertificateType::client; 7828841dbd6SMarri Devender Rao std::string installPath(certDir + "/" + certificateFile); 7838841dbd6SMarri Devender Rao std::string verifyPath(installPath); 7846ec13c8fSNan Zhou std::string verifyUnit(ManagerInTest::unitToRestartInTest); 785cf06ccdcSNan Zhou auto objPath = std::string(objectNamePrefix) + '/' + 786cf06ccdcSNan Zhou certificateTypeToString(type) + '/' + endpoint; 787ddf64866SMarri Devender Rao std::string emptyFile("emptycert.pem"); 788e6597c5bSMarri Devender Rao std::ofstream ofs; 789e6597c5bSMarri Devender Rao ofs.open(emptyFile, std::ofstream::out); 790e6597c5bSMarri Devender Rao ofs.close(); 791e6597c5bSMarri Devender Rao EXPECT_THROW( 792e6597c5bSMarri Devender Rao { 793e6597c5bSMarri Devender Rao try 794e6597c5bSMarri Devender Rao { 795ffad1ef1SMarri Devender Rao auto event = sdeventplus::Event::get_default(); 796ffad1ef1SMarri Devender Rao // Attach the bus to sd_event to service user requests 797ffad1ef1SMarri Devender Rao bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 7986ec13c8fSNan Zhou ManagerInTest manager(bus, event, objPath.c_str(), type, 7996ec13c8fSNan Zhou verifyUnit, installPath); 800ffad1ef1SMarri Devender Rao MainApp mainApp(&manager); 801ffad1ef1SMarri Devender Rao mainApp.install(emptyFile); 802e6597c5bSMarri Devender Rao } 803e6597c5bSMarri Devender Rao catch (const InvalidCertificate& e) 804e6597c5bSMarri Devender Rao { 805e6597c5bSMarri Devender Rao throw; 806e6597c5bSMarri Devender Rao } 807e6597c5bSMarri Devender Rao }, 808e6597c5bSMarri Devender Rao InvalidCertificate); 809e6597c5bSMarri Devender Rao EXPECT_FALSE(fs::exists(verifyPath)); 810e6597c5bSMarri Devender Rao fs::remove(emptyFile); 811e6597c5bSMarri Devender Rao } 812e6597c5bSMarri Devender Rao 813ddf64866SMarri Devender Rao /** @brief Check if install fails if certificate file is corrupted 814e6597c5bSMarri Devender Rao */ 8158841dbd6SMarri Devender Rao TEST_F(TestCertificates, TestInvalidCertificateFile) 816e6597c5bSMarri Devender Rao { 817e6597c5bSMarri Devender Rao std::string endpoint("ldap"); 818e3d47cd4SNan Zhou CertificateType type = CertificateType::client; 819e6597c5bSMarri Devender Rao 820e6597c5bSMarri Devender Rao std::ofstream ofs; 821ddf64866SMarri Devender Rao ofs.open(certificateFile, std::ofstream::out); 822ddf64866SMarri Devender Rao ofs << "-----BEGIN CERTIFICATE-----"; 823ddf64866SMarri Devender Rao ofs << "ADD_SOME_INVALID_DATA_INTO_FILE"; 824ddf64866SMarri Devender Rao ofs << "-----END CERTIFICATE-----"; 825e6597c5bSMarri Devender Rao ofs.close(); 826e6597c5bSMarri Devender Rao 8278841dbd6SMarri Devender Rao std::string installPath(certDir + "/" + certificateFile); 8288841dbd6SMarri Devender Rao std::string verifyPath(installPath); 8296ec13c8fSNan Zhou std::string verifyUnit(ManagerInTest::unitToRestartInTest); 830cf06ccdcSNan Zhou auto objPath = std::string(objectNamePrefix) + '/' + 831cf06ccdcSNan Zhou certificateTypeToString(type) + '/' + endpoint; 832e6597c5bSMarri Devender Rao EXPECT_THROW( 833e6597c5bSMarri Devender Rao { 834e6597c5bSMarri Devender Rao try 835e6597c5bSMarri Devender Rao { 836ffad1ef1SMarri Devender Rao auto event = sdeventplus::Event::get_default(); 837ffad1ef1SMarri Devender Rao // Attach the bus to sd_event to service user requests 838ffad1ef1SMarri Devender Rao bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 8396ec13c8fSNan Zhou ManagerInTest manager(bus, event, objPath.c_str(), type, 8406ec13c8fSNan Zhou verifyUnit, installPath); 841ffad1ef1SMarri Devender Rao MainApp mainApp(&manager); 842ffad1ef1SMarri Devender Rao mainApp.install(certificateFile); 843e6597c5bSMarri Devender Rao } 844e6597c5bSMarri Devender Rao catch (const InvalidCertificate& e) 845e6597c5bSMarri Devender Rao { 846e6597c5bSMarri Devender Rao throw; 847e6597c5bSMarri Devender Rao } 848e6597c5bSMarri Devender Rao }, 849e6597c5bSMarri Devender Rao InvalidCertificate); 850e6597c5bSMarri Devender Rao EXPECT_FALSE(fs::exists(verifyPath)); 851ddf64866SMarri Devender Rao } 852ddf64866SMarri Devender Rao 853ddf64866SMarri Devender Rao /** 854ddf64866SMarri Devender Rao * Class to generate private and certificate only file and test verification 855ddf64866SMarri Devender Rao */ 8568841dbd6SMarri Devender Rao class TestInvalidCertificate : public ::testing::Test 857ddf64866SMarri Devender Rao { 858ddf64866SMarri Devender Rao public: 859223e4604SPatrick Williams TestInvalidCertificate() : bus(sdbusplus::bus::new_default()) {} 860ddf64866SMarri Devender Rao void SetUp() override 861ddf64866SMarri Devender Rao { 862ddf64866SMarri Devender Rao char dirTemplate[] = "/tmp/FakeCerts.XXXXXX"; 863ddf64866SMarri Devender Rao auto dirPtr = mkdtemp(dirTemplate); 864cfb5802aSNan Zhou if (dirPtr == nullptr) 865ddf64866SMarri Devender Rao { 866ddf64866SMarri Devender Rao throw std::bad_alloc(); 867ddf64866SMarri Devender Rao } 868fe590c4eSZbigniew Lukwinski certDir = std::string(dirPtr) + "/certs"; 869fe590c4eSZbigniew Lukwinski fs::create_directories(certDir); 870ddf64866SMarri Devender Rao certificateFile = "cert.pem"; 871ddf64866SMarri Devender Rao keyFile = "key.pem"; 872ddf64866SMarri Devender Rao std::string cmd = "openssl req -x509 -sha256 -newkey rsa:2048 "; 873ddf64866SMarri Devender Rao cmd += "-keyout key.pem -out cert.pem -days 3650 "; 874ddf64866SMarri Devender Rao cmd += "-subj " 875ddf64866SMarri Devender Rao "/O=openbmc-project.xyz/CN=localhost" 876ddf64866SMarri Devender Rao " -nodes"; 877ddf64866SMarri Devender Rao 878ddf64866SMarri Devender Rao auto val = std::system(cmd.c_str()); 879ddf64866SMarri Devender Rao if (val) 880ddf64866SMarri Devender Rao { 881ddf64866SMarri Devender Rao std::cout << "command Error: " << val << std::endl; 882ddf64866SMarri Devender Rao } 883ddf64866SMarri Devender Rao } 884ddf64866SMarri Devender Rao void TearDown() override 885ddf64866SMarri Devender Rao { 886ddf64866SMarri Devender Rao fs::remove_all(certDir); 887ddf64866SMarri Devender Rao fs::remove(certificateFile); 888ddf64866SMarri Devender Rao fs::remove(keyFile); 889ddf64866SMarri Devender Rao } 890ddf64866SMarri Devender Rao 891ddf64866SMarri Devender Rao protected: 892b3dbfb37SPatrick Williams sdbusplus::bus_t bus; 893ddf64866SMarri Devender Rao std::string certificateFile; 894ddf64866SMarri Devender Rao std::string keyFile; 895ddf64866SMarri Devender Rao std::string certDir; 896ddf64866SMarri Devender Rao }; 897ddf64866SMarri Devender Rao 898ddf64866SMarri Devender Rao /** @brief Check install fails if private key is missing in certificate file 899ddf64866SMarri Devender Rao */ 9008841dbd6SMarri Devender Rao TEST_F(TestInvalidCertificate, TestMissingPrivateKey) 901ddf64866SMarri Devender Rao { 902ddf64866SMarri Devender Rao std::string endpoint("ldap"); 903e3d47cd4SNan Zhou CertificateType type = CertificateType::client; 9048841dbd6SMarri Devender Rao std::string installPath(certDir + "/" + certificateFile); 9058841dbd6SMarri Devender Rao std::string verifyPath(installPath); 9066ec13c8fSNan Zhou std::string verifyUnit(ManagerInTest::unitToRestartInTest); 907cf06ccdcSNan Zhou auto objPath = std::string(objectNamePrefix) + '/' + 908cf06ccdcSNan Zhou certificateTypeToString(type) + '/' + endpoint; 9098841dbd6SMarri Devender Rao EXPECT_THROW( 9108841dbd6SMarri Devender Rao { 9118841dbd6SMarri Devender Rao try 9128841dbd6SMarri Devender Rao { 913ffad1ef1SMarri Devender Rao auto event = sdeventplus::Event::get_default(); 914ffad1ef1SMarri Devender Rao // Attach the bus to sd_event to service user requests 915ffad1ef1SMarri Devender Rao bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 9166ec13c8fSNan Zhou ManagerInTest manager(bus, event, objPath.c_str(), type, 9176ec13c8fSNan Zhou verifyUnit, installPath); 918ffad1ef1SMarri Devender Rao MainApp mainApp(&manager); 919ffad1ef1SMarri Devender Rao mainApp.install(certificateFile); 9208841dbd6SMarri Devender Rao } 921cd30c496SMarri Devender Rao catch (const InternalFailure& e) 9228841dbd6SMarri Devender Rao { 9238841dbd6SMarri Devender Rao throw; 9248841dbd6SMarri Devender Rao } 9258841dbd6SMarri Devender Rao }, 926cd30c496SMarri Devender Rao InternalFailure); 9278841dbd6SMarri Devender Rao EXPECT_FALSE(fs::exists(verifyPath)); 9288841dbd6SMarri Devender Rao } 9298841dbd6SMarri Devender Rao 9308841dbd6SMarri Devender Rao /** @brief Check install fails if ceritificate is missing in certificate file 9318841dbd6SMarri Devender Rao */ 9328841dbd6SMarri Devender Rao TEST_F(TestInvalidCertificate, TestMissingCeritificate) 9338841dbd6SMarri Devender Rao { 9348841dbd6SMarri Devender Rao std::string endpoint("ldap"); 935e3d47cd4SNan Zhou CertificateType type = CertificateType::client; 9368841dbd6SMarri Devender Rao std::string installPath(certDir + "/" + keyFile); 9378841dbd6SMarri Devender Rao std::string verifyPath(installPath); 9386ec13c8fSNan Zhou std::string verifyUnit(ManagerInTest::unitToRestartInTest); 939cf06ccdcSNan Zhou auto objPath = std::string(objectNamePrefix) + '/' + 940cf06ccdcSNan Zhou certificateTypeToString(type) + '/' + endpoint; 9418841dbd6SMarri Devender Rao EXPECT_THROW( 9428841dbd6SMarri Devender Rao { 9438841dbd6SMarri Devender Rao try 9448841dbd6SMarri Devender Rao { 945f4682712SMarri Devender Rao auto event = sdeventplus::Event::get_default(); 946ffad1ef1SMarri Devender Rao // Attach the bus to sd_event to service user requests 947ffad1ef1SMarri Devender Rao bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 9486ec13c8fSNan Zhou ManagerInTest manager(bus, event, objPath.c_str(), type, 9496ec13c8fSNan Zhou verifyUnit, installPath); 950ddf64866SMarri Devender Rao MainApp mainApp(&manager); 951ffad1ef1SMarri Devender Rao mainApp.install(keyFile); 952ddf64866SMarri Devender Rao } 953cd30c496SMarri Devender Rao catch (const InternalFailure& e) 954ddf64866SMarri Devender Rao { 955ddf64866SMarri Devender Rao throw; 956ddf64866SMarri Devender Rao } 957ddf64866SMarri Devender Rao }, 958ddf64866SMarri Devender Rao InvalidCertificate); 959ddf64866SMarri Devender Rao EXPECT_FALSE(fs::exists(verifyPath)); 960ddf64866SMarri Devender Rao } 961ddf64866SMarri Devender Rao 9628841dbd6SMarri Devender Rao /** @brief Check if error is thrown when multiple certificates are installed 9638841dbd6SMarri Devender Rao * At present only one certificate per service is allowed 964ddf64866SMarri Devender Rao */ 9658841dbd6SMarri Devender Rao TEST_F(TestCertificates, TestCertInstallNotAllowed) 966ddf64866SMarri Devender Rao { 9678841dbd6SMarri Devender Rao using NotAllowed = 9688841dbd6SMarri Devender Rao sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed; 969ddf64866SMarri Devender Rao std::string endpoint("ldap"); 970e3d47cd4SNan Zhou CertificateType type = CertificateType::client; 9718841dbd6SMarri Devender Rao std::string installPath(certDir + "/" + certificateFile); 9728841dbd6SMarri Devender Rao std::string verifyPath(installPath); 9736ec13c8fSNan Zhou std::string verifyUnit(ManagerInTest::unitToRestartInTest); 974cf06ccdcSNan Zhou auto objPath = std::string(objectNamePrefix) + '/' + 975cf06ccdcSNan Zhou certificateTypeToString(type) + '/' + endpoint; 976f4682712SMarri Devender Rao auto event = sdeventplus::Event::get_default(); 977ffad1ef1SMarri Devender Rao // Attach the bus to sd_event to service user requests 978ffad1ef1SMarri Devender Rao bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 9796ec13c8fSNan Zhou ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit, 9806ec13c8fSNan Zhou installPath); 981ddf64866SMarri Devender Rao MainApp mainApp(&manager); 9828841dbd6SMarri Devender Rao mainApp.install(certificateFile); 9838841dbd6SMarri Devender Rao EXPECT_TRUE(fs::exists(verifyPath)); 984ddf64866SMarri Devender Rao EXPECT_THROW( 985ddf64866SMarri Devender Rao { 986ddf64866SMarri Devender Rao try 987ddf64866SMarri Devender Rao { 9888841dbd6SMarri Devender Rao // install second certificate 9898841dbd6SMarri Devender Rao mainApp.install(certificateFile); 990ddf64866SMarri Devender Rao } 9918841dbd6SMarri Devender Rao catch (const NotAllowed& e) 992ddf64866SMarri Devender Rao { 993ddf64866SMarri Devender Rao throw; 994ddf64866SMarri Devender Rao } 995ddf64866SMarri Devender Rao }, 9968841dbd6SMarri Devender Rao NotAllowed); 997e6597c5bSMarri Devender Rao } 998f4682712SMarri Devender Rao 999f4682712SMarri Devender Rao TEST_F(TestCertificates, TestGenerateCSR) 1000f4682712SMarri Devender Rao { 1001f4682712SMarri Devender Rao std::string endpoint("https"); 1002cf06ccdcSNan Zhou std::string unit; 1003e3d47cd4SNan Zhou CertificateType type = CertificateType::server; 1004f4682712SMarri Devender Rao std::string installPath(certDir + "/" + certificateFile); 1005f4682712SMarri Devender Rao std::string verifyPath(installPath); 1006e3d47cd4SNan Zhou std::string csrPath(certDir + "/" + CSRFile); 1007f4682712SMarri Devender Rao std::string privateKeyPath(certDir + "/" + privateKeyFile); 1008f4682712SMarri Devender Rao std::vector<std::string> alternativeNames{"localhost1", "localhost2"}; 10098a09b52aSRamesh Iyyar std::string challengePassword("Password"); 1010f4682712SMarri Devender Rao std::string city("HYB"); 1011f4682712SMarri Devender Rao std::string commonName("abc.com"); 1012f4682712SMarri Devender Rao std::string contactPerson("Admin"); 1013f4682712SMarri Devender Rao std::string country("IN"); 1014f4682712SMarri Devender Rao std::string email("admin@in.ibm.com"); 1015f4682712SMarri Devender Rao std::string givenName("givenName"); 1016f4682712SMarri Devender Rao std::string initials("G"); 1017f4682712SMarri Devender Rao int64_t keyBitLength(2048); 1018f4682712SMarri Devender Rao std::string keyCurveId("0"); 1019f4682712SMarri Devender Rao std::string keyPairAlgorithm("RSA"); 1020f4682712SMarri Devender Rao std::vector<std::string> keyUsage{"serverAuth", "clientAuth"}; 1021f4682712SMarri Devender Rao std::string organization("IBM"); 10228a09b52aSRamesh Iyyar std::string organizationalUnit("orgUnit"); 1023f4682712SMarri Devender Rao std::string state("TS"); 1024f4682712SMarri Devender Rao std::string surname("surname"); 1025f4682712SMarri Devender Rao std::string unstructuredName("unstructuredName"); 1026cf06ccdcSNan Zhou auto objPath = std::string(objectNamePrefix) + '/' + 1027cf06ccdcSNan Zhou certificateTypeToString(type) + '/' + endpoint; 1028f4682712SMarri Devender Rao auto event = sdeventplus::Event::get_default(); 1029ffad1ef1SMarri Devender Rao // Attach the bus to sd_event to service user requests 1030ffad1ef1SMarri Devender Rao bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 1031f4682712SMarri Devender Rao Manager manager(bus, event, objPath.c_str(), type, std::move(unit), 1032f4682712SMarri Devender Rao std::move(installPath)); 1033f4682712SMarri Devender Rao Status status; 1034e3d47cd4SNan Zhou CSR csr(bus, objPath.c_str(), csrPath.c_str(), status); 1035f4682712SMarri Devender Rao MainApp mainApp(&manager, &csr); 1036f4682712SMarri Devender Rao mainApp.generateCSR(alternativeNames, challengePassword, city, commonName, 1037f4682712SMarri Devender Rao contactPerson, country, email, givenName, initials, 1038f4682712SMarri Devender Rao keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage, 1039f4682712SMarri Devender Rao organization, organizationalUnit, state, surname, 1040f4682712SMarri Devender Rao unstructuredName); 1041f4682712SMarri Devender Rao std::string csrData(""); 1042f4682712SMarri Devender Rao // generateCSR takes considerable time to create CSR and privateKey Files 1043e3d47cd4SNan Zhou EXPECT_FALSE(fs::exists(csrPath)); 1044f4682712SMarri Devender Rao EXPECT_FALSE(fs::exists(privateKeyPath)); 1045f4682712SMarri Devender Rao EXPECT_THROW( 1046f4682712SMarri Devender Rao { 1047f4682712SMarri Devender Rao try 1048f4682712SMarri Devender Rao { 1049e129be3bSPatrick Williams csrData = csr.csr(); 1050f4682712SMarri Devender Rao } 1051f4682712SMarri Devender Rao catch (const InternalFailure& e) 1052f4682712SMarri Devender Rao { 1053f4682712SMarri Devender Rao throw; 1054f4682712SMarri Devender Rao } 1055f4682712SMarri Devender Rao }, 1056f4682712SMarri Devender Rao InternalFailure); 1057f4682712SMarri Devender Rao // wait for 10 sec to get CSR and privateKey Files generated 1058f4682712SMarri Devender Rao sleep(10); 1059e3d47cd4SNan Zhou EXPECT_TRUE(fs::exists(csrPath)); 1060f4682712SMarri Devender Rao EXPECT_TRUE(fs::exists(privateKeyPath)); 1061e129be3bSPatrick Williams csrData = csr.csr(); 1062f4682712SMarri Devender Rao ASSERT_NE("", csrData.c_str()); 1063f4682712SMarri Devender Rao } 1064f4682712SMarri Devender Rao 10658a09b52aSRamesh Iyyar /** @brief Check if ECC key pair is generated when user is not given algorithm 10668a09b52aSRamesh Iyyar * type. At present RSA and EC key pair algorithm are supported 10678a09b52aSRamesh Iyyar */ 10688a09b52aSRamesh Iyyar TEST_F(TestCertificates, TestGenerateCSRwithEmptyKeyPairAlgorithm) 10698a09b52aSRamesh Iyyar { 10708a09b52aSRamesh Iyyar std::string endpoint("https"); 1071cf06ccdcSNan Zhou std::string unit; 1072e3d47cd4SNan Zhou CertificateType type = CertificateType::server; 10738a09b52aSRamesh Iyyar std::string installPath(certDir + "/" + certificateFile); 10748a09b52aSRamesh Iyyar std::string verifyPath(installPath); 1075e3d47cd4SNan Zhou std::string csrPath(certDir + "/" + CSRFile); 10768a09b52aSRamesh Iyyar std::string privateKeyPath(certDir + "/" + privateKeyFile); 10778a09b52aSRamesh Iyyar std::vector<std::string> alternativeNames{"localhost1", "localhost2"}; 10788a09b52aSRamesh Iyyar std::string challengePassword("Password"); 10798a09b52aSRamesh Iyyar std::string city("HYB"); 10808a09b52aSRamesh Iyyar std::string commonName("abc.com"); 10818a09b52aSRamesh Iyyar std::string contactPerson("Admin"); 10828a09b52aSRamesh Iyyar std::string country("IN"); 10838a09b52aSRamesh Iyyar std::string email("admin@in.ibm.com"); 10848a09b52aSRamesh Iyyar std::string givenName("givenName"); 10858a09b52aSRamesh Iyyar std::string initials("G"); 10868a09b52aSRamesh Iyyar int64_t keyBitLength(2048); 10878a09b52aSRamesh Iyyar std::string keyCurveId(""); 10888a09b52aSRamesh Iyyar std::string keyPairAlgorithm(""); 10898a09b52aSRamesh Iyyar std::vector<std::string> keyUsage{"serverAuth", "clientAuth"}; 10908a09b52aSRamesh Iyyar std::string organization("IBM"); 10918a09b52aSRamesh Iyyar std::string organizationalUnit("orgUnit"); 10928a09b52aSRamesh Iyyar std::string state("TS"); 10938a09b52aSRamesh Iyyar std::string surname("surname"); 10948a09b52aSRamesh Iyyar std::string unstructuredName("unstructuredName"); 1095cf06ccdcSNan Zhou auto objPath = std::string(objectNamePrefix) + '/' + 1096cf06ccdcSNan Zhou certificateTypeToString(type) + '/' + endpoint; 1097f4682712SMarri Devender Rao auto event = sdeventplus::Event::get_default(); 1098f4682712SMarri Devender Rao Manager manager(bus, event, objPath.c_str(), type, std::move(unit), 1099f4682712SMarri Devender Rao std::move(installPath)); 1100f4682712SMarri Devender Rao Status status; 1101e3d47cd4SNan Zhou CSR csr(bus, objPath.c_str(), csrPath.c_str(), status); 1102f4682712SMarri Devender Rao MainApp mainApp(&manager, &csr); 1103f4682712SMarri Devender Rao mainApp.generateCSR(alternativeNames, challengePassword, city, commonName, 1104f4682712SMarri Devender Rao contactPerson, country, email, givenName, initials, 1105f4682712SMarri Devender Rao keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage, 1106f4682712SMarri Devender Rao organization, organizationalUnit, state, surname, 1107f4682712SMarri Devender Rao unstructuredName); 1108f4682712SMarri Devender Rao sleep(10); 1109e3d47cd4SNan Zhou EXPECT_TRUE(fs::exists(csrPath)); 11108a09b52aSRamesh Iyyar EXPECT_TRUE(fs::exists(privateKeyPath)); 11118a09b52aSRamesh Iyyar } 11128a09b52aSRamesh Iyyar 11138a09b52aSRamesh Iyyar /** @brief Check if error is thrown when giving un supported key pair 11148a09b52aSRamesh Iyyar * algorithm. At present RSA and EC key pair algorithm are supported 11158a09b52aSRamesh Iyyar */ 11168a09b52aSRamesh Iyyar TEST_F(TestCertificates, TestGenerateCSRwithUnsupportedKeyPairAlgorithm) 11178a09b52aSRamesh Iyyar { 11188a09b52aSRamesh Iyyar std::string endpoint("https"); 1119cf06ccdcSNan Zhou std::string unit; 1120e3d47cd4SNan Zhou CertificateType type = CertificateType::server; 11218a09b52aSRamesh Iyyar std::string installPath(certDir + "/" + certificateFile); 11228a09b52aSRamesh Iyyar std::string verifyPath(installPath); 1123e3d47cd4SNan Zhou std::string csrPath(certDir + "/" + CSRFile); 11248a09b52aSRamesh Iyyar std::string privateKeyPath(certDir + "/" + privateKeyFile); 11258a09b52aSRamesh Iyyar std::vector<std::string> alternativeNames{"localhost1", "localhost2"}; 11268a09b52aSRamesh Iyyar std::string challengePassword("Password"); 11278a09b52aSRamesh Iyyar std::string city("HYB"); 11288a09b52aSRamesh Iyyar std::string commonName("abc.com"); 11298a09b52aSRamesh Iyyar std::string contactPerson("Admin"); 11308a09b52aSRamesh Iyyar std::string country("IN"); 11318a09b52aSRamesh Iyyar std::string email("admin@in.ibm.com"); 11328a09b52aSRamesh Iyyar std::string givenName("givenName"); 11338a09b52aSRamesh Iyyar std::string initials("G"); 11348a09b52aSRamesh Iyyar int64_t keyBitLength(2048); 11358a09b52aSRamesh Iyyar std::string keyCurveId("secp521r1"); 11368a09b52aSRamesh Iyyar std::string keyPairAlgorithm("UnSupportedAlgorithm"); 11378a09b52aSRamesh Iyyar std::vector<std::string> keyUsage{"serverAuth", "clientAuth"}; 11388a09b52aSRamesh Iyyar std::string organization("IBM"); 11398a09b52aSRamesh Iyyar std::string organizationalUnit("orgUnit"); 11408a09b52aSRamesh Iyyar std::string state("TS"); 11418a09b52aSRamesh Iyyar std::string surname("surname"); 11428a09b52aSRamesh Iyyar std::string unstructuredName("unstructuredName"); 1143cf06ccdcSNan Zhou auto objPath = std::string(objectNamePrefix) + '/' + 1144cf06ccdcSNan Zhou certificateTypeToString(type) + '/' + endpoint; 11458a09b52aSRamesh Iyyar auto event = sdeventplus::Event::get_default(); 11468a09b52aSRamesh Iyyar Manager manager(bus, event, objPath.c_str(), type, std::move(unit), 11478a09b52aSRamesh Iyyar std::move(installPath)); 11488a09b52aSRamesh Iyyar Status status; 1149e3d47cd4SNan Zhou CSR csr(bus, objPath.c_str(), csrPath.c_str(), status); 11508a09b52aSRamesh Iyyar MainApp mainApp(&manager, &csr); 11518a09b52aSRamesh Iyyar mainApp.generateCSR(alternativeNames, challengePassword, city, commonName, 11528a09b52aSRamesh Iyyar contactPerson, country, email, givenName, initials, 11538a09b52aSRamesh Iyyar keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage, 11548a09b52aSRamesh Iyyar organization, organizationalUnit, state, surname, 11558a09b52aSRamesh Iyyar unstructuredName); 1156e3d47cd4SNan Zhou EXPECT_FALSE(fs::exists(csrPath)); 1157f4682712SMarri Devender Rao EXPECT_FALSE(fs::exists(privateKeyPath)); 1158f4682712SMarri Devender Rao } 11598a09b52aSRamesh Iyyar 11608a09b52aSRamesh Iyyar /** @brief Check if error is thrown when NID_undef is returned for given key 11618a09b52aSRamesh Iyyar * curve id 11628a09b52aSRamesh Iyyar */ 11638a09b52aSRamesh Iyyar TEST_F(TestCertificates, TestECKeyGenerationwithNIDundefCase) 11648a09b52aSRamesh Iyyar { 11658a09b52aSRamesh Iyyar std::string endpoint("https"); 1166cf06ccdcSNan Zhou std::string unit; 1167e3d47cd4SNan Zhou CertificateType type = CertificateType::server; 11688a09b52aSRamesh Iyyar std::string installPath(certDir + "/" + certificateFile); 11698a09b52aSRamesh Iyyar std::string verifyPath(installPath); 1170e3d47cd4SNan Zhou std::string csrPath(certDir + "/" + CSRFile); 11718a09b52aSRamesh Iyyar std::string privateKeyPath(certDir + "/" + privateKeyFile); 11728a09b52aSRamesh Iyyar std::vector<std::string> alternativeNames{"localhost1", "localhost2"}; 11738a09b52aSRamesh Iyyar std::string challengePassword("Password"); 11748a09b52aSRamesh Iyyar std::string city("BLR"); 11758a09b52aSRamesh Iyyar std::string commonName("abc.com"); 11768a09b52aSRamesh Iyyar std::string contactPerson("Admin"); 11778a09b52aSRamesh Iyyar std::string country("IN"); 11788a09b52aSRamesh Iyyar std::string email("admin@in.ibm.com"); 11798a09b52aSRamesh Iyyar std::string givenName("givenName"); 11808a09b52aSRamesh Iyyar std::string initials("G"); 11818a09b52aSRamesh Iyyar int64_t keyBitLength(2048); 11828a09b52aSRamesh Iyyar std::string keyCurveId("DummyCurveName"); 11838a09b52aSRamesh Iyyar std::string keyPairAlgorithm("EC"); 11848a09b52aSRamesh Iyyar std::vector<std::string> keyUsage{"serverAuth", "clientAuth"}; 11858a09b52aSRamesh Iyyar std::string organization("IBM"); 11868a09b52aSRamesh Iyyar std::string organizationalUnit("orgUnit"); 11878a09b52aSRamesh Iyyar std::string state("TS"); 11888a09b52aSRamesh Iyyar std::string surname("surname"); 11898a09b52aSRamesh Iyyar std::string unstructuredName("unstructuredName"); 1190cf06ccdcSNan Zhou auto objPath = std::string(objectNamePrefix) + '/' + 1191cf06ccdcSNan Zhou certificateTypeToString(type) + '/' + endpoint; 11928a09b52aSRamesh Iyyar auto event = sdeventplus::Event::get_default(); 11938a09b52aSRamesh Iyyar Manager manager(bus, event, objPath.c_str(), type, std::move(unit), 11948a09b52aSRamesh Iyyar std::move(installPath)); 11958a09b52aSRamesh Iyyar Status status; 1196e3d47cd4SNan Zhou CSR csr(bus, objPath.c_str(), csrPath.c_str(), status); 11978a09b52aSRamesh Iyyar MainApp mainApp(&manager, &csr); 11988a09b52aSRamesh Iyyar mainApp.generateCSR(alternativeNames, challengePassword, city, commonName, 11998a09b52aSRamesh Iyyar contactPerson, country, email, givenName, initials, 12008a09b52aSRamesh Iyyar keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage, 12018a09b52aSRamesh Iyyar organization, organizationalUnit, state, surname, 12028a09b52aSRamesh Iyyar unstructuredName); 1203e3d47cd4SNan Zhou EXPECT_FALSE(fs::exists(csrPath)); 12048a09b52aSRamesh Iyyar EXPECT_FALSE(fs::exists(privateKeyPath)); 12058a09b52aSRamesh Iyyar } 12068a09b52aSRamesh Iyyar 12078a09b52aSRamesh Iyyar /** @brief Check default Key Curve Id is used if given curve id is empty 12088a09b52aSRamesh Iyyar */ 12098a09b52aSRamesh Iyyar TEST_F(TestCertificates, TestECKeyGenerationwithDefaultKeyCurveId) 12108a09b52aSRamesh Iyyar { 12118a09b52aSRamesh Iyyar std::string endpoint("https"); 1212cf06ccdcSNan Zhou std::string unit; 1213e3d47cd4SNan Zhou CertificateType type = CertificateType::server; 12148a09b52aSRamesh Iyyar std::string installPath(certDir + "/" + certificateFile); 12158a09b52aSRamesh Iyyar std::string verifyPath(installPath); 1216e3d47cd4SNan Zhou std::string csrPath(certDir + "/" + CSRFile); 12178a09b52aSRamesh Iyyar std::string privateKeyPath(certDir + "/" + privateKeyFile); 12188a09b52aSRamesh Iyyar std::vector<std::string> alternativeNames{"localhost1", "localhost2"}; 12198a09b52aSRamesh Iyyar std::string challengePassword("Password"); 12208a09b52aSRamesh Iyyar std::string city("BLR"); 12218a09b52aSRamesh Iyyar std::string commonName("abc.com"); 12228a09b52aSRamesh Iyyar std::string contactPerson("Admin"); 12238a09b52aSRamesh Iyyar std::string country("IN"); 12248a09b52aSRamesh Iyyar std::string email("admin@in.ibm.com"); 12258a09b52aSRamesh Iyyar std::string givenName("givenName"); 12268a09b52aSRamesh Iyyar std::string initials("G"); 12278a09b52aSRamesh Iyyar int64_t keyBitLength(2048); 12288a09b52aSRamesh Iyyar std::string keyCurveId(""); 12298a09b52aSRamesh Iyyar std::string keyPairAlgorithm("EC"); 12308a09b52aSRamesh Iyyar std::vector<std::string> keyUsage{"serverAuth", "clientAuth"}; 12318a09b52aSRamesh Iyyar std::string organization("IBM"); 12328a09b52aSRamesh Iyyar std::string organizationalUnit("orgUnit"); 12338a09b52aSRamesh Iyyar std::string state("TS"); 12348a09b52aSRamesh Iyyar std::string surname("surname"); 12358a09b52aSRamesh Iyyar std::string unstructuredName("unstructuredName"); 1236cf06ccdcSNan Zhou auto objPath = std::string(objectNamePrefix) + '/' + 1237cf06ccdcSNan Zhou certificateTypeToString(type) + '/' + endpoint; 12388a09b52aSRamesh Iyyar auto event = sdeventplus::Event::get_default(); 12398a09b52aSRamesh Iyyar Manager manager(bus, event, objPath.c_str(), type, std::move(unit), 12408a09b52aSRamesh Iyyar std::move(installPath)); 12418a09b52aSRamesh Iyyar Status status; 1242e3d47cd4SNan Zhou CSR csr(bus, objPath.c_str(), csrPath.c_str(), status); 12438a09b52aSRamesh Iyyar MainApp mainApp(&manager, &csr); 12448a09b52aSRamesh Iyyar mainApp.generateCSR(alternativeNames, challengePassword, city, commonName, 12458a09b52aSRamesh Iyyar contactPerson, country, email, givenName, initials, 12468a09b52aSRamesh Iyyar keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage, 12478a09b52aSRamesh Iyyar organization, organizationalUnit, state, surname, 12488a09b52aSRamesh Iyyar unstructuredName); 12498a09b52aSRamesh Iyyar sleep(10); 1250e3d47cd4SNan Zhou EXPECT_TRUE(fs::exists(csrPath)); 12518a09b52aSRamesh Iyyar EXPECT_TRUE(fs::exists(privateKeyPath)); 12528a09b52aSRamesh Iyyar } 12538a09b52aSRamesh Iyyar 12548a09b52aSRamesh Iyyar /** @brief Check if error is not thrown to generate EC key pair 12558a09b52aSRamesh Iyyar */ 12568a09b52aSRamesh Iyyar TEST_F(TestCertificates, TestECKeyGeneration) 12578a09b52aSRamesh Iyyar { 12588a09b52aSRamesh Iyyar std::string endpoint("https"); 1259cf06ccdcSNan Zhou std::string unit; 1260e3d47cd4SNan Zhou CertificateType type = CertificateType::server; 12618a09b52aSRamesh Iyyar std::string installPath(certDir + "/" + certificateFile); 12628a09b52aSRamesh Iyyar std::string verifyPath(installPath); 1263e3d47cd4SNan Zhou std::string csrPath(certDir + "/" + CSRFile); 12648a09b52aSRamesh Iyyar std::string privateKeyPath(certDir + "/" + privateKeyFile); 12658a09b52aSRamesh Iyyar std::vector<std::string> alternativeNames{"localhost1", "localhost2"}; 12668a09b52aSRamesh Iyyar std::string challengePassword("Password"); 12678a09b52aSRamesh Iyyar std::string city("BLR"); 12688a09b52aSRamesh Iyyar std::string commonName("abc.com"); 12698a09b52aSRamesh Iyyar std::string contactPerson("Admin"); 12708a09b52aSRamesh Iyyar std::string country("IN"); 12718a09b52aSRamesh Iyyar std::string email("admin@in.ibm.com"); 12728a09b52aSRamesh Iyyar std::string givenName("givenName"); 12738a09b52aSRamesh Iyyar std::string initials("G"); 12748a09b52aSRamesh Iyyar int64_t keyBitLength(2048); 12758a09b52aSRamesh Iyyar std::string keyCurveId("secp521r1"); 12768a09b52aSRamesh Iyyar std::string keyPairAlgorithm("EC"); 12778a09b52aSRamesh Iyyar std::vector<std::string> keyUsage{"serverAuth", "clientAuth"}; 12788a09b52aSRamesh Iyyar std::string organization("IBM"); 12798a09b52aSRamesh Iyyar std::string organizationalUnit("orgUnit"); 12808a09b52aSRamesh Iyyar std::string state("TS"); 12818a09b52aSRamesh Iyyar std::string surname("surname"); 12828a09b52aSRamesh Iyyar std::string unstructuredName("unstructuredName"); 1283cf06ccdcSNan Zhou auto objPath = std::string(objectNamePrefix) + '/' + 1284cf06ccdcSNan Zhou certificateTypeToString(type) + '/' + endpoint; 12858a09b52aSRamesh Iyyar auto event = sdeventplus::Event::get_default(); 12868a09b52aSRamesh Iyyar Manager manager(bus, event, objPath.c_str(), type, std::move(unit), 12878a09b52aSRamesh Iyyar std::move(installPath)); 12888a09b52aSRamesh Iyyar Status status; 1289e3d47cd4SNan Zhou CSR csr(bus, objPath.c_str(), csrPath.c_str(), status); 12908a09b52aSRamesh Iyyar MainApp mainApp(&manager, &csr); 12918a09b52aSRamesh Iyyar mainApp.generateCSR(alternativeNames, challengePassword, city, commonName, 12928a09b52aSRamesh Iyyar contactPerson, country, email, givenName, initials, 12938a09b52aSRamesh Iyyar keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage, 12948a09b52aSRamesh Iyyar organization, organizationalUnit, state, surname, 12958a09b52aSRamesh Iyyar unstructuredName); 1296e3d47cd4SNan Zhou std::cout << "CSRPath: " << csrPath << std::endl 12978a09b52aSRamesh Iyyar << "privateKeyPath: " << privateKeyPath << std::endl; 12988a09b52aSRamesh Iyyar sleep(10); 1299e3d47cd4SNan Zhou EXPECT_TRUE(fs::exists(csrPath)); 13008a09b52aSRamesh Iyyar EXPECT_TRUE(fs::exists(privateKeyPath)); 13018a09b52aSRamesh Iyyar } 1302c6e58c7eSRamesh Iyyar 1303bf3cf751SNan Zhou /** @brief Check error is thrown if giving unsupported key bit length to 1304c6e58c7eSRamesh Iyyar * generate rsa key 1305c6e58c7eSRamesh Iyyar */ 1306c6e58c7eSRamesh Iyyar TEST_F(TestCertificates, TestRSAKeyWithUnsupportedKeyBitLength) 1307c6e58c7eSRamesh Iyyar { 1308c6e58c7eSRamesh Iyyar std::string endpoint("https"); 1309cf06ccdcSNan Zhou std::string unit; 1310e3d47cd4SNan Zhou CertificateType type = CertificateType::server; 1311c6e58c7eSRamesh Iyyar std::string installPath(certDir + "/" + certificateFile); 1312c6e58c7eSRamesh Iyyar std::string verifyPath(installPath); 1313e3d47cd4SNan Zhou std::string csrPath(certDir + "/" + CSRFile); 1314c6e58c7eSRamesh Iyyar std::string privateKeyPath(certDir + "/" + privateKeyFile); 1315c6e58c7eSRamesh Iyyar std::vector<std::string> alternativeNames{"localhost1", "localhost2"}; 1316c6e58c7eSRamesh Iyyar std::string challengePassword("Password"); 1317c6e58c7eSRamesh Iyyar std::string city("BLR"); 1318c6e58c7eSRamesh Iyyar std::string commonName("abc.com"); 1319c6e58c7eSRamesh Iyyar std::string contactPerson("Admin"); 1320c6e58c7eSRamesh Iyyar std::string country("IN"); 1321c6e58c7eSRamesh Iyyar std::string email("admin@in.ibm.com"); 1322c6e58c7eSRamesh Iyyar std::string givenName("givenName"); 1323c6e58c7eSRamesh Iyyar std::string initials("G"); 1324c6e58c7eSRamesh Iyyar int64_t keyBitLength(4096); 1325c6e58c7eSRamesh Iyyar std::string keyCurveId("secp521r1"); 1326c6e58c7eSRamesh Iyyar std::string keyPairAlgorithm("RSA"); 1327c6e58c7eSRamesh Iyyar std::vector<std::string> keyUsage{"serverAuth", "clientAuth"}; 1328c6e58c7eSRamesh Iyyar std::string organization("IBM"); 1329c6e58c7eSRamesh Iyyar std::string organizationalUnit("orgUnit"); 1330c6e58c7eSRamesh Iyyar std::string state("TS"); 1331c6e58c7eSRamesh Iyyar std::string surname("surname"); 1332c6e58c7eSRamesh Iyyar std::string unstructuredName("unstructuredName"); 1333cf06ccdcSNan Zhou auto objPath = std::string(objectNamePrefix) + '/' + 1334cf06ccdcSNan Zhou certificateTypeToString(type) + '/' + endpoint; 1335c6e58c7eSRamesh Iyyar auto event = sdeventplus::Event::get_default(); 1336c6e58c7eSRamesh Iyyar Manager manager(bus, event, objPath.c_str(), type, std::move(unit), 1337c6e58c7eSRamesh Iyyar std::move(installPath)); 1338c6e58c7eSRamesh Iyyar Status status; 1339e3d47cd4SNan Zhou CSR csr(bus, objPath.c_str(), csrPath.c_str(), status); 1340c6e58c7eSRamesh Iyyar MainApp mainApp(&manager, &csr); 1341c6e58c7eSRamesh Iyyar mainApp.generateCSR(alternativeNames, challengePassword, city, commonName, 1342c6e58c7eSRamesh Iyyar contactPerson, country, email, givenName, initials, 1343c6e58c7eSRamesh Iyyar keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage, 1344c6e58c7eSRamesh Iyyar organization, organizationalUnit, state, surname, 1345c6e58c7eSRamesh Iyyar unstructuredName); 1346e3d47cd4SNan Zhou EXPECT_FALSE(fs::exists(csrPath)); 1347c6e58c7eSRamesh Iyyar EXPECT_FALSE(fs::exists(privateKeyPath)); 1348c6e58c7eSRamesh Iyyar } 1349c6e58c7eSRamesh Iyyar 1350c6e58c7eSRamesh Iyyar /** @brief Check error is thrown if generated rsa key file is not present 1351c6e58c7eSRamesh Iyyar */ 1352c6e58c7eSRamesh Iyyar TEST_F(TestCertificates, TestRSAKeyFileNotPresentCase) 1353c6e58c7eSRamesh Iyyar { 1354c6e58c7eSRamesh Iyyar std::string endpoint("https"); 1355cf06ccdcSNan Zhou std::string unit; 1356e3d47cd4SNan Zhou CertificateType type = CertificateType::server; 1357c6e58c7eSRamesh Iyyar std::string installPath(certDir + "/" + certificateFile); 1358c6e58c7eSRamesh Iyyar std::string verifyPath(installPath); 1359e3d47cd4SNan Zhou std::string csrPath(certDir + "/" + CSRFile); 1360c6e58c7eSRamesh Iyyar std::string privateKeyPath(certDir + "/" + privateKeyFile); 1361c6e58c7eSRamesh Iyyar std::vector<std::string> alternativeNames{"localhost1", "localhost2"}; 1362c6e58c7eSRamesh Iyyar std::string challengePassword("Password"); 1363c6e58c7eSRamesh Iyyar std::string city("BLR"); 1364c6e58c7eSRamesh Iyyar std::string commonName("abc.com"); 1365c6e58c7eSRamesh Iyyar std::string contactPerson("Admin"); 1366c6e58c7eSRamesh Iyyar std::string country("IN"); 1367c6e58c7eSRamesh Iyyar std::string email("admin@in.ibm.com"); 1368c6e58c7eSRamesh Iyyar std::string givenName("givenName"); 1369c6e58c7eSRamesh Iyyar std::string initials("G"); 1370c6e58c7eSRamesh Iyyar int64_t keyBitLength(2048); 1371c6e58c7eSRamesh Iyyar std::string keyCurveId("secp521r1"); 1372c6e58c7eSRamesh Iyyar std::string keyPairAlgorithm("RSA"); 1373c6e58c7eSRamesh Iyyar std::vector<std::string> keyUsage{"serverAuth", "clientAuth"}; 1374c6e58c7eSRamesh Iyyar std::string organization("IBM"); 1375c6e58c7eSRamesh Iyyar std::string organizationalUnit("orgUnit"); 1376c6e58c7eSRamesh Iyyar std::string state("TS"); 1377c6e58c7eSRamesh Iyyar std::string surname("surname"); 1378c6e58c7eSRamesh Iyyar std::string unstructuredName("unstructuredName"); 1379cf06ccdcSNan Zhou auto objPath = std::string(objectNamePrefix) + '/' + 1380cf06ccdcSNan Zhou certificateTypeToString(type) + '/' + endpoint; 1381c6e58c7eSRamesh Iyyar auto event = sdeventplus::Event::get_default(); 1382c6e58c7eSRamesh Iyyar Manager manager(bus, event, objPath.c_str(), type, std::move(unit), 1383c6e58c7eSRamesh Iyyar std::move(installPath)); 1384c6e58c7eSRamesh Iyyar 1385c6e58c7eSRamesh Iyyar // Removing generated RSA key file 1386c6e58c7eSRamesh Iyyar fs::remove(rsaPrivateKeyFilePath); 1387c6e58c7eSRamesh Iyyar 1388c6e58c7eSRamesh Iyyar Status status; 1389e3d47cd4SNan Zhou CSR csr(bus, objPath.c_str(), csrPath.c_str(), status); 1390c6e58c7eSRamesh Iyyar MainApp mainApp(&manager, &csr); 1391c6e58c7eSRamesh Iyyar mainApp.generateCSR(alternativeNames, challengePassword, city, commonName, 1392c6e58c7eSRamesh Iyyar contactPerson, country, email, givenName, initials, 1393c6e58c7eSRamesh Iyyar keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage, 1394c6e58c7eSRamesh Iyyar organization, organizationalUnit, state, surname, 1395c6e58c7eSRamesh Iyyar unstructuredName); 1396e3d47cd4SNan Zhou EXPECT_FALSE(fs::exists(csrPath)); 1397c6e58c7eSRamesh Iyyar EXPECT_FALSE(fs::exists(privateKeyPath)); 1398c6e58c7eSRamesh Iyyar } 1399c6e58c7eSRamesh Iyyar 1400c6e58c7eSRamesh Iyyar /** @brief Check private key file is created from generated rsa key file is 1401c6e58c7eSRamesh Iyyar * `present 1402c6e58c7eSRamesh Iyyar */ 1403c6e58c7eSRamesh Iyyar TEST_F(TestCertificates, TestRSAKeyFromRSAKeyFileIsWrittenIntoPrivateKeyFile) 1404c6e58c7eSRamesh Iyyar { 1405c6e58c7eSRamesh Iyyar std::string endpoint("https"); 1406cf06ccdcSNan Zhou std::string unit; 1407e3d47cd4SNan Zhou CertificateType type = CertificateType::server; 1408c6e58c7eSRamesh Iyyar std::string installPath(certDir + "/" + certificateFile); 1409c6e58c7eSRamesh Iyyar std::string verifyPath(installPath); 1410e3d47cd4SNan Zhou std::string csrPath(certDir + "/" + CSRFile); 1411c6e58c7eSRamesh Iyyar std::string privateKeyPath(certDir + "/" + privateKeyFile); 1412c6e58c7eSRamesh Iyyar std::vector<std::string> alternativeNames{"localhost1", "localhost2"}; 1413c6e58c7eSRamesh Iyyar std::string challengePassword("Password"); 1414c6e58c7eSRamesh Iyyar std::string city("BLR"); 1415c6e58c7eSRamesh Iyyar std::string commonName("abc.com"); 1416c6e58c7eSRamesh Iyyar std::string contactPerson("Admin"); 1417c6e58c7eSRamesh Iyyar std::string country("IN"); 1418c6e58c7eSRamesh Iyyar std::string email("admin@in.ibm.com"); 1419c6e58c7eSRamesh Iyyar std::string givenName("givenName"); 1420c6e58c7eSRamesh Iyyar std::string initials("G"); 1421c6e58c7eSRamesh Iyyar int64_t keyBitLength(2048); 1422c6e58c7eSRamesh Iyyar std::string keyCurveId("secp521r1"); 1423c6e58c7eSRamesh Iyyar std::string keyPairAlgorithm("RSA"); 1424c6e58c7eSRamesh Iyyar std::vector<std::string> keyUsage{"serverAuth", "clientAuth"}; 1425c6e58c7eSRamesh Iyyar std::string organization("IBM"); 1426c6e58c7eSRamesh Iyyar std::string organizationalUnit("orgUnit"); 1427c6e58c7eSRamesh Iyyar std::string state("TS"); 1428c6e58c7eSRamesh Iyyar std::string surname("surname"); 1429c6e58c7eSRamesh Iyyar std::string unstructuredName("unstructuredName"); 1430cf06ccdcSNan Zhou auto objPath = std::string(objectNamePrefix) + '/' + 1431cf06ccdcSNan Zhou certificateTypeToString(type) + '/' + endpoint; 1432c6e58c7eSRamesh Iyyar auto event = sdeventplus::Event::get_default(); 1433c6e58c7eSRamesh Iyyar Manager manager(bus, event, objPath.c_str(), type, std::move(unit), 1434c6e58c7eSRamesh Iyyar std::move(installPath)); 1435c6e58c7eSRamesh Iyyar Status status; 1436e3d47cd4SNan Zhou CSR csr(bus, objPath.c_str(), csrPath.c_str(), status); 1437c6e58c7eSRamesh Iyyar MainApp mainApp(&manager, &csr); 1438c6e58c7eSRamesh Iyyar mainApp.generateCSR(alternativeNames, challengePassword, city, commonName, 1439c6e58c7eSRamesh Iyyar contactPerson, country, email, givenName, initials, 1440c6e58c7eSRamesh Iyyar keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage, 1441c6e58c7eSRamesh Iyyar organization, organizationalUnit, state, surname, 1442c6e58c7eSRamesh Iyyar unstructuredName); 1443c6e58c7eSRamesh Iyyar sleep(10); 1444e3d47cd4SNan Zhou EXPECT_TRUE(fs::exists(csrPath)); 1445c6e58c7eSRamesh Iyyar EXPECT_TRUE(fs::exists(privateKeyPath)); 1446c6e58c7eSRamesh Iyyar } 1447c6e58c7eSRamesh Iyyar 1448bf3cf751SNan Zhou /** @brief Check RSA key is generated during application startup*/ 1449c6e58c7eSRamesh Iyyar TEST_F(TestCertificates, TestGenerateRSAPrivateKeyFile) 1450c6e58c7eSRamesh Iyyar { 1451c6e58c7eSRamesh Iyyar std::string endpoint("https"); 1452e3d47cd4SNan Zhou CertificateType type = CertificateType::server; 1453c6e58c7eSRamesh Iyyar std::string installPath(certDir + "/" + certificateFile); 14546ec13c8fSNan Zhou std::string verifyUnit(ManagerInTest::unitToRestartInTest); 1455cf06ccdcSNan Zhou auto objPath = std::string(objectNamePrefix) + '/' + 1456cf06ccdcSNan Zhou certificateTypeToString(type) + '/' + endpoint; 1457c6e58c7eSRamesh Iyyar auto event = sdeventplus::Event::get_default(); 1458c6e58c7eSRamesh Iyyar 1459c6e58c7eSRamesh Iyyar EXPECT_FALSE(fs::exists(rsaPrivateKeyFilePath)); 14606ec13c8fSNan Zhou Manager manager(bus, event, objPath.c_str(), type, verifyUnit, installPath); 1461c6e58c7eSRamesh Iyyar EXPECT_TRUE(fs::exists(rsaPrivateKeyFilePath)); 1462c6e58c7eSRamesh Iyyar } 14636ec13c8fSNan Zhou 14646ec13c8fSNan Zhou /** 14656ec13c8fSNan Zhou * Class to test Authorities List installation and replacement 14666ec13c8fSNan Zhou */ 14676ec13c8fSNan Zhou class AuthoritiesListTest : public testing::Test 14686ec13c8fSNan Zhou { 14696ec13c8fSNan Zhou public: 14706ec13c8fSNan Zhou AuthoritiesListTest() : 14716ec13c8fSNan Zhou bus(sdbusplus::bus::new_default()), 14726ec13c8fSNan Zhou authoritiesListFolder( 14736ec13c8fSNan Zhou Certificate::generateUniqueFilePath(fs::temp_directory_path())) 14746ec13c8fSNan Zhou { 14756ec13c8fSNan Zhou fs::create_directory(authoritiesListFolder); 14766ec13c8fSNan Zhou createAuthoritiesList(maxNumAuthorityCertificates); 14776ec13c8fSNan Zhou } 14786ec13c8fSNan Zhou ~AuthoritiesListTest() override 14796ec13c8fSNan Zhou { 14806ec13c8fSNan Zhou fs::remove_all(authoritiesListFolder); 14816ec13c8fSNan Zhou } 14826ec13c8fSNan Zhou 14836ec13c8fSNan Zhou protected: 14846ec13c8fSNan Zhou // Creates a testing authorities list which consists of |count| root 14856ec13c8fSNan Zhou // certificates 14866ec13c8fSNan Zhou void createAuthoritiesList(int count) 14876ec13c8fSNan Zhou { 14886ec13c8fSNan Zhou fs::path srcFolder = fs::temp_directory_path(); 14896ec13c8fSNan Zhou srcFolder = Certificate::generateUniqueFilePath(srcFolder); 14906ec13c8fSNan Zhou fs::create_directory(srcFolder); 14916ec13c8fSNan Zhou createSingleAuthority(srcFolder, "root_0"); 14926ec13c8fSNan Zhou sourceAuthoritiesListFile = srcFolder / "root_0_cert"; 14936ec13c8fSNan Zhou for (int i = 1; i < count; ++i) 14946ec13c8fSNan Zhou { 14956ec13c8fSNan Zhou std::string name = "root_" + std::to_string(i); 14966ec13c8fSNan Zhou createSingleAuthority(srcFolder, name); 14976ec13c8fSNan Zhou appendContentFromFile(sourceAuthoritiesListFile, 14986ec13c8fSNan Zhou srcFolder / (name + "_cert")); 14996ec13c8fSNan Zhou } 15006ec13c8fSNan Zhou } 15016ec13c8fSNan Zhou 15026ec13c8fSNan Zhou // Creates a single self-signed root certificate in given |path|; the key 15036ec13c8fSNan Zhou // will be |path|/|cn|_key, the cert will be |path|/|cn|_cert, and the cn 15046ec13c8fSNan Zhou // will be "/O=openbmc-project.xyz/C=US/ST=CA/CN=|cn|" 15056ec13c8fSNan Zhou static void createSingleAuthority(const std::string& path, 15066ec13c8fSNan Zhou const std::string& cn) 15076ec13c8fSNan Zhou { 15086ec13c8fSNan Zhou std::string key = fs::path(path) / (cn + "_key"); 15096ec13c8fSNan Zhou std::string cert = fs::path(path) / (cn + "_cert"); 15106ec13c8fSNan Zhou std::string cmd = "openssl req -x509 -sha256 -newkey rsa:2048 -keyout "; 15116ec13c8fSNan Zhou cmd += key + " -out " + cert + " -nodes --days 365000 "; 15126ec13c8fSNan Zhou cmd += "-subj /O=openbmc-project.xyz/CN=" + cn; 15136ec13c8fSNan Zhou ASSERT_EQ(std::system(cmd.c_str()), 0); 15146ec13c8fSNan Zhou } 15156ec13c8fSNan Zhou 15166ec13c8fSNan Zhou // Appends the content of the |from| file to the |to| file. 15176ec13c8fSNan Zhou static void appendContentFromFile(const std::string& to, 15186ec13c8fSNan Zhou const std::string& from) 15196ec13c8fSNan Zhou { 15206ec13c8fSNan Zhou ASSERT_NO_THROW({ 15216ec13c8fSNan Zhou std::ifstream inputCertFileStream; 15226ec13c8fSNan Zhou std::ofstream outputCertFileStream; 15236ec13c8fSNan Zhou inputCertFileStream.exceptions(std::ifstream::failbit | 15246ec13c8fSNan Zhou std::ifstream::badbit | 15256ec13c8fSNan Zhou std::ifstream::eofbit); 15266ec13c8fSNan Zhou outputCertFileStream.exceptions(std::ofstream::failbit | 15276ec13c8fSNan Zhou std::ofstream::badbit | 15286ec13c8fSNan Zhou std::ofstream::eofbit); 15296ec13c8fSNan Zhou inputCertFileStream.open(from); 15306ec13c8fSNan Zhou outputCertFileStream.open(to, std::ios::app); 15316ec13c8fSNan Zhou outputCertFileStream << inputCertFileStream.rdbuf() << std::flush; 15326ec13c8fSNan Zhou inputCertFileStream.close(); 15336ec13c8fSNan Zhou outputCertFileStream.close(); 15346ec13c8fSNan Zhou }); 15356ec13c8fSNan Zhou } 15366ec13c8fSNan Zhou 15376ec13c8fSNan Zhou // Appends the content of the |from| buffer to the |to| file. 15386ec13c8fSNan Zhou static void setContentFromString(const std::string& to, 15396ec13c8fSNan Zhou const std::string& from) 15406ec13c8fSNan Zhou { 15416ec13c8fSNan Zhou ASSERT_NO_THROW({ 15426ec13c8fSNan Zhou std::ofstream outputCertFileStream; 15436ec13c8fSNan Zhou outputCertFileStream.exceptions(std::ofstream::failbit | 15446ec13c8fSNan Zhou std::ofstream::badbit | 15456ec13c8fSNan Zhou std::ofstream::eofbit); 15466ec13c8fSNan Zhou outputCertFileStream.open(to, std::ios::out); 15476ec13c8fSNan Zhou outputCertFileStream << from << std::flush; 15486ec13c8fSNan Zhou outputCertFileStream.close(); 15496ec13c8fSNan Zhou }); 15506ec13c8fSNan Zhou } 15516ec13c8fSNan Zhou 15526ec13c8fSNan Zhou // Verifies the effect of InstallAll or ReplaceAll 15536ec13c8fSNan Zhou void verifyCertificates(std::vector<std::unique_ptr<Certificate>>& certs) 15546ec13c8fSNan Zhou { 15556ec13c8fSNan Zhou // The trust bundle file has been copied over 15566ec13c8fSNan Zhou EXPECT_FALSE(fs::is_empty(authoritiesListFolder)); 15576ec13c8fSNan Zhou EXPECT_TRUE( 15586ec13c8fSNan Zhou compareFiles(authoritiesListFolder / defaultAuthoritiesListFileName, 15596ec13c8fSNan Zhou sourceAuthoritiesListFile)); 15606ec13c8fSNan Zhou 15616ec13c8fSNan Zhou ASSERT_EQ(certs.size(), maxNumAuthorityCertificates); 15626ec13c8fSNan Zhou // Check attributes and alias 15636ec13c8fSNan Zhou for (size_t i = 0; i < certs.size(); ++i) 15646ec13c8fSNan Zhou { 15656ec13c8fSNan Zhou std::string name = "root_" + std::to_string(i); 15666ec13c8fSNan Zhou EXPECT_EQ(certs[i]->subject(), "O=openbmc-project.xyz,CN=" + name); 15676ec13c8fSNan Zhou EXPECT_EQ(certs[i]->issuer(), "O=openbmc-project.xyz,CN=" + name); 15686ec13c8fSNan Zhou std::string symbolLink = 15696ec13c8fSNan Zhou authoritiesListFolder / 15706ec13c8fSNan Zhou (certs[i]->getCertId().substr(0, 8) + ".0"); 15716ec13c8fSNan Zhou ASSERT_TRUE(fs::exists(symbolLink)); 15726ec13c8fSNan Zhou compareFileAgainstString(symbolLink, certs[i]->certificateString()); 15736ec13c8fSNan Zhou } 15746ec13c8fSNan Zhou } 15756ec13c8fSNan Zhou 15766ec13c8fSNan Zhou // Expects that the content of |path| file is |buffer|. 15776ec13c8fSNan Zhou static void compareFileAgainstString(const std::string& path, 15786ec13c8fSNan Zhou const std::string& buffer) 15796ec13c8fSNan Zhou { 15806ec13c8fSNan Zhou ASSERT_NO_THROW({ 15816ec13c8fSNan Zhou std::ifstream inputCertFileStream; 15826ec13c8fSNan Zhou inputCertFileStream.exceptions(std::ifstream::failbit | 15836ec13c8fSNan Zhou std::ifstream::badbit | 15846ec13c8fSNan Zhou std::ifstream::eofbit); 15856ec13c8fSNan Zhou inputCertFileStream.open(path); 15866ec13c8fSNan Zhou std::stringstream read; 15876ec13c8fSNan Zhou read << inputCertFileStream.rdbuf(); 15886ec13c8fSNan Zhou inputCertFileStream.close(); 15896ec13c8fSNan Zhou EXPECT_EQ(read.str(), buffer); 15906ec13c8fSNan Zhou }); 15916ec13c8fSNan Zhou }; 15926ec13c8fSNan Zhou 1593b3dbfb37SPatrick Williams sdbusplus::bus_t bus; 15946ec13c8fSNan Zhou fs::path authoritiesListFolder; 15956ec13c8fSNan Zhou fs::path sourceAuthoritiesListFile; 15966ec13c8fSNan Zhou }; 15976ec13c8fSNan Zhou 15986ec13c8fSNan Zhou // Tests that the Authority Manager installs all the certificates in an 15996ec13c8fSNan Zhou // authorities list 16006ec13c8fSNan Zhou TEST_F(AuthoritiesListTest, InstallAll) 16016ec13c8fSNan Zhou { 1602*2e8fa88eSMichal Orzel std::string endpoint("truststore"); 16036ec13c8fSNan Zhou std::string verifyUnit(ManagerInTest::unitToRestartInTest); 1604e3d47cd4SNan Zhou CertificateType type = CertificateType::authority; 16056ec13c8fSNan Zhou 16066ec13c8fSNan Zhou std::string object = std::string(objectNamePrefix) + '/' + 16076ec13c8fSNan Zhou certificateTypeToString(type) + '/' + endpoint; 16086ec13c8fSNan Zhou auto event = sdeventplus::Event::get_default(); 16096ec13c8fSNan Zhou // Attach the bus to sd_event to service user requests 16106ec13c8fSNan Zhou bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 16116ec13c8fSNan Zhou ManagerInTest manager(bus, event, object.c_str(), type, verifyUnit, 16126ec13c8fSNan Zhou authoritiesListFolder); 16136ec13c8fSNan Zhou EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest))) 16146ec13c8fSNan Zhou .WillOnce(Return()); 16156ec13c8fSNan Zhou ASSERT_TRUE(manager.getCertificates().empty()); 16166ec13c8fSNan Zhou 16176ec13c8fSNan Zhou std::vector<sdbusplus::message::object_path> objects = 16186ec13c8fSNan Zhou manager.installAll(sourceAuthoritiesListFile); 16196ec13c8fSNan Zhou for (size_t i = 0; i < manager.getCertificates().size(); ++i) 16206ec13c8fSNan Zhou { 16216ec13c8fSNan Zhou EXPECT_EQ(manager.getCertificates()[i]->getObjectPath(), objects[i]); 16226ec13c8fSNan Zhou } 16236ec13c8fSNan Zhou verifyCertificates(manager.getCertificates()); 16246ec13c8fSNan Zhou } 16256ec13c8fSNan Zhou 16266ec13c8fSNan Zhou // Tests that the Authority Manager recovers from the authorities list persisted 16276ec13c8fSNan Zhou // in the installation path at boot up 16286ec13c8fSNan Zhou TEST_F(AuthoritiesListTest, RecoverAtBootUp) 16296ec13c8fSNan Zhou { 1630*2e8fa88eSMichal Orzel std::string endpoint("truststore"); 16316ec13c8fSNan Zhou std::string verifyUnit(ManagerInTest::unitToRestartInTest); 1632e3d47cd4SNan Zhou CertificateType type = CertificateType::authority; 16336ec13c8fSNan Zhou 16346ec13c8fSNan Zhou std::string object = std::string(objectNamePrefix) + '/' + 16356ec13c8fSNan Zhou certificateTypeToString(type) + '/' + endpoint; 16366ec13c8fSNan Zhou auto event = sdeventplus::Event::get_default(); 16376ec13c8fSNan Zhou // Attach the bus to sd_event to service user requests 16386ec13c8fSNan Zhou bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 16396ec13c8fSNan Zhou 16406ec13c8fSNan Zhou // Copy the trust bundle into the installation path before creating an 16416ec13c8fSNan Zhou // Authority Manager 16426ec13c8fSNan Zhou fs::copy_file(/*from=*/sourceAuthoritiesListFile, 16436ec13c8fSNan Zhou authoritiesListFolder / defaultAuthoritiesListFileName); 16446ec13c8fSNan Zhou // Create some noise as well 16456ec13c8fSNan Zhou fs::copy_file(/*from=*/sourceAuthoritiesListFile, 16466ec13c8fSNan Zhou authoritiesListFolder / "should_be_deleted"); 16476ec13c8fSNan Zhou 16486ec13c8fSNan Zhou ManagerInTest manager(bus, event, object.c_str(), type, verifyUnit, 16496ec13c8fSNan Zhou authoritiesListFolder); 16506ec13c8fSNan Zhou 16516ec13c8fSNan Zhou ASSERT_EQ(manager.getCertificates().size(), maxNumAuthorityCertificates); 16526ec13c8fSNan Zhou 16536ec13c8fSNan Zhou // Check attributes and alias 16546ec13c8fSNan Zhou std::unordered_set<std::string> expectedFiles = {authoritiesListFolder / 16556ec13c8fSNan Zhou "trust_bundle"}; 16566ec13c8fSNan Zhou std::vector<std::unique_ptr<Certificate>>& certs = 16576ec13c8fSNan Zhou manager.getCertificates(); 16586ec13c8fSNan Zhou for (size_t i = 0; i < certs.size(); ++i) 16596ec13c8fSNan Zhou { 16606ec13c8fSNan Zhou std::string name = "root_" + std::to_string(i); 16616ec13c8fSNan Zhou EXPECT_EQ(certs[i]->subject(), "O=openbmc-project.xyz,CN=" + name); 16626ec13c8fSNan Zhou EXPECT_EQ(certs[i]->issuer(), "O=openbmc-project.xyz,CN=" + name); 1663223e4604SPatrick Williams std::string symbolLink = authoritiesListFolder / 1664223e4604SPatrick Williams (certs[i]->getCertId().substr(0, 8) + ".0"); 16656ec13c8fSNan Zhou expectedFiles.insert(symbolLink); 16666ec13c8fSNan Zhou expectedFiles.insert(certs[i]->getCertFilePath()); 16676ec13c8fSNan Zhou ASSERT_TRUE(fs::exists(symbolLink)); 16686ec13c8fSNan Zhou compareFileAgainstString(symbolLink, certs[i]->certificateString()); 16696ec13c8fSNan Zhou } 16706ec13c8fSNan Zhou 16716ec13c8fSNan Zhou // Check folder content 16726ec13c8fSNan Zhou for (auto& path : fs::directory_iterator(authoritiesListFolder)) 16736ec13c8fSNan Zhou { 16746ec13c8fSNan Zhou EXPECT_NE(path, authoritiesListFolder / "should_be_deleted"); 16756ec13c8fSNan Zhou expectedFiles.erase(path.path()); 16766ec13c8fSNan Zhou } 16776ec13c8fSNan Zhou EXPECT_TRUE(expectedFiles.empty()); 16786ec13c8fSNan Zhou } 16796ec13c8fSNan Zhou 16806ec13c8fSNan Zhou TEST_F(AuthoritiesListTest, InstallAndDelete) 16816ec13c8fSNan Zhou { 1682*2e8fa88eSMichal Orzel std::string endpoint("truststore"); 16836ec13c8fSNan Zhou std::string verifyUnit(ManagerInTest::unitToRestartInTest); 1684e3d47cd4SNan Zhou CertificateType type = CertificateType::authority; 16856ec13c8fSNan Zhou 16866ec13c8fSNan Zhou std::string object = std::string(objectNamePrefix) + '/' + 16876ec13c8fSNan Zhou certificateTypeToString(type) + '/' + endpoint; 16886ec13c8fSNan Zhou 16896ec13c8fSNan Zhou auto event = sdeventplus::Event::get_default(); 16906ec13c8fSNan Zhou // Attach the bus to sd_event to service user requests 16916ec13c8fSNan Zhou bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 16926ec13c8fSNan Zhou ManagerInTest manager(bus, event, object.c_str(), type, verifyUnit, 16936ec13c8fSNan Zhou authoritiesListFolder); 16946ec13c8fSNan Zhou EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest))) 16956ec13c8fSNan Zhou .WillOnce(Return()) 16966ec13c8fSNan Zhou .WillOnce(Return()); 16976ec13c8fSNan Zhou ASSERT_TRUE(manager.getCertificates().empty()); 16986ec13c8fSNan Zhou ASSERT_EQ(manager.installAll(sourceAuthoritiesListFile).size(), 16996ec13c8fSNan Zhou maxNumAuthorityCertificates); 17006ec13c8fSNan Zhou manager.deleteAll(); 17016ec13c8fSNan Zhou EXPECT_TRUE(manager.getCertificates().empty()); 17026ec13c8fSNan Zhou // Check folder content 17036ec13c8fSNan Zhou for (const fs::path& f : fs::directory_iterator(authoritiesListFolder)) 17046ec13c8fSNan Zhou { 17056ec13c8fSNan Zhou EXPECT_THAT(f.filename(), testing::AnyOf(".", "..")); 17066ec13c8fSNan Zhou } 17076ec13c8fSNan Zhou } 17086ec13c8fSNan Zhou 17096ec13c8fSNan Zhou TEST_F(AuthoritiesListTest, InstallAllWrongManagerType) 17106ec13c8fSNan Zhou { 17116ec13c8fSNan Zhou std::string endpoint("ldap"); 1712e3d47cd4SNan Zhou CertificateType type = CertificateType::server; 17136ec13c8fSNan Zhou 17146ec13c8fSNan Zhou std::string object = std::string(objectNamePrefix) + '/' + 17156ec13c8fSNan Zhou certificateTypeToString(type) + '/' + endpoint; 17166ec13c8fSNan Zhou 17176ec13c8fSNan Zhou auto event = sdeventplus::Event::get_default(); 17186ec13c8fSNan Zhou // Attach the bus to sd_event to service user requests 17196ec13c8fSNan Zhou bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 17206ec13c8fSNan Zhou ManagerInTest serverManager(bus, event, object.c_str(), type, "", 17216ec13c8fSNan Zhou authoritiesListFolder); 17226ec13c8fSNan Zhou EXPECT_THROW(serverManager.installAll(sourceAuthoritiesListFile), 17236ec13c8fSNan Zhou sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed); 17246ec13c8fSNan Zhou 1725e3d47cd4SNan Zhou type = CertificateType::client; 17266ec13c8fSNan Zhou object = std::string(objectNamePrefix) + '/' + 17276ec13c8fSNan Zhou certificateTypeToString(type) + '/' + endpoint; 17286ec13c8fSNan Zhou ManagerInTest clientManager(bus, event, object.c_str(), type, "", 17296ec13c8fSNan Zhou authoritiesListFolder); 17306ec13c8fSNan Zhou EXPECT_THROW(clientManager.installAll(sourceAuthoritiesListFile), 17316ec13c8fSNan Zhou sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed); 17326ec13c8fSNan Zhou } 17336ec13c8fSNan Zhou 17346ec13c8fSNan Zhou TEST_F(AuthoritiesListTest, InstallAllTwice) 17356ec13c8fSNan Zhou { 1736*2e8fa88eSMichal Orzel std::string endpoint("truststore"); 17376ec13c8fSNan Zhou std::string verifyUnit(ManagerInTest::unitToRestartInTest); 1738e3d47cd4SNan Zhou CertificateType type = CertificateType::authority; 17396ec13c8fSNan Zhou 17406ec13c8fSNan Zhou std::string object = std::string(objectNamePrefix) + '/' + 17416ec13c8fSNan Zhou certificateTypeToString(type) + '/' + endpoint; 17426ec13c8fSNan Zhou 17436ec13c8fSNan Zhou auto event = sdeventplus::Event::get_default(); 17446ec13c8fSNan Zhou // Attach the bus to sd_event to service user requests 17456ec13c8fSNan Zhou bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 17466ec13c8fSNan Zhou ManagerInTest manager(bus, event, object.c_str(), type, verifyUnit, 17476ec13c8fSNan Zhou authoritiesListFolder); 17486ec13c8fSNan Zhou EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest))) 17496ec13c8fSNan Zhou .WillOnce(Return()); 17506ec13c8fSNan Zhou ASSERT_TRUE(manager.getCertificates().empty()); 17516ec13c8fSNan Zhou 17526ec13c8fSNan Zhou ASSERT_EQ(manager.installAll(sourceAuthoritiesListFile).size(), 17536ec13c8fSNan Zhou maxNumAuthorityCertificates); 175456bfa731SNan Zhou EXPECT_THROW(manager.installAll(sourceAuthoritiesListFile), 17556ec13c8fSNan Zhou sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed); 17566ec13c8fSNan Zhou } 17576ec13c8fSNan Zhou 17586ec13c8fSNan Zhou TEST_F(AuthoritiesListTest, InstallAllMissSourceFile) 17596ec13c8fSNan Zhou { 1760*2e8fa88eSMichal Orzel std::string endpoint("truststore"); 17616ec13c8fSNan Zhou std::string verifyUnit(ManagerInTest::unitToRestartInTest); 1762e3d47cd4SNan Zhou CertificateType type = CertificateType::authority; 17636ec13c8fSNan Zhou 17646ec13c8fSNan Zhou std::string object = std::string(objectNamePrefix) + '/' + 17656ec13c8fSNan Zhou certificateTypeToString(type) + '/' + endpoint; 17666ec13c8fSNan Zhou 17676ec13c8fSNan Zhou auto event = sdeventplus::Event::get_default(); 17686ec13c8fSNan Zhou // Attach the bus to sd_event to service user requests 17696ec13c8fSNan Zhou bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 17706ec13c8fSNan Zhou ManagerInTest manager(bus, event, object.c_str(), type, verifyUnit, 17716ec13c8fSNan Zhou authoritiesListFolder); 17726ec13c8fSNan Zhou 17736ec13c8fSNan Zhou EXPECT_THROW(manager.installAll(authoritiesListFolder / "trust_bundle"), 17746ec13c8fSNan Zhou InternalFailure); 17756ec13c8fSNan Zhou } 17766ec13c8fSNan Zhou 17776ec13c8fSNan Zhou TEST_F(AuthoritiesListTest, TooManyRootCertificates) 17786ec13c8fSNan Zhou { 1779*2e8fa88eSMichal Orzel std::string endpoint("truststore"); 17806ec13c8fSNan Zhou std::string verifyUnit(ManagerInTest::unitToRestartInTest); 1781e3d47cd4SNan Zhou CertificateType type = CertificateType::authority; 17826ec13c8fSNan Zhou 17836ec13c8fSNan Zhou std::string object = std::string(objectNamePrefix) + '/' + 17846ec13c8fSNan Zhou certificateTypeToString(type) + '/' + endpoint; 17856ec13c8fSNan Zhou 17866ec13c8fSNan Zhou auto event = sdeventplus::Event::get_default(); 17876ec13c8fSNan Zhou // Attach the bus to sd_event to service user requests 17886ec13c8fSNan Zhou bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 17896ec13c8fSNan Zhou ManagerInTest manager(bus, event, object.c_str(), type, verifyUnit, 17906ec13c8fSNan Zhou authoritiesListFolder); 17916ec13c8fSNan Zhou createAuthoritiesList(maxNumAuthorityCertificates + 1); 17926ec13c8fSNan Zhou EXPECT_THROW(manager.installAll(sourceAuthoritiesListFile), 17936ec13c8fSNan Zhou sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed); 17946ec13c8fSNan Zhou } 17956ec13c8fSNan Zhou 17966ec13c8fSNan Zhou TEST_F(AuthoritiesListTest, CertInWrongFormat) 17976ec13c8fSNan Zhou { 1798*2e8fa88eSMichal Orzel std::string endpoint("truststore"); 17996ec13c8fSNan Zhou std::string verifyUnit(ManagerInTest::unitToRestartInTest); 1800e3d47cd4SNan Zhou CertificateType type = CertificateType::authority; 18016ec13c8fSNan Zhou 18026ec13c8fSNan Zhou std::string object = std::string(objectNamePrefix) + '/' + 18036ec13c8fSNan Zhou certificateTypeToString(type) + '/' + endpoint; 18046ec13c8fSNan Zhou 18056ec13c8fSNan Zhou auto event = sdeventplus::Event::get_default(); 18066ec13c8fSNan Zhou // Attach the bus to sd_event to service user requests 18076ec13c8fSNan Zhou bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 18086ec13c8fSNan Zhou 18096ec13c8fSNan Zhou ManagerInTest manager(bus, event, object.c_str(), type, verifyUnit, 18106ec13c8fSNan Zhou authoritiesListFolder); 18116ec13c8fSNan Zhou 18126ec13c8fSNan Zhou // Replace the authorities list with non-valid PEM encoded x509 certificate 18136ec13c8fSNan Zhou setContentFromString(sourceAuthoritiesListFile, "blah-blah"); 18146ec13c8fSNan Zhou EXPECT_THROW(manager.installAll(sourceAuthoritiesListFile), 18156ec13c8fSNan Zhou InvalidCertificate); 18166ec13c8fSNan Zhou setContentFromString(sourceAuthoritiesListFile, 18176ec13c8fSNan Zhou "-----BEGIN CERTIFICATE-----"); 18186ec13c8fSNan Zhou EXPECT_THROW(manager.installAll(sourceAuthoritiesListFile), 18196ec13c8fSNan Zhou InvalidCertificate); 18206ec13c8fSNan Zhou } 18216ec13c8fSNan Zhou 18226ec13c8fSNan Zhou TEST_F(AuthoritiesListTest, ReplaceAll) 18236ec13c8fSNan Zhou { 1824*2e8fa88eSMichal Orzel std::string endpoint("truststore"); 18256ec13c8fSNan Zhou std::string verifyUnit(ManagerInTest::unitToRestartInTest); 1826e3d47cd4SNan Zhou CertificateType type = CertificateType::authority; 18276ec13c8fSNan Zhou 18286ec13c8fSNan Zhou std::string object = std::string(objectNamePrefix) + '/' + 18296ec13c8fSNan Zhou certificateTypeToString(type) + '/' + endpoint; 18306ec13c8fSNan Zhou 18316ec13c8fSNan Zhou auto event = sdeventplus::Event::get_default(); 18326ec13c8fSNan Zhou // Attach the bus to sd_event to service user requests 18336ec13c8fSNan Zhou bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 18346ec13c8fSNan Zhou ManagerInTest manager(bus, event, object.c_str(), type, verifyUnit, 18356ec13c8fSNan Zhou authoritiesListFolder); 18366ec13c8fSNan Zhou EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest))) 18376ec13c8fSNan Zhou .WillOnce(Return()) 18386ec13c8fSNan Zhou .WillOnce(Return()); 18396ec13c8fSNan Zhou manager.installAll(sourceAuthoritiesListFile); 18406ec13c8fSNan Zhou 18416ec13c8fSNan Zhou // Replace the current list with a different list 18426ec13c8fSNan Zhou fs::remove_all(sourceAuthoritiesListFile.parent_path()); 18436ec13c8fSNan Zhou createAuthoritiesList(maxNumAuthorityCertificates); 18446ec13c8fSNan Zhou std::vector<sdbusplus::message::object_path> objects = 18456ec13c8fSNan Zhou manager.replaceAll(sourceAuthoritiesListFile); 18466ec13c8fSNan Zhou 18476ec13c8fSNan Zhou for (size_t i = 0; i < manager.getCertificates().size(); ++i) 18486ec13c8fSNan Zhou { 18496ec13c8fSNan Zhou EXPECT_EQ(manager.getCertificates()[i]->getObjectPath(), objects[i]); 18506ec13c8fSNan Zhou } 18516ec13c8fSNan Zhou verifyCertificates(manager.getCertificates()); 18526ec13c8fSNan Zhou } 18536ec13c8fSNan Zhou 1854e1289adfSNan Zhou } // namespace 1855e1289adfSNan Zhou } // namespace phosphor::certs 1856