Current Behavior
When we use multiple rate-limiting plugins that share the same Redis address but connect to different databases or use different credentials (username/password), connection reuse can lead to getting a connection with the wrong database or user/password.
For example, assuming I configure two such limit-count plugins on a routes,
"limit-count": {
"count": 1,
"time_window": 30,
"rejected_code": 429,
"key": "remote_addr",
"policy": "redis",
"redis_host": "redis1.local",
"redis_port": 6379,
"redis_database": 1
}
"limit-count": {
"count": 1,
"time_window": 30,
"rejected_code": 429,
"key": "remote_addr",
"policy": "redis",
"redis_host": "redis1.local",
"redis_port": 6379,
"redis_database": 2
}
I will randomly get connections from the pool that use the wrong database. The core issue here is that authentication and database selection are executed only during the initial connect, after which the connection is placed back into the pool.
To fix this problem, we could re-authenticate and re-select the database whenever we detect that the connection's current credentials or database don't match the required ones. Alternatively – which in my opinion is a better approach – we can introduce separate connection pools for such connections. We can achieve this by implementing a function that generates a pool name based on the username, password, and database number,
local function get_pool_name(conf)
local database = conf.redis_database or 0
local connection_string = conf.redis_host .. ":" .. conf.redis_port .. "/" .. database
if conf.redis_username and conf.redis_username ~= "" then
local password = conf.redis_password or ""
local hashed_credentials = ngx.md5(conf.redis_username .. ":" .. password)
return hashed_credentials .. "@" .. connection_string
else
return connection_string
end
end
and then use it in sock_opts.
local sock_opts = {
...
pool = get_pool_name(conf)
}
Expected Behavior
Redis commands must be executed using a connection configured with the appropriate user, password, and database ID, in accordance with the plugin's configuration.
Error Logs
No response
Steps to Reproduce
No description needed.
Environment
It's irrelevant.
Current Behavior
When we use multiple rate-limiting plugins that share the same Redis address but connect to different databases or use different credentials (username/password), connection reuse can lead to getting a connection with the wrong database or user/password.
For example, assuming I configure two such limit-count plugins on a routes,
I will randomly get connections from the pool that use the wrong database. The core issue here is that authentication and database selection are executed only during the initial connect, after which the connection is placed back into the pool.
To fix this problem, we could re-authenticate and re-select the database whenever we detect that the connection's current credentials or database don't match the required ones. Alternatively – which in my opinion is a better approach – we can introduce separate connection pools for such connections. We can achieve this by implementing a function that generates a pool name based on the username, password, and database number,
and then use it in sock_opts.
Expected Behavior
Redis commands must be executed using a connection configured with the appropriate user, password, and database ID, in accordance with the plugin's configuration.
Error Logs
No response
Steps to Reproduce
No description needed.
Environment
It's irrelevant.