Add support to upload CA certificate
Added support to upload CA certificates in
/etc/ssl/certs path. Curently scope is limited to one
certificate and any new upload is going to override the
existing CA certificate.
Change-Id: I9cc60accf6aae4d8123e5f86d618effe33d68d53
Signed-off-by: Jayanth Othayoth <ojayanth@in.ibm.com>
diff --git a/argument.cpp b/argument.cpp
index a5402e6..38d3978 100644
--- a/argument.cpp
+++ b/argument.cpp
@@ -69,7 +69,7 @@
std::cerr << "Options:\n";
std::cerr << " --help Print this menu\n";
std::cerr << " --type certificate type\n";
- std::cerr << " Valid types: Client,Server\n";
+ std::cerr << " Valid types: client,server,authority\n";
std::cerr << " --endpoint d-bus endpoint\n";
std::cerr << " --path certificate file path\n";
std::cerr << " --unit=<name> Optional systemd unit need to reload\n";
diff --git a/certs_manager.cpp b/certs_manager.cpp
index d8c6263..8f36782 100644
--- a/certs_manager.cpp
+++ b/certs_manager.cpp
@@ -59,16 +59,6 @@
elog<InvalidCertificate>(Reason("Certificate validation failed"));
}
- // Compare the Keys
- if (!compareKeys(path))
- {
- elog<InvalidCertificate>(
- Reason("Private key is not matching with Certificate"));
- }
-
- // Copy the certificate file
- copy(path, certPath);
-
// Invoke type specific install function.
auto iter = typeFuncMap.find(type);
if (iter == typeFuncMap.end())
@@ -76,25 +66,40 @@
log<level::ERR>("Unsupported Type", entry("TYPE=%s", type.c_str()));
elog<InternalFailure>();
}
- iter->second();
-}
+ iter->second(path);
-void Manager::serverInstall()
-{
+ // Copy the certificate file
+ copy(path, certPath);
+
if (!unit.empty())
{
reloadOrReset(unit);
}
}
-void Manager::clientInstall()
+void Manager::serverInstallHelper(const std::string& filePath)
{
- if (!unit.empty())
+ if (!compareKeys(filePath))
{
- reloadOrReset(unit);
+ elog<InvalidCertificate>(
+ Reason("Private key does not match the Certificate"));
}
}
+void Manager::clientInstallHelper(const std::string& filePath)
+{
+ if (!compareKeys(filePath))
+ {
+ elog<InvalidCertificate>(
+ Reason("Private key does not match the Certificate"));
+ }
+}
+
+void Manager::authorityInstallHelper(const std::string& filePath)
+{
+ // No additional steps required now.
+}
+
void Manager::reloadOrReset(const std::string& unit)
{
constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1";
diff --git a/certs_manager.hpp b/certs_manager.hpp
index 8601c64..1ca4f1a 100644
--- a/certs_manager.hpp
+++ b/certs_manager.hpp
@@ -18,13 +18,17 @@
// Supported Types.
static constexpr auto SERVER = "server";
static constexpr auto CLIENT = "client";
+static constexpr auto AUTHORITY = "authority";
using Create = sdbusplus::xyz::openbmc_project::Certs::server::Install;
using Delete = sdbusplus::xyz::openbmc_project::Object::server::Delete;
using Ifaces = sdbusplus::server::object::object<Create, Delete>;
-using InstallFunc = std::function<void()>;
+using InstallFunc = std::function<void(const std::string&)>;
using InputType = std::string;
+// for placeholders
+using namespace std::placeholders;
+
class Manager : public Ifaces
{
public:
@@ -59,9 +63,11 @@
certPath(std::move(certPath))
{
typeFuncMap[SERVER] =
- std::bind(&phosphor::certs::Manager::serverInstall, this);
+ std::bind(&phosphor::certs::Manager::serverInstallHelper, this, _1);
typeFuncMap[CLIENT] =
- std::bind(&phosphor::certs::Manager::clientInstall, this);
+ std::bind(&phosphor::certs::Manager::clientInstallHelper, this, _1);
+ typeFuncMap[AUTHORITY] = std::bind(
+ &phosphor::certs::Manager::authorityInstallHelper, this, _1);
}
/** @brief Implementation for Install
@@ -78,11 +84,20 @@
void delete_() override;
private:
- /** @brief Client certificate Installation helper function **/
- virtual void clientInstall();
+ /** @brief Client certificate Installation helper function
+ * @param[in] path - Certificate key file path.
+ */
+ virtual void clientInstallHelper(const std::string& filePath);
- /** @brief Server certificate Installation helper function **/
- virtual void serverInstall();
+ /** @brief Server certificate Installation helper function
+ * @param[in] path - Certificate key file path.
+ */
+ virtual void serverInstallHelper(const std::string& filePath);
+
+ /** @brief Authority certificate Installation helper function
+ * @param[in] path - Certificate key file path.
+ */
+ virtual void authorityInstallHelper(const std::string& filePath);
/** @brief systemd unit reload or reset helper function
* Reload if the unit supports it and use a restart otherwise.
diff --git a/mainapp.cpp b/mainapp.cpp
index 5b0f29f..3f97025 100644
--- a/mainapp.cpp
+++ b/mainapp.cpp
@@ -45,7 +45,8 @@
auto type = std::move((options)["type"]);
if ((type == phosphor::certs::util::ArgumentParser::empty_string) ||
!((type == phosphor::certs::SERVER) ||
- (type == phosphor::certs::CLIENT)))
+ (type == phosphor::certs::CLIENT) ||
+ (type == phosphor::certs::AUTHORITY)))
{
ExitWithError("type not specified or invalid.", argv);
}
diff --git a/test/certs_manager_test.cpp b/test/certs_manager_test.cpp
index f1a7587..c381cec 100644
--- a/test/certs_manager_test.cpp
+++ b/test/certs_manager_test.cpp
@@ -117,8 +117,7 @@
{
}
- MOCK_METHOD0(clientInstall, void());
- MOCK_METHOD0(serverInstall, void());
+ MOCK_METHOD1(reloadOrReset, void(const std::string& unit));
};
/** @brief Check if server install routine is invoked for server setup
@@ -130,10 +129,11 @@
std::string type("server");
std::string path(certDir + "/" + certificateFile);
std::string verifyPath(path);
+ std::string verifyUnit(unit);
auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
MockCertManager manager(bus, objPath.c_str(), type, std::move(unit),
std::move(path));
- EXPECT_CALL(manager, serverInstall()).Times(1);
+ EXPECT_CALL(manager, reloadOrReset(verifyUnit)).Times(1);
MainApp mainApp(&manager);
EXPECT_NO_THROW({ mainApp.install(certificateFile); });
@@ -149,10 +149,31 @@
std::string type("client");
std::string path(certDir + "/" + certificateFile);
std::string verifyPath(path);
+ std::string verifyUnit(unit);
auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
MockCertManager manager(bus, objPath.c_str(), type, std::move(unit),
std::move(path));
- EXPECT_CALL(manager, clientInstall()).Times(1);
+ EXPECT_CALL(manager, reloadOrReset(verifyUnit)).Times(1);
+ MainApp mainApp(&manager);
+ EXPECT_NO_THROW({ mainApp.install(certificateFile); });
+ EXPECT_TRUE(fs::exists(verifyPath));
+}
+
+/** @brief Check if authority install routine is invoked for authority setup
+ */
+TEST_F(TestCertsManager, InvokeAuthorityInstall)
+{
+ std::string endpoint("ldap");
+ std::string unit("nslcd.service");
+ std::string type("authority");
+ std::string path(certDir + "/" + certificateFile);
+ std::string verifyPath(path);
+ std::string verifyUnit(unit);
+ auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
+ MockCertManager manager(bus, objPath.c_str(), type, std::move(unit),
+ std::move(path));
+ EXPECT_CALL(manager, reloadOrReset(verifyUnit)).Times(1);
+
MainApp mainApp(&manager);
EXPECT_NO_THROW({ mainApp.install(certificateFile); });
EXPECT_TRUE(fs::exists(verifyPath));
@@ -167,10 +188,11 @@
std::string type("client");
std::string path(certDir + "/" + certificateFile);
std::string verifyPath(path);
+ std::string verifyUnit(unit);
auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
MockCertManager manager(bus, objPath.c_str(), type, std::move(unit),
std::move(path));
- EXPECT_CALL(manager, clientInstall()).Times(1);
+ EXPECT_CALL(manager, reloadOrReset(verifyUnit)).Times(1);
MainApp mainApp(&manager);
EXPECT_NO_THROW({ mainApp.install(certificateFile); });
EXPECT_TRUE(fs::exists(verifyPath));
@@ -186,10 +208,11 @@
std::string type("client");
std::string path(certDir + "/" + certificateFile);
std::string verifyPath(path);
+ std::string verifyUnit(unit);
auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
MockCertManager manager(bus, objPath.c_str(), type, std::move(unit),
std::move(path));
- EXPECT_CALL(manager, clientInstall()).Times(0);
+ EXPECT_CALL(manager, reloadOrReset(verifyUnit)).Times(0);
MainApp mainApp(&manager);
std::string certpath = "nofile.pem";
EXPECT_THROW(
@@ -222,10 +245,11 @@
std::string path(certDir + "/" + emptyFile);
std::string verifyPath(path);
+ std::string verifyUnit(unit);
auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
MockCertManager manager(bus, objPath.c_str(), type, std::move(unit),
std::move(path));
- EXPECT_CALL(manager, clientInstall()).Times(0);
+ EXPECT_CALL(manager, reloadOrReset(verifyUnit)).Times(0);
MainApp mainApp(&manager);
EXPECT_THROW(
{
@@ -260,10 +284,11 @@
std::string path(certDir + "/" + certificateFile);
std::string verifyPath(path);
+ std::string verifyUnit(unit);
auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
MockCertManager manager(bus, objPath.c_str(), type, std::move(unit),
std::move(path));
- EXPECT_CALL(manager, clientInstall()).Times(0);
+ EXPECT_CALL(manager, reloadOrReset(verifyUnit)).Times(0);
MainApp mainApp(&manager);
EXPECT_THROW(
{
@@ -280,24 +305,6 @@
EXPECT_FALSE(fs::exists(verifyPath));
}
-/** @brief Test deletion of installed certificate file
- */
-class MockReloadReset : public phosphor::certs::Manager
-{
- public:
- MockReloadReset(sdbusplus::bus::bus& bus, const char* path,
- std::string& type, std::string&& unit,
- std::string&& certPath) :
- Manager(bus, path, type, std::forward<std::string>(unit),
- std::forward<std::string>(certPath))
- {
- }
- virtual ~MockReloadReset()
- {
- }
-
- MOCK_METHOD1(reloadOrReset, void(const std::string& unit));
-};
TEST_F(TestCertsManager, TestDeleteCertificate)
{
std::string endpoint("ldap");
@@ -307,7 +314,7 @@
std::string verifyPath(path);
std::string verifyUnit(unit);
auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
- MockReloadReset manager(bus, objPath.c_str(), type, std::move(unit),
+ MockCertManager manager(bus, objPath.c_str(), type, std::move(unit),
std::move(path));
EXPECT_CALL(manager, reloadOrReset(verifyUnit)).Times(2);
MainApp mainApp(&manager);
@@ -374,11 +381,11 @@
std::string type("client");
std::string path(certDir + "/" + certificateFile);
std::string verifyPath(path);
-
+ std::string verifyUnit(unit);
auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
MockCertManager manager(bus, objPath.c_str(), type, std::move(unit),
std::move(path));
- EXPECT_CALL(manager, clientInstall()).Times(0);
+ EXPECT_CALL(manager, reloadOrReset(verifyUnit)).Times(0);
MainApp mainApp(&manager);
EXPECT_THROW(
{
@@ -404,11 +411,12 @@
std::string type("client");
std::string path(certDir + "/" + keyFile);
std::string verifyPath(path);
+ std::string verifyUnit(unit);
auto objPath = std::string(OBJPATH) + '/' + type + '/' + endpoint;
MockCertManager manager(bus, objPath.c_str(), type, std::move(unit),
std::move(path));
- EXPECT_CALL(manager, clientInstall()).Times(0);
+ EXPECT_CALL(manager, reloadOrReset(verifyUnit)).Times(0);
MainApp mainApp(&manager);
EXPECT_THROW(
{