Skip to content
This repository has been archived by the owner on Nov 17, 2020. It is now read-only.

Commit

Permalink
Support topic authorisation for publishing
Browse files Browse the repository at this point in the history
  • Loading branch information
acogoluegnes committed Jan 31, 2017
1 parent a213e62 commit 76bad8c
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 6 deletions.
11 changes: 10 additions & 1 deletion src/rabbit_auth_backend_cache.erl
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
-behaviour(rabbit_authz_backend).

-export([user_login_authentication/2, user_login_authorization/1,
check_vhost_access/3, check_resource_access/3]).
check_vhost_access/3, check_resource_access/3, check_topic_access/4]).

%% Implementation of rabbit_auth_backend

Expand Down Expand Up @@ -59,6 +59,15 @@ check_resource_access(#auth_user{} = AuthUser,
(_) -> unknown
end).

check_topic_access(#auth_user{} = AuthUser,
#resource{} = Resource, Permission, Context) ->
with_cache(authz, {check_topic_access, [AuthUser, Resource, Permission, Context]},
fun(true) -> success;
(false) -> refusal;
({error, _} = Err) -> Err;
(_) -> unknown
end).

with_cache(BackendType, {F, A}, Fun) ->
{ok, AuthCache} = application:get_env(rabbitmq_auth_backend_cache,
cache_module),
Expand Down
64 changes: 59 additions & 5 deletions test/src/rabbit_auth_backend_cache_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ all() ->
authentication_response,
authorization_response,
access_response,
cache_expiration
cache_expiration,
cache_expiration_topic
].

init_per_suite(Config) ->
Expand All @@ -27,6 +28,27 @@ setup_env(Config) ->
end_per_suite(Config) ->
rabbit_ct_helpers:run_teardown_steps(Config, rabbit_ct_broker_helpers:teardown_steps()).

init_per_testcase(access_response, Config) ->
ok = rpc(Config, rabbit_auth_backend_internal, set_topic_permissions, [
<<"guest">>, <<"/">>, <<"amq.topic">>, <<"^a">>, <<"acting-user">>
]),
Config;
init_per_testcase(_TestCase, Config) ->
Config.

end_per_testcase(TestCase, Config) when TestCase == access_response;
TestCase == cache_expiration_topic ->
ok = rpc(Config, rabbit_auth_backend_internal, clear_topic_permissions, [
<<"guest">>, <<"/">>, <<"acting-user">>
]),
Config;
end_per_testcase(cache_expiration, Config) ->
rabbit_ct_broker_helpers:add_user(Config, <<"guest">>),
rabbit_ct_broker_helpers:set_full_permissions(Config, <<"/">>),
Config;
end_per_testcase(_TestCase, Config) ->
Config.

authentication_response(Config) ->
{ok, AuthRespOk} = rpc(Config,rabbit_auth_backend_internal, user_login_authentication, [<<"guest">>, [{password, <<"guest">>}]]),
{ok, AuthRespOk} = rpc(Config,rabbit_auth_backend_cache, user_login_authentication, [<<"guest">>, [{password, <<"guest">>}]]),
Expand All @@ -43,8 +65,11 @@ authorization_response(Config) ->
access_response(Config) ->
AvailableVhost = <<"/">>,
RestrictedVhost = <<"restricted">>,
AvailableResource = #resource{virtual_host = AvailableVhost, kind = excahnge, name = <<"some">>},
RestrictedResource = #resource{virtual_host = RestrictedVhost, kind = excahnge, name = <<"some">>},
AvailableResource = #resource{virtual_host = AvailableVhost, kind = exchange, name = <<"some">>},
RestrictedResource = #resource{virtual_host = RestrictedVhost, kind = exchange, name = <<"some">>},
TopicResource = #resource{virtual_host = AvailableVhost, kind = topic, name = <<"amq.topic">>},
AuthorisedTopicContext = #{routing_key => <<"a.b">>},
RestrictedTopicContext = #{routing_key => <<"b.b">>},

{ok, Auth} = rpc(Config,rabbit_auth_backend_internal, user_login_authentication, [<<"guest">>, [{password, <<"guest">>}]]),
true = rpc(Config,rabbit_auth_backend_internal, check_vhost_access, [Auth, AvailableVhost, none]),
Expand All @@ -57,7 +82,13 @@ access_response(Config) ->
true = rpc(Config,rabbit_auth_backend_cache, check_resource_access, [Auth, AvailableResource, configure]),

false = rpc(Config,rabbit_auth_backend_internal, check_resource_access, [Auth, RestrictedResource, configure]),
false = rpc(Config,rabbit_auth_backend_cache, check_resource_access, [Auth, RestrictedResource, configure]).
false = rpc(Config,rabbit_auth_backend_cache, check_resource_access, [Auth, RestrictedResource, configure]),

true = rpc(Config,rabbit_auth_backend_internal, check_topic_access, [Auth, TopicResource, write, AuthorisedTopicContext]),
true = rpc(Config,rabbit_auth_backend_cache, check_topic_access, [Auth, TopicResource, write, AuthorisedTopicContext]),

false = rpc(Config,rabbit_auth_backend_internal, check_topic_access, [Auth, TopicResource, write, RestrictedTopicContext]),
false = rpc(Config,rabbit_auth_backend_cache, check_topic_access, [Auth, TopicResource, write, RestrictedTopicContext]).

cache_expiration(Config) ->
AvailableVhost = <<"/">>,
Expand All @@ -71,7 +102,7 @@ cache_expiration(Config) ->
true = rpc(Config,rabbit_auth_backend_cache, check_resource_access, [Auth, AvailableResource, configure]),

rpc(Config,rabbit_auth_backend_internal, change_password, [<<"guest">>, <<"newpass">>, <<"acting-user">>]),

{refused, _, _} = rpc(Config,rabbit_auth_backend_internal, user_login_authentication, [<<"guest">>, [{password, <<"guest">>}]]),
{ok, Auth} = rpc(Config,rabbit_auth_backend_cache, user_login_authentication, [<<"guest">>, [{password, <<"guest">>}]]),
true = rpc(Config,rabbit_auth_backend_internal, check_vhost_access, [Auth, AvailableVhost, none]),
Expand Down Expand Up @@ -99,6 +130,29 @@ cache_expiration(Config) ->
false = rpc(Config,rabbit_auth_backend_internal, check_resource_access, [Auth, AvailableResource, configure]),
false = rpc(Config,rabbit_auth_backend_cache, check_resource_access, [Auth, AvailableResource, configure]).

cache_expiration_topic(Config) ->
AvailableVhost = <<"/">>,
TopicResource = #resource{virtual_host = AvailableVhost, kind = topic, name = <<"amq.topic">>},
RestrictedTopicContext = #{routing_key => <<"b.b">>},

{ok, Auth} = rpc(Config,rabbit_auth_backend_internal, user_login_authentication, [<<"guest">>, [{password, <<"guest">>}]]),

% topic access is authorised if no permission is found
true = rpc(Config,rabbit_auth_backend_internal, check_topic_access, [Auth, TopicResource, write, RestrictedTopicContext]),
true = rpc(Config,rabbit_auth_backend_cache, check_topic_access, [Auth, TopicResource, write, RestrictedTopicContext]),

ok = rpc(Config, rabbit_auth_backend_internal, set_topic_permissions, [
<<"guest">>, <<"/">>, <<"amq.topic">>, <<"^a">>, <<"acting-user">>
]),

false = rpc(Config,rabbit_auth_backend_internal, check_topic_access, [Auth, TopicResource, write, RestrictedTopicContext]),
true = rpc(Config,rabbit_auth_backend_cache, check_topic_access, [Auth, TopicResource, write, RestrictedTopicContext]),

{ok, TTL} = rpc(Config, application, get_env, [rabbitmq_auth_backend_cache, cache_ttl]),
timer:sleep(TTL),

false = rpc(Config,rabbit_auth_backend_internal, check_topic_access, [Auth, TopicResource, write, RestrictedTopicContext]),
false = rpc(Config,rabbit_auth_backend_cache, check_topic_access, [Auth, TopicResource, write, RestrictedTopicContext]).

rpc(Config, M, F, A) ->
rabbit_ct_broker_helpers:rpc(Config, 0, M, F, A).
Expand Down

0 comments on commit 76bad8c

Please sign in to comment.