diff --git a/apps/emqx_dashboard/src/emqx_dashboard_admin.erl b/apps/emqx_dashboard/src/emqx_dashboard_admin.erl index d5e83b293..3ae2a33e1 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_admin.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_admin.erl @@ -103,11 +103,9 @@ add_default_user() -> %% API %%-------------------------------------------------------------------- - - -spec add_user(dashboard_username(), binary(), dashboard_user_role(), binary()) -> {ok, map()} | {error, any()}. -add_user(Username, Password, Role, Desc) when is_binary(Password) -> +add_user(Username, Password, Role, Desc) when is_binary(Username), is_binary(Password) -> case {legal_username(Username), legal_password(Password), legal_role(Role)} of {ok, ok, ok} -> do_add_user(Username, Password, Role, Desc); {{error, Reason}, _, _} -> {error, Reason}; @@ -120,8 +118,6 @@ do_add_user(Username, Password, Role, Desc) -> return(Res). %% 0-9 or A-Z or a-z or $_ -legal_username(?SSO_USERNAME(_, _)) -> - ok; legal_username(<<>>) -> {error, <<"Username cannot be empty">>}; legal_username(UserName) -> @@ -211,7 +207,7 @@ add_user_(Username, Password, Role, Desc) -> description = Desc }, mnesia:write(Admin), - #{username => Username, role => Role, description => Desc}; + flatten_username(#{username => Username, role => Role, description => Desc}); [_] -> mnesia:abort(<<"username_already_exist">>) end. @@ -232,7 +228,8 @@ remove_user(Username) when is_binary(Username) -> {error, Reason} end. --spec update_user(binary(), dashboard_user_role(), binary()) -> {ok, map()} | {error, term()}. +-spec update_user(dashboard_username(), dashboard_user_role(), binary()) -> + {ok, map()} | {error, term()}. update_user(Username, Role, Desc) when is_binary(Username) -> case legal_role(Role) of ok -> @@ -279,7 +276,10 @@ update_user_(Username, Role, Desc) -> mnesia:abort(<<"username_not_found">>); [Admin] -> mnesia:write(Admin#?ADMIN{role = Role, description = Desc}), - {role(Admin) =:= Role, #{username => Username, role => Role, description => Desc}} + { + role(Admin) =:= Role, + flatten_username(#{username => Username, role => Role, description => Desc}) + } end. change_password(Username, OldPasswd, NewPasswd) when is_binary(Username) -> @@ -335,11 +335,11 @@ all_users() -> role = Role } ) -> - #{ + flatten_username(#{ username => Username, description => Desc, role => ensure_role(Role) - } + }) end, ets:tab2list(?ADMIN) ). @@ -417,10 +417,24 @@ legal_role(Role) -> role(Data) -> emqx_dashboard_rbac:role(Data). --spec add_sso_user(atom(), binary(), dashboard_user_role(), binary()) -> +flatten_username(#{username := ?SSO_USERNAME(Backend, Name)} = Data) -> + Data#{ + username := Name, + backend => Backend + }; +flatten_username(#{username := Username} = Data) when is_binary(Username) -> + Data#{backend => local}. + +-spec add_sso_user(dashboard_sso_backend(), binary(), dashboard_user_role(), binary()) -> {ok, map()} | {error, any()}. -add_sso_user(Backend, Username, Role, Desc) -> - add_user(?SSO_USERNAME(Backend, Username), <<>>, Role, Desc). +add_sso_user(Backend, Username0, Role, Desc) when is_binary(Username0) -> + case legal_role(Role) of + ok -> + Username = ?SSO_USERNAME(Backend, Username0), + do_add_user(Username, <<>>, Role, Desc); + {error, _} = Error -> + Error + end. -spec lookup_user(dashboard_sso_backend(), binary()) -> [emqx_admin()]. lookup_user(Backend, Username) when is_atom(Backend) -> @@ -434,6 +448,9 @@ legal_role(_) -> role(_) -> ?ROLE_DEFAULT. + +flatten_username(Data) -> + Data. -endif. -ifdef(TEST). diff --git a/apps/emqx_dashboard/src/emqx_dashboard_api.erl b/apps/emqx_dashboard/src/emqx_dashboard_api.erl index 9ed6d1a77..3d68fd098 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_api.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_api.erl @@ -89,6 +89,7 @@ schema("/logout") -> post => #{ tags => [<<"dashboard">>], desc => ?DESC(logout_api), + parameters => sso_parameters(), 'requestBody' => fields([username]), responses => #{ 204 => <<"Dashboard logout successfully">>, @@ -114,7 +115,7 @@ schema("/users") -> desc => ?DESC(create_user_api), 'requestBody' => fields([username, password, role, description]), responses => #{ - 200 => fields([username, role, description]) + 200 => fields([username, role, description, backend]) } } }; @@ -124,17 +125,17 @@ schema("/users/:username") -> put => #{ tags => [<<"dashboard">>], desc => ?DESC(update_user_api), - parameters => fields([username_in_path]), + parameters => sso_parameters(fields([username_in_path])), 'requestBody' => fields([role, description]), responses => #{ - 200 => fields([username, role, description]), + 200 => fields([username, role, description, backend]), 404 => response_schema(404) } }, delete => #{ tags => [<<"dashboard">>], desc => ?DESC(delete_user_api), - parameters => fields([username_in_path]), + parameters => sso_parameters(fields([username_in_path])), responses => #{ 204 => <<"Delete User successfully">>, 400 => emqx_dashboard_swagger:error_codes( @@ -169,7 +170,7 @@ response_schema(404) -> emqx_dashboard_swagger:error_codes([?USER_NOT_FOUND], ?DESC(users_api404)). fields(user) -> - fields([username, description]); + fields([username, role, description, backend]); fields(List) -> [field(Key) || Key <- List, field_filter(Key)]. @@ -206,7 +207,10 @@ field(old_pwd) -> field(new_pwd) -> {new_pwd, mk(binary(), #{desc => ?DESC(new_pwd)})}; field(role) -> - {role, mk(binary(), #{desc => ?DESC(role), example => ?ROLE_DEFAULT})}. + {role, + mk(binary(), #{desc => ?DESC(role), default => ?ROLE_DEFAULT, example => ?ROLE_DEFAULT})}; +field(backend) -> + {backend, mk(binary(), #{desc => ?DESC(backend), example => <<"local">>})}. %% ------------------------------------------------------------------------------------------------- %% API @@ -229,15 +233,16 @@ login(post, #{body := Params}) -> end. logout(_, #{ - body := #{<<"username">> := Username}, + body := #{<<"username">> := Username0} = Req, headers := #{<<"authorization">> := <<"Bearer ", Token/binary>>} }) -> + Username = username(Req, Username0), case emqx_dashboard_admin:destroy_token_by_username(Username, Token) of ok -> - ?SLOG(info, #{msg => "Dashboard logout successfully", username => Username}), + ?SLOG(info, #{msg => "Dashboard logout successfully", username => Username0}), 204; _R -> - ?SLOG(info, #{msg => "Dashboard logout failed.", username => Username}), + ?SLOG(info, #{msg => "Dashboard logout failed.", username => Username0}), {401, ?WRONG_TOKEN_OR_USERNAME, <<"Ensure your token & username">>} end. @@ -266,9 +271,10 @@ users(post, #{body := Params}) -> end end. -user(put, #{bindings := #{username := Username}, body := Params}) -> +user(put, #{bindings := #{username := Username0}, body := Params} = Req) -> Role = maps:get(<<"role">>, Params, ?ROLE_DEFAULT), Desc = maps:get(<<"description">>, Params), + Username = username(Req, Username0), case emqx_dashboard_admin:update_user(Username, Role, Desc) of {ok, Result} -> {200, filter_result(Result)}; @@ -277,14 +283,15 @@ user(put, #{bindings := #{username := Username}, body := Params}) -> {error, Reason} -> {400, ?BAD_REQUEST, Reason} end; -user(delete, #{bindings := #{username := Username}, headers := Headers}) -> - case Username == emqx_dashboard_admin:default_username() of +user(delete, #{bindings := #{username := Username0}, headers := Headers} = Req) -> + case Username0 == emqx_dashboard_admin:default_username() of true -> - ?SLOG(info, #{msg => "Dashboard delete admin user failed", username => Username}), - Message = list_to_binary(io_lib:format("Cannot delete user ~p", [Username])), + ?SLOG(info, #{msg => "Dashboard delete admin user failed", username => Username0}), + Message = list_to_binary(io_lib:format("Cannot delete user ~p", [Username0])), {400, ?NOT_ALLOWED, Message}; false -> - case is_self_auth(Username, Headers) of + Username = username(Req, Username0), + case is_self_auth(Username0, Headers) of true -> {400, ?NOT_ALLOWED, <<"Cannot delete self">>}; false -> @@ -293,13 +300,15 @@ user(delete, #{bindings := #{username := Username}, headers := Headers}) -> {404, ?USER_NOT_FOUND, Reason}; {ok, _} -> ?SLOG(info, #{ - msg => "Dashboard delete admin user", username => Username + msg => "Dashboard delete admin user", username => Username0 }), {204} end end end. +is_self_auth(?SSO_USERNAME(_, _), _) -> + fasle; is_self_auth(Username, #{<<"authorization">> := Token}) -> is_self_auth(Username, Token); is_self_auth(Username, #{<<"Authorization">> := Token}) -> @@ -362,6 +371,19 @@ field_filter(_) -> filter_result(Result) -> Result. +sso_parameters() -> + sso_parameters([]). + +sso_parameters(Params) -> + emqx_dashboard_sso_api:sso_parameters(Params). + +username(#{bindings := #{backend := local}}, Username) -> + Username; +username(#{bindings := #{backend := Backend}}, Username) -> + ?SSO_USERNAME(Backend, Username); +username(_Req, Username) -> + Username. + -else. field_filter(role) -> @@ -372,6 +394,14 @@ field_filter(_) -> filter_result(Result) when is_list(Result) -> lists:map(fun filter_result/1, Result); filter_result(Result) -> - maps:without([role], Result). + maps:without([role, backend], Result). +sso_parameters() -> + sso_parameters([]). + +sso_parameters(Any) -> + Any. + +username(_Req, Username) -> + Username. -endif. diff --git a/apps/emqx_dashboard/src/emqx_dashboard_token.erl b/apps/emqx_dashboard/src/emqx_dashboard_token.erl index f71df77bd..b45df1930 100644 --- a/apps/emqx_dashboard/src/emqx_dashboard_token.erl +++ b/apps/emqx_dashboard/src/emqx_dashboard_token.erl @@ -179,6 +179,9 @@ owner(Token) -> {atomic, []} -> {error, not_found} end. +jwk(?SSO_USERNAME(Backend, Name), Password, Salt) -> + BackendBin = erlang:atom_to_binary(Backend), + jwk(<>, Password, Salt); jwk(Username, Password, Salt) -> Key = crypto:hash(md5, <>), #{ @@ -192,12 +195,17 @@ jwt_expiration_time() -> token_ttl() -> emqx_conf:get([dashboard, token_expired_time], ?EXPTIME). +format(Token, ?SSO_USERNAME(Backend, Name), Role, ExpTime) -> + format(Token, Backend, Name, Role, ExpTime); format(Token, Username, Role, ExpTime) -> + format(Token, local, Username, Role, ExpTime). + +format(Token, Backend, Username, Role, ExpTime) -> #?ADMIN_JWT{ token = Token, username = Username, exptime = ExpTime, - extra = #{role => Role} + extra = #{role => Role, backend => Backend} }. %%-------------------------------------------------------------------- diff --git a/apps/emqx_dashboard_sso/README.md b/apps/emqx_dashboard_sso/README.md index da4ff7c9a..530117a27 100644 --- a/apps/emqx_dashboard_sso/README.md +++ b/apps/emqx_dashboard_sso/README.md @@ -1,4 +1,4 @@ -# Dashboard Single sign-on +# Dashboard Single sign-On Single Sign-On is a mechanism that allows a user to automatically sign in to multiple applications after signing in to one. This improves convenience and security. @@ -8,4 +8,4 @@ Please see our [contributing.md](../../CONTRIBUTING.md). ## License -See [APL](../../APL.txt). +See EMQ Business Source License 1.1, refer to [LICENSE](BSL.txt). diff --git a/apps/emqx_dashboard_sso/src/emqx_dashboard_sso.erl b/apps/emqx_dashboard_sso/src/emqx_dashboard_sso.erl index 957437161..287082414 100644 --- a/apps/emqx_dashboard_sso/src/emqx_dashboard_sso.erl +++ b/apps/emqx_dashboard_sso/src/emqx_dashboard_sso.erl @@ -26,7 +26,7 @@ -callback update(Config :: config(), State :: state()) -> {ok, NewState :: state()} | {error, Reason :: term()}. -callback destroy(State :: state()) -> ok. --callback sign(request(), State :: state()) -> +-callback login(request(), State :: state()) -> {ok, Token :: binary()} | {error, Reason :: term()}. %%------------------------------------------------------------------------------ diff --git a/apps/emqx_dashboard_sso/src/emqx_dashboard_sso_api.erl b/apps/emqx_dashboard_sso/src/emqx_dashboard_sso_api.erl index 5bd6a9da3..dd473931c 100644 --- a/apps/emqx_dashboard_sso/src/emqx_dashboard_sso_api.erl +++ b/apps/emqx_dashboard_sso/src/emqx_dashboard_sso_api.erl @@ -27,12 +27,13 @@ ]). -export([ - running/2, login/2, sso/2, backend/2 ]). +-export([sso_parameters/1]). + -define(BAD_USERNAME_OR_PWD, 'BAD_USERNAME_OR_PWD'). -define(BAD_REQUEST, 'BAD_REQUEST'). @@ -47,8 +48,7 @@ api_spec() -> paths() -> [ "/sso", - "/sso/login", - "/sso/running", + "/sso/login/:backend", "/sso/:backend" ]. @@ -59,16 +59,17 @@ schema("/sso") -> tags => [?TAGS], desc => ?DESC(get_sso), responses => #{ - 200 => array(ref(backend_status)) + 200 => array(enum(emqx_dashboard_sso:types())) } } }; -schema("/sso/login") -> +schema("/sso/login/:backend") -> #{ 'operationId' => login, post => #{ tags => [?TAGS], desc => ?DESC(login), + parameters => backend_name_in_path(), 'requestBody' => login_union(), responses => #{ 200 => emqx_dashboard_api:fields([token, version, license]), @@ -77,17 +78,6 @@ schema("/sso/login") -> } } }; -schema("/sso/running") -> - #{ - 'operationId' => running, - get => #{ - tags => [?TAGS], - desc => ?DESC(get_running), - responses => #{ - 200 => array(enum(emqx_dashboard_sso:types())) - } - } - }; schema("/sso/:backend") -> #{ 'operationId' => backend, @@ -100,15 +90,6 @@ schema("/sso/:backend") -> 404 => response_schema(404) } }, - post => #{ - tags => [?TAGS], - desc => ?DESC(create_backend), - parameters => backend_name_in_path(), - 'requestBody' => backend_union(), - responses => #{ - 200 => backend_union() - } - }, put => #{ tags => [?TAGS], desc => ?DESC(update_backend), @@ -131,22 +112,19 @@ schema("/sso/:backend") -> }. fields(backend_status) -> - emqx_dashboard_sso_schema:common_backend_schema(enum(emqx_dashboard_sso:types())). + emqx_dashboard_sso_schema:common_backend_schema(emqx_dashboard_sso:types()). %% ------------------------------------------------------------------------------------------------- %% API -running(get, _Request) -> - {200, emqx_dashboard_sso_manager:running()}. - -login(post, #{backend := Backend} = Request) -> +login(post, #{bindings := #{backend := Backend}, body := Sign}) -> case emqx_dashboard_sso_manager:lookup_state(Backend) of undefined -> - {404, ?BACKEND_NOT_FOUND}; + {404, ?BACKEND_NOT_FOUND, <<"Backend not found">>}; State -> Provider = emqx_dashboard_sso:provider(Backend), - case Provider:login(Request, State) of + case Provider:login(Sign, State) of {ok, Token} -> - ?SLOG(info, #{msg => "Dashboard SSO login successfully", request => Request}), + ?SLOG(info, #{msg => "Dashboard SSO login successfully", request => Sign}), Version = iolist_to_binary(proplists:get_value(version, emqx_sys:info())), {200, #{ token => Token, @@ -155,7 +133,9 @@ login(post, #{backend := Backend} = Request) -> }}; {error, Reason} -> ?SLOG(info, #{ - msg => "Dashboard SSO login failed", request => Request, reason => Reason + msg => "Dashboard SSO login failed", + request => Sign, + reason => Reason }), {401, ?BAD_USERNAME_OR_PWD, <<"Auth failed">>} end @@ -166,7 +146,7 @@ sso(get, _Request) -> {200, lists:map( fun(Backend) -> - maps:with([backend, enabled], Backend) + maps:with([backend, enable], Backend) end, maps:values(SSO) )}. @@ -176,14 +156,15 @@ backend(get, #{bindings := #{backend := Type}}) -> undefined -> {404, ?BACKEND_NOT_FOUND}; Backend -> - {200, Backend} + {200, to_json(Backend)} end; -backend(create, #{bindings := #{backend := Backend}, body := Config}) -> - on_backend_update(Backend, Config, fun emqx_dashboard_sso_manager:create/2); backend(put, #{bindings := #{backend := Backend}, body := Config}) -> on_backend_update(Backend, Config, fun emqx_dashboard_sso_manager:update/2); -backend(delete, #{bindings := #{backend := Backend}, body := Config}) -> - on_backend_update(Backend, Config, fun emqx_dashboard_sso_manager:delete/2). +backend(delete, #{bindings := #{backend := Backend}}) -> + handle_backend_update_result(emqx_dashboard_sso_manager:delete(Backend), undefined). + +sso_parameters(Params) -> + backend_name_as_arg(query, [local], <<"local">>) ++ Params. %% ------------------------------------------------------------------------------------------------- %% internal @@ -199,14 +180,18 @@ login_union() -> hoconsc:union([Mod:login_ref() || Mod <- emqx_dashboard_sso:modules()]). backend_name_in_path() -> + backend_name_as_arg(path, [], <<"ldap">>). + +backend_name_as_arg(In, Extra, Default) -> [ - {name, + {backend, mk( - binary(), + enum(Extra ++ emqx_dashboard_sso:types()), #{ - in => path, + in => In, desc => ?DESC(backend_name_in_qs), - example => <<"ldap">> + required => true, + example => Default } )} ]. @@ -216,7 +201,7 @@ on_backend_update(Backend, Config, Fun) -> handle_backend_update_result(Result, Config). valid_config(Backend, Config, Fun) -> - case maps:get(backend, Config, undefined) of + case maps:get(<<"backend">>, Config, undefined) of Backend -> Fun(Backend, Config); _ -> @@ -224,12 +209,20 @@ valid_config(Backend, Config, Fun) -> end. handle_backend_update_result({ok, _}, Config) -> - {200, Config}; + {200, to_json(Config)}; handle_backend_update_result(ok, _) -> 204; handle_backend_update_result({error, not_exists}, _) -> - {404, ?BACKEND_NOT_FOUND}; + {404, ?BACKEND_NOT_FOUND, <<"Backend not found">>}; handle_backend_update_result({error, already_exists}, _) -> - {400, ?BAD_REQUEST, <<"Backend already exists.">>}; + {400, ?BAD_REQUEST, <<"Backend already exists">>}; handle_backend_update_result({error, Reason}, _) -> {400, ?BAD_REQUEST, Reason}. + +to_json(Data) -> + emqx_utils_maps:jsonable_map( + Data, + fun(K, V) -> + {K, emqx_utils_maps:binary_string(V)} + end + ). diff --git a/apps/emqx_dashboard_sso/src/emqx_dashboard_sso_ldap.erl b/apps/emqx_dashboard_sso/src/emqx_dashboard_sso_ldap.erl index 94762081c..dc7e6a74a 100644 --- a/apps/emqx_dashboard_sso/src/emqx_dashboard_sso_ldap.erl +++ b/apps/emqx_dashboard_sso/src/emqx_dashboard_sso_ldap.erl @@ -18,7 +18,7 @@ -export([ hocon_ref/0, login_ref/0, - sign/2, + login/2, create/1, update/2, destroy/1 @@ -35,14 +35,14 @@ login_ref() -> hoconsc:ref(?MODULE, login). fields(ldap) -> - emqx_dashboard_sso_schema:common_backend_schema(ldap) ++ + emqx_dashboard_sso_schema:common_backend_schema([ldap]) ++ [ {query_timeout, fun query_timeout/1} ] ++ emqx_ldap:fields(config) ++ emqx_ldap:fields(bind_opts); fields(login) -> [ - emqx_dashboard_sso_schema:backend_schema(ldap) + emqx_dashboard_sso_schema:backend_schema([ldap]) | emqx_dashboard_sso_schema:username_password_schema() ]. @@ -61,7 +61,7 @@ create(Config0) -> case emqx_dashboard_sso_manager:create_resource(ResourceId, emqx_ldap, Config) of {ok, _} -> {ok, State#{resource_id => ResourceId}}; - Error -> + {error, _} = Error -> Error end. @@ -70,7 +70,7 @@ update(Config0, #{resource_id := ResourceId} = _State) -> case emqx_dashboard_sso_manager:update_resource(ResourceId, emqx_ldap, Config) of {ok, _} -> {ok, NState#{resource_id => ResourceId}}; - Error -> + {error, _} = Error -> Error end. @@ -78,8 +78,8 @@ destroy(#{resource_id := ResourceId}) -> _ = emqx_resource:remove_local(ResourceId), ok. -sign( - #{username := Username} = Req, +login( + #{<<"username">> := Username} = Req, #{ query_timeout := Timeout, resource_id := ResourceId @@ -101,8 +101,7 @@ sign( ) of ok -> - User = ensure_user_exists(Username), - {ok, emqx_dashboard_token:sign(User, <<>>)}; + ensure_user_exists(Username); {error, _} = Error -> Error end; @@ -128,7 +127,12 @@ parse_config(Config) -> ensure_user_exists(Username) -> case emqx_dashboard_admin:lookup_user(ldap, Username) of [User] -> - User; + {ok, emqx_dashboard_token:sign(User, <<>>)}; [] -> - emqx_dashboard_admin:add_sso_user(ldap, Username, ?ROLE_VIEWER, <<>>) + case emqx_dashboard_admin:add_sso_user(ldap, Username, ?ROLE_VIEWER, <<>>) of + {ok, _} -> + ensure_user_exists(Username); + Error -> + Error + end end. diff --git a/apps/emqx_dashboard_sso/src/emqx_dashboard_sso_manager.erl b/apps/emqx_dashboard_sso/src/emqx_dashboard_sso_manager.erl index 63bb6536c..a087af615 100644 --- a/apps/emqx_dashboard_sso/src/emqx_dashboard_sso_manager.erl +++ b/apps/emqx_dashboard_sso/src/emqx_dashboard_sso_manager.erl @@ -30,7 +30,6 @@ ]). -export([ - create/2, update/2, delete/1, pre_config_update/3, @@ -68,8 +67,6 @@ running() -> emqx:get_config([emqx_dashboard_sso]) ). -create(Backend, Config) -> - update_config(Backend, {?FUNCTION_NAME, Backend, Config}). update(Backend, Config) -> update_config(Backend, {?FUNCTION_NAME, Backend, Config}). delete(Backend) -> @@ -85,7 +82,7 @@ lookup_state(Backend) -> make_resource_id(Backend) -> BackendBin = bin(Backend), - emqx_resource:generate_id(BackendBin). + emqx_resource:generate_id(<<"sso:", BackendBin/binary>>). create_resource(ResourceId, Module, Config) -> Result = emqx_resource:create_local( @@ -95,7 +92,7 @@ create_resource(ResourceId, Module, Config) -> Config, ?DEFAULT_RESOURCE_OPTS ), - start_resource_if_enabled(Result, ResourceId, Config). + start_resource_if_enabled(ResourceId, Result, Config). update_resource(ResourceId, Module, Config) -> Result = emqx_resource:recreate_local( @@ -127,6 +124,9 @@ init([]) -> handle_call({update_config, Req, NewConf, OldConf}, _From, State) -> Result = on_config_update(Req, NewConf, OldConf), + io:format(">>> on_config_update:~p~n,Req:~p~n NewConf:~p~n OldConf:~p~n", [ + Result, Req, NewConf, OldConf + ]), {reply, Result, State}; handle_call(_Request, _From, State) -> Reply = ok, @@ -166,60 +166,43 @@ start_backend_services() -> maps:to_list(Backends) ). -update_config(Backend, UpdateReq) -> - case emqx_conf:update([dashboard_sso, Backend], UpdateReq, #{override_to => cluster}) of +update_config(_Backend, UpdateReq) -> + case emqx_conf:update([dashboard_sso], UpdateReq, #{override_to => cluster}) of {ok, UpdateResult} -> #{post_config_update := #{?MODULE := Result}} = UpdateResult, - {ok, Result}; + Result; Error -> Error end. -pre_config_update(_Path, {create, Backend, Config}, OldConf) -> - case maps:find(Backend, OldConf) of - {ok, _} -> - throw(already_exists); - error -> - {ok, OldConf#{Backend => Config}} - end; pre_config_update(_Path, {update, Backend, Config}, OldConf) -> - case maps:find(Backend, OldConf) of - error -> - throw(not_exists); - {ok, _} -> - {ok, OldConf#{Backend => Config}} - end; + BackendBin = bin(Backend), + {ok, OldConf#{BackendBin => Config}}; pre_config_update(_Path, {delete, Backend}, OldConf) -> - case maps:find(Backend, OldConf) of + BackendBin = bin(Backend), + case maps:find(BackendBin, OldConf) of error -> throw(not_exists); {ok, _} -> - {ok, maps:remove(Backend, OldConf)} + {ok, maps:remove(BackendBin, OldConf)} end. post_config_update(_Path, UpdateReq, NewConf, OldConf, _AppEnvs) -> Result = call({update_config, UpdateReq, NewConf, OldConf}), {ok, Result}. -on_config_update({create, Backend, Config}, _NewConf, _OldConf) -> +on_config_update({update, Backend, _Config}, NewConf, _OldConf) -> + Provider = provider(Backend), + Config = maps:get(Backend, NewConf), case lookup(Backend) of undefined -> - Provider = provider(Backend), on_backend_updated( Provider:create(Config), fun(State) -> ets:insert(dashboard_sso, #dashboard_sso{backend = Backend, state = State}) end ); - _Data -> - {error, already_exists} - end; -on_config_update({update, Backend, Config}, _NewConf, _OldConf) -> - case lookup(Backend) of - undefined -> - {error, not_exists}; Data -> - Provider = provider(Backend), on_backend_updated( Provider:update(Config, Data#dashboard_sso.state), fun(State) -> diff --git a/apps/emqx_dashboard_sso/src/emqx_dashboard_sso_schema.erl b/apps/emqx_dashboard_sso/src/emqx_dashboard_sso_schema.erl index ce9a53557..19b0473fd 100644 --- a/apps/emqx_dashboard_sso/src/emqx_dashboard_sso_schema.erl +++ b/apps/emqx_dashboard_sso/src/emqx_dashboard_sso_schema.erl @@ -14,7 +14,7 @@ backend_schema/1, username_password_schema/0 ]). --import(hoconsc, [ref/2, mk/2]). +-import(hoconsc, [ref/2, mk/2, enum/1]). %%------------------------------------------------------------------------------ %% Hocon Schema @@ -39,6 +39,7 @@ desc(dashboard_sso) -> desc(_) -> undefined. +-spec common_backend_schema(list(atom())) -> proplists:proplist(). common_backend_schema(Backend) -> [ {enable, @@ -54,7 +55,7 @@ common_backend_schema(Backend) -> backend_schema(Backend) -> {backend, - mk(Backend, #{ + mk(enum(Backend), #{ required => true, desc => ?DESC(backend) })}. diff --git a/apps/emqx_enterprise/src/emqx_enterprise.app.src b/apps/emqx_enterprise/src/emqx_enterprise.app.src index ac35da5b9..37d31c5ec 100644 --- a/apps/emqx_enterprise/src/emqx_enterprise.app.src +++ b/apps/emqx_enterprise/src/emqx_enterprise.app.src @@ -1,6 +1,6 @@ {application, emqx_enterprise, [ {description, "EMQX Enterprise Edition"}, - {vsn, "0.1.2"}, + {vsn, "0.1.3"}, {registered, []}, {applications, [ kernel, diff --git a/apps/emqx_ldap/src/emqx_ldap.erl b/apps/emqx_ldap/src/emqx_ldap.erl index cdf6a9a4c..021916339 100644 --- a/apps/emqx_ldap/src/emqx_ldap.erl +++ b/apps/emqx_ldap/src/emqx_ldap.erl @@ -75,8 +75,16 @@ fields(config) -> ?HOCON(emqx_schema:timeout_duration_ms(), #{ desc => ?DESC(request_timeout), default => <<"5s">> + })}, + {ssl, + ?HOCON(?R_REF(?MODULE, ssl), #{ + default => #{<<"enable">> => false}, + desc => ?DESC(emqx_connector_schema_lib, "ssl") })} - ] ++ emqx_connector_schema_lib:ssl_fields(); + ]; +fields(ssl) -> + Schema = emqx_schema:client_ssl_opts_schema(#{}), + lists:keydelete("user_lookup_fun", 1, Schema); fields(bind_opts) -> [ {bind_password, diff --git a/rel/i18n/emqx_dashboard_api.hocon b/rel/i18n/emqx_dashboard_api.hocon index 01fc6eb16..5f6bd3cde 100644 --- a/rel/i18n/emqx_dashboard_api.hocon +++ b/rel/i18n/emqx_dashboard_api.hocon @@ -79,4 +79,10 @@ users_api404.desc: version.desc: """EMQX Version""" +role.desc: +"""User role""" + +backend.desc: +"""User account source""" + } diff --git a/rel/i18n/emqx_dashboard_sso_api.hocon b/rel/i18n/emqx_dashboard_sso_api.hocon index 122ef0085..85cb7d31b 100644 --- a/rel/i18n/emqx_dashboard_sso_api.hocon +++ b/rel/i18n/emqx_dashboard_sso_api.hocon @@ -10,21 +10,11 @@ login.desc: login.label: """Get Dashboard Auth Token.""" -get_running.desc: -"""Get Running SSO backends""" -get_running.label: -"""Running SSO""" - get_backend.desc: """Get details of a backend""" get_backend.label: """Backend Details""" -create_backend.desc: -"""Create a backend""" -create_backend.label: -"""Create Backend""" - update_backend.desc: """Update a backend""" update_backend.label: