diff --git a/CHANGES-4.3.md b/CHANGES-4.3.md index 400b94531..29ea968a8 100644 --- a/CHANGES-4.3.md +++ b/CHANGES-4.3.md @@ -32,8 +32,6 @@ File format: scenarios, especially when the emqx-bridge-mqtt plugin is configured as shared subscription. [#7462] * Add some compression functions to rule-engine: gzip, gunzip, zip, unzip, zip_compress, zip_uncompress -* Add support for JWT authorization [#7596] - Now MQTT clients may be authorized with respect to a specific claim containing publish/subscribe topic whitelists. ### Bug fixes diff --git a/apps/emqx_auth_jwt/README.md b/apps/emqx_auth_jwt/README.md index 954171692..7af41f490 100644 --- a/apps/emqx_auth_jwt/README.md +++ b/apps/emqx_auth_jwt/README.md @@ -46,11 +46,6 @@ auth.jwt.verify_claims = off ## - %u: username ## - %c: clientid # auth.jwt.verify_claims.username = %u - -## Name of the claim containg ACL rules -## -## Value: String -#auth.jwt.acl_claim_name = acl ``` Load the Plugin @@ -67,33 +62,6 @@ Example mosquitto_pub -t 'pub' -m 'hello' -i test -u test -P eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiYm9iIiwiYWdlIjoyOX0.bIV_ZQ8D5nQi0LT8AVkpM4Pd6wmlbpR9S8nOLJAsA8o ``` -ACL ---- -JWT may contain lists of topics allowed for subscribing/publishing (ACL rules): - -Payload example: -```json -{ - "sub": "emqx", - "name": "John Doe", - "iat": 1516239022, - "exp": 1516239122, - "acl": { - "sub": [ - "a/b", - "c/+", - "%u/%c" - ], - "pub": [ - "a/b", - "c/+", - "%u/%c" - ] - } -} -``` - - Algorithms ---------- diff --git a/apps/emqx_auth_jwt/etc/emqx_auth_jwt.conf b/apps/emqx_auth_jwt/etc/emqx_auth_jwt.conf index 372b342d1..748902f9f 100644 --- a/apps/emqx_auth_jwt/etc/emqx_auth_jwt.conf +++ b/apps/emqx_auth_jwt/etc/emqx_auth_jwt.conf @@ -47,8 +47,3 @@ auth.jwt.verify_claims = off ## For example, to verify that the username in the JWT payload is the same ## as the client (MQTT protocol) username #auth.jwt.verify_claims.username = %u - -## Name of the claim containg ACL rules -## -## Value: String -#auth.jwt.acl_claim_name = acl diff --git a/apps/emqx_auth_jwt/priv/emqx_auth_jwt.schema b/apps/emqx_auth_jwt/priv/emqx_auth_jwt.schema index ff676c3ff..3d8de3678 100644 --- a/apps/emqx_auth_jwt/priv/emqx_auth_jwt.schema +++ b/apps/emqx_auth_jwt/priv/emqx_auth_jwt.schema @@ -47,13 +47,3 @@ end, [], cuttlefish_variable:filter_by_prefix("auth.jwt.verify_claims", Conf)) end end}. - -{mapping, "auth.jwt.acl_claim_name", "emqx_auth_jwt.acl_claim_name", [ - {default, "acl"}, - {datatype, string} -]}. - -{translation, "emqx_auth_jwt.acl_claim_name", fun(Conf) -> - list_to_binary(cuttlefish:conf_get("auth.jwt.acl_claim_name", Conf)) -end}. - diff --git a/apps/emqx_auth_jwt/src/emqx_auth_jwt.appup.src b/apps/emqx_auth_jwt/src/emqx_auth_jwt.appup.src index 9af4560bf..684b4fa93 100644 --- a/apps/emqx_auth_jwt/src/emqx_auth_jwt.appup.src +++ b/apps/emqx_auth_jwt/src/emqx_auth_jwt.appup.src @@ -1,9 +1,15 @@ -%% -*- mode: erlang -*- -%% Unless you know what you are doing, DO NOT edit manually!! +%% -*-: erlang -*- {VSN, - [{<<"4\\.3\\.[0-1]">>, - [{restart_application, emqx_auth_jwt}]}, - {<<".*">>,[]}], - [{<<"4\\.3\\.[0-1]">>, - [{restart_application, emqx_auth_jwt}]}, - {<<".*">>,[]}]}. + [ + {<<"4\\.3\\.[0-1]">>, [ + {load_module, emqx_auth_jwt_svr, brutal_purge, soft_purge, []} + ]}, + {<<".*">>, []} + ], + [ + {<<"4\\.3\\.[0-1]">>, [ + {load_module, emqx_auth_jwt_svr, brutal_purge, soft_purge, []} + ]}, + {<<".*">>, []} + ] +}. diff --git a/apps/emqx_auth_jwt/src/emqx_auth_jwt.erl b/apps/emqx_auth_jwt/src/emqx_auth_jwt.erl index 46451d1bb..ba37eac2b 100644 --- a/apps/emqx_auth_jwt/src/emqx_auth_jwt.erl +++ b/apps/emqx_auth_jwt/src/emqx_auth_jwt.erl @@ -1,5 +1,5 @@ %%-------------------------------------------------------------------- -%% Copyright (c) 2020-2022 EMQ Technologies Co., Ltd. All Rights Reserved. +%% Copyright (c) 2020-2021 EMQ Technologies Co., Ltd. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -22,8 +22,7 @@ -logger_header("[JWT]"). -export([ register_metrics/0 - , check_auth/3 - , check_acl/5 + , check/3 , description/0 ]). @@ -47,14 +46,16 @@ register_metrics() -> %% Authentication callbacks %%-------------------------------------------------------------------- -check_auth(ClientInfo, AuthResult, #{from := From, checklists := Checklists}) -> +check(ClientInfo, AuthResult, #{pid := Pid, + from := From, + checklists := Checklists}) -> case maps:find(From, ClientInfo) of error -> ok = emqx_metrics:inc(?AUTH_METRICS(ignore)); {ok, undefined} -> ok = emqx_metrics:inc(?AUTH_METRICS(ignore)); {ok, Token} -> - case emqx_auth_jwt_svr:verify(Token) of + case emqx_auth_jwt_svr:verify(Pid, Token) of {error, not_found} -> ok = emqx_metrics:inc(?AUTH_METRICS(ignore)); {error, not_token} -> @@ -67,38 +68,12 @@ check_auth(ClientInfo, AuthResult, #{from := From, checklists := Checklists}) -> end end. -check_acl(ClientInfo = #{jwt_claims := Claims}, - PubSub, - Topic, - _NoMatchAction, - #{acl_claim_name := AclClaimName}) -> - Deadline = erlang:system_time(second), - case Claims of - #{AclClaimName := Acl, <<"exp">> := Exp} - when is_integer(Exp) andalso Exp >= Deadline -> - verify_acl(ClientInfo, Acl, PubSub, Topic); - _ -> ignore - end. - description() -> "Authentication with JWT". %%------------------------------------------------------------------------------ %% Verify Claims %%-------------------------------------------------------------------- -verify_acl(ClientInfo, #{<<"sub">> := SubTopics}, subscribe, Topic) when is_list(SubTopics) -> - verify_acl(ClientInfo, SubTopics, Topic); -verify_acl(ClientInfo, #{<<"pub">> := PubTopics}, publish, Topic) when is_list(PubTopics) -> - verify_acl(ClientInfo, PubTopics, Topic); -verify_acl(_ClientInfo, _Acl, _PubSub, _Topic) -> {stop, deny}. - -verify_acl(_ClientInfo, [], _Topic) -> {stop, deny}; -verify_acl(ClientInfo, [AclTopic | AclTopics], Topic) -> - case match_topic(ClientInfo, AclTopic, Topic) of - true -> {stop, allow}; - false -> verify_acl(ClientInfo, AclTopics, Topic) - end. - verify_claims(Checklists, Claims, ClientInfo) -> case do_verify_claims(feedvar(Checklists, ClientInfo), Claims) of {error, Reason} -> @@ -122,9 +97,3 @@ feedvar(Checklists, #{username := Username, clientid := ClientId}) -> ({K, <<"%c">>}) -> {K, ClientId}; ({K, Expected}) -> {K, Expected} end, Checklists). - -match_topic(ClientInfo, AclTopic, Topic) -> - AclTopicWords = emqx_topic:words(AclTopic), - TopicWords = emqx_topic:words(Topic), - AclTopicRendered = emqx_access_rule:feed_var(ClientInfo, AclTopicWords), - emqx_topic:match(TopicWords, AclTopicRendered). diff --git a/apps/emqx_auth_jwt/src/emqx_auth_jwt_app.erl b/apps/emqx_auth_jwt/src/emqx_auth_jwt_app.erl index a1e9fc619..e501b0af4 100644 --- a/apps/emqx_auth_jwt/src/emqx_auth_jwt_app.erl +++ b/apps/emqx_auth_jwt/src/emqx_auth_jwt_app.erl @@ -31,20 +31,16 @@ start(_Type, _Args) -> {ok, Sup} = supervisor:start_link({local, ?MODULE}, ?MODULE, []), - {ok, _} = start_auth_server(jwks_svr_options()), + {ok, Pid} = start_auth_server(jwks_svr_options()), ok = emqx_auth_jwt:register_metrics(), + AuthEnv0 = auth_env(), + AuthEnv1 = AuthEnv0#{pid => Pid}, - AuthEnv = auth_env(), - _ = emqx:hook('client.authenticate', {emqx_auth_jwt, check_auth, [AuthEnv]}), - - AclEnv = acl_env(), - _ = emqx:hook('client.check_acl', {emqx_auth_jwt, check_acl, [AclEnv]}), + _ = emqx:hook('client.authenticate', {emqx_auth_jwt, check, [AuthEnv1]}), + {ok, Sup, AuthEnv1}. - {ok, Sup}. - -stop(_State) -> - emqx:unhook('client.authenticate', {emqx_auth_jwt, check_auth}), - emqx:unhook('client.check_acl', {emqx_auth_jwt, check_acl}). +stop(AuthEnv) -> + emqx:unhook('client.authenticate', {emqx_auth_jwt, check, [AuthEnv]}). %%-------------------------------------------------------------------- %% Dummy supervisor @@ -73,9 +69,6 @@ auth_env() -> , checklists => Checklists }. -acl_env() -> - #{acl_claim_name => env(acl_claim_name, <<"acl">>)}. - jwks_svr_options() -> [{K, V} || {K, V} <- [{secret, env(secret, undefined)}, diff --git a/apps/emqx_auth_jwt/src/emqx_auth_jwt_svr.erl b/apps/emqx_auth_jwt/src/emqx_auth_jwt_svr.erl index 05e45cec3..f34cde783 100644 --- a/apps/emqx_auth_jwt/src/emqx_auth_jwt_svr.erl +++ b/apps/emqx_auth_jwt/src/emqx_auth_jwt_svr.erl @@ -1,5 +1,5 @@ %%-------------------------------------------------------------------- -%% Copyright (c) 2020-2022 EMQ Technologies Co., Ltd. All Rights Reserved. +%% Copyright (c) 2020-2021 EMQ Technologies Co., Ltd. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -26,7 +26,7 @@ %% APIs -export([start_link/1]). --export([verify/1]). +-export([verify/2]). %% gen_server callbacks -export([ init/1 @@ -44,9 +44,8 @@ | {interval, pos_integer()}. -define(INTERVAL, 300000). --define(TAB, ?MODULE). --record(state, {addr, tref, intv}). +-record(state, {static, remote, addr, tref, intv}). %%-------------------------------------------------------------------- %% APIs @@ -56,13 +55,13 @@ start_link(Options) -> gen_server:start_link(?MODULE, [Options], []). --spec verify(binary()) +-spec verify(pid(), binary()) -> {error, term()} | {ok, Payload :: map()}. -verify(JwsCompacted) when is_binary(JwsCompacted) -> +verify(S, JwsCompacted) when is_binary(JwsCompacted) -> case catch jose_jws:peek(JwsCompacted) of {'EXIT', _} -> {error, not_token}; - _ -> do_verify(JwsCompacted) + _ -> gen_server:call(S, {verify, JwsCompacted}) end. %%-------------------------------------------------------------------- @@ -71,12 +70,12 @@ verify(JwsCompacted) when is_binary(JwsCompacted) -> init([Options]) -> ok = jose:json_module(jiffy), - _ = ets:new(?TAB, [set, protected, named_table]), {Static, Remote} = do_init_jwks(Options), - true = ets:insert(?TAB, [{static, Static}, {remote, Remote}]), Intv = proplists:get_value(interval, Options, ?INTERVAL), {ok, reset_timer( #state{ + static = Static, + remote = Remote, addr = proplists:get_value(jwks_addr, Options), intv = Intv})}. @@ -106,6 +105,9 @@ do_init_jwks(Options) -> Remote = K2J(jwks_addr, fun request_jwks/1), {[J ||J <- [OctJwk, PemJwk], J /= undefined], Remote}. +handle_call({verify, JwsCompacted}, _From, State) -> + handle_verify(JwsCompacted, State); + handle_call(_Req, _From, State) -> {reply, ok, State}. @@ -114,7 +116,7 @@ handle_cast(_Msg, State) -> handle_info({timeout, _TRef, refresh}, State = #state{addr = Addr}) -> NState = try - true = ets:insert(?TAB, {remote, request_jwks(Addr)}) + State#state{remote = request_jwks(Addr)} catch _:_ -> State end, @@ -134,10 +136,24 @@ code_change(_OldVsn, State, _Extra) -> %% Internal funcs %%-------------------------------------------------------------------- -keys(Type) -> - case ets:lookup(?TAB, Type) of - [{_, Keys}] -> Keys; - [] -> [] +handle_verify(JwsCompacted, + State = #state{static = Static, remote = Remote}) -> + try + Jwks = case emqx_json:decode(jose_jws:peek_protected(JwsCompacted), [return_maps]) of + #{<<"kid">> := Kid} when Remote /= undefined -> + [J || J <- Remote, maps:get(<<"kid">>, J#jose_jwk.fields, undefined) =:= Kid]; + _ -> Static + end, + case Jwks of + [] -> {reply, {error, not_found}, State}; + _ -> + {reply, do_verify(JwsCompacted, Jwks), State} + end + catch + Class : Reason : Stk -> + ?LOG(error, "Handle JWK crashed: ~p, ~p, stacktrace: ~p~n", + [Class, Reason, Stk]), + {reply, {error, invalid_signature}, State} end. request_jwks(Addr) -> @@ -165,26 +181,6 @@ cancel_timer(State = #state{tref = TRef}) -> _ = erlang:cancel_timer(TRef), State#state{tref = undefined}. -do_verify(JwsCompacted) -> - try - Remote = keys(remote), - Jwks = case emqx_json:decode(jose_jws:peek_protected(JwsCompacted), [return_maps]) of - #{<<"kid">> := Kid} when Remote /= undefined -> - [J || J <- Remote, maps:get(<<"kid">>, J#jose_jwk.fields, undefined) =:= Kid]; - _ -> keys(static) - end, - case Jwks of - [] -> {error, not_found}; - _ -> - do_verify(JwsCompacted, Jwks) - end - catch - Class : Reason : Stk -> - ?LOG(error, "verify JWK crashed: ~p, ~p, stacktrace: ~p~n", - [Class, Reason, Stk]), - {error, invalid_signature} - end. - do_verify(_JwsCompated, []) -> {error, invalid_signature}; do_verify(JwsCompacted, [Jwk|More]) -> @@ -218,12 +214,11 @@ check_claims(Claims) -> do_check_claim([], Claims) -> Claims; do_check_claim([{K, F}|More], Claims) -> - case Claims of - #{K := V} -> + case maps:take(K, Claims) of + error -> do_check_claim(More, Claims); + {V, NClaims} -> case F(V) of - true -> do_check_claim(More, Claims); + true -> do_check_claim(More, NClaims); _ -> {false, K} - end; - _ -> - do_check_claim(More, Claims) + end end. diff --git a/apps/emqx_auth_jwt/test/emqx_auth_jwt_SUITE.erl b/apps/emqx_auth_jwt/test/emqx_auth_jwt_SUITE.erl index e28c7348b..d4f562b6f 100644 --- a/apps/emqx_auth_jwt/test/emqx_auth_jwt_SUITE.erl +++ b/apps/emqx_auth_jwt/test/emqx_auth_jwt_SUITE.erl @@ -1,5 +1,5 @@ %%-------------------------------------------------------------------- -%% Copyright (c) 2020-2022 EMQ Technologies Co., Ltd. All Rights Reserved. +%% Copyright (c) 2020-2021 EMQ Technologies Co., Ltd. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -20,13 +20,22 @@ -compile(nowarn_export_all). -include_lib("emqx/include/emqx.hrl"). --include_lib("emqx/include/emqx_mqtt.hrl"). -include_lib("eunit/include/eunit.hrl"). -include_lib("common_test/include/ct.hrl"). -define(APP, emqx_auth_jwt). -all() -> emqx_ct:all(?MODULE). +all() -> + [{group, emqx_auth_jwt}]. + +groups() -> + [{emqx_auth_jwt, [sequence], [ t_check_auth + , t_check_claims + , t_check_claims_clientid + , t_check_claims_username + , t_check_claims_kid_in_header + ]} + ]. init_per_suite(Config) -> emqx_ct_helpers:start_apps([emqx_auth_jwt], fun set_special_configs/1), @@ -35,14 +44,6 @@ init_per_suite(Config) -> end_per_suite(_Config) -> emqx_ct_helpers:stop_apps([emqx_auth_jwt]). -init_per_testcase(TestCase, Config) -> - ?MODULE:TestCase(init, Config), - emqx_ct_helpers:start_apps([emqx_auth_jwt], fun set_special_configs/1), - Config. - -end_per_testcase(_Case, _Config) -> - emqx_ct_helpers:stop_apps([emqx_auth_jwt]). - set_special_configs(emqx) -> application:set_env(emqx, allow_anonymous, false), application:set_env(emqx, acl_nomatch, deny), @@ -77,9 +78,7 @@ sign(Payload, Alg, Key) -> %% Testcases %%------------------------------------------------------------------------------ -t_check_auth(init, _Config) -> - application:unset_env(emqx_auth_jwt, verify_claims). -t_check_auth(_Config) -> +t_check_auth(_) -> Plain = #{clientid => <<"client1">>, username => <<"plain">>, zone => external}, Jwt = sign([{clientid, <<"client1">>}, {username, <<"plain">>}, @@ -103,9 +102,10 @@ t_check_auth(_Config) -> ?assertEqual({error, invalid_signature}, Result2), ?assertMatch({error, _}, emqx_access_control:authenticate(Plain#{password => <<"asd">>})). -t_check_claims(init, _Config) -> - application:set_env(emqx_auth_jwt, verify_claims, [{sub, <<"value">>}]). -t_check_claims(_Config) -> +t_check_claims(_) -> + application:set_env(emqx_auth_jwt, verify_claims, [{sub, <<"value">>}]), + application:stop(emqx_auth_jwt), application:start(emqx_auth_jwt), + Plain = #{clientid => <<"client1">>, username => <<"plain">>, zone => external}, Jwt = sign([{client_id, <<"client1">>}, {username, <<"plain">>}, @@ -120,9 +120,9 @@ t_check_claims(_Config) -> ct:pal("Auth result for the invalid jwt: ~p~n", [Result2]), ?assertEqual({error, invalid_signature}, Result2). -t_check_claims_clientid(init, _Config) -> - application:set_env(emqx_auth_jwt, verify_claims, [{clientid, <<"%c">>}]). -t_check_claims_clientid(_Config) -> +t_check_claims_clientid(_) -> + application:set_env(emqx_auth_jwt, verify_claims, [{clientid, <<"%c">>}]), + application:stop(emqx_auth_jwt), application:start(emqx_auth_jwt), Plain = #{clientid => <<"client23">>, username => <<"plain">>, zone => external}, Jwt = sign([{clientid, <<"client23">>}, {username, <<"plain">>}, @@ -136,9 +136,10 @@ t_check_claims_clientid(_Config) -> ct:pal("Auth result for the invalid jwt: ~p~n", [Result2]), ?assertEqual({error, invalid_signature}, Result2). -t_check_claims_username(init, _Config) -> - application:set_env(emqx_auth_jwt, verify_claims, [{username, <<"%u">>}]). -t_check_claims_username(_Config) -> +t_check_claims_username(_) -> + application:set_env(emqx_auth_jwt, verify_claims, [{username, <<"%u">>}]), + application:stop(emqx_auth_jwt), application:start(emqx_auth_jwt), + Plain = #{clientid => <<"client23">>, username => <<"plain">>, zone => external}, Jwt = sign([{client_id, <<"client23">>}, {username, <<"plain">>}, @@ -152,9 +153,8 @@ t_check_claims_username(_Config) -> ct:pal("Auth result for the invalid jwt: ~p~n", [Result3]), ?assertEqual({error, invalid_signature}, Result3). -t_check_claims_kid_in_header(init, _Config) -> - application:set_env(emqx_auth_jwt, verify_claims, []). -t_check_claims_kid_in_header(_Config) -> +t_check_claims_kid_in_header(_) -> + application:set_env(emqx_auth_jwt, verify_claims, []), Plain = #{clientid => <<"client23">>, username => <<"plain">>, zone => external}, Jwt = sign([{clientid, <<"client23">>}, {username, <<"plain">>}, @@ -164,125 +164,3 @@ t_check_claims_kid_in_header(_Config) -> Result0 = emqx_access_control:authenticate(Plain#{password => Jwt}), ct:pal("Auth result: ~p~n", [Result0]), ?assertMatch({ok, #{auth_result := success, jwt_claims := _}}, Result0). - -t_check_jwt_acl(init, _Config) -> - application:set_env(emqx_auth_jwt, verify_claims, [{sub, <<"value">>}]). -t_check_jwt_acl(_Config) -> - Jwt = sign([{client_id, <<"client1">>}, - {username, <<"plain">>}, - {sub, value}, - {acl, [{sub, [<<"a/b">>]}, - {pub, [<<"c/d">>]}]}, - {exp, os:system_time(seconds) + 10}], - <<"HS256">>, - <<"emqxsecret">>), - - {ok, C} = emqtt:start_link( - [{clean_start, true}, - {proto_ver, v5}, - {client_id, <<"client1">>}, - {password, Jwt}]), - {ok, _} = emqtt:connect(C), - - ?assertMatch( - {ok, #{}, [0]}, - emqtt:subscribe(C, <<"a/b">>, 0)), - - ?assertMatch( - ok, - emqtt:publish(C, <<"c/d">>, <<"hi">>, 0)), - - ?assertMatch( - {ok, #{}, [?RC_NOT_AUTHORIZED]}, - emqtt:subscribe(C, <<"c/d">>, 0)), - - ok = emqtt:publish(C, <<"a/b">>, <<"hi">>, 0), - - receive - {publish, #{topic := <<"a/b">>}} -> - ?assert(false, "Publish to `a/b` should not be allowed") - after 100 -> ok - end, - - ok = emqtt:disconnect(C). - -t_check_jwt_acl_no_recs(init, _Config) -> - application:set_env(emqx_auth_jwt, verify_claims, [{sub, <<"value">>}]). -t_check_jwt_acl_no_recs(_Config) -> - Jwt = sign([{client_id, <<"client1">>}, - {username, <<"plain">>}, - {sub, value}, - {acl, []}, - {exp, os:system_time(seconds) + 10}], - <<"HS256">>, - <<"emqxsecret">>), - - {ok, C} = emqtt:start_link( - [{clean_start, true}, - {proto_ver, v5}, - {client_id, <<"client1">>}, - {password, Jwt}]), - {ok, _} = emqtt:connect(C), - - ?assertMatch( - {ok, #{}, [?RC_NOT_AUTHORIZED]}, - emqtt:subscribe(C, <<"a/b">>, 0)), - - ok = emqtt:disconnect(C). - -t_check_jwt_acl_no_acl_claim(init, _Config) -> - application:set_env(emqx_auth_jwt, verify_claims, [{sub, <<"value">>}]). -t_check_jwt_acl_no_acl_claim(_Config) -> - Jwt = sign([{client_id, <<"client1">>}, - {username, <<"plain">>}, - {sub, value}, - {exp, os:system_time(seconds) + 10}], - <<"HS256">>, - <<"emqxsecret">>), - - {ok, C} = emqtt:start_link( - [{clean_start, true}, - {proto_ver, v5}, - {client_id, <<"client1">>}, - {password, Jwt}]), - {ok, _} = emqtt:connect(C), - - ?assertMatch( - {ok, #{}, [?RC_NOT_AUTHORIZED]}, - emqtt:subscribe(C, <<"a/b">>, 0)), - - ok = emqtt:disconnect(C). - -t_check_jwt_acl_expire(init, _Config) -> - application:set_env(emqx_auth_jwt, verify_claims, [{sub, <<"value">>}]). -t_check_jwt_acl_expire(_Config) -> - Jwt = sign([{client_id, <<"client1">>}, - {username, <<"plain">>}, - {sub, value}, - {acl, [{sub, [<<"a/b">>]}]}, - {exp, os:system_time(seconds) + 1}], - <<"HS256">>, - <<"emqxsecret">>), - - {ok, C} = emqtt:start_link( - [{clean_start, true}, - {proto_ver, v5}, - {client_id, <<"client1">>}, - {password, Jwt}]), - {ok, _} = emqtt:connect(C), - - ?assertMatch( - {ok, #{}, [0]}, - emqtt:subscribe(C, <<"a/b">>, 0)), - - ?assertMatch( - {ok, #{}, [0]}, - emqtt:unsubscribe(C, <<"a/b">>)), - - timer:sleep(2000), - - ?assertMatch( - {ok, #{}, [?RC_NOT_AUTHORIZED]}, - emqtt:subscribe(C, <<"a/b">>, 0)), - - ok = emqtt:disconnect(C). diff --git a/src/emqx.appup.src b/src/emqx.appup.src index 347634ba9..1ef499276 100644 --- a/src/emqx.appup.src +++ b/src/emqx.appup.src @@ -2,8 +2,7 @@ %% Unless you know what you are doing, DO NOT edit manually!! {VSN, [{"4.3.14", - [{load_module,emqx_access_rule,brutal_purge,soft_purge,[]}, - {load_module,emqx,brutal_purge,soft_purge,[]}, + [{load_module,emqx,brutal_purge,soft_purge,[]}, {load_module,emqx_sys,brutal_purge,soft_purge,[]}, {load_module,emqx_plugins,brutal_purge,soft_purge,[]}, {load_module,emqx_shared_sub,brutal_purge,soft_purge,[]}, @@ -11,8 +10,7 @@ {load_module,emqx_app,brutal_purge,soft_purge,[]}, {load_module,emqx_hooks,brutal_purge,soft_purge,[]}]}, {"4.3.13", - [{load_module,emqx_access_rule,brutal_purge,soft_purge,[]}, - {load_module,emqx_shared_sub,brutal_purge,soft_purge,[]}, + [{load_module,emqx_shared_sub,brutal_purge,soft_purge,[]}, {load_module,emqx_hooks,brutal_purge,soft_purge,[]}, {load_module,emqx,brutal_purge,soft_purge,[]}, {load_module,emqx_plugins,brutal_purge,soft_purge,[]}, @@ -29,8 +27,7 @@ {load_module,emqx_misc,brutal_purge,soft_purge,[]}, {load_module,emqx_connection,brutal_purge,soft_purge,[]}]}, {"4.3.12", - [{load_module,emqx_access_rule,brutal_purge,soft_purge,[]}, - {load_module,emqx_shared_sub,brutal_purge,soft_purge,[]}, + [{load_module,emqx_shared_sub,brutal_purge,soft_purge,[]}, {load_module,emqx_hooks,brutal_purge,soft_purge,[]}, {load_module,emqx_plugins,brutal_purge,soft_purge,[]}, {load_module,emqx_frame,brutal_purge,soft_purge,[]}, @@ -55,8 +52,7 @@ {load_module,emqx_message,brutal_purge,soft_purge,[]}, {load_module,emqx_limiter,brutal_purge,soft_purge,[]}]}, {"4.3.11", - [{load_module,emqx_access_rule,brutal_purge,soft_purge,[]}, - {load_module,emqx_shared_sub,brutal_purge,soft_purge,[]}, + [{load_module,emqx_shared_sub,brutal_purge,soft_purge,[]}, {load_module,emqx_hooks,brutal_purge,soft_purge,[]}, {load_module,emqx_plugins,brutal_purge,soft_purge,[]}, {load_module,emqx_pmon,brutal_purge,soft_purge,[]}, @@ -83,8 +79,7 @@ {load_module,emqx_message,brutal_purge,soft_purge,[]}, {load_module,emqx_limiter,brutal_purge,soft_purge,[]}]}, {"4.3.10", - [{load_module,emqx_access_rule,brutal_purge,soft_purge,[]}, - {load_module,emqx_shared_sub,brutal_purge,soft_purge,[]}, + [{load_module,emqx_shared_sub,brutal_purge,soft_purge,[]}, {load_module,emqx_hooks,brutal_purge,soft_purge,[]}, {load_module,emqx_plugins,brutal_purge,soft_purge,[]}, {load_module,emqx_pmon,brutal_purge,soft_purge,[]}, @@ -111,8 +106,7 @@ {load_module,emqx_message,brutal_purge,soft_purge,[]}, {load_module,emqx_limiter,brutal_purge,soft_purge,[]}]}, {"4.3.9", - [{load_module,emqx_access_rule,brutal_purge,soft_purge,[]}, - {load_module,emqx_shared_sub,brutal_purge,soft_purge,[]}, + [{load_module,emqx_shared_sub,brutal_purge,soft_purge,[]}, {load_module,emqx_hooks,brutal_purge,soft_purge,[]}, {load_module,emqx_plugins,brutal_purge,soft_purge,[]}, {load_module,emqx_pmon,brutal_purge,soft_purge,[]}, @@ -143,8 +137,7 @@ {load_module,emqx_message,brutal_purge,soft_purge,[]}, {load_module,emqx_limiter,brutal_purge,soft_purge,[]}]}, {"4.3.8", - [{load_module,emqx_access_rule,brutal_purge,soft_purge,[]}, - {load_module,emqx_shared_sub,brutal_purge,soft_purge,[]}, + [{load_module,emqx_shared_sub,brutal_purge,soft_purge,[]}, {load_module,emqx_hooks,brutal_purge,soft_purge,[]}, {load_module,emqx_plugins,brutal_purge,soft_purge,[]}, {load_module,emqx_pmon,brutal_purge,soft_purge,[]}, @@ -175,8 +168,7 @@ {load_module,emqx_message,brutal_purge,soft_purge,[]}, {load_module,emqx_limiter,brutal_purge,soft_purge,[]}]}, {"4.3.7", - [{load_module,emqx_access_rule,brutal_purge,soft_purge,[]}, - {load_module,emqx_shared_sub,brutal_purge,soft_purge,[]}, + [{load_module,emqx_shared_sub,brutal_purge,soft_purge,[]}, {load_module,emqx_hooks,brutal_purge,soft_purge,[]}, {load_module,emqx_plugins,brutal_purge,soft_purge,[]}, {load_module,emqx_pmon,brutal_purge,soft_purge,[]}, @@ -208,8 +200,7 @@ {load_module,emqx_message,brutal_purge,soft_purge,[]}, {load_module,emqx_limiter,brutal_purge,soft_purge,[]}]}, {"4.3.6", - [{load_module,emqx_access_rule,brutal_purge,soft_purge,[]}, - {load_module,emqx_shared_sub,brutal_purge,soft_purge,[]}, + [{load_module,emqx_shared_sub,brutal_purge,soft_purge,[]}, {load_module,emqx_hooks,brutal_purge,soft_purge,[]}, {load_module,emqx_plugins,brutal_purge,soft_purge,[]}, {load_module,emqx_pmon,brutal_purge,soft_purge,[]}, @@ -453,8 +444,7 @@ {load_module,emqx_limiter,brutal_purge,soft_purge,[]}]}, {<<".*">>,[]}], [{"4.3.14", - [{load_module,emqx_access_rule,brutal_purge,soft_purge,[]}, - {load_module,emqx,brutal_purge,soft_purge,[]}, + [{load_module,emqx,brutal_purge,soft_purge,[]}, {load_module,emqx_sys,brutal_purge,soft_purge,[]}, {load_module,emqx_plugins,brutal_purge,soft_purge,[]}, {load_module,emqx_shared_sub,brutal_purge,soft_purge,[]}, @@ -462,8 +452,7 @@ {load_module,emqx_app,brutal_purge,soft_purge,[]}, {load_module,emqx_hooks,brutal_purge,soft_purge,[]}]}, {"4.3.13", - [{load_module,emqx_access_rule,brutal_purge,soft_purge,[]}, - {load_module,emqx_shared_sub,brutal_purge,soft_purge,[]}, + [{load_module,emqx_shared_sub,brutal_purge,soft_purge,[]}, {load_module,emqx_hooks,brutal_purge,soft_purge,[]}, {load_module,emqx,brutal_purge,soft_purge,[]}, {load_module,emqx_plugins,brutal_purge,soft_purge,[]}, @@ -480,8 +469,7 @@ {load_module,emqx_cm,brutal_purge,soft_purge,[]}, {load_module,emqx_connection,brutal_purge,soft_purge,[]}]}, {"4.3.12", - [{load_module,emqx_access_rule,brutal_purge,soft_purge,[]}, - {load_module,emqx_shared_sub,brutal_purge,soft_purge,[]}, + [{load_module,emqx_shared_sub,brutal_purge,soft_purge,[]}, {load_module,emqx_hooks,brutal_purge,soft_purge,[]}, {load_module,emqx_plugins,brutal_purge,soft_purge,[]}, {load_module,emqx_frame,brutal_purge,soft_purge,[]}, @@ -505,8 +493,7 @@ {load_module,emqx_message,brutal_purge,soft_purge,[]}, {load_module,emqx_limiter,brutal_purge,soft_purge,[]}]}, {"4.3.11", - [{load_module,emqx_access_rule,brutal_purge,soft_purge,[]}, - {load_module,emqx_shared_sub,brutal_purge,soft_purge,[]}, + [{load_module,emqx_shared_sub,brutal_purge,soft_purge,[]}, {load_module,emqx_hooks,brutal_purge,soft_purge,[]}, {load_module,emqx_plugins,brutal_purge,soft_purge,[]}, {load_module,emqx_pmon,brutal_purge,soft_purge,[]}, @@ -532,8 +519,7 @@ {load_module,emqx_message,brutal_purge,soft_purge,[]}, {load_module,emqx_limiter,brutal_purge,soft_purge,[]}]}, {"4.3.10", - [{load_module,emqx_access_rule,brutal_purge,soft_purge,[]}, - {load_module,emqx_shared_sub,brutal_purge,soft_purge,[]}, + [{load_module,emqx_shared_sub,brutal_purge,soft_purge,[]}, {load_module,emqx_hooks,brutal_purge,soft_purge,[]}, {load_module,emqx_plugins,brutal_purge,soft_purge,[]}, {load_module,emqx_pmon,brutal_purge,soft_purge,[]}, @@ -559,8 +545,7 @@ {load_module,emqx_message,brutal_purge,soft_purge,[]}, {load_module,emqx_limiter,brutal_purge,soft_purge,[]}]}, {"4.3.9", - [{load_module,emqx_access_rule,brutal_purge,soft_purge,[]}, - {load_module,emqx_shared_sub,brutal_purge,soft_purge,[]}, + [{load_module,emqx_shared_sub,brutal_purge,soft_purge,[]}, {load_module,emqx_hooks,brutal_purge,soft_purge,[]}, {load_module,emqx_plugins,brutal_purge,soft_purge,[]}, {load_module,emqx_pmon,brutal_purge,soft_purge,[]}, @@ -590,8 +575,7 @@ {load_module,emqx_message,brutal_purge,soft_purge,[]}, {load_module,emqx_limiter,brutal_purge,soft_purge,[]}]}, {"4.3.8", - [{load_module,emqx_access_rule,brutal_purge,soft_purge,[]}, - {load_module,emqx_shared_sub,brutal_purge,soft_purge,[]}, + [{load_module,emqx_shared_sub,brutal_purge,soft_purge,[]}, {load_module,emqx_hooks,brutal_purge,soft_purge,[]}, {load_module,emqx_plugins,brutal_purge,soft_purge,[]}, {load_module,emqx_pmon,brutal_purge,soft_purge,[]}, @@ -621,8 +605,7 @@ {load_module,emqx_message,brutal_purge,soft_purge,[]}, {load_module,emqx_limiter,brutal_purge,soft_purge,[]}]}, {"4.3.7", - [{load_module,emqx_access_rule,brutal_purge,soft_purge,[]}, - {load_module,emqx_shared_sub,brutal_purge,soft_purge,[]}, + [{load_module,emqx_shared_sub,brutal_purge,soft_purge,[]}, {load_module,emqx_hooks,brutal_purge,soft_purge,[]}, {load_module,emqx_plugins,brutal_purge,soft_purge,[]}, {load_module,emqx_pmon,brutal_purge,soft_purge,[]}, @@ -653,8 +636,7 @@ {load_module,emqx_message,brutal_purge,soft_purge,[]}, {load_module,emqx_limiter,brutal_purge,soft_purge,[]}]}, {"4.3.6", - [{load_module,emqx_access_rule,brutal_purge,soft_purge,[]}, - {load_module,emqx_shared_sub,brutal_purge,soft_purge,[]}, + [{load_module,emqx_shared_sub,brutal_purge,soft_purge,[]}, {load_module,emqx_hooks,brutal_purge,soft_purge,[]}, {load_module,emqx_plugins,brutal_purge,soft_purge,[]}, {load_module,emqx_pmon,brutal_purge,soft_purge,[]}, diff --git a/src/emqx_access_rule.erl b/src/emqx_access_rule.erl index da2a39a22..49831d614 100644 --- a/src/emqx_access_rule.erl +++ b/src/emqx_access_rule.erl @@ -1,5 +1,5 @@ %%-------------------------------------------------------------------- -%% Copyright (c) 2017-2022 EMQ Technologies Co., Ltd. All Rights Reserved. +%% Copyright (c) 2017-2021 EMQ Technologies Co., Ltd. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -19,7 +19,6 @@ %% APIs -export([ match/3 , compile/1 - , feed_var/2 ]). -export_type([rule/0]).