[pkg-nagios-changes] [Git][nagios-team/pkg-icinga2][upstream] New upstream version 2.13.1

Bas Couwenberg (@sebastic) gitlab at salsa.debian.org
Thu Aug 19 15:32:53 BST 2021



Bas Couwenberg pushed to branch upstream at Debian Nagios Maintainer Group / pkg-icinga2


Commits:
204c036b by Bas Couwenberg at 2021-08-19T15:48:42+02:00
New upstream version 2.13.1
- - - - -


14 changed files:

- CHANGELOG.md
- ICINGA2_VERSION
- doc/09-object-types.md
- doc/17-language-reference.md
- lib/base/configuration.cpp
- lib/base/tlsstream.cpp
- lib/db_ido_pgsql/idopgsqlconnection.cpp
- lib/icingadb/redisconnection.cpp
- lib/perfdata/elasticsearchwriter.cpp
- lib/perfdata/elasticsearchwriter.ti
- lib/perfdata/gelfwriter.cpp
- lib/perfdata/gelfwriter.ti
- lib/perfdata/influxdbcommonwriter.cpp
- lib/perfdata/influxdbcommonwriter.ti


Changes:

=====================================
CHANGELOG.md
=====================================
@@ -7,6 +7,26 @@ documentation before upgrading to a new release.
 
 Released closed milestones can be found on [GitHub](https://github.com/Icinga/icinga2/milestones?state=closed).
 
+## 2.13.1 (2021-08-19)
+
+The main focus of this version is a security vulnerability in the TLS certificate verification of our metrics writers ElasticsearchWriter, GelfWriter, InfluxdbWriter and Influxdb2Writer.
+
+Version 2.13.1 also fixes two issues indroduced with the 2.13.0 release.
+
+### Security
+
+* Add TLS server certificate validation to ElasticsearchWriter, GelfWriter, InfluxdbWriter and Influxdb2Writer ([GHSA-cxfm-8j5v-5qr2](https://github.com/Icinga/icinga2/security/advisories/GHSA-cxfm-8j5v-5qr2))
+
+Depending on your setup, manual intervention beyond installing the new versions
+may be required, so please read the more detailed information in the
+[release blog post](https://icinga.com/blog/2021/08/19/icinga-2-13-1-security-release//)
+carefully
+
+### Bugfixes
+
+* IDO PgSQL: Fix a string quoting regression introduced in 2.13.0 #8958
+* ApiListener: Automatically fall back to IPv4 in default configuration on systems without IPv6 support #8961
+
 ## 2.13.0 (2021-08-03)
 
 [Issues and PRs](https://github.com/Icinga/icinga2/issues?utf8=%E2%9C%93&q=milestone%3A2.13.0)


=====================================
ICINGA2_VERSION
=====================================
@@ -1,2 +1,2 @@
-Version: 2.13.0
+Version: 2.13.1
 Revision: 1


=====================================
doc/09-object-types.md
=====================================
@@ -1095,7 +1095,7 @@ Configuration Attributes:
   ca\_path                              | String                | **Deprecated.** Path to the CA certificate file.
   ticket\_salt                          | String                | **Optional.** Private key for [CSR auto-signing](06-distributed-monitoring.md#distributed-monitoring-setup-csr-auto-signing). **Required** for a signing master instance.
   crl\_path                             | String                | **Optional.** Path to the CRL file.
-  bind\_host                            | String                | **Optional.** The IP address the api listener should be bound to. If not specified, the ApiListener is bound to `::` and listens for both IPv4 and IPv6 connections.
+  bind\_host                            | String                | **Optional.** The IP address the api listener should be bound to. If not specified, the ApiListener is bound to `::` and listens for both IPv4 and IPv6 connections or to `0.0.0.0` if IPv6 is not supported by the operating system.
   bind\_port                            | Number                | **Optional.** The port the api listener should be bound to. Defaults to `5665`.
   accept\_config                        | Boolean               | **Optional.** Accept zone configuration. Defaults to `false`.
   accept\_commands                      | Boolean               | **Optional.** Accept remote commands. Defaults to `false`.
@@ -1238,6 +1238,7 @@ Configuration Attributes:
   username                  | String                | **Optional.** Basic auth username if Elasticsearch is hidden behind an HTTP proxy.
   password                  | String                | **Optional.** Basic auth password if Elasticsearch is hidden behind an HTTP proxy.
   enable\_tls               | Boolean               | **Optional.** Whether to use a TLS stream. Defaults to `false`. Requires an HTTP proxy.
+  insecure\_noverify        | Boolean               | **Optional.** Disable TLS peer verification.
   ca\_path                  | String                | **Optional.** Path to CA certificate to validate the remote host. Requires `enable_tls` set to `true`.
   cert\_path                | String                | **Optional.** Path to host certificate to present to the remote host for mutual verification. Requires `enable_tls` set to `true`.
   key\_path                 | String                | **Optional.** Path to host key to accompany the cert\_path. Requires `enable_tls` set to `true`.
@@ -1325,6 +1326,7 @@ Configuration Attributes:
   enable\_send\_perfdata    | Boolean               | **Optional.** Enable performance data for 'CHECK RESULT' events.
   enable\_ha                | Boolean               | **Optional.** Enable the high availability functionality. Only valid in a [cluster setup](06-distributed-monitoring.md#distributed-monitoring-high-availability-features). Defaults to `false`.
   enable\_tls               | Boolean               | **Optional.** Whether to use a TLS stream. Defaults to `false`.
+  insecure\_noverify        | Boolean               | **Optional.** Disable TLS peer verification.
   ca\_path                  | String                | **Optional.** Path to CA certificate to validate the remote host. Requires `enable_tls` set to `true`.
   cert\_path                | String                | **Optional.** Path to host certificate to present to the remote host for mutual verification. Requires `enable_tls` set to `true`.
   key\_path                 | String                | **Optional.** Path to host key to accompany the cert\_path. Requires `enable_tls` set to `true`.
@@ -1662,6 +1664,7 @@ Configuration Attributes:
   password                  | String                | **Optional.** InfluxDB user password.  Defaults to `none`.
   basic\_auth               | Dictionary            | **Optional.** Username and password for HTTP basic authentication.
   ssl\_enable               | Boolean               | **Optional.** Whether to use a TLS stream. Defaults to `false`.
+  ssl\_insecure\_noverify   | Boolean               | **Optional.** Disable TLS peer verification.
   ssl\_ca\_cert             | String                | **Optional.** Path to CA certificate to validate the remote host.
   ssl\_cert                 | String                | **Optional.** Path to host certificate to present to the remote host for mutual verification.
   ssl\_key                  | String                | **Optional.** Path to host key to accompany the ssl\_cert.
@@ -1724,6 +1727,7 @@ Configuration Attributes:
   bucket                    | String                | **Required.** InfluxDB bucket name.
   auth\_token               | String                | **Required.** InfluxDB authentication token.
   ssl\_enable               | Boolean               | **Optional.** Whether to use a TLS stream. Defaults to `false`.
+  ssl\_insecure\_noverify   | Boolean               | **Optional.** Disable TLS peer verification.
   ssl\_ca\_cert             | String                | **Optional.** Path to CA certificate to validate the remote host.
   ssl\_cert                 | String                | **Optional.** Path to host certificate to present to the remote host for mutual verification.
   ssl\_key                  | String                | **Optional.** Path to host key to accompany the ssl\_cert.


=====================================
doc/17-language-reference.md
=====================================
@@ -504,7 +504,7 @@ Environment         |**Read-write.** The name of the Icinga environment. Include
 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.
 MaxConcurrentChecks |**Read-write.** The number of max checks run simultaneously. Defaults to `512`.
-ApiBindHost         |**Read-write.** Overrides the default value for the ApiListener `bind_host` attribute. Defaults to `::`.
+ApiBindHost         |**Read-write.** Overrides the default value for the ApiListener `bind_host` attribute. Defaults to `::` if IPv6 is supported by the operating system and to `0.0.0.0` otherwise.
 ApiBindPort         |**Read-write.** Overrides the default value for the ApiListener `bind_port` attribute. Not set by default.
 
 #### Application Runtime Constants <a id="icinga-constants-application-runtime"></a>


=====================================
lib/base/configuration.cpp
=====================================
@@ -8,7 +8,20 @@ using namespace icinga;
 
 REGISTER_TYPE(Configuration);
 
-String Configuration::ApiBindHost{"::"};
+String Configuration::ApiBindHost = []() {
+#ifndef _WIN32
+	// Automatically fall back to an IPv4 default if socket() tells us that IPv6 is not supported.
+	int fd = socket(AF_INET6, SOCK_STREAM, 0);
+	if (fd < 0 && errno == EAFNOSUPPORT) {
+		return "0.0.0.0";
+	} else if (fd >= 0) {
+		close(fd);
+	}
+#endif /* _WIN32 */
+
+	return "::";
+}();
+
 String Configuration::ApiBindPort{"5665"};
 bool Configuration::AttachDebugger{false};
 String Configuration::CacheDir;


=====================================
lib/base/tlsstream.cpp
=====================================
@@ -37,6 +37,10 @@ void UnbufferedAsioTlsStream::BeforeHandshake(handshake_type type)
 {
 	namespace ssl = boost::asio::ssl;
 
+	if (!m_Hostname.IsEmpty()) {
+		X509_VERIFY_PARAM_set1_host(SSL_get0_param(native_handle()), m_Hostname.CStr(), m_Hostname.GetLength());
+	}
+
 	set_verify_mode(ssl::verify_peer | ssl::verify_client_once);
 
 	set_verify_callback([this](bool preverified, ssl::verify_context& ctx) {


=====================================
lib/db_ido_pgsql/idopgsqlconnection.cpp
=====================================
@@ -263,7 +263,7 @@ void IdoPgsqlConnection::Reconnect()
 
 	String dbVersionName = "idoutils";
 	IncreasePendingQueries(1);
-	result = Query("SELECT version FROM " + GetTablePrefix() + "dbversion WHERE name=E'" + Escape(dbVersionName) + "'");
+	result = Query("SELECT version FROM " + GetTablePrefix() + "dbversion WHERE name='" + Escape(dbVersionName) + "'");
 
 	Dictionary::Ptr row = FetchRow(result, 0);
 
@@ -295,12 +295,12 @@ void IdoPgsqlConnection::Reconnect()
 	String instanceName = GetInstanceName();
 
 	IncreasePendingQueries(1);
-	result = Query("SELECT instance_id FROM " + GetTablePrefix() + "instances WHERE instance_name = E'" + Escape(instanceName) + "'");
+	result = Query("SELECT instance_id FROM " + GetTablePrefix() + "instances WHERE instance_name = '" + Escape(instanceName) + "'");
 	row = FetchRow(result, 0);
 
 	if (!row) {
 		IncreasePendingQueries(1);
-		Query("INSERT INTO " + GetTablePrefix() + "instances (instance_name, instance_description) VALUES (E'" + Escape(instanceName) + "', E'" + Escape(GetInstanceDescription()) + "')");
+		Query("INSERT INTO " + GetTablePrefix() + "instances (instance_name, instance_description) VALUES ('" + Escape(instanceName) + "', '" + Escape(GetInstanceDescription()) + "')");
 		m_InstanceID = GetSequenceValue(GetTablePrefix() + "instances", "instance_id");
 	} else {
 		m_InstanceID = DbReference(row->Get("instance_id"));
@@ -384,8 +384,8 @@ void IdoPgsqlConnection::Reconnect()
 	IncreasePendingQueries(1);
 	Query("INSERT INTO " + GetTablePrefix() + "conninfo " +
 		"(instance_id, connect_time, last_checkin_time, agent_name, agent_version, connect_type, data_start_time) VALUES ("
-		+ Convert::ToString(static_cast<long>(m_InstanceID)) + ", NOW(), NOW(), E'icinga2 db_ido_pgsql', E'" + Escape(Application::GetAppVersion())
-		+ "', E'" + (reconnect ? "RECONNECT" : "INITIAL") + "', NOW())");
+		+ Convert::ToString(static_cast<long>(m_InstanceID)) + ", NOW(), NOW(), 'icinga2 db_ido_pgsql', '" + Escape(Application::GetAppVersion())
+		+ "', '" + (reconnect ? "RECONNECT" : "INITIAL") + "', NOW())");
 
 	/* clear config tables for the initial config dump */
 	PrepareDatabase();
@@ -522,7 +522,7 @@ DbReference IdoPgsqlConnection::GetSequenceValue(const String& table, const Stri
 	AssertOnWorkQueue();
 
 	IncreasePendingQueries(1);
-	IdoPgsqlResult result = Query("SELECT CURRVAL(pg_get_serial_sequence(E'" + Escape(table) + "', E'" + Escape(column) + "')) AS id");
+	IdoPgsqlResult result = Query("SELECT CURRVAL(pg_get_serial_sequence('" + Escape(table) + "', '" + Escape(column) + "')) AS id");
 
 	Dictionary::Ptr row = FetchRow(result, 0);
 
@@ -604,11 +604,11 @@ void IdoPgsqlConnection::InternalActivateObject(const DbObject::Ptr& dbobj)
 		if (!dbobj->GetName2().IsEmpty()) {
 			qbuf << "INSERT INTO " + GetTablePrefix() + "objects (instance_id, objecttype_id, name1, name2, is_active) VALUES ("
 				<< static_cast<long>(m_InstanceID) << ", " << dbobj->GetType()->GetTypeID() << ", "
-				<< "E'" << Escape(dbobj->GetName1()) << "', E'" << Escape(dbobj->GetName2()) << "', 1)";
+				<< "'" << Escape(dbobj->GetName1()) << "', '" << Escape(dbobj->GetName2()) << "', 1)";
 		} else {
 			qbuf << "INSERT INTO " + GetTablePrefix() + "objects (instance_id, objecttype_id, name1, is_active) VALUES ("
 				<< static_cast<long>(m_InstanceID) << ", " << dbobj->GetType()->GetTypeID() << ", "
-				<< "E'" << Escape(dbobj->GetName1()) << "', 1)";
+				<< "'" << Escape(dbobj->GetName1()) << "', 1)";
 		}
 
 		IncreasePendingQueries(1);
@@ -719,7 +719,7 @@ bool IdoPgsqlConnection::FieldToEscapedString(const String& key, const Value& va
 		else
 			fvalue = rawvalue;
 
-		*result = "E'" + Escape(fvalue) + "'";
+		*result = "'" + Escape(fvalue) + "'";
 	}
 
 	return true;


=====================================
lib/icingadb/redisconnection.cpp
=====================================
@@ -274,13 +274,6 @@ void RedisConnection::Connect(asio::yield_context& yc)
 					auto connectTimeout (MakeTimeout(conn));
 					Defer cancelTimeout ([&connectTimeout]() { connectTimeout->Cancel(); });
 
-					if (!m_Insecure) {
-						auto native (tlsConn.native_handle());
-
-						X509_VERIFY_PARAM_set1_host(SSL_get0_param(native), m_Host.CStr(), 0);
-						SSL_set_verify(native, SSL_VERIFY_PEER, NULL);
-					}
-
 					icinga::Connect(conn->lowest_layer(), m_Host, Convert::ToString(m_Port), yc);
 					tlsConn.async_handshake(tlsConn.client, yc);
 


=====================================
lib/perfdata/elasticsearchwriter.cpp
=====================================
@@ -632,6 +632,18 @@ OptionalTlsStream ElasticsearchWriter::Connect()
 				<< "TLS handshake with host '" << GetHost() << "' on port " << GetPort() << " failed.";
 			throw;
 		}
+
+		if (!GetInsecureNoverify()) {
+			if (!tlsStream.GetPeerCertificate()) {
+				BOOST_THROW_EXCEPTION(std::runtime_error("Elasticsearch didn't present any TLS certificate."));
+			}
+
+			if (!tlsStream.IsVerifyOK()) {
+				BOOST_THROW_EXCEPTION(std::runtime_error(
+					"TLS certificate validation failed: " + std::string(tlsStream.GetVerifyError())
+				));
+			}
+		}
 	}
 
 	return std::move(stream);


=====================================
lib/perfdata/elasticsearchwriter.ti
=====================================
@@ -29,6 +29,9 @@ class ElasticsearchWriter : ConfigObject
 	[config] bool enable_tls {
 		default {{{ return false; }}}
 	};
+	[config] bool insecure_noverify {
+		default {{{ return false; }}}
+	};
 	[config] String ca_path;
 	[config] String cert_path;
 	[config] String key_path;


=====================================
lib/perfdata/gelfwriter.cpp
=====================================
@@ -135,10 +135,8 @@ void GelfWriter::AssertOnWorkQueue()
 
 void GelfWriter::ExceptionHandler(boost::exception_ptr exp)
 {
-	Log(LogCritical, "GelfWriter", "Exception during Graylog Gelf operation: Verify that your backend is operational!");
-
-	Log(LogDebug, "GelfWriter")
-		<< "Exception during Graylog Gelf operation: " << DiagnosticInformation(std::move(exp));
+	Log(LogCritical, "GelfWriter") << "Exception during Graylog Gelf operation: " << DiagnosticInformation(exp, false);
+	Log(LogDebug, "GelfWriter") << "Exception during Graylog Gelf operation: " << DiagnosticInformation(exp, true);
 
 	DisconnectInternal();
 }
@@ -206,6 +204,18 @@ void GelfWriter::ReconnectInternal()
 				<< "TLS handshake with host '" << GetHost() << " failed.'";
 			throw;
 		}
+
+		if (!GetInsecureNoverify()) {
+			if (!tlsStream.GetPeerCertificate()) {
+				BOOST_THROW_EXCEPTION(std::runtime_error("Graylog Gelf didn't present any TLS certificate."));
+			}
+
+			if (!tlsStream.IsVerifyOK()) {
+				BOOST_THROW_EXCEPTION(std::runtime_error(
+					"TLS certificate validation failed: " + std::string(tlsStream.GetVerifyError())
+				));
+			}
+		}
 	}
 
 	SetConnected(true);


=====================================
lib/perfdata/gelfwriter.ti
=====================================
@@ -34,6 +34,9 @@ class GelfWriter : ConfigObject
     [config] bool enable_tls {
         default {{{ return false; }}}
     };
+    [config] bool insecure_noverify {
+        default {{{ return false; }}}
+    };
     [config] String ca_path;
     [config] String cert_path;
     [config] String key_path;


=====================================
lib/perfdata/influxdbcommonwriter.cpp
=====================================
@@ -187,6 +187,18 @@ OptionalTlsStream InfluxdbCommonWriter::Connect()
 				<< "TLS handshake with host '" << GetHost() << "' failed.";
 			throw;
 		}
+
+		if (!GetSslInsecureNoverify()) {
+			if (!tlsStream.GetPeerCertificate()) {
+				BOOST_THROW_EXCEPTION(std::runtime_error("InfluxDB didn't present any TLS certificate."));
+			}
+
+			if (!tlsStream.IsVerifyOK()) {
+				BOOST_THROW_EXCEPTION(std::runtime_error(
+					"TLS certificate validation failed: " + std::string(tlsStream.GetVerifyError())
+				));
+			}
+		}
 	}
 
 	return std::move(stream);


=====================================
lib/perfdata/influxdbcommonwriter.ti
=====================================
@@ -18,6 +18,9 @@ abstract class InfluxdbCommonWriter : ConfigObject
 	[config] bool ssl_enable {
 		default {{{ return false; }}}
 	};
+	[config] bool ssl_insecure_noverify {
+		default {{{ return false; }}}
+	};
 	[config] String ssl_ca_cert {
 		default {{{ return ""; }}}
 	};



View it on GitLab: https://salsa.debian.org/nagios-team/pkg-icinga2/-/commit/204c036b4c2008485d03b47d09150ba002941f93

-- 
View it on GitLab: https://salsa.debian.org/nagios-team/pkg-icinga2/-/commit/204c036b4c2008485d03b47d09150ba002941f93
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-nagios-changes/attachments/20210819/9d171965/attachment-0001.htm>


More information about the pkg-nagios-changes mailing list