aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--conf/modules.d/redis.conf1
-rw-r--r--lualib/lua_redis.lua37
-rw-r--r--lualib/rspamadm/configwizard.lua16
-rw-r--r--lualib/rspamadm/fuzzy_convert.lua34
-rw-r--r--src/libserver/fuzzy_backend/fuzzy_backend_redis.c26
-rw-r--r--src/libserver/redis_pool.cxx53
-rw-r--r--src/libserver/redis_pool.h3
-rw-r--r--src/libstat/backends/redis_backend.c21
-rw-r--r--src/libstat/learn_cache/redis_cache.c21
-rw-r--r--src/lua/lua_redis.c17
-rw-r--r--src/plugins/lua/bimi.lua9
-rw-r--r--src/rspamadm/fuzzy_convert.c8
-rw-r--r--src/rspamadm/stat_convert.c9
13 files changed, 212 insertions, 43 deletions
diff --git a/conf/modules.d/redis.conf b/conf/modules.d/redis.conf
index eb430cbb1..24948b150 100644
--- a/conf/modules.d/redis.conf
+++ b/conf/modules.d/redis.conf
@@ -19,6 +19,7 @@ redis {
#disabled_modules = ["ratelimit"]; # List of modules that should not use redis from this section
#timeout = 1s;
#db = "0";
+ #username = "some_username";
#password = "some_password";
.include(try=true,priority=5) "${DBDIR}/dynamic/redis.conf"
.include(try=true,priority=1,duplicate=merge) "$LOCAL_CONFDIR/local.d/redis.conf"
diff --git a/lualib/lua_redis.lua b/lualib/lua_redis.lua
index b03160bb0..377541f87 100644
--- a/lualib/lua_redis.lua
+++ b/lualib/lua_redis.lua
@@ -30,12 +30,14 @@ local common_schema = {
database = ts.string:is_optional():describe("Database number"),
dbname = ts.string:is_optional():describe("Database number"),
prefix = ts.string:is_optional():describe("Key prefix"),
+ username = ts.string:is_optional():describe("Username"),
password = ts.string:is_optional():describe("Password"),
expand_keys = ts.boolean:is_optional():describe("Expand keys"),
sentinels = (ts.string + ts.array_of(ts.string)):is_optional():describe("Sentinel servers"),
sentinel_watch_time = (ts.number + ts.string / lutil.parse_time_interval):is_optional():describe("Sentinel watch time"),
sentinel_masters_pattern = ts.string:is_optional():describe("Sentinel masters pattern"),
sentinel_master_maxerrors = (ts.number + ts.string / tonumber):is_optional():describe("Sentinel master max errors"),
+ sentinel_username = ts.string:is_optional():describe("sentinel username"),
sentinel_password = ts.string:is_optional():describe("Sentinel password"),
}
@@ -153,6 +155,7 @@ local function redis_query_sentinel(ev_base, params, initialised)
local ret = rspamd_redis.make_request {
host = addr:get_addr(),
timeout = params.timeout,
+ username = params.sentinel_username,
password = params.sentinel_password,
config = rspamd_config,
ev_base = ev_base,
@@ -184,6 +187,7 @@ local function redis_query_sentinel(ev_base, params, initialised)
timeout = params.timeout,
config = rspamd_config,
ev_base = ev_base,
+ username = params.sentinel_username,
password = params.sentinel_password,
cmd = 'SENTINEL',
args = { 'masters' },
@@ -366,6 +370,9 @@ local function process_redis_opts(options, redis_params)
redis_params['db'] = tostring(options['database'])
end
end
+ if options['username'] and not redis_params['username'] then
+ redis_params['username'] = options['username']
+ end
if options['password'] and not redis_params['password'] then
redis_params['password'] = options['password']
end
@@ -996,6 +1003,10 @@ local function rspamd_redis_make_request(task, redis_params, key, is_write,
end
end
+ if redis_params['username'] then
+ options['username'] = redis_params['username']
+ end
+
if redis_params['password'] then
options['password'] = redis_params['password']
end
@@ -1086,6 +1097,10 @@ local function redis_make_request_taskless(ev_base, cfg, redis_params, key,
end
end
+ if redis_params['username'] then
+ options['username'] = redis_params['username']
+ end
+
if redis_params['password'] then
options['password'] = redis_params['password']
end
@@ -1157,6 +1172,10 @@ local function prepare_redis_call(script)
upstream = s
}
+ if script.redis_params['username'] then
+ cur_opts['username'] = script.redis_params['username']
+ end
+
if script.redis_params['password'] then
cur_opts['password'] = script.redis_params['password']
end
@@ -1497,7 +1516,15 @@ local function redis_connect_sync(redis_params, is_write, key, cfg, ev_base)
if conn then
local need_exec = false
- if redis_params['password'] then
+ if redis_params['username'] then
+ if redis_params['password'] then
+ conn:add_cmd('AUTH', { redis_params['username'], redis_params['password'] })
+ need_exec = true
+ else
+ logger.errx('Redis requires a password when username is supplied')
+ return false, nil, addr
+ end
+ elseif redis_params['password'] then
conn:add_cmd('AUTH', { redis_params['password'] })
need_exec = true
end
@@ -1602,6 +1629,10 @@ exports.request = function(redis_params, attrs, req)
opts.args = req
end
+ if redis_params.username then
+ opts.username = redis_params.username
+ end
+
if redis_params.password then
opts.password = redis_params.password
end
@@ -1701,6 +1732,10 @@ exports.connect = function(redis_params, attrs)
opts.host = addr:get_addr()
opts.timeout = redis_params.timeout
+ if redis_params.username then
+ opts.username = redis_params.username
+ end
+
if redis_params.password then
opts.password = redis_params.password
end
diff --git a/lualib/rspamadm/configwizard.lua b/lualib/rspamadm/configwizard.lua
index 27c358e3b..7bcda5a01 100644
--- a/lualib/rspamadm/configwizard.lua
+++ b/lualib/rspamadm/configwizard.lua
@@ -249,7 +249,21 @@ local function setup_redis(cfg, changes)
redis_params['write_servers'] = ws
end
- if ask_yes_no('Do you have any password set for your Redis?') then
+ if ask_yes_no('Do you have any username set for your Redis?') then
+ local usernm = readline_default("Enter Redis username:", nil)
+
+ if usernm then
+ changes.l['redis.conf']['username'] = usernm
+ redis_params['username'] = usernm
+ end
+
+ local passwd = readline_default("Enter Redis password:", nil)
+
+ if passwd then
+ changes.l['redis.conf']['password'] = passwd
+ redis_params['password'] = passwd
+ end
+ elseif ask_yes_no('Do you have any password set for your Redis?') then
local passwd = readline_default("Enter Redis password:", nil)
if passwd then
diff --git a/lualib/rspamadm/fuzzy_convert.lua b/lualib/rspamadm/fuzzy_convert.lua
index a31baa4e2..67a2664bc 100644
--- a/lualib/rspamadm/fuzzy_convert.lua
+++ b/lualib/rspamadm/fuzzy_convert.lua
@@ -12,7 +12,16 @@ local function connect_redis(server, password, db)
return nil, 'Cannot connect: ' .. err
end
- if password then
+ if username then
+ if password then
+ ret = conn:add_cmd('AUTH', { username, password })
+ if not ret then
+ return nil, 'Cannot queue command'
+ end
+ else
+ return nil, 'Redis requires a password when username is supplied'
+ end
+ else if password then
ret = conn:add_cmd('AUTH', { password })
if not ret then
return nil, 'Cannot queue command'
@@ -28,8 +37,8 @@ local function connect_redis(server, password, db)
return conn, nil
end
-local function send_digests(digests, redis_host, redis_password, redis_db)
- local conn, err = connect_redis(redis_host, redis_password, redis_db)
+local function send_digests(digests, redis_host, redis_username, redis_password, redis_db)
+ local conn, err = connect_redis(redis_host, redis_username, redis_password, redis_db)
if err then
print(err)
return false
@@ -62,8 +71,8 @@ local function send_digests(digests, redis_host, redis_password, redis_db)
return true
end
-local function send_shingles(shingles, redis_host, redis_password, redis_db)
- local conn, err = connect_redis(redis_host, redis_password, redis_db)
+local function send_shingles(shingles, redis_host, redis_username, redis_password, redis_db)
+ local conn, err = connect_redis(redis_host, redis_username, redis_password, redis_db)
if err then
print("Redis error: " .. err)
return false
@@ -95,8 +104,8 @@ local function send_shingles(shingles, redis_host, redis_password, redis_db)
return true
end
-local function update_counters(total, redis_host, redis_password, redis_db)
- local conn, err = connect_redis(redis_host, redis_password, redis_db)
+local function update_counters(total, redis_host, redis_username, redis_password, redis_db)
+ local conn, err = connect_redis(redis_host, redis_username, redis_password, redis_db)
if err then
print(err)
return false
@@ -135,6 +144,7 @@ return function(_, res)
local total_digests = 0
local total_shingles = 0
local lim_batch = 1000 -- Update each 1000 entries
+ local redis_username = res['redis_username']
local redis_password = res['redis_password']
local redis_db = nil
@@ -162,14 +172,14 @@ return function(_, res)
end
end
if num_batch_digests >= lim_batch then
- if not send_digests(digests, res['redis_host'], redis_password, redis_db) then
+ if not send_digests(digests, res['redis_host'], redis_username, redis_password, redis_db) then
return
end
num_batch_digests = 0
digests = {}
end
if num_batch_shingles >= lim_batch then
- if not send_shingles(shingles, res['redis_host'], redis_password, redis_db) then
+ if not send_shingles(shingles, res['redis_host'], redis_username, redis_password, redis_db) then
return
end
num_batch_shingles = 0
@@ -177,12 +187,12 @@ return function(_, res)
end
end
if digests[1] then
- if not send_digests(digests, res['redis_host'], redis_password, redis_db) then
+ if not send_digests(digests, res['redis_host'], redis_username, redis_password, redis_db) then
return
end
end
if shingles[1] then
- if not send_shingles(shingles, res['redis_host'], redis_password, redis_db) then
+ if not send_shingles(shingles, res['redis_host'], redis_username, redis_password, redis_db) then
return
end
end
@@ -191,7 +201,7 @@ return function(_, res)
'Migrated %d digests and %d shingles',
total_digests, total_shingles
)
- if not update_counters(total_digests, res['redis_host'], redis_password, redis_db) then
+ if not update_counters(total_digests, res['redis_host'], redis_username, redis_password, redis_db) then
message = message .. ' but failed to update counters'
end
print(message)
diff --git a/src/libserver/fuzzy_backend/fuzzy_backend_redis.c b/src/libserver/fuzzy_backend/fuzzy_backend_redis.c
index 9b5b3bc02..7ab7ca63e 100644
--- a/src/libserver/fuzzy_backend/fuzzy_backend_redis.c
+++ b/src/libserver/fuzzy_backend/fuzzy_backend_redis.c
@@ -52,6 +52,7 @@ INIT_LOG_MODULE(fuzzy_redis)
struct rspamd_fuzzy_backend_redis {
lua_State *L;
const gchar *redis_object;
+ const gchar *username;
const gchar *password;
const gchar *dbname;
gchar *id;
@@ -256,6 +257,14 @@ rspamd_fuzzy_backend_init_redis(struct rspamd_fuzzy_backend *bk,
}
lua_pop(L, 1);
+ lua_pushstring(L, "username");
+ lua_gettable(L, -2);
+ if (lua_type(L, -1) == LUA_TSTRING) {
+ backend->username = rspamd_mempool_strdup(cfg->cfg_pool,
+ lua_tostring(L, -1));
+ }
+ lua_pop(L, 1);
+
lua_pushstring(L, "password");
lua_gettable(L, -2);
if (lua_type(L, -1) == LUA_TSTRING) {
@@ -277,6 +286,11 @@ rspamd_fuzzy_backend_init_redis(struct rspamd_fuzzy_backend *bk,
strlen(backend->dbname));
}
+ if (backend->username) {
+ rspamd_cryptobox_hash_update(&st, backend->username,
+ strlen(backend->username));
+ }
+
if (backend->password) {
rspamd_cryptobox_hash_update(&st, backend->password,
strlen(backend->password));
@@ -681,7 +695,8 @@ void rspamd_fuzzy_backend_check_redis(struct rspamd_fuzzy_backend *bk,
addr = rspamd_upstream_addr_next(up);
g_assert(addr != NULL);
session->ctx = rspamd_redis_pool_connect(backend->pool,
- backend->dbname, backend->password,
+ backend->dbname,
+ backend->username, backend->password,
rspamd_inet_address_to_string(addr),
rspamd_inet_address_get_port(addr));
@@ -819,7 +834,8 @@ void rspamd_fuzzy_backend_count_redis(struct rspamd_fuzzy_backend *bk,
addr = rspamd_upstream_addr_next(up);
g_assert(addr != NULL);
session->ctx = rspamd_redis_pool_connect(backend->pool,
- backend->dbname, backend->password,
+ backend->dbname,
+ backend->username, backend->password,
rspamd_inet_address_to_string(addr),
rspamd_inet_address_get_port(addr));
@@ -956,7 +972,8 @@ void rspamd_fuzzy_backend_version_redis(struct rspamd_fuzzy_backend *bk,
addr = rspamd_upstream_addr_next(up);
g_assert(addr != NULL);
session->ctx = rspamd_redis_pool_connect(backend->pool,
- backend->dbname, backend->password,
+ backend->dbname,
+ backend->username, backend->password,
rspamd_inet_address_to_string(addr),
rspamd_inet_address_get_port(addr));
@@ -1527,7 +1544,8 @@ void rspamd_fuzzy_backend_update_redis(struct rspamd_fuzzy_backend *bk,
addr = rspamd_upstream_addr_next(up);
g_assert(addr != NULL);
session->ctx = rspamd_redis_pool_connect(backend->pool,
- backend->dbname, backend->password,
+ backend->dbname,
+ backend->username, backend->password,
rspamd_inet_address_to_string(addr),
rspamd_inet_address_get_port(addr));
diff --git a/src/libserver/redis_pool.cxx b/src/libserver/redis_pool.cxx
index 86ff2adb2..34c09d055 100644
--- a/src/libserver/redis_pool.cxx
+++ b/src/libserver/redis_pool.cxx
@@ -62,6 +62,7 @@ struct redis_pool_connection {
explicit redis_pool_connection(redis_pool *_pool,
redis_pool_elt *_elt,
const std::string &db,
+ const std::string &username,
const std::string &password,
struct redisAsyncContext *_ctx);
@@ -87,6 +88,7 @@ class redis_pool_elt {
std::list<redis_pool_connection_ptr> terminating;
std::string ip;
std::string db;
+ std::string username;
std::string password;
int port;
redis_pool_key_t key;
@@ -100,16 +102,20 @@ public:
redis_pool_elt(redis_pool_elt &&other) = default;
explicit redis_pool_elt(redis_pool *_pool,
- const gchar *_db, const gchar *_password,
+ const gchar *_db, const gchar *_username,
+ const gchar *_password,
const char *_ip, int _port)
: pool(_pool), ip(_ip), port(_port),
- key(redis_pool_elt::make_key(_db, _password, _ip, _port))
+ key(redis_pool_elt::make_key(_db, _username, _password, _ip, _port))
{
is_unix = ip[0] == '.' || ip[0] == '/';
if (_db) {
db = _db;
}
+ if( _username ) {
+ username = _username;
+ }
if (_password) {
password = _password;
}
@@ -144,8 +150,8 @@ public:
conn->elt_pos = std::prev(std::end(terminating));
}
- inline static auto make_key(const gchar *db, const gchar *password,
- const char *ip, int port) -> redis_pool_key_t
+ inline static auto make_key(const gchar *db, const gchar *username,
+ const gchar *password, const char *ip, int port) -> redis_pool_key_t
{
rspamd_cryptobox_fast_hash_state_t st;
@@ -154,6 +160,9 @@ public:
if (db) {
rspamd_cryptobox_fast_hash_update(&st, db, strlen(db));
}
+ if (username) {
+ rspamd_cryptobox_fast_hash_update(&st, username, strlen(username));
+ }
if (password) {
rspamd_cryptobox_fast_hash_update(&st, password, strlen(password));
}
@@ -232,8 +241,8 @@ public:
cfg = _cfg;
}
- auto new_connection(const gchar *db, const gchar *password,
- const char *ip, int port) -> redisAsyncContext *;
+ auto new_connection(const gchar *db, const gchar *username,
+ const gchar *password, const char *ip, int port) -> redisAsyncContext *;
auto release_connection(redisAsyncContext *ctx,
enum rspamd_redis_pool_release_type how) -> void;
@@ -398,6 +407,7 @@ auto redis_pool_connection::schedule_timeout() -> void
redis_pool_connection::redis_pool_connection(redis_pool *_pool,
redis_pool_elt *_elt,
const std::string &db,
+ const std::string &username,
const std::string &password,
struct redisAsyncContext *_ctx)
: ctx(_ctx), elt(_elt), pool(_pool)
@@ -413,7 +423,18 @@ redis_pool_connection::redis_pool_connection(redis_pool *_pool,
redisLibevAttach(pool->event_loop, ctx);
redisAsyncSetDisconnectCallback(ctx, redis_pool_connection::redis_on_disconnect);
- if (!password.empty()) {
+ if (!username.empty()) {
+ if (!password.empty()) {
+ redisAsyncCommand(ctx, nullptr, nullptr,
+ "AUTH %s %s", username.c_str(), password.c_str());
+ }
+ else {
+ msg_err("Redis requires a password when username is supplied");
+ redisAsyncFree(ctx);
+ return nullptr;
+ }
+ }
+ else if (!password.empty()) {
redisAsyncCommand(ctx, nullptr, nullptr,
"AUTH %s", password.c_str());
}
@@ -464,7 +485,7 @@ auto redis_pool_elt::new_connection() -> redisAsyncContext *
auto *nctx = redis_async_new();
if (nctx) {
active.emplace_front(std::make_unique<redis_pool_connection>(pool, this,
- db.c_str(), password.c_str(), nctx));
+ db.c_str(), username.c_str(), password.c_str(), nctx));
active.front()->elt_pos = active.begin();
}
@@ -475,7 +496,7 @@ auto redis_pool_elt::new_connection() -> redisAsyncContext *
auto *nctx = redis_async_new();
if (nctx) {
active.emplace_front(std::make_unique<redis_pool_connection>(pool, this,
- db.c_str(), password.c_str(), nctx));
+ db.c_str(), username.c_str(), password.c_str(), nctx));
active.front()->elt_pos = active.begin();
}
@@ -485,12 +506,12 @@ auto redis_pool_elt::new_connection() -> redisAsyncContext *
RSPAMD_UNREACHABLE;
}
-auto redis_pool::new_connection(const gchar *db, const gchar *password,
- const char *ip, int port) -> redisAsyncContext *
+auto redis_pool::new_connection(const gchar *db, const gchar *username,
+ const gchar *password, const char *ip, int port) -> redisAsyncContext *
{
if (!wanna_die) {
- auto key = redis_pool_elt::make_key(db, password, ip, port);
+ auto key = redis_pool_elt::make_key(db, username, password, ip, port);
auto found_elt = elts_by_key.find(key);
if (found_elt != elts_by_key.end()) {
@@ -501,7 +522,7 @@ auto redis_pool::new_connection(const gchar *db, const gchar *password,
else {
/* Need to create a pool */
auto nelt = elts_by_key.try_emplace(key,
- this, db, password, ip, port);
+ this, db, username, password, ip, port);
return nelt.first->second.new_connection();
}
@@ -583,13 +604,13 @@ void rspamd_redis_pool_config(void *p,
struct redisAsyncContext *
rspamd_redis_pool_connect(void *p,
- const gchar *db, const gchar *password,
- const char *ip, int port)
+ const gchar *db, const gchar *username,
+ const gchar *password, const char *ip, int port)
{
g_assert(p != NULL);
auto *pool = reinterpret_cast<class rspamd::redis_pool *>(p);
- return pool->new_connection(db, password, ip, port);
+ return pool->new_connection(db, username, password, ip, port);
}
diff --git a/src/libserver/redis_pool.h b/src/libserver/redis_pool.h
index 339bf5f53..ecdaa0f85 100644
--- a/src/libserver/redis_pool.h
+++ b/src/libserver/redis_pool.h
@@ -45,6 +45,7 @@ void rspamd_redis_pool_config(void *pool,
* Create or reuse the specific redis connection
* @param pool
* @param db
+ * @param username
* @param password
* @param ip
* @param port
@@ -52,7 +53,7 @@ void rspamd_redis_pool_config(void *pool,
*/
struct redisAsyncContext *rspamd_redis_pool_connect(
void *pool,
- const gchar *db, const gchar *password,
+ const gchar *db, const gchar *username, const gchar *password,
const char *ip, int port);
enum rspamd_redis_pool_release_type {
diff --git a/src/libstat/backends/redis_backend.c b/src/libstat/backends/redis_backend.c
index a0d11bb0d..72ffd6c44 100644
--- a/src/libstat/backends/redis_backend.c
+++ b/src/libstat/backends/redis_backend.c
@@ -45,6 +45,7 @@ struct redis_stat_ctx {
gint conf_ref;
struct rspamd_stat_async_elt *stat_elt;
const gchar *redis_object;
+ const gchar *username;
const gchar *password;
const gchar *dbname;
gdouble timeout;
@@ -363,7 +364,17 @@ gsize rspamd_redis_expand_object(const gchar *pattern,
static void
rspamd_redis_maybe_auth(struct redis_stat_ctx *ctx, redisAsyncContext *redis)
{
- if (ctx->password) {
+ if (ctx->username) {
+ if (ctx->password) {
+ redisAsyncCommand(redis, NULL, NULL, "AUTH %s %s", ctx->username, ctx->password);
+ }
+ else {
+ msg_err("Redis requires a password when username is supplied");
+ redisAsyncFree(ctx);
+ return NULL;
+ }
+ }
+ else if (ctx->password) {
redisAsyncCommand(redis, NULL, NULL, "AUTH %s", ctx->password);
}
if (ctx->dbname) {
@@ -1603,6 +1614,14 @@ rspamd_redis_init(struct rspamd_stat_ctx *ctx,
}
lua_pop(L, 1);
+ lua_pushstring(L, "username");
+ lua_gettable(L, -2);
+ if (lua_type(L, -1) == LUA_TSTRING) {
+ backend->username = rspamd_mempool_strdup(cfg->cfg_pool,
+ lua_tostring(L, -1));
+ }
+ lua_pop(L, 1);
+
lua_pushstring(L, "password");
lua_gettable(L, -2);
if (lua_type(L, -1) == LUA_TSTRING) {
diff --git a/src/libstat/learn_cache/redis_cache.c b/src/libstat/learn_cache/redis_cache.c
index 3026009bc..0bbae8560 100644
--- a/src/libstat/learn_cache/redis_cache.c
+++ b/src/libstat/learn_cache/redis_cache.c
@@ -35,6 +35,7 @@ static const gchar *M = "redis learn cache";
struct rspamd_redis_cache_ctx {
lua_State *L;
struct rspamd_statfile_config *stcf;
+ const gchar *username;
const gchar *password;
const gchar *dbname;
const gchar *redis_object;
@@ -77,7 +78,17 @@ static void
rspamd_redis_cache_maybe_auth(struct rspamd_redis_cache_ctx *ctx,
redisAsyncContext *redis)
{
- if (ctx->password) {
+ if (ctx->username) {
+ if (ctx->password) {
+ redisAsyncCommand(redis, NULL, NULL, "AUTH %s %s", ctx->username, ctx->password);
+ }
+ else {
+ msg_err("Redis requires a password when username is supplied");
+ redisAsyncFree(ctx);
+ return NULL;
+ }
+ }
+ else if (ctx->password) {
redisAsyncCommand(redis, NULL, NULL, "AUTH %s", ctx->password);
}
if (ctx->dbname) {
@@ -328,6 +339,14 @@ rspamd_stat_cache_redis_init(struct rspamd_stat_ctx *ctx,
}
lua_pop(L, 1);
+ lua_pushstring(L, "username");
+ lua_gettable(L, -2);
+ if (lua_type(L, -1) == LUA_TSTRING) {
+ cache_ctx->username = rspamd_mempool_strdup(cfg->cfg_pool,
+ lua_tostring(L, -1));
+ }
+ lua_pop(L, 1);
+
lua_pushstring(L, "password");
lua_gettable(L, -2);
if (lua_type(L, -1) == LUA_TSTRING) {
diff --git a/src/lua/lua_redis.c b/src/lua/lua_redis.c
index 2ac5a47b7..1ad3b3d17 100644
--- a/src/lua/lua_redis.c
+++ b/src/lua/lua_redis.c
@@ -110,9 +110,9 @@ struct lua_redis_userdata {
};
#define msg_debug_lua_redis(...) rspamd_conditional_debug_fast(NULL, NULL, \
- rspamd_lua_redis_log_id, "lua_redis", ud->log_tag, \
- G_STRFUNC, \
- __VA_ARGS__)
+ rspamd_lua_redis_log_id, "lua_redis", ud->log_tag, \
+ G_STRFUNC, \
+ __VA_ARGS__)
INIT_LOG_MODULE(lua_redis)
#define LUA_REDIS_SPECIFIC_REPLIED (1 << 0)
@@ -875,7 +875,7 @@ rspamd_lua_redis_prepare_connection(lua_State *L, gint *pcbref, gboolean is_asyn
struct rspamd_lua_ip *addr = NULL;
struct rspamd_task *task = NULL;
const gchar *host = NULL;
- const gchar *password = NULL, *dbname = NULL, *log_tag = NULL;
+ const gchar *username = NULL, *password = NULL, *dbname = NULL, *log_tag = NULL;
gint cbref = -1;
struct rspamd_config *cfg = NULL;
struct rspamd_async_session *session = NULL;
@@ -970,6 +970,13 @@ rspamd_lua_redis_prepare_connection(lua_State *L, gint *pcbref, gboolean is_asyn
}
lua_pop(L, 1);
+ lua_pushstring(L, "username");
+ lua_gettable(L, -2);
+ if (lua_type(L, -1) == LUA_TSTRING) {
+ username = lua_tostring(L, -1);
+ }
+ lua_pop(L, 1);
+
lua_pushstring(L, "password");
lua_gettable(L, -2);
if (lua_type(L, -1) == LUA_TSTRING) {
@@ -1053,7 +1060,7 @@ rspamd_lua_redis_prepare_connection(lua_State *L, gint *pcbref, gboolean is_asyn
if (ret) {
ud->terminated = 0;
ud->ctx = rspamd_redis_pool_connect(ud->pool,
- dbname, password,
+ dbname, username, password,
rspamd_inet_address_to_string(addr->addr),
rspamd_inet_address_get_port(addr->addr));
diff --git a/src/plugins/lua/bimi.lua b/src/plugins/lua/bimi.lua
index 914484543..5053cc941 100644
--- a/src/plugins/lua/bimi.lua
+++ b/src/plugins/lua/bimi.lua
@@ -263,7 +263,14 @@ local function check_bimi_vmc(task, domain, record)
if redis_params.db then
db = string.format('/%s', redis_params.db)
end
- if redis_params.password then
+ if redis_params.username then
+ if redis_params.password then
+ password = string.format( '%s:%s@', redis_params.username, redis_params.password)
+ else
+ rspamd_logger.errx(task, "Redis requires a password when username is supplied")
+ return
+ end
+ elseif redis_params.password then
password = string.format(':%s@', redis_params.password)
end
local redis_server = string.format('redis://%s%s:%s%s',
diff --git a/src/rspamadm/fuzzy_convert.c b/src/rspamadm/fuzzy_convert.c
index 1b2866b59..5d967a64c 100644
--- a/src/rspamadm/fuzzy_convert.c
+++ b/src/rspamadm/fuzzy_convert.c
@@ -21,6 +21,7 @@
static gchar *source_db = NULL;
static gchar *redis_host = NULL;
static gchar *redis_db = NULL;
+static gchar *redis_username = NULL;
static gchar *redis_password = NULL;
static int64_t fuzzy_expiry = 0;
@@ -46,6 +47,8 @@ static GOptionEntry entries[] = {
"Output redis ip (in format ip:port)", NULL},
{"dbname", 'D', 0, G_OPTION_ARG_STRING, &redis_db,
"Database in redis (should be numeric)", NULL},
+ {"username", 'u', 0, G_OPTION_ARG_STRING, &redis_username,
+ "Username to connect to redis", NULL},
{"password", 'p', 0, G_OPTION_ARG_STRING, &redis_password,
"Password to connect to redis", NULL},
{NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL}};
@@ -63,6 +66,7 @@ rspamadm_fuzzyconvert_help(gboolean full_help, const struct rspamadm_command *cm
"-d: input sqlite\n"
"-h: output redis ip (in format ip:port)\n"
"-D: output redis database\n"
+ "-u: redis username\n";
"-p: redis password\n";
}
else {
@@ -117,6 +121,10 @@ rspamadm_fuzzyconvert(gint argc, gchar **argv, const struct rspamadm_command *cm
ucl_object_insert_key(obj, ucl_object_fromint(fuzzy_expiry),
"expiry", 0, false);
+ if (redis_username) {
+ ucl_object_insert_key(obj, ucl_object_fromstring(redis_username),
+ "redis_username", 0, false);
+ }
if (redis_password) {
ucl_object_insert_key(obj, ucl_object_fromstring(redis_password),
"redis_password", 0, false);
diff --git a/src/rspamadm/stat_convert.c b/src/rspamadm/stat_convert.c
index ba2c4efb9..0741279aa 100644
--- a/src/rspamadm/stat_convert.c
+++ b/src/rspamadm/stat_convert.c
@@ -34,6 +34,7 @@ static gchar *cache_db = NULL;
/* Outputs */
static gchar *redis_host = NULL;
static gchar *redis_db = NULL;
+static gchar *redis_username = NULL;
static gchar *redis_password = NULL;
static gboolean reset_previous = FALSE;
@@ -70,6 +71,8 @@ static GOptionEntry entries[] = {
"Input learn cache", NULL},
{"redis-host", 'h', 0, G_OPTION_ARG_STRING, &redis_host,
"Output redis ip (in format ip:port)", NULL},
+ {"redis-username", 'u', 0, G_OPTION_ARG_STRING, &redis_username,
+ "Username to connect to redis", NULL},
{"redis-password", 'p', 0, G_OPTION_ARG_STRING, &redis_password,
"Password to connect to redis", NULL},
{"redis-db", 'd', 0, G_OPTION_ARG_STRING, &redis_db,
@@ -92,6 +95,7 @@ rspamadm_statconvert_help(gboolean full_help, const struct rspamadm_command *cmd
"** Or specify options directly **\n"
"--redis-host: output redis ip (in format ip:port)\n"
"--redis-db: output redis database\n"
+ "--redis-username: redis username\n"
"--redis-password: redis password\n"
"--cache: sqlite3 file for learn cache\n"
"--spam-db: sqlite3 input file for spam data\n"
@@ -229,6 +233,11 @@ rspamadm_statconvert(gint argc, gchar **argv, const struct rspamadm_command *cmd
"dbname", 0, false);
}
+ if (redis_username) {
+ ucl_object_insert_key(redis, ucl_object_fromstring(redis_username),
+ "username", 0, false);
+ }
+
if (redis_password) {
ucl_object_insert_key(redis, ucl_object_fromstring(redis_password),
"password", 0, false);