2020-07-10 21:31:17 +08:00
|
|
|
%% 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/.
|
2016-12-21 19:33:15 +08:00
|
|
|
%%
|
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.
|
2016-12-21 19:33:15 +08:00
|
|
|
%%
|
|
|
|
|
2020-04-01 00:20:48 +08:00
|
|
|
-module(unit_access_control_credential_validation_SUITE).
|
2016-12-21 19:33:15 +08:00
|
|
|
|
|
|
|
-compile(export_all).
|
2016-12-29 00:56:44 +08:00
|
|
|
-include_lib("proper/include/proper.hrl").
|
2016-12-21 19:33:15 +08:00
|
|
|
-include_lib("eunit/include/eunit.hrl").
|
|
|
|
|
|
|
|
all() ->
|
|
|
|
[
|
2017-01-04 19:41:45 +08:00
|
|
|
{group, unit},
|
|
|
|
{group, integration}
|
2016-12-21 19:33:15 +08:00
|
|
|
].
|
|
|
|
|
2017-01-04 19:41:45 +08:00
|
|
|
groups() ->
|
|
|
|
[
|
|
|
|
{integration, [], [
|
2017-01-05 03:35:09 +08:00
|
|
|
min_length_integration_fails
|
|
|
|
, regexp_integration_fails
|
|
|
|
, min_length_integration_succeeds
|
|
|
|
, regexp_integration_succeeds
|
2017-01-05 15:52:37 +08:00
|
|
|
, min_length_change_password_integration_fails
|
|
|
|
, regexp_change_password_integration_fails
|
|
|
|
, min_length_change_password_integration_succeeds
|
|
|
|
, regexp_change_password_integration_succeeds
|
2017-01-04 19:41:45 +08:00
|
|
|
]},
|
|
|
|
{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
|
2017-01-04 19:41:45 +08:00
|
|
|
]}
|
|
|
|
].
|
|
|
|
|
|
|
|
suite() ->
|
|
|
|
[
|
|
|
|
{timetrap, {minutes, 4}}
|
|
|
|
].
|
|
|
|
|
2017-01-05 03:35:09 +08:00
|
|
|
%%
|
|
|
|
%% Setup/teardown
|
|
|
|
%%
|
|
|
|
|
2017-01-04 19:41:45 +08:00
|
|
|
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());
|
2017-01-04 19:41:45 +08:00
|
|
|
|
|
|
|
init_per_group(unit, Config) ->
|
2016-12-21 19:33:15 +08:00
|
|
|
Config.
|
|
|
|
|
2017-01-05 03:35:09 +08:00
|
|
|
end_per_group(integration, Config) ->
|
2017-01-07 02:18:22 +08:00
|
|
|
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) ->
|
2016-12-21 19:33:15 +08:00
|
|
|
Config.
|
|
|
|
|
2017-01-05 03:35:09 +08:00
|
|
|
-define(USERNAME, <<"abc">>).
|
|
|
|
|
2017-01-04 19:41:45 +08:00
|
|
|
init_per_testcase(Testcase, Config) ->
|
2017-01-05 03:35:09 +08:00
|
|
|
rabbit_ct_helpers:testcase_started(Config, Testcase).
|
2017-01-04 19:41:45 +08:00
|
|
|
|
|
|
|
end_per_testcase(Testcase, Config) ->
|
2017-01-05 03:35:09 +08:00
|
|
|
rabbit_ct_helpers:testcase_finished(Config, Testcase).
|
2016-12-21 19:33:15 +08:00
|
|
|
|
|
|
|
%%
|
|
|
|
%% Test Cases
|
|
|
|
%%
|
|
|
|
|
|
|
|
basic_unconditionally_accepting_succeeds(_Config) ->
|
2017-01-05 23:55:49 +08:00
|
|
|
F = fun rabbit_credential_validator_accept_everything:validate/2,
|
2016-12-21 19:33:15 +08:00
|
|
|
|
|
|
|
Pwd1 = crypto:strong_rand_bytes(1),
|
2017-01-05 23:55:49 +08:00
|
|
|
?assertEqual(ok, F(?USERNAME, Pwd1)),
|
2016-12-21 19:33:15 +08:00
|
|
|
Pwd2 = crypto:strong_rand_bytes(5),
|
2017-01-05 23:55:49 +08:00
|
|
|
?assertEqual(ok, F(?USERNAME, Pwd2)),
|
2016-12-21 19:33:15 +08:00
|
|
|
Pwd3 = crypto:strong_rand_bytes(10),
|
2017-01-05 23:55:49 +08:00
|
|
|
?assertEqual(ok, F(?USERNAME, Pwd3)),
|
2016-12-21 19:33:15 +08:00
|
|
|
Pwd4 = crypto:strong_rand_bytes(50),
|
2017-01-05 23:55:49 +08:00
|
|
|
?assertEqual(ok, F(?USERNAME, Pwd4)),
|
2016-12-21 19:33:15 +08:00
|
|
|
Pwd5 = crypto:strong_rand_bytes(100),
|
2017-01-05 23:55:49 +08:00
|
|
|
?assertEqual(ok, F(?USERNAME, Pwd5)),
|
2016-12-21 19:33:15 +08:00
|
|
|
Pwd6 = crypto:strong_rand_bytes(1000),
|
2017-01-05 23:55:49 +08:00
|
|
|
?assertEqual(ok, F(?USERNAME, Pwd6)).
|
2016-12-21 20:44:53 +08:00
|
|
|
|
|
|
|
min_length_fails(_Config) ->
|
2017-01-05 23:55:49 +08:00
|
|
|
F = fun rabbit_credential_validator_min_password_length:validate/3,
|
2016-12-21 20:44:53 +08:00
|
|
|
|
|
|
|
Pwd1 = crypto:strong_rand_bytes(1),
|
2017-01-05 23:55:49 +08:00
|
|
|
?assertMatch({error, _}, F(?USERNAME, Pwd1, 5)),
|
2016-12-21 20:44:53 +08:00
|
|
|
Pwd2 = crypto:strong_rand_bytes(5),
|
2017-01-05 23:55:49 +08:00
|
|
|
?assertMatch({error, _}, F(?USERNAME, Pwd2, 6)),
|
2016-12-21 20:44:53 +08:00
|
|
|
Pwd3 = crypto:strong_rand_bytes(10),
|
2017-01-05 23:55:49 +08:00
|
|
|
?assertMatch({error, _}, F(?USERNAME, Pwd3, 15)),
|
2016-12-21 20:44:53 +08:00
|
|
|
Pwd4 = crypto:strong_rand_bytes(50),
|
2020-02-29 07:13:49 +08:00
|
|
|
?assertMatch({error, _}, F(?USERNAME, Pwd4, 60)),
|
|
|
|
Pwd5 = undefined,
|
|
|
|
?assertMatch({error, _}, F(?USERNAME, Pwd5, 60)),
|
|
|
|
Pwd6 = <<"">>,
|
|
|
|
?assertMatch({error, _}, F(?USERNAME, Pwd6, 60)).
|
2016-12-21 20:44:53 +08:00
|
|
|
|
|
|
|
min_length_succeeds(_Config) ->
|
2017-01-05 23:55:49 +08:00
|
|
|
F = fun rabbit_credential_validator_min_password_length:validate/3,
|
2016-12-21 20:44:53 +08:00
|
|
|
|
2017-01-05 23:55:49 +08:00
|
|
|
?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)).
|
2016-12-29 00:56:44 +08:00
|
|
|
|
|
|
|
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).
|
|
|
|
|
2016-12-30 03:56:57 +08:00
|
|
|
regexp_fails(_Config) ->
|
2017-01-05 23:55:49 +08:00
|
|
|
F = fun rabbit_credential_validator_password_regexp:validate/3,
|
2016-12-30 03:56:57 +08:00
|
|
|
|
2017-01-05 23:55:49 +08:00
|
|
|
?assertMatch({error, _}, F(?USERNAME, <<"abc">>, "^xyz")),
|
|
|
|
?assertMatch({error, _}, F(?USERNAME, <<"abcdef">>, "^xyz")),
|
|
|
|
?assertMatch({error, _}, F(?USERNAME, <<"abcxyz">>, "^abc\\d+")).
|
2016-12-30 03:56:57 +08:00
|
|
|
|
|
|
|
regexp_succeeds(_Config) ->
|
2017-01-05 23:55:49 +08:00
|
|
|
F = fun rabbit_credential_validator_password_regexp:validate/3,
|
2016-12-30 03:56:57 +08:00
|
|
|
|
2017-01-05 23:55:49 +08:00
|
|
|
?assertEqual(ok, F(?USERNAME, <<"abc">>, "^abc")),
|
|
|
|
?assertEqual(ok, F(?USERNAME, <<"abcdef">>, "^abc")),
|
|
|
|
?assertEqual(ok, F(?USERNAME, <<"abc123">>, "^abc\\d+")).
|
2017-01-03 15:08:45 +08:00
|
|
|
|
|
|
|
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).
|
2016-12-30 03:56:57 +08:00
|
|
|
|
2017-01-04 19:41:45 +08:00
|
|
|
min_length_integration_fails(Config) ->
|
2017-01-07 02:18:22 +08:00
|
|
|
rabbit_ct_broker_helpers:delete_user(Config, ?USERNAME),
|
|
|
|
rabbit_ct_broker_helpers:switch_credential_validator(Config, min_length, 50),
|
2017-01-05 23:55:49 +08:00
|
|
|
?assertMatch(rabbit_credential_validator_min_password_length, validator_backend(Config)),
|
2017-01-05 15:52:37 +08:00
|
|
|
?assertMatch({error, "minimum required password length is 50"},
|
2017-01-07 02:18:22 +08:00
|
|
|
rabbit_ct_broker_helpers:add_user(Config, ?USERNAME, <<"_">>)).
|
2017-01-04 19:41:45 +08:00
|
|
|
|
2017-01-05 00:26:55 +08:00
|
|
|
regexp_integration_fails(Config) ->
|
2017-01-07 02:18:22 +08:00
|
|
|
rabbit_ct_broker_helpers:delete_user(Config, ?USERNAME),
|
|
|
|
rabbit_ct_broker_helpers:switch_credential_validator(Config, regexp),
|
2017-01-05 23:55:49 +08:00
|
|
|
?assertMatch(rabbit_credential_validator_password_regexp, validator_backend(Config)),
|
2017-01-07 02:18:22 +08:00
|
|
|
?assertMatch({error, _}, rabbit_ct_broker_helpers:add_user(Config, ?USERNAME, <<"_">>)).
|
2017-01-05 00:26:55 +08:00
|
|
|
|
|
|
|
min_length_integration_succeeds(Config) ->
|
2017-01-07 02:18:22 +08:00
|
|
|
rabbit_ct_broker_helpers:delete_user(Config, ?USERNAME),
|
|
|
|
rabbit_ct_broker_helpers:switch_credential_validator(Config, min_length, 5),
|
2017-01-05 23:55:49 +08:00
|
|
|
?assertMatch(rabbit_credential_validator_min_password_length, validator_backend(Config)),
|
2017-01-07 02:18:22 +08:00
|
|
|
?assertMatch(ok, rabbit_ct_broker_helpers:add_user(Config, ?USERNAME, <<"abcdefghi">>)).
|
2017-01-05 00:26:55 +08:00
|
|
|
|
|
|
|
regexp_integration_succeeds(Config) ->
|
2017-01-07 02:18:22 +08:00
|
|
|
rabbit_ct_broker_helpers:delete_user(Config, ?USERNAME),
|
|
|
|
rabbit_ct_broker_helpers:switch_credential_validator(Config, regexp),
|
2017-01-05 23:55:49 +08:00
|
|
|
?assertMatch(rabbit_credential_validator_password_regexp, validator_backend(Config)),
|
2017-01-07 02:18:22 +08:00
|
|
|
?assertMatch(ok, rabbit_ct_broker_helpers:add_user(Config, ?USERNAME, <<"xyz12345678901">>)).
|
2017-01-05 00:26:55 +08:00
|
|
|
|
2017-01-05 15:52:37 +08:00
|
|
|
min_length_change_password_integration_fails(Config) ->
|
2017-01-07 02:18:22 +08:00
|
|
|
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),
|
2017-01-05 23:55:49 +08:00
|
|
|
?assertMatch(rabbit_credential_validator_min_password_length, validator_backend(Config)),
|
2017-01-05 15:52:37 +08:00
|
|
|
?assertMatch({error, "minimum required password length is 50"},
|
2017-01-07 02:18:22 +08:00
|
|
|
rabbit_ct_broker_helpers:change_password(Config, ?USERNAME, <<"_">>)).
|
2017-01-05 15:52:37 +08:00
|
|
|
|
|
|
|
regexp_change_password_integration_fails(Config) ->
|
2017-01-07 02:18:22 +08:00
|
|
|
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),
|
2017-01-05 23:55:49 +08:00
|
|
|
?assertMatch(rabbit_credential_validator_password_regexp, validator_backend(Config)),
|
2017-01-07 02:18:22 +08:00
|
|
|
?assertMatch({error, _}, rabbit_ct_broker_helpers:change_password(Config, ?USERNAME, <<"_">>)).
|
2017-01-05 15:52:37 +08:00
|
|
|
|
|
|
|
min_length_change_password_integration_succeeds(Config) ->
|
2017-01-07 02:18:22 +08:00
|
|
|
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),
|
2017-01-05 23:55:49 +08:00
|
|
|
?assertMatch(rabbit_credential_validator_min_password_length, validator_backend(Config)),
|
2017-01-07 02:18:22 +08:00
|
|
|
?assertMatch(ok, rabbit_ct_broker_helpers:change_password(Config, ?USERNAME, <<"abcdefghi">>)).
|
2017-01-05 15:52:37 +08:00
|
|
|
|
|
|
|
regexp_change_password_integration_succeeds(Config) ->
|
2017-01-07 02:18:22 +08:00
|
|
|
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),
|
2017-01-05 23:55:49 +08:00
|
|
|
?assertMatch(rabbit_credential_validator_password_regexp, validator_backend(Config)),
|
2017-01-07 02:18:22 +08:00
|
|
|
?assertMatch(ok, rabbit_ct_broker_helpers:change_password(Config, ?USERNAME, <<"xyz12345678901">>)).
|
2017-01-05 15:52:37 +08:00
|
|
|
|
2016-12-29 00:56:44 +08:00
|
|
|
%%
|
|
|
|
%% PropEr
|
|
|
|
%%
|
|
|
|
|
|
|
|
prop_min_length_fails_validation() ->
|
|
|
|
N = 5,
|
2017-01-05 23:55:49 +08:00
|
|
|
F = fun rabbit_credential_validator_min_password_length:validate/3,
|
2016-12-29 00:56:44 +08:00
|
|
|
?FORALL(Val, binary(N),
|
|
|
|
?FORALL(Length, choose(N + 1, 100),
|
2017-01-05 23:55:49 +08:00
|
|
|
failed_validation(F(?USERNAME, Val, Length + 1)))).
|
2016-12-29 00:56:44 +08:00
|
|
|
|
|
|
|
prop_min_length_passes_validation() ->
|
|
|
|
N = 20,
|
2017-01-05 23:55:49 +08:00
|
|
|
F = fun rabbit_credential_validator_min_password_length:validate/3,
|
2016-12-29 00:56:44 +08:00
|
|
|
?FORALL(Val, binary(N),
|
|
|
|
?FORALL(Length, choose(1, N - 1),
|
2017-01-05 23:55:49 +08:00
|
|
|
passed_validation(F(?USERNAME, Val, Length)))).
|
2016-12-29 00:56:44 +08:00
|
|
|
|
2017-01-03 15:08:45 +08:00
|
|
|
prop_regexp_fails_validation() ->
|
|
|
|
N = 5,
|
2017-01-05 23:55:49 +08:00
|
|
|
F = fun rabbit_credential_validator_password_regexp:validate/3,
|
2017-01-03 15:08:45 +08:00
|
|
|
?FORALL(Val, binary(N),
|
|
|
|
?FORALL(Length, choose(N + 1, 100),
|
2017-01-05 23:55:49 +08:00
|
|
|
failed_validation(F(?USERNAME, Val, regexp_that_requires_length_of_at_least(Length + 1))))).
|
2017-01-03 15:08:45 +08:00
|
|
|
|
|
|
|
prop_regexp_passes_validation() ->
|
|
|
|
N = 5,
|
2017-01-05 23:55:49 +08:00
|
|
|
F = fun rabbit_credential_validator_password_regexp:validate/3,
|
2017-01-03 15:08:45 +08:00
|
|
|
?FORALL(Val, binary(N),
|
2017-01-05 23:55:49 +08:00
|
|
|
passed_validation(F(?USERNAME, Val, regexp_that_requires_length_of_at_most(size(Val) + 1)))).
|
2017-01-03 15:08:45 +08:00
|
|
|
|
2016-12-29 00:56:44 +08:00
|
|
|
%%
|
|
|
|
%% Helpers
|
|
|
|
%%
|
|
|
|
|
|
|
|
passed_validation(ok) ->
|
|
|
|
true;
|
|
|
|
passed_validation({error, _}) ->
|
|
|
|
false.
|
|
|
|
|
|
|
|
failed_validation(Result) ->
|
|
|
|
not passed_validation(Result).
|
2017-01-03 15:08:45 +08:00
|
|
|
|
|
|
|
regexp_that_requires_length_of_at_least(N) when is_integer(N) ->
|
2022-10-08 06:59:05 +08:00
|
|
|
rabbit_misc:format("^[a-zA-Z0-9]{~tp,~tp}", [N, N + 10]).
|
2017-01-03 15:08:45 +08:00
|
|
|
|
|
|
|
regexp_that_requires_length_of_at_most(N) when is_integer(N) ->
|
2022-10-08 06:59:05 +08:00
|
|
|
rabbit_misc:format("^[a-zA-Z0-9]{0,~tp}", [N]).
|
2017-01-04 19:41:45 +08:00
|
|
|
|
2017-01-05 03:35:09 +08:00
|
|
|
validator_backend(Config) ->
|
|
|
|
rabbit_ct_broker_helpers:rpc(Config, 0, rabbit_credential_validation, backend, []).
|