Преглед изворни кода

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

firest пре 3 година
родитељ
комит
0db6b8d47e

+ 9 - 9
apps/emqx_gateway/test/emqx_coap_SUITE.erl

@@ -106,19 +106,19 @@ t_connection(_) ->
 
 t_publish(_) ->
     Action = fun(Channel, Token) ->
-                     Topic = <<"/abc">>,
-                     Payload = <<"123">>,
+        Topic = <<"/abc">>,
+        Payload = <<"123">>,
 
-                     TopicStr = binary_to_list(Topic),
-                     URI = ?PS_PREFIX ++ TopicStr ++ "?clientid=client1&token=" ++ Token,
+        TopicStr = binary_to_list(Topic),
+        URI = ?PS_PREFIX ++ TopicStr ++ "?clientid=client1&token=" ++ Token,
 
-                     %% Sub topic first
-                     emqx:subscribe(Topic),
+        %% Sub topic first
+        emqx:subscribe(Topic),
 
-                     Req = make_req(post, Payload),
-                     {ok, changed, _} = do_request(Channel, URI, Req),
+        Req = make_req(post, Payload),
+        {ok, changed, _} = do_request(Channel, URI, Req),
 
-                     receive
+        receive
             {deliver, Topic, Msg} ->
                 ?assertEqual(Topic, Msg#message.topic),
                 ?assertEqual(Payload, Msg#message.payload)

+ 16 - 0
apps/emqx_gateway/test/emqx_exproto_SUITE.erl

@@ -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
 %%--------------------------------------------------------------------

+ 199 - 99
apps/emqx_gateway/test/emqx_gateway_authn_http_SUITE.erl

@@ -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) ->
-                 case (Expr) of
-                     Guard -> ok;
-                     X__V ->
-                         erlang:error({assertMatch,
-                                       [{module, ?MODULE},
-                                        {line, ?LINE},
-                                        {expression, (??Expr)},
-                                        {pattern, (??Guard)},
-                                        {value, X__V}]})
-                 end
-         end)).
+    (fun(Expr) ->
+        case (Expr) of
+            Guard ->
+                ok;
+            X__V ->
+                erlang:error(
+                    {assertMatch, [
+                        {module, ?MODULE},
+                        {line, ?LINE},
+                        {expression, (??Expr)},
+                        {pattern, (??Guard)},
+                        {value, X__V}
+                    ]}
+                )
+        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).
@@ -94,19 +108,21 @@ t_authn(_) ->
 
 case_coap() ->
     Login = fun(URI, Checker) ->
-                    Action = fun(Channel) ->
-                                     Req = emqx_coap_SUITE:make_req(post),
-                                     Checker(emqx_coap_SUITE:do_request(Channel, URI, Req))
-                             end,
-                    emqx_coap_SUITE:do(Action)
-              end,
+        Action = fun(Channel) ->
+            Req = emqx_coap_SUITE:make_req(post),
+            Checker(emqx_coap_SUITE:do_request(Channel, URI, Req))
+        end,
+        emqx_coap_SUITE:do(Action)
+    end,
     Prefix = emqx_coap_SUITE:mqtt_prefix(),
-    RightUrl = Prefix ++
-        "/connection?clientid=client1&username=admin&password=public",
+    RightUrl =
+        Prefix ++
+            "/connection?clientid=client1&username=admin&password=public",
     Login(RightUrl, ?checkMatch({ok, created, _Data})),
 
-    LeftUrl = Prefix ++
-        "/connection?clientid=client1&username=bad&password=bad",
+    LeftUrl =
+        Prefix ++
+            "/connection?clientid=client1&username=bad&password=bad",
     Login(LeftUrl, ?checkMatch({error, bad_request, _Data})),
     ok.
 
@@ -118,28 +134,33 @@ 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}])),
-                                  ?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>">>},
-                                            [],
-                                            MsgId),
-
-                                          Checker(Mod:test_recv_coap_response(Socket))
-                                  end)
-            end,
+        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>">>
+                    },
+                    [],
+                    MsgId
+                ),
+
+                Checker(Mod:test_recv_coap_response(Socket))
+            end
+        )
+    end,
 
     MakeCheker = fun(Type, Method) ->
-                         fun(Msg) ->
-                                 ?assertEqual(Type, emqx_coap_SUITE:get_field(type, Msg)),
-                                 ?assertEqual(Method, emqx_coap_SUITE:get_field(method, Msg))
-                         end
-                 end,
+        fun(Msg) ->
+            ?assertEqual(Type, emqx_coap_SUITE:get_field(type, Msg)),
+            ?assertEqual(Method, emqx_coap_SUITE:get_field(method, Msg))
+        end
+    end,
 
     RightUrl = "coap://127.0.0.1:~b/rd?ep=~ts&lt=345&lwm2m=1&imei=admin&password=public",
     Login(RightUrl, MakeCheker(ack, {ok, created})),
@@ -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])),
-                                  ?FUNCTOR(Socket, gen_udp:close(Socket)),
-                                  fun(Socket) ->
-                                          Mod:send_connect_msg(Socket, <<"client_id_test1">>),
-                                          ?assertEqual(Expect, Mod:receive_response(Socket))
-                                  end)
-            end,
+        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,
     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.
 
 %%------------------------------------------------------------------------------
@@ -181,15 +273,15 @@ case_stomp() ->
 
 raw_http_auth_config() ->
     #{
-      mechanism => <<"password_based">>,
-      enable => <<"true">>,
+        mechanism => <<"password_based">>,
+        enable => <<"true">>,
 
-      backend => <<"http">>,
-      method => <<"get">>,
-      url => <<"http://127.0.0.1:33333/auth">>,
-      body => #{<<"username">> => ?PH_USERNAME, <<"password">> => ?PH_PASSWORD},
-      headers => #{<<"X-Test-Header">> => <<"Test Value">>}
-     }.
+        backend => <<"http">>,
+        method => <<"get">>,
+        url => <<"http://127.0.0.1:33333/auth">>,
+        body => #{<<"username">> => ?PH_USERNAME, <<"password">> => ?PH_PASSWORD},
+        headers => #{<<"X-Test-Header">> => <<"Test Value">>}
+    }.
 
 set_http_authn(start) ->
     {ok, _} = emqx_authn_http_test_server:start_link(?HTTP_PORT, ?HTTP_PATH),
@@ -197,37 +289,40 @@ set_http_authn(start) ->
     AuthConfig = raw_http_auth_config(),
 
     Set = fun(Protocol) ->
-                  Chain = emqx_authentication:global_chain(Protocol),
-                  emqx_authn_test_lib:delete_authenticators([authentication], Chain),
+        Chain = emqx_authentication:global_chain(Protocol),
+        emqx_authn_test_lib:delete_authenticators([authentication], Chain),
 
-                  {ok, _} = emqx:update_config(
-                              ?PATH,
-                              {create_authenticator, Chain, AuthConfig}),
+        {ok, _} = emqx:update_config(
+            ?PATH,
+            {create_authenticator, Chain, AuthConfig}
+        ),
 
-                  {ok, [#{provider := emqx_authn_http}]} = emqx_authentication:list_authenticators(Chain)
-          end,
+        {ok, [#{provider := emqx_authn_http}]} = emqx_authentication:list_authenticators(Chain)
+    end,
     lists:foreach(Set, ?PROTOCOLS),
 
     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">>} ->
-                              Req = cowboy_req:reply(200, Req0);
-                          _ ->
-                              Req = cowboy_req:reply(400, Req0)
-                      end,
-                      {ok, Req, State}
-              end,
+        ct:pal("Req:~p State:~p~n", [Req0, State]),
+        case cowboy_req:match_qs([username, password], Req0) of
+            #{
+                username := <<"admin">>,
+                password := <<"public">>
+            } ->
+                Req = cowboy_req:reply(200, Req0);
+            _ ->
+                Req = cowboy_req:reply(400, Req0)
+        end,
+        {ok, Req, State}
+    end,
     emqx_authn_http_test_server:set_handler(Handler);
 set_http_authn(stop) ->
     ok = emqx_authn_http_test_server:stop().
 
 clear_authn() ->
     Clear = fun(Protocol) ->
-                    Chain = emqx_authentication:global_chain(Protocol),
-                    emqx_authn_test_lib:delete_authenticators([authentication], Chain)
-            end,
+        Chain = emqx_authentication:global_chain(Protocol),
+        emqx_authn_test_lib:delete_authenticators([authentication], Chain)
+    end,
     lists:foreach(Clear, ?PROTOCOLS).
 
 %%------------------------------------------------------------------------------
@@ -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) ->
-                          {name, GwName} = erlang:fun_info(Gateway, name),
-                          ct:pal("start gateway case:~p~n", [GwName]),
-                          Gateway()
-                  end, Gateways),
+    lists:foreach(
+        fun(Gateway) ->
+            {name, GwName} = erlang:fun_info(Gateway, name),
+            ct:pal("start gateway case:~p~n", [GwName]),
+            Gateway()
+        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
-              {ok, X} -> X;
-              Other -> Other
-          end,
+    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.

+ 6 - 0
apps/emqx_gateway/test/emqx_stomp_SUITE.erl

@@ -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
 %%--------------------------------------------------------------------