Skip to content

Commit

Permalink
feature: Support password auth for plugin limit-count-redis (#1150)
Browse files Browse the repository at this point in the history
  • Loading branch information
totemofwolf authored Feb 24, 2020
1 parent 1747252 commit 5b1a47a
Show file tree
Hide file tree
Showing 4 changed files with 256 additions and 3 deletions.
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)
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]

0 comments on commit 5b1a47a

Please sign in to comment.