fix(sso): add a API with authorization-free to list running backends
This commit is contained in:
parent
123d31fa7d
commit
2283db62ec
|
@ -217,12 +217,31 @@ authorize(Req) ->
|
||||||
<<"You don't have permission to access this resource">>}
|
<<"You don't have permission to access this resource">>}
|
||||||
end;
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
return_unauthorized(
|
case is_authorization_free(Req) of
|
||||||
<<"AUTHORIZATION_HEADER_ERROR">>,
|
true ->
|
||||||
<<"Support authorization: basic/bearer ">>
|
ok;
|
||||||
)
|
_ ->
|
||||||
|
return_unauthorized(
|
||||||
|
<<"AUTHORIZATION_HEADER_ERROR">>,
|
||||||
|
<<"Support authorization: basic/bearer ">>
|
||||||
|
)
|
||||||
|
end
|
||||||
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) ->
|
return_unauthorized(Code, Message) ->
|
||||||
{401,
|
{401,
|
||||||
#{
|
#{
|
||||||
|
|
|
@ -25,12 +25,13 @@
|
||||||
]).
|
]).
|
||||||
|
|
||||||
-export([
|
-export([
|
||||||
|
running/2,
|
||||||
login/2,
|
login/2,
|
||||||
sso/2,
|
sso/2,
|
||||||
backend/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_USERNAME_OR_PWD, 'BAD_USERNAME_OR_PWD').
|
||||||
-define(BAD_REQUEST, 'BAD_REQUEST').
|
-define(BAD_REQUEST, 'BAD_REQUEST').
|
||||||
|
@ -45,10 +46,22 @@ api_spec() ->
|
||||||
paths() ->
|
paths() ->
|
||||||
[
|
[
|
||||||
"/sso",
|
"/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") ->
|
schema("/sso") ->
|
||||||
#{
|
#{
|
||||||
'operationId' => sso,
|
'operationId' => sso,
|
||||||
|
@ -113,6 +126,19 @@ fields(backend_status) ->
|
||||||
|
|
||||||
%% -------------------------------------------------------------------------------------------------
|
%% -------------------------------------------------------------------------------------------------
|
||||||
%% API
|
%% 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}) ->
|
login(post, #{bindings := #{backend := Backend}, body := Sign}) ->
|
||||||
case emqx_dashboard_sso_manager:lookup_state(Backend) of
|
case emqx_dashboard_sso_manager:lookup_state(Backend) of
|
||||||
undefined ->
|
undefined ->
|
||||||
|
@ -165,6 +191,10 @@ backend(delete, #{bindings := #{backend := Backend}}) ->
|
||||||
sso_parameters(Params) ->
|
sso_parameters(Params) ->
|
||||||
backend_name_as_arg(query, [local], <<"local">>) ++ Params.
|
backend_name_as_arg(query, [local], <<"local">>) ++ Params.
|
||||||
|
|
||||||
|
is_authorization_free(Req) ->
|
||||||
|
Path = cowboy_req:path(Req),
|
||||||
|
is_path_authorization_free(Path).
|
||||||
|
|
||||||
%% -------------------------------------------------------------------------------------------------
|
%% -------------------------------------------------------------------------------------------------
|
||||||
%% internal
|
%% internal
|
||||||
response_schema(401) ->
|
response_schema(401) ->
|
||||||
|
@ -225,3 +255,10 @@ to_json(Data) ->
|
||||||
{K, emqx_utils_maps:binary_string(V)}
|
{K, emqx_utils_maps:binary_string(V)}
|
||||||
end
|
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.
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
-define(LDAP_DEFAULT_PORT, 389).
|
-define(LDAP_DEFAULT_PORT, 389).
|
||||||
-define(LDAP_USER, <<"mqttuser0001">>).
|
-define(LDAP_USER, <<"mqttuser0001">>).
|
||||||
-define(LDAP_USER_PASSWORD, <<"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() ->
|
all() ->
|
||||||
[
|
[
|
||||||
|
@ -54,8 +54,10 @@ end_per_testcase(Case, _) ->
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
t_create(_) ->
|
t_create(_) ->
|
||||||
|
check_running([]),
|
||||||
Path = uri(["sso", "ldap"]),
|
Path = uri(["sso", "ldap"]),
|
||||||
{ok, 200, Result} = request(put, Path, ldap_config()),
|
{ok, 200, Result} = request(put, Path, ldap_config()),
|
||||||
|
check_running([]),
|
||||||
?assertMatch(#{backend := <<"ldap">>, enable := false}, decode_json(Result)),
|
?assertMatch(#{backend := <<"ldap">>, enable := false}, decode_json(Result)),
|
||||||
?assertMatch([#{backend := <<"ldap">>, enable := false}], get_sso()),
|
?assertMatch([#{backend := <<"ldap">>, enable := false}], get_sso()),
|
||||||
?assertNotEqual(undefined, emqx_dashboard_sso_manager:lookup_state(ldap)),
|
?assertNotEqual(undefined, emqx_dashboard_sso_manager:lookup_state(ldap)),
|
||||||
|
@ -64,6 +66,7 @@ t_create(_) ->
|
||||||
t_update(_) ->
|
t_update(_) ->
|
||||||
Path = uri(["sso", "ldap"]),
|
Path = uri(["sso", "ldap"]),
|
||||||
{ok, 200, Result} = request(put, Path, ldap_config(#{<<"enable">> => <<"true">>})),
|
{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}, decode_json(Result)),
|
||||||
?assertMatch([#{backend := <<"ldap">>, enable := true}], get_sso()),
|
?assertMatch([#{backend := <<"ldap">>, enable := true}], get_sso()),
|
||||||
?assertNotEqual(undefined, emqx_dashboard_sso_manager:lookup_state(ldap)),
|
?assertNotEqual(undefined, emqx_dashboard_sso_manager:lookup_state(ldap)),
|
||||||
|
@ -96,7 +99,8 @@ t_first_login(_) ->
|
||||||
<<"username">> => ?LDAP_USER,
|
<<"username">> => ?LDAP_USER,
|
||||||
<<"password">> => ?LDAP_USER_PASSWORD
|
<<"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(#{license := _, token := _}, decode_json(Result)),
|
||||||
?assertMatch(
|
?assertMatch(
|
||||||
[#?ADMIN{username = ?SSO_USERNAME(ldap, ?LDAP_USER)}],
|
[#?ADMIN{username = ?SSO_USERNAME(ldap, ?LDAP_USER)}],
|
||||||
|
@ -119,8 +123,15 @@ t_delete(_) ->
|
||||||
Path = uri(["sso", "ldap"]),
|
Path = uri(["sso", "ldap"]),
|
||||||
?assertMatch({ok, 204, _}, request(delete, Path)),
|
?assertMatch({ok, 204, _}, request(delete, Path)),
|
||||||
?assertMatch({ok, 404, _}, request(delete, Path)),
|
?assertMatch({ok, 404, _}, request(delete, Path)),
|
||||||
|
check_running([]),
|
||||||
ok.
|
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() ->
|
get_sso() ->
|
||||||
Path = uri(["sso"]),
|
Path = uri(["sso"]),
|
||||||
{ok, 200, Result} = request(get, Path),
|
{ok, 200, Result} = request(get, Path),
|
||||||
|
@ -150,3 +161,7 @@ ldap_server() ->
|
||||||
decode_json(Data) ->
|
decode_json(Data) ->
|
||||||
BinJson = emqx_utils_json:decode(Data, [return_maps]),
|
BinJson = emqx_utils_json:decode(Data, [return_maps]),
|
||||||
emqx_utils_maps:unsafe_atom_key_map(BinJson).
|
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).
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
emqx_dashboard_api {
|
emqx_dashboard_api {
|
||||||
|
|
||||||
|
list_running.desc:
|
||||||
|
"""List all running SSO backends"""
|
||||||
|
list_running.label:
|
||||||
|
"""Running Backends"""
|
||||||
|
|
||||||
get_sso.desc:
|
get_sso.desc:
|
||||||
"""List all SSO backends"""
|
"""List all SSO backends"""
|
||||||
get_sso.label:
|
get_sso.label:
|
||||||
|
|
Loading…
Reference in New Issue