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

Auto-pull-request-on-2021-01-29 #249

Open
wants to merge 26 commits into
base: dev/v4.3.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
3d46ac1
perf(replace httpc): replace httpc with gun, improve performance and …
Dec 4, 2020
fc77af9
fix(flush gun stream): fix the issue that flush only one message
Dec 4, 2020
fd54573
fix(hostname): fix the issue that host cannot be parse
Dec 8, 2020
6657729
fix: fix undefined function
Dec 9, 2020
100b8e6
fix: fix spelling mistake
Dec 9, 2020
d561702
feature: support hot upgrade of authentication using http server
Dec 11, 2020
fbf4f0f
fix: add emqx_auth_http.appup.src
Dec 11, 2020
a453611
improve: simplified upgrade script
Dec 11, 2020
e26417d
fix(url without path): add handle of url without path
Dec 14, 2020
8942648
fix(http header): bad http header key
Dec 17, 2020
dd707c3
fix(hot upgrade): update hot upgrade script
Dec 23, 2020
a94a9e0
fix(http header): fix bad path and header
Dec 23, 2020
c284e2f
Auto-pull-request-on-2021-01-16 (#244)
Rory-Z Jan 16, 2021
e4ee8b1
fix(http): fix request dropped when connection closed by keepalive
Jan 28, 2021
5255e88
fix(http): update retry handling
Jan 28, 2021
4d01362
fix(http keepalive): update upgrade script
Jan 28, 2021
09cdc75
fix(only acl): fix the issue that only acl can not be enabled
Mar 10, 2021
3d49302
chore(more logs): add more logs for getting the cause of the error be…
Apr 15, 2021
834abf4
chore(upgrade): add upgrade script
Apr 15, 2021
7936d58
fix(upgrade script): fix upgrade script
Apr 15, 2021
40da87f
fix(upgrade): fix upgrade script
Apr 15, 2021
805e32f
chore(dependency): Update cowlib to 2.8.0
k32 Apr 30, 2021
2f40ec9
Merge pull request #260 from emqx/dev/k32/update-cowlib
k32 Apr 30, 2021
1b7c191
Fixed 2 little typos
LautaroJayat May 10, 2021
69770d8
Merge pull request #261 from LautaroJayat/patch-1
k32 May 10, 2021
325f1b5
chore: rename EMQ X -> EMQX
HJianBo Dec 27, 2023
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
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
emqx_auth_http
==============

EMQ X HTTP Auth/ACL Plugin
EMQX HTTP Auth/ACL Plugin

Build
-----
Expand Down Expand Up @@ -96,5 +96,4 @@ Apache License Version 2.0
Author
------

EMQ X Team.

EMQX Team.
24 changes: 12 additions & 12 deletions etc/emqx_auth_http.conf
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
##
## Value: URL
##
## Examples: http://127.0.0.1:8991/mqtt/auth, https://[::1]:8991/mqtt/auth
auth.http.auth_req = http://127.0.0.1:8991/mqtt/auth
## Examples: http://127.0.0.1:80/mqtt/auth, https://[::1]:80/mqtt/auth
auth.http.auth_req = http://127.0.0.1:80/mqtt/auth

## Value: post | get
auth.http.auth_req.method = post
Expand Down Expand Up @@ -39,13 +39,13 @@ auth.http.auth_req.params = clientid=%c,username=%u,password=%P
##
## Value: URL
##
## Examples: http://127.0.0.1:8991/mqtt/superuser, https://[::1]:8991/mqtt/superuser
#auth.http.super_req = http://127.0.0.1:8991/mqtt/superuser
## Examples: http://127.0.0.1:80/mqtt/superuser, https://[::1]:80/mqtt/superuser
#auth.http.super_req = http://127.0.0.1:80/mqtt/superuser

## Value: post | get
#auth.http.super_req.method = post

## It only works when method=pos
## It only works when method=post
## Value: json | x-www-form-urlencoded
#auth.http.super_req.content_type = x-www-form-urlencoded

Expand All @@ -69,8 +69,8 @@ auth.http.auth_req.params = clientid=%c,username=%u,password=%P
##
## Value: URL
##
## Examples: http://127.0.0.1:8991/mqtt/acl, https://[::1]:8991/mqtt/acl
auth.http.acl_req = http://127.0.0.1:8991/mqtt/acl
## Examples: http://127.0.0.1:80/mqtt/acl, https://[::1]:80/mqtt/acl
auth.http.acl_req = http://127.0.0.1:80/mqtt/acl

## Value: post | get
auth.http.acl_req.method = get
Expand Down Expand Up @@ -101,23 +101,23 @@ auth.http.acl_req.params = access=%A,username=%u,clientid=%c,ipaddr=%a,topic=%t,
## -m: minute, e.g. '5m' for 5 minutes
## -s: second, e.g. '30s' for 30 seconds
##
## Default: 0
## auth.http.request.timeout = 0
## Default: 5s
## auth.http.request.timeout = 5s

## Connection time-out time, used during the initial request
## when the client is connecting to the server
##
## Value: Duration
##
## Default is same with the timeout option
## auth.http.request.connect_timeout = 0
## auth.http.request.connect_timeout = 5

## Re-send http reuqest times
## Re-send http request times
##
## Value: integer
##
## Default: 3
auth.http.request.retry_times = 3
auth.http.request.retry_times = 5

## The interval for re-sending the http request
##
Expand Down
2 changes: 1 addition & 1 deletion include/emqx_auth_http.hrl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

-define(APP, emqx_auth_http).

-record(http_request, {method = post, content_type, url, params, options = []}).
-record(http_request, {method = post, path, headers, params, request_timeout}).

-record(auth_metrics, {
success = 'client.auth.success',
Expand Down
78 changes: 41 additions & 37 deletions priv/emqx_auth_http.schema
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,21 @@

{mapping, "auth.http.auth_req.content_type", "emqx_auth_http.auth_req", [
{default, 'x-www-form-urlencoded'},
{datatype, {enum, [json, 'x-www-form-urlencoded']}}
{datatype, {enum, ['json', 'x-www-form-urlencoded']}}
]}.

{mapping, "auth.http.auth_req.params", "emqx_auth_http.auth_req", [
{datatype, string}
]}.

{translation, "emqx_auth_http.auth_req", fun(Conf) ->
case cuttlefish:conf_get("auth.http.auth_req", Conf) of
case cuttlefish:conf_get("auth.http.auth_req", Conf, undefined) of
undefined -> cuttlefish:unset();
Url ->
Params = cuttlefish:conf_get("auth.http.auth_req.params", Conf),
[{url, Url},
{method, cuttlefish:conf_get("auth.http.auth_req.method", Conf)},
{content_type, cuttlefish:conf_get("auth.http.auth_req.content_type", Conf)},
{content_type, list_to_binary("application/" ++ atom_to_list(cuttlefish:conf_get("auth.http.auth_req.content_type", Conf)))},
{params, [list_to_tuple(string:tokens(S, "=")) || S <- string:tokens(Params, ",")]}]
end
end}.
Expand All @@ -41,7 +41,7 @@ end}.

{mapping, "auth.http.super_req.content_type", "emqx_auth_http.super_req", [
{default, 'x-www-form-urlencoded'},
{datatype, {enum, [json, 'x-www-form-urlencoded']}}
{datatype, {enum, ['json', 'x-www-form-urlencoded']}}
]}.

{mapping, "auth.http.super_req.params", "emqx_auth_http.super_req", [
Expand All @@ -53,7 +53,7 @@ end}.
undefined -> cuttlefish:unset();
Url -> Params = cuttlefish:conf_get("auth.http.super_req.params", Conf),
[{url, Url}, {method, cuttlefish:conf_get("auth.http.super_req.method", Conf)},
{content_type, cuttlefish:conf_get("auth.http.super_req.content_type", Conf)},
{content_type, list_to_binary("application/" ++ atom_to_list(cuttlefish:conf_get("auth.http.super_req.content_type", Conf)))},
{params, [list_to_tuple(string:tokens(S, "=")) || S <- string:tokens(Params, ",")]}]
end
end}.
Expand All @@ -70,7 +70,7 @@ end}.

{mapping, "auth.http.acl_req.content_type", "emqx_auth_http.acl_req", [
{default, 'x-www-form-urlencoded'},
{datatype, {enum, [json, 'x-www-form-urlencoded']}}
{datatype, {enum, ['json', 'x-www-form-urlencoded']}}
]}.

{mapping, "auth.http.acl_req.params", "emqx_auth_http.acl_req", [
Expand All @@ -81,43 +81,67 @@ end}.
case cuttlefish:conf_get("auth.http.acl_req", Conf, undefined) of
undefined -> cuttlefish:unset();
Url -> Params = cuttlefish:conf_get("auth.http.acl_req.params", Conf),
[{url, Url}, {method, cuttlefish:conf_get("auth.http.acl_req.method", Conf)},
{content_type, cuttlefish:conf_get("auth.http.acl_req.content_type", Conf)},
[{url, Url},
{method, cuttlefish:conf_get("auth.http.acl_req.method", Conf)},
{content_type, list_to_binary("application/" ++ atom_to_list(cuttlefish:conf_get("auth.http.acl_req.content_type", Conf)))},
{params, [list_to_tuple(string:tokens(S, "=")) || S <- string:tokens(Params, ",")]}]
end
end}.

{mapping, "auth.http.request.timeout", "emqx_auth_http.http_opts", [
{default, 0},
{mapping, "auth.http.request.timeout", "emqx_auth_http.request_timeout", [
{default, "5s"},
{datatype, [integer, {duration, ms}]}
]}.

{mapping, "auth.http.request.connect_timeout", "emqx_auth_http.http_opts", [
{mapping, "auth.http.pool_size", "emqx_auth_http.pool_opts", [
{default, 8},
{datatype, integer}
]}.

{mapping, "auth.http.request.connect_timeout", "emqx_auth_http.pool_opts", [
{default, "5s"},
{datatype, [integer, {duration, ms}]}
]}.

{mapping, "auth.http.ssl.cacertfile", "emqx_auth_http.http_opts", [
{mapping, "auth.http.ssl.cacertfile", "emqx_auth_http.pool_opts", [
{datatype, string}
]}.

{mapping, "auth.http.ssl.certfile", "emqx_auth_http.http_opts", [
{mapping, "auth.http.ssl.certfile", "emqx_auth_http.pool_opts", [
{datatype, string}
]}.

{mapping, "auth.http.ssl.keyfile", "emqx_auth_http.http_opts", [
{mapping, "auth.http.ssl.keyfile", "emqx_auth_http.pool_opts", [
{datatype, string}
]}.

{translation, "emqx_auth_http.http_opts", fun(Conf) ->
{mapping, "auth.http.request.retry_times", "emqx_auth_http.pool_opts", [
{default, 5},
{datatype, integer}
]}.

{mapping, "auth.http.request.retry_interval", "emqx_auth_http.pool_opts", [
{default, "1s"},
{datatype, {duration, ms}}
]}.

{mapping, "auth.http.request.retry_backoff", "emqx_auth_http.pool_opts", [
{default, 2.0},
{datatype, float}
]}.

{translation, "emqx_auth_http.pool_opts", fun(Conf) ->
Filter = fun(L) -> [{K, V} || {K, V} <- L, V =/= undefined] end,
InfinityFun = fun(0) -> infinity;
(Duration) -> Duration
end,
SslOpts = Filter([{cacertfile, cuttlefish:conf_get("auth.http.ssl.cacertfile", Conf, undefined)},
{certfile, cuttlefish:conf_get("auth.http.ssl.certfile", Conf, undefined)},
{keyfile, cuttlefish:conf_get("auth.http.ssl.keyfile", Conf, undefined)}]),
Opts = [{timeout, InfinityFun(cuttlefish:conf_get("auth.http.request.timeout", Conf))},
{connect_timeout, InfinityFun(cuttlefish:conf_get("auth.http.request.connect_timeout", Conf, undefined))}],
Opts = [{pool_size, cuttlefish:conf_get("auth.http.pool_size", Conf)},
{connect_timeout, InfinityFun(cuttlefish:conf_get("auth.http.request.connect_timeout", Conf))},
{retry, cuttlefish:conf_get("auth.http.request.retry_times", Conf)},
{retry_timeout, cuttlefish:conf_get("auth.http.request.retry_interval", Conf)}],
case SslOpts of
[] -> Filter(Opts);
_ ->
Expand All @@ -131,26 +155,6 @@ end}.
end
end}.

{mapping, "auth.http.request.retry_times", "emqx_auth_http.retry_opts", [
{default, 3},
{datatype, integer}
]}.

{mapping, "auth.http.request.retry_interval", "emqx_auth_http.retry_opts", [
{default, "1s"},
{datatype, {duration, ms}}
]}.

{mapping, "auth.http.request.retry_backoff", "emqx_auth_http.retry_opts", [
{default, 2.0},
{datatype, float}
]}.

{translation, "emqx_auth_http.retry_opts", fun(Conf) ->
[{times, cuttlefish:conf_get("auth.http.request.retry_times", Conf)},
{interval, cuttlefish:conf_get("auth.http.request.retry_interval", Conf)},
{backoff, cuttlefish:conf_get("auth.http.request.retry_backoff", Conf)}]
end}.

{mapping, "auth.http.header.$field", "emqx_auth_http.headers", [
{datatype, string}
Expand Down
9 changes: 7 additions & 2 deletions rebar.config
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
{deps, []}.
%% Cowlib is only used to pull gun, which is using old rebar file
{deps,
[{cowlib, {git, "https://github.com/ninenines/cowlib", {tag, "2.8.0"}}},
{gun, {git, "https://github.com/emqx/gun", {tag, "1.3.4"}}},
{gproc, {git, "https://github.com/uwiger/gproc", {tag, "0.8.0"}}}
]}.

{edoc_opts, [{preprocess, true}]}.
{erl_opts, [warn_unused_vars,
Expand All @@ -20,7 +25,7 @@
[{test,
[{deps,
[{emqx_ct_helpers, {git, "https://github.com/emqx/emqx-ct-helpers", {tag, "1.2.2"}}},
{emqtt, {git, "https://github.com/emqx/emqtt", {tag, "1.2.0"}}}
{emqtt, {git, "https://github.com/emqx/emqtt", {tag, "v1.2.2"}}}
]}
]}
]}.
29 changes: 13 additions & 16 deletions src/emqx_acl_http.erl
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
-logger_header("[ACL http]").

-import(emqx_auth_http_cli,
[ request/8
[ request/6
, feedvar/2
]).

Expand All @@ -48,18 +48,16 @@ check_acl(ClientInfo, PubSub, Topic, AclResult, State) ->

do_check_acl(#{username := <<$$, _/binary>>}, _PubSub, _Topic, _AclResult, _Config) ->
ok;
do_check_acl(ClientInfo, PubSub, Topic, _AclResult, #{acl_req := AclReq,
http_opts := HttpOpts,
retry_opts := RetryOpts,
headers := Headers}) ->
do_check_acl(ClientInfo, PubSub, Topic, _AclResult, #{acl_req := AclReq,
pool_name := PoolName}) ->
ClientInfo1 = ClientInfo#{access => access(PubSub), topic => Topic},
case check_acl_request(AclReq, ClientInfo1, Headers, HttpOpts, RetryOpts) of
{ok, 200, "ignore"} -> ok;
case check_acl_request(PoolName, AclReq, ClientInfo1) of
{ok, 200, <<"ignore">>} -> ok;
{ok, 200, _Body} -> {stop, allow};
{ok, _Code, _Body} -> {stop, deny};
{error, Error} ->
?LOG(error, "Request ACL url ~s, error: ~p",
[AclReq#http_request.url, Error]),
?LOG(error, "Request ACL path ~s, error: ~p",
[AclReq#http_request.path, Error]),
ok
end.

Expand All @@ -79,13 +77,12 @@ inc_metrics({stop, deny}) ->
return_with(Fun, Result) ->
Fun(Result), Result.

check_acl_request(#http_request{url = Url,
method = Method,
content_type = ContentType,
params = Params,
options = Options},
ClientInfo, Headers, HttpOpts, RetryOpts) ->
request(Method, ContentType, Url, feedvar(Params, ClientInfo), Headers, HttpOpts, Options, RetryOpts).
check_acl_request(PoolName, #http_request{path = Path,
method = Method,
headers = Headers,
params = Params,
request_timeout = RequestTimeout}, ClientInfo) ->
request(PoolName, Method, Path, Headers, feedvar(Params, ClientInfo), RequestTimeout).

access(subscribe) -> 1;
access(publish) -> 2.
Expand Down
6 changes: 3 additions & 3 deletions src/emqx_auth_http.app.src
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
{application, emqx_auth_http,
[{description, "EMQ X Authentication/ACL with HTTP API"},
[{description, "EMQX Authentication/ACL with HTTP API"},
{vsn, "git"},
{modules, []},
{registered, [emqx_auth_http_sup]},
{applications, [kernel,stdlib]},
{applications, [kernel,stdlib,gproc,gun]},
{mod, {emqx_auth_http_app, []}},
{env, []},
{licenses, ["Apache-2.0"]},
{maintainers, ["EMQ X Team <[email protected]>"]},
{maintainers, ["EMQX Team <[email protected]>"]},
{links, [{"Homepage", "https://emqx.io/"},
{"Github", "https://github.com/emqx/emqx-auth-http"}
]}
Expand Down
29 changes: 29 additions & 0 deletions src/emqx_auth_http.appup.src
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
%% -*-: erlang -*-
{VSN,
[
{<<"4.2.([7-9]|(10))">>, [
{load_module, emqx_http_client, brutal_purge, soft_purge, []}
]},
{"4.2.6", [
{load_module, emqx_auth_http_cli, brutal_purge, soft_purge, []},
{load_module, emqx_http_client, brutal_purge, soft_purge, []}
]},
{<<"4.2.[0-5]">>, [
{restart_application, emqx_auth_http}
]},
{<<".*">>, []}
],
[
{<<"4.2.([7-9]|(10))">>, [
{load_module, emqx_http_client, brutal_purge, soft_purge, []}
]},
{"4.2.6", [
{load_module, emqx_auth_http_cli, brutal_purge, soft_purge, []},
{load_module, emqx_http_client, brutal_purge, soft_purge, []}
]},
{<<"4.2.[0-5]">>, [
{restart_application, emqx_auth_http}
]},
{<<".*">>, []}
]
}.
Loading
Loading