Skip to content

Commit

Permalink
Merge pull request #4140 from esl/mod-keystore-for-cets
Browse files Browse the repository at this point in the history
Add CETS backend for mod_keystore
  • Loading branch information
chrzaszcz authored Oct 9, 2023
2 parents 27f7362 + e2d18e1 commit 6b46e5c
Show file tree
Hide file tree
Showing 8 changed files with 75 additions and 8 deletions.
1 change: 1 addition & 0 deletions big_tests/test.config
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@
{stream_management_backend, cets},
{muc_online_backend, cets},
{jingle_sip_backend, cets},
{keystore_backend, cets},
{auth_method, "rdbms"},
{internal_databases, "[internal_databases.cets]
cluster_name = \"{{cluster_name}}\""},
Expand Down
7 changes: 4 additions & 3 deletions big_tests/tests/graphql_token_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,10 @@ end_per_suite(Config) ->
dynamic_modules:restore_modules(Config),
escalus:end_per_suite(Config).

required_modules() ->
required_modules(Config) ->
KeyOpts = #{keys => #{token_secret => ram,
provision_pre_shared => ram}},
provision_pre_shared => ram},
backend => ct_helper:get_preset_var(Config, keystore_backend, mnesia)},
KeyStoreOpts = config_parser_helper:mod_config(mod_keystore, KeyOpts),
[{mod_keystore, KeyStoreOpts},
{mod_auth_token, auth_token_opts()}].
Expand Down Expand Up @@ -112,7 +113,7 @@ init_per_group(user, Config) ->

ensure_token_started(Config) ->
HostType = domain_helper:host_type(),
dynamic_modules:ensure_modules(HostType, required_modules()),
dynamic_modules:ensure_modules(HostType, required_modules(Config)),
Config.

ensure_token_stopped(Config) ->
Expand Down
7 changes: 4 additions & 3 deletions big_tests/tests/oauth_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ init_per_suite(Config0) ->
true ->
HostType = domain_helper:host_type(),
Config = dynamic_modules:save_modules(HostType, Config0),
dynamic_modules:ensure_modules(HostType, required_modules()),
dynamic_modules:ensure_modules(HostType, required_modules(Config)),
escalus:init_per_suite(Config);
false ->
{skip, "RDBMS not available"}
Expand Down Expand Up @@ -459,8 +459,9 @@ serialize(ServerSideToken) ->
to_lower(B) when is_binary(B) ->
list_to_binary(string:to_lower(binary_to_list(B))).

required_modules() ->
KeyOpts = #{keys => #{token_secret => ram,
required_modules(Config) ->
KeyOpts = #{backend => ct_helper:get_preset_var(Config, keystore_backend, mnesia),
keys => #{token_secret => ram,
%% This is a hack for tests! As the name implies,
%% a pre-shared key should be read from a file stored
%% on disk. This way it can be shared with trusted 3rd
Expand Down
2 changes: 1 addition & 1 deletion rebar.lock
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
{<<"certifi">>,{pkg,<<"certifi">>,<<"2.9.0">>},1},
{<<"cets">>,
{git,"https://github.com/esl/cets.git",
{ref,"e3ad43f3836ea457bcb54e2f8266e9d7c32b014f"}},
{ref,"f715c4a2e4b2bcb9f5c1dcd5164ee5271aefa0a9"}},
0},
{<<"cowboy">>,{pkg,<<"cowboy">>,<<"2.9.0">>},0},
{<<"cowboy_swagger">>,{pkg,<<"cowboy_swagger">>,<<"2.5.1">>},0},
Expand Down
1 change: 1 addition & 0 deletions src/mod_keystore.erl
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ start(HostType, Opts) ->
-spec stop(mongooseim:host_type()) -> ok.
stop(HostType) ->
clear_keystore_ets(HostType),
mod_keystore_backend:stop(HostType),
ok.

-spec hooks(mongooseim:host_type()) -> gen_hook:hook_list().
Expand Down
8 changes: 7 additions & 1 deletion src/mod_keystore_backend.erl
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
%% the backend modules (i.e. mod_keystore_mnesia...).
-module(mod_keystore_backend).

