-
Notifications
You must be signed in to change notification settings - Fork 294
CP-310425: Include user names in the http response message #6766
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: feature/limit-vnc-console-sessions
Are you sure you want to change the base?
CP-310425: Include user names in the http response message #6766
Conversation
ocaml/xapi/xapi_globs.ml
Outdated
|
|
||
| let ssh_auto_mode_default = ref true | ||
|
|
||
| let display_user_name_in_XC = ref true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In a general way, it could be include_console_username_in_error.
ocaml/xapi/console.ml
Outdated
| in | ||
| Printf.sprintf | ||
| "<html><body><h1>Connection Limit Exceeded</h1><p>%s currently \ | ||
| connected to this console (VM %s). No more connections are allowed \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
connected -> connecting
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
connected is correct.
The message would be:
User 'root' is currently connected to ...
ocaml/xapi/console.ml
Outdated
|
|
||
| let active_connections : int VMMap.t ref = ref VMMap.empty | ||
| (* VMMap maps VM IDs to a list of (user_name, session_id) tuples representing active connections *) | ||
| let active_connections : (string * string) list VMMap.t ref = ref VMMap.empty |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer a record type if possible to avoid that these strings are confused.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. record is much better.
ocaml/xapi/console.ml
Outdated
| | Some _ | None -> | ||
| active_connections := VMMap.remove vm_id !active_connections | ||
| | Some connections -> | ||
| let updated_connections = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could do:
match List.filter (fun (_, sid) -> sid <> session_id) connections with
| [] -> ..
| upd -> ..
ocaml/xapi/console.ml
Outdated
| VMMap.find_opt vm_id !active_connections |> Option.value ~default:[] | ||
| in | ||
| let count = List.length connections in | ||
| if is_limit_enabled && count > 0 then ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would suffice to check against the empty list and to avoid the length call.
ocaml/xapi/console.ml
Outdated
| | c -> | ||
| String.make 1 c | ||
| in | ||
| String.fold_left (fun acc c -> acc ^ escape_char c) "" s |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an expensive way to create a string. We should not use this if this is happen frequently or the string is long. The string by default is constructed one character at a time, creating a lot of garbage along the way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We probably have code for this; a function like html_escape should be put into an existing library to make it more accessible and to avoid that we re-implement it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for telling me. I'll look for existing library or make it a common function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If nothing exists, I suggest:
- have a quick scan over the string. If no character needs escaping, use the string as is
- if there is something to do, use
Bufferto create the resulting string
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Found an exsiting function:
Xapi_stdext_std.Xstringext.String.escaped
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This existing function is slow, too - but we are going to improve it.
psafont
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The commit message is lacking information on why is this change needed.
I understand is a refinement on the previous design when there was no option to avoid leaking user names to clients, but this needs to be spelled out at least in the commit message.
ocaml/xapi/console.ml
Outdated
| match connected_users with | ||
| | [user] -> | ||
| Printf.sprintf "User '%s' is" (html_escape user) | ||
| | users -> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be empty.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, though it's unlikely to be empty. We have to consider the case.
ocaml/xapi/console.ml
Outdated
| with_lock mutex (fun () -> | ||
| match VMMap.find_opt vm_id !active_connections with | ||
| | Some n when n > 1 -> | ||
| active_connections := VMMap.add vm_id (n - 1) !active_connections | ||
| | Some _ | None -> | ||
| active_connections := VMMap.remove vm_id !active_connections | ||
| | Some connections -> | ||
| let updated_connections = | ||
| List.filter (fun (_, sid) -> sid <> session_id) connections | ||
| in | ||
| if updated_connections = [] then | ||
| active_connections := VMMap.remove vm_id !active_connections | ||
| else | ||
| active_connections := | ||
| VMMap.add vm_id updated_connections !active_connections | ||
| | None -> | ||
| (* Unlikely *) | ||
| () |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about:
with_lock mutex (fun () ->
let f conns = Option.bind conns (fun conns ->
match List.filter (fun (_, sid) -> sid <> session_id) conns with
| [] -> None
| l -> Some l
)
in
active_connections := VMMap.update vm_id f !active_connections
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Elegant!
ocaml/xapi/console.ml
Outdated
| ) | ||
| ) | ||
|
|
||
| let get_connected_users vm_id = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's better to get the users from try_add.
7d30cf5 to
22c1839
Compare
Updated the commit message. |
|
All comments resolved. |
22c1839 to
846927e
Compare
ocaml/xapi/console.ml
Outdated
| if !Xapi_globs.include_console_username_in_error then | ||
| let users_text = | ||
| match connected_users with | ||
| | [] -> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since now the connected_users comes from try_add, it must not be empty. So it would be an internal error or bug in this case that I think raise Failure after an error logging can be used.
ocaml/xapi/console.ml
Outdated
| Printf.sprintf | ||
| "<html><body><h1>Connection Limit Exceeded</h1><p>There're users \ | ||
| currently connected to this console (VM %s). No more connections are \ | ||
| allowed when limit_console_sessions is enabled.</p></body></html>" | ||
| vm_id |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This duplication could be resolved like:
let body =
let users_text =
match (!Xapi_globs.include_console_username_in_error, connected_users) with
| true, [] ->
error "The connected user list should not be empty." ;
raise Failure
| true, [user] ->
Printf.sprintf "User '%s' is" (html_escape user)
| true, users ->
let escaped_users = List.map html_escape users in
Printf.sprintf "Users '%s' are" (String.concat ", " escaped_users)
| false, _ ->
"There're users"
in
Printf.sprintf
"<html><body><h1>Connection Limit Exceeded</h1><p>%s currently \
connected to this console (VM %s). No more connections are allowed \
when limit_console_sessions is enabled.</p></body></html>"
users_text vm_id
in
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I need to get more used to using match instead of if in OCaml. :)
When a VNC console connection is rejected due to the session limit, users want to know which user(s) are currently connected. However, displaying usernames in HTTP error responses may raise privacy concerns in some deployments, so also add a configure to enable/disable the display of the usernames. The main changes are: 1. To contain the active users in the response message, changed the active_connections to record the existing users and use the unique session id to identify them in case multiple connections have the same user name. 2. Use Http_svr.escape to escape html special characters 3. Added `include_console_username_in_error` to enable/disable the display of user names Signed-off-by: Stephen Cheng <stephen.cheng@citrix.com>
846927e to
f55ac2c
Compare
| let f conns = | ||
| Option.bind conns (fun conns -> | ||
| match | ||
| List.filter (fun conn -> conn.session_id <> session_id) conns |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is dropping all entries for a given session_id when a connection finishes. However, it is possible to use the same session_id on multiple connections.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If that is the case, we need to define an unique id for each connection added.
Tested:
Included the currently connected user
rootin the http response message:No user name in the http response message: