test(gateway): integration stomp && exproto test with http authn

This commit is contained in:
firest 2022-04-02 13:54:59 +08:00
parent 25ebe2535e
commit 0db6b8d47e
4 changed files with 229 additions and 107 deletions

View File

@ -40,6 +40,19 @@
-define(TCPOPTS, [binary, {active, false}]).
-define(DTLSOPTS, [binary, {active, false}, {protocol, dtls}]).
%%--------------------------------------------------------------------
-define(CONF_DEFAULT,
<<"\n"
"gateway.exproto {\n"
" server.bind = 9100,\n"
" handler.address = \"http://127.0.0.1:9001\"\n"
" listeners.tcp.default {\n"
" bind = 7993,\n"
" acceptors = 8\n"
" }\n"
"}\n">>
).
%%--------------------------------------------------------------------
%% Setups
%%--------------------------------------------------------------------
@ -84,6 +97,9 @@ listener_confs(Type) ->
Default = #{bind => 7993, acceptors => 8},
#{Type => #{'default' => maps:merge(Default, socketopts(Type))}}.
default_config() ->
?CONF_DEFAULT.
%%--------------------------------------------------------------------
%% Tests cases
%%--------------------------------------------------------------------

View File

@ -29,31 +29,45 @@
-define(HTTP_PORT, 33333).
-define(HTTP_PATH, "/auth").
-define(CREDENTIALS, #{username => <<"admin">>,
password => <<"public">>,
listener => 'tcp:default',
protocol => mqtt
}).
-define(checkMatch(Guard),
(fun (Expr) ->
(fun(Expr) ->
case (Expr) of
Guard -> ok;
Guard ->
ok;
X__V ->
erlang:error({assertMatch,
[{module, ?MODULE},
erlang:error(
{assertMatch, [
{module, ?MODULE},
{line, ?LINE},
{expression, (??Expr)},
{pattern, (??Guard)},
{value, X__V}]})
{value, X__V}
]}
)
end
end)).
end)
).
-define(FUNCTOR(Expr), fun() -> Expr end).
-define(FUNCTOR(Arg, Expr), fun(Arg) -> Expr end).
-define(PROTOCOLS, [coap, lwm2m, 'mqtt-sn'] ).
-define(CONFS, [emqx_coap_SUITE, emqx_lwm2m_SUITE, emqx_sn_protocol_SUITE]).
-define(CASES, [fun case_coap/0, fun case_lwm2m/0, fun case_emqx_sn/0, fun case_stomp/0]).
-define(PROTOCOLS, [coap, lwm2m, 'mqtt-sn', stomp, exproto]).
-define(CONFS, [
emqx_coap_SUITE,
emqx_lwm2m_SUITE,
emqx_sn_protocol_SUITE,
emqx_stomp_SUITE,
emqx_exproto_SUITE
]).
-define(CASES, [
fun case_coap/0,
fun case_lwm2m/0,
fun case_emqx_sn/0,
fun case_stomp/0,
fun case_exproto/0
]).
-define(AUTHNS, [fun set_http_authn/1]).
-type auth_controller() :: fun((start | stop) -> ok).
@ -101,11 +115,13 @@ case_coap() ->
emqx_coap_SUITE:do(Action)
end,
Prefix = emqx_coap_SUITE:mqtt_prefix(),
RightUrl = Prefix ++
RightUrl =
Prefix ++
"/connection?clientid=client1&username=admin&password=public",
Login(RightUrl, ?checkMatch({ok, created, _Data})),
LeftUrl = Prefix ++
LeftUrl =
Prefix ++
"/connection?clientid=client1&username=bad&password=bad",
Login(LeftUrl, ?checkMatch({error, bad_request, _Data})),
ok.
@ -118,20 +134,25 @@ case_lwm2m() ->
Epn = "urn:oma:lwm2m:oma:3",
Port = emqx_lwm2m_SUITE:default_port(),
Login = fun(URI, Checker) ->
with_resource(?FUNCTOR(gen_udp:open(0, [binary, {active, false}])),
with_resource(
?FUNCTOR(gen_udp:open(0, [binary, {active, false}])),
?FUNCTOR(Socket, gen_udp:close(Socket)),
fun(Socket) ->
Mod:test_send_coap_request(
Socket,
post,
Mod:sprintf(URI, [Port, Epn]),
#coap_content{content_format = <<"text/plain">>,
payload = <<"</1>, </2>, </3>, </4>, </5>">>},
#coap_content{
content_format = <<"text/plain">>,
payload = <<"</1>, </2>, </3>, </4>, </5>">>
},
[],
MsgId),
MsgId
),
Checker(Mod:test_recv_coap_response(Socket))
end)
end
)
end,
MakeCheker = fun(Type, Method) ->
@ -156,23 +177,94 @@ case_lwm2m() ->
case_emqx_sn() ->
Mod = emqx_sn_protocol_SUITE,
Login = fun(Expect) ->
with_resource(?FUNCTOR(gen_udp:open(0, [binary])),
with_resource(
?FUNCTOR(gen_udp:open(0, [binary])),
?FUNCTOR(Socket, gen_udp:close(Socket)),
fun(Socket) ->
Mod:send_connect_msg(Socket, <<"client_id_test1">>),
?assertEqual(Expect, Mod:receive_response(Socket))
end)
end
)
end,
Login(<<>>),
RawCfg = emqx_conf:get_raw([gateway, mqttsn], #{}),
NewCfg = RawCfg#{<<"clientinfo_override">> => #{<<"username">> => <<"admin">>,
<<"password">> => <<"public">>}},
NewCfg = RawCfg#{
<<"clientinfo_override">> => #{
<<"username">> => <<"admin">>,
<<"password">> => <<"public">>
}
},
emqx_gateway_conf:update_gateway(mqttsn, NewCfg),
Login(<<3, ?SN_CONNACK, 0>>),
ok.
case_stomp() ->
Mod = emqx_stomp_SUITE,
Login = fun(Username, Password, Checker) ->
Fun = fun(Sock) ->
gen_tcp:send(
Sock,
Mod:serialize(
<<"CONNECT">>,
[
{<<"accept-version">>, Mod:stomp_ver()},
{<<"host">>, <<"127.0.0.1:61613">>},
{<<"login">>, Username},
{<<"passcode">>, Password},
{<<"heart-beat">>, <<"1000,2000">>}
]
)
),
{ok, Data} = gen_tcp:recv(Sock, 0),
{ok, Frame, _, _} = Mod:parse(Data),
Checker(Frame)
end,
Mod:with_connection(Fun)
end,
Login(
<<"admin">>,
<<"public">>,
?FUNCTOR(
Frame,
?assertEqual(<<"CONNECTED">>, Mod:get_field(command, Frame))
)
),
Login(<<"bad">>, <<"bad">>, fun(Frame) ->
?assertEqual(<<"ERROR">>, Mod:get_field(command, Frame)),
?assertEqual(<<"Login Failed: not_authorized">>, Mod:get_field(body, Frame))
end),
ok.
case_exproto() ->
Mod = emqx_exproto_SUITE,
SvrMod = emqx_exproto_echo_svr,
Svrs = SvrMod:start(),
Login = fun(Username, Password, Expect) ->
with_resource(
?FUNCTOR(Mod:open(tcp)),
?FUNCTOR(Sock, Mod:close(Sock)),
fun(Sock) ->
Client = #{
proto_name => <<"demo">>,
proto_ver => <<"v0.1">>,
clientid => <<"test_client_1">>,
username => Username
},
ConnBin = SvrMod:frame_connect(Client, Password),
Mod:send(Sock, ConnBin),
{ok, Recv} = Mod:recv(Sock, 5000),
C = ?FUNCTOR(Bin, emqx_json:decode(Bin, [return_maps])),
?assertEqual(C(Expect), C(Recv))
end
)
end,
Login(<<"admin">>, <<"public">>, SvrMod:frame_connack(0)),
Login(<<"bad">>, <<"bad">>, SvrMod:frame_connack(1)),
SvrMod:stop(Svrs),
ok.
%%------------------------------------------------------------------------------
@ -202,7 +294,8 @@ set_http_authn(start) ->
{ok, _} = emqx:update_config(
?PATH,
{create_authenticator, Chain, AuthConfig}),
{create_authenticator, Chain, AuthConfig}
),
{ok, [#{provider := emqx_authn_http}]} = emqx_authentication:list_authenticators(Chain)
end,
@ -211,8 +304,10 @@ set_http_authn(start) ->
Handler = fun(Req0, State) ->
ct:pal("Req:~p State:~p~n", [Req0, State]),
case cowboy_req:match_qs([username, password], Req0) of
#{username := <<"admin">>,
password := <<"public">>} ->
#{
username := <<"admin">>,
password := <<"public">>
} ->
Req = cowboy_req:reply(200, Req0);
_ ->
Req = cowboy_req:reply(400, Req0)
@ -242,11 +337,14 @@ test_gateway_with_auths([{Auth, Gateways} | T]) ->
{name, Name} = erlang:fun_info(Auth, name),
ct:pal("start auth:~p~n", [Name]),
Auth(start),
lists:foreach(fun(Gateway) ->
lists:foreach(
fun(Gateway) ->
{name, GwName} = erlang:fun_info(Gateway, name),
ct:pal("start gateway case:~p~n", [GwName]),
Gateway()
end, Gateways),
end,
Gateways
),
ct:pal("stop auth:~p~n", [Name]),
Auth(stop),
test_gateway_with_auths(T);
@ -263,17 +361,19 @@ merge_conf([Conf | T], Acc) ->
_ ->
merge_conf(T, Acc)
end;
merge_conf([ ], Acc) ->
merge_conf([], Acc) ->
erlang:list_to_binary("gateway{" ++ string:join(Acc, ",") ++ "}").
with_resource(Init, Close, Fun) ->
Res = case Init() of
Res =
case Init() of
{ok, X} -> X;
Other -> Other
end,
try
Fun(Res)
catch C:R:S ->
catch
C:R:S ->
Close(Res),
erlang:raise(C, R, S)
end.

View File

@ -61,6 +61,12 @@ end_per_suite(_Cfg) ->
emqx_mgmt_api_test_util:end_suite([emqx_gateway]),
ok.
default_config() ->
?CONF_DEFAULT.
stomp_ver() ->
?STOMP_VER.
%%--------------------------------------------------------------------
%% Test Cases
%%--------------------------------------------------------------------