-export([init/2, init_ram_key/2, get_key/1]).
-export([init/2, stop/1, init_ram_key/2, get_key/1]).

-define(MAIN_MODULE, mod_keystore).

-callback init(mongooseim:host_type(), gen_mod:module_opts()) -> ok.
-callback stop(mongooseim:host_type()) -> ok.

%% Cluster members race to decide whose key gets stored in the distributed database.
%% That's why ProposedKey (the key this cluster member tries to propagate to other nodes)
Expand All @@ -24,6 +25,11 @@ init(HostType, Opts) ->
Args = [HostType, Opts],
mongoose_backend:call(HostType, ?MAIN_MODULE, ?FUNCTION_NAME, Args).

-spec stop(mongooseim:host_type()) -> ok.
stop(HostType) ->
Args = [HostType],
mongoose_backend:call(HostType, ?MAIN_MODULE, ?FUNCTION_NAME, Args).

%% Cluster members race to decide whose key gets stored in the distributed database.
%% That's why ProposedKey (the key this cluster member tries to propagate to other nodes)
%% might not be the same as ActualKey (key of the member who will have won the race).
Expand Down
52 changes: 52 additions & 0 deletions src/mod_keystore_cets.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
-module(mod_keystore_cets).
-behaviour(mod_keystore_backend).

-export([init/2,
stop/1,
init_ram_key/1,
get_key/1]).

%% CETS callbacks
-export([handle_conflict/2]).

-ignore_xref([get_key/1, init/2, init_ram_key/1]).

-include("mod_keystore.hrl").
-include("mongoose_logger.hrl").

table_name(HostType) ->
binary_to_atom(<<"cets_keystore_", HostType/binary>>).

-spec init(mongooseim:host_type(), gen_mod:module_opts()) -> ok.
init(HostType, _Opts) ->
%% There is no logic to remove keys.
%% Separate table per HostType (so we could remove the table once the module is unloaded).
Tab = table_name(HostType),
cets:start(Tab, #{handle_conflict => fun ?MODULE:handle_conflict/2}),
cets_discovery:add_table(mongoose_cets_discovery, Tab),
ok.

-spec stop(mongooseim:host_type()) -> ok.
stop(HostType) ->
Tab = table_name(HostType),
cets_discovery:delete_table(mongoose_cets_discovery, Tab),
cets:stop(Tab),
ok.

%% We need to choose one key consistently.
handle_conflict(Rec1, Rec2) ->
max(Rec1, Rec2).

-spec init_ram_key(ProposedKey) -> Result when
ProposedKey :: mod_keystore:key(),
Result :: {ok, ActualKey} | {error, init_ram_key_failed},
ActualKey :: mod_keystore:key().
init_ram_key(#key{id = Id = {_, HostType}, key = PropKey}) ->
Tab = table_name(HostType),
{_, [{Id, Key}]} = cets:insert_new_or_lookup(Tab, {Id, PropKey}),
{ok, #key{id = Id, key = Key}}.

-spec get_key(Id :: mod_keystore:key_id()) -> mod_keystore:key_list().
get_key(Id = {_, HostType}) ->
Tab = table_name(HostType),
ets:lookup(Tab, Id).
5 changes: 5 additions & 0 deletions src/mod_keystore_mnesia.erl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
-behaviour(mod_keystore_backend).

-export([init/2,
stop/1,
init_ram_key/1,
get_key/1]).

Expand All @@ -16,6 +17,10 @@ init(_HostType, _Opts) ->
{attributes, record_info(fields, key)}]),
ok.

-spec stop(mongooseim:host_type()) -> ok.
stop(_HostType) ->
ok.

-spec init_ram_key(ProposedKey) -> Result when
ProposedKey :: mod_keystore:key(),
Result :: {ok, ActualKey} | {error, any()},
Expand Down

0 comments on commit 6b46e5c

Please sign in to comment.