[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-API] [PATCH] CA-35368: add support to per-key RBAC



7 files changed, 126 insertions(+), 24 deletions(-)
ocaml/idl/datamodel.ml                |   23 +++++----
ocaml/idl/datamodel_types.ml          |    4 +
ocaml/idl/datamodel_utils.ml          |    6 ++
ocaml/idl/ocaml_backend/gen_rbac.ml   |   21 +++++++-
ocaml/idl/ocaml_backend/gen_server.ml |    3 -
ocaml/idl/ocaml_backend/rbac.ml       |   79 +++++++++++++++++++++++++++++++--
ocaml/idl/ocaml_backend/rbac_audit.ml |   14 ++---


# HG changeset patch
# User Marcus Granado <marcus.granado@xxxxxxxxxx>
# Date 1259255339 0
# Node ID c9fd958b25ee2e4334558024f64bf0659410e756
# Parent  c2e75d891d3dd4542066384cf07331bf727500ca
CA-35368: add support to per-key RBAC

Signed-off-by: Marcus Granado <marcus.granado@xxxxxxxxxxxxx>

diff -r c2e75d891d3d -r c9fd958b25ee ocaml/idl/datamodel.ml
--- a/ocaml/idl/datamodel.ml    Fri Nov 13 14:01:05 2009 +0000
+++ b/ocaml/idl/datamodel.ml    Thu Nov 26 17:08:59 2009 +0000
@@ -187,6 +187,7 @@
     ?(no_current_operations=false) ?(secret=false) ?(hide_from_docs=false)
     ?(pool_internal=false)
     ~allowed_roles
+    ?(map_keys_roles=[])
     ?(params=[]) ?versioned_params () = 
   (* if you specify versioned_params then these get put in the params field of 
the message record;
      otherwise params go in with no default values and 
param_release=call_release...
@@ -213,7 +214,8 @@
     msg_no_current_operations = no_current_operations;
     msg_hide_from_docs = hide_from_docs;
     msg_pool_internal = pool_internal;
-    msg_allowed_roles = allowed_roles
+    msg_allowed_roles = allowed_roles;
+    msg_map_keys_roles = map_keys_roles
   }
 
 let assert_operation_valid enum cls self = call 
@@ -2537,7 +2539,9 @@
 (** Make an object field record *)
 let field ?(in_oss_since = Some "3.0.3") ?(in_product_since = rel_rio) 
?(internal_only = false)
     ?internal_deprecated_since ?(ignore_foreign_key = false) 
