refactor(client_attr): allow more than one initial extraction
This commit is contained in:
parent
2577224bc7
commit
da5b01aa46
|
@ -269,8 +269,7 @@ init(
|
|||
},
|
||||
Zone
|
||||
),
|
||||
AttrExtractionConfig = get_mqtt_conf(Zone, client_attrs_init),
|
||||
ClientInfo = initialize_client_attrs_from_cert(AttrExtractionConfig, ClientInfo0, Peercert),
|
||||
ClientInfo = initialize_client_attrs_from_cert(ClientInfo0, Peercert),
|
||||
{NClientInfo, NConnInfo} = take_ws_cookie(ClientInfo, ConnInfo),
|
||||
#channel{
|
||||
conninfo = NConnInfo,
|
||||
|
@ -1575,7 +1574,7 @@ enrich_client(ConnPkt, Channel = #channel{clientinfo = ClientInfo}) ->
|
|||
fun maybe_username_as_clientid/2,
|
||||
fun maybe_assign_clientid/2,
|
||||
%% attr init should happen after clientid and username assign
|
||||
fun maybe_set_client_initial_attr/2
|
||||
fun maybe_set_client_initial_attrs/2
|
||||
],
|
||||
ConnPkt,
|
||||
ClientInfo
|
||||
|
@ -1587,7 +1586,17 @@ enrich_client(ConnPkt, Channel = #channel{clientinfo = ClientInfo}) ->
|
|||
{error, ReasonCode, Channel#channel{clientinfo = NClientInfo}}
|
||||
end.
|
||||
|
||||
initialize_client_attrs_from_cert(
|
||||
initialize_client_attrs_from_cert(#{zone := Zone} = ClientInfo, Peercert) ->
|
||||
Inits = get_client_attrs_init_config(Zone),
|
||||
lists:foldl(
|
||||
fun(Init, Acc) ->
|
||||
do_initialize_client_attrs_from_cert(Init, Acc, Peercert)
|
||||
end,
|
||||
ClientInfo,
|
||||
Inits
|
||||
).
|
||||
|
||||
do_initialize_client_attrs_from_cert(
|
||||
#{
|
||||
extract_from := From,
|
||||
extract_regexp := Regexp,
|
||||
|
@ -1596,6 +1605,8 @@ initialize_client_attrs_from_cert(
|
|||
ClientInfo,
|
||||
Peercert
|
||||
) when From =:= cn orelse From =:= dn ->
|
||||
Attrs0 = maps:get(client_attrs, ClientInfo, #{}),
|
||||
Attrs =
|
||||
case extract_client_attr_from_cert(From, Regexp, Peercert) of
|
||||
{ok, Value} ->
|
||||
?SLOG(
|
||||
|
@ -1606,11 +1617,12 @@ initialize_client_attrs_from_cert(
|
|||
extracted_value => Value
|
||||
}
|
||||
),
|
||||
ClientInfo#{client_attrs => #{AttrName => Value}};
|
||||
Attrs0#{AttrName => Value};
|
||||
_ ->
|
||||
ClientInfo#{client_attrs => #{}}
|
||||
end;
|
||||
initialize_client_attrs_from_cert(_, ClientInfo, _Peercert) ->
|
||||
Attrs0
|
||||
end,
|
||||
ClientInfo#{client_attrs => Attrs};
|
||||
do_initialize_client_attrs_from_cert(_, ClientInfo, _Peercert) ->
|
||||
ClientInfo.
|
||||
|
||||
extract_client_attr_from_cert(cn, Regexp, Peercert) ->
|
||||
|
@ -1668,13 +1680,24 @@ maybe_assign_clientid(#mqtt_packet_connect{clientid = <<>>}, ClientInfo) ->
|
|||
maybe_assign_clientid(#mqtt_packet_connect{clientid = ClientId}, ClientInfo) ->
|
||||
{ok, ClientInfo#{clientid => ClientId}}.
|
||||
|
||||
maybe_set_client_initial_attr(ConnPkt, #{zone := Zone} = ClientInfo0) ->
|
||||
Config = get_mqtt_conf(Zone, client_attrs_init),
|
||||
ClientInfo = initialize_client_attrs_from_user_property(Config, ConnPkt, ClientInfo0),
|
||||
get_client_attrs_init_config(Zone) ->
|
||||
case get_mqtt_conf(Zone, client_attrs_init, []) of
|
||||
L when is_list(L) -> L;
|
||||
M when is_map(M) -> [M]
|
||||
end.
|
||||
|
||||
maybe_set_client_initial_attrs(ConnPkt, #{zone := Zone} = ClientInfo0) ->
|
||||
Inits = get_client_attrs_init_config(Zone),
|
||||
ClientInfo = initialize_client_attrs_from_user_property(Inits, ConnPkt, ClientInfo0),
|
||||
{ok, initialize_client_attrs_from_clientinfo(Inits, ClientInfo)}.
|
||||
|
||||
initialize_client_attrs_from_clientinfo(Inits, ClientInfo) ->
|
||||
lists:foldl(
|
||||
fun(Init, Acc) ->
|
||||
Attrs = maps:get(client_attrs, ClientInfo, #{}),
|
||||
case extract_attr_from_clientinfo(Config, ClientInfo) of
|
||||
case extract_attr_from_clientinfo(Init, ClientInfo) of
|
||||
{ok, Value} ->
|
||||
#{extract_as := Name} = Config,
|
||||
#{extract_as := Name} = Init,
|
||||
?SLOG(
|
||||
debug,
|
||||
#{
|
||||
|
@ -1683,12 +1706,25 @@ maybe_set_client_initial_attr(ConnPkt, #{zone := Zone} = ClientInfo0) ->
|
|||
extracted_value => Value
|
||||
}
|
||||
),
|
||||
{ok, ClientInfo#{client_attrs => Attrs#{Name => Value}}};
|
||||
Acc#{client_attrs => Attrs#{Name => Value}};
|
||||
_ ->
|
||||
{ok, ClientInfo}
|
||||
end.
|
||||
Acc
|
||||
end
|
||||
end,
|
||||
ClientInfo,
|
||||
Inits
|
||||
).
|
||||
|
||||
initialize_client_attrs_from_user_property(
|
||||
initialize_client_attrs_from_user_property(Inits, ConnPkt, ClientInfo) ->
|
||||
lists:foldl(
|
||||
fun(Init, Acc) ->
|
||||
do_initialize_client_attrs_from_user_property(Init, ConnPkt, Acc)
|
||||
end,
|
||||
ClientInfo,
|
||||
Inits
|
||||
).
|
||||
|
||||
do_initialize_client_attrs_from_user_property(
|
||||
#{
|
||||
extract_from := user_property,
|
||||
extract_as := PropertyKey
|
||||
|
@ -1696,6 +1732,8 @@ initialize_client_attrs_from_user_property(
|
|||
ConnPkt,
|
||||
ClientInfo
|
||||
) ->
|
||||
Attrs0 = maps:get(client_attrs, ClientInfo, #{}),
|
||||
Attrs =
|
||||
case extract_client_attr_from_user_property(ConnPkt, PropertyKey) of
|
||||
{ok, Value} ->
|
||||
?SLOG(
|
||||
|
@ -1706,11 +1744,12 @@ initialize_client_attrs_from_user_property(
|
|||
extracted_value => Value
|
||||
}
|
||||
),
|
||||
ClientInfo#{client_attrs => #{PropertyKey => Value}};
|
||||
Attrs0#{PropertyKey => Value};
|
||||
_ ->
|
||||
ClientInfo
|
||||
end;
|
||||
initialize_client_attrs_from_user_property(_, _ConnInfo, ClientInfo) ->
|
||||
Attrs0
|
||||
end,
|
||||
ClientInfo#{client_attrs => Attrs};
|
||||
do_initialize_client_attrs_from_user_property(_, _ConnPkt, ClientInfo) ->
|
||||
ClientInfo.
|
||||
|
||||
extract_client_attr_from_user_property(
|
||||
|
|
|
@ -3552,9 +3552,9 @@ mqtt_general() ->
|
|||
)},
|
||||
{"client_attrs_init",
|
||||
sc(
|
||||
hoconsc:union([disabled, ref("client_attrs_init")]),
|
||||
hoconsc:union([hoconsc:array(ref("client_attrs_init")), ref("client_attrs_init")]),
|
||||
#{
|
||||
default => disabled,
|
||||
default => [],
|
||||
desc => ?DESC("client_attrs_init")
|
||||
}
|
||||
)}
|
||||
|
|
|
@ -454,7 +454,7 @@ zone_global_defaults() ->
|
|||
upgrade_qos => false,
|
||||
use_username_as_clientid => false,
|
||||
wildcard_subscription => true,
|
||||
client_attrs_init => disabled
|
||||
client_attrs_init => []
|
||||
},
|
||||
overload_protection =>
|
||||
#{
|
||||
|
|
|
@ -170,7 +170,7 @@ t_client_attr_as_mountpoint(_Config) ->
|
|||
?assertMatch([_], emqx_router:match_routes(MatchTopic)),
|
||||
emqtt:stop(Client)
|
||||
end),
|
||||
emqx_config:put_zone_conf(default, [mqtt, client_attrs_init], disabled),
|
||||
emqx_config:put_zone_conf(default, [mqtt, client_attrs_init], []),
|
||||
ok.
|
||||
|
||||
t_current_conns_tcp(_Config) ->
|
||||
|
|
|
@ -572,7 +572,7 @@ t_alias_prefix(_Config) ->
|
|||
?assertMatch({ok, _, [?RC_NOT_AUTHORIZED]}, emqtt:subscribe(C, SubTopicNotAllowed)),
|
||||
unlink(C),
|
||||
emqtt:stop(C),
|
||||
emqx_config:put_zone_conf(default, [mqtt, client_attrs_init], disalbed),
|
||||
emqx_config:put_zone_conf(default, [mqtt, client_attrs_init], []),
|
||||
ok.
|
||||
|
||||
%% client is allowed by ACL to publish to its LWT topic, is connected,
|
||||
|
|
|
@ -7,7 +7,7 @@ an MQTT connection.
|
|||
|
||||
### Initialization of `client_attrs`
|
||||
|
||||
- The `client_attrs` field can be initially populated based on the configuration from one of the
|
||||
- The `client_attrs` fields can be initially populated based on the configuration from one of the
|
||||
following sources:
|
||||
- `cn`: The common name from the TLS client's certificate.
|
||||
- `dn`: The distinguished name from the TLS client's certificate, that is, the certificate "Subject".
|
||||
|
|
|
@ -1575,7 +1575,8 @@ client_attrs_init {
|
|||
label: "Client Attributes Initialization"
|
||||
desc: """~
|
||||
Specify how to initialize client attributes.
|
||||
One initial client attribute can be initialized as `client_attrs.NAME`,
|
||||
This config accepts one initialization rule, or a list of rules.
|
||||
Client attributes 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_attrs` property with the specified name,
|
||||
and can be used as a placeholder in a template for authentication and authorization.
|
||||
|
|
Loading…
Reference in New Issue