Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: Support password auth for plugin limit-count-redis #1150

Merged
merged 2 commits into from
Feb 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ matrix:
include:
- os: linux
services:
- redis-server
- docker
env: OSNAME=linux_openresty
- os: osx
env: OSNAME=osx_openresty
Expand All @@ -21,7 +21,7 @@ matrix:
- /usr/local/Homebrew
- os: linux
services:
- redis-server
- docker
env: OSNAME=linux_tengine
- os: linux
env: OSNAME=linux_apisix_luarocks
Expand Down Expand Up @@ -51,6 +51,8 @@ before_cache:
- brew cleanup

before_install:
- docker pull redis:3.0-alpine
- docker run --rm -itd -p 6379:6379 --name apisix_redis redis:3.0-alpine
- echo $OSNAME
- $PWD/.travis/${OSNAME}_runner.sh before_install

Expand Down
5 changes: 4 additions & 1 deletion lua/apisix/plugins/limit-count.lua
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ local schema = {
redis_port = {
type = "integer", minimum = 1
},
redis_password = {
type = "string", minLength = 0
},
redis_timeout = {
type = "integer", minimum = 1
},
Expand Down Expand Up @@ -122,7 +125,7 @@ function _M.access(conf, ctx)
end

core.log.error("failed to limit req: ", err)
return 500
return 500, {error_msg = "failed to limit count: ", err}
end

core.response.set_header("X-RateLimit-Limit", conf.count,
Expand Down
14 changes: 14 additions & 0 deletions lua/apisix/plugins/limit-count/limit-count-redis.lua
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,20 @@ function _M.incoming(self, key)
return false, err
end

local count
count, err = red:get_reused_times()
if 0 == count then
if conf.redis_password and conf.redis_password ~= '' then
local ok, err = red:auth(conf.redis_password)
if not ok then
return nil, err
end
end
elseif err then
-- core.log.info(" err: ", err)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return nil, err

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return nil, err

OK

return nil, err
end

local limit = self.limit
local window = self.window
local remaining
Expand Down
234 changes: 234 additions & 0 deletions t/plugin/limit-count-redis.t
Original file line number Diff line number Diff line change
Expand Up @@ -209,3 +209,237 @@ passed
[404, 503, 404, 503, 503]
--- no_error_log
[error]



=== TEST 6: set route, with redis host, port and right password
--- config
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
-- set redis password
local redis = require "resty.redis"

local red = redis:new()

red:set_timeout(1000) -- 1 sec

local ok, err = red:connect("127.0.0.1", 6379)
if not ok then
ngx.say("failed to connect: ", err)
return
end

-- for get_reused_times works
-- local ok, err = red:set_keepalive(10000, 100)
-- if not ok then
-- ngx.say("failed to set keepalive: ", err)
-- return
-- end

local count
count, err = red:get_reused_times()
if 0 == count then
local res, err = red:eval([[
local key = 'requirepass'
local value = "foobared"
-- redis.replicate_commands()
local val = redis.pcall('CONFIG', 'SET', key, value)
return val
]], 0)
--
if not res then
ngx.say("failed to set: ", err)
return
end
elseif err then
-- ngx.say("already set requirepass done: ", err)
return
end

local code, body = t('/apisix/admin/routes/1',
ngx.HTTP_PUT,
[[{
"uri": "/hello",
"plugins": {
"limit-count": {
"count": 2,
"time_window": 60,
"rejected_code": 503,
"key": "remote_addr",
"policy": "redis",
"redis_host": "127.0.0.1",
"redis_port": 6379,
"redis_timeout": 1001,
"redis_password": "foobared"
}
},
"upstream": {
"nodes": {
"127.0.0.1:1980": 1
},
"type": "roundrobin"
}
}]]
)

if code >= 300 then
ngx.status = code
end
ngx.say(body)
}
}
--- request
GET /t
--- response_body
passed
--- no_error_log
[error]



=== TEST 7: up the limit
--- pipelined_requests eval
["GET /hello", "GET /hello", "GET /hello", "GET /hello"]
--- error_code eval
[200, 200, 503, 503]
--- no_error_log
[error]



=== TEST 8: up the limit
--- pipelined_requests eval
["GET /hello1", "GET /hello", "GET /hello2", "GET /hello", "GET /hello"]
--- error_code eval
[404, 503, 404, 503, 503]
--- no_error_log
[error]



=== TEST 9: set route, with redis host, port and wrong password
--- config
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
local code, body = t('/apisix/admin/routes/1',
ngx.HTTP_PUT,
[[{
"plugins": {
"limit-count": {
"count": 2,
"time_window": 60,
"rejected_code": 503,
"key": "remote_addr",
"policy": "redis",
"redis_host": "127.0.0.1",
"redis_port": 6379,
"redis_timeout": 1001,
"redis_password": "WRONG_foobared"
}
},
"upstream": {
"nodes": {
"127.0.0.1:1980": 1
},
"type": "roundrobin"
},
"uri": "/hello_new"
}]]
)

if code >= 300 then
ngx.status = code
end
ngx.print(body)
}
}
--- request
GET /t
--- error_code eval
200
--- no_error_log
[error]



=== TEST 10: request for TEST 9
--- request
GET /hello_new
--- error_code eval
500
--- response_body
{"1":"ERR invalid password","error_msg":"failed to limit count: "}
--- error_log
failed to limit req: ERR invalid password



=== TEST 11: multi request for TEST 9
--- pipelined_requests eval
["GET /hello_new", "GET /hello1", "GET /hello1", "GET /hello_new"]
--- error_code eval
[500, 404, 404, 500]



=== TEST 12: restore redis password to ''
--- config
location /t {
content_by_lua_block {
local t = require("lib.test_admin").test
-- set redis password
local redis = require "resty.redis"

local red = redis:new()

red:set_timeout(1000) -- 1 sec

local ok, err = red:connect("127.0.0.1", 6379)
if not ok then
ngx.say("failed to connect: ", err)
return
end

-- for get_reused_times works
-- local ok, err = red:set_keepalive(10000, 100)
-- if not ok then
-- ngx.say("failed to set keepalive: ", err)
-- return
-- end

local count
count, err = red:get_reused_times()
if 0 == count then
local redis_password = "foobared"
if redis_password and redis_password ~= '' then
local ok, err = red:auth(redis_password)
if not ok then
return nil, err
end
end
local res, err = red:eval([[
local key = 'requirepass'
local value = ''
-- redis.replicate_commands()
local val = redis.pcall('CONFIG', 'SET', key, value)
return val
]], 0)
--
if not res then
ngx.say("failed to set: ", err)
return
end
elseif err then
-- ngx.say("already set requirepass done: ", err)
return
end
}
}
--- request
GET /t
--- error_code eval
200
--- no_error_log
[error]