?(writer_roles=None) ?(reader_roles=None)
-    ?(qualifier = RW) ?(ty = String) ?(effect = false) ?(default_value = None) 
?(persist = true) name desc =
+    ?(qualifier = RW) ?(ty = String) ?(effect = false) ?(default_value = None) 
?(persist = true)
+    ?(map_keys_roles=[]) (* list of (key_name,(writer_roles)) for a map field 
*)
+    name desc =
   
 
   Field { release={internal=get_product_releases in_product_since; 
@@ -2552,6 +2556,7 @@
          field_ignore_foreign_key = ignore_foreign_key;
          field_setter_roles = writer_roles;
          field_getter_roles = reader_roles;
+         field_map_keys_roles = map_keys_roles;
          }
 
 let uid ?(in_oss_since=Some "3.0.3") ?(reader_roles=None) refname =
@@ -2859,7 +2864,7 @@
       field ~qualifier:DynamicRO ~ty:String "type" "if the task has completed 
successfully, this field contains the type of the encoded result (i.e. name of 
the class whose reference is in the result field). Undefined otherwise.";
       field ~qualifier:DynamicRO ~ty:String "result" "if the task has 
completed successfully, this field contains the result value (either Void or an 
object reference). Undefined otherwise.";
       field ~qualifier:DynamicRO ~ty:(Set String) "error_info" "if the task 
has failed, this field contains the set of associated error strings. Undefined 
otherwise.";
-      field ~writer_roles:_R_VM_OP ~in_product_since:rel_miami 
~default_value:(Some (VMap [])) ~ty:(Map(String, String)) "other_config" 
"additional configuration";
+      field ~in_product_since:rel_miami ~default_value:(Some (VMap [])) 
~ty:(Map(String, String)) "other_config" "additional configuration" 
~map_keys_roles:[("applies_to",(_R_VM_OP));("XenCenterUUID",(_R_VM_OP))];
       (* field ~ty:(Set(Ref _alert)) ~in_product_since:rel_miami 
~qualifier:DynamicRO "alerts" "all alerts related to this task"; *)
       field ~qualifier:DynamicRO ~in_product_since:rel_orlando 
~default_value:(Some (VRef "")) ~ty:(Ref _task) "subtask_of" "Ref pointing to 
the task this is a substask of.";
       field ~qualifier:DynamicRO ~in_product_since:rel_orlando ~ty:(Set (Ref 
_task)) "subtasks"   "List pointing to all the substasks."; 
@@ -3481,7 +3486,7 @@
        namespace ~name:"API_version" ~contents:api_version ();
        field ~qualifier:DynamicRO ~ty:Bool "enabled" "True if the host is 
currently enabled";
        field ~qualifier:StaticRO ~ty:(Map(String, String)) "software_version" 
"version strings";
-       field ~ty:(Map(String, String)) "other_config" "additional 
configuration";
+       field ~ty:(Map(String, String)) "other_config" "additional 
configuration" 
~map_keys_roles:[("folder",(_R_VM_OP));("XenCenter.CustomFields.*",(_R_VM_OP))];
        field ~qualifier:StaticRO ~ty:(Set(String)) "capabilities" "Xen 
capabilities";
        field ~qualifier:DynamicRO ~ty:(Map(String, String)) 
"cpu_configuration" "The CPU configuration on this host.  May contain keys such 
as \"nr_nodes\", \"sockets_per_node\", \"cores_per_socket\", or 
\"threads_per_core\"";
        field ~qualifier:DynamicRO ~ty:String "sched_policy" "Scheduler policy 
currently in force on this host";
@@ -3618,7 +3623,7 @@
     ] @ (allowed_and_current_operations ~writer_roles:_R_POOL_OP 
network_operations) @ [
       field ~qualifier:DynamicRO ~ty:(Set (Ref _vif)) "VIFs" "list of 
connected vifs";
       field ~qualifier:DynamicRO ~ty:(Set (Ref _pif)) "PIFs" "list of 
connected pifs";
-      field ~writer_roles:_R_POOL_OP ~ty:(Map(String, String)) "other_config" 
"additional configuration" ;
+      field ~writer_roles:_R_POOL_OP ~ty:(Map(String, String)) "other_config" 
"additional configuration" 
~map_keys_roles:[("folder",(_R_VM_OP));("XenCenter.CustomFields.*",(_R_VM_OP));("XenCenterCreateInProgress",(_R_VM_OP))];
       field ~in_oss_since:None ~qualifier:DynamicRO "bridge" "name of the 
bridge corresponding to this network on the local host";
       field ~qualifier:DynamicRO ~in_product_since:rel_orlando 
~ty:(Map(String, Ref _blob)) ~default_value:(Some (VMap [])) "blobs" "Binary 
blobs associated with this network";
       field ~writer_roles:_R_POOL_OP ~in_product_since:rel_orlando 
~default_value:(Some (VSet [])) ~ty:(Set String) "tags" "user-specified tags 
for categorization purposes"
@@ -4112,7 +4117,7 @@
        field ~qualifier:StaticRO "type" "type of the storage repository";
        field ~qualifier:StaticRO "content_type" "the type of the SR's content, 
if required (e.g. ISOs)";
        field ~qualifier:DynamicRO "shared" ~ty:Bool "true if this SR is 
(capable of being) shared between multiple hosts";
-       field ~ty:(Map(String, String)) "other_config" "additional 
configuration";
+       field ~ty:(Map(String, String)) "other_config" "additional 
configuration" 
~map_keys_roles:[("folder",(_R_VM_OP));("XenCenter.CustomFields.*",(_R_VM_OP))];
        field  ~in_product_since:rel_orlando ~default_value:(Some (VSet [])) 
~ty:(Set String) "tags" "user-specified tags for categorization purposes";
        field ~ty:Bool ~qualifier:DynamicRO ~in_oss_since:None 
~internal_only:true "default_vdi_visibility" "";
        field ~in_oss_since:None ~ty:(Map(String, String)) 
~in_product_since:rel_miami ~qualifier:RW "sm_config" "SM dependent data" 
~default_value:(Some (VMap []));
@@ -4385,7 +4390,7 @@
        field ~qualifier:StaticRO ~ty:vdi_type "type" "type of the VDI";
        field ~qualifier:StaticRO ~ty:Bool "sharable" "true if this disk may be 
shared";
        field ~qualifier:StaticRO ~ty:Bool "read_only" "true if this disk may 
ONLY be mounted read-only";
-       field  ~ty:(Map(String, String)) "other_config" "additional 
configuration" ;
+       field ~ty:(Map(String, String)) "other_config" "additional 
configuration" 
~map_keys_roles:[("folder",(_R_VM_OP));("XenCenter.CustomFields.*",(_R_VM_OP))];
        field ~qualifier:DynamicRO ~ty:Bool "storage_lock" "true if this disk 
is locked at the storage level";
        (* XXX: location field was in the database in rio, now API in miami *)
        field ~in_oss_since:None ~in_product_since:rel_miami ~ty:String 
~qualifier:DynamicRO ~default_value:(Some (VString "")) "location" "location 
information";
@@ -5026,7 +5031,7 @@
                        ; field ~in_oss_since:None ~qualifier:RW ~ty:(Ref _sr) 
"default_SR" "Default SR for VDIs"
                        ; field ~in_oss_since:None ~qualifier:RW ~ty:(Ref _sr) 
"suspend_image_SR" "The SR in which VDIs for suspend images are created"
                        ; field ~in_oss_since:None ~qualifier:RW ~ty:(Ref _sr) 
"crash_dump_SR" "The SR in which VDIs for crash dumps are created"
-                       ; field ~writer_roles:_R_VM_OP ~in_oss_since:None 
~ty:(Map(String, String)) "other_config" "additional configuration"
+                       ; field ~in_oss_since:None ~ty:(Map(String, String)) 
"other_config" "additional configuration" 
~map_keys_roles:[("folder",(_R_VM_OP));("XenCenter.CustomFields.*",(_R_VM_OP));("EMPTY_FOLDERS",(_R_VM_OP))]
                        ; field ~in_oss_since:None 
~in_product_since:rel_orlando ~qualifier:DynamicRO ~ty:Bool 
~default_value:(Some (VBool false)) "ha_enabled" "true if HA is enabled on the 
pool, false otherwise"
                        ; field ~in_oss_since:None 
~in_product_since:rel_orlando ~qualifier:DynamicRO ~ty:(Map(String, String)) 
~default_value:(Some (VMap [])) "ha_configuration" "The current HA 
configuration"
                        ; field ~in_oss_since:None 
~in_product_since:rel_orlando ~qualifier:DynamicRO ~ty:(Set String) 
~default_value:(Some (VSet [])) "ha_statefiles" "HA statefile VDIs in use"
@@ -5437,7 +5442,7 @@
        field ~ty:(Map(String, String)) "platform" "platform-specific 
configuration";
 
        field "PCI_bus" "PCI bus path for pass-through devices";
-       field  ~ty:(Map(String, String)) "other_config" "additional 
configuration";
+       field  ~ty:(Map(String, String)) "other_config" "additional 
configuration" 
~map_keys_roles:[("folder",(_R_VM_OP));("XenCenter.CustomFields.*",(_R_VM_OP))];
        field ~qualifier:DynamicRO ~ty:Int "domid" "domain ID (if available, -1 
otherwise)";
        field ~qualifier:DynamicRO ~in_oss_since:None ~ty:String "domarch" 
