1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
%% 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/.
%%
%% Copyright (c) 2019-2020 VMware, Inc. or its affiliates. All rights reserved.
%%
-module(unit_access_control_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).
%% -------------------------------------------------------------------
%% Test cases
%% -------------------------------------------------------------------
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}).
|