Merge pull request #8736 from lafirest/fix/init_jwt

fix(jwt): change `request_jwks` to be called after initialization
This commit is contained in:
JianBo He 2022-08-18 10:19:30 +08:00 committed by GitHub
commit 1eadd4f750
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 41 additions and 28 deletions

View File

@ -18,6 +18,7 @@ File format:
- Add tzdata apk package to alpine docker image. [#8671](https://github.com/emqx/emqx/pull/8671) - Add tzdata apk package to alpine docker image. [#8671](https://github.com/emqx/emqx/pull/8671)
- Add node evacuation and cluster rebalancing features [#8597](https://github.com/emqx/emqx/pull/8597) - Add node evacuation and cluster rebalancing features [#8597](https://github.com/emqx/emqx/pull/8597)
- Refine Rule Engine error log. RuleId will be logged when take action failed. [#8737](https://github.com/emqx/emqx/pull/8737) - Refine Rule Engine error log. RuleId will be logged when take action failed. [#8737](https://github.com/emqx/emqx/pull/8737)
- Improved jwt authentication module initialization process.[#8736](https://github.com/emqx/emqx/pull/8736)
### Bug fixes ### Bug fixes

View File

@ -1,6 +1,6 @@
{application, emqx_auth_jwt, {application, emqx_auth_jwt,
[{description, "EMQ X Authentication with JWT"}, [{description, "EMQ X Authentication with JWT"},
{vsn, "4.3.4"}, % strict semver, bump manually! {vsn, "4.3.5"}, % strict semver, bump manually!
{modules, []}, {modules, []},
{registered, [emqx_auth_jwt_sup]}, {registered, [emqx_auth_jwt_sup]},
{applications, [kernel,stdlib,jose]}, {applications, [kernel,stdlib,jose]},

View File

@ -1,9 +1,11 @@
%% -*- mode: erlang -*- %% -*- mode: erlang -*-
%% Unless you know what you are doing, DO NOT edit manually!! %% Unless you know what you are doing, DO NOT edit manually!!
{VSN, {VSN,
[{"4.3.3",[{load_module,emqx_auth_jwt_svr,brutal_purge,soft_purge,[]}]}, [{"4.3.4",[{load_module,emqx_auth_jwt_svr,brutal_purge,soft_purge,[]}]},
{"4.3.3",[{load_module,emqx_auth_jwt_svr,brutal_purge,soft_purge,[]}]},
{<<"4\\.3\\.[0-2]">>,[{restart_application,emqx_auth_jwt}]}, {<<"4\\.3\\.[0-2]">>,[{restart_application,emqx_auth_jwt}]},
{<<".*">>,[]}], {<<".*">>,[]}],
[{"4.3.3",[{load_module,emqx_auth_jwt_svr,brutal_purge,soft_purge,[]}]}, [{"4.3.4",[{load_module,emqx_auth_jwt_svr,brutal_purge,soft_purge,[]}]},
{"4.3.3",[{load_module,emqx_auth_jwt_svr,brutal_purge,soft_purge,[]}]},
{<<"4\\.3\\.[0-2]">>,[{restart_application,emqx_auth_jwt}]}, {<<"4\\.3\\.[0-2]">>,[{restart_application,emqx_auth_jwt}]},
{<<".*">>,[]}]}. {<<".*">>,[]}]}.

View File

@ -73,8 +73,9 @@ verify(JwsCompacted) when is_binary(JwsCompacted) ->
init([Options]) -> init([Options]) ->
ok = jose:json_module(jiffy), ok = jose:json_module(jiffy),
_ = ets:new(?TAB, [set, protected, named_table]), _ = ets:new(?TAB, [set, protected, named_table]),
{Static, Remote} = do_init_jwks(Options), Static = do_init_jwks(Options),
true = ets:insert(?TAB, [{static, Static}, {remote, Remote}]), to_request_jwks(Options),
true = ets:insert(?TAB, [{static, Static}, {remote, undefined}]),
Intv = proplists:get_value(interval, Options, ?INTERVAL), Intv = proplists:get_value(interval, Options, ?INTERVAL),
{ok, reset_timer( {ok, reset_timer(
#state{ #state{
@ -83,29 +84,13 @@ init([Options]) ->
%% @private %% @private
do_init_jwks(Options) -> do_init_jwks(Options) ->
K2J = fun(K, F) -> OctJwk = key2jwt_value(secret,
case proplists:get_value(K, Options) of fun(V) ->
undefined -> undefined; jose_jwk:from_oct(list_to_binary(V))
V -> end,
try F(V) of Options),
{error, Reason} -> PemJwk = key2jwt_value(pubkey, fun jose_jwk:from_pem_file/1, Options),
?LOG(warning, "Build ~p JWK ~p failed: {error, ~p}~n", [J ||J <- [OctJwk, PemJwk], J /= undefined].
[K, V, Reason]),
undefined;
J -> J
catch T:R ->
?LOG(warning, "Build ~p JWK ~p failed: {~p, ~p}~n",
[K, V, T, R]),
undefined
end
end
end,
OctJwk = K2J(secret, fun(V) ->
jose_jwk:from_oct(list_to_binary(V))
end),
PemJwk = K2J(pubkey, fun jose_jwk:from_pem_file/1),
Remote = K2J(jwks_addr, fun request_jwks/1),
{[J ||J <- [OctJwk, PemJwk], J /= undefined], Remote}.
handle_call(_Req, _From, State) -> handle_call(_Req, _From, State) ->
{reply, ok, State}. {reply, ok, State}.
@ -122,6 +107,11 @@ handle_info({timeout, _TRef, refresh}, State = #state{addr = Addr}) ->
end, end,
{noreply, reset_timer(NState)}; {noreply, reset_timer(NState)};
handle_info({request_jwks, Options}, State) ->
Remote = key2jwt_value(jwks_addr, fun request_jwks/1, Options),
true = ets:insert(?TAB, {remote, Remote}),
{noreply, State};
handle_info(_Info, State) -> handle_info(_Info, State) ->
{noreply, State}. {noreply, State}.
@ -249,3 +239,23 @@ do_check_claim([{K, F}|More], Claims) ->
_ -> _ ->
do_check_claim(More, Claims) do_check_claim(More, Claims)
end. end.
to_request_jwks(Options) ->
erlang:send(self(), {request_jwks, Options}).
key2jwt_value(Key, Func, Options) ->
case proplists:get_value(Key, Options) of
undefined -> undefined;
V ->
try Func(V) of
{error, Reason} ->
?LOG(warning, "Build ~p JWK ~p failed: {error, ~p}~n",
[Key, V, Reason]),
undefined;
J -> J
catch T:R ->
?LOG(warning, "Build ~p JWK ~p failed: {~p, ~p}~n",
[Key, V, T, R]),
undefined
end
end.