"Domain architecture (if available, null string otherwise)";
        field ~in_oss_since:None ~qualifier:DynamicRO ~ty:(Map(String, String)) 
"last_boot_CPU_flags" "describes the CPU flags on which the VM was last booted";
diff -r c2e75d891d3d -r c9fd958b25ee ocaml/idl/datamodel_types.ml
--- a/ocaml/idl/datamodel_types.ml      Fri Nov 13 14:01:05 2009 +0000
+++ b/ocaml/idl/datamodel_types.ml      Thu Nov 26 17:08:59 2009 +0000
@@ -133,6 +133,7 @@
     msg_custom_marshaller: bool;
     msg_hide_from_docs: bool;
     msg_allowed_roles: string list option;
+    msg_map_keys_roles: (string * (string list option)) list
 }
 
 and field = {
@@ -148,7 +149,8 @@
     field_has_effect: bool;
     field_ignore_foreign_key: bool;
     field_setter_roles: string list option;
-    field_getter_roles: string list option
+    field_getter_roles: string list option;
+    field_map_keys_roles: (string * (string list option)) list
 }
 
 and error = { 
diff -r c2e75d891d3d -r c9fd958b25ee ocaml/idl/datamodel_utils.ml
--- a/ocaml/idl/datamodel_utils.ml      Fri Nov 13 14:01:05 2009 +0000
+++ b/ocaml/idl/datamodel_utils.ml      Thu Nov 26 17:08:59 2009 +0000
@@ -219,7 +219,8 @@
                 msg_hide_from_docs = false;
                 msg_pool_internal = false;
                 msg_db_only = fld.internal_only;
-                msg_allowed_roles = None
+                msg_allowed_roles = None;
+                msg_map_keys_roles = []
               } in
   let getter = { common with
                   msg_name = prefix "get_";
@@ -283,6 +284,7 @@
                          "Add the given key-value pair to the %s field of the 
given %s."
                          (String.concat "/" fld.full_name) x.name);
            msg_allowed_roles = fld.field_setter_roles;
