summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMatthias Radestock <matthias@lshift.net>2009-01-16 16:24:34 +0000
committerMatthias Radestock <matthias@lshift.net>2009-01-16 16:24:34 +0000
commitea7885a47d3b8c2c343f12d1a81ea0a4c684122a (patch)
treef9174449faf81e9285c9d5eac99833111d4cccab /src
parented334fbf951ddd6337a7bf93ba5225bbad23adfd (diff)
downloadrabbitmq-server-git-ea7885a47d3b8c2c343f12d1a81ea0a4c684122a.tar.gz
beginnings of permission admin
I changed the table structure (again). It's a choice between two of efficiency, integrity and no data duplication - I picked the last two. We pass the permission regexps around as binaries and store them like that too, just as we do for all other string-y datums. I was toying with the idea of making set_permissions take a #permission record instead of two separate regexp params, so that it is easy to add more permissions later. But that is inconsistent with the rest of the rabbit_access_control API, which is "flat", and complicates the code in rabbit_control and the rabbit_tests.
Diffstat (limited to 'src')
-rw-r--r--src/rabbit.erl6
-rw-r--r--src/rabbit_access_control.erl78
-rw-r--r--src/rabbit_control.erl42
-rw-r--r--src/rabbit_mnesia.erl6
-rw-r--r--src/rabbit_tests.erl26
5 files changed, 96 insertions, 62 deletions
diff --git a/src/rabbit.erl b/src/rabbit.erl
index 30b8c39475..7ad13a7d28 100644
--- a/src/rabbit.erl
+++ b/src/rabbit.erl
@@ -264,9 +264,13 @@ insert_default_data() ->
{ok, DefaultUser} = application:get_env(default_user),
{ok, DefaultPass} = application:get_env(default_pass),
{ok, DefaultVHost} = application:get_env(default_vhost),
+ {ok, [DefaultConfigurationPerm, DefaultMessagingPerm]} =
+ application:get_env(default_permissions),
ok = rabbit_access_control:add_vhost(DefaultVHost),
ok = rabbit_access_control:add_user(DefaultUser, DefaultPass),
- ok = rabbit_access_control:map_user_vhost(DefaultUser, DefaultVHost),
+ ok = rabbit_access_control:set_permissions(DefaultUser, DefaultVHost,
+ DefaultConfigurationPerm,
+ DefaultMessagingPerm),
ok.
start_builtin_amq_applications() ->
diff --git a/src/rabbit_access_control.erl b/src/rabbit_access_control.erl
index e248575b60..177e6f20c0 100644
--- a/src/rabbit_access_control.erl
+++ b/src/rabbit_access_control.erl
@@ -38,7 +38,7 @@
-export([add_user/2, delete_user/1, change_password/2, list_users/0,
lookup_user/1]).
-export([add_vhost/1, delete_vhost/1, list_vhosts/0, list_vhost_users/1]).
--export([list_user_vhosts/1, map_user_vhost/2, unmap_user_vhost/2]).
+-export([list_user_vhosts/1, set_permissions/4, clear_permissions/2]).
%%----------------------------------------------------------------------------
@@ -57,8 +57,8 @@
-spec(list_vhosts/0 :: () -> [vhost()]).
-spec(list_vhost_users/1 :: (vhost()) -> [username()]).
-spec(list_user_vhosts/1 :: (username()) -> [vhost()]).
--spec(map_user_vhost/2 :: (username(), vhost()) -> 'ok').
--spec(unmap_user_vhost/2 :: (username(), vhost()) -> 'ok').
+-spec(set_permissions/4 :: (username(), vhost(), regexp(), regexp()) -> 'ok').
+-spec(clear_permissions/2 :: (username(), vhost()) -> 'ok').
-endif.
@@ -112,10 +112,9 @@ internal_lookup_vhost_access(Username, VHostPath) ->
%% TODO: use dirty ops instead
rabbit_misc:execute_mnesia_transaction(
fun () ->
- case mnesia:match_object(
- #user_permission{username = Username,
- virtual_host = VHostPath,
- _ = '_'}) of
+ case mnesia:read({user_permission,
+ #user_vhost{username = Username,
+ virtual_host = VHostPath}}) of
[] -> not_found;
[R] -> {ok, R}
end
@@ -152,7 +151,13 @@ delete_user(Username) ->
Username,
fun () ->
ok = mnesia:delete({user, Username}),
- ok = mnesia:delete({user_permission, Username})
+ [ok = mnesia:delete_object(R) ||
+ R <- mnesia:match_object(
+ #user_permission{user_vhost = #user_vhost{
+ username = Username,
+ virtual_host = '_'},
+ permission = '_'})],
+ ok
end)),
rabbit_log:info("Deleted user ~p~n", [Username]),
R.
@@ -222,7 +227,7 @@ internal_delete_vhost(VHostPath) ->
end,
rabbit_exchange:list(VHostPath)),
lists:foreach(fun (Username) ->
- ok = unmap_user_vhost(Username, VHostPath)
+ ok = clear_permissions(Username, VHostPath)
end,
list_vhost_users(VHostPath)),
ok = mnesia:delete({vhost, VHostPath}),
@@ -233,47 +238,62 @@ list_vhosts() ->
list_vhost_users(VHostPath) ->
[Username ||
- #user_permission{username = Username} <-
+ #user_permission{user_vhost = #user_vhost{username = Username}} <-
%% TODO: use dirty ops instead
rabbit_misc:execute_mnesia_transaction(
rabbit_misc:with_vhost(
VHostPath,
- fun () -> mnesia:index_read(user_permission, VHostPath,
- #user_permission.virtual_host)
+ fun () -> mnesia:match_object(
+ #user_permission{user_vhost = #user_vhost{
+ username = '_',
+ virtual_host = VHostPath},
+ permission = '_'})
end))].
list_user_vhosts(Username) ->
[VHostPath ||
- #user_permission{virtual_host = VHostPath} <-
+ #user_permission{user_vhost = #user_vhost{virtual_host = VHostPath}} <-
%% TODO: use dirty ops instead
rabbit_misc:execute_mnesia_transaction(
rabbit_misc:with_user(
Username,
- fun () -> mnesia:read({user_permission, Username}) end))].
+ fun () -> mnesia:match_object(
+ #user_permission{user_vhost = #user_vhost{
+ username = Username,
+ virtual_host = '_'},
+ permission = '_'})
+ end))].
+
+validate_regexp(RegexpBin) ->
+ Regexp = binary_to_list(RegexpBin),
+ case regexp:parse(Regexp) of
+ {ok, _} -> ok;
+ {error, Reason} -> throw({error, {invalid_regexp, Regexp, Reason}})
+ end.
-map_user_vhost(Username, VHostPath) ->
+set_permissions(Username, VHostPath, ConfigurationPerm, MessagingPerm) ->
+ validate_regexp(ConfigurationPerm),
+ validate_regexp(MessagingPerm),
rabbit_misc:execute_mnesia_transaction(
rabbit_misc:with_user_and_vhost(
Username, VHostPath,
- fun () ->
- ok = mnesia:write(
- #user_permission{username = Username,
- virtual_host = VHostPath,
- permission = #permission{
- configuration = ".*",
- messaging = ".*"}})
+ fun () -> ok = mnesia:write(
+ #user_permission{user_vhost = #user_vhost{
+ username = Username,
+ virtual_host = VHostPath},
+ permission = #permission{
+ configuration = ConfigurationPerm,
+ messaging = MessagingPerm}})
end)).
-unmap_user_vhost(Username, VHostPath) ->
+
+clear_permissions(Username, VHostPath) ->
rabbit_misc:execute_mnesia_transaction(
rabbit_misc:with_user_and_vhost(
Username, VHostPath,
fun () ->
- [ok = mnesia:delete_object(R) ||
- R <- mnesia:match_object(
- #user_permission{username = Username,
- virtual_host = VHostPath,
- _ = '_'})],
- ok
+ ok = mnesia:delete({user_permission,
+ #user_vhost{username = Username,
+ virtual_host = VHostPath}})
end)).
diff --git a/src/rabbit_control.erl b/src/rabbit_control.erl
index cbc11b4031..d897b3e9f8 100644
--- a/src/rabbit_control.erl
+++ b/src/rabbit_control.erl
@@ -114,8 +114,8 @@ Available commands:
delete_vhost <VHostPath>
list_vhosts
- map_user_vhost <UserName> <VHostPath>
- unmap_user_vhost <UserName> <VHostPath>
+ set_permissions [-p <VHostPath>] <UserName> <Permission> <Permission>
+ clear_permissions [-p <VHostPath>] <UserName>
list_user_vhosts <UserName>
list_vhost_users <VHostPath>
@@ -223,13 +223,17 @@ action(list_vhosts, Node, [], Inform) ->
Inform("Listing vhosts", []),
display_list(call(Node, {rabbit_access_control, list_vhosts, []}));
-action(map_user_vhost, Node, Args = [_Username, _VHostPath], Inform) ->
- Inform("Mapping user ~p to vhost ~p", Args),
- call(Node, {rabbit_access_control, map_user_vhost, Args});
+action(set_permissions, Node, Args, Inform) ->
+ {VHost, [Username, ConfigurationPerm, MessagingPerm]} =
+ parse_vhost_flag(Args),
+ Inform("Setting permissions for user ~p in vhost ~p", [Username, VHost]),
+ call(Node, {rabbit_access_control, set_permissions,
+ [Username, VHost, ConfigurationPerm, MessagingPerm]});
-action(unmap_user_vhost, Node, Args = [_Username, _VHostPath], Inform) ->
- Inform("Unmapping user ~p from vhost ~p", Args),
- call(Node, {rabbit_access_control, unmap_user_vhost, Args});
+action(clear_permissions, Node, Args, Inform) ->
+ {VHost, [Username]} = parse_vhost_flag(Args),
+ Inform("Clearing permissions for user ~p in vhost ~p", [Username, VHost]),
+ call(Node, {rabbit_access_control, clear_permissions, [Username, VHost]});
action(list_user_vhosts, Node, Args = [_Username], Inform) ->
Inform("Listing vhosts for user ~p", Args),
@@ -241,7 +245,7 @@ action(list_vhost_users, Node, Args = [_VHostPath], Inform) ->
action(list_queues, Node, Args, Inform) ->
Inform("Listing queues", []),
- {VHostArg, RemainingArgs} = parse_vhost_flag(Args),
+ {VHostArg, RemainingArgs} = parse_vhost_flag_bin(Args),
ArgAtoms = list_replace(node, pid,
default_if_empty(RemainingArgs, [name, messages])),
display_info_list(rpc_call(Node, rabbit_amqqueue, info_all,
@@ -250,7 +254,7 @@ action(list_queues, Node, Args, Inform) ->
action(list_exchanges, Node, Args, Inform) ->
Inform("Listing exchanges", []),
- {VHostArg, RemainingArgs} = parse_vhost_flag(Args),
+ {VHostArg, RemainingArgs} = parse_vhost_flag_bin(Args),
ArgAtoms = default_if_empty(RemainingArgs, [name, type]),
display_info_list(rpc_call(Node, rabbit_exchange, info_all,
[VHostArg, ArgAtoms]),
@@ -258,7 +262,7 @@ action(list_exchanges, Node, Args, Inform) ->
action(list_bindings, Node, Args, Inform) ->
Inform("Listing bindings", []),
- {VHostArg, _} = parse_vhost_flag(Args),
+ {VHostArg, _} = parse_vhost_flag_bin(Args),
InfoKeys = [exchange_name, routing_key, queue_name, args],
display_info_list(
[lists:zip(InfoKeys, tuple_to_list(X)) ||
@@ -275,12 +279,16 @@ action(list_connections, Node, Args, Inform) ->
ArgAtoms).
parse_vhost_flag(Args) when is_list(Args) ->
- case Args of
- ["-p", VHost | RemainingArgs] ->
- {list_to_binary(VHost), RemainingArgs};
- RemainingArgs ->
- {<<"/">>, RemainingArgs}
- end.
+ case Args of
+ ["-p", VHost | RemainingArgs] ->
+ {VHost, RemainingArgs};
+ RemainingArgs ->
+ {"/", RemainingArgs}
+ end.
+
+parse_vhost_flag_bin(Args) ->
+ {VHost, RemainingArgs} = parse_vhost_flag(Args),
+ {list_to_binary(VHost), RemainingArgs}.
default_if_empty(List, Default) when is_list(List) ->
if List == [] ->
diff --git a/src/rabbit_mnesia.erl b/src/rabbit_mnesia.erl
index 31c0efbed7..b7f3dd0a89 100644
--- a/src/rabbit_mnesia.erl
+++ b/src/rabbit_mnesia.erl
@@ -102,10 +102,8 @@ force_reset() -> reset(true).
table_definitions() ->
[{user, [{disc_copies, [node()]},
{attributes, record_info(fields, user)}]},
- {user_permission, [{type, bag},
- {disc_copies, [node()]},
- {attributes, record_info(fields, user_permission)},
- {index, [virtual_host]}]},
+ {user_permission, [{disc_copies, [node()]},
+ {attributes, record_info(fields, user_permission)}]},
{vhost, [{disc_copies, [node()]},
{attributes, record_info(fields, vhost)}]},
{rabbit_config, [{disc_copies, [node()]}]},
diff --git a/src/rabbit_tests.erl b/src/rabbit_tests.erl
index df2e71d9e6..26398f9b46 100644
--- a/src/rabbit_tests.erl
+++ b/src/rabbit_tests.erl
@@ -444,17 +444,18 @@ test_user_management() ->
{error, {no_such_vhost, _}} =
control_action(delete_vhost, ["/testhost"]),
{error, {no_such_user, _}} =
- control_action(map_user_vhost, ["foo", "/"]),
+ control_action(set_permissions, ["foo", ".*", ".*"]),
{error, {no_such_user, _}} =
- control_action(unmap_user_vhost, ["foo", "/"]),
+ control_action(clear_permissions, ["foo"]),
{error, {no_such_user, _}} =
control_action(list_user_vhosts, ["foo"]),
{error, {no_such_vhost, _}} =
- control_action(map_user_vhost, ["guest", "/testhost"]),
- {error, {no_such_vhost, _}} =
- control_action(unmap_user_vhost, ["guest", "/testhost"]),
- {error, {no_such_vhost, _}} =
control_action(list_vhost_users, ["/testhost"]),
+ {error, {invalid_regexp, _, _}} =
+ control_action(set_permissions, ["guest", "+foo", ".*"]),
+ {error, {invalid_regexp, _, _}} =
+ control_action(set_permissions, ["guest", ".*", "+foo"]),
+
%% user creation
ok = control_action(add_user, ["foo", "bar"]),
{error, {user_already_exists, _}} =
@@ -469,13 +470,15 @@ test_user_management() ->
ok = control_action(list_vhosts, []),
%% user/vhost mapping
- ok = control_action(map_user_vhost, ["foo", "/testhost"]),
- ok = control_action(map_user_vhost, ["foo", "/testhost"]),
+ ok = control_action(set_permissions, ["-p", "/testhost",
+ "foo", ".*", ".*"]),
+ ok = control_action(set_permissions, ["-p", "/testhost",
+ "foo", ".*", ".*"]),
ok = control_action(list_user_vhosts, ["foo"]),
%% user/vhost unmapping
- ok = control_action(unmap_user_vhost, ["foo", "/testhost"]),
- ok = control_action(unmap_user_vhost, ["foo", "/testhost"]),
+ ok = control_action(clear_permissions, ["-p", "/testhost", "foo"]),
+ ok = control_action(clear_permissions, ["-p", "/testhost", "foo"]),
%% vhost deletion
ok = control_action(delete_vhost, ["/testhost"]),
@@ -484,7 +487,8 @@ test_user_management() ->
%% deleting a populated vhost
ok = control_action(add_vhost, ["/testhost"]),
- ok = control_action(map_user_vhost, ["foo", "/testhost"]),
+ ok = control_action(set_permissions, ["-p", "/testhost",
+ "foo", ".*", ".*"]),
ok = control_action(delete_vhost, ["/testhost"]),
%% user deletion