mirror of
https://github.com/Icinga/icinga2.git
synced 2025-07-25 14:44:32 +02:00
RedisConnection: AUTH and SELECT
... or PING to trigger NOAUTH.
This commit is contained in:
parent
37e53eaa68
commit
e1e8ec2ea2
@ -28,6 +28,8 @@
|
|||||||
using namespace icinga;
|
using namespace icinga;
|
||||||
namespace asio = boost::asio;
|
namespace asio = boost::asio;
|
||||||
|
|
||||||
|
boost::regex RedisConnection::m_ErrAuth ("\\AERR AUTH ");
|
||||||
|
|
||||||
RedisConnection::RedisConnection(const String& host, int port, const String& path, const String& password, int db,
|
RedisConnection::RedisConnection(const String& host, int port, const String& path, const String& password, int db,
|
||||||
bool useTls, bool insecure, const String& certPath, const String& keyPath, const String& caPath, const String& crlPath,
|
bool useTls, bool insecure, const String& certPath, const String& keyPath, const String& caPath, const String& crlPath,
|
||||||
const String& tlsProtocolmin, const String& cipherList, DebugInfo di, const RedisConnection::Ptr& parent)
|
const String& tlsProtocolmin, const String& cipherList, DebugInfo di, const RedisConnection::Ptr& parent)
|
||||||
@ -296,6 +298,7 @@ void RedisConnection::Connect(asio::yield_context& yc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Handshake(conn, yc);
|
||||||
m_TlsConn = std::move(conn);
|
m_TlsConn = std::move(conn);
|
||||||
} else {
|
} else {
|
||||||
Log(m_Parent ? LogNotice : LogInformation, "IcingaDB")
|
Log(m_Parent ? LogNotice : LogInformation, "IcingaDB")
|
||||||
@ -303,6 +306,7 @@ void RedisConnection::Connect(asio::yield_context& yc)
|
|||||||
|
|
||||||
auto conn (Shared<TcpConn>::Make(m_Strand.context()));
|
auto conn (Shared<TcpConn>::Make(m_Strand.context()));
|
||||||
icinga::Connect(conn->next_layer(), m_Host, Convert::ToString(m_Port), yc);
|
icinga::Connect(conn->next_layer(), m_Host, Convert::ToString(m_Port), yc);
|
||||||
|
Handshake(conn, yc);
|
||||||
m_TcpConn = std::move(conn);
|
m_TcpConn = std::move(conn);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -311,6 +315,7 @@ void RedisConnection::Connect(asio::yield_context& yc)
|
|||||||
|
|
||||||
auto conn (Shared<UnixConn>::Make(m_Strand.context()));
|
auto conn (Shared<UnixConn>::Make(m_Strand.context()));
|
||||||
conn->next_layer().async_connect(Unix::endpoint(m_Path.CStr()), yc);
|
conn->next_layer().async_connect(Unix::endpoint(m_Path.CStr()), yc);
|
||||||
|
Handshake(conn, yc);
|
||||||
m_UnixConn = std::move(conn);
|
m_UnixConn = std::move(conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include "base/array.hpp"
|
#include "base/array.hpp"
|
||||||
#include "base/atomic.hpp"
|
#include "base/atomic.hpp"
|
||||||
|
#include "base/convert.hpp"
|
||||||
#include "base/io-engine.hpp"
|
#include "base/io-engine.hpp"
|
||||||
#include "base/object.hpp"
|
#include "base/object.hpp"
|
||||||
#include "base/ringbuffer.hpp"
|
#include "base/ringbuffer.hpp"
|
||||||
@ -25,6 +26,7 @@
|
|||||||
#include <boost/asio/streambuf.hpp>
|
#include <boost/asio/streambuf.hpp>
|
||||||
#include <boost/asio/write.hpp>
|
#include <boost/asio/write.hpp>
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
|
#include <boost/regex.hpp>
|
||||||
#include <boost/utility/string_view.hpp>
|
#include <boost/utility/string_view.hpp>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
@ -150,6 +152,8 @@ namespace icinga
|
|||||||
template<class AsyncWriteStream>
|
template<class AsyncWriteStream>
|
||||||
static void WriteRESP(AsyncWriteStream& stream, const Query& query, boost::asio::yield_context& yc);
|
static void WriteRESP(AsyncWriteStream& stream, const Query& query, boost::asio::yield_context& yc);
|
||||||
|
|
||||||
|
static boost::regex m_ErrAuth;
|
||||||
|
|
||||||
RedisConnection(boost::asio::io_context& io, String host, int port, String path, String password,
|
RedisConnection(boost::asio::io_context& io, String host, int port, String path, String password,
|
||||||
int db, bool useTls, bool insecure, String certPath, String keyPath, String caPath, String crlPath,
|
int db, bool useTls, bool insecure, String certPath, String keyPath, String caPath, String crlPath,
|
||||||
String tlsProtocolmin, String cipherList, DebugInfo di, const Ptr& parent);
|
String tlsProtocolmin, String cipherList, DebugInfo di, const Ptr& parent);
|
||||||
@ -171,6 +175,9 @@ namespace icinga
|
|||||||
void IncreasePendingQueries(int count);
|
void IncreasePendingQueries(int count);
|
||||||
void DecreasePendingQueries(int count);
|
void DecreasePendingQueries(int count);
|
||||||
|
|
||||||
|
template<class StreamPtr>
|
||||||
|
void Handshake(StreamPtr& stream, boost::asio::yield_context& yc);
|
||||||
|
|
||||||
String m_Path;
|
String m_Path;
|
||||||
String m_Host;
|
String m_Host;
|
||||||
int m_Port;
|
int m_Port;
|
||||||
@ -387,6 +394,65 @@ void RedisConnection::WriteOne(StreamPtr& stream, RedisConnection::Query& query,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize a Redis stream
|
||||||
|
*
|
||||||
|
* @param stream Redis server connection
|
||||||
|
* @param query Redis query
|
||||||
|
*/
|
||||||
|
template<class StreamPtr>
|
||||||
|
void RedisConnection::Handshake(StreamPtr& strm, boost::asio::yield_context& yc)
|
||||||
|
{
|
||||||
|
if (m_Password.IsEmpty() && !m_DbIndex) {
|
||||||
|
// Trigger NOAUTH
|
||||||
|
WriteRESP(*strm, {"PING"}, yc);
|
||||||
|
} else {
|
||||||
|
if (!m_Password.IsEmpty()) {
|
||||||
|
WriteRESP(*strm, {"AUTH", m_Password}, yc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_DbIndex) {
|
||||||
|
WriteRESP(*strm, {"SELECT", Convert::ToString(m_DbIndex)}, yc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
strm->async_flush(yc);
|
||||||
|
|
||||||
|
if (m_Password.IsEmpty() && !m_DbIndex) {
|
||||||
|
Reply pong (ReadRESP(*strm, yc));
|
||||||
|
|
||||||
|
if (pong.IsObjectType<RedisError>()) {
|
||||||
|
// Likely NOAUTH
|
||||||
|
BOOST_THROW_EXCEPTION(std::runtime_error(RedisError::Ptr(pong)->GetMessage()));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!m_Password.IsEmpty()) {
|
||||||
|
Reply auth (ReadRESP(*strm, yc));
|
||||||
|
|
||||||
|
if (auth.IsObjectType<RedisError>()) {
|
||||||
|
auto& authErr (RedisError::Ptr(auth)->GetMessage().GetData());
|
||||||
|
boost::smatch what;
|
||||||
|
|
||||||
|
if (boost::regex_search(authErr, what, m_ErrAuth)) {
|
||||||
|
Log(LogWarning, "IcingaDB") << authErr;
|
||||||
|
} else {
|
||||||
|
// Likely WRONGPASS
|
||||||
|
BOOST_THROW_EXCEPTION(std::runtime_error(authErr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_DbIndex) {
|
||||||
|
Reply select (ReadRESP(*strm, yc));
|
||||||
|
|
||||||
|
if (select.IsObjectType<RedisError>()) {
|
||||||
|
// Likely NOAUTH or ERR DB
|
||||||
|
BOOST_THROW_EXCEPTION(std::runtime_error(RedisError::Ptr(select)->GetMessage()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read a Redis protocol value from stream
|
* Read a Redis protocol value from stream
|
||||||
*
|
*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user