Skip to content
Permalink
Browse files

Merge pull request #6500 from ajaffie/feature/cli-ca-remove-6049

Implemented `ca remove` cli command + documentation.
  • Loading branch information...
dnsmichi committed Jun 7, 2019
2 parents 1997878 + 3554579 commit ee4c5c5c2b6e72e7ce4fe7d43d758daa46cd56f5
@@ -451,6 +451,16 @@ information/cli: Signed certificate for 'CN = icinga2-client2.localdomain'.
> `ca list` cannot be used as historical inventory. Certificate
> signing requests older than 1 week are automatically deleted.
You can also remove an undesired CSR using the `ca remove` command using the
syntax as the `ca sign` command.

```
[root@pym ~]# icinga2 ca remove 5c31ca0e2269c10363a97e40e3f2b2cd56493f9194d5b1852541b835970da46e
information/cli: Certificate 5c31ca0e2269c10363a97e40e3f2b2cd56493f9194d5b1852541b835970da46e removed.
```
If you want to restore a certificate you have removed, you can use `ca restore`.


## Client/Satellite Setup <a id="distributed-monitoring-setup-satellite-client"></a>

This section describes the setup of a satellite and/or client connected to an
@@ -21,6 +21,8 @@ Usage:
Supported commands:
* api setup (setup for API)
* ca list (lists all certificate signing requests)
* ca restore (restores a removed certificate request)
* ca remove (removes an outstanding certificate request)
* ca sign (signs an outstanding certificate request)
* console (Icinga debug console)
* daemon (starts Icinga 2)
@@ -185,6 +187,8 @@ Usage:
Supported commands:
* ca list (lists all certificate signing requests)
* ca sign (signs an outstanding certificate request)
* ca restore (restores a removed certificate request)
* ca remove (removes an outstanding certificate request)
Global options:
-h [ --help ] show this help message
@@ -232,6 +236,7 @@ Command options:
--all List all certificate signing requests, including
signed. Note: Old requests are automatically
cleaned by Icinga after 1 week.
--removed List all removed CSRs (for use with 'ca restore')
--json encode output as JSON
Report bugs at <https://github.com/Icinga/icinga2>
@@ -164,6 +164,16 @@ or with sudo.
You can use the new `--all` parameter to show all signing requests.
Note that Icinga automatically purges signed requests older than 1 week.

#### New: CA Remove/Restore <a id="upgrading-to-2-11-cli-commands-ca-remove-restore></a>

`ca remove` allows you to remove pending signing requests. Once the
master receives a CSR, and it is marked as removed, the request is
denied.

`ca restore` allows you to restore a removed signing request. You
can list removed signing requests with the new `--removed` parameter
for `ca list`.

### Configuration <a id="upgrading-to-2-11-configuration"></a>

