diff --git a/doc/06-distributed-monitoring.md b/doc/06-distributed-monitoring.md
index dca0aea95..41e0468fd 100644
--- a/doc/06-distributed-monitoring.md
+++ b/doc/06-distributed-monitoring.md
@@ -451,6 +451,14 @@ 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.
+```
+
## Client/Satellite Setup
This section describes the setup of a satellite and/or client connected to an
diff --git a/doc/11-cli-commands.md b/doc/11-cli-commands.md
index dff5bc390..f9197f0ee 100644
--- a/doc/11-cli-commands.md
+++ b/doc/11-cli-commands.md
@@ -21,6 +21,7 @@ Usage:
Supported commands:
* api setup (setup for API)
* ca list (lists all certificate signing requests)
+ * ca remove (removes an outstanding certificate request)
* ca sign (signs an outstanding certificate request)
* console (Icinga debug console)
* daemon (starts Icinga 2)
diff --git a/lib/cli/CMakeLists.txt b/lib/cli/CMakeLists.txt
index 7a5e91887..980429171 100644
--- a/lib/cli/CMakeLists.txt
+++ b/lib/cli/CMakeLists.txt
@@ -5,6 +5,7 @@ set(cli_SOURCES
apisetupcommand.cpp apisetupcommand.hpp
apisetuputility.cpp apisetuputility.hpp
calistcommand.cpp calistcommand.hpp
+ caremovecommand.cpp caremovecommand.hpp
casigncommand.cpp casigncommand.hpp
clicommand.cpp clicommand.hpp
consolecommand.cpp consolecommand.hpp
diff --git a/lib/cli/caremovecommand.cpp b/lib/cli/caremovecommand.cpp
new file mode 100644
index 000000000..ab6e0f811
--- /dev/null
+++ b/lib/cli/caremovecommand.cpp
@@ -0,0 +1,72 @@
+/******************************************************************************
+ * Icinga 2 *
+ * Copyright (C) 2012-2018 Icinga Development Team (https://www.icinga.com/) *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License *
+ * as published by the Free Software Foundation; either version 2 *
+ * of the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the Free Software Foundation *
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ******************************************************************************/
+
+#include "cli/caremovecommand.hpp"
+#include "remote/apilistener.hpp"
+#include "base/logger.hpp"
+#include "base/application.hpp"
+#include "base/tlsutility.hpp"
+
+using namespace icinga;
+
+REGISTER_CLICOMMAND("ca/remove", CARemoveCommand);
+
+String CARemoveCommand::GetDescription() const
+{
+ return "Removes an outstanding certificate request.";
+}
+
+String CARemoveCommand::GetShortDescription() const
+{
+ return "removes an outstanding certificate request";
+}
+
+int CARemoveCommand::GetMinArguments() const
+{
+ return 1;
+}
+
+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& ap) const
+{
+ String requestFile = ApiListener::GetCertificateRequestsDir() + "/" + ap[0] + ".json";
+
+ if (!Utility::PathExists(requestFile)) {
+ Log(LogCritical, "cli")
+ << "No request exists for fingerprint '" << ap[0] << "'.";
+ return 1;
+ }
+
+ if(remove(requestFile.CStr()) != 0)
+ return 1;
+
+ Log(LogInformation, "cli")
+ << "Certificate " << ap[0] << " removed.";
+
+ return 0;
+}
diff --git a/lib/cli/caremovecommand.hpp b/lib/cli/caremovecommand.hpp
new file mode 100644
index 000000000..fabfd6974
--- /dev/null
+++ b/lib/cli/caremovecommand.hpp
@@ -0,0 +1,47 @@
+/******************************************************************************
+ * Icinga 2 *
+ * Copyright (C) 2012-2018 Icinga Development Team (https://www.icinga.com/) *
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License *
+ * as published by the Free Software Foundation; either version 2 *
+ * of the License, or (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the Free Software Foundation *
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ******************************************************************************/
+
+#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& ap) const override;
+};
+
+}
+
+#endif /* CASIGNCOMMAND_H */