Merge pull request #10102 from Icinga/icingadb-redis-username

Icinga DB: Config no_user_modify and Support Redis username authentication
This commit is contained in:
Julian Brost 2024-11-12 17:04:20 +01:00 committed by GitHub
commit 67175c43c0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 33 additions and 22 deletions

View File

@ -1387,7 +1387,9 @@ Configuration Attributes:
host | String | **Optional.** Redis host. Defaults to `127.0.0.1`.
port | Number | **Optional.** Redis port. Defaults to `6380` since the Redis server provided by the `icingadb-redis` package listens on that port.
path | String | **Optional.** Redis unix socket path. Can be used instead of `host` and `port` attributes.
username | String | **Optional.** Redis auth username. Only possible if Redis ACLs are used. Requires `password` to be set as well.
password | String | **Optional.** Redis auth password.
db\_index | Number | **Optional.** Redis logical database by its number. Defaults to `0`.
enable\_tls | Boolean | **Optional.** Whether to use TLS.
cert\_path | String | **Optional.** Path to the certificate.
key\_path | String | **Optional.** Path to the private key.

View File

@ -47,6 +47,11 @@ void IcingaDB::Validate(int types, const ValidationUtils& utils)
if (!(types & FAConfig))
return;
if (!GetUsername().IsEmpty() && GetPassword().IsEmpty()) {
BOOST_THROW_EXCEPTION(ValidationError(this, std::vector<String>(),
"Redis password must be set, if username is provided."));
}
if (GetEnableTls() && GetCertPath().IsEmpty() != GetKeyPath().IsEmpty()) {
BOOST_THROW_EXCEPTION(ValidationError(this, std::vector<String>(), "Either both a client certificate (cert_path) and its private key (key_path) or none of them must be given."));
}
@ -76,7 +81,7 @@ void IcingaDB::Start(bool runtimeCreated)
m_WorkQueue.SetExceptionCallback([this](boost::exception_ptr exp) { ExceptionHandler(std::move(exp)); });
m_Rcon = new RedisConnection(GetHost(), GetPort(), GetPath(), GetPassword(), GetDbIndex(),
m_Rcon = new RedisConnection(GetHost(), GetPort(), GetPath(), GetUsername(), GetPassword(), GetDbIndex(),
GetEnableTls(), GetInsecureNoverify(), GetCertPath(), GetKeyPath(), GetCaPath(), GetCrlPath(),
GetTlsProtocolmin(), GetCipherList(), GetConnectTimeout(), GetDebugInfo());
m_RconLocked.store(m_Rcon);
@ -86,7 +91,7 @@ void IcingaDB::Start(bool runtimeCreated)
if (!ctype)
continue;
RedisConnection::Ptr con = new RedisConnection(GetHost(), GetPort(), GetPath(), GetPassword(), GetDbIndex(),
RedisConnection::Ptr con = new RedisConnection(GetHost(), GetPort(), GetPath(), GetUsername(), GetPassword(), GetDbIndex(),
GetEnableTls(), GetInsecureNoverify(), GetCertPath(), GetKeyPath(), GetCaPath(), GetCrlPath(),
GetTlsProtocolmin(), GetCipherList(), GetConnectTimeout(), GetDebugInfo(), m_Rcon);

View File

@ -12,36 +12,37 @@ class IcingaDB : ConfigObject
{
activation_priority 100;
[config] String host {
[config, no_user_modify] String host {
default {{{ return "127.0.0.1"; }}}
};
[config] int port {
[config, no_user_modify] int port {
default {{{ return 6380; }}}
};
[config] String path;
[config, no_user_modify] String path;
[config, no_user_modify] String username;
[config, no_user_view, no_user_modify] String password;
[config] int db_index;
[config, no_user_modify] int db_index;
[config] bool enable_tls {
[config, no_user_modify] bool enable_tls {
default {{{ return false; }}}
};
[config] bool insecure_noverify {
[config, no_user_modify] bool insecure_noverify {
default {{{ return false; }}}
};
[config] String cert_path;
[config] String key_path;
[config] String ca_path;
[config] String crl_path;
[config] String cipher_list {
[config, no_user_modify] String cert_path;
[config, no_user_modify] String key_path;
[config, no_user_modify] String ca_path;
[config, no_user_modify] String crl_path;
[config, no_user_modify] String cipher_list {
default {{{ return DEFAULT_TLS_CIPHERS; }}}
};
[config] String tls_protocolmin {
[config, no_user_modify] String tls_protocolmin {
default {{{ return DEFAULT_TLS_PROTOCOLMIN; }}}
};
[config] double connect_timeout {
[config, no_user_modify] double connect_timeout {
default {{{ return DEFAULT_CONNECT_TIMEOUT; }}}
};

View File

@ -30,18 +30,18 @@ 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& username, const String& password, int db,
bool useTls, bool insecure, const String& certPath, const String& keyPath, const String& caPath, const String& crlPath,
const String& tlsProtocolmin, const String& cipherList, double connectTimeout, DebugInfo di, const RedisConnection::Ptr& parent)
: RedisConnection(IoEngine::Get().GetIoContext(), host, port, path, password, db,
: RedisConnection(IoEngine::Get().GetIoContext(), host, port, path, username, password, db,
useTls, insecure, certPath, keyPath, caPath, crlPath, tlsProtocolmin, cipherList, connectTimeout, std::move(di), parent)
{
}
RedisConnection::RedisConnection(boost::asio::io_context& io, String host, int port, String path, String password,
RedisConnection::RedisConnection(boost::asio::io_context& io, String host, int port, String path, String username, String password,
int db, bool useTls, bool insecure, String certPath, String keyPath, String caPath, String crlPath,
String tlsProtocolmin, String cipherList, double connectTimeout, DebugInfo di, const RedisConnection::Ptr& parent)
: m_Host(std::move(host)), m_Port(port), m_Path(std::move(path)), m_Password(std::move(password)),
: m_Host(std::move(host)), m_Port(port), m_Path(std::move(path)), m_Username(std::move(username)), m_Password(std::move(password)),
m_DbIndex(db), m_CertPath(std::move(certPath)), m_KeyPath(std::move(keyPath)), m_Insecure(insecure),
m_CaPath(std::move(caPath)), m_CrlPath(std::move(crlPath)), m_TlsProtocolmin(std::move(tlsProtocolmin)),
m_CipherList(std::move(cipherList)), m_ConnectTimeout(connectTimeout), m_DebugInfo(std::move(di)), m_Connecting(false), m_Connected(false),

View File

@ -84,7 +84,7 @@ namespace icinga
: Config(config), State(state), History(history) { }
};
RedisConnection(const String& host, int port, const String& path, const String& password, int db,
RedisConnection(const String& host, int port, const String& path, const String& username, const String& password, int db,
bool useTls, bool insecure, const String& certPath, const String& keyPath, const String& caPath, const String& crlPath,
const String& tlsProtocolmin, const String& cipherList, double connectTimeout, DebugInfo di, const Ptr& parent = nullptr);
@ -196,7 +196,7 @@ namespace icinga
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 username, String password,
int db, bool useTls, bool insecure, String certPath, String keyPath, String caPath, String crlPath,
String tlsProtocolmin, String cipherList, double connectTimeout, DebugInfo di, const Ptr& parent);
@ -227,6 +227,7 @@ namespace icinga
String m_Path;
String m_Host;
int m_Port;
String m_Username;
String m_Password;
int m_DbIndex;
@ -457,7 +458,9 @@ void RedisConnection::Handshake(StreamPtr& strm, boost::asio::yield_context& yc)
// Trigger NOAUTH
WriteRESP(*strm, {"PING"}, yc);
} else {
if (!m_Password.IsEmpty()) {
if (!m_Username.IsEmpty()) {
WriteRESP(*strm, {"AUTH", m_Username, m_Password}, yc);
} else if (!m_Password.IsEmpty()) {
WriteRESP(*strm, {"AUTH", m_Password}, yc);
}