diff --git a/apps/emqx/src/emqx_channel.erl b/apps/emqx/src/emqx_channel.erl index 99a991225..49a5b2226 100644 --- a/apps/emqx/src/emqx_channel.erl +++ b/apps/emqx/src/emqx_channel.erl @@ -1846,7 +1846,7 @@ do_authenticate(Credential, #channel{clientinfo = ClientInfo} = Channel) -> %% 1. `is_superuser': The superuser flag from various backends %% 2. `acl': ACL rules from JWT, HTTP auth backend %% 3. `client_attrs': Extra client attributes from JWT, HTTP auth backend -%% 4. Maybe more non-standard fileds used by hook callbacks +%% 4. Maybe more non-standard fields used by hook callbacks merge_auth_result(ClientInfo, AuthResult0) when is_map(ClientInfo) andalso is_map(AuthResult0) -> IsSuperuser = maps:get(is_superuser, AuthResult0, false), AuthResult = maps:without([client_attrs], AuthResult0), diff --git a/apps/emqx_auth/src/emqx_authn/emqx_authn_utils.erl b/apps/emqx_auth/src/emqx_authn/emqx_authn_utils.erl index 3e12e3992..9ce934a30 100644 --- a/apps/emqx_auth/src/emqx_authn/emqx_authn_utils.erl +++ b/apps/emqx_auth/src/emqx_authn/emqx_authn_utils.erl @@ -216,12 +216,18 @@ client_attrs(_) -> drop_invalid_attr(Map) when is_map(Map) -> maps:from_list(do_drop_invalid_attr(maps:to_list(Map))). -do_drop_invalid_attr(KVL) -> - F = fun({K, V}) -> - emqx_utils:is_restricted_str(K) andalso - emqx_utils:is_restricted_str(V) - end, - lists:filter(F, KVL). +do_drop_invalid_attr([]) -> + []; +do_drop_invalid_attr([{K, V} | More]) -> + case emqx_utils:is_restricted_str(K) andalso emqx_utils:is_restricted_str(V) of + true -> + [{iolist_to_binary(K), iolist_to_binary(V)} | do_drop_invalid_attr(More)]; + false -> + ?SLOG(debug, #{msg => "invalid_client_attr_dropped", key => K, value => V}, #{ + tag => "AUTHN" + }), + do_drop_invalid_attr(More) + end. ensure_apps_started(bcrypt) -> {ok, _} = application:ensure_all_started(bcrypt), diff --git a/apps/emqx_utils/src/emqx_template.erl b/apps/emqx_utils/src/emqx_template.erl index 21c0e1d4f..b0272b1bb 100644 --- a/apps/emqx_utils/src/emqx_template.erl +++ b/apps/emqx_utils/src/emqx_template.erl @@ -157,15 +157,8 @@ validate(Allowed, Template) -> {error, [{Var, disallowed} || Var <- Disallowed]} end. -find_disallowed([], _Allowed) -> - []; -find_disallowed([Var | Rest], Allowed) -> - case is_allowed(Var, Allowed) of - true -> - find_disallowed(Rest, Allowed); - false -> - [Var | find_disallowed(Rest, Allowed)] - end. +find_disallowed(Vars, Allowed) -> + lists:filter(fun(Var) -> not is_allowed(Var, Allowed) end, Vars). is_allowed(_Var, []) -> false; diff --git a/changes/ce/feat-12750.en.md b/changes/ce/feat-12750.en.md index 92886d298..33c1d0b4f 100644 --- a/changes/ce/feat-12750.en.md +++ b/changes/ce/feat-12750.en.md @@ -11,7 +11,7 @@ attributes derived from the `clientinfo` fields upon accepting an MQTT connectio - `clientid`: The MQTT client ID provided by the client. - `username`: The username provided by the client. - `cn`: The common name from the TLS client's certificate. - - `dn`: The distinguish name from the TLS client's certificate, i.e., the certificate "Subject". + - `dn`: The distinguished name from the TLS client's certificate, i.e., the certificate "Subject". ### Extension through Authentication Responses diff --git a/rel/i18n/emqx_schema.hocon b/rel/i18n/emqx_schema.hocon index b65cb76b3..32b8ff8e9 100644 --- a/rel/i18n/emqx_schema.hocon +++ b/rel/i18n/emqx_schema.hocon @@ -1577,7 +1577,7 @@ client_attrs_init { Specify how to initialize client attributes. One initial client attribute can be initialized as `client_attrs.NAME`, where `NAME` is the name of the attribute specified in the config `extract_as`. - The initialized client attribute will be stored in the `client_attr` property with the specified name, + The initialized client attribute will be stored in the `client_attrs` property with the specified name, and can be used as a placeholder in a template for authentication and authorization. For example, use `${client_attrs.alias}` to render a HTTP POST body when `extract_as = alias`.""" } @@ -1605,14 +1605,14 @@ client_attrs_init_extract_regexp { The regular expression to extract a client attribute from the client property specified by `client_attrs_init.extract_from` config. The expression should match the entire client property value, and capturing groups are concatenated to make the client attribute. For example if the client attribute is the first part of the client ID delemited by a dash, the regular expression would be `^(.+?)-.*$`. - Note that failure to match the regular expression will result in the client attribute being absence but not an empty string.""" + Note that failure to match the regular expression will result in the client attribute being absent but not an empty string.""" } client_attrs_init_extract_as { label: "Name the extracted attribute" desc: """~ The name of the client attribute extracted from the client property specified by `client_attrs_init.extract_from` config. - The extracted attribute will be stored in the `client_attr` property with this name. + The extracted attribute will be stored in the `client_attrs` property with this name. In case `extract_from = user_property`, this should be the key of the user property.""" }