The deprecated `concurrent_checks` attribute in the [checker feature](09-object-types.md#objecttype-checkercomponent)
@@ -5,6 +5,8 @@ set(cli_SOURCES
apisetupcommand.cpp apisetupcommand.hpp
apisetuputility.cpp apisetuputility.hpp
calistcommand.cpp calistcommand.hpp
caremovecommand.cpp caremovecommand.hpp
carestorecommand.cpp carestorecommand.hpp
casigncommand.cpp casigncommand.hpp
clicommand.cpp clicommand.hpp
consolecommand.cpp consolecommand.hpp
@@ -14,32 +14,49 @@ namespace po = boost::program_options;

REGISTER_CLICOMMAND("ca/list", CAListCommand);

/**
* Provide a long CLI description sentence.
*
* @return text
*/
String CAListCommand::GetDescription() const
{
return "Lists pending certificate signing requests.";
}

/**
* Provide a short CLI description.
*
* @return text
*/
String CAListCommand::GetShortDescription() const
{
return "lists pending certificate signing requests";
}

/**
* Initialize available CLI parameters.
*
* @param visibleDesc Register visible parameters.
* @param hiddenDesc Register hidden parameters.
*/
void CAListCommand::InitParameters(boost::program_options::options_description& visibleDesc,
boost::program_options::options_description& hiddenDesc) const
{
visibleDesc.add_options()
("all", "List all certificate signing requests, including signed. Note: Old requests are automatically cleaned by Icinga after 1 week.")
("removed", "List all removed CSRs (for use with 'ca restore')")
("json", "encode output as JSON");
}

/**
* The entry point for the "ca list" CLI command.
*
* @returns An exit status.
* @return An exit status.
*/
int CAListCommand::Run(const boost::program_options::variables_map& vm, const std::vector<std::string>& ap) const
{
Dictionary::Ptr requests = PkiUtility::GetCertificateRequests();
Dictionary::Ptr requests = PkiUtility::GetCertificateRequests(vm.count("removed"));

if (vm.count("json"))
std::cout << JsonEncode(requests);
@@ -0,0 +1,93 @@
/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */

#include "cli/caremovecommand.hpp"
#include "base/logger.hpp"
#include "base/application.hpp"
#include "base/tlsutility.hpp"
#include "remote/apilistener.hpp"

using namespace icinga;

REGISTER_CLICOMMAND("ca/remove", CARemoveCommand);

/**
* Provide a long CLI description sentence.
*
* @return text
*/
String CARemoveCommand::GetDescription() const
{
return "Removes an outstanding certificate request.";
}

/**
* Provide a short CLI description.
*
* @return text
*/
String CARemoveCommand::GetShortDescription() const
{
return "removes an outstanding certificate request";
}

/**
* Define minimum arguments without key parameter.
*
* @return number of arguments
*/
int CARemoveCommand::GetMinArguments() const
{
return 1;
}

/**
* Impersonate as Icinga user.
*
* @return impersonate level
*/
ImpersonationLevel CARemoveCommand::GetImpersonationLevel() const
{
return ImpersonateIcinga;
}

/**
* The entry point for the "ca remove" CLI command.
*
* @returns An exit status.
*/
int CARemoveCommand::Run(const boost::program_options::variables_map& vm, const std::vector<std::string>& ap) const
{
String fingerPrint = ap[0];
String requestFile = ApiListener::GetCertificateRequestsDir() + "/" + fingerPrint + ".json";

if (!Utility::PathExists(requestFile)) {
Log(LogCritical, "cli")
<< "No request exists for fingerprint '" << fingerPrint << "'.";
return 1;
}

Dictionary::Ptr request = Utility::LoadJsonFile(requestFile);
std::shared_ptr<X509> certRequest = StringToCertificate(request->Get("cert_request"));

if (!certRequest) {
Log(LogCritical, "cli", "Certificate request is invalid. Could not parse X.509 certificate for the 'cert_request' attribute.");
return 1;
}

String cn = GetCertificateCN(certRequest);

if (request->Contains("cert_response")) {
Log(LogCritical, "cli")
<< "Certificate request for CN '" << cn << "' already signed, removal is not possible.";
return 1;
}

Utility::SaveJsonFile(ApiListener::GetCertificateRequestsDir() + "/" + fingerPrint + ".removed", 0600, request);

Utility::Remove(requestFile);

Log(LogInformation, "cli")
<< "Certificate request for CN " << cn << " removed.";

return 0;
}
@@ -0,0 +1,30 @@
/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */

#ifndef CAREMOVECOMMAND_H
#define CAREMOVECOMMAND_H

#include "cli/clicommand.hpp"

namespace icinga
{

/**
* The "ca remove" command.
*
* @ingroup cli
*/
class CARemoveCommand final : public CLICommand
{
public:
DECLARE_PTR_TYPEDEFS(CARemoveCommand);

String GetDescription() const override;
String GetShortDescription() const override;
int GetMinArguments() const override;
ImpersonationLevel GetImpersonationLevel() const override;
int Run(const boost::program_options::variables_map& vm, const std::vector<std::string>& ap) const override;
};

}

#endif /* CAREMOVECOMMAND_H */
@@ -0,0 +1,88 @@
/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */

#include "cli/carestorecommand.hpp"
#include "base/logger.hpp"
#include "base/application.hpp"
#include "base/tlsutility.hpp"
#include "remote/apilistener.hpp"

using namespace icinga;

REGISTER_CLICOMMAND("ca/restore", CARestoreCommand);

/**
* Provide a long CLI description sentence.
*
* @return text
*/
String CARestoreCommand::GetDescription() const
{
return "Restores a previously removed certificate request.";
}

/**
* Provide a short CLI description.
*
* @return text
*/
String CARestoreCommand::GetShortDescription() const
{
return "restores a removed certificate request";
}

/**
* Define minimum arguments without key parameter.
*
* @return number of arguments
*/
int CARestoreCommand::GetMinArguments() const
{
return 1;
}

/**
* Impersonate as Icinga user.
*
* @return impersonate level
*/
ImpersonationLevel CARestoreCommand::GetImpersonationLevel() const
{
return ImpersonateIcinga;
}

/**
* The entry point for the "ca restore" CLI command.
*
* @returns An exit status.
*/
int CARestoreCommand::Run(const boost::program_options::variables_map& vm, const std::vector<std::string>& ap) const
{
String fingerPrint = ap[0];
String removedRequestFile = ApiListener::GetCertificateRequestsDir() + "/" + fingerPrint + ".removed";

if (!Utility::PathExists(removedRequestFile)) {
Log(LogCritical, "cli")
<< "Cannot find removed fingerprint '" << fingerPrint << "', bailing out.";
return 1;
}

Dictionary::Ptr request = Utility::LoadJsonFile(removedRequestFile);
std::shared_ptr<X509> certRequest = StringToCertificate(request->Get("cert_request"));

if (!certRequest) {
Log(LogCritical, "cli", "Certificate request is invalid. Could not parse X.509 certificate for the 'cert_request' attribute.");
/* Purge the file when we know that it is broken. */
Utility::Remove(removedRequestFile);
return 1;
}

Utility::SaveJsonFile(ApiListener::GetCertificateRequestsDir() + "/" + fingerPrint + ".json", 0600, request);

Utility::Remove(removedRequestFile);

Log(LogInformation, "cli")
<< "Restored certificate request for CN '" << GetCertificateCN(certRequest) << "', sign it with:\n"
<< "\"icinga2 ca sign " << fingerPrint << "\"";

return 0;
}
@@ -0,0 +1,30 @@
/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */

#ifndef CARESTORECOMMAND_H
#define CARESTORECOMMAND_H

#include "cli/clicommand.hpp"

namespace icinga
{

/**
* The "ca restore" command.
*
* @ingroup cli
*/
class CARestoreCommand final : public CLICommand
{
public:
DECLARE_PTR_TYPEDEFS(CARestoreCommand);

String GetDescription() const override;
String GetShortDescription() const override;
int GetMinArguments() const override;
ImpersonationLevel GetImpersonationLevel() const override;
int Run(const boost::program_options::variables_map& vm, const std::vector<std::string>& ap) const override;
};

}

#endif /* CASTORECOMMAND_H */

0 comments on commit ee4c5c5

Please sign in to comment.
You can’t perform that action at this time.