summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon MacMullen <simon@rabbitmq.com>2010-12-14 15:03:44 +0000
committerSimon MacMullen <simon@rabbitmq.com>2010-12-14 15:03:44 +0000
commit2f43ffd37fc7fd8ecfdc2e421c6834740e080748 (patch)
tree21c7bf2e7832d280cc756b44150df3802999b156
parent2376a52d1655385a9ae6f9656bcff4ca70d20ba2 (diff)
parent8d0f82119fb6b45f9dd0d0acebee4440e8bdf340 (diff)
downloadrabbitmq-server-2f43ffd37fc7fd8ecfdc2e421c6834740e080748.tar.gz
Merge from default
-rw-r--r--ebin/rabbit_app.in3
-rw-r--r--include/rabbit.hrl8
-rw-r--r--include/rabbit_auth_backend_spec.hrl48
-rw-r--r--src/rabbit_access_control.erl169
-rw-r--r--src/rabbit_auth_backend.erl48
-rw-r--r--src/rabbit_auth_backend_internal.erl112
-rw-r--r--src/rabbit_auth_mechanism_external.erl2
-rw-r--r--src/rabbit_channel.erl30
-rw-r--r--src/rabbit_channel_sup.erl4
-rw-r--r--src/rabbit_mnesia.erl6
-rw-r--r--src/rabbit_reader.erl4
-rw-r--r--src/rabbit_registry.erl3
-rw-r--r--src/rabbit_types.erl16
-rw-r--r--src/rabbit_upgrade_functions.erl15
14 files changed, 357 insertions, 111 deletions
diff --git a/ebin/rabbit_app.in b/ebin/rabbit_app.in
index 3888f198..6fb7bbc5 100644
--- a/ebin/rabbit_app.in
+++ b/ebin/rabbit_app.in
@@ -31,4 +31,5 @@
{cluster_nodes, []},
{server_properties, []},
{collect_statistics, none},
- {auth_mechanisms, ['PLAIN', 'AMQPLAIN']} ]} ]}.
+ {auth_mechanisms, ['PLAIN', 'AMQPLAIN']},
+ {auth_backends, [rabbit_auth_backend_internal]} ]} ]}.
diff --git a/include/rabbit.hrl b/include/rabbit.hrl
index fccfad97..e5fceaed 100644
--- a/include/rabbit.hrl
+++ b/include/rabbit.hrl
@@ -29,7 +29,13 @@
%% Contributor(s): ______________________________________.
%%
--record(user, {username, password_hash, is_admin}).
+-record(user, {username,
+ is_admin,
+ auth_backend, %% Module this user came from
+ impl %% Scratch space for that module
+ }).
+
+-record(internal_user, {username, password_hash, is_admin}).
-record(permission, {configure, write, read}).
-record(user_vhost, {username, virtual_host}).
-record(user_permission, {user_vhost, permission}).
diff --git a/include/rabbit_auth_backend_spec.hrl b/include/rabbit_auth_backend_spec.hrl
new file mode 100644
index 00000000..aa9b7b98
--- /dev/null
+++ b/include/rabbit_auth_backend_spec.hrl
@@ -0,0 +1,48 @@
+%% The contents of this file are subject to the Mozilla Public License
+%% Version 1.1 (the "License"); you may not use this file except in
+%% compliance with the License. You may obtain a copy of the License at
+%% http://www.mozilla.org/MPL/
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+%% License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% The Original Code is RabbitMQ.
+%%
+%% The Initial Developers of the Original Code are LShift Ltd,
+%% Cohesive Financial Technologies LLC, and Rabbit Technologies Ltd.
+%%
+%% Portions created before 22-Nov-2008 00:00:00 GMT by LShift Ltd,
+%% Cohesive Financial Technologies LLC, or Rabbit Technologies Ltd
+%% are Copyright (C) 2007-2008 LShift Ltd, Cohesive Financial
+%% Technologies LLC, and Rabbit Technologies Ltd.
+%%
+%% Portions created by LShift Ltd are Copyright (C) 2007-2010 LShift
+%% Ltd. Portions created by Cohesive Financial Technologies LLC are
+%% Copyright (C) 2007-2010 Cohesive Financial Technologies
+%% LLC. Portions created by Rabbit Technologies Ltd are Copyright
+%% (C) 2007-2010 Rabbit Technologies Ltd.
+%%
+%% All Rights Reserved.
+%%
+%% Contributor(s): ______________________________________.
+%%
+-ifdef(use_specs).
+
+-type(vhost_permission_atom() :: 'read' | 'write').
+
+-spec(description/0 :: () -> [{atom(), any()}]).
+
+-spec(check_user_login/2 :: (rabbit_access_control:username(), [term()]) ->
+ {'ok', rabbit_types:user()} |
+ {'refused', rabbit_access_control:username()} |
+ {'error', any()}).
+-spec(check_vhost_access/3 :: (rabbit_types:user(), rabbit_types:vhost(),
+ vhost_permission_atom()) ->
+ boolean() | {'error', any()}).
+-spec(check_resource_access/3 :: (rabbit_types:user(),
+ rabbit_types:r(atom()),
+ rabbit_access_control:permission_atom()) ->
+ boolean() | {'error', any()}).
+-endif.
diff --git a/src/rabbit_access_control.erl b/src/rabbit_access_control.erl
index 2bc946db..8c550e35 100644
--- a/src/rabbit_access_control.erl
+++ b/src/rabbit_access_control.erl
@@ -33,8 +33,9 @@
-include_lib("stdlib/include/qlc.hrl").
-include("rabbit.hrl").
--export([user_pass_login/2, check_user_pass_login/2, make_salt/0,
- check_vhost_access/2, check_resource_access/3]).
+-export([user_pass_login/2, check_user_pass_login/2, check_user_login/2,
+ make_salt/0, check_password/2, check_vhost_access/2,
+ check_resource_access/3, list_vhosts/1]).
-export([add_user/2, delete_user/1, change_password/2, set_admin/1,
clear_admin/1, list_users/0, lookup_user/1, clear_password/1]).
-export([change_password_hash/2, hash_password/1]).
@@ -47,7 +48,7 @@
-ifdef(use_specs).
--export_type([username/0, password/0, password_hash/0]).
+-export_type([username/0, password/0, password_hash/0, permission_atom/0]).
-type(permission_atom() :: 'configure' | 'read' | 'write').
-type(username() :: binary()).
@@ -61,11 +62,12 @@
(username(), password())
-> {'ok', rabbit_types:user()} | {'refused', string(), [any()]}).
-spec(make_salt/0 :: () -> binary()).
+-spec(check_password/2 :: (password(), password_hash()) -> boolean()).
-spec(check_vhost_access/2 ::
(rabbit_types:user(), rabbit_types:vhost())
-> 'ok' | rabbit_types:channel_exit()).
-spec(check_resource_access/3 ::
- (username(), rabbit_types:r(atom()), permission_atom())
+ (rabbit_types:user(), rabbit_types:r(atom()), permission_atom())
-> 'ok' | rabbit_types:channel_exit()).
-spec(add_user/2 :: (username(), password()) -> 'ok').
-spec(delete_user/1 :: (username()) -> 'ok').
@@ -77,7 +79,7 @@
-spec(clear_admin/1 :: (username()) -> 'ok').
-spec(list_users/0 :: () -> [{username(), boolean()}]).
-spec(lookup_user/1 ::
- (username()) -> rabbit_types:ok(rabbit_types:user())
+ (username()) -> rabbit_types:ok(rabbit_types:internal_user())
| rabbit_types:error('not_found')).
-spec(add_vhost/1 :: (rabbit_types:vhost()) -> 'ok').
-spec(delete_vhost/1 :: (rabbit_types:vhost()) -> 'ok').
@@ -109,88 +111,94 @@ user_pass_login(User, Pass) ->
U
end.
-check_user_pass_login(Username, Pass) ->
- Refused = {refused, "user '~s' - invalid credentials", [Username]},
- case lookup_user(Username) of
- {ok, User} ->
- case check_password(Pass, User#user.password_hash) of
- true -> {ok, User};
- _ -> Refused
- end;
- {error, not_found} ->
- Refused
- end.
-
-internal_lookup_vhost_access(Username, VHostPath) ->
- %% TODO: use dirty ops instead
- rabbit_misc:execute_mnesia_transaction(
- fun () ->
- case mnesia:read({rabbit_user_permission,
- #user_vhost{username = Username,
- virtual_host = VHostPath}}) of
- [] -> not_found;
- [R] -> {ok, R}
- end
- end).
-
-check_vhost_access(#user{username = Username}, VHostPath) ->
+check_user_pass_login(Username, Password) ->
+ check_user_login(Username, [{password, Password}]).
+
+check_user_login(Username, AuthProps) ->
+ {ok, Modules} = application:get_env(rabbit, auth_backends),
+ lists:foldl(
+ fun(Module, {refused, _, _}) ->
+ case Module:check_user_login(Username, AuthProps) of
+ {error, E} ->
+ {refused, "~s failed authenticating ~s: ~p~n",
+ [Module, Username, E]};
+ Else ->
+ Else
+ end;
+ (_, {ok, User}) ->
+ {ok, User}
+ end, {refused, "No modules checked '~s'", [Username]}, Modules).
+
+check_vhost_access(User = #user{ username = Username,
+ auth_backend = Module }, VHostPath) ->
?LOGDEBUG("Checking VHost access for ~p to ~p~n", [Username, VHostPath]),
- case internal_lookup_vhost_access(Username, VHostPath) of
- {ok, _R} ->
+ check_access(
+ fun() ->
+ vhost_exists(VHostPath) andalso
+ Module:check_vhost_access(User, VHostPath, write)
+ end,
+ "~s failed checking vhost access to ~s for ~s: ~p~n",
+ [Module, VHostPath, Username],
+ "access to vhost '~s' refused for user '~s'",
+ [VHostPath, Username]).
+
+check_resource_access(User, R = #resource{kind = exchange, name = <<"">>},
+ Permission) ->
+ check_resource_access(User, R#resource{name = <<"amq.default">>},
+ Permission);
+check_resource_access(User = #user{username = Username, auth_backend = Module},
+ Resource, Permission) ->
+ check_access(
+ fun() -> Module:check_resource_access(User, Resource, Permission) end,
+ "~s failed checking resource access to ~p for ~s: ~p~n",
+ [Module, Resource, Username],
+ "access to ~s refused for user '~s'",
+ [rabbit_misc:rs(Resource), Username]).
+
+check_access(Fun, ErrStr, ErrArgs, RefStr, RefArgs) ->
+ Allow = case Fun() of
+ {error, _} = E ->
+ rabbit_log:error(ErrStr, ErrArgs ++ [E]),
+ false;
+ Else ->
+ Else
+ end,
+ case Allow of
+ true ->
ok;
- not_found ->
- rabbit_misc:protocol_error(
- access_refused, "access to vhost '~s' refused for user '~s'",
- [VHostPath, Username])
+ false ->
+ rabbit_misc:protocol_error(access_refused, RefStr, RefArgs)
end.
-permission_index(configure) -> #permission.configure;
-permission_index(write) -> #permission.write;
-permission_index(read) -> #permission.read.
+list_vhosts(User = #user{username = Username, auth_backend = Module}) ->
+ lists:filter(
+ fun(VHost) ->
+ case Module:check_vhost_access(User, VHost, read) of
+ {error, _} = E ->
+ rabbit_log:warning("~w failed checking vhost access "
+ "to ~s for ~s: ~p~n",
+ [Module, VHost, Username, E]),
+ false;
+ Else ->
+ Else
+ end
+ end, list_vhosts()).
-check_resource_access(Username,
- R = #resource{kind = exchange, name = <<"">>},
- Permission) ->
- check_resource_access(Username,
- R#resource{name = <<"amq.default">>},
- Permission);
-check_resource_access(Username,
- R = #resource{virtual_host = VHostPath, name = Name},
- Permission) ->
- Res = case mnesia:dirty_read({rabbit_user_permission,
- #user_vhost{username = Username,
- virtual_host = VHostPath}}) of
- [] ->
- false;
- [#user_permission{permission = P}] ->
- PermRegexp =
- case element(permission_index(Permission), P) of
- %% <<"^$">> breaks Emacs' erlang mode
- <<"">> -> <<$^, $$>>;
- RE -> RE
- end,
- case re:run(Name, PermRegexp, [{capture, none}]) of
- match -> true;
- nomatch -> false
- end
- end,
- if Res -> ok;
- true -> rabbit_misc:protocol_error(
- access_refused, "access to ~s refused for user '~s'",
- [rabbit_misc:rs(R), Username])
- end.
+%% TODO move almost everything below this line to rabbit_auth_backend_internal
+%%----------------------------------------------------------------------------
add_user(Username, Password) ->
R = rabbit_misc:execute_mnesia_transaction(
fun () ->
case mnesia:wread({rabbit_user, Username}) of
[] ->
- ok = mnesia:write(rabbit_user,
- #user{username = Username,
- password_hash =
- hash_password(Password),
- is_admin = false},
- write);
+ ok = mnesia:write(
+ rabbit_user,
+ #internal_user{username = Username,
+ password_hash =
+ hash_password(Password),
+ is_admin = false},
+ write);
_ ->
mnesia:abort({user_already_exists, Username})
end
@@ -226,7 +234,8 @@ clear_password(Username) ->
change_password_hash(Username, PasswordHash) ->
R = update_user(Username, fun(User) ->
- User#user{ password_hash = PasswordHash }
+ User#internal_user{
+ password_hash = PasswordHash }
end),
rabbit_log:info("Changed password for user ~p~n", [Username]),
R.
@@ -257,7 +266,7 @@ clear_admin(Username) ->
set_admin(Username, IsAdmin) ->
R = update_user(Username, fun(User) ->
- User#user{is_admin = IsAdmin}
+ User#internal_user{is_admin = IsAdmin}
end),
rabbit_log:info("Set user admin flag for user ~p to ~p~n",
[Username, IsAdmin]),
@@ -274,8 +283,8 @@ update_user(Username, Fun) ->
list_users() ->
[{Username, IsAdmin} ||
- #user{username = Username, is_admin = IsAdmin} <-
- mnesia:dirty_match_object(rabbit_user, #user{_ = '_'})].
+ #internal_user{username = Username, is_admin = IsAdmin} <-
+ mnesia:dirty_match_object(rabbit_user, #internal_user{_ = '_'})].
lookup_user(Username) ->
rabbit_misc:dirty_read({rabbit_user, Username}).
diff --git a/src/rabbit_auth_backend.erl b/src/rabbit_auth_backend.erl
new file mode 100644
index 00000000..18f32873
--- /dev/null
+++ b/src/rabbit_auth_backend.erl
@@ -0,0 +1,48 @@
+%% The contents of this file are subject to the Mozilla Public License
+%% Version 1.1 (the "License"); you may not use this file except in
+%% compliance with the License. You may obtain a copy of the License at
+%% http://www.mozilla.org/MPL/
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+%% License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% The Original Code is RabbitMQ.
+%%
+%% The Initial Developers of the Original Code are LShift Ltd,
+%% Cohesive Financial Technologies LLC, and Rabbit Technologies Ltd.
+%%
+%% Portions created before 22-Nov-2008 00:00:00 GMT by LShift Ltd,
+%% Cohesive Financial Technologies LLC, or Rabbit Technologies Ltd
+%% are Copyright (C) 2007-2008 LShift Ltd, Cohesive Financial
+%% Technologies LLC, and Rabbit Technologies Ltd.
+%%
+%% Portions created by LShift Ltd are Copyright (C) 2007-2010 LShift
+%% Ltd. Portions created by Cohesive Financial Technologies LLC are
+%% Copyright (C) 2007-2010 Cohesive Financial Technologies
+%% LLC. Portions created by Rabbit Technologies Ltd are Copyright
+%% (C) 2007-2010 Rabbit Technologies Ltd.
+%%
+%% All Rights Reserved.
+%%
+%% Contributor(s): ______________________________________.
+%%
+
+-module(rabbit_auth_backend).
+
+-export([behaviour_info/1]).
+
+behaviour_info(callbacks) ->
+ [
+ %% A description (TODO should this be here if we're not using registry?).
+ {description, 0},
+
+ {check_user_login, 2},
+
+ {check_vhost_access, 3},
+
+ {check_resource_access, 3}
+ ];
+behaviour_info(_Other) ->
+ undefined.
diff --git a/src/rabbit_auth_backend_internal.erl b/src/rabbit_auth_backend_internal.erl
new file mode 100644
index 00000000..df5a0ace
--- /dev/null
+++ b/src/rabbit_auth_backend_internal.erl
@@ -0,0 +1,112 @@
+%% The contents of this file are subject to the Mozilla Public License
+%% Version 1.1 (the "License"); you may not use this file except in
+%% compliance with the License. You may obtain a copy of the License at
+%% http://www.mozilla.org/MPL/
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+%% License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% The Original Code is RabbitMQ.
+%%
+%% The Initial Developers of the Original Code are LShift Ltd,
+%% Cohesive Financial Technologies LLC, and Rabbit Technologies Ltd.
+%%
+%% Portions created before 22-Nov-2008 00:00:00 GMT by LShift Ltd,
+%% Cohesive Financial Technologies LLC, or Rabbit Technologies Ltd
+%% are Copyright (C) 2007-2008 LShift Ltd, Cohesive Financial
+%% Technologies LLC, and Rabbit Technologies Ltd.
+%%
+%% Portions created by LShift Ltd are Copyright (C) 2007-2010 LShift
+%% Ltd. Portions created by Cohesive Financial Technologies LLC are
+%% Copyright (C) 2007-2010 Cohesive Financial Technologies
+%% LLC. Portions created by Rabbit Technologies Ltd are Copyright
+%% (C) 2007-2010 Rabbit Technologies Ltd.
+%%
+%% All Rights Reserved.
+%%
+%% Contributor(s): ______________________________________.
+%%
+
+-module(rabbit_auth_backend_internal).
+-include("rabbit.hrl").
+
+-behaviour(rabbit_auth_backend).
+
+-export([description/0]).
+-export([check_user_login/2, check_vhost_access/3, check_resource_access/3]).
+
+-include("rabbit_auth_backend_spec.hrl").
+
+%% Our internal user database
+
+description() ->
+ [{name, <<"Internal">>},
+ {description, <<"Internal user / password database">>}].
+
+check_user_login(Username, []) ->
+ internal_check_user_login(Username, fun() -> true end);
+check_user_login(Username, [{password, Password}]) ->
+ internal_check_user_login(
+ Username,
+ fun(#internal_user{password_hash = Hash}) ->
+ rabbit_access_control:check_password(Password, Hash)
+ end);
+check_user_login(Username, AuthProps) ->
+ exit({unknown_auth_props, Username, AuthProps}).
+
+internal_check_user_login(Username, Fun) ->
+ Refused = {refused, "user '~s' - invalid credentials", [Username]},
+ case rabbit_access_control:lookup_user(Username) of
+ {ok, User = #internal_user{is_admin = IsAdmin}} ->
+ case Fun(User) of
+ true -> {ok, #user{username = Username,
+ is_admin = IsAdmin,
+ auth_backend = ?MODULE,
+ impl = User}};
+ _ -> Refused
+ end;
+ {error, not_found} ->
+ Refused
+ end.
+
+check_vhost_access(#user{is_admin = true}, _VHostPath, read) ->
+ true;
+
+check_vhost_access(#user{username = Username}, VHostPath, write) ->
+ %% TODO: use dirty ops instead
+ rabbit_misc:execute_mnesia_transaction(
+ fun () ->
+ case mnesia:read({rabbit_user_permission,
+ #user_vhost{username = Username,
+ virtual_host = VHostPath}}) of
+ [] -> false;
+ [_R] -> true
+ end
+ end).
+
+check_resource_access(#user{username = Username},
+ #resource{virtual_host = VHostPath, name = Name},
+ Permission) ->
+ case mnesia:dirty_read({rabbit_user_permission,
+ #user_vhost{username = Username,
+ virtual_host = VHostPath}}) of
+ [] ->
+ false;
+ [#user_permission{permission = P}] ->
+ PermRegexp =
+ case element(permission_index(Permission), P) of
+ %% <<"^$">> breaks Emacs' erlang mode
+ <<"">> -> <<$^, $$>>;
+ RE -> RE
+ end,
+ case re:run(Name, 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.
diff --git a/src/rabbit_auth_mechanism_external.erl b/src/rabbit_auth_mechanism_external.erl
index 6572f786..1c4e5c15 100644
--- a/src/rabbit_auth_mechanism_external.erl
+++ b/src/rabbit_auth_mechanism_external.erl
@@ -81,7 +81,7 @@ handle_response(_Response, #state{username = Username}) ->
{refused, _, _} = E ->
E;
_ ->
- case rabbit_access_control:lookup_user(Username) of
+ case rabbit_access_control:check_user_login(Username, []) of
{ok, User} ->
{ok, User};
{error, not_found} ->
diff --git a/src/rabbit_channel.erl b/src/rabbit_channel.erl
index 4e9bd4b1..d50599c1 100644
--- a/src/rabbit_channel.erl
+++ b/src/rabbit_channel.erl
@@ -47,7 +47,7 @@
-record(ch, {state, channel, reader_pid, writer_pid, limiter_pid,
start_limiter_fun, transaction_id, tx_participants, next_tag,
uncommitted_ack_q, unacked_message_q,
- username, virtual_host, most_recently_declared_queue,
+ user, virtual_host, most_recently_declared_queue,
consumer_mapping, blocking, queue_collector_pid, stats_timer,
confirm_enabled, publish_seqno, confirm_multiple, confirm_tref,
held_confirms, unconfirmed, queues_for_msg}).
@@ -83,7 +83,7 @@
-type(channel_number() :: non_neg_integer()).
-spec(start_link/7 ::
- (channel_number(), pid(), pid(), rabbit_access_control:username(),
+ (channel_number(), pid(), pid(), rabbit_types:user(),
rabbit_types:vhost(), pid(),
fun ((non_neg_integer()) -> rabbit_types:ok(pid()))) ->
rabbit_types:ok_pid_or_error()).
@@ -111,9 +111,9 @@
%%----------------------------------------------------------------------------
-start_link(Channel, ReaderPid, WriterPid, Username, VHost, CollectorPid,
+start_link(Channel, ReaderPid, WriterPid, User, VHost, CollectorPid,
StartLimiterFun) ->
- gen_server2:start_link(?MODULE, [Channel, ReaderPid, WriterPid, Username,
+ gen_server2:start_link(?MODULE, [Channel, ReaderPid, WriterPid, User,
VHost, CollectorPid, StartLimiterFun], []).
do(Pid, Method) ->
@@ -168,7 +168,7 @@ emit_stats(Pid) ->
%%---------------------------------------------------------------------------
-init([Channel, ReaderPid, WriterPid, Username, VHost, CollectorPid,
+init([Channel, ReaderPid, WriterPid, User, VHost, CollectorPid,
StartLimiterFun]) ->
process_flag(trap_exit, true),
ok = pg_local:join(rabbit_channels, self()),
@@ -184,7 +184,7 @@ init([Channel, ReaderPid, WriterPid, Username, VHost, CollectorPid,
next_tag = 1,
uncommitted_ack_q = queue:new(),
unacked_message_q = queue:new(),
- username = Username,
+ user = User,
virtual_host = VHost,
most_recently_declared_queue = <<>>,
consumer_mapping = dict:new(),
@@ -371,7 +371,7 @@ return_queue_declare_ok(#resource{name = ActualName},
message_count = MessageCount,
consumer_count = ConsumerCount}).
-check_resource_access(Username, Resource, Perm) ->
+check_resource_access(User, Resource, Perm) ->
V = {Resource, Perm},
Cache = case get(permission_cache) of
undefined -> [];
@@ -381,7 +381,7 @@ check_resource_access(Username, Resource, Perm) ->
case lists:member(V, Cache) of
true -> lists:delete(V, Cache);
false -> ok = rabbit_access_control:check_resource_access(
- Username, Resource, Perm),
+ User, Resource, Perm),
lists:sublist(Cache, ?MAX_PERMISSION_CACHE_SIZE - 1)
end,
put(permission_cache, [V | CacheTail]),
@@ -391,14 +391,14 @@ clear_permission_cache() ->
erase(permission_cache),
ok.
-check_configure_permitted(Resource, #ch{username = Username}) ->
- check_resource_access(Username, Resource, configure).
+check_configure_permitted(Resource, #ch{user = User}) ->
+ check_resource_access(User, Resource, configure).
-check_write_permitted(Resource, #ch{username = Username}) ->
- check_resource_access(Username, Resource, write).
+check_write_permitted(Resource, #ch{user = User}) ->
+ check_resource_access(User, Resource, write).
-check_read_permitted(Resource, #ch{username = Username}) ->
- check_resource_access(Username, Resource, read).
+check_read_permitted(Resource, #ch{user = User}) ->
+ check_resource_access(User, Resource, read).
expand_queue_name_shortcut(<<>>, #ch{most_recently_declared_queue = <<>>}) ->
rabbit_misc:protocol_error(
@@ -1300,7 +1300,7 @@ infos(Items, State) -> [{Item, i(Item, State)} || Item <- Items].
i(pid, _) -> self();
i(connection, #ch{reader_pid = ReaderPid}) -> ReaderPid;
i(number, #ch{channel = Channel}) -> Channel;
-i(user, #ch{username = Username}) -> Username;
+i(user, #ch{user = User}) -> User#user.username;
i(vhost, #ch{virtual_host = VHost}) -> VHost;
i(transactional, #ch{transaction_id = TxnKey}) -> TxnKey =/= none;
i(consumer_count, #ch{consumer_mapping = ConsumerMapping}) ->
diff --git a/src/rabbit_channel_sup.erl b/src/rabbit_channel_sup.erl
index 02199a65..e11f8a3e 100644
--- a/src/rabbit_channel_sup.erl
+++ b/src/rabbit_channel_sup.erl
@@ -56,7 +56,7 @@
%%----------------------------------------------------------------------------
-start_link({Protocol, Sock, Channel, FrameMax, ReaderPid, Username, VHost,
+start_link({Protocol, Sock, Channel, FrameMax, ReaderPid, User, VHost,
Collector}) ->
{ok, SupPid} = supervisor2:start_link(?MODULE, []),
{ok, WriterPid} =
@@ -69,7 +69,7 @@ start_link({Protocol, Sock, Channel, FrameMax, ReaderPid, Username, VHost,
supervisor2:start_child(
SupPid,
{channel, {rabbit_channel, start_link,
- [Channel, ReaderPid, WriterPid, Username, VHost,
+ [Channel, ReaderPid, WriterPid, User, VHost,
Collector, start_limiter_fun(SupPid)]},
intrinsic, ?MAX_WAIT, worker, [rabbit_channel]}),
{ok, FramingChannelPid} =
diff --git a/src/rabbit_mnesia.erl b/src/rabbit_mnesia.erl
index dadfc16e..1f2d4d7d 100644
--- a/src/rabbit_mnesia.erl
+++ b/src/rabbit_mnesia.erl
@@ -154,10 +154,10 @@ nodes_of_type(Type) ->
table_definitions() ->
[{rabbit_user,
- [{record_name, user},
- {attributes, record_info(fields, user)},
+ [{record_name, internal_user},
+ {attributes, record_info(fields, internal_user)},
{disc_copies, [node()]},
- {match, #user{_='_'}}]},
+ {match, #internal_user{_='_'}}]},
{rabbit_user_permission,
[{record_name, user_permission},
{attributes, record_info(fields, user_permission)},
diff --git a/src/rabbit_reader.erl b/src/rabbit_reader.erl
index 41b14771..c542ea66 100644
--- a/src/rabbit_reader.erl
+++ b/src/rabbit_reader.erl
@@ -969,12 +969,12 @@ send_to_new_channel(Channel, AnalyzedFrame, State) ->
channel_sup_sup_pid = ChanSupSup,
connection = #connection{protocol = Protocol,
frame_max = FrameMax,
- user = #user{username = Username},
+ user = User,
vhost = VHost}} = State,
{ok, ChSupPid, ChFrPid} =
rabbit_channel_sup_sup:start_channel(
ChanSupSup, {Protocol, Sock, Channel, FrameMax,
- self(), Username, VHost, Collector}),
+ self(), User, VHost, Collector}),
erlang:monitor(process, ChSupPid),
put({channel, Channel}, {ch_fr_pid, ChFrPid}),
put({ch_sup_pid, ChSupPid}, {{channel, Channel}, {ch_fr_pid, ChFrPid}}),
diff --git a/src/rabbit_registry.erl b/src/rabbit_registry.erl
index 7a3fcb51..ca300e72 100644
--- a/src/rabbit_registry.erl
+++ b/src/rabbit_registry.erl
@@ -111,7 +111,8 @@ sanity_check_module(ClassModule, Module) ->
end.
class_module(exchange) -> rabbit_exchange_type;
-class_module(auth_mechanism) -> rabbit_auth_mechanism.
+class_module(auth_mechanism) -> rabbit_auth_mechanism;
+class_module(auth_backend) -> rabbit_auth_backend.
%%---------------------------------------------------------------------------
diff --git a/src/rabbit_types.erl b/src/rabbit_types.erl
index 548014be..15e71ee4 100644
--- a/src/rabbit_types.erl
+++ b/src/rabbit_types.erl
@@ -42,8 +42,8 @@
vhost/0, ctag/0, amqp_error/0, r/1, r2/2, r3/3, listener/0,
binding/0, binding_source/0, binding_destination/0,
amqqueue/0, exchange/0,
- connection/0, protocol/0, user/0, ok/1, error/1, ok_or_error/1,
- ok_or_error2/2, ok_pid_or_error/0, channel_exit/0,
+ connection/0, protocol/0, user/0, internal_user/0, ok/1, error/1,
+ ok_or_error/1, ok_or_error2/2, ok_pid_or_error/0, channel_exit/0,
connection_exit/0]).
-type(channel_exit() :: no_return()).
@@ -151,9 +151,15 @@
-type(protocol() :: rabbit_framing:protocol()).
-type(user() ::
- #user{username :: rabbit_access_control:username(),
- password_hash :: rabbit_access_control:password_hash(),
- is_admin :: boolean()}).
+ #user{username :: rabbit_access_control:username(),
+ is_admin :: boolean(),
+ auth_backend :: atom(),
+ impl :: any()}).
+
+-type(internal_user() ::
+ #internal_user{username :: rabbit_access_control:username(),
+ password_hash :: rabbit_access_control:password_hash(),
+ is_admin :: boolean()}).
-type(ok(A) :: {'ok', A}).
-type(error(A) :: {'error', A}).
diff --git a/src/rabbit_upgrade_functions.erl b/src/rabbit_upgrade_functions.erl
index 1c56d51d..5dd4c558 100644
--- a/src/rabbit_upgrade_functions.erl
+++ b/src/rabbit_upgrade_functions.erl
@@ -27,6 +27,7 @@
-rabbit_upgrade({remove_user_scope, []}).
-rabbit_upgrade({hash_passwords, []}).
-rabbit_upgrade({add_ip_to_listener, []}).
+-rabbit_upgrade({user_to_internal_user, []}).
%% -------------------------------------------------------------------
@@ -35,6 +36,7 @@
-spec(remove_user_scope/0 :: () -> 'ok').
-spec(hash_passwords/0 :: () -> 'ok').
-spec(add_ip_to_listener/0 :: () -> 'ok').
+-spec(user_to_internal_user/0 :: () -> 'ok').
-endif.
@@ -71,8 +73,21 @@ add_ip_to_listener() ->
end,
[node, protocol, host, ip_address, port]).
+user_to_internal_user() ->
+ mnesia(
+ rabbit_user,
+ fun({user, Username, PasswordHash, IsAdmin}) ->
+ {internal_user, Username, PasswordHash, IsAdmin}
+ end,
+ [username, password_hash, is_admin], internal_user).
+
%%--------------------------------------------------------------------
mnesia(TableName, Fun, FieldList) ->
{atomic, ok} = mnesia:transform_table(TableName, Fun, FieldList),
ok.
+
+mnesia(TableName, Fun, FieldList, NewRecordName) ->
+ {atomic, ok} = mnesia:transform_table(TableName, Fun, FieldList,
+ NewRecordName),
+ ok.