2014-10-17 15:13:17 +02:00
/******************************************************************************
* Icinga 2 *
2018-01-02 12:06:00 +01:00
* Copyright ( C ) 2012 - 2018 Icinga Development Team ( https : //www.icinga.com/) *
2014-10-17 15:13:17 +02:00
* *
* 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 . *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2014-10-31 11:38:16 +01:00
# include "cli/nodesetupcommand.hpp"
# include "cli/nodeutility.hpp"
2014-10-21 18:24:35 +02:00
# include "cli/featureutility.hpp"
2015-06-25 11:00:25 +02:00
# include "cli/apisetuputility.hpp"
2017-09-05 14:21:30 +02:00
# include "remote/apilistener.hpp"
2017-09-05 14:44:56 +02:00
# include "remote/pkiutility.hpp"
2014-10-19 14:21:12 +02:00
# include "base/logger.hpp"
2014-10-21 18:24:35 +02:00
# include "base/console.hpp"
2014-10-17 15:13:17 +02:00
# include "base/application.hpp"
2014-10-23 15:05:12 +02:00
# include "base/tlsutility.hpp"
2014-12-14 11:33:45 +01:00
# include "base/scriptglobal.hpp"
2014-12-15 10:16:06 +01:00
# include "base/exception.hpp"
2014-10-17 15:13:17 +02:00
# include <boost/algorithm/string/join.hpp>
# include <boost/algorithm/string/replace.hpp>
2014-10-21 21:33:21 +02:00
2014-10-18 21:06:28 +02:00
# include <iostream>
2014-10-17 15:13:17 +02:00
# include <fstream>
# include <vector>
using namespace icinga ;
namespace po = boost : : program_options ;
2014-10-31 11:38:16 +01:00
REGISTER_CLICOMMAND ( " node/setup " , NodeSetupCommand ) ;
2014-10-17 15:13:17 +02:00
2018-01-04 04:25:35 +01:00
String NodeSetupCommand : : GetDescription ( ) const
2014-10-17 15:13:17 +02:00
{
2014-10-31 11:53:44 +01:00
return " Sets up an Icinga 2 node. " ;
2014-10-17 15:13:17 +02:00
}
2018-01-04 04:25:35 +01:00
String NodeSetupCommand : : GetShortDescription ( ) const
2014-10-17 15:13:17 +02:00
{
2014-10-31 11:53:44 +01:00
return " set up node " ;
2014-10-17 15:13:17 +02:00
}
2014-10-31 11:38:16 +01:00
void NodeSetupCommand : : InitParameters ( boost : : program_options : : options_description & visibleDesc ,
2017-12-19 15:50:05 +01:00
boost : : program_options : : options_description & hiddenDesc ) const
2014-10-17 15:13:17 +02:00
{
visibleDesc . add_options ( )
2014-10-18 21:06:28 +02:00
( " zone " , po : : value < std : : string > ( ) , " The name of the local zone " )
2016-12-06 11:22:24 +01:00
( " master_host " , po : : value < std : : string > ( ) , " The name of the master host for auto-signing the csr; syntax: host[,port] " )
2014-10-23 04:38:54 +02:00
( " endpoint " , po : : value < std : : vector < std : : string > > ( ) , " Connect to remote endpoint; syntax: cn[,host,port] " )
2014-10-18 21:06:28 +02:00
( " listen " , po : : value < std : : string > ( ) , " Listen on host,port " )
2017-10-16 18:38:18 +02:00
( " ticket " , po : : value < std : : string > ( ) , " Generated ticket number for this request (optional) " )
2014-10-18 21:06:28 +02:00
( " trustedcert " , po : : value < std : : string > ( ) , " Trusted master certificate file " )
( " cn " , po : : value < std : : string > ( ) , " The certificate's common name " )
2015-03-27 14:11:21 +01:00
( " accept-config " , " Accept config from master " )
( " accept-commands " , " Accept commands from master " )
2017-11-15 18:42:29 +01:00
( " master " , " Use setup for a master instance " )
2018-02-26 08:34:45 +01:00
( " global_zones " , po : : value < std : : vector < std : : string > > ( ) , " The names of the additional global zones. " ) ;
2015-11-25 18:58:52 +01:00
hiddenDesc . add_options ( )
( " master_zone " , po : : value < std : : string > ( ) , " The name of the master zone " ) ;
2014-10-17 15:13:17 +02:00
}
2014-10-31 11:38:16 +01:00
std : : vector < String > NodeSetupCommand : : GetArgumentSuggestions ( const String & argument , const String & word ) const
2014-10-21 18:24:35 +02:00
{
2014-10-22 15:36:39 +02:00
if ( argument = = " key " | | argument = = " cert " | | argument = = " trustedcert " )
2014-10-21 18:24:35 +02:00
return GetBashCompletionSuggestions ( " file " , word ) ;
else if ( argument = = " host " )
return GetBashCompletionSuggestions ( " hostname " , word ) ;
else if ( argument = = " port " )
return GetBashCompletionSuggestions ( " service " , word ) ;
else
return CLICommand : : GetArgumentSuggestions ( argument , word ) ;
}
2018-01-04 04:25:35 +01:00
ImpersonationLevel NodeSetupCommand : : GetImpersonationLevel ( ) const
2014-10-24 15:29:46 +02:00
{
return ImpersonateRoot ;
}
2014-10-17 15:13:17 +02:00
/**
2014-10-31 11:53:44 +01:00
* The entry point for the " node setup " CLI command .
2014-10-17 15:13:17 +02:00
*
* @ returns An exit status .
*/
2014-10-31 11:38:16 +01:00
int NodeSetupCommand : : Run ( const boost : : program_options : : variables_map & vm , const std : : vector < std : : string > & ap ) const
2014-10-17 15:13:17 +02:00
{
if ( ! ap . empty ( ) ) {
2014-10-19 17:52:17 +02:00
Log ( LogWarning , " cli " )
2017-12-19 15:50:05 +01:00
< < " Ignoring parameters: " < < boost : : algorithm : : join ( ap , " " ) ;
2014-10-17 15:13:17 +02:00
}
2014-10-23 04:23:22 +02:00
if ( vm . count ( " master " ) )
2014-10-21 18:24:35 +02:00
return SetupMaster ( vm , ap ) ;
2014-10-23 04:23:22 +02:00
else
2014-10-31 11:38:16 +01:00
return SetupNode ( vm , ap ) ;
2014-10-17 15:13:17 +02:00
}
2014-10-18 21:06:28 +02:00
2014-10-31 11:38:16 +01:00
int NodeSetupCommand : : SetupMaster ( const boost : : program_options : : variables_map & vm , const std : : vector < std : : string > & ap )
2014-10-18 21:06:28 +02:00
{
2014-10-23 03:35:01 +02:00
/* Ignore not required parameters */
2014-10-22 19:27:21 +02:00
if ( vm . count ( " ticket " ) )
2014-10-31 11:38:16 +01:00
Log ( LogWarning , " cli " , " Master for Node setup: Ignoring --ticket " ) ;
2014-10-23 03:35:01 +02:00
2014-10-22 19:27:21 +02:00
if ( vm . count ( " endpoint " ) )
2014-10-31 11:38:16 +01:00
Log ( LogWarning , " cli " , " Master for Node setup: Ignoring --endpoint " ) ;
2014-10-23 03:35:01 +02:00
2014-10-22 19:27:21 +02:00
if ( vm . count ( " trustedcert " ) )
2014-10-31 11:38:16 +01:00
Log ( LogWarning , " cli " , " Master for Node setup: Ignoring --trustedcert " ) ;
2014-10-22 19:27:21 +02:00
2015-03-27 14:11:21 +01:00
if ( vm . count ( " accept-config " ) )
Log ( LogWarning , " cli " , " Master for Node setup: Ignoring --accept-config " ) ;
if ( vm . count ( " accept-commands " ) )
Log ( LogWarning , " cli " , " Master for Node setup: Ignoring --accept-commands " ) ;
2017-12-19 15:50:05 +01:00
String cn = Utility : : GetFQDN ( ) ;
2014-10-21 21:33:21 +02:00
2017-12-19 15:50:05 +01:00
if ( vm . count ( " cn " ) )
cn = vm [ " cn " ] . as < std : : string > ( ) ;
2014-10-21 18:24:35 +02:00
2015-07-08 15:32:47 +02:00
/* check whether the user wants to generate a new certificate or not */
2017-09-06 17:33:54 +02:00
String existingPath = ApiListener : : GetCertsDir ( ) + " / " + cn + " .crt " ;
2015-07-08 15:32:47 +02:00
Log ( LogInformation , " cli " )
2017-12-19 15:50:05 +01:00
< < " Checking in existing certificates for common name ' " < < cn < < " '... " ;
2015-07-08 15:32:47 +02:00
2017-09-06 17:33:54 +02:00
if ( Utility : : PathExists ( existingPath ) ) {
2015-07-08 15:32:47 +02:00
Log ( LogWarning , " cli " )
2017-12-19 15:50:05 +01:00
< < " Certificate ' " < < existingPath < < " ' for CN ' " < < cn < < " ' already exists. Not generating new certificate. " ;
2015-07-08 15:32:47 +02:00
} else {
Log ( LogInformation , " cli " )
2017-12-19 15:50:05 +01:00
< < " Certificates not yet generated. Running 'api setup' now. " ;
2015-07-08 15:32:47 +02:00
ApiSetupUtility : : SetupMasterCertificates ( cn ) ;
}
Log ( LogInformation , " cli " , " Generating master configuration for Icinga 2. " ) ;
2015-10-22 15:56:27 +02:00
ApiSetupUtility : : SetupMasterApiUser ( ) ;
2015-07-08 15:32:47 +02:00
if ( ! FeatureUtility : : CheckFeatureEnabled ( " api " ) ) {
2015-10-22 15:56:27 +02:00
ApiSetupUtility : : SetupMasterEnableApi ( ) ;
2015-07-08 15:32:47 +02:00
} else {
Log ( LogInformation , " cli " )
2017-12-19 15:50:05 +01:00
< < " 'api' feature already enabled. \n " ;
2015-07-08 15:32:47 +02:00
}
2015-11-25 17:41:03 +01:00
/* write zones.conf and update with zone + endpoint information */
2014-10-22 08:06:06 +02:00
Log ( LogInformation , " cli " , " Generating zone and object configuration. " ) ;
2014-10-21 18:24:35 +02:00
2017-11-15 18:42:29 +01:00
std : : vector < String > globalZones ;
2018-02-26 08:34:45 +01:00
std : : vector < std : : string > setupGlobalZones ;
2017-11-15 18:42:29 +01:00
if ( vm . count ( " global_zones " ) )
2018-02-26 08:34:45 +01:00
setupGlobalZones = vm [ " global_zones " ] . as < std : : vector < std : : string > > ( ) ;
2017-11-15 18:42:29 +01:00
globalZones . push_back ( " global-templates " ) ;
globalZones . push_back ( " director-global " ) ;
for ( int i = 0 ; i < setupGlobalZones . size ( ) ; i + + ) {
if ( std : : find ( globalZones . begin ( ) , globalZones . end ( ) , setupGlobalZones [ i ] ) ! = globalZones . end ( ) ) {
Log ( LogCritical , " cli " )
< < " The global zone ' " < < setupGlobalZones [ i ] < < " ' is already specified. " ;
return 1 ;
}
}
globalZones . insert ( globalZones . end ( ) , setupGlobalZones . begin ( ) , setupGlobalZones . end ( ) ) ;
NodeUtility : : GenerateNodeMasterIcingaConfig ( globalZones ) ;
2014-10-21 16:04:20 +02:00
2015-06-25 11:00:25 +02:00
/* update the ApiListener config - SetupMaster() will always enable it */
2014-10-28 21:13:15 +01:00
Log ( LogInformation , " cli " , " Updating the APIListener feature. " ) ;
2014-10-21 16:04:20 +02:00
2014-10-28 21:13:15 +01:00
String apipath = FeatureUtility : : GetFeaturesAvailablePath ( ) + " /api.conf " ;
2014-10-31 11:38:16 +01:00
NodeUtility : : CreateBackupFile ( apipath ) ;
2014-10-28 21:13:15 +01:00
2016-02-22 16:47:41 +01:00
std : : fstream fp ;
2016-02-24 13:55:25 +01:00
String tempApiPath = Utility : : CreateTempFile ( apipath + " .XXXXXX " , 0644 , fp ) ;
2014-10-28 21:13:15 +01:00
fp < < " /** \n "
2017-12-19 15:50:05 +01:00
< < " * The API listener is used for distributed monitoring setups. \n "
< < " */ \n "
< < " object ApiListener \" api \" { \n " ;
2014-10-28 21:13:15 +01:00
if ( vm . count ( " listen " ) ) {
2018-01-04 18:24:45 +01:00
std : : vector < String > tokens = String ( vm [ " listen " ] . as < std : : string > ( ) ) . Split ( " , " ) ;
2014-10-28 21:13:15 +01:00
if ( tokens . size ( ) > 0 )
fp < < " bind_host = \" " < < tokens [ 0 ] < < " \" \n " ;
if ( tokens . size ( ) > 1 )
fp < < " bind_port = " < < tokens [ 1 ] < < " \n " ;
}
fp < < " \n "
2017-12-19 15:50:05 +01:00
< < " ticket_salt = TicketSalt \n "
< < " } \n " ;
2014-10-28 21:13:15 +01:00
fp . close ( ) ;
# ifdef _WIN32
2014-12-18 16:55:45 +01:00
_unlink ( apipath . CStr ( ) ) ;
2014-10-28 21:13:15 +01:00
# endif /* _WIN32 */
2016-02-22 16:47:41 +01:00
if ( rename ( tempApiPath . CStr ( ) , apipath . CStr ( ) ) < 0 ) {
2014-12-18 16:55:45 +01:00
BOOST_THROW_EXCEPTION ( posix_error ( )
2017-12-19 15:50:05 +01:00
< < boost : : errinfo_api_function ( " rename " )
< < boost : : errinfo_errno ( errno )
< < boost : : errinfo_file_name ( tempApiPath ) ) ;
2014-12-18 16:55:45 +01:00
}
2014-10-22 19:27:21 +02:00
2014-10-23 03:35:01 +02:00
/* update constants.conf with NodeName = CN + TicketSalt = random value */
if ( cn ! = Utility : : GetFQDN ( ) ) {
Log ( LogWarning , " cli " )
< < " CN ' " < < cn < < " ' does not match the default FQDN ' " < < Utility : : GetFQDN ( ) < < " '. Requires update for NodeName constant in constants.conf! " ;
}
2014-10-31 11:38:16 +01:00
NodeUtility : : UpdateConstant ( " NodeName " , cn ) ;
2015-11-25 17:41:03 +01:00
NodeUtility : : UpdateConstant ( " ZoneName " , cn ) ;
2014-10-23 15:05:12 +02:00
String salt = RandomString ( 16 ) ;
2014-10-31 11:38:16 +01:00
NodeUtility : : UpdateConstant ( " TicketSalt " , salt ) ;
2014-10-21 16:04:20 +02:00
2014-10-21 18:24:35 +02:00
Log ( LogInformation , " cli " )
2017-12-19 15:50:05 +01:00
< < " Edit the api feature config file ' " < < apipath < < " ' and set a secure 'ticket_salt' attribute. " ;
2014-10-21 18:24:35 +02:00
2014-10-23 03:35:01 +02:00
/* tell the user to reload icinga2 */
2014-10-21 21:33:21 +02:00
2014-10-22 08:06:06 +02:00
Log ( LogInformation , " cli " , " Make sure to restart Icinga 2. " ) ;
2014-10-21 18:24:35 +02:00
return 0 ;
2014-10-18 21:06:28 +02:00
}
2014-10-31 11:38:16 +01:00
int NodeSetupCommand : : SetupNode ( const boost : : program_options : : variables_map & vm , const std : : vector < std : : string > & ap )
2014-10-18 21:06:28 +02:00
{
2017-10-16 18:38:18 +02:00
/* require at least one endpoint. Ticket is optional. */
2014-10-23 04:23:22 +02:00
if ( ! vm . count ( " endpoint " ) ) {
Log ( LogCritical , " cli " , " You need to specify at least one endpoint (--endpoint). " ) ;
return 1 ;
}
2014-10-21 18:24:35 +02:00
2014-10-31 22:21:36 +01:00
if ( ! vm . count ( " zone " ) ) {
Log ( LogCritical , " cli " , " You need to specify the local zone (--zone). " ) ;
return 1 ;
}
2017-10-16 18:38:18 +02:00
String ticket ;
2014-10-21 18:24:35 +02:00
2017-10-16 18:38:18 +02:00
if ( vm . count ( " ticket " ) )
ticket = vm [ " ticket " ] . as < std : : string > ( ) ;
if ( ticket . IsEmpty ( ) ) {
Log ( LogInformation , " cli " )
2017-12-19 15:50:05 +01:00
< < " Requesting certificate without a ticket. " ;
2017-10-16 18:38:18 +02:00
} else {
Log ( LogInformation , " cli " )
2017-12-19 15:50:05 +01:00
< < " Requesting certificate with ticket ' " < < ticket < < " '. " ;
2017-10-16 18:38:18 +02:00
}
2014-10-21 16:04:20 +02:00
2014-10-23 03:35:01 +02:00
/* require master host information for auto-signing requests */
2014-10-21 21:33:21 +02:00
if ( ! vm . count ( " master_host " ) ) {
2017-09-06 17:33:54 +02:00
Log ( LogCritical , " cli " , " Please pass the master host connection information for auto-signing using '--master_host <host>'. This can also be a direct parent satellite since 2.8. " ) ;
2014-10-21 21:33:21 +02:00
return 1 ;
}
2018-01-04 18:24:45 +01:00
std : : vector < String > tokens = String ( vm [ " master_host " ] . as < std : : string > ( ) ) . Split ( " , " ) ;
2014-10-21 21:33:21 +02:00
String master_host ;
String master_port = " 5665 " ;
if ( tokens . size ( ) = = 1 | | tokens . size ( ) = = 2 )
master_host = tokens [ 0 ] ;
if ( tokens . size ( ) = = 2 )
master_port = tokens [ 1 ] ;
Log ( LogInformation , " cli " )
2017-12-19 15:50:05 +01:00
< < " Verifying parent host connection information: host ' " < < master_host < < " ', port ' " < < master_port < < " '. " ;
2014-10-21 21:33:21 +02:00
2014-10-23 03:35:01 +02:00
/* trusted cert must be passed (retrieved by the user with 'pki save-cert' before) */
2014-10-21 21:33:21 +02:00
2014-10-21 18:24:35 +02:00
if ( ! vm . count ( " trustedcert " ) ) {
Log ( LogCritical , " cli " )
2017-12-19 15:50:05 +01:00
< < " Please pass the trusted cert retrieved from the parent node (master or satellite) \n "
< < " (Hint: 'icinga2 pki save-cert --host <masterhost> --port <5665> --key local.key --cert local.crt --trustedcert master.crt'). " ;
2014-10-21 18:24:35 +02:00
return 1 ;
}
2017-11-21 13:20:55 +01:00
std : : shared_ptr < X509 > trustedcert = GetX509Certificate ( vm [ " trustedcert " ] . as < std : : string > ( ) ) ;
2014-10-21 18:24:35 +02:00
Log ( LogInformation , " cli " )
2017-12-19 15:50:05 +01:00
< < " Verifying trusted certificate file ' " < < vm [ " trustedcert " ] . as < std : : string > ( ) < < " '. " ;
2014-10-21 18:24:35 +02:00
2014-10-23 03:35:01 +02:00
/* retrieve CN and pass it (defaults to FQDN) */
2014-10-21 18:24:35 +02:00
String cn = Utility : : GetFQDN ( ) ;
if ( vm . count ( " cn " ) )
cn = vm [ " cn " ] . as < std : : string > ( ) ;
2014-10-21 16:04:20 +02:00
2014-10-21 18:24:35 +02:00
Log ( LogInformation , " cli " )
2017-12-19 15:50:05 +01:00
< < " Using the following CN (defaults to FQDN): ' " < < cn < < " '. " ;
2014-10-21 18:24:35 +02:00
2014-10-23 03:35:01 +02:00
/* pki request a signed certificate from the master */
2014-10-21 21:33:21 +02:00
2017-09-06 12:11:48 +02:00
String pki_path = ApiListener : : GetCertsDir ( ) ;
2015-08-24 15:11:49 +02:00
Utility : : MkDirP ( pki_path , 0700 ) ;
2014-10-30 20:34:33 +01:00
2014-12-14 11:33:45 +01:00
String user = ScriptGlobal : : Get ( " RunAsUser " ) ;
String group = ScriptGlobal : : Get ( " RunAsGroup " ) ;
2014-10-30 20:34:33 +01:00
if ( ! Utility : : SetFileOwnership ( pki_path , user , group ) ) {
Log ( LogWarning , " cli " )
2017-12-19 15:50:05 +01:00
< < " Cannot set ownership for user ' " < < user < < " ' group ' " < < group < < " ' on file ' " < < pki_path < < " '. Verify it yourself! " ;
2014-10-30 20:34:33 +01:00
}
2015-08-24 15:11:49 +02:00
String key = pki_path + " / " + cn + " .key " ;
String cert = pki_path + " / " + cn + " .crt " ;
String ca = pki_path + " /ca.crt " ;
2015-02-09 14:19:26 +01:00
if ( Utility : : PathExists ( key ) )
NodeUtility : : CreateBackupFile ( key , true ) ;
if ( Utility : : PathExists ( cert ) )
NodeUtility : : CreateBackupFile ( cert ) ;
2014-10-22 21:49:41 +02:00
if ( PkiUtility : : NewCert ( cn , key , String ( ) , cert ) ! = 0 ) {
Log ( LogCritical , " cli " , " Failed to generate new self-signed certificate. " ) ;
2014-10-22 15:29:54 +02:00
return 1 ;
}
2014-10-21 18:24:35 +02:00
2014-10-30 20:34:33 +01:00
/* fix permissions: root -> icinga daemon user */
2016-02-23 08:41:48 +01:00
if ( ! Utility : : SetFileOwnership ( key , user , group ) ) {
Log ( LogWarning , " cli " )
2017-12-19 15:50:05 +01:00
< < " Cannot set ownership for user ' " < < user < < " ' group ' " < < group < < " ' on file ' " < < key < < " '. Verify it yourself! " ;
2014-10-30 20:34:33 +01:00
}
2017-09-06 17:33:54 +02:00
Log ( LogInformation , " cli " , " Requesting a signed certificate from the parent Icinga node. " ) ;
2014-10-21 18:24:35 +02:00
2017-10-16 18:38:18 +02:00
if ( PkiUtility : : RequestCertificate ( master_host , master_port , key , cert , ca , trustedcert , ticket ) > 0 ) {
Log ( LogCritical , " cli " )
2017-12-19 15:50:05 +01:00
< < " Failed to fetch signed certificate from parent Icinga node ' "
< < master_host < < " , "
< < master_port < < " '. Please try again. " ;
2014-10-22 21:49:41 +02:00
return 1 ;
}
2014-10-21 21:33:21 +02:00
2016-02-23 08:41:48 +01:00
if ( ! Utility : : SetFileOwnership ( ca , user , group ) ) {
Log ( LogWarning , " cli " )
2017-12-19 15:50:05 +01:00
< < " Cannot set ownership for user ' " < < user < < " ' group ' " < < group < < " ' on file ' " < < ca < < " '. Verify it yourself! " ;
2016-02-23 08:41:48 +01:00
}
2014-10-30 20:34:33 +01:00
/* fix permissions (again) when updating the signed certificate */
if ( ! Utility : : SetFileOwnership ( cert , user , group ) ) {
Log ( LogWarning , " cli " )
2017-12-19 15:50:05 +01:00
< < " Cannot set ownership for user ' " < < user < < " ' group ' " < < group < < " ' on file ' " < < cert < < " '. Verify it yourself! " ;
2014-10-30 20:34:33 +01:00
}
2014-11-02 20:17:57 +01:00
/* disable the notifications feature */
Log ( LogInformation , " cli " , " Disabling the Notification feature. " ) ;
2017-11-23 09:58:05 +01:00
FeatureUtility : : DisableFeatures ( { " notification " } ) ;
2014-11-02 20:17:57 +01:00
2014-10-28 21:13:15 +01:00
/* enable the ApiListener config */
2014-10-21 16:04:20 +02:00
2014-11-02 20:17:57 +01:00
Log ( LogInformation , " cli " , " Updating the ApiListener feature. " ) ;
2014-10-21 18:24:35 +02:00
2017-11-23 09:58:05 +01:00
FeatureUtility : : EnableFeatures ( { " api " } ) ;
2014-10-21 21:33:21 +02:00
2014-10-28 21:13:15 +01:00
String apipath = FeatureUtility : : GetFeaturesAvailablePath ( ) + " /api.conf " ;
2014-10-31 11:38:16 +01:00
NodeUtility : : CreateBackupFile ( apipath ) ;
2014-10-28 21:13:15 +01:00
2016-02-22 16:47:41 +01:00
std : : fstream fp ;
2016-02-24 13:55:25 +01:00
String tempApiPath = Utility : : CreateTempFile ( apipath + " .XXXXXX " , 0644 , fp ) ;
2014-10-28 21:13:15 +01:00
fp < < " /** \n "
2017-12-19 15:50:05 +01:00
< < " * The API listener is used for distributed monitoring setups. \n "
< < " */ \n "
< < " object ApiListener \" api \" { \n " ;
2014-10-28 21:13:15 +01:00
if ( vm . count ( " listen " ) ) {
2018-01-04 18:24:45 +01:00
std : : vector < String > tokens = String ( vm [ " listen " ] . as < std : : string > ( ) ) . Split ( " , " ) ;
2014-10-28 21:13:15 +01:00
if ( tokens . size ( ) > 0 )
fp < < " bind_host = \" " < < tokens [ 0 ] < < " \" \n " ;
if ( tokens . size ( ) > 1 )
fp < < " bind_port = " < < tokens [ 1 ] < < " \n " ;
}
2015-06-18 19:13:10 +02:00
fp < < " \n " ;
2015-03-27 14:11:21 +01:00
if ( vm . count ( " accept-config " ) )
2015-06-18 19:13:10 +02:00
fp < < " accept_config = true \n " ;
2015-03-27 14:11:21 +01:00
else
2015-06-18 19:13:10 +02:00
fp < < " accept_config = false \n " ;
2015-03-27 14:11:21 +01:00
if ( vm . count ( " accept-commands " ) )
2015-06-18 19:13:10 +02:00
fp < < " accept_commands = true \n " ;
2015-03-27 14:11:21 +01:00
else
2015-06-18 19:13:10 +02:00
fp < < " accept_commands = false \n " ;
2014-10-21 21:33:21 +02:00
2014-10-28 21:13:15 +01:00
fp < < " \n "
2017-12-19 15:50:05 +01:00
< < " } \n " ;
2014-10-21 21:33:21 +02:00
2014-10-28 21:13:15 +01:00
fp . close ( ) ;
2014-10-21 21:33:21 +02:00
2014-10-28 21:13:15 +01:00
# ifdef _WIN32
2014-12-18 16:55:45 +01:00
_unlink ( apipath . CStr ( ) ) ;
2014-10-28 21:13:15 +01:00
# endif /* _WIN32 */
2014-10-21 21:33:21 +02:00
2016-02-22 16:47:41 +01:00
if ( rename ( tempApiPath . CStr ( ) , apipath . CStr ( ) ) < 0 ) {
2014-12-18 16:55:45 +01:00
BOOST_THROW_EXCEPTION ( posix_error ( )
2017-12-19 15:50:05 +01:00
< < boost : : errinfo_api_function ( " rename " )
< < boost : : errinfo_errno ( errno )
< < boost : : errinfo_file_name ( tempApiPath ) ) ;
2014-12-18 16:55:45 +01:00
}
2014-10-22 19:27:21 +02:00
2014-10-23 03:35:01 +02:00
/* generate local zones.conf with zone+endpoint */
2014-10-21 16:04:20 +02:00
2014-10-22 08:06:06 +02:00
Log ( LogInformation , " cli " , " Generating zone and object configuration. " ) ;
2014-10-21 18:24:35 +02:00
2017-11-15 18:42:29 +01:00
std : : vector < String > globalZones ;
2018-02-26 08:34:45 +01:00
std : : vector < std : : string > setupGlobalZones ;
2017-11-15 18:42:29 +01:00
if ( vm . count ( " global_zones " ) )
2018-02-26 08:34:45 +01:00
setupGlobalZones = vm [ " global_zones " ] . as < std : : vector < std : : string > > ( ) ;
2017-11-15 18:42:29 +01:00
globalZones . push_back ( " global-templates " ) ;
globalZones . push_back ( " director-global " ) ;
for ( int i = 0 ; i < setupGlobalZones . size ( ) ; i + + ) {
if ( std : : find ( globalZones . begin ( ) , globalZones . end ( ) , setupGlobalZones [ i ] ) ! = globalZones . end ( ) ) {
Log ( LogCritical , " cli " )
< < " The global zone ' " < < setupGlobalZones [ i ] < < " ' is already specified. " ;
return 1 ;
}
}
globalZones . insert ( globalZones . end ( ) , setupGlobalZones . begin ( ) , setupGlobalZones . end ( ) ) ;
NodeUtility : : GenerateNodeIcingaConfig ( vm [ " endpoint " ] . as < std : : vector < std : : string > > ( ) , globalZones ) ;
2014-10-21 21:33:21 +02:00
2014-10-23 03:35:01 +02:00
/* update constants.conf with NodeName = CN */
2014-10-22 15:29:54 +02:00
if ( cn ! = Utility : : GetFQDN ( ) ) {
Log ( LogWarning , " cli " )
2017-12-19 15:50:05 +01:00
< < " CN ' " < < cn < < " ' does not match the default FQDN ' " < < Utility : : GetFQDN ( ) < < " '. Requires an update for the NodeName constant in constants.conf! " ;
2014-10-22 15:29:54 +02:00
}
2014-10-21 21:33:21 +02:00
2014-10-31 11:38:16 +01:00
NodeUtility : : UpdateConstant ( " NodeName " , cn ) ;
2015-11-25 17:41:03 +01:00
NodeUtility : : UpdateConstant ( " ZoneName " , vm [ " zone " ] . as < std : : string > ( ) ) ;
2014-10-21 21:33:21 +02:00
2017-10-16 18:38:18 +02:00
if ( ! ticket . IsEmpty ( ) ) {
String ticketPath = ApiListener : : GetCertsDir ( ) + " /ticket " ;
2017-08-29 11:57:16 +02:00
2017-10-16 18:38:18 +02:00
String tempTicketPath = Utility : : CreateTempFile ( ticketPath + " .XXXXXX " , 0600 , fp ) ;
2017-08-29 11:57:16 +02:00
2017-10-16 18:38:18 +02:00
if ( ! Utility : : SetFileOwnership ( tempTicketPath , user , group ) ) {
Log ( LogWarning , " cli " )
2017-12-19 15:50:05 +01:00
< < " Cannot set ownership for user ' " < < user
< < " ' group ' " < < group
< < " ' on file ' " < < tempTicketPath < < " '. Verify it yourself! " ;
2017-10-16 18:38:18 +02:00
}
2017-08-29 11:57:16 +02:00
2017-10-16 18:38:18 +02:00
fp < < ticket ;
2017-08-29 11:57:16 +02:00
2017-10-16 18:38:18 +02:00
fp . close ( ) ;
2014-10-21 16:04:20 +02:00
2017-08-29 11:57:16 +02:00
# ifdef _WIN32
2017-10-16 18:38:18 +02:00
_unlink ( ticketPath . CStr ( ) ) ;
2017-08-29 11:57:16 +02:00
# endif /* _WIN32 */
2017-10-16 18:38:18 +02:00
if ( rename ( tempTicketPath . CStr ( ) , ticketPath . CStr ( ) ) < 0 ) {
BOOST_THROW_EXCEPTION ( posix_error ( )
2017-12-19 15:50:05 +01:00
< < boost : : errinfo_api_function ( " rename " )
< < boost : : errinfo_errno ( errno )
< < boost : : errinfo_file_name ( tempTicketPath ) ) ;
2017-10-16 18:38:18 +02:00
}
2017-08-29 11:57:16 +02:00
}
/* tell the user to reload icinga2 */
2014-10-22 08:06:06 +02:00
Log ( LogInformation , " cli " , " Make sure to restart Icinga 2. " ) ;
2014-10-21 16:04:20 +02:00
2014-10-21 18:24:35 +02:00
return 0 ;
2014-10-18 21:06:28 +02:00
}