+           msg_map_keys_roles = List.map (fun (k,(w))->(k,w)) 
fld.field_map_keys_roles;
            msg_tag = FromField(Add, fld) };
        { common with
            msg_name = prefix "remove_from_";
@@ -293,6 +295,7 @@
                          "Remove the given key and its corresponding value 
from the %s field of the given %s.  If the key is not in that Map, then do 
nothing."
                          (String.concat "/" fld.full_name) x.name);
            msg_allowed_roles = fld.field_setter_roles;
+           msg_map_keys_roles = List.map (fun (k,(w))->(k,w)) 
fld.field_map_keys_roles;
            msg_tag = FromField(Remove, fld) };
       ]
   | t, _ -> [
@@ -320,6 +323,7 @@
                 msg_session=false; msg_release=x.obj_release; 
msg_has_effect=false; msg_tag=Custom;
                 msg_force_custom = x.force_custom_actions;
                 msg_allowed_roles = None;
+                msg_map_keys_roles = [];
                 msg_obj_name=x.name } in
   (* Constructor *)
   let ctor = { common with 
diff -r c2e75d891d3d -r c9fd958b25ee ocaml/idl/ocaml_backend/gen_rbac.ml
--- a/ocaml/idl/ocaml_backend/gen_rbac.ml       Fri Nov 13 14:01:05 2009 +0000
+++ b/ocaml/idl/ocaml_backend/gen_rbac.ml       Thu Nov 26 17:08:59 2009 +0000
@@ -79,7 +79,8 @@
 let permission_description = "A basic permission"
 let permission_name wire_name =
        let s1 =replace_char (Printf.sprintf "permission_%s" wire_name) '.' '_' 
in
-       replace_char s1 '/' '_'
+       let s2 = replace_char s1 '/' '_' in
+       Stringext.String.replace "*" "WILDCHAR" s2
 
 let permission_index = ref 0
 let writer_permission name nperms =
@@ -213,8 +214,12 @@
                let r,perms = match r1 with []->(xr,[])|r1::_->r1 in 
                concat (xperm,((r,xperm::perms)::r2),extra_rs)
 
+let get_key_permission_name permission key_name =
+  permission ^ "/key_" ^ key_name
+
 let add_permission_to_roles roles_permissions (obj: obj) (x: message) =
        let msg_allowed_roles = x.msg_allowed_roles in
+       let msg_map_keys_roles = x.msg_map_keys_roles in
        let wire_name = DU.wire_name ~sync:true obj x in
        match msg_allowed_roles with
                | None -> (
@@ -222,7 +227,19 @@
                                (* a message should have at least one role *)
                                failwith (Printf.sprintf "No roles for message 
%s" wire_name);
                        )
-               | Some(allowed_roles) -> concat 
(wire_name,roles_permissions,allowed_roles)
+               | Some(allowed_roles) -> 
+                               let with_msg_roles_permissions =
+                                       (concat 
(wire_name,roles_permissions,allowed_roles))
+                               in
+                               List.fold_left
+                                       (fun rsps (k,rs)->
+                                               let wire_name_key = 
get_key_permission_name wire_name k in
+                                               match rs with
+                                               |None->failwith (Printf.sprintf 
"No roles for key %s" wire_name_key)
+                                               |Some(allowed_roles)->(concat 
(wire_name_key, rsps, allowed_roles))
+                                       )
+                                       with_msg_roles_permissions
+                                       msg_map_keys_roles
 
 let get_http_permissions_roles =
        List.fold_left
diff -r c2e75d891d3d -r c9fd958b25ee ocaml/idl/ocaml_backend/gen_server.ml
--- a/ocaml/idl/ocaml_backend/gen_server.ml     Fri Nov 13 14:01:05 2009 +0000
+++ b/ocaml/idl/ocaml_backend/gen_server.ml     Thu Nov 26 17:08:59 2009 +0000
@@ -158,7 +158,8 @@
   let rbac_check_begin = if has_session_arg
     then [
                        "let arg_names = "^(List.fold_right (fun arg args -> 
"\""^arg^"\"::"^args) string_args (if is_non_constructor_with_defaults then 
"\"default_args\"::[]" else "[]"))^" in";
-                       "Rbac.check session_id __call 
~args:(arg_names,__params) ~__context ~fn:(fun ()-> (*RBAC-BEGIN*)"]
+                       "let key_names = "^(List.fold_right (fun arg args -> 
"\""^arg^"\"::"^args) (List.map (fun (k,_)->k) x.msg_map_keys_roles) "[]")^" 
in";
+                       "Rbac.check session_id __call 
~args:(arg_names,__params) ~keys:key_names ~__context ~fn:(fun ()-> 
(*RBAC-BEGIN*)"]
     else []
   in
   let rbac_check_end = if has_session_arg then [") (*RBAC-END*)"] else [] in
diff -r c2e75d891d3d -r c9fd958b25ee ocaml/idl/ocaml_backend/rbac.ml
--- a/ocaml/idl/ocaml_backend/rbac.ml   Fri Nov 13 14:01:05 2009 +0000
+++ b/ocaml/idl/ocaml_backend/rbac.ml   Thu Nov 26 17:08:59 2009 +0000
@@ -95,6 +95,80 @@
                        session_permissions_tbl
                        session_id
 
+(* create a key permission name that can be in the session *)
+let get_key_permission_name permission key_name =
+       permission ^ "/key_" ^ key_name
+
+(* create a key-error permission name that is never in the session *)
+let get_keyERR_permission_name permission err =
+       permission ^ "/keyERR_" ^ err
+
+let permission_of_action ?args ~keys _action =
+       (* all permissions are in lowercase, see gen_rbac.writer_ *)
+       let action = (String.lowercase _action) in
+       if (List.length keys) < 1
+       then (* most actions do not use rbac-guarded map keys in the arguments 
*)
+               action
+
+       else (* only actions with rbac-guarded map keys fall here *)
+       match args with
+       |None -> begin (* this should never happen *)
+                       debug "DENYING access: no args for keyed-action %s" 
action;
+                       get_keyERR_permission_name action "DENY_NOARGS" (* will 
always deny *)
+               end
+       |Some (arg_keys,arg_values) ->
+               if (List.length arg_keys) <> (List.length arg_values)
+               then begin (* this should never happen *)
+                       debug "DENYING access: arg_keys and arg_values lengths 
don't match: arg_keys=[%s], arg_values=[%s]"
+                               ((List.fold_left (fun ss s->ss^s^",") "" 
arg_keys))
+                               ((List.fold_left (fun ss s->ss^(Xml.to_string 
s)^",") "" arg_values))
+                       ;
+                       get_keyERR_permission_name action "DENY_WRGLEN" (* will 
always deny *)  
+               end
+               else (* keys and values have the same length *)
+               let rec get_permission_name_of_keys arg_keys arg_values =
+                       match arg_keys,arg_values with
+                       |[],[]|_,[]|[],_-> (* this should never happen *)
+                               begin 
+                                       debug "DENYING access: no 'key' 
argument in the action %s" action;
+                                       get_keyERR_permission_name action 
"DENY_NOKEY" (* deny by default *)
+                               end
+                       |k::ks,v::vs->
+                               if k<>"key" (* "key" is defined in 
datamodel_utils.ml *)
+                               then
+                                       (get_permission_name_of_keys ks vs)
+                               else (* found "key" in args *)
+                                       match v with
+                                       | Xml.Element("value",_,(Xml.PCData 
key_name_in_args)::[]) ->
+                                       begin
+                                               (*debug "key_name_in_args=%s, 
keys=[%s]" key_name_in_args ((List.fold_left (fun ss s->ss^s^",") "" keys)) ;*)
+                                               try 
+                                               let key_name =
+                                                       List.find
+                                                       (fun key_name ->
+                                                        if 
Stringext.String.endswith "*" key_name
+                                                        then begin (* resolve 
wildcards at the end *)
+                                                                
Stringext.String.startswith
+                                                                        
(String.sub key_name 0 ((String.length key_name) - 1))
+                                                                        
key_name_in_args
+                                                        end
+                                                        else (* no wildcards 
to resolve *)
+                                                                key_name = 
key_name_in_args
+                                                       )
+                                                       keys
+                                               in
+                                                       get_key_permission_name 
action (String.lowercase key_name)
+                                               with Not_found -> (* expected, 
key_in_args is not rbac-protected *)
+                                                       action
+                                       end
+                                       |_ -> begin (* this should never happen 
*)
+                                                debug "DENYING access: wrong 
XML value [%s] in the 'key' argument of action %s" (Xml.to_string v) action;
+                                                get_keyERR_permission_name 
action "DENY_NOVALUE"
+                                       end
+               in
+               get_permission_name_of_keys arg_keys arg_values
+
+
 let is_permission_in_session ~session_id ~permission ~session =
        let find_linear elem set = List.exists (fun e -> e = elem) set in
        let find_log elem set = Permission_set.mem elem set in
@@ -137,10 +211,9 @@
 
 (* Execute fn if rbac access is allowed for action, otherwise fails. *)
 let nofn = fun () -> ()
-let check ?(extra_dmsg="") ?(extra_msg="") ?args ~__context ~fn session_id 
action =
+let check ?(extra_dmsg="") ?(extra_msg="") ?args ?(keys=[]) ~__context ~fn 
session_id action =
 
-       (* all permissions are in lowercase, see gen_rbac.writer_ *)
-       let permission = String.lowercase action in
+       let permission = permission_of_action action ?args ~keys in
        
        if (is_access_allowed ~__context ~session_id ~permission)
        then (* allow access to action *)
diff -r c2e75d891d3d -r c9fd958b25ee ocaml/idl/ocaml_backend/rbac_audit.ml
--- a/ocaml/idl/ocaml_backend/rbac_audit.ml     Fri Nov 13 14:01:05 2009 +0000
+++ b/ocaml/idl/ocaml_backend/rbac_audit.ml     Thu Nov 26 17:08:59 2009 +0000
@@ -299,7 +299,7 @@
        with e -> (* never bubble up the error here *) 
                D.debug "ignoring %s" (ExnHelper.string_of_exn e)
 
-let sexpr_of __context session_id allowed_denied ok_error result_error ?args 
action =
+let sexpr_of __context session_id allowed_denied ok_error result_error ?args 
action permission =
   let result_error = 
                if result_error = "" then result_error else ":"^result_error
        in
@@ -312,7 +312,7 @@
                SExpr.String (ok_error ^ result_error)::
     SExpr.String (call_type_of action)::
                (*SExpr.String (Helper_hostname.get_hostname ())::*)
-    SExpr.String action::
+    SExpr.String permission::
     (SExpr.Node (sexpr_of_parameters action args))::
                []
        )
@@ -321,11 +321,11 @@
 
 let fn_append_to_master_audit_log = ref None
 
-let audit_line_of __context session_id allowed_denied ok_error result_error 
action ?args =
+let audit_line_of __context session_id allowed_denied ok_error result_error 
action permission ?args =
        let _line = 
                (SExpr.string_of 
                         (sexpr_of __context session_id allowed_denied 
-                                       ok_error result_error ?args action
+                                       ok_error result_error ?args action 
permission
                         )
                )
        in
@@ -339,7 +339,7 @@
 let allowed_ok ~__context ~session_id ~action ~permission ?args ?result () =
        wrap (fun () ->
                if has_to_audit action then 
-                       audit_line_of __context session_id "ALLOWED" "OK" "" 
action ?args
+                       audit_line_of __context session_id "ALLOWED" "OK" "" 
action permission ?args
        )
 
 let allowed_error ~__context ~session_id ~action ~permission ?args ?error () =
@@ -350,13 +350,13 @@
                                | None -> ""
                                | Some error -> (ExnHelper.string_of_exn error)
                        in
-                       audit_line_of __context session_id "ALLOWED" "ERROR" 
error_str action ?args
+                       audit_line_of __context session_id "ALLOWED" "ERROR" 
error_str action permission ?args
        )
        
 let denied ~__context ~session_id ~action ~permission ?args () =
        wrap (fun () ->
                if has_to_audit action then
-                       audit_line_of __context session_id "DENIED" "" "" 
action ?args
+                       audit_line_of __context session_id "DENIED" "" "" 
action permission ?args
        )
 
 let session_destroy ~__context ~session_id =

Attachment: xen-api.hg.patch
Description: Text Data

_______________________________________________
xen-api mailing list
xen-api@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/mailman/listinfo/xen-api

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.