rabbitmq-server/deps/rabbit/test/unit_access_control_credent...

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

269 lines
11 KiB
Erlang
Raw Permalink Normal View History

%% This Source Code Form is subject to the terms of the Mozilla Public
%% License, v. 2.0. If a copy of the MPL was not distributed with this
%% file, You can obtain one at https://mozilla.org/MPL/2.0/.
%%
2024-01-02 11:02:20 +08:00
%% Copyright (c) 2007-2025 Broadcom. All Rights Reserved. The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. All rights reserved.
%%
2020-04-01 00:20:48 +08:00
-module(unit_access_control_credential_validation_SUITE).
-compile(export_all).
-include_lib("proper/include/proper.hrl").
-include_lib("eunit/include/eunit.hrl").
all() ->
[
{group, unit},
{group, integration}
].
groups() ->
[
{integration, [], [
2017-01-05 03:35:09 +08:00
min_length_integration_fails
, regexp_integration_fails
, min_length_integration_succeeds
, regexp_integration_succeeds
, min_length_change_password_integration_fails
, regexp_change_password_integration_fails
, min_length_change_password_integration_succeeds
, regexp_change_password_integration_succeeds
]},
{unit, [parallel], [
2017-01-05 03:35:09 +08:00
basic_unconditionally_accepting_succeeds,
min_length_fails,
min_length_succeeds,
min_length_proper_fails,
min_length_proper_succeeds,
regexp_fails,
regexp_succeeds,
regexp_proper_fails,
regexp_proper_succeeds
]}
].
suite() ->
[
{timetrap, {minutes, 4}}
].
2017-01-05 03:35:09 +08:00
%%
%% Setup/teardown
%%
init_per_suite(Config) ->
rabbit_ct_helpers:log_environment(),
rabbit_ct_helpers:run_setup_steps(Config).
end_per_suite(Config) ->
rabbit_ct_helpers:run_teardown_steps(Config).
init_per_group(integration, Config) ->
2017-01-05 03:35:09 +08:00
Suffix = rabbit_ct_helpers:testcase_absname(Config, "", "-"),
Config1 = rabbit_ct_helpers:set_config(Config, [
{rmq_nodes_count, 1},
{rmq_nodename_suffix, Suffix}
]),
rabbit_ct_helpers:run_steps(Config1,
rabbit_ct_broker_helpers:setup_steps());
init_per_group(unit, Config) ->
Config.
2017-01-05 03:35:09 +08:00
end_per_group(integration, Config) ->
rabbit_ct_broker_helpers:switch_credential_validator(Config, accept_everything),
2017-01-05 03:35:09 +08:00
rabbit_ct_helpers:run_steps(Config,
rabbit_ct_broker_helpers:teardown_steps());
end_per_group(unit, Config) ->
Config.
2017-01-05 03:35:09 +08:00
-define(USERNAME, <<"abc">>).
init_per_testcase(Testcase, Config) ->
2017-01-05 03:35:09 +08:00
rabbit_ct_helpers:testcase_started(Config, Testcase).
end_per_testcase(Testcase, Config) ->
2017-01-05 03:35:09 +08:00
rabbit_ct_helpers:testcase_finished(Config, Testcase).
%%
%% Test Cases
%%
basic_unconditionally_accepting_succeeds(_Config) ->
F = fun rabbit_credential_validator_accept_everything:validate/2,
Pwd1 = crypto:strong_rand_bytes(1),
?assertEqual(ok, F(?USERNAME, Pwd1)),
Pwd2 = crypto:strong_rand_bytes(5),
?assertEqual(ok, F(?USERNAME, Pwd2)),
Pwd3 = crypto:strong_rand_bytes(10),
?assertEqual(ok, F(?USERNAME, Pwd3)),
Pwd4 = crypto:strong_rand_bytes(50),
?assertEqual(ok, F(?USERNAME, Pwd4)),
Pwd5 = crypto:strong_rand_bytes(100),
?assertEqual(ok, F(?USERNAME, Pwd5)),
Pwd6 = crypto:strong_rand_bytes(1000),
?assertEqual(ok, F(?USERNAME, Pwd6)).
min_length_fails(_Config) ->
F = fun rabbit_credential_validator_min_password_length:validate/3,
Pwd1 = crypto:strong_rand_bytes(1),
?assertMatch({error, _}, F(?USERNAME, Pwd1, 5)),
Pwd2 = crypto:strong_rand_bytes(5),
?assertMatch({error, _}, F(?USERNAME, Pwd2, 6)),
Pwd3 = crypto:strong_rand_bytes(10),
?assertMatch({error, _}, F(?USERNAME, Pwd3, 15)),
Pwd4 = crypto:strong_rand_bytes(50),
?assertMatch({error, _}, F(?USERNAME, Pwd4, 60)),
Pwd5 = undefined,
?assertMatch({error, _}, F(?USERNAME, Pwd5, 60)),
Pwd6 = <<"">>,
?assertMatch({error, _}, F(?USERNAME, Pwd6, 60)).
min_length_succeeds(_Config) ->
F = fun rabbit_credential_validator_min_password_length:validate/3,
?assertEqual(ok, F(?USERNAME, crypto:strong_rand_bytes(1), 1)),
?assertEqual(ok, F(?USERNAME, crypto:strong_rand_bytes(6), 6)),
?assertEqual(ok, F(?USERNAME, crypto:strong_rand_bytes(7), 6)),
?assertEqual(ok, F(?USERNAME, crypto:strong_rand_bytes(20), 20)),
?assertEqual(ok, F(?USERNAME, crypto:strong_rand_bytes(40), 30)),
?assertEqual(ok, F(?USERNAME, crypto:strong_rand_bytes(50), 50)).
min_length_proper_fails(_Config) ->
rabbit_ct_proper_helpers:run_proper(fun prop_min_length_fails_validation/0, [], 500).
min_length_proper_succeeds(_Config) ->
rabbit_ct_proper_helpers:run_proper(fun prop_min_length_passes_validation/0, [], 500).
regexp_fails(_Config) ->
F = fun rabbit_credential_validator_password_regexp:validate/3,
?assertMatch({error, _}, F(?USERNAME, <<"abc">>, "^xyz")),
?assertMatch({error, _}, F(?USERNAME, <<"abcdef">>, "^xyz")),
?assertMatch({error, _}, F(?USERNAME, <<"abcxyz">>, "^abc\\d+")).
regexp_succeeds(_Config) ->
F = fun rabbit_credential_validator_password_regexp:validate/3,
?assertEqual(ok, F(?USERNAME, <<"abc">>, "^abc")),
?assertEqual(ok, F(?USERNAME, <<"abcdef">>, "^abc")),
?assertEqual(ok, F(?USERNAME, <<"abc123">>, "^abc\\d+")).
regexp_proper_fails(_Config) ->
rabbit_ct_proper_helpers:run_proper(fun prop_regexp_fails_validation/0, [], 500).
regexp_proper_succeeds(_Config) ->
rabbit_ct_proper_helpers:run_proper(fun prop_regexp_passes_validation/0, [], 500).
min_length_integration_fails(Config) ->
rabbit_ct_broker_helpers:delete_user(Config, ?USERNAME),
rabbit_ct_broker_helpers:switch_credential_validator(Config, min_length, 50),
?assertMatch(rabbit_credential_validator_min_password_length, validator_backend(Config)),
?assertMatch({error, "minimum required password length is 50"},
rabbit_ct_broker_helpers:add_user(Config, ?USERNAME, <<"_">>)).
2017-01-05 00:26:55 +08:00
regexp_integration_fails(Config) ->
rabbit_ct_broker_helpers:delete_user(Config, ?USERNAME),
rabbit_ct_broker_helpers:switch_credential_validator(Config, regexp),
?assertMatch(rabbit_credential_validator_password_regexp, validator_backend(Config)),
?assertMatch({error, _}, rabbit_ct_broker_helpers:add_user(Config, ?USERNAME, <<"_">>)).
2017-01-05 00:26:55 +08:00
min_length_integration_succeeds(Config) ->
rabbit_ct_broker_helpers:delete_user(Config, ?USERNAME),
rabbit_ct_broker_helpers:switch_credential_validator(Config, min_length, 5),
?assertMatch(rabbit_credential_validator_min_password_length, validator_backend(Config)),
?assertMatch(ok, rabbit_ct_broker_helpers:add_user(Config, ?USERNAME, <<"abcdefghi">>)).
2017-01-05 00:26:55 +08:00
regexp_integration_succeeds(Config) ->
rabbit_ct_broker_helpers:delete_user(Config, ?USERNAME),
rabbit_ct_broker_helpers:switch_credential_validator(Config, regexp),
?assertMatch(rabbit_credential_validator_password_regexp, validator_backend(Config)),
?assertMatch(ok, rabbit_ct_broker_helpers:add_user(Config, ?USERNAME, <<"xyz12345678901">>)).
2017-01-05 00:26:55 +08:00
min_length_change_password_integration_fails(Config) ->
rabbit_ct_broker_helpers:delete_user(Config, ?USERNAME),
rabbit_ct_broker_helpers:switch_credential_validator(Config, accept_everything),
rabbit_ct_broker_helpers:add_user(Config, ?USERNAME, <<"abcdefghi">>),
rabbit_ct_broker_helpers:switch_credential_validator(Config, min_length, 50),
?assertMatch(rabbit_credential_validator_min_password_length, validator_backend(Config)),
?assertMatch({error, "minimum required password length is 50"},
rabbit_ct_broker_helpers:change_password(Config, ?USERNAME, <<"_">>)).
regexp_change_password_integration_fails(Config) ->
rabbit_ct_broker_helpers:delete_user(Config, ?USERNAME),
rabbit_ct_broker_helpers:switch_credential_validator(Config, accept_everything),
rabbit_ct_broker_helpers:add_user(Config, ?USERNAME, <<"abcdefghi">>),
rabbit_ct_broker_helpers:switch_credential_validator(Config, regexp),
?assertMatch(rabbit_credential_validator_password_regexp, validator_backend(Config)),
?assertMatch({error, _}, rabbit_ct_broker_helpers:change_password(Config, ?USERNAME, <<"_">>)).
min_length_change_password_integration_succeeds(Config) ->
rabbit_ct_broker_helpers:delete_user(Config, ?USERNAME),
rabbit_ct_broker_helpers:switch_credential_validator(Config, accept_everything),
rabbit_ct_broker_helpers:add_user(Config, ?USERNAME, <<"abcdefghi">>),
rabbit_ct_broker_helpers:switch_credential_validator(Config, min_length, 5),
?assertMatch(rabbit_credential_validator_min_password_length, validator_backend(Config)),
?assertMatch(ok, rabbit_ct_broker_helpers:change_password(Config, ?USERNAME, <<"abcdefghi">>)).
regexp_change_password_integration_succeeds(Config) ->
rabbit_ct_broker_helpers:delete_user(Config, ?USERNAME),
rabbit_ct_broker_helpers:switch_credential_validator(Config, accept_everything),
rabbit_ct_broker_helpers:add_user(Config, ?USERNAME, <<"abcdefghi">>),
rabbit_ct_broker_helpers:switch_credential_validator(Config, regexp),
?assertMatch(rabbit_credential_validator_password_regexp, validator_backend(Config)),
?assertMatch(ok, rabbit_ct_broker_helpers:change_password(Config, ?USERNAME, <<"xyz12345678901">>)).
%%
%% PropEr
%%
prop_min_length_fails_validation() ->
N = 5,
F = fun rabbit_credential_validator_min_password_length:validate/3,
?FORALL(Val, binary(N),
?FORALL(Length, choose(N + 1, 100),
failed_validation(F(?USERNAME, Val, Length + 1)))).
prop_min_length_passes_validation() ->
N = 20,
F = fun rabbit_credential_validator_min_password_length:validate/3,
?FORALL(Val, binary(N),
?FORALL(Length, choose(1, N - 1),
passed_validation(F(?USERNAME, Val, Length)))).
prop_regexp_fails_validation() ->
N = 5,
F = fun rabbit_credential_validator_password_regexp:validate/3,
?FORALL(Val, binary(N),
?FORALL(Length, choose(N + 1, 100),
failed_validation(F(?USERNAME, Val, regexp_that_requires_length_of_at_least(Length + 1))))).
prop_regexp_passes_validation() ->
N = 5,
F = fun rabbit_credential_validator_password_regexp:validate/3,
?FORALL(Val, binary(N),
passed_validation(F(?USERNAME, Val, regexp_that_requires_length_of_at_most(size(Val) + 1)))).
%%
%% Helpers
%%
passed_validation(ok) ->
true;
passed_validation({error, _}) ->
false.
failed_validation(Result) ->
not passed_validation(Result).
regexp_that_requires_length_of_at_least(N) when is_integer(N) ->
rabbit_misc:format("^[a-zA-Z0-9]{~tp,~tp}", [N, N + 10]).
regexp_that_requires_length_of_at_most(N) when is_integer(N) ->
rabbit_misc:format("^[a-zA-Z0-9]{0,~tp}", [N]).
2017-01-05 03:35:09 +08:00
validator_backend(Config) ->
rabbit_ct_broker_helpers:rpc(Config, 0, rabbit_credential_validation, backend, []).