1. paulj
  2. rabbitmq-bql

Commits

Paul Jones  committed ad16c03

Support requiring permissions for configuration and query tasks

  • Participants
  • Parent commits a0637f5
  • Branches bug22237

Comments (0)

Files changed (1)

File src/bql_applicator.erl

View file
 -include_lib("rabbit_common/include/rabbit_framing.hrl").
 
 -define(RPC_TIMEOUT, 30000).
+-define(MASTER_VHOST, <<"/">>).
 
 -record(state, {node, user, vhost}).
 
 
     {ok, [catch apply_command(Command, #state {node = Node, user = User, vhost = VHost}) 
             || Command <- Commands]}.
-            
+                                          
 % Queue Management
 apply_command({create_queue, Name, Durable, Args}, #state {user = Username, vhost = VHost}) ->
     QueueName = rabbit_misc:r(VHost, queue, list_to_binary(Name)),
     end;
 
 % User Management
-apply_command({create_user, Name, Password}, #state {node = Node}) ->
+apply_command({create_user, Name, Password}, #state {user = Username, node = Node}) ->
+    ensure_wildcard_access(Username, ?MASTER_VHOST, configure),
     rpc_call(Node, rabbit_access_control, add_user, [list_to_binary(Name), list_to_binary(Password)]),
     ok;
-apply_command({drop_user, Name}, #state {node = Node}) ->
+apply_command({drop_user, Name}, #state {user = Username, node = Node}) ->
+    ensure_wildcard_access(Username, ?MASTER_VHOST, configure),
     rpc_call(Node, rabbit_access_control, delete_user, [list_to_binary(Name)]),
     ok;
 
 % VHost Management
-apply_command({create_vhost, Name}, #state {node = Node}) ->
+apply_command({create_vhost, Name}, #state {user = Username, node = Node}) ->
+    ensure_wildcard_access(Username, ?MASTER_VHOST, configure),
     rpc_call(Node, rabbit_access_control, add_vhost, [list_to_binary(Name)]),
     ok;
-apply_command({drop_vhost, Name}, #state {node = Node}) ->
+apply_command({drop_vhost, Name}, #state {user = Username, node = Node}) ->
+    ensure_wildcard_access(Username, ?MASTER_VHOST, configure),
     rpc_call(Node, rabbit_access_control, delete_vhost, [list_to_binary(Name)]),
     ok;
 
                    list_to_binary(RoutingKey), <<"">>, Username, VHost);
 
 % Privilege Management
-apply_command({grant, Privilege, Regex, User}, #state {node = Node, vhost = VHost}) ->
+apply_command({grant, Privilege, Regex, User}, #state {node = Node, user = Username, vhost = VHost}) ->
+    ensure_wildcard_access(Username, ?MASTER_VHOST, configure),
     PrivilegeList = expand_privilege_list(Privilege),
-    apply_privilege_list(Node, list_to_binary(User), VHost, PrivilegeList, list_to_binary(Regex));
-apply_command({revoke, Privilege, User}, #state {node = Node, vhost = VHost}) ->
+    apply_privilege_list(list_to_binary(User), VHost, PrivilegeList, list_to_binary(Regex));
+apply_command({revoke, Privilege, User}, #state {node = Node, user = Username, vhost = VHost}) ->
+    ensure_wildcard_access(Username, ?MASTER_VHOST, configure),
     PrivilegeList = expand_privilege_list(Privilege),
-    apply_privilege_list(Node, list_to_binary(User), VHost, PrivilegeList, <<"">>);
+    apply_privilege_list(list_to_binary(User), VHost, PrivilegeList, <<"">>);
   
 % Queries
-apply_command({select, "exchanges", Fields, Modifiers}, #state {node = Node, vhost = VHost}) ->
+apply_command({select, "exchanges", Fields, Modifiers}, #state {node = Node, user = Username, vhost = VHost}) ->
+    ensure_wildcard_access(Username, VHost, read),
     AllFieldList = [name, type, durable, auto_delete, arguments],
     FieldList = validate_fields(AllFieldList, Fields),
     Exchanges = rpc_call(Node, rabbit_exchange, info_all, [VHost]),
     interpret_response(AllFieldList, FieldList, Exchanges, Modifiers);
 
-apply_command({select, "queues", Fields, Modifiers}, #state {node = Node, vhost = VHost}) ->
+apply_command({select, "queues", Fields, Modifiers}, #state {node = Node, user = Username, vhost = VHost}) ->
+    ensure_wildcard_access(Username, VHost, read),
     AllFieldList = [name, durable, auto_delete, arguments, pid, messages_ready,
                     messages_unacknowledged, messages_uncommitted, messages, acks_uncommitted,
                     consumers, transactions, memory],
     Queues = rpc_call(Node, rabbit_amqqueue, info_all, [VHost]),
     interpret_response(AllFieldList, FieldList, Queues, Modifiers);
 
-apply_command({select, "bindings", Fields, Modifiers}, #state {node = Node, vhost = VHost}) ->
+apply_command({select, "bindings", Fields, Modifiers}, #state {node = Node, user = Username, vhost = VHost}) ->
+    ensure_wildcard_access(Username, VHost, read),
     AllFieldList = [exchange_name, queue_name, routing_key, args],
     FieldList = validate_fields(AllFieldList, Fields),
     Bindings = rpc_call(Node, rabbit_exchange, list_bindings, [VHost]),
     interpret_response(AllFieldList, FieldList, Bindings, Modifiers);
 
-apply_command({select, "users", Fields, Modifiers}, #state {node = Node}) ->
+apply_command({select, "users", Fields, Modifiers}, #state {node = Node, user = Username}) ->
+    ensure_wildcard_access(Username, ?MASTER_VHOST, read),
     AllFieldList = [name],
     FieldList = validate_fields(AllFieldList, Fields),
     Response = rpc_call(Node, rabbit_access_control, list_users, []),
     Users = [[binary_to_list(User)] || User <- Response],
     interpret_response(AllFieldList, FieldList, Users, Modifiers);
 
-apply_command({select, "vhosts", Fields, Modifiers}, #state {node = Node}) ->
+apply_command({select, "vhosts", Fields, Modifiers}, #state {node = Node, user = Username}) ->
+    ensure_wildcard_access(Username, ?MASTER_VHOST, read),
     AllFieldList = [name],
     FieldList = validate_fields(AllFieldList, Fields),
     Response = rpc_call(Node, rabbit_access_control, list_vhosts, []),
     VHosts = [[{name, binary_to_list(User)}] || User <- Response],
     interpret_response(AllFieldList, FieldList, VHosts, Modifiers);
 
-apply_command({select, "permissions", Fields, Modifiers}, #state {node = Node, vhost = VHost}) ->
+apply_command({select, "permissions", Fields, Modifiers}, #state {node = Node, user = Username, vhost = VHost}) ->
+    ensure_wildcard_access(Username, VHost, read),
     AllFieldList = [username,configure_perm,write_perm,read_perm],
     FieldList = validate_fields(AllFieldList, Fields),
     Permissions = rpc_call(Node, rabbit_access_control, list_vhost_permissions, [VHost]),
     interpret_response(AllFieldList, FieldList, Permissions, Modifiers);
 
-apply_command({select, "connections", Fields, Modifiers}, #state {node = Node}) ->
+apply_command({select, "connections", Fields, Modifiers}, #state {node = Node, user = Username}) ->
+    ensure_wildcard_access(Username, ?MASTER_VHOST, read),
     AllFieldList = [pid, address, port, peer_address, peer_port, recv_oct, recv_cnt, send_oct, send_cnt,
                     send_pend, state, channels, user, vhost, timeout, frame_max],
     FieldList = validate_fields(AllFieldList, Fields),
 expand_privilege_list(X) ->
     [X].
 
-apply_privilege_list(Node, User, VHost, PrivilegeList, Regex) ->
+apply_privilege_list(User, VHost, PrivilegeList, Regex) ->
     %% Retrieve the old privilege structure
-    Current = retrieve_privileges(Node, User, VHost),
+    Current = retrieve_privileges(User, VHost),
 
     %% Update each privilege detailed in the privilege spec
     NewPrivs = [case X of
     [NewConfigure,NewWrite,NewRead] = NewPrivs,
 
     % Set the permissions
-    rpc_call(Node, rabbit_access_control, set_permissions, [User, VHost, NewConfigure, NewWrite, NewRead]),
+    rabbit_access_control:set_permissions(User, VHost, NewConfigure, NewWrite, NewRead),
     ok.
 
-retrieve_privileges(Node, User, VHost) ->
-    Permissions = rpc_call(Node, rabbit_access_control, list_vhost_permissions, [VHost]),
+retrieve_privileges(User, VHost) ->
+    Permissions = rabbit_access_control:list_vhost_permissions(VHost),
     UserPermissions = [[{configure, ConfigureRE}, {write, WriteRE}, {read, ReadRE}]
         || {PermUser, ConfigureRE, WriteRE, ReadRE} <- Permissions, User =:= PermUser],
     case length(UserPermissions) of
 ensure_resource_access(Username, Resource, Perm) ->
     rabbit_access_control:check_resource_access(Username, Resource, Perm).
     
+ensure_wildcard_access(Username, VHost, Perm) ->
+    VHostPerms = retrieve_privileges(Username, VHost),
+    Priv = proplists:get_value(Perm, VHostPerms, <<"">>),
+    case Priv == <<".*">> of
+        true -> ok;
+        false -> 
+            rabbit_misc:protocol_error(access_refused, 
+                "wildcard access to ~p on vhost ~s refused for user '~s'",
+                [Perm, VHost, Username])
+    end.
+    
 binding_action(Fun, ExchangeNameBin, QueueNameBin, RoutingKey, Arguments, Username, VHost) ->
     QueueName = rabbit_misc:r(VHost, queue, QueueNameBin),
     ensure_resource_access(Username, QueueName, write),