mirror of
https://github.com/Icinga/icinga2.git
synced 2025-07-05 12:54:30 +02:00
Merge pull request #6512 from Icinga/feature/sni-environment
Refactor environment for API connections
This commit is contained in:
commit
060a1ebbd9
@ -116,8 +116,8 @@ you still need a [Host](09-object-types.md#objecttype-host) object.
|
|||||||
|
|
||||||
In case you are using the CLI commands later, you don't have to write
|
In case you are using the CLI commands later, you don't have to write
|
||||||
this configuration from scratch in a text editor.
|
this configuration from scratch in a text editor.
|
||||||
The [ApiListener](09-object-types.md#objecttype-apilistener)
|
The [ApiListener](09-object-types.md#objecttype-apilistener) object is
|
||||||
object is used to load the SSL certificates and specify restrictions, e.g.
|
used to load the TLS certificates and specify restrictions, e.g.
|
||||||
for accepting configuration commands.
|
for accepting configuration commands.
|
||||||
|
|
||||||
It is also used for the [Icinga 2 REST API](12-icinga2-api.md#icinga2-api) which shares
|
It is also used for the [Icinga 2 REST API](12-icinga2-api.md#icinga2-api) which shares
|
||||||
@ -2793,3 +2793,36 @@ Add the global zone `global-templates` in case it did not exist.
|
|||||||
global = true
|
global = true
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
## Using Multiple Environments <a id="distributed-monitoring-environments"></a>
|
||||||
|
|
||||||
|
In some cases it can be desired to run multiple Icinga instances on the same host.
|
||||||
|
Two potential scenarios include:
|
||||||
|
|
||||||
|
* Different versions of the same monitoring configuration (e.g. production and testing)
|
||||||
|
* Disparate sets of checks for entirely unrelated monitoring environments (e.g. infrastructure and applications)
|
||||||
|
|
||||||
|
The configuration is done with the global constants `ApiBindHost` and `ApiBindPort`
|
||||||
|
or the `bind_host` and `bind_port` attributes of the
|
||||||
|
[ApiListener](09-object-types.md#objecttype-apilistener) object.
|
||||||
|
|
||||||
|
The environment must be set with the global constant `Environment` or as object attribute
|
||||||
|
of the [IcingaApplication](#objecttype-icingaapplication) object.
|
||||||
|
|
||||||
|
In any case the constant is default value for the attribute and the direct configuration in the objects
|
||||||
|
have more precedence. The constants have been added to allow the values being set from the CLI on startup.
|
||||||
|
|
||||||
|
When Icinga establishes a TLS connection to another cluster instance it automatically uses the [SNI extension](https://en.wikipedia.org/wiki/Server_Name_Indication)
|
||||||
|
to signal which endpoint it is attempting to connect to. On its own this can already be used to position multiple
|
||||||
|
Icinga instances behind a load balancer.
|
||||||
|
|
||||||
|
SNI example: `icinga2-client1.localdomain`
|
||||||
|
|
||||||
|
However, if the environment is configured to `production`, Icinga appends the environment name to the SNI hostname like this:
|
||||||
|
|
||||||
|
SNI example with environment: `icinga2-client1.localdomain:production`
|
||||||
|
|
||||||
|
Middleware like loadbalancers or TLS proxies can read the SNI header and route the connection to the appropriate target.
|
||||||
|
I.e., it uses a single externally-visible TCP port (usually 5665) and forwards connections to one or more Icinga
|
||||||
|
instances which are bound to a local TCP port. It does so by inspecting the environment name that is sent as part of the
|
||||||
|
SNI extension.
|
||||||
|
@ -67,6 +67,7 @@ Configuration Attributes:
|
|||||||
access\_control\_allow\_credentials | Boolean | **Deprecated.** Indicates whether or not the actual request can be made using credentials. Defaults to `true`. [(MDN docs)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Access-Control-Allow-Credentials)
|
access\_control\_allow\_credentials | Boolean | **Deprecated.** Indicates whether or not the actual request can be made using credentials. Defaults to `true`. [(MDN docs)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Access-Control-Allow-Credentials)
|
||||||
access\_control\_allow\_headers | String | **Deprecated.** Used in response to a preflight request to indicate which HTTP headers can be used when making the actual request. Defaults to `Authorization`. [(MDN docs)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Access-Control-Allow-Headers)
|
access\_control\_allow\_headers | String | **Deprecated.** Used in response to a preflight request to indicate which HTTP headers can be used when making the actual request. Defaults to `Authorization`. [(MDN docs)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Access-Control-Allow-Headers)
|
||||||
access\_control\_allow\_methods | String | **Deprecated.** Used in response to a preflight request to indicate which HTTP methods can be used when making the actual request. Defaults to `GET, POST, PUT, DELETE`. [(MDN docs)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Access-Control-Allow-Methods)
|
access\_control\_allow\_methods | String | **Deprecated.** Used in response to a preflight request to indicate which HTTP methods can be used when making the actual request. Defaults to `GET, POST, PUT, DELETE`. [(MDN docs)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Access-Control-Allow-Methods)
|
||||||
|
environment | String | **Optional.** Used as suffix in TLS SNI extension name; default from constant `ApiEnvironment`, which is empty.
|
||||||
|
|
||||||
The attributes `access_control_allow_credentials`, `access_control_allow_headers` and `access_control_allow_methods`
|
The attributes `access_control_allow_credentials`, `access_control_allow_headers` and `access_control_allow_methods`
|
||||||
are controlled by Icinga 2 and are not changeable by config any more.
|
are controlled by Icinga 2 and are not changeable by config any more.
|
||||||
@ -816,6 +817,7 @@ Configuration Attributes:
|
|||||||
enable\_service\_checks | Boolean | **Optional.** Whether active service checks are globally enabled. Defaults to true.
|
enable\_service\_checks | Boolean | **Optional.** Whether active service checks are globally enabled. Defaults to true.
|
||||||
enable\_perfdata | Boolean | **Optional.** Whether performance data processing is globally enabled. Defaults to true.
|
enable\_perfdata | Boolean | **Optional.** Whether performance data processing is globally enabled. Defaults to true.
|
||||||
vars | Dictionary | **Optional.** A dictionary containing custom attributes that are available globally.
|
vars | Dictionary | **Optional.** A dictionary containing custom attributes that are available globally.
|
||||||
|
environment | String | **Optional.** Specify the Icinga environment. This overrides the `Environment` constant specified in the configuration or on the CLI with `--define`. Defaults to empty.
|
||||||
|
|
||||||
## IdoMySqlConnection <a id="objecttype-idomysqlconnection"></a>
|
## IdoMySqlConnection <a id="objecttype-idomysqlconnection"></a>
|
||||||
|
|
||||||
|
@ -41,6 +41,7 @@ has been removed and this setting has no effect.
|
|||||||
|
|
||||||
New [Icinga constants](17-language-reference.md#icinga-constants) have been added in this release.
|
New [Icinga constants](17-language-reference.md#icinga-constants) have been added in this release.
|
||||||
|
|
||||||
|
* `Environment` for specifying the Icinga environment. Defaults to not set.
|
||||||
* `ApiBindHost` and `ApiBindPort` to allow overriding the default ApiListener values. This will be used for an Icinga addon only.
|
* `ApiBindHost` and `ApiBindPort` to allow overriding the default ApiListener values. This will be used for an Icinga addon only.
|
||||||
|
|
||||||
## Upgrading to v2.9 <a id="upgrading-to-2-9"></a>
|
## Upgrading to v2.9 <a id="upgrading-to-2-9"></a>
|
||||||
|
@ -407,10 +407,10 @@ Constant | Description
|
|||||||
--------------------|-------------------
|
--------------------|-------------------
|
||||||
Vars |**Read-write.** Contains a dictionary with global custom attributes. Not set by default.
|
Vars |**Read-write.** Contains a dictionary with global custom attributes. Not set by default.
|
||||||
NodeName |**Read-write.** Contains the cluster node name. Set to the local hostname by default.
|
NodeName |**Read-write.** Contains the cluster node name. Set to the local hostname by default.
|
||||||
|
Environment |**Read-write.** The name of the Icinga environment. Included in the SNI host name for outbound connections. Not set by default.
|
||||||
RunAsUser |**Read-write.** Defines the user the Icinga 2 daemon is running as. Set in the Icinga 2 sysconfig.
|
RunAsUser |**Read-write.** Defines the user the Icinga 2 daemon is running as. Set in the Icinga 2 sysconfig.
|
||||||
RunAsGroup |**Read-write.** Defines the group the Icinga 2 daemon is running as. Set in the Icinga 2 sysconfig.
|
RunAsGroup |**Read-write.** Defines the group the Icinga 2 daemon is running as. Set in the Icinga 2 sysconfig.
|
||||||
MaxConcurrentChecks |**Read-write.** The number of max checks run simultaneously. Defaults to `512`.
|
MaxConcurrentChecks |**Read-write.** The number of max checks run simultaneously. Defaults to `512`.
|
||||||
Environment |**Read-write.** The name of the Icinga environment. Included in the SNI host name when making outbound connections. Defaults to `production`.
|
|
||||||
ApiBindHost |**Read-write.** Overrides the default value for the ApiListener `bind_host` attribute. Not set by default.
|
ApiBindHost |**Read-write.** Overrides the default value for the ApiListener `bind_host` attribute. Not set by default.
|
||||||
ApiBindPort |**Read-write.** Overrides the default value for the ApiListener `bind_port` attribute. Not set by default.
|
ApiBindPort |**Read-write.** Overrides the default value for the ApiListener `bind_port` attribute. Not set by default.
|
||||||
|
|
||||||
@ -454,7 +454,6 @@ SysconfDir |**Read-only.** Contains the path of the sysconf directory.
|
|||||||
LocalStateDir |**Read-only.** Contains the path of the local state directory. Defaults to `PrefixDir + "/var"`.
|
LocalStateDir |**Read-only.** Contains the path of the local state directory. Defaults to `PrefixDir + "/var"`.
|
||||||
RunDir |**Read-only.** Contains the path of the run directory. Defaults to `LocalStateDir + "/run"`.
|
RunDir |**Read-only.** Contains the path of the run directory. Defaults to `LocalStateDir + "/run"`.
|
||||||
|
|
||||||
|
|
||||||
Advanced runtime constants. Please only use them if advised by support or developers.
|
Advanced runtime constants. Please only use them if advised by support or developers.
|
||||||
|
|
||||||
Variable | Description
|
Variable | Description
|
||||||
|
@ -297,8 +297,6 @@ static int Main()
|
|||||||
Application::DeclareConst("Concurrency", std::thread::hardware_concurrency());
|
Application::DeclareConst("Concurrency", std::thread::hardware_concurrency());
|
||||||
Application::DeclareConst("MaxConcurrentChecks", Application::GetDefaultMaxConcurrentChecks());
|
Application::DeclareConst("MaxConcurrentChecks", Application::GetDefaultMaxConcurrentChecks());
|
||||||
|
|
||||||
ScriptGlobal::Set("Environment", "production");
|
|
||||||
|
|
||||||
ScriptGlobal::Set("AttachDebugger", false);
|
ScriptGlobal::Set("AttachDebugger", false);
|
||||||
|
|
||||||
ScriptGlobal::Set("PlatformKernel", Utility::GetPlatformKernel());
|
ScriptGlobal::Set("PlatformKernel", Utility::GetPlatformKernel());
|
||||||
|
@ -27,7 +27,7 @@ mkclass_target(sysloglogger.ti sysloglogger-ti.cpp sysloglogger-ti.hpp)
|
|||||||
|
|
||||||
set(base_SOURCES
|
set(base_SOURCES
|
||||||
i2-base.hpp
|
i2-base.hpp
|
||||||
application.cpp application.hpp application-ti.hpp application-version.cpp
|
application.cpp application.hpp application-ti.hpp application-version.cpp application-environment.cpp
|
||||||
array.cpp array.hpp array-script.cpp
|
array.cpp array.hpp array-script.cpp
|
||||||
base64.cpp base64.hpp
|
base64.cpp base64.hpp
|
||||||
boolean.cpp boolean.hpp boolean-script.cpp
|
boolean.cpp boolean.hpp boolean-script.cpp
|
||||||
|
34
lib/base/application-environment.cpp
Normal file
34
lib/base/application-environment.cpp
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* 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 "base/application.hpp"
|
||||||
|
#include "base/scriptglobal.hpp"
|
||||||
|
|
||||||
|
using namespace icinga;
|
||||||
|
|
||||||
|
String Application::GetAppEnvironment()
|
||||||
|
{
|
||||||
|
Value defaultValue = Empty;
|
||||||
|
return ScriptGlobal::Get("Environment", &defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::SetAppEnvironment(const String& name)
|
||||||
|
{
|
||||||
|
ScriptGlobal::Set("Environment", name);
|
||||||
|
}
|
@ -107,6 +107,9 @@ public:
|
|||||||
static String GetAppVersion();
|
static String GetAppVersion();
|
||||||
static String GetAppSpecVersion();
|
static String GetAppSpecVersion();
|
||||||
|
|
||||||
|
static String GetAppEnvironment();
|
||||||
|
static void SetAppEnvironment(const String& name);
|
||||||
|
|
||||||
static double GetStartTime();
|
static double GetStartTime();
|
||||||
static void SetStartTime(double ts);
|
static void SetStartTime(double ts);
|
||||||
|
|
||||||
|
@ -79,10 +79,10 @@ void IcingaApplication::StatsFunc(const Dictionary::Ptr& status, const Array::Pt
|
|||||||
{ "enable_host_checks", icingaapplication->GetEnableHostChecks() },
|
{ "enable_host_checks", icingaapplication->GetEnableHostChecks() },
|
||||||
{ "enable_service_checks", icingaapplication->GetEnableServiceChecks() },
|
{ "enable_service_checks", icingaapplication->GetEnableServiceChecks() },
|
||||||
{ "enable_perfdata", icingaapplication->GetEnablePerfdata() },
|
{ "enable_perfdata", icingaapplication->GetEnablePerfdata() },
|
||||||
|
{ "environment", icingaapplication->GetEnvironment() },
|
||||||
{ "pid", Utility::GetPid() },
|
{ "pid", Utility::GetPid() },
|
||||||
{ "program_start", Application::GetStartTime() },
|
{ "program_start", Application::GetStartTime() },
|
||||||
{ "version", Application::GetAppVersion() },
|
{ "version", Application::GetAppVersion() }
|
||||||
{ "environment", ScriptGlobal::Get("Environment", &Empty) }
|
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,6 +294,16 @@ String IcingaApplication::GetNodeName() const
|
|||||||
return ScriptGlobal::Get("NodeName");
|
return ScriptGlobal::Get("NodeName");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String IcingaApplication::GetEnvironment() const
|
||||||
|
{
|
||||||
|
return Application::GetAppEnvironment();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IcingaApplication::SetEnvironment(const String& value, bool suppress_events, const Value& cookie)
|
||||||
|
{
|
||||||
|
Application::SetAppEnvironment(value);
|
||||||
|
}
|
||||||
|
|
||||||
void IcingaApplication::ValidateVars(const Lazy<Dictionary::Ptr>& lvalue, const ValidationUtils& utils)
|
void IcingaApplication::ValidateVars(const Lazy<Dictionary::Ptr>& lvalue, const ValidationUtils& utils)
|
||||||
{
|
{
|
||||||
MacroProcessor::ValidateCustomVars(this, lvalue());
|
MacroProcessor::ValidateCustomVars(this, lvalue());
|
||||||
|
@ -50,6 +50,9 @@ public:
|
|||||||
|
|
||||||
String GetNodeName() const;
|
String GetNodeName() const;
|
||||||
|
|
||||||
|
String GetEnvironment() const override;
|
||||||
|
void SetEnvironment(const String& value, bool suppress_events = false, const Value& cookie = Empty) override;
|
||||||
|
|
||||||
void ValidateVars(const Lazy<Dictionary::Ptr>& lvalue, const ValidationUtils& utils) override;
|
void ValidateVars(const Lazy<Dictionary::Ptr>& lvalue, const ValidationUtils& utils) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -26,6 +26,12 @@ namespace icinga
|
|||||||
|
|
||||||
class IcingaApplication : Application
|
class IcingaApplication : Application
|
||||||
{
|
{
|
||||||
|
[config, no_storage, virtual] String environment {
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
default {{{ return Application::GetAppEnvironment(); }}}
|
||||||
|
};
|
||||||
|
|
||||||
[config] bool enable_notifications {
|
[config] bool enable_notifications {
|
||||||
default {{{ return true; }}}
|
default {{{ return true; }}}
|
||||||
};
|
};
|
||||||
|
@ -388,16 +388,10 @@ void ApiListener::AddConnection(const Endpoint::Ptr& endpoint)
|
|||||||
|
|
||||||
TcpSocket::Ptr client = new TcpSocket();
|
TcpSocket::Ptr client = new TcpSocket();
|
||||||
|
|
||||||
String serverName = endpoint->GetName();
|
|
||||||
|
|
||||||
String env = ScriptGlobal::Get("Environment", &Empty);
|
|
||||||
if (env != "" && env != "production")
|
|
||||||
serverName += ":" + env;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
endpoint->SetConnecting(true);
|
endpoint->SetConnecting(true);
|
||||||
client->Connect(host, port);
|
client->Connect(host, port);
|
||||||
NewClientHandler(client, serverName, RoleClient);
|
NewClientHandler(client, endpoint->GetName(), RoleClient);
|
||||||
endpoint->SetConnecting(false);
|
endpoint->SetConnecting(false);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
endpoint->SetConnecting(false);
|
endpoint->SetConnecting(false);
|
||||||
@ -447,10 +441,17 @@ void ApiListener::NewClientHandlerInternal(const Socket::Ptr& client, const Stri
|
|||||||
|
|
||||||
TlsStream::Ptr tlsStream;
|
TlsStream::Ptr tlsStream;
|
||||||
|
|
||||||
|
String environmentName = Application::GetAppEnvironment();
|
||||||
|
|
||||||
|
String serverName = hostname;
|
||||||
|
|
||||||
|
if (!environmentName.IsEmpty())
|
||||||
|
serverName += ":" + environmentName;
|
||||||
|
|
||||||
{
|
{
|
||||||
ObjectLock olock(this);
|
ObjectLock olock(this);
|
||||||
try {
|
try {
|
||||||
tlsStream = new TlsStream(client, hostname, role, m_SSLContext);
|
tlsStream = new TlsStream(client, serverName, role, m_SSLContext);
|
||||||
} catch (const std::exception&) {
|
} catch (const std::exception&) {
|
||||||
Log(LogCritical, "ApiListener")
|
Log(LogCritical, "ApiListener")
|
||||||
<< "Cannot create TLS stream from client connection (" << conninfo << ")";
|
<< "Cannot create TLS stream from client connection (" << conninfo << ")";
|
||||||
|
@ -568,6 +568,7 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&)
|
|||||||
<< "{" << std::endl;
|
<< "{" << std::endl;
|
||||||
|
|
||||||
for (const Field& field : klass.Fields) {
|
for (const Field& field : klass.Fields) {
|
||||||
|
if (!field.PureSetAccessor)
|
||||||
m_Impl << "\t" << "Set" << field.GetFriendlyName() << "(" << "GetDefault" << field.GetFriendlyName() << "(), true);" << std::endl;
|
m_Impl << "\t" << "Set" << field.GetFriendlyName() << "(" << "GetDefault" << field.GetFriendlyName() << "(), true);" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user