Skip to content

Commit

Permalink
Merge pull request #3131 from esl/configurable_dummy_auth_delays
Browse files Browse the repository at this point in the history
Make dummy auth delays configurable

This PR makes delays configurable for dummy auth method, which by default are too long and that's something that can be noticed in CI.
  • Loading branch information
DenysGonchar committed May 27, 2021
2 parents 404f6a0 + c239f44 commit e55fa8e
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 17 deletions.
38 changes: 31 additions & 7 deletions doc/authentication-methods/dummy.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,36 @@

The purpose of this method is to make it possible to authenticate a user without
the need for real authentication. In other words, using this module allows to
connect any user to the server without providing any password,
certificate, etc.
connect any user to the server without providing any password, certificate, etc.

From a more detailed perspective, the backend just accepts every
authentication attempt and introduces a random delay (50-500ms) to
an authorization response.
This kind of authorization sometimes really comes in handy, especially during development and testing.

The backend just accepts every authentication attempt and introduces a random delay (50-500ms) to an authorization response. The delay works like
```erlang
timer:sleep(Base + rand:uniform(Variance)),
```
where `Base` is `base_time` and `Variance` is `variance`, as configured below.

## Configuration

### `auth.dummy.base_time`
* **Scope:** local
* **Syntax:** integer
* **Default:** 50
* **Example:** `base_time = 5`

### `auth.dummy.variance`
* **Scope:** local
* **Syntax:** integer
* **Default:** 450
* **Example:** `variance = 10`

### Example

```toml
[auth]
methods = ["dummy"]
dummy.base = 5
dummy.variance = 10
```

This kind of authorization sometimes really comes in handy, especially during
development and testing.
4 changes: 3 additions & 1 deletion rel/mim1.vars-toml.config
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@

[[host_config]]
host_type = \"test type\"
auth = { methods = [\"dummy\"] }
auth.methods = [\"dummy\"]
auth.dummy.base_time = 1
auth.dummy.variance = 5
[host_config.modules.mod_carboncopy]"}.
{password_format, "password.format = \"scram\"
password.hash = [\"sha256\"]"}.
Expand Down
5 changes: 4 additions & 1 deletion src/auth/ejabberd_auth_dummy.erl
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ stop(_HostType) ->
ok.

authorize(Creds) ->
timer:sleep(50 + rand:uniform(450)),
HostType = mongoose_credentials:host_type(Creds),
Base = ejabberd_auth:get_opt(HostType, dummy_base_timeout, 50),
Variance = ejabberd_auth:get_opt(HostType, dummy_variance, 450),
timer:sleep(Base + rand:uniform(Variance)),
{ok, mongoose_credentials:set(Creds, auth_module, ?MODULE)}.

check_password(_HostType, _User, _Server, _Password) ->
Expand Down
14 changes: 13 additions & 1 deletion src/config/mongoose_config_spec.erl
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,8 @@ auth() ->
<<"jwt">> => auth_jwt(),
<<"ldap">> => auth_ldap(),
<<"riak">> => auth_riak(),
<<"rdbms">> => auth_rdbms()},
<<"rdbms">> => auth_rdbms(),
<<"dummy">> => auth_dummy()},
process = fun ?MODULE:process_auth/1,
format = {foreach, host_local_config}
}.
Expand Down Expand Up @@ -646,6 +647,17 @@ auth_rdbms() ->
format = none
}.

%% path: (host_config[].)auth.dummy
auth_dummy() ->
#section{
items = #{<<"base_time">> => #option{type = integer,
format = {kv, dummy_base_timeout}},
<<"variance">> => #option{type = integer,
format = {kv, dummy_variance}}
},
format = none
}.

%% path: outgoing_pools
outgoing_pools() ->
PoolTypes = [<<"cassandra">>, <<"elastic">>, <<"http">>, <<"ldap">>,
Expand Down
24 changes: 17 additions & 7 deletions test/auth_dummy_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -33,25 +33,37 @@ all() -> [
supports_dynamic_domains
].

init_per_suite(C) ->
{ok, _} = application:ensure_all_started(jid),
meck:new(ejabberd_config, [no_link]),
meck:expect(ejabberd_config, get_local_option,
fun({auth_method, ?HOST_TYPE}) -> dummy end),
meck:expect(ejabberd_config, get_local_option,
fun(auth_opts, _Host) ->
[{dummy_base_timeout, 5}, {dummy_variance, 10}]
end),
C.

end_per_suite(C) ->
meck:unload(),
C.

%%--------------------------------------------------------------------
%% Authentication tests
%%--------------------------------------------------------------------

authorize(_Config) ->
{ok, _} = application:ensure_all_started(jid),
Creds = mongoose_credentials:new(?DOMAIN, ?HOST_TYPE),
{ok, Creds2} = ejabberd_auth_dummy:authorize(Creds),
ejabberd_auth_dummy = mongoose_credentials:get(Creds2, auth_module).

ejabberd_auth_interfaces(_Config) ->
[meck:new(M, Opts) || {M, Opts} <-
[{mongoose_domain_api, []}, {ejabberd_auth_dummy, [passthrough]},
{ejabberd_config, []}, {mongoose_metrics, []}]],
{mongoose_metrics, []}]],

meck:expect(mongoose_domain_api, get_domain_host_type,
fun(?DOMAIN) -> {ok, ?HOST_TYPE} end),
meck:expect(ejabberd_config, get_local_option,
fun({auth_method, ?HOST_TYPE}) -> dummy end),
meck:expect(mongoose_metrics, update, fun(_, _, _) -> ok end),

Creds = mongoose_credentials:new(?DOMAIN, ?HOST_TYPE),
Expand All @@ -67,9 +79,7 @@ ejabberd_auth_interfaces(_Config) ->
Digest = <<"any_digest">>, DigestGen = fun(_) -> <<"">> end,
false = ejabberd_auth:check_password(JID, Password, Digest, DigestGen),
Args2 = [?HOST_TYPE, UserName, ?DOMAIN, Password, Digest, DigestGen],
1 = meck:num_calls(ejabberd_auth_dummy, check_password, Args2),

meck:unload().
1 = meck:num_calls(ejabberd_auth_dummy, check_password, Args2).

supports_dynamic_domains(_) ->
true = ejabberd_auth:does_method_support(dummy, dynamic_domains),
Expand Down

0 comments on commit e55fa8e

Please sign in to comment.