chore(gw): integrate with emqx-authn

This commit is contained in:
JianBo He 2021-08-03 14:07:40 +08:00
parent cf20fc6db7
commit f36c523ae8
6 changed files with 65 additions and 23 deletions

View File

@ -28,6 +28,10 @@
-export([ authenticator_name/1 -export([ authenticator_name/1
]). ]).
%% Export it for emqx_gateway_schema module
-export([ authenticators/1
]).
structs() -> [ "authentication" ]. structs() -> [ "authentication" ].
fields("authentication") -> fields("authentication") ->

View File

@ -16,7 +16,14 @@ gateway: {
password: "${Packet.headers.passcode}" password: "${Packet.headers.passcode}"
} }
authenticator: allow_anonymous authenticators: [
{
name: "authenticator1"
mechanism: password-based
server_type: built-in-database
user_id_type: clientid
}
]
listener.tcp.1: { listener.tcp.1: {
bind: 61613 bind: 61613
@ -29,7 +36,7 @@ gateway: {
coap.1: { coap.1: {
enable_stats: false enable_stats: false
authenticator: allow_anonymous authenticators: []
heartbeat: 30s heartbeat: 30s
resource: mqtt resource: mqtt
notify_type: qos notify_type: qos
@ -42,7 +49,7 @@ gateway: {
coap.2: { coap.2: {
enable_stats: false enable_stats: false
authenticator: allow_anonymous authenticators: []
heartbeat: 30s heartbeat: 30s
resource: pubsub resource: pubsub
notify_type: non notify_type: non
@ -114,7 +121,7 @@ gateway: {
#ssl.cacertfile: #ssl.cacertfile:
} }
authenticator: allow_anonymous authenticators: []
listener.tcp.1: { listener.tcp.1: {
bind: 7993 bind: 7993

View File

@ -32,7 +32,7 @@
%% Gateway ID %% Gateway ID
, type := gateway_type() , type := gateway_type()
%% Autenticator %% Autenticator
, auth := emqx_authn:chain_id() , auth := emqx_authn:chain_id() | undefined
%% The ConnectionManager PID %% The ConnectionManager PID
, cm := pid() , cm := pid()
}. }.
@ -65,6 +65,8 @@
-spec authenticate(context(), emqx_types:clientinfo()) -spec authenticate(context(), emqx_types:clientinfo())
-> {ok, emqx_types:clientinfo()} -> {ok, emqx_types:clientinfo()}
| {error, any()}. | {error, any()}.
authenticate(_Ctx = #{auth := undefined}, ClientInfo) ->
{ok, mountpoint(ClientInfo)};
authenticate(_Ctx = #{auth := ChainId}, ClientInfo0) -> authenticate(_Ctx = #{auth := ChainId}, ClientInfo0) ->
ClientInfo = ClientInfo0#{ ClientInfo = ClientInfo0#{
zone => default, zone => default,
@ -78,7 +80,7 @@ authenticate(_Ctx = #{auth := ChainId}, ClientInfo0) ->
{error, Reason} {error, Reason}
end; end;
authenticate(_Ctx, ClientInfo) -> authenticate(_Ctx, ClientInfo) ->
{ok, ClientInfo}. {ok, mountpoint(ClientInfo)}.
%% @doc Register the session to the cluster. %% @doc Register the session to the cluster.
%% %%

View File

@ -86,8 +86,8 @@ call(Pid, Req) ->
init([Insta, Ctx0, _GwDscrptr]) -> init([Insta, Ctx0, _GwDscrptr]) ->
process_flag(trap_exit, true), process_flag(trap_exit, true),
#{rawconf := RawConf} = Insta, #{id := InstaId, rawconf := RawConf} = Insta,
Ctx = do_init_context(RawConf, Ctx0), Ctx = do_init_context(InstaId, RawConf, Ctx0),
State = #state{ State = #state{
insta = Insta, insta = Insta,
ctx = Ctx, ctx = Ctx,
@ -103,16 +103,16 @@ init([Insta, Ctx0, _GwDscrptr]) ->
{ok, NState} {ok, NState}
end. end.
do_init_context(RawConf, Ctx) -> do_init_context(InstaId, RawConf, Ctx) ->
Auth = case maps:get(authenticator, RawConf, allow_anonymous) of Auth = case maps:get(authenticators, RawConf, []) of
allow_anonymous -> allow_anonymous; [] -> undefined;
Funcs when is_list(Funcs) -> AuthCfgs when is_list(AuthCfgs) ->
create_authenticator_for_gateway_insta(Funcs) create_authenticators_for_gateway_insta(InstaId, AuthCfgs)
end, end,
Ctx#{auth => Auth}. Ctx#{auth => Auth}.
do_deinit_context(Ctx) -> do_deinit_context(Ctx) ->
cleanup_authenticator_for_gateway_insta(maps:get(auth, Ctx)), cleanup_authenticators_for_gateway_insta(maps:get(auth, Ctx)),
ok. ok.
handle_call(info, _From, State = #state{insta = Insta}) -> handle_call(info, _From, State = #state{insta = Insta}) ->
@ -213,13 +213,42 @@ code_change(_OldVsn, State, _Extra) ->
%% Internal funcs %% Internal funcs
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
create_authenticator_for_gateway_insta(_Funcs) -> %% @doc AuthCfgs is a array of authenticatior configurations,
todo. %% see: emqx_authn_schema:authenticators/1
create_authenticators_for_gateway_insta(InstaId0, AuthCfgs) ->
ChainId = atom_to_binary(InstaId0, utf8),
case emqx_authn:create_chain(#{id => ChainId}) of
{ok, _ChainInfo} ->
Results = lists:map(fun(AuthCfg = #{name := Name}) ->
case emqx_authn:create_authenticator(
ChainId,
AuthCfg) of
{ok, _AuthInfo} -> ok;
{error, Reason} -> {Name, Reason}
end
end, AuthCfgs),
NResults = [ E || E <- Results, E /= ok],
NResults /= [] andalso begin
logger:error("Failed to create authenticators: ~p", [NResults]),
throw({bad_autheticators, NResults})
end, ok;
{error, Reason} ->
logger:error("Failed to create authenticator chain: ~p", [Reason]),
throw({bad_chain, {ChainId, Reason}})
end.
cleanup_authenticator_for_gateway_insta(allow_anonymouse) -> cleanup_authenticators_for_gateway_insta(undefined) ->
ok; ok;
cleanup_authenticator_for_gateway_insta(_ChainId) -> cleanup_authenticators_for_gateway_insta(ChainId) ->
todo. case emqx_authn:delete_chain(ChainId) of
ok -> ok;
{error, {not_found, _}} ->
logger:warning("Failed clean authenticator chain: ~s, "
"reason: not_found", [ChainId]);
{error, Reason} ->
logger:error("Failed clean authenticator chain: ~s, "
"reason: ~p", [ChainId, Reason])
end.
cb_insta_destroy(State = #state{insta = Insta = #{type := Type}, cb_insta_destroy(State = #state{insta = Insta = #{type := Type},
insta_state = InstaState}) -> insta_state = InstaState}) ->

View File

@ -46,7 +46,7 @@ fields(stomp) ->
fields(stomp_structs) -> fields(stomp_structs) ->
[ {frame, t(ref(stomp_frame))} [ {frame, t(ref(stomp_frame))}
, {clientinfo_override, t(ref(clientinfo_override))} , {clientinfo_override, t(ref(clientinfo_override))}
, {authenticator, t(union([allow_anonymous]))} , {authenticators, fun emqx_authn_schema:authenticators/1}
, {listener, t(ref(tcp_listener_group))} , {listener, t(ref(tcp_listener_group))}
]; ];
@ -97,7 +97,7 @@ fields(exproto) ->
fields(exproto_structs) -> fields(exproto_structs) ->
[ {server, t(ref(exproto_grpc_server))} [ {server, t(ref(exproto_grpc_server))}
, {handler, t(ref(exproto_grpc_handler))} , {handler, t(ref(exproto_grpc_handler))}
, {authenticator, t(union([allow_anonymous]))} , {authenticators, fun emqx_authn_schema:authenticators/1}
, {listener, t(ref(udp_tcp_listener_group))} , {listener, t(ref(udp_tcp_listener_group))}
]; ];
@ -209,7 +209,7 @@ fields(coap) ->
fields(coap_structs) -> fields(coap_structs) ->
[ {enable_stats, t(boolean(), undefined, true)} [ {enable_stats, t(boolean(), undefined, true)}
, {authenticator, t(union([allow_anonymous]))} , {authenticators, fun emqx_authn_schema:authenticators/1}
, {heartbeat, t(duration(), undefined, "15s")} , {heartbeat, t(duration(), undefined, "15s")}
, {resource, t(union([mqtt, pubsub]), undefined, mqtt)} , {resource, t(union([mqtt, pubsub]), undefined, mqtt)}
, {notify_type, t(union([non, con, qos]), undefined, qos)} , {notify_type, t(union([non, con, qos]), undefined, qos)}

View File

@ -109,7 +109,7 @@ format_listenon({Addr, Port}) when is_tuple(Addr) ->
-type rawconf() :: -type rawconf() ::
#{ clientinfo_override => #{} #{ clientinfo_override => #{}
, authenticators := #{} , authenticators := list()
, listeners => listener() , listeners => listener()
, atom() => any() , atom() => any()
}. }.