]> granicus.if.org Git - icinga2/commitdiff
API: Implement 'generate-ticket' action and update distributed monitoring docs
authorMichael Friedrich <michael.friedrich@netways.de>
Mon, 15 Aug 2016 12:32:41 +0000 (14:32 +0200)
committerMichael Friedrich <michael.friedrich@netways.de>
Mon, 15 Aug 2016 13:19:28 +0000 (15:19 +0200)
fixes #12433

doc/12-icinga2-api.md
doc/6-distributed-monitoring.md
lib/icinga/apiactions.cpp
lib/icinga/apiactions.hpp

index 41650171e12d3667ea2c131dd68f8edc3b9099e2..24168a3da24ffa89dea04a9f5caf0c40988c98d7 100644 (file)
@@ -1105,6 +1105,31 @@ Example:
         ]
     }
 
+### <a id="icinga2-api-actions-generate-ticket"></a> generate-ticket
+
+Generates a PKI ticket for [CSR auto-signing](6-distributed-monitoring.md#distributed-monitoring-setup-csr-auto-signing).
+This can be used in combination with satellite/client setups requesting this ticket number.
+
+Send a `POST` request to the URL endpoint `/v1/actions/generate-ticket`.
+
+  Parameter     | Type      | Description
+  --------------|-----------|--------------
+  cn            | string    | **Required.** The host's common name for which the ticket should be geenerated.
+
+Example:
+
+    $ curl -k -s -u root:icinga -H 'Accept: application/json' -X POST 'https://localhost:5665/v1/actions/generate-ticket' \
+    -d '{ "cn": "icinga2-client1.localdomain" }' | python -m json.tool
+    {
+        "results": [
+            {
+                "code": 200.0,
+                "status": "Generated PKI ticket '4f75d2ecd253575fe9180938ebff7cbca262f96e' for common name 'icinga2-client1.localdomain'.",
+                "ticket": "4f75d2ecd253575fe9180938ebff7cbca262f96e"
+            }
+        ]
+    }
+
 
 ## <a id="icinga2-api-event-streams"></a> Event Streams
 
index 8d95ba6ff4688aa98308dda401dfe985b9df4e85..e43b3ed12b70eea29f69002a74985465aa9bc8fc 100644 (file)
@@ -215,11 +215,21 @@ existing master node setup. If you haven't done so already please [run the maste
 
 Icinga 2 on the master node must be running and accepting connections on port `5665`.
 
+### <a id="distributed-monitoring-setup-csr-auto-signing"></a> CSR Auto-Signing
+
 The `node wizard` cli command will setup a satellite/client using CSR auto-signing. This
 involves that the setup wizard sends a certificate signing request (CSR) to the
 master node.
 There is a security mechanism in place which requires the client to send in a valid
-ticket for CSR auto-signing. This ticket must be generated on the master beforehand.
+ticket for CSR auto-signing.
+
+This ticket must be generated beforehand. The `ticket_salt` attribute for the [ApiListener](9-object-types.md#objecttype-apilistener)
+must be properly configured in order to make this work.
+
+There are two possible ways to retrieve the ticket:
+
+* [CLI command](11-cli-commands.md#cli-command-pki) executed on the master node
+* [REST API](12-icinga2-api.md#icinga2-api) request against the master node
 
 Required information:
 
@@ -231,7 +241,23 @@ Example for the client `icinga2-client1.localdomain` generating a ticket on the
 `icinga2-master1.localdomain`:
 
     [root@icinga2-master1.localdomain /]# icinga2 pki ticket --cn icinga2-client1.localdomain
-    4f75d2ecd253575fe9180938ebff7cbca262f96e
+
+Querying the [Icinga 2 API](12-icinga2-api.md#icinga2-api) on the master requires an [ApiUser](12-icinga2-api.md#icinga2-api-authentication)
+object with at least the `actions/generate-ticket`.
+
+    [root@icinga2-master1.localdomain /]# vim /etc/icinga2/conf.d/api-users.conf
+
+    object ApiUser "client-pki-ticket" {
+      password = "bea11beb7b810ea9ce6ea" //change this
+      permissions = [ "actions/generate-ticket" ]
+    }
+
+    [root@icinga2-master1.localdomain /]# systemctl restart icinga2
+
+Retrieve the ticket on the client node `icinga2-client1.localdomain` with curl for example:
+
+     [root@icinga2-client1.localdomain /]# curl -k -s -u client-pki-ticket:bea11beb7b810ea9ce6ea -H 'Accept: application/json' \
+     -X POST 'https://icinga2-master1.localdomain:5665/v1/actions/generate-ticket' -d '{ "cn": "icinga2-client1.localdomain" }'
 
 Store that ticket number for the satellite/client setup below.
 
@@ -251,7 +277,7 @@ Required information:
   Add more master endpoints | **Optional.** If you have multiple master nodes configured, add them here.
   Master connection for CSR auto-signing | **Required.** The master node's IP address or FQDN and port where the client should request a certificate from. Defaults to the master endpoint host.
   Certificate information | **Required.** Verify that the connecting host really is the requested master node.
-  Request ticket      | **Required.** Paste the previously generated ticket number from the master node here.
+  Request ticket      | **Required.** Paste the previously generated [ticket number](6-distributed-monitoring.md#distributed-monitoring-setup-csr-auto-signing).
   API bind host       | **Optional.** Allows to specify the address where the ApiListener is bound to. For advanced usage only.
   API bind port       | **Optional.** Allows to specify the port where the ApiListener is bound to. For advanced usage only (requires changing the default port 5665 everywhere).
   Accept config       | **Optional.** Whether this node accepts configuration sync from the master node (required for [config sync mode](6-distributed-monitoring.md#distributed-monitoring-top-down-config-sync). Defaults to 'n'.
@@ -1605,7 +1631,7 @@ Add the disk check using command endpoint checks (details in the
 
 ### <a id="distributed-monitoring-windows-nscp"></a> Windows Client and NSClient++
 
-The [Windows setup](#distributed-monitoring-setup-client-windows) already allows
+The [Windows setup](6-distributed-monitoring.md#distributed-monitoring-setup-client-windows) already allows
 you to install the NSClient++ package. In addition to the Windows plugins you can
 also use the [nscp-local commands](10-icinga-template-library.md#nscp-plugin-check-commands)
 provided by the Icinga Template Library (ITL).
@@ -1805,7 +1831,7 @@ Required information:
 * The client common name (CN). Use the FQDN, e.g. `icinga2-node2.localdomain`.
 * The master host and zone name. Pass that to `pki save-cert` as `--host` parameter for example.
  * Optional: Master endpoint host and port information for the `--endpoint` parameter.
-* The client ticket number generated on the master (`icinga2 pki ticket --cn icinga2-node2.localdomain`)
+* The client [ticket number](6-distributed-monitoring.md#distributed-monitoring-setup-csr-auto-signing)
 
 Generate a new local self-signed certificate.
 
index 7181b27b4785efcbd1d2f93b0dcfb1d01a03639b..69d687c3fc4c7dd2dc7dfc7c2da8a3a0d7135ccc 100644 (file)
@@ -26,6 +26,7 @@
 #include "icinga/eventcommand.hpp"
 #include "icinga/notificationcommand.hpp"
 #include "remote/apiaction.hpp"
+#include "remote/apilistener.hpp"
 #include "remote/httputility.hpp"
 #include "base/utility.hpp"
 #include "base/convert.hpp"
@@ -45,6 +46,7 @@ REGISTER_APIACTION(schedule_downtime, "Service;Host", &ApiActions::ScheduleDownt
 REGISTER_APIACTION(remove_downtime, "Service;Host;Downtime", &ApiActions::RemoveDowntime);
 REGISTER_APIACTION(shutdown_process, "", &ApiActions::ShutdownProcess);
 REGISTER_APIACTION(restart_process, "", &ApiActions::RestartProcess);
+REGISTER_APIACTION(generate_ticket, "", &ApiActions::GenerateTicket);
 
 Dictionary::Ptr ApiActions::CreateResult(int code, const String& status,
     const Dictionary::Ptr& additional)
@@ -372,3 +374,25 @@ Dictionary::Ptr ApiActions::RestartProcess(const ConfigObject::Ptr& object,
        return ApiActions::CreateResult(200, "Restarting Icinga 2.");
 }
 
+Dictionary::Ptr ApiActions::GenerateTicket(const ConfigObject::Ptr&,
+    const Dictionary::Ptr& params)
+{
+       if (!params->Contains("cn"))
+               return ApiActions::CreateResult(404, "Option 'cn' is required");
+
+       String cn = HttpUtility::GetLastParameter(params, "cn");
+
+       ApiListener::Ptr listener = ApiListener::GetInstance();
+       String salt = listener->GetTicketSalt();
+
+       if (salt.IsEmpty())
+               return ApiActions::CreateResult(500, "Ticket salt is not configured in ApiListener object");
+
+       String ticket = PBKDF2_SHA1(cn, salt, 50000);
+
+       Dictionary::Ptr additional = new Dictionary();
+       additional->Set("ticket", ticket);
+
+       return ApiActions::CreateResult(200, "Generated PKI ticket '" + ticket + "' for common name '"
+           + cn + "'.", additional);
+}
index 26cee5cbbff88b25126baae756563c20c770ca65..34694641f3bcd5b099434c30b2c7b48d8ab7030c 100644 (file)
@@ -45,6 +45,7 @@ public:
        static Dictionary::Ptr RemoveDowntime(const ConfigObject::Ptr& object, const Dictionary::Ptr& params);
        static Dictionary::Ptr ShutdownProcess(const ConfigObject::Ptr& object, const Dictionary::Ptr& params);
        static Dictionary::Ptr RestartProcess(const ConfigObject::Ptr& object, const Dictionary::Ptr& params);
+       static Dictionary::Ptr GenerateTicket(const ConfigObject::Ptr& object, const Dictionary::Ptr& params);
 
 private:
        static Dictionary::Ptr CreateResult(int code, const String& status, const Dictionary::Ptr& additional = Dictionary::Ptr());