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

Commit

Permalink
Add check_topic_access/4 to rabbit_authz_backend
Browse files Browse the repository at this point in the history
  • Loading branch information
acogoluegnes committed Dec 29, 2016
1 parent 26f1d5c commit 241c42b
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 34 deletions.
4 changes: 1 addition & 3 deletions include/rabbit.hrl
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,7 @@
%% exchange, queue, ...
kind,
%% name as a binary
name,
%% options (e.g. routing key) as a map
options
name
}).

%% fields described as 'transient' here are cleared when writing to
Expand Down
3 changes: 2 additions & 1 deletion src/rabbit_auth_backend_dummy.erl
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

-export([user/0]).
-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]).

-spec user() -> rabbit_types:user().

Expand All @@ -42,3 +42,4 @@ user_login_authorization(_) ->

check_vhost_access(#auth_user{}, _VHostPath, _Sock) -> true.
check_resource_access(#auth_user{}, #resource{}, _Permission) -> true.
check_topic_access(#auth_user{}, #resource{}, _Permission, _Context) -> true.
49 changes: 25 additions & 24 deletions src/rabbit_auth_backend_internal.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]).

-export([add_user/2, delete_user/1, lookup_user/1,
change_password/2, clear_password/1,
Expand Down Expand Up @@ -141,29 +141,6 @@ check_vhost_access(#auth_user{username = Username}, VHostPath, _Sock) ->
[_R] -> true
end.

check_resource_access(#auth_user{username = Username},
#resource{virtual_host = VHostPath, name = Name,
options = Options,
kind = topic},
_Permission) ->
case mnesia:dirty_read({rabbit_topic_permission,
#topic_permission_key{user_vhost = #user_vhost{username = Username,
virtual_host = VHostPath},
name = Name
}}) of
[] ->
true;
[#topic_permission{pattern = Pattern}] ->
PermRegexp = case Pattern of
%% <<"^$">> breaks Emacs' erlang mode
<<"">> -> <<$^, $$>>;
RE -> RE
end,
case re:run(maps:get(routing_key, Options), PermRegexp, [{capture, none}]) of
match -> true;
nomatch -> false
end
end;
check_resource_access(#auth_user{username = Username},
#resource{virtual_host = VHostPath, name = Name},
Permission) ->
Expand All @@ -184,6 +161,30 @@ check_resource_access(#auth_user{username = Username},
end
end.

check_topic_access(#auth_user{username = Username},
#resource{virtual_host = VHostPath, name = Name, kind = topic},
_Permission,
Context) ->
case mnesia:dirty_read({rabbit_topic_permission,
#topic_permission_key{user_vhost = #user_vhost{username = Username,
virtual_host = VHostPath},
name = Name
}}) of
[] ->
true;
[#topic_permission{pattern = Pattern}] ->
PermRegexp = case Pattern of
%% <<"^$">> breaks Emacs' erlang mode
<<"">> -> <<$^, $$>>;
RE -> RE
end,
case re:run(maps:get(routing_key, Context), PermRegexp, [{capture, none}]) of
match -> true;
nomatch -> false
end
end.


permission_index(configure) -> #permission.configure;
permission_index(write) -> #permission.write;
permission_index(read) -> #permission.read.
Expand Down
14 changes: 14 additions & 0 deletions src/rabbit_authz_backend.erl
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,17 @@
rabbit_types:r(atom()),
rabbit_access_control:permission_atom()) ->
boolean() | {'error', any()}.

%% Given #auth_user, topic as resource, permission, and context, can a user access the topic?
%%
%% Possible responses:
%% true
%% false
%% {error, Error}
%% Something went wrong. Log and die.
-callback check_topic_access(rabbit_types:auth_user(),
rabbit_types:r(atom()),
rabbit_access_control:permission_atom(),
rabbit_types:context()) ->
boolean() | {'error', any()}.

11 changes: 6 additions & 5 deletions src/rabbit_channel.erl
Original file line number Diff line number Diff line change
Expand Up @@ -782,17 +782,18 @@ check_internal_exchange(_) ->
ok.

check_topic_authorisation(#exchange{name = Name, type = topic}, #ch{user = User}, RoutingKey) ->
Resource = Name#resource{kind = topic, options = #{routing_key => RoutingKey}},
Resource = Name#resource{kind = topic},
Context = #{routing_key => RoutingKey},
Cache = case get(topic_permission_cache) of
undefined -> [];
Other -> Other
end,
case lists:member(Resource, Cache) of
case lists:member({Resource, Context}, Cache) of
true -> ok;
false -> ok = rabbit_access_control:check_resource_access(
User, Resource, write),
false -> ok = rabbit_access_control:check_topic_access(
User, Resource, write, Context),
CacheTail = lists:sublist(Cache, ?MAX_PERMISSION_CACHE_SIZE-1),
put(topic_permission_cache, [Resource | CacheTail])
put(topic_permission_cache, [{Resource, Context} | CacheTail])
end;
check_topic_authorisation(_, _, _) ->
ok.
Expand Down
4 changes: 3 additions & 1 deletion src/rabbit_types.erl
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
ok/1, error/1, ok_or_error/1, ok_or_error2/2, ok_pid_or_error/0,
channel_exit/0, connection_exit/0, mfargs/0, proc_name/0,
proc_type_and_name/0, timestamp/0,
tracked_connection/0, node_type/0]).
tracked_connection/0, node_type/0, context/0]).

-type(maybe(T) :: T | 'none').
-type(timestamp() :: {non_neg_integer(), non_neg_integer(), non_neg_integer()}).
Expand Down Expand Up @@ -185,3 +185,5 @@

-type(proc_name() :: term()).
-type(proc_type_and_name() :: {atom(), proc_name()}).

-type(context() :: map()).

0 comments on commit 241c42b

Please sign in to comment.