fix: add debug level logging for invalid client attributes

This commit is contained in:
zmstone 2024-03-22 10:07:48 +01:00
parent 0cf61932b6
commit 5e9814d171
5 changed files with 19 additions and 20 deletions

View File

@ -1846,7 +1846,7 @@ do_authenticate(Credential, #channel{clientinfo = ClientInfo} = Channel) ->
%% 1. `is_superuser': The superuser flag from various backends %% 1. `is_superuser': The superuser flag from various backends
%% 2. `acl': ACL rules from JWT, HTTP auth backend %% 2. `acl': ACL rules from JWT, HTTP auth backend
%% 3. `client_attrs': Extra client attributes 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) -> merge_auth_result(ClientInfo, AuthResult0) when is_map(ClientInfo) andalso is_map(AuthResult0) ->
IsSuperuser = maps:get(is_superuser, AuthResult0, false), IsSuperuser = maps:get(is_superuser, AuthResult0, false),
AuthResult = maps:without([client_attrs], AuthResult0), AuthResult = maps:without([client_attrs], AuthResult0),

View File

@ -216,12 +216,18 @@ client_attrs(_) ->
drop_invalid_attr(Map) when is_map(Map) -> drop_invalid_attr(Map) when is_map(Map) ->
maps:from_list(do_drop_invalid_attr(maps:to_list(Map))). maps:from_list(do_drop_invalid_attr(maps:to_list(Map))).
do_drop_invalid_attr(KVL) -> do_drop_invalid_attr([]) ->
F = fun({K, V}) -> [];
emqx_utils:is_restricted_str(K) andalso do_drop_invalid_attr([{K, V} | More]) ->
emqx_utils:is_restricted_str(V) case emqx_utils:is_restricted_str(K) andalso emqx_utils:is_restricted_str(V) of
end, true ->
lists:filter(F, KVL). [{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) -> ensure_apps_started(bcrypt) ->
{ok, _} = application:ensure_all_started(bcrypt), {ok, _} = application:ensure_all_started(bcrypt),

View File

@ -157,15 +157,8 @@ validate(Allowed, Template) ->
{error, [{Var, disallowed} || Var <- Disallowed]} {error, [{Var, disallowed} || Var <- Disallowed]}
end. end.
find_disallowed([], _Allowed) -> find_disallowed(Vars, Allowed) ->
[]; lists:filter(fun(Var) -> not is_allowed(Var, Allowed) end, Vars).
find_disallowed([Var | Rest], Allowed) ->
case is_allowed(Var, Allowed) of
true ->
find_disallowed(Rest, Allowed);
false ->
[Var | find_disallowed(Rest, Allowed)]
end.
is_allowed(_Var, []) -> is_allowed(_Var, []) ->
false; false;

View File

@ -11,7 +11,7 @@ attributes derived from the `clientinfo` fields upon accepting an MQTT connectio
- `clientid`: The MQTT client ID provided by the client. - `clientid`: The MQTT client ID provided by the client.
- `username`: The username provided by the client. - `username`: The username provided by the client.
- `cn`: The common name from the TLS client's certificate. - `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 ### Extension through Authentication Responses

View File

@ -1577,7 +1577,7 @@ client_attrs_init {
Specify how to initialize client attributes. Specify how to initialize client attributes.
One initial client attribute can be initialized as `client_attrs.NAME`, 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`. 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. 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`.""" 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 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. 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 `^(.+?)-.*$`. 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 { client_attrs_init_extract_as {
label: "Name the extracted attribute" label: "Name the extracted attribute"
desc: """~ desc: """~
The name of the client attribute extracted from the client property specified by `client_attrs_init.extract_from` config. 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.""" In case `extract_from = user_property`, this should be the key of the user property."""
} }