Merge pull request #7939 from savonarola/authz-generalize
feat(authz): add default authn-based authz source
This commit is contained in:
commit
4d661cd67b
|
@ -210,4 +210,15 @@ Authentication will verify that the value of claims in the JWT (taken from the P
|
|||
zh: """SSL 配置。"""
|
||||
}
|
||||
}
|
||||
|
||||
acl_claim_name {
|
||||
desc {
|
||||
en: """JWT claim name to use for getting ACL rules."""
|
||||
zh: """JWT claim name to use for getting ACL rules."""
|
||||
}
|
||||
label {
|
||||
en: """acl_claim_name"""
|
||||
zh: """acl_claim_name"""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -111,6 +111,11 @@ desc(_) ->
|
|||
common_fields() ->
|
||||
[
|
||||
{mechanism, emqx_authn_schema:mechanism('jwt')},
|
||||
{acl_claim_name, #{
|
||||
type => binary(),
|
||||
default => <<"acl">>,
|
||||
desc => ?DESC(acl_claim_name)
|
||||
}},
|
||||
{verify_claims, fun verify_claims/1}
|
||||
] ++ emqx_authn_schema:common_fields().
|
||||
|
||||
|
@ -231,17 +236,19 @@ authenticate(
|
|||
Credential = #{password := JWT},
|
||||
#{
|
||||
verify_claims := VerifyClaims0,
|
||||
jwk := JWK
|
||||
jwk := JWK,
|
||||
acl_claim_name := AclClaimName
|
||||
}
|
||||
) ->
|
||||
JWKs = [JWK],
|
||||
VerifyClaims = replace_placeholder(VerifyClaims0, Credential),
|
||||
verify(JWT, JWKs, VerifyClaims);
|
||||
verify(JWT, JWKs, VerifyClaims, AclClaimName);
|
||||
authenticate(
|
||||
Credential = #{password := JWT},
|
||||
#{
|
||||
verify_claims := VerifyClaims0,
|
||||
jwk_resource := ResourceId
|
||||
jwk_resource := ResourceId,
|
||||
acl_claim_name := AclClaimName
|
||||
}
|
||||
) ->
|
||||
case emqx_resource:query(ResourceId, get_jwks) of
|
||||
|
@ -254,7 +261,7 @@ authenticate(
|
|||
ignore;
|
||||
{ok, JWKs} ->
|
||||
VerifyClaims = replace_placeholder(VerifyClaims0, Credential),
|
||||
verify(JWT, JWKs, VerifyClaims)
|
||||
verify(JWT, JWKs, VerifyClaims, AclClaimName)
|
||||
end.
|
||||
|
||||
destroy(#{jwk_resource := ResourceId}) ->
|
||||
|
@ -272,7 +279,8 @@ create2(#{
|
|||
algorithm := 'hmac-based',
|
||||
secret := Secret0,
|
||||
secret_base64_encoded := Base64Encoded,
|
||||
verify_claims := VerifyClaims
|
||||
verify_claims := VerifyClaims,
|
||||
acl_claim_name := AclClaimName
|
||||
}) ->
|
||||
case may_decode_secret(Base64Encoded, Secret0) of
|
||||
{error, Reason} ->
|
||||
|
@ -281,24 +289,28 @@ create2(#{
|
|||
JWK = jose_jwk:from_oct(Secret),
|
||||
{ok, #{
|
||||
jwk => JWK,
|
||||
verify_claims => VerifyClaims
|
||||
verify_claims => VerifyClaims,
|
||||
acl_claim_name => AclClaimName
|
||||
}}
|
||||
end;
|
||||
create2(#{
|
||||
use_jwks := false,
|
||||
algorithm := 'public-key',
|
||||
public_key := PublicKey,
|
||||
verify_claims := VerifyClaims
|
||||
verify_claims := VerifyClaims,
|
||||
acl_claim_name := AclClaimName
|
||||
}) ->
|
||||
JWK = create_jwk_from_public_key(PublicKey),
|
||||
{ok, #{
|
||||
jwk => JWK,
|
||||
verify_claims => VerifyClaims
|
||||
verify_claims => VerifyClaims,
|
||||
acl_claim_name => AclClaimName
|
||||
}};
|
||||
create2(
|
||||
#{
|
||||
use_jwks := true,
|
||||
verify_claims := VerifyClaims
|
||||
verify_claims := VerifyClaims,
|
||||
acl_claim_name := AclClaimName
|
||||
} = Config
|
||||
) ->
|
||||
ResourceId = emqx_authn_utils:make_resource_id(?MODULE),
|
||||
|
@ -310,7 +322,8 @@ create2(
|
|||
),
|
||||
{ok, #{
|
||||
jwk_resource => ResourceId,
|
||||
verify_claims => VerifyClaims
|
||||
verify_claims => VerifyClaims,
|
||||
acl_claim_name => AclClaimName
|
||||
}}.
|
||||
|
||||
create_jwk_from_public_key(PublicKey) when
|
||||
|
@ -352,23 +365,39 @@ replace_placeholder([{Name, {placeholder, PL}} | More], Variables, Acc) ->
|
|||
replace_placeholder([{Name, Value} | More], Variables, Acc) ->
|
||||
replace_placeholder(More, Variables, [{Name, Value} | Acc]).
|
||||
|
||||
verify(JWT, JWKs, VerifyClaims) ->
|
||||
verify(JWT, JWKs, VerifyClaims, AclClaimName) ->
|
||||
case do_verify(JWT, JWKs, VerifyClaims) of
|
||||
{ok, Extra} -> {ok, Extra};
|
||||
{ok, Extra} -> {ok, acl(Extra, AclClaimName)};
|
||||
{error, {missing_claim, _}} -> {error, bad_username_or_password};
|
||||
{error, invalid_signature} -> ignore;
|
||||
{error, {claims, _}} -> {error, bad_username_or_password}
|
||||
end.
|
||||
|
||||
acl(Claims, AclClaimName) ->
|
||||
Acl =
|
||||
case Claims of
|
||||
#{<<"exp">> := Expire, AclClaimName := Rules} ->
|
||||
#{
|
||||
acl => #{
|
||||
rules => Rules,
|
||||
expire => Expire
|
||||
}
|
||||
};
|
||||
_ ->
|
||||
#{}
|
||||
end,
|
||||
maps:merge(emqx_authn_utils:is_superuser(Claims), Acl).
|
||||
|
||||
do_verify(_JWS, [], _VerifyClaims) ->
|
||||
{error, invalid_signature};
|
||||
do_verify(JWS, [JWK | More], VerifyClaims) ->
|
||||
try jose_jws:verify(JWK, JWS) of
|
||||
{true, Payload, _JWS} ->
|
||||
Claims = emqx_json:decode(Payload, [return_maps]),
|
||||
Claims0 = emqx_json:decode(Payload, [return_maps]),
|
||||
Claims = try_convert_to_int(Claims0, [<<"exp">>, <<"iat">>, <<"nbf">>]),
|
||||
case verify_claims(Claims, VerifyClaims) of
|
||||
ok ->
|
||||
{ok, maps:put(jwt, Claims, emqx_authn_utils:is_superuser(Claims))};
|
||||
{ok, Claims};
|
||||
{error, Reason} ->
|
||||
{error, Reason}
|
||||
end;
|
||||
|
@ -384,37 +413,39 @@ verify_claims(Claims, VerifyClaims0) ->
|
|||
Now = os:system_time(seconds),
|
||||
VerifyClaims =
|
||||
[
|
||||
{<<"exp">>, required,
|
||||
with_int_value(fun(ExpireTime) ->
|
||||
Now < ExpireTime
|
||||
end)},
|
||||
{<<"iat">>, optional,
|
||||
with_int_value(fun(IssueAt) ->
|
||||
IssueAt =< Now
|
||||
end)},
|
||||
{<<"nbf">>, optional,
|
||||
with_int_value(fun(NotBefore) ->
|
||||
NotBefore =< Now
|
||||
end)}
|
||||
{<<"exp">>, required, fun(ExpireTime) ->
|
||||
is_integer(ExpireTime) andalso Now < ExpireTime
|
||||
end},
|
||||
{<<"iat">>, optional, fun(IssueAt) ->
|
||||
is_integer(IssueAt) andalso IssueAt =< Now
|
||||
end},
|
||||
{<<"nbf">>, optional, fun(NotBefore) ->
|
||||
is_integer(NotBefore) andalso NotBefore =< Now
|
||||
end}
|
||||
] ++ VerifyClaims0,
|
||||
do_verify_claims(Claims, VerifyClaims).
|
||||
|
||||
with_int_value(Fun) ->
|
||||
fun(Value) ->
|
||||
try_convert_to_int(Claims, [Name | Names]) ->
|
||||
case Claims of
|
||||
#{Name := Value} ->
|
||||
case Value of
|
||||
Int when is_integer(Int) -> Fun(Int);
|
||||
Int when is_integer(Int) ->
|
||||
try_convert_to_int(Claims#{Name => Int}, Names);
|
||||
Bin when is_binary(Bin) ->
|
||||
case string:to_integer(Bin) of
|
||||
{Int, <<>>} -> Fun(Int);
|
||||
_ -> false
|
||||
{Int, <<>>} ->
|
||||
try_convert_to_int(Claims#{Name => Int}, Names);
|
||||
_ ->
|
||||
try_convert_to_int(Claims, Names)
|
||||
end;
|
||||
Str when is_list(Str) ->
|
||||
case string:to_integer(Str) of
|
||||
{Int, ""} -> Fun(Int);
|
||||
_ -> false
|
||||
end
|
||||
end
|
||||
end.
|
||||
_ ->
|
||||
try_convert_to_int(Claims, Names)
|
||||
end;
|
||||
_ ->
|
||||
try_convert_to_int(Claims, Names)
|
||||
end;
|
||||
try_convert_to_int(Claims, []) ->
|
||||
Claims.
|
||||
|
||||
do_verify_claims(_Claims, []) ->
|
||||
ok;
|
||||
|
|
|
@ -56,6 +56,7 @@ t_jwt_authenticator_hmac_based(_) ->
|
|||
Secret = <<"abcdef">>,
|
||||
Config = #{
|
||||
mechanism => jwt,
|
||||
acl_claim_name => <<"acl">>,
|
||||
use_jwks => false,
|
||||
algorithm => 'hmac-based',
|
||||
secret => Secret,
|
||||
|
@ -179,6 +180,7 @@ t_jwt_authenticator_public_key(_) ->
|
|||
PrivateKey = test_rsa_key(private),
|
||||
Config = #{
|
||||
mechanism => jwt,
|
||||
acl_claim_name => <<"acl">>,
|
||||
use_jwks => false,
|
||||
algorithm => 'public-key',
|
||||
public_key => PublicKey,
|
||||
|
@ -214,6 +216,7 @@ t_jwks_renewal(_Config) ->
|
|||
|
||||
BadConfig0 = #{
|
||||
mechanism => jwt,
|
||||
acl_claim_name => <<"acl">>,
|
||||
algorithm => 'public-key',
|
||||
ssl => #{enable => false},
|
||||
verify_claims => [],
|
||||
|
@ -308,6 +311,7 @@ t_jwt_authenticator_verify_claims(_) ->
|
|||
Secret = <<"abcdef">>,
|
||||
Config0 = #{
|
||||
mechanism => jwt,
|
||||
acl_claim_name => <<"acl">>,
|
||||
use_jwks => false,
|
||||
algorithm => 'hmac-based',
|
||||
secret => Secret,
|
||||
|
@ -384,6 +388,7 @@ t_jwt_not_allow_empty_claim_name(_) ->
|
|||
Request = #{
|
||||
<<"use_jwks">> => false,
|
||||
<<"algorithm">> => <<"hmac-based">>,
|
||||
<<"acl_claim_name">> => <<"acl">>,
|
||||
<<"secret">> => <<"secret">>,
|
||||
<<"mechanism">> => <<"jwt">>
|
||||
},
|
||||
|
|
|
@ -348,28 +348,6 @@ Filter supports the following placeholders:
|
|||
}
|
||||
}
|
||||
|
||||
jwt {
|
||||
desc {
|
||||
en: """Authorization using ACL rules from authentication JWT."""
|
||||
zh: """使用 JWT 登录认证中携带的 ACL 规则来进行发布和订阅的授权。"""
|
||||
}
|
||||
label {
|
||||
en: """jwt"""
|
||||
zh: """jwt"""
|
||||
}
|
||||
}
|
||||
|
||||
acl_claim_name {
|
||||
desc {
|
||||
en: """JWT claim name to use for getting ACL rules."""
|
||||
zh: """JWT claim name to use for getting ACL rules."""
|
||||
}
|
||||
label {
|
||||
en: """acl_claim_name"""
|
||||
zh: """acl_claim_name"""
|
||||
}
|
||||
}
|
||||
|
||||
cmd {
|
||||
desc {
|
||||
en: """Database query used to retrieve authorization data."""
|
||||
|
|
|
@ -95,6 +95,7 @@ register_metrics() ->
|
|||
|
||||
init() ->
|
||||
ok = register_metrics(),
|
||||
ok = init_metrics(client_info_source()),
|
||||
emqx_conf:add_handler(?CONF_KEY_PATH, ?MODULE),
|
||||
Sources = emqx_conf:get(?CONF_KEY_PATH, []),
|
||||
ok = check_dup_types(Sources),
|
||||
|
@ -307,7 +308,7 @@ authorize(
|
|||
DefaultResult,
|
||||
Sources
|
||||
) ->
|
||||
case do_authorize(Client, PubSub, Topic, Sources) of
|
||||
case do_authorize(Client, PubSub, Topic, sources_with_defaults(Sources)) of
|
||||
{{matched, allow}, AuthzSource} ->
|
||||
emqx:run_hook(
|
||||
'client.check_authz_complete',
|
||||
|
@ -392,6 +393,14 @@ get_enabled_authzs() ->
|
|||
%% Internal function
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
client_info_source() ->
|
||||
emqx_authz_client_info:create(
|
||||
#{type => client_info, enable => true}
|
||||
).
|
||||
|
||||
sources_with_defaults(Sources) ->
|
||||
[client_info_source() | Sources].
|
||||
|
||||
take(Type) -> take(Type, lookup()).
|
||||
|
||||
%% Take the source of give type, the sources list is split into two parts
|
||||
|
@ -431,8 +440,8 @@ type(postgresql) -> postgresql;
|
|||
type(<<"postgresql">>) -> postgresql;
|
||||
type(built_in_database) -> built_in_database;
|
||||
type(<<"built_in_database">>) -> built_in_database;
|
||||
type(jwt) -> jwt;
|
||||
type(<<"jwt">>) -> jwt;
|
||||
type(client_info) -> client_info;
|
||||
type(<<"client_info">>) -> client_info;
|
||||
%% should never happen if the input is type-checked by hocon schema
|
||||
type(Unknown) -> throw({unknown_authz_source_type, Unknown}).
|
||||
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2022 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.
|
||||
%% You may obtain a copy of the License at
|
||||
%%
|
||||
%% http://www.apache.org/licenses/LICENSE-2.0
|
||||
%%
|
||||
%% Unless required by applicable law or agreed to in writing, software
|
||||
%% distributed under the License is distributed on an "AS IS" BASIS,
|
||||
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
%% See the License for the specific language governing permissions and
|
||||
%% limitations under the License.
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
-module(emqx_authz_client_info).
|
||||
|
||||
-include_lib("emqx/include/logger.hrl").
|
||||
|
||||
-behaviour(emqx_authz).
|
||||
|
||||
-ifdef(TEST).
|
||||
-compile(export_all).
|
||||
-compile(nowarn_export_all).
|
||||
-endif.
|
||||
|
||||
%% APIs
|
||||
-export([
|
||||
description/0,
|
||||
create/1,
|
||||
update/1,
|
||||
destroy/1,
|
||||
authorize/4
|
||||
]).
|
||||
|
||||
-define(RULE_NAMES, [
|
||||
{[pub, <<"pub">>], publish},
|
||||
{[sub, <<"sub">>], subscribe},
|
||||
{[all, <<"all">>], all}
|
||||
]).
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% emqx_authz callbacks
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
description() ->
|
||||
"AuthZ with ClientInfo".
|
||||
|
||||
create(Source) ->
|
||||
Source.
|
||||
|
||||
update(Source) ->
|
||||
Source.
|
||||
|
||||
destroy(_Source) -> ok.
|
||||
|
||||
authorize(#{acl := Acl} = Client, PubSub, Topic, _Source) ->
|
||||
case check(Acl) of
|
||||
{ok, Rules} when is_map(Rules) ->
|
||||
do_authorize(Client, PubSub, Topic, Rules);
|
||||
{error, MatchResult} ->
|
||||
MatchResult
|
||||
end;
|
||||
authorize(_Client, _PubSub, _Topic, _Source) ->
|
||||
nomatch.
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Internal functions
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
check(#{expire := Expire, rules := Rules}) when is_map(Rules) ->
|
||||
Now = erlang:system_time(second),
|
||||
case Expire of
|
||||
N when is_integer(N) andalso N > Now -> {ok, Rules};
|
||||
undefined -> {ok, Rules};
|
||||
_ -> {error, {matched, deny}}
|
||||
end;
|
||||
%% no expire
|
||||
check(#{rules := Rules}) ->
|
||||
{ok, Rules};
|
||||
%% no rules — no match
|
||||
check(#{}) ->
|
||||
{error, nomatch}.
|
||||
|
||||
do_authorize(Client, PubSub, Topic, AclRules) ->
|
||||
do_authorize(Client, PubSub, Topic, AclRules, ?RULE_NAMES).
|
||||
|
||||
do_authorize(_Client, _PubSub, _Topic, _AclRules, []) ->
|
||||
{matched, deny};
|
||||
do_authorize(Client, PubSub, Topic, AclRules, [{Keys, Action} | RuleNames]) ->
|
||||
TopicFilters = get_topic_filters(Keys, AclRules, []),
|
||||
case
|
||||
emqx_authz_rule:match(
|
||||
Client,
|
||||
PubSub,
|
||||
Topic,
|
||||
emqx_authz_rule:compile({allow, all, Action, TopicFilters})
|
||||
)
|
||||
of
|
||||
{matched, Permission} -> {matched, Permission};
|
||||
nomatch -> do_authorize(Client, PubSub, Topic, AclRules, RuleNames)
|
||||
end.
|
||||
|
||||
get_topic_filters([], _Rules, Default) ->
|
||||
Default;
|
||||
get_topic_filters([Key | Keys], Rules, Default) ->
|
||||
case Rules of
|
||||
#{Key := Value} -> Value;
|
||||
#{} -> get_topic_filters(Keys, Rules, Default)
|
||||
end.
|
|
@ -1,142 +0,0 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2022 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.
|
||||
%% You may obtain a copy of the License at
|
||||
%%
|
||||
%% http://www.apache.org/licenses/LICENSE-2.0
|
||||
%%
|
||||
%% Unless required by applicable law or agreed to in writing, software
|
||||
%% distributed under the License is distributed on an "AS IS" BASIS,
|
||||
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
%% See the License for the specific language governing permissions and
|
||||
%% limitations under the License.
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
-module(emqx_authz_jwt).
|
||||
|
||||
-include_lib("emqx/include/logger.hrl").
|
||||
|
||||
-behaviour(emqx_authz).
|
||||
|
||||
-ifdef(TEST).
|
||||
-compile(export_all).
|
||||
-compile(nowarn_export_all).
|
||||
-endif.
|
||||
|
||||
%% APIs
|
||||
-export([
|
||||
description/0,
|
||||
create/1,
|
||||
update/1,
|
||||
destroy/1,
|
||||
authorize/4
|
||||
]).
|
||||
|
||||
-define(JWT_RULE_NAMES, [
|
||||
{<<"pub">>, publish},
|
||||
{<<"sub">>, subscribe},
|
||||
{<<"all">>, all}
|
||||
]).
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% emqx_authz callbacks
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
description() ->
|
||||
"AuthZ with JWT".
|
||||
|
||||
create(#{acl_claim_name := _AclClaimName} = Source) ->
|
||||
Source.
|
||||
|
||||
update(#{acl_claim_name := _AclClaimName} = Source) ->
|
||||
Source.
|
||||
|
||||
destroy(_Source) -> ok.
|
||||
|
||||
authorize(#{jwt := JWT} = Client, PubSub, Topic, #{acl_claim_name := AclClaimName}) ->
|
||||
case verify(JWT) of
|
||||
{ok, #{AclClaimName := Rules}} when is_map(Rules) ->
|
||||
do_authorize(Client, PubSub, Topic, Rules);
|
||||
_ ->
|
||||
{matched, deny}
|
||||
end;
|
||||
authorize(_Client, _PubSub, _Topic, _Source) ->
|
||||
nomatch.
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Internal functions
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
verify(JWT) ->
|
||||
Now = erlang:system_time(second),
|
||||
VerifyClaims =
|
||||
[
|
||||
{<<"exp">>, required,
|
||||
with_int_value(fun(ExpireTime) ->
|
||||
Now < ExpireTime
|
||||
end)},
|
||||
{<<"iat">>, optional,
|
||||
with_int_value(fun(IssueAt) ->
|
||||
IssueAt =< Now
|
||||
end)},
|
||||
{<<"nbf">>, optional,
|
||||
with_int_value(fun(NotBefore) ->
|
||||
NotBefore =< Now
|
||||
end)}
|
||||
],
|
||||
IsValid = lists:all(
|
||||
fun({ClaimName, Required, Validator}) ->
|
||||
verify_claim(ClaimName, Required, JWT, Validator)
|
||||
end,
|
||||
VerifyClaims
|
||||
),
|
||||
case IsValid of
|
||||
true -> {ok, JWT};
|
||||
false -> error
|
||||
end.
|
||||
|
||||
with_int_value(Fun) ->
|
||||
fun(Value) ->
|
||||
case Value of
|
||||
Int when is_integer(Int) -> Fun(Int);
|
||||
Bin when is_binary(Bin) ->
|
||||
case string:to_integer(Bin) of
|
||||
{Int, <<>>} -> Fun(Int);
|
||||
_ -> false
|
||||
end;
|
||||
Str when is_list(Str) ->
|
||||
case string:to_integer(Str) of
|
||||
{Int, ""} -> Fun(Int);
|
||||
_ -> false
|
||||
end
|
||||
end
|
||||
end.
|
||||
|
||||
verify_claim(ClaimName, Required, JWT, Validator) ->
|
||||
case JWT of
|
||||
#{ClaimName := Value} ->
|
||||
Validator(Value);
|
||||
#{} ->
|
||||
Required =:= optional
|
||||
end.
|
||||
|
||||
do_authorize(Client, PubSub, Topic, AclRules) ->
|
||||
do_authorize(Client, PubSub, Topic, AclRules, ?JWT_RULE_NAMES).
|
||||
|
||||
do_authorize(_Client, _PubSub, _Topic, _AclRules, []) ->
|
||||
{matched, deny};
|
||||
do_authorize(Client, PubSub, Topic, AclRules, [{Key, Action} | JWTRuleNames]) ->
|
||||
TopicFilters = maps:get(Key, AclRules, []),
|
||||
case
|
||||
emqx_authz_rule:match(
|
||||
Client,
|
||||
PubSub,
|
||||
Topic,
|
||||
emqx_authz_rule:compile({allow, all, Action, TopicFilters})
|
||||
)
|
||||
of
|
||||
{matched, Permission} -> {matched, Permission};
|
||||
nomatch -> do_authorize(Client, PubSub, Topic, AclRules, JWTRuleNames)
|
||||
end.
|
|
@ -70,8 +70,7 @@ fields("authorization") ->
|
|||
hoconsc:ref(?MODULE, postgresql),
|
||||
hoconsc:ref(?MODULE, redis_single),
|
||||
hoconsc:ref(?MODULE, redis_sentinel),
|
||||
hoconsc:ref(?MODULE, redis_cluster),
|
||||
hoconsc:ref(?MODULE, jwt)
|
||||
hoconsc:ref(?MODULE, redis_cluster)
|
||||
]
|
||||
),
|
||||
default => [],
|
||||
|
@ -129,15 +128,6 @@ fields(redis_cluster) ->
|
|||
authz_common_fields(redis) ++
|
||||
connector_fields(redis, cluster) ++
|
||||
[{cmd, cmd()}];
|
||||
fields(jwt) ->
|
||||
authz_common_fields(jwt) ++
|
||||
[
|
||||
{acl_claim_name, #{
|
||||
type => binary(),
|
||||
default => <<"acl">>,
|
||||
desc => ?DESC(acl_claim_name)
|
||||
}}
|
||||
];
|
||||
fields("metrics_status_fields") ->
|
||||
[
|
||||
{"resource_metrics", mk(ref(?MODULE, "resource_metrics"), #{desc => ?DESC("metrics")})},
|
||||
|
@ -236,8 +226,6 @@ desc(redis_sentinel) ->
|
|||
?DESC(redis_sentinel);
|
||||
desc(redis_cluster) ->
|
||||
?DESC(redis_cluster);
|
||||
desc(jwt) ->
|
||||
?DESC(jwt);
|
||||
desc(_) ->
|
||||
undefined.
|
||||
|
||||
|
|
|
@ -58,7 +58,6 @@ init_per_testcase(_TestCase, Config) ->
|
|||
),
|
||||
|
||||
ok = emqx_authz_test_lib:reset_authorizers(),
|
||||
{ok, _} = emqx_authz:update(replace, [authz_config()]),
|
||||
Config.
|
||||
|
||||
end_per_testcase(_TestCase, _Config) ->
|
||||
|
@ -317,17 +316,12 @@ authn_config() ->
|
|||
<<"algorithm">> => <<"hmac-based">>,
|
||||
<<"secret">> => ?SECRET,
|
||||
<<"secret_base64_encoded">> => <<"false">>,
|
||||
<<"acl_claim_name">> => <<"acl">>,
|
||||
<<"verify_claims">> => #{
|
||||
<<"username">> => ?PH_USERNAME
|
||||
}
|
||||
}.
|
||||
|
||||
authz_config() ->
|
||||
#{
|
||||
<<"type">> => <<"jwt">>,
|
||||
<<"acl_claim_name">> => <<"acl">>
|
||||
}.
|
||||
|
||||
generate_jws(Payload) ->
|
||||
JWK = jose_jwk:from_oct(?SECRET),
|
||||
Header = #{
|
||||
|
|
Loading…
Reference in New Issue