@@ -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" |
@@ -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 |
@@ -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 |
@@ -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) |
@@ -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)); | |||
@@ -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); | |||
} | |||
@@ -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 { |
@@ -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) { |
@@ -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) { |
@@ -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)); | |||
@@ -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', |
@@ -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); |
@@ -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); |