mirror of https://github.com/Icinga/icinga2.git
Merge pull request #6813 from Icinga/feature/gelfwriter-tls-support
Implement TLS support for the GelfWriter feature
This commit is contained in:
commit
5d0af5c879
|
@ -1344,7 +1344,10 @@ Configuration Attributes:
|
||||||
source | String | **Optional.** Source name for this instance. Defaults to `icinga2`.
|
source | String | **Optional.** Source name for this instance. Defaults to `icinga2`.
|
||||||
enable\_send\_perfdata | Boolean | **Optional.** Enable performance data for 'CHECK RESULT' events.
|
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\_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`.
|
||||||
|
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`.
|
||||||
|
|
||||||
### GraphiteWriter <a id="objecttype-graphitewriter"></a>
|
### GraphiteWriter <a id="objecttype-graphitewriter"></a>
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,11 @@
|
||||||
#include "base/statsfunction.hpp"
|
#include "base/statsfunction.hpp"
|
||||||
#include <boost/algorithm/string/replace.hpp>
|
#include <boost/algorithm/string/replace.hpp>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include "base/io-engine.hpp"
|
||||||
|
#include <boost/asio/write.hpp>
|
||||||
|
#include <boost/asio/buffer.hpp>
|
||||||
|
#include <boost/system/error_code.hpp>
|
||||||
|
#include <boost/asio/error.hpp>
|
||||||
|
|
||||||
using namespace icinga;
|
using namespace icinga;
|
||||||
|
|
||||||
|
@ -126,11 +131,7 @@ void GelfWriter::ExceptionHandler(boost::exception_ptr exp)
|
||||||
Log(LogDebug, "GelfWriter")
|
Log(LogDebug, "GelfWriter")
|
||||||
<< "Exception during Graylog Gelf operation: " << DiagnosticInformation(std::move(exp));
|
<< "Exception during Graylog Gelf operation: " << DiagnosticInformation(std::move(exp));
|
||||||
|
|
||||||
if (GetConnected()) {
|
DisconnectInternal();
|
||||||
m_Stream->Close();
|
|
||||||
|
|
||||||
SetConnected(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GelfWriter::Reconnect()
|
void GelfWriter::Reconnect()
|
||||||
|
@ -156,20 +157,46 @@ void GelfWriter::ReconnectInternal()
|
||||||
if (GetConnected())
|
if (GetConnected())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
TcpSocket::Ptr socket = new TcpSocket();
|
|
||||||
|
|
||||||
Log(LogNotice, "GelfWriter")
|
Log(LogNotice, "GelfWriter")
|
||||||
<< "Reconnecting to Graylog Gelf on host '" << GetHost() << "' port '" << GetPort() << "'.";
|
<< "Reconnecting to Graylog Gelf on host '" << GetHost() << "' port '" << GetPort() << "'.";
|
||||||
|
|
||||||
try {
|
bool ssl = GetEnableTls();
|
||||||
socket->Connect(GetHost(), GetPort());
|
|
||||||
} catch (const std::exception& ex) {
|
if (ssl) {
|
||||||
Log(LogCritical, "GelfWriter")
|
std::shared_ptr<boost::asio::ssl::context> sslContext;
|
||||||
<< "Can't connect to Graylog Gelf on host '" << GetHost() << "' port '" << GetPort() << "'.";
|
|
||||||
throw ex;
|
try {
|
||||||
|
sslContext = MakeAsioSslContext(GetCertPath(), GetKeyPath(), GetCaPath());
|
||||||
|
} catch (const std::exception& ex) {
|
||||||
|
Log(LogWarning, "GelfWriter")
|
||||||
|
<< "Unable to create SSL context.";
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Stream.first = std::make_shared<AsioTlsStream>(IoEngine::Get().GetIoService(), *sslContext, GetHost());
|
||||||
|
} else {
|
||||||
|
m_Stream.second = std::make_shared<AsioTcpStream>(IoEngine::Get().GetIoService());
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Stream = new NetworkStream(socket);
|
try {
|
||||||
|
icinga::Connect(ssl ? m_Stream.first->lowest_layer() : m_Stream.second->lowest_layer(), GetHost(), GetPort());
|
||||||
|
} catch (const std::exception& ex) {
|
||||||
|
Log(LogWarning, "GelfWriter")
|
||||||
|
<< "Can't connect to Graylog Gelf on host '" << GetHost() << "' port '" << GetPort() << ".'";
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ssl) {
|
||||||
|
auto& tlsStream (m_Stream.first->next_layer());
|
||||||
|
|
||||||
|
try {
|
||||||
|
tlsStream.handshake(tlsStream.client);
|
||||||
|
} catch (const std::exception& ex) {
|
||||||
|
Log(LogWarning, "GelfWriter")
|
||||||
|
<< "TLS handshake with host '" << GetHost() << " failed.'";
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SetConnected(true);
|
SetConnected(true);
|
||||||
|
|
||||||
|
@ -194,9 +221,22 @@ void GelfWriter::DisconnectInternal()
|
||||||
if (!GetConnected())
|
if (!GetConnected())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_Stream->Close();
|
if (m_Stream.first) {
|
||||||
|
boost::system::error_code ec;
|
||||||
|
m_Stream.first->next_layer().shutdown(ec);
|
||||||
|
|
||||||
|
// https://stackoverflow.com/a/25703699
|
||||||
|
// As long as the error code's category is not an SSL category, then the protocol was securely shutdown
|
||||||
|
if (ec.category() == boost::asio::error::get_ssl_category()) {
|
||||||
|
Log(LogCritical, "GelfWriter")
|
||||||
|
<< "TLS shutdown with host '" << GetHost() << "' could not be done securely.";
|
||||||
|
}
|
||||||
|
} else if (m_Stream.second) {
|
||||||
|
m_Stream.second->close();
|
||||||
|
}
|
||||||
|
|
||||||
SetConnected(false);
|
SetConnected(false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GelfWriter::CheckResultHandler(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr)
|
void GelfWriter::CheckResultHandler(const Checkable::Ptr& checkable, const CheckResult::Ptr& cr)
|
||||||
|
@ -456,7 +496,13 @@ void GelfWriter::SendLogMessage(const Checkable::Ptr& checkable, const String& g
|
||||||
Log(LogDebug, "GelfWriter")
|
Log(LogDebug, "GelfWriter")
|
||||||
<< "Checkable '" << checkable->GetName() << "' sending message '" << log << "'.";
|
<< "Checkable '" << checkable->GetName() << "' sending message '" << log << "'.";
|
||||||
|
|
||||||
m_Stream->Write(log.CStr(), log.GetLength());
|
if (m_Stream.first) {
|
||||||
|
boost::asio::write(*m_Stream.first, boost::asio::buffer(msgbuf.str()));
|
||||||
|
m_Stream.first->flush();
|
||||||
|
} else {
|
||||||
|
boost::asio::write(*m_Stream.second, boost::asio::buffer(msgbuf.str()));
|
||||||
|
m_Stream.second->flush();
|
||||||
|
}
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
Log(LogCritical, "GelfWriter")
|
Log(LogCritical, "GelfWriter")
|
||||||
<< "Cannot write to TCP socket on host '" << GetHost() << "' port '" << GetPort() << "'.";
|
<< "Cannot write to TCP socket on host '" << GetHost() << "' port '" << GetPort() << "'.";
|
||||||
|
|
|
@ -33,7 +33,7 @@ protected:
|
||||||
void Pause() override;
|
void Pause() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Stream::Ptr m_Stream;
|
OptionalTlsStream m_Stream;
|
||||||
WorkQueue m_WorkQueue{10000000, 1};
|
WorkQueue m_WorkQueue{10000000, 1};
|
||||||
|
|
||||||
Timer::Ptr m_ReconnectTimer;
|
Timer::Ptr m_ReconnectTimer;
|
||||||
|
|
|
@ -31,6 +31,12 @@ class GelfWriter : ConfigObject
|
||||||
[config] bool enable_ha {
|
[config] bool enable_ha {
|
||||||
default {{{ return false; }}}
|
default {{{ return false; }}}
|
||||||
};
|
};
|
||||||
|
[config] bool enable_tls {
|
||||||
|
default {{{ return false; }}}
|
||||||
|
};
|
||||||
|
[config] String ca_path;
|
||||||
|
[config] String cert_path;
|
||||||
|
[config] String key_path;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue