Merge pull request #58 from rabbitmq/rabbitmq-server-1085

Add tests for topic authorisation consumption
This commit is contained in:
Michael Klishin 2017-02-06 01:22:27 +03:00 committed by GitHub
commit 1284d3d662
2 changed files with 86 additions and 17 deletions

View File

@ -119,11 +119,11 @@ check_topic_access(User = #auth_user{username = Username,
Context) ->
OptionsArgs = topic_context_as_options(Context),
Args = [{username, Username},
{user_dn, UserDN},
{vhost, VHost},
{resource, Resource},
{name, Name},
{permission, Permission}] ++ OptionsArgs,
{user_dn, UserDN},
{vhost, VHost},
{resource, Resource},
{name, Name},
{permission, Permission}] ++ OptionsArgs,
?L("CHECK: ~s for ~s", [log_resource(Args), log_user(User)]),
R = evaluate_ldap(env(topic_access_query), Args, User),
?L("DECISION: ~s for ~s: ~p",

View File

@ -86,6 +86,7 @@ base_conf_ldap(LdapPort, IdleTimeout, PoolSize) ->
]}}
]}}
]}},
{topic_access_query, topic_access_query_base()},
{tag_queries, [{monitor, {constant, true}},
{administrator, {constant, false}},
{management, {constant, false}}]}
@ -96,7 +97,7 @@ base_conf_ldap(LdapPort, IdleTimeout, PoolSize) ->
all() ->
[
{group, non_parallel_tests},
{group, with_idle_timeout}
{group, with_idle_timeout}
].
groups() ->
@ -109,7 +110,8 @@ groups() ->
tag_attribution_internal_followed_by_ldap_and_internal,
invalid_or_clause_ldap_only,
invalid_and_clause_ldap_only,
topic_authorisation_ldap_only,
topic_authorisation_publishing_ldap_only,
topic_authorisation_consumption,
match_bidirectional
],
[
@ -230,6 +232,11 @@ end_per_testcase(Testcase, Config)
Testcase == invalid_and_clause_ldap_only ->
set_env(Config, vhost_access_query_base_env()),
rabbit_ct_helpers:testcase_finished(Config, Testcase);
end_per_testcase(Testcase, Config)
when Testcase == topic_authorisation_publishing_ldap_only;
Testcase == topic_authorisation_consumption ->
set_env(Config, topic_access_query_base_env()),
rabbit_ct_helpers:testcase_finished(Config, Testcase);
end_per_testcase(Testcase, Config) ->
rabbit_ct_helpers:testcase_finished(Config, Testcase).
@ -362,7 +369,9 @@ invalid_and_clause_ldap_only(Config) ->
% This may not be a reliable return value assertion
{error, not_allowed} = amqp_connection:start(B?ALICE).
topic_authorisation_ldap_only(Config) ->
topic_authorisation_publishing_ldap_only(Config) ->
%% topic authorisation at publishing time is enforced in the AMQP channel
%% so it can be tested by sending messages
ok = rabbit_ct_broker_helpers:rpc(Config, 0,
application, set_env, [rabbit, auth_backends, [rabbit_auth_backend_ldap]]),
@ -376,20 +385,20 @@ topic_authorisation_ldap_only(Config) ->
P = #amqp_params_network{port = rabbit_ct_broker_helpers:get_node_config(Config, 0, tcp_port_amqp)},
test_publish(P?ALICE, <<"amq.topic">>, <<"a.b.c">>, ok),
%% check string substitution (on username)
set_env(Config, [{topic_access_query, {'and',
[{equals, "${username}", "Alice"}]
}}]),
set_env(Config, [{topic_access_query, {for, [{permission, write, {equals, "${username}", "Alice"}},
{permission, read, {constant, false}}
]}}]),
test_publish(P?ALICE, <<"amq.topic">>, <<"a.b.c">>, ok),
test_publish(P?BOB, <<"amq.topic">>, <<"a.b.c">>, fail),
%% check string substitution on routing key (with regex)
set_env(Config, [{topic_access_query, {'and',
[{equals, "${username}", "Alice"},
{match, {string, "${routing_key}"}, {string, "^a"}}
]
}}]),
set_env(Config, [{topic_access_query, {for, [{permission, write, {'and',
[{equals, "${username}", "Alice"},
{match, {string, "${routing_key}"}, {string, "^a"}}]
}},
{permission, read, {constant, false}}
]}}]),
%% user and routing key OK
test_publish(P?ALICE, <<"amq.topic">>, <<"a.b.c">>, ok),
%% user and routing key OK
@ -401,6 +410,60 @@ topic_authorisation_ldap_only(Config) ->
ok.
topic_authorisation_consumption(Config) ->
%% topic authorisation for consumption isn't enforced in AMQP
%% (it is in plugins like STOMP and MQTT, at subscription time)
%% so we directly test the LDAP backend, inside the broker
ok = rabbit_ct_broker_helpers:rpc(Config, 0,
?MODULE, topic_authorisation_consumption1, [Config]).
topic_authorisation_consumption1(Config) ->
%% we can't use the LDAP backend record here, falling back to simple tuples
Alice = {auth_user,<<"Alice">>, [monitor],
{impl,"cn=Alice,ou=People,dc=rabbitmq,dc=com",<<"password">>}
},
Bob = {auth_user,<<"Bob">>, [monitor],
{impl,"cn=Bob,ou=People,dc=rabbitmq,dc=com",<<"password">>}
},
Resource = #resource{virtual_host = <<"/">>, name = <<"amq.topic">>, kind = topic},
Context = #{routing_key => <<"a.b">>},
%% default is to let pass
true = rabbit_auth_backend_ldap:check_topic_access(Alice, Resource, read, Context),
%% let pass for topic
set_env(Config, [{topic_access_query, {for, [{permission, read, {constant, true}},
{permission, write, {constant, false}}]
}}]),
true = rabbit_auth_backend_ldap:check_topic_access(Alice, Resource, read, Context),
%% check string substitution (on username)
set_env(Config, [{topic_access_query, {for, [{permission, read, {equals, "${username}", "Alice"}},
{permission, write, {constant, false}}]
}}]),
true = rabbit_auth_backend_ldap:check_topic_access(Alice, Resource, read, Context),
false = rabbit_auth_backend_ldap:check_topic_access(Bob, Resource, read, Context),
%% check string substitution on routing key (with regex)
set_env(Config, [{topic_access_query, {for, [{permission, read, {'and',
[{equals, "${username}", "Alice"},
{match, {string, "${routing_key}"}, {string, "^a"}}]
}},
{permission, write, {constant, false}}]
}}]),
%% user and routing key OK
true = rabbit_auth_backend_ldap:check_topic_access(Alice, Resource, read, #{routing_key => <<"a.b.c">>}),
%% user and routing key OK
true = rabbit_auth_backend_ldap:check_topic_access(Alice, Resource, read, #{routing_key => <<"a.c">>}),
%% user OK, routing key KO, should fail
false = rabbit_auth_backend_ldap:check_topic_access(Alice, Resource, read, #{routing_key => <<"b.c">>}),
%% user KO, routing key OK, should fail
false = rabbit_auth_backend_ldap:check_topic_access(Bob, Resource, read, #{routing_key => <<"a.b.c">>}),
ok.
match_bidirectional(Config) ->
ok = rabbit_ct_broker_helpers:rpc(Config, 0,
application, set_env, [rabbit, auth_backends, [rabbit_auth_backend_ldap]]),
@ -594,6 +657,12 @@ vhost_access_query_base_env() ->
vhost_access_query_base() ->
{exists, "ou=${vhost},ou=vhosts,dc=rabbitmq,dc=com"}.
topic_access_query_base_env() ->
[{topic_access_query, topic_access_query_base()}].
topic_access_query_base() ->
{constant, true}.
test_login(Config, {N, Env}, Login, FilterList, ResultFun) ->
case lists:member(N, FilterList) of
true -> [];