Przeglądaj źródła

Merge pull request #11645 from lafirest/fix/sso_running

fix(sso): add an API with authorization-free to list running backends
lafirest 2 lat temu
rodzic
commit
2dfa7f9686

+ 23 - 4
apps/emqx_dashboard/src/emqx_dashboard.erl

@@ -217,12 +217,31 @@ authorize(Req) ->
                         <<"You don't have permission to access this resource">>}
             end;
         _ ->
-            return_unauthorized(
-                <<"AUTHORIZATION_HEADER_ERROR">>,
-                <<"Support authorization: basic/bearer ">>
-            )
+            case is_authorization_free(Req) of
+                true ->
+                    ok;
+                _ ->
+                    return_unauthorized(
+                        <<"AUTHORIZATION_HEADER_ERROR">>,
+                        <<"Support authorization: basic/bearer ">>
+                    )
+            end
     end.
 
+-if(?EMQX_RELEASE_EDITION == ee).
+%% this is a temporary design to skip the authorization for some APIs,
+%% it will be removed future
+is_authorization_free(Req) ->
+    emqx_dashboard_sso_api:is_authorization_free(Req).
+
+-else.
+
+-dialyzer({no_match, [authorize/1]}).
+
+is_authorization_free(_Req) ->
+    false.
+-endif.
+
 return_unauthorized(Code, Message) ->
     {401,
         #{

+ 40 - 3
apps/emqx_dashboard_sso/src/emqx_dashboard_sso_api.erl

@@ -25,12 +25,13 @@
 ]).
 
 -export([
+    running/2,
     login/2,
     sso/2,
     backend/2
 ]).
 
--export([sso_parameters/1]).
+-export([sso_parameters/1, is_authorization_free/1]).
 
 -define(BAD_USERNAME_OR_PWD, 'BAD_USERNAME_OR_PWD').
 -define(BAD_REQUEST, 'BAD_REQUEST').
@@ -45,10 +46,22 @@ api_spec() ->
 paths() ->
     [
         "/sso",
-        "/sso/login/:backend",
-        "/sso/:backend"
+        "/sso/:backend",
+        "/sso/running",
+        "/sso/login/:backend"
     ].
 
+schema("/sso/running") ->
+    #{
+        'operationId' => running,
+        get => #{
+            tags => [?TAGS],
+            desc => ?DESC(list_running),
+            responses => #{
+                200 => array(enum(emqx_dashboard_sso:types()))
+            }
+        }
+    };
 schema("/sso") ->
     #{
         'operationId' => sso,
@@ -113,6 +126,19 @@ fields(backend_status) ->
 
 %% -------------------------------------------------------------------------------------------------
 %% API
+running(get, _Request) ->
+    SSO = emqx:get_config([dashboard_sso], #{}),
+    {200,
+        lists:filtermap(
+            fun
+                (#{backend := Backend, enable := true}) ->
+                    {true, Backend};
+                (_) ->
+                    false
+            end,
+            maps:values(SSO)
+        )}.
+
 login(post, #{bindings := #{backend := Backend}, body := Sign}) ->
     case emqx_dashboard_sso_manager:lookup_state(Backend) of
         undefined ->
@@ -165,6 +191,10 @@ backend(delete, #{bindings := #{backend := Backend}}) ->
 sso_parameters(Params) ->
     backend_name_as_arg(query, [local], <<"local">>) ++ Params.
 
+is_authorization_free(Req) ->
+    Path = cowboy_req:path(Req),
+    is_path_authorization_free(Path).
+
 %% -------------------------------------------------------------------------------------------------
 %% internal
 response_schema(401) ->
@@ -225,3 +255,10 @@ to_json(Data) ->
             {K, emqx_utils_maps:binary_string(V)}
         end
     ).
+
+is_path_authorization_free(<<"/api/v5/sso/running">>) ->
+    true;
+is_path_authorization_free(<<"/api/v5/sso/login", _/binary>>) ->
+    true;
+is_path_authorization_free(_) ->
+    false.

+ 17 - 2
apps/emqx_dashboard_sso/test/emqx_dashboard_sso_ldap_SUITE.erl

@@ -14,7 +14,7 @@
 -define(LDAP_DEFAULT_PORT, 389).
 -define(LDAP_USER, <<"mqttuser0001">>).
 -define(LDAP_USER_PASSWORD, <<"mqttuser0001">>).
--import(emqx_mgmt_api_test_util, [request/2, request/3, uri/1]).
+-import(emqx_mgmt_api_test_util, [request/2, request/3, uri/1, request_api/3]).
 
 all() ->
     [
@@ -54,8 +54,10 @@ end_per_testcase(Case, _) ->
     ok.
 
 t_create(_) ->
+    check_running([]),
     Path = uri(["sso", "ldap"]),
     {ok, 200, Result} = request(put, Path, ldap_config()),
+    check_running([]),
     ?assertMatch(#{backend := <<"ldap">>, enable := false}, decode_json(Result)),
     ?assertMatch([#{backend := <<"ldap">>, enable := false}], get_sso()),
     ?assertNotEqual(undefined, emqx_dashboard_sso_manager:lookup_state(ldap)),
@@ -64,6 +66,7 @@ t_create(_) ->
 t_update(_) ->
     Path = uri(["sso", "ldap"]),
     {ok, 200, Result} = request(put, Path, ldap_config(#{<<"enable">> => <<"true">>})),
+    check_running([<<"ldap">>]),
     ?assertMatch(#{backend := <<"ldap">>, enable := true}, decode_json(Result)),
     ?assertMatch([#{backend := <<"ldap">>, enable := true}], get_sso()),
     ?assertNotEqual(undefined, emqx_dashboard_sso_manager:lookup_state(ldap)),
@@ -96,7 +99,8 @@ t_first_login(_) ->
         <<"username">> => ?LDAP_USER,
         <<"password">> => ?LDAP_USER_PASSWORD
     },
-    {ok, 200, Result} = request(post, Path, Req),
+    %% this API is authorization-free
+    {ok, 200, Result} = request_without_authorization(post, Path, Req),
     ?assertMatch(#{license := _, token := _}, decode_json(Result)),
     ?assertMatch(
         [#?ADMIN{username = ?SSO_USERNAME(ldap, ?LDAP_USER)}],
@@ -119,8 +123,15 @@ t_delete(_) ->
     Path = uri(["sso", "ldap"]),
     ?assertMatch({ok, 204, _}, request(delete, Path)),
     ?assertMatch({ok, 404, _}, request(delete, Path)),
+    check_running([]),
     ok.
 
+check_running(Expect) ->
+    Path = uri(["sso", "running"]),
+    %% this API is authorization-free
+    {ok, Result} = request_api(get, Path, []),
+    ?assertEqual(Expect, decode_json(Result)).
+
 get_sso() ->
     Path = uri(["sso"]),
     {ok, 200, Result} = request(get, Path),
@@ -150,3 +161,7 @@ ldap_server() ->
 decode_json(Data) ->
     BinJson = emqx_utils_json:decode(Data, [return_maps]),
     emqx_utils_maps:unsafe_atom_key_map(BinJson).
+
+request_without_authorization(Method, Url, Body) ->
+    Opts = #{compatible_mode => true, httpc_req_opts => [{body_format, binary}]},
+    emqx_mgmt_api_test_util:request_api(Method, Url, [], [], Body, Opts).

+ 5 - 0
rel/i18n/emqx_dashboard_sso_api.hocon

@@ -1,5 +1,10 @@
 emqx_dashboard_api {
 
+list_running.desc:
+"""List all running SSO backends"""
+list_running.label:
+"""Running Backends"""
+
 get_sso.desc:
 """List all SSO backends"""
 get_sso.label: