diff --git a/apps/emqx/src/emqx_access_control.erl b/apps/emqx/src/emqx_access_control.erl
index 914651535..35b3767e0 100644
--- a/apps/emqx/src/emqx_access_control.erl
+++ b/apps/emqx/src/emqx_access_control.erl
@@ -63,4 +63,5 @@ do_authorize(ClientInfo, PubSub, Topic) ->
-compile({inline, [run_hooks/3]}).
run_hooks(Name, Args, Acc) ->
- ok = emqx_metrics:inc(Name), emqx_hooks:run_fold(Name, Args, Acc).
+ ok = emqx_metrics:inc(Name),
+ emqx_hooks:run_fold(Name, Args, Acc).
diff --git a/apps/emqx/src/emqx_schema.erl b/apps/emqx/src/emqx_schema.erl
index 2415f051c..1c471da90 100644
--- a/apps/emqx/src/emqx_schema.erl
+++ b/apps/emqx/src/emqx_schema.erl
@@ -108,9 +108,27 @@ in zone
configs"""
})}
, {?EMQX_AUTHENTICATION_CONFIG_ROOT_NAME,
authentication(
-"""Default authentication configs for all MQTT listeners.
+"""Default authentication configs for all MQTT listeners.
+
For per-listener overrides see authentication
-in listener configs""")}
+in listener configs
+
+
+EMQ X can be configured with:
+
+
+[]
: The default value, it allows *ALL* logins
+- one: For example
{enable:true,backend:\"built-in-database\",mechanism=\"password-based\"}
+- chain: An array of structs.
+
+
+When a chain is configured, the login credentials are checked against the backends
+per the configured order, until an 'allow' or 'deny' decision can be made.
+
+If there is no decision after a full chain exhaustion, the login is rejected.
+""")}
+ %% NOTE: authorization schema here is only to keep emqx app prue
+ %% the full schema for EMQ X node is injected in emqx_conf_schema.
, {"authorization",
sc(ref("authorization"),
#{})}
diff --git a/apps/emqx_conf/src/emqx_conf_schema.erl b/apps/emqx_conf/src/emqx_conf_schema.erl
index 571644aaf..8103796b7 100644
--- a/apps/emqx_conf/src/emqx_conf_schema.erl
+++ b/apps/emqx_conf/src/emqx_conf_schema.erl
@@ -68,8 +68,7 @@ roots() ->
undefined -> persistent_term:put(PtKey, emqx_authn_schema);
_ -> ok
end,
- %% authorization configs are merged in THIS schema's "authorization" fields
- lists:keydelete("authorization", 1, emqx_schema:roots(high)) ++
+ emqx_schema_high_prio_roots() ++
[ {"node",
sc(hoconsc:ref("node"),
#{ desc => "Node name, cookie, config & data directories "
@@ -93,20 +92,6 @@ roots() ->
"should work, but in case you need to do performance "
"fine-turning or experiment a bit, this is where to look."
})}
- , {"authorization",
- sc(hoconsc:ref("authorization"),
- #{ desc => """
-Authorization a.k.a ACL.
-In EMQ X, MQTT client access control is extremly flexible.
-An out of the box set of authorization data sources are supported.
-For example,
-'file' source is to support concise and yet generic ACL rules in a file;
-'built-in-database' source can be used to store per-client customisable rule sets,
-natively in the EMQ X node;
-'http' source to make EMQ X call an external HTTP API to make the decision;
-'postgresql' etc. to look up clients or rules from external databases;
-"""
- })}
, {"db",
sc(ref("db"),
#{ desc => "Settings of the embedded database."
@@ -849,3 +834,22 @@ ensure_list(V) ->
roots(Module) ->
lists:map(fun({_BinName, Root}) -> Root end, hocon_schema:roots(Module)).
+
+%% Like authentication schema, authorization schema is incomplete in emqx_schema
+%% module, this function replaces the root filed "authorization" with a new schema
+emqx_schema_high_prio_roots() ->
+ Roots = emqx_schema:roots(high),
+ Authz = {"authorization",
+ sc(hoconsc:ref("authorization"),
+ #{ desc => """
+Authorization a.k.a ACL.
+In EMQ X, MQTT client access control is extremly flexible.
+An out of the box set of authorization data sources are supported.
+For example,
+'file' source is to support concise and yet generic ACL rules in a file;
+'built-in-database' source can be used to store per-client customisable rule sets,
+natively in the EMQ X node;
+'http' source to make EMQ X call an external HTTP API to make the decision;
+'postgresql' etc. to look up clients or rules from external databases;
+""" })},
+ lists:keyreplace("authorization", 1, Roots, Authz).