chore(authz): improve and clarify types
This commit is contained in:
parent
a0e0a27f87
commit
aaf57ecfbc
|
@ -29,13 +29,15 @@
|
||||||
compile/4
|
compile/4
|
||||||
]).
|
]).
|
||||||
|
|
||||||
-export_type([action/0, action_precompile/0]).
|
|
||||||
|
|
||||||
-include_lib("emqx/include/logger.hrl").
|
-include_lib("emqx/include/logger.hrl").
|
||||||
-include_lib("emqx/include/emqx_placeholder.hrl").
|
-include_lib("emqx/include/emqx_placeholder.hrl").
|
||||||
-include("emqx_authz.hrl").
|
-include("emqx_authz.hrl").
|
||||||
|
|
||||||
-type permission() :: allow | deny.
|
%%--------------------------------------------------------------------
|
||||||
|
%% "condition" types describe compiled rules used internally for matching
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
|
||||||
|
-type permission_resolution() :: allow | deny.
|
||||||
|
|
||||||
-type who_condition() ::
|
-type who_condition() ::
|
||||||
ipaddress()
|
ipaddress()
|
||||||
|
@ -61,7 +63,18 @@
|
||||||
|
|
||||||
-type topic_condition() :: list(emqx_types:topic() | {eq, emqx_types:topic()}).
|
-type topic_condition() :: list(emqx_types:topic() | {eq, emqx_types:topic()}).
|
||||||
|
|
||||||
-type rule() :: {permission(), who_condition(), action_condition(), topic_condition()}.
|
-type rule() :: {permission_resolution(), who_condition(), action_condition(), topic_condition()}.
|
||||||
|
|
||||||
|
-export_type([
|
||||||
|
permission_resolution/0,
|
||||||
|
action_condition/0,
|
||||||
|
topic_condition/0
|
||||||
|
]).
|
||||||
|
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
%% `action()` type describes client's actions that are mached
|
||||||
|
%% against the compiled "condition" rules
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
|
||||||
-type qos() :: emqx_types:qos().
|
-type qos() :: emqx_types:qos().
|
||||||
-type retain() :: boolean().
|
-type retain() :: boolean().
|
||||||
|
@ -69,32 +82,54 @@
|
||||||
#{action_type := subscribe, qos := qos()}
|
#{action_type := subscribe, qos := qos()}
|
||||||
| #{action_type := publish, qos := qos(), retain := retain()}.
|
| #{action_type := publish, qos := qos(), retain := retain()}.
|
||||||
|
|
||||||
-export_type([
|
-export_type([action/0, qos/0, retain/0]).
|
||||||
permission/0,
|
|
||||||
who_condition/0,
|
%%--------------------------------------------------------------------
|
||||||
action_condition/0,
|
%% "precompiled" types describe rule DSL that is used in "acl.conf" file
|
||||||
topic_condition/0
|
%% to describe rules. Also, rules extracted from external sources
|
||||||
]).
|
%% like database, etc. are preprocessed into these types first
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
|
||||||
|
-type permission_resolution_precompile() :: permission_resolution().
|
||||||
|
|
||||||
|
-type who_precompile() :: who_condition().
|
||||||
|
|
||||||
|
-type subscribe_option_precompile() :: {qos, qos() | [qos()]}.
|
||||||
|
-type publish_option_precompile() :: {qos, qos() | [qos()]} | {retain, retain_condition()}.
|
||||||
|
|
||||||
-type action_precompile() ::
|
-type action_precompile() ::
|
||||||
subscribe
|
subscribe
|
||||||
|
| {subscribe, [subscribe_option_precompile()]}
|
||||||
| publish
|
| publish
|
||||||
| {subscribe, list()}
|
| {publish, [publish_option_precompile()]}
|
||||||
| {publish, list()}
|
| all
|
||||||
| all.
|
| {all, [publish_option_precompile()]}.
|
||||||
|
|
||||||
-type topic_filter() :: emqx_types:topic().
|
%% besides exact `topic_condition()` we also accept `<<"eq ...">>` and `"eq ..."`
|
||||||
|
%% as precompiled topic conditions
|
||||||
|
-type topic_precompile() :: topic_condition() | binary() | string().
|
||||||
|
|
||||||
-type rule_precompile() :: {permission(), who_condition(), action_precompile(), [topic_filter()]}.
|
-type rule_precompile() :: {
|
||||||
|
permission_resolution_precompile(), who_condition(), action_precompile(), [topic_precompile()]
|
||||||
|
}.
|
||||||
|
|
||||||
|
-export_type([
|
||||||
|
permission_resolution_precompile/0,
|
||||||
|
action_precompile/0,
|
||||||
|
topic_precompile/0,
|
||||||
|
rule_precompile/0
|
||||||
|
]).
|
||||||
|
|
||||||
-define(IS_PERMISSION(Permission), (Permission =:= allow orelse Permission =:= deny)).
|
-define(IS_PERMISSION(Permission), (Permission =:= allow orelse Permission =:= deny)).
|
||||||
-define(ALLOWED_VARS, [?VAR_USERNAME, ?VAR_CLIENTID, ?VAR_NS_CLIENT_ATTRS]).
|
-define(ALLOWED_VARS, [?VAR_USERNAME, ?VAR_CLIENTID, ?VAR_NS_CLIENT_ATTRS]).
|
||||||
|
|
||||||
-spec compile(permission(), who_condition(), action_precompile(), [topic_filter()]) -> rule().
|
-spec compile(permission_resolution_precompile(), who_precompile(), action_precompile(), [
|
||||||
|
topic_precompile()
|
||||||
|
]) -> rule().
|
||||||
compile(Permission, Who, Action, TopicFilters) ->
|
compile(Permission, Who, Action, TopicFilters) ->
|
||||||
compile({Permission, Who, Action, TopicFilters}).
|
compile({Permission, Who, Action, TopicFilters}).
|
||||||
|
|
||||||
-spec compile({permission(), all} | rule_precompile()) -> rule().
|
-spec compile({permission_resolution_precompile(), all} | rule_precompile()) -> rule().
|
||||||
compile({Permission, all}) when
|
compile({Permission, all}) when
|
||||||
?IS_PERMISSION(Permission)
|
?IS_PERMISSION(Permission)
|
||||||
->
|
->
|
||||||
|
|
|
@ -25,6 +25,30 @@
|
||||||
|
|
||||||
-include("emqx_authz.hrl").
|
-include("emqx_authz.hrl").
|
||||||
|
|
||||||
|
%% Raw rules have the following format:
|
||||||
|
%% [
|
||||||
|
%% #{
|
||||||
|
%% %% <<"allow">> | <"deny">>,
|
||||||
|
%% <<"permission">> => <<"allow">>,
|
||||||
|
%%
|
||||||
|
%% %% <<"pub">> | <<"sub">> | <<"all">>
|
||||||
|
%% <<"action">> => <<"pub">>,
|
||||||
|
%%
|
||||||
|
%% %% <<"a/$#">>, <<"eq a/b/+">>, ...
|
||||||
|
%% <<"topic">> => TopicFilter,
|
||||||
|
%%
|
||||||
|
%% %% when 'topic' is not provided
|
||||||
|
%% <<"topics">> => [TopicFilter],
|
||||||
|
%%
|
||||||
|
%% %% 0 | 1 | 2 | [0, 1, 2] | <<"0">> | <<"1">> | ...
|
||||||
|
%% <<"qos">> => 0,
|
||||||
|
%%
|
||||||
|
%% %% true | false | all | 0 | 1 | <<"true">> | ...
|
||||||
|
%% %% only for pub action
|
||||||
|
%% <<"retain">> => true
|
||||||
|
%% },
|
||||||
|
%% ...
|
||||||
|
%% ],
|
||||||
-type rule_raw() :: #{binary() => binary() | [binary()]}.
|
-type rule_raw() :: #{binary() => binary() | [binary()]}.
|
||||||
|
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
|
@ -33,9 +57,9 @@
|
||||||
|
|
||||||
-spec parse_rule(rule_raw()) ->
|
-spec parse_rule(rule_raw()) ->
|
||||||
{ok, {
|
{ok, {
|
||||||
emqx_authz_rule:permission(),
|
emqx_authz_rule:permission_resolution_precompile(),
|
||||||
emqx_authz_rule:action_condition(),
|
emqx_authz_rule:action_precompile(),
|
||||||
emqx_authz_rule:topic_condition()
|
emqx_authz_rule:topic_precompile()
|
||||||
}}
|
}}
|
||||||
| {error, map()}.
|
| {error, map()}.
|
||||||
parse_rule(
|
parse_rule(
|
||||||
|
@ -65,9 +89,9 @@ parse_rule(RuleRaw) ->
|
||||||
}}.
|
}}.
|
||||||
|
|
||||||
-spec format_rule({
|
-spec format_rule({
|
||||||
emqx_authz_rule:permission(),
|
emqx_authz_rule:permission_resolution_precompile(),
|
||||||
emqx_authz_rule:action_condition(),
|
emqx_authz_rule:action_precompile(),
|
||||||
emqx_authz_rule:topic_condition()
|
emqx_authz_rule:topic_precompile()
|
||||||
}) -> map().
|
}) -> map().
|
||||||
format_rule({Permission, Action, Topics}) when is_list(Topics) ->
|
format_rule({Permission, Action, Topics}) when is_list(Topics) ->
|
||||||
maps:merge(
|
maps:merge(
|
||||||
|
|
|
@ -75,22 +75,35 @@ destroy(_Source) -> ok.
|
||||||
%% v2: (rules are checked in sequence, passthrough when no match)
|
%% v2: (rules are checked in sequence, passthrough when no match)
|
||||||
%%
|
%%
|
||||||
%% [{
|
%% [{
|
||||||
%% Permission :: emqx_authz_rule:permission(),
|
%% Permission :: emqx_authz_rule:permission_resolution(),
|
||||||
%% Action :: emqx_authz_rule:action_condition(),
|
%% Action :: emqx_authz_rule:action_condition(),
|
||||||
%% Topics :: emqx_authz_rule:topic_condition()
|
%% Topics :: emqx_authz_rule:topic_condition()
|
||||||
%% }]
|
%% }]
|
||||||
%%
|
%%
|
||||||
%% which is compiled from raw rules like below by emqx_authz_rule_raw
|
%% which is compiled from raw rule maps like below by `emqx_authz_rule_raw`
|
||||||
%%
|
%%
|
||||||
%% [
|
%% [
|
||||||
%% #{
|
%% #{
|
||||||
%% permission := allow | deny
|
%% %% <<"allow">> | <"deny">>,
|
||||||
%% action := pub | sub | all
|
%% <<"permission">> => <<"allow">>,
|
||||||
%% topic => TopicFilter,
|
%%
|
||||||
%% topics => [TopicFilter] %% when 'topic' is not provided
|
%% %% <<"pub">> | <<"sub">> | <<"all">>
|
||||||
%% qos => 0 | 1 | 2 | [0, 1, 2]
|
%% <<"action">> => <<"pub">>,
|
||||||
%% retain => true | false | all %% only for pub action
|
%%
|
||||||
%% }
|
%% %% <<"a/$#">>, <<"eq a/b/+">>, ...
|
||||||
|
%% <<"topic">> => TopicFilter,
|
||||||
|
%%
|
||||||
|
%% %% when 'topic' is not provided
|
||||||
|
%% <<"topics">> => [TopicFilter],
|
||||||
|
%%
|
||||||
|
%% %% 0 | 1 | 2 | [0, 1, 2] | <<"0">> | <<"1">> | ...
|
||||||
|
%% <<"qos">> => 0,
|
||||||
|
%%
|
||||||
|
%% %% true | false | all | 0 | 1 | <<"true">> | ...
|
||||||
|
%% %% only for pub action
|
||||||
|
%% <<"retain">> => true
|
||||||
|
%% },
|
||||||
|
%% ...
|
||||||
%% ]
|
%% ]
|
||||||
%%
|
%%
|
||||||
authorize(#{acl := Acl} = Client, PubSub, Topic, _Source) ->
|
authorize(#{acl := Acl} = Client, PubSub, Topic, _Source) ->
|
||||||
|
|
|
@ -33,7 +33,9 @@
|
||||||
-type who() :: username() | clientid() | all.
|
-type who() :: username() | clientid() | all.
|
||||||
|
|
||||||
-type rule() :: {
|
-type rule() :: {
|
||||||
emqx_authz_rule:permission(), emqx_authz_rule:action_precompile(), emqx_types:topic()
|
emqx_authz_rule:permission_resolution_precompile(),
|
||||||
|
emqx_authz_rule:action_precompile(),
|
||||||
|
emqx_authz_rule:topic_precompile()
|
||||||
}.
|
}.
|
||||||
-type rules() :: [rule()].
|
-type rules() :: [rule()].
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue