summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--test/authn_authz_context_propagation_SUITE.erl136
-rw-r--r--test/rabbit_auth_backend_context_propagation_mock.erl55
-rw-r--r--test/rabbit_foo_protocol_connection_info.erl34
3 files changed, 225 insertions, 0 deletions
diff --git a/test/authn_authz_context_propagation_SUITE.erl b/test/authn_authz_context_propagation_SUITE.erl
new file mode 100644
index 0000000000..8eaf169b46
--- /dev/null
+++ b/test/authn_authz_context_propagation_SUITE.erl
@@ -0,0 +1,136 @@
+%% The contents of this file are subject to the Mozilla Public License
+%% Version 1.1 (the "License"); you may not use this file except in
+%% compliance with the License. You may obtain a copy of the License at
+%% https://www.mozilla.org/MPL/
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+%% License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% The Original Code is RabbitMQ.
+%%
+%% The Initial Developer of the Original Code is GoPivotal, Inc.
+%% Copyright (c) 2019 Pivotal Software, Inc. All rights reserved.
+%%
+
+-module(authn_authz_context_propagation_SUITE).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("eunit/include/eunit.hrl").
+-include_lib("amqp_client/include/amqp_client.hrl").
+
+-compile(export_all).
+
+all() ->
+ [
+ {group, non_parallel_tests}
+ ].
+
+groups() ->
+ [
+ {non_parallel_tests, [], [
+ propagate_context_to_auth_backend
+ ]}
+ ].
+
+%% -------------------------------------------------------------------
+%% Testsuite 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(_, Config) ->
+ Config.
+
+end_per_group(_, Config) ->
+ Config.
+
+init_per_testcase(Testcase, Config) ->
+ AuthConfig = {rabbit, [
+ {auth_backends, [rabbit_auth_backend_context_propagation_mock]}
+ ]
+ },
+ rabbit_ct_helpers:testcase_started(Config, Testcase),
+ Config1 = rabbit_ct_helpers:set_config(Config, [
+ {rmq_nodename_suffix, Testcase}
+ ]),
+ rabbit_ct_helpers:run_setup_steps(Config1,
+ [ fun(Conf) -> merge_app_env(AuthConfig, Conf) end ] ++
+ rabbit_ct_broker_helpers:setup_steps() ++
+ rabbit_ct_client_helpers:setup_steps()).
+
+merge_app_env(SomeConfig, Config) ->
+ rabbit_ct_helpers:merge_app_env(Config, SomeConfig).
+
+end_per_testcase(Testcase, Config) ->
+ Config1 = rabbit_ct_helpers:run_steps(Config,
+ rabbit_ct_client_helpers:teardown_steps() ++
+ rabbit_ct_broker_helpers:teardown_steps()),
+ rabbit_ct_helpers:testcase_finished(Config1, Testcase).
+
+%% -------------------------------------------------------------------
+%% Testcases.
+%% -------------------------------------------------------------------
+
+propagate_context_to_auth_backend(Config) ->
+ ok = rabbit_ct_broker_helpers:add_code_path_to_all_nodes(Config,
+ rabbit_auth_backend_context_propagation_mock),
+ passed = rabbit_ct_broker_helpers:rpc(Config, 0,
+ ?MODULE, propagate_context_to_auth_backend1, []).
+
+propagate_context_to_auth_backend1() ->
+ rabbit_auth_backend_context_propagation_mock:init(),
+ AmqpParams = #amqp_params_direct{
+ virtual_host = <<"/">>,
+ username = <<"guest">>,
+ password = <<"guest">>,
+ adapter_info = #amqp_adapter_info{additional_info = [
+ {variable_map, #{<<"key1">> => <<"value1">>}}
+ ],
+ protocol = {'FOO_PROTOCOL', '1.0'} %% this will trigger a call to rabbit_foo_protocol_connection_info
+ }
+ },
+ {ok, Conn} = amqp_connection:start(AmqpParams),
+
+ %% rabbit_direct will call the rabbit_foo_protocol_connection_info module to extract information
+ %% this information will be propagated to the authentication backend
+ [{authentication, AuthProps}] = rabbit_auth_backend_context_propagation_mock:get(authentication),
+ ?assertEqual(<<"value1">>, proplists:get_value(key1, AuthProps)),
+
+ %% variable_map is propagated from rabbit_direct to the authorization backend
+ [{vhost_access, AuthzData}] = rabbit_auth_backend_context_propagation_mock:get(vhost_access),
+ ?assertEqual(<<"value1">>, maps:get(<<"key1">>, AuthzData)),
+
+ %% variable_map is extracted when the channel is created and kept in its state
+ {ok, Ch} = amqp_connection:open_channel(Conn),
+ QName = <<"channel_propagate_context_to_authz_backend-q">>,
+ amqp_channel:call(Ch, #'queue.declare'{queue = QName}),
+
+ check_send_receive(Ch, <<"">>, QName, QName),
+ amqp_channel:call(Ch, #'queue.bind'{queue = QName, exchange = <<"amq.topic">>, routing_key = <<"a.b">>}),
+ %% variable_map content is propagated from rabbit_channel to the authorization backend (resource check)
+ [{resource_access, AuthzContext}] = rabbit_auth_backend_context_propagation_mock:get(resource_access),
+ ?assertEqual(<<"value1">>, maps:get(<<"key1">>, AuthzContext)),
+
+ check_send_receive(Ch, <<"amq.topic">>, <<"a.b">>, QName),
+ %% variable_map is propagated from rabbit_channel to the authorization backend (topic check)
+ [{topic_access, TopicContext}] = rabbit_auth_backend_context_propagation_mock:get(topic_access),
+ VariableMap = maps:get(variable_map, TopicContext),
+ ?assertEqual(<<"value1">>, maps:get(<<"key1">>, VariableMap)),
+
+ passed.
+
+check_send_receive(Ch, Exchange, RoutingKey, QName) ->
+ amqp_channel:call(Ch,
+ #'basic.publish'{exchange = Exchange, routing_key = RoutingKey},
+ #amqp_msg{payload = <<"foo">>}),
+
+ {#'basic.get_ok'{}, #amqp_msg{payload = <<"foo">>}} =
+ amqp_channel:call(Ch, #'basic.get'{queue = QName,
+ no_ack = true}).
diff --git a/test/rabbit_auth_backend_context_propagation_mock.erl b/test/rabbit_auth_backend_context_propagation_mock.erl
new file mode 100644
index 0000000000..7f1c287079
--- /dev/null
+++ b/test/rabbit_auth_backend_context_propagation_mock.erl
@@ -0,0 +1,55 @@
+%% The contents of this file are subject to the Mozilla Public License
+%% Version 1.1 (the "License"); you may not use this file except in
+%% compliance with the License. You may obtain a copy of the License
+%% at https://www.mozilla.org/MPL/
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and
+%% limitations under the License.
+%%
+%% The Original Code is RabbitMQ.
+%%
+%% The Initial Developer of the Original Code is GoPivotal, Inc.
+%% Copyright (c) 2019 Pivotal Software, Inc. All rights reserved.
+%%
+
+%% A mock authn/authz that records information during calls. For testing purposes only.
+
+-module(rabbit_auth_backend_context_propagation_mock).
+-include_lib("rabbit_common/include/rabbit.hrl").
+
+-behaviour(rabbit_authn_backend).
+-behaviour(rabbit_authz_backend).
+
+-export([user_login_authentication/2, user_login_authorization/2,
+ check_vhost_access/3, check_resource_access/4, check_topic_access/4,
+ state_can_expire/0,
+ get/1, init/0]).
+
+init() ->
+ ets:new(?MODULE, [set, public, named_table]).
+
+user_login_authentication(_, AuthProps) ->
+ ets:insert(?MODULE, {authentication, AuthProps}),
+ {ok, #auth_user{username = <<"dummy">>,
+ tags = [],
+ impl = none}}.
+
+user_login_authorization(_, _) ->
+ {ok, does_not_matter}.
+
+check_vhost_access(#auth_user{}, _VHostPath, AuthzData) ->
+ ets:insert(?MODULE, {vhost_access, AuthzData}),
+ true.
+check_resource_access(#auth_user{}, #resource{}, _Permission, AuthzContext) ->
+ ets:insert(?MODULE, {resource_access, AuthzContext}),
+ true.
+check_topic_access(#auth_user{}, #resource{}, _Permission, TopicContext) ->
+ ets:insert(?MODULE, {topic_access, TopicContext}),
+ true.
+
+state_can_expire() -> false.
+
+get(K) ->
+ ets:lookup(?MODULE, K).
diff --git a/test/rabbit_foo_protocol_connection_info.erl b/test/rabbit_foo_protocol_connection_info.erl
new file mode 100644
index 0000000000..ead6e8f11e
--- /dev/null
+++ b/test/rabbit_foo_protocol_connection_info.erl
@@ -0,0 +1,34 @@
+%% The contents of this file are subject to the Mozilla Public License
+%% Version 1.1 (the "License"); you may not use this file except in
+%% compliance with the License. You may obtain a copy of the License
+%% at https://www.mozilla.org/MPL/
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and
+%% limitations under the License.
+%%
+%% The Original Code is RabbitMQ.
+%%
+%% The Initial Developer of the Original Code is GoPivotal, Inc.
+%% Copyright (c) 2019 Pivotal Software, Inc. All rights reserved.
+%%
+-module(rabbit_foo_protocol_connection_info).
+
+%% Dummy module to test authentication context propagation
+
+%% API
+-export([additional_authn_params/4]).
+
+additional_authn_params(_Creds, _VHost, _Pid, Infos) ->
+ case proplists:get_value(variable_map, Infos, undefined) of
+ VariableMap when is_map(VariableMap) ->
+ case maps:get(<<"key1">>, VariableMap, []) of
+ Value when is_binary(Value)->
+ [{key1, Value}];
+ [] ->
+ []
+ end;
+ _ ->
+ []
+ end. \ No newline at end of file