|
7 | 7 |
|
8 | 8 | -module(topic_permission_SUITE). |
9 | 9 |
|
10 | | --include_lib("rabbit_common/include/rabbit.hrl"). |
| 10 | +-include_lib("eunit/include/eunit.hrl"). |
| 11 | +-include_lib("amqp_client/include/amqp_client.hrl"). |
11 | 12 |
|
12 | | --compile(export_all). |
| 13 | +-compile([export_all, nowarn_export_all]). |
13 | 14 |
|
14 | 15 | all() -> |
15 | 16 | [ |
16 | | - {group, sequential_tests} |
| 17 | + {group, sequential_tests} |
17 | 18 | ]. |
18 | 19 |
|
19 | | -groups() -> [ |
20 | | - {sequential_tests, [], [ |
21 | | - topic_permission_database_access, |
22 | | - topic_permission_checks |
23 | | - ]} |
| 20 | +groups() -> |
| 21 | + [ |
| 22 | + {sequential_tests, [], |
| 23 | + [ |
| 24 | + amqpl_cc_headers, |
| 25 | + amqpl_bcc_headers, |
| 26 | + topic_permission_database_access, |
| 27 | + topic_permission_checks |
| 28 | + ]} |
24 | 29 | ]. |
25 | 30 |
|
26 | 31 | init_per_suite(Config) -> |
27 | 32 | rabbit_ct_helpers:log_environment(), |
28 | | - Config1 = rabbit_ct_helpers:set_config(Config, [ |
29 | | - {rmq_nodename_suffix, ?MODULE} |
30 | | - ]), |
31 | | - rabbit_ct_helpers:run_setup_steps(Config1, |
32 | | - rabbit_ct_broker_helpers:setup_steps() ++ |
33 | | - rabbit_ct_client_helpers:setup_steps()). |
| 33 | + Config1 = rabbit_ct_helpers:set_config( |
| 34 | + Config, |
| 35 | + [{rmq_nodename_suffix, ?MODULE}]), |
| 36 | + rabbit_ct_helpers:run_setup_steps( |
| 37 | + Config1, |
| 38 | + rabbit_ct_broker_helpers:setup_steps() ++ |
| 39 | + rabbit_ct_client_helpers:setup_steps()). |
34 | 40 |
|
35 | 41 | end_per_suite(Config) -> |
36 | | - rabbit_ct_helpers:run_teardown_steps(Config, |
37 | | - rabbit_ct_client_helpers:teardown_steps() ++ |
38 | | - rabbit_ct_broker_helpers:teardown_steps()). |
| 42 | + rabbit_ct_helpers:run_teardown_steps( |
| 43 | + Config, |
| 44 | + rabbit_ct_client_helpers:teardown_steps() ++ |
| 45 | + rabbit_ct_broker_helpers:teardown_steps()). |
| 46 | + |
| 47 | +init_per_group(_, Config) -> |
| 48 | + Config. |
39 | 49 |
|
40 | | -init_per_group(_, Config) -> Config. |
41 | | -end_per_group(_, Config) -> Config. |
| 50 | +end_per_group(_, Config) -> |
| 51 | + Config. |
42 | 52 |
|
43 | 53 | init_per_testcase(Testcase, Config) -> |
44 | | - ok = rabbit_ct_broker_helpers:rpc(Config, 0, |
45 | | - ?MODULE, clear_tables, []), |
46 | 54 | rabbit_ct_helpers:testcase_started(Config, Testcase). |
47 | 55 |
|
48 | | -clear_tables() -> |
49 | | - ok = rabbit_db_vhost:clear(), |
50 | | - ok = rabbit_db_user:clear(). |
51 | | - |
52 | 56 | end_per_testcase(Testcase, Config) -> |
53 | 57 | rabbit_ct_helpers:testcase_finished(Config, Testcase). |
54 | 58 |
|
| 59 | +amqpl_cc_headers(Config) -> |
| 60 | + amqpl_headers(<<"CC">>, Config). |
| 61 | + |
| 62 | +amqpl_bcc_headers(Config) -> |
| 63 | + amqpl_headers(<<"BCC">>, Config). |
| 64 | + |
| 65 | +amqpl_headers(Header, Config) -> |
| 66 | + QName1 = <<"q1">>, |
| 67 | + QName2 = <<"q2">>, |
| 68 | + Ch1 = rabbit_ct_client_helpers:open_channel(Config), |
| 69 | + |
| 70 | + ok = set_topic_permissions(Config, "^a", ".*"), |
| 71 | + |
| 72 | + #'queue.declare_ok'{} = amqp_channel:call(Ch1, #'queue.declare'{queue = QName1}), |
| 73 | + #'queue.declare_ok'{} = amqp_channel:call(Ch1, #'queue.declare'{queue = QName2}), |
| 74 | + #'queue.bind_ok'{} = amqp_channel:call(Ch1, #'queue.bind'{queue = QName1, |
| 75 | + exchange = <<"amq.topic">>, |
| 76 | + routing_key = <<"a.1">>}), |
| 77 | + #'queue.bind_ok'{} = amqp_channel:call(Ch1, #'queue.bind'{queue = QName2, |
| 78 | + exchange = <<"amq.topic">>, |
| 79 | + routing_key = <<"a.2">>}), |
| 80 | + |
| 81 | + amqp_channel:call(Ch1, #'confirm.select'{}), |
| 82 | + amqp_channel:register_confirm_handler(Ch1, self()), |
| 83 | + |
| 84 | + %% We have permissions to send to both topics. |
| 85 | + %% Therefore, m1 should be sent to both queues. |
| 86 | + amqp_channel:call( |
| 87 | + Ch1, |
| 88 | + #'basic.publish'{exchange = <<"amq.topic">>, |
| 89 | + routing_key = <<"a.1">>}, |
| 90 | + #amqp_msg{payload = <<"m1">>, |
| 91 | + props = #'P_basic'{headers = [{Header, array, [{longstr, <<"a.2">>}]}]}}), |
| 92 | + receive #'basic.ack'{} -> ok |
| 93 | + after 5000 -> ct:fail({missing_confirm, ?LINE}) |
| 94 | + end, |
| 95 | + |
| 96 | + monitor(process, Ch1), |
| 97 | + amqp_channel:call( |
| 98 | + Ch1, |
| 99 | + #'basic.publish'{exchange = <<"amq.topic">>, |
| 100 | + routing_key = <<"x.1">>}, |
| 101 | + #amqp_msg{payload = <<"m2">>, |
| 102 | + props = #'P_basic'{headers = [{Header, array, [{longstr, <<"a.2">>}]}]}}), |
| 103 | + ok = assert_channel_down( |
| 104 | + Ch1, |
| 105 | + <<"ACCESS_REFUSED - write access to topic 'x.1' in exchange " |
| 106 | + "'amq.topic' in vhost '/' refused for user 'guest'">>), |
| 107 | + |
| 108 | + Ch2 = rabbit_ct_client_helpers:open_channel(Config), |
| 109 | + monitor(process, Ch2), |
| 110 | + amqp_channel:call( |
| 111 | + Ch2, |
| 112 | + #'basic.publish'{exchange = <<"amq.topic">>, |
| 113 | + routing_key = <<"a.1">>}, |
| 114 | + #amqp_msg{payload = <<"m3">>, |
| 115 | + props = #'P_basic'{headers = [{Header, array, [{longstr, <<"x.2">>}]}]}}), |
| 116 | + ok = assert_channel_down( |
| 117 | + Ch2, |
| 118 | + <<"ACCESS_REFUSED - write access to topic 'x.2' in exchange " |
| 119 | + "'amq.topic' in vhost '/' refused for user 'guest'">>), |
| 120 | + |
| 121 | + Ch3 = rabbit_ct_client_helpers:open_channel(Config), |
| 122 | + ?assertEqual(#'queue.delete_ok'{message_count = 1}, |
| 123 | + amqp_channel:call(Ch3, #'queue.delete'{queue = QName1})), |
| 124 | + ?assertEqual(#'queue.delete_ok'{message_count = 1}, |
| 125 | + amqp_channel:call(Ch3, #'queue.delete'{queue = QName2})), |
| 126 | + ok = rabbit_ct_client_helpers:close_channel(Ch3), |
| 127 | + ok = clear_topic_permissions(Config). |
| 128 | + |
55 | 129 | topic_permission_database_access(Config) -> |
| 130 | + ok = rabbit_ct_broker_helpers:rpc(Config, ?MODULE, clear_tables, []), |
56 | 131 | ok = rabbit_ct_broker_helpers:rpc(Config, 0, |
57 | 132 | ?MODULE, topic_permission_database_access1, [Config]). |
58 | 133 |
|
@@ -134,6 +209,7 @@ topic_permission_database_access1(_Config) -> |
134 | 209 | ok. |
135 | 210 |
|
136 | 211 | topic_permission_checks(Config) -> |
| 212 | + ok = rabbit_ct_broker_helpers:rpc(Config, ?MODULE, clear_tables, []), |
137 | 213 | ok = rabbit_ct_broker_helpers:rpc(Config, 0, |
138 | 214 | ?MODULE, topic_permission_checks1, [Config]). |
139 | 215 |
|
@@ -228,3 +304,26 @@ topic_permission_checks1(_Config) -> |
228 | 304 | ) || Perm <- Permissions], |
229 | 305 |
|
230 | 306 | ok. |
| 307 | + |
| 308 | +clear_tables() -> |
| 309 | + ok = rabbit_db_vhost:clear(), |
| 310 | + ok = rabbit_db_user:clear(). |
| 311 | + |
| 312 | +set_topic_permissions(Config, WritePat, ReadPat) -> |
| 313 | + ok = rabbit_ct_broker_helpers:rpc( |
| 314 | + Config, 0, rabbit_auth_backend_internal, set_topic_permissions, |
| 315 | + [<<"guest">>, <<"/">>, <<"amq.topic">>, WritePat, ReadPat, <<"acting-user">>]). |
| 316 | + |
| 317 | +clear_topic_permissions(Config) -> |
| 318 | + ok = rabbit_ct_broker_helpers:rpc( |
| 319 | + Config, 0, rabbit_auth_backend_internal, clear_topic_permissions, |
| 320 | + [<<"guest">>, <<"/">>, <<"acting-user">>]). |
| 321 | + |
| 322 | +assert_channel_down(Ch, Reason) -> |
| 323 | + receive {'DOWN', _MonitorRef, process, Ch, |
| 324 | + {shutdown, |
| 325 | + {server_initiated_close, 403, Reason}}} -> |
| 326 | + ok |
| 327 | + after 5000 -> |
| 328 | + ct:fail({did_not_receive, Reason}) |
| 329 | + end. |
0 commit comments