Skip to content

Commit e17315c

Browse files
authored
CP-311257: Raise proper error code (#6963)
2 parents f383999 + da6c8bf commit e17315c

10 files changed

Lines changed: 91 additions & 67 deletions

File tree

ocaml/idl/datamodel_errors.ml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -734,7 +734,9 @@ let _ =
734734
error Api_errors.auth_unknown_type ["type"]
735735
~doc:"Unknown type of external authentication." () ;
736736
error Api_errors.auth_is_disabled []
737-
~doc:"External authentication is disabled, unable to resolve subject name."
737+
~doc:"External authentication is disabled" () ;
738+
error Api_errors.auth_invalid_certs ["message"]
739+
~doc:"The certificates are invalid to setup TLS connection to Windows AD."
738740
() ;
739741
error Api_errors.auth_enable_failed ["message"]
740742
~doc:"The host failed to enable external authentication." () ;
@@ -750,6 +752,8 @@ let _ =
750752
~doc:"The host failed to enable external authentication." () ;
751753
error Api_errors.auth_enable_failed_invalid_account ["message"]
752754
~doc:"The host failed to enable external authentication." () ;
755+
error Api_errors.auth_enable_failed_invalid_certs ["message"]
756+
~doc:"The host failed to enable external authentication." () ;
753757
error Api_errors.auth_disable_failed ["message"]
754758
~doc:"The host failed to disable external authentication." () ;
755759
error Api_errors.auth_disable_failed_wrong_credentials ["message"]
@@ -839,7 +843,9 @@ let _ =
839843
~doc:"The pool failed to enable external authentication." () ;
840844
error Api_errors.pool_auth_enable_failed_invalid_account ["host"; "message"]
841845
~doc:"The pool failed to enable external authentication." () ;
842-
error Api_errors.pool_auth_set_ldaps_failed ["host"; "message"]
846+
error Api_errors.pool_auth_enable_failed_invalid_certs ["host"; "message"]
847+
~doc:"The pool failed to enable external authentication." () ;
848+
error Api_errors.auth_set_ldaps_failed ["host"; "message"]
843849
~doc:"The pool failed to set LDAPS configuration." () ;
844850
error Api_errors.pool_auth_disable_failed ["host"; "message"]
845851
~doc:

ocaml/libs/xapi-stdext/lib/xapi-stdext-std/listext.ml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,16 @@ module List = struct
100100
in
101101
loop [] l
102102

103+
let try_map_any f l =
104+
let rec loop errs = function
105+
| [] ->
106+
Error (List.rev errs)
107+
| x :: xs -> (
108+
match f x with Ok _ as ok -> ok | Error e -> loop (e :: errs) xs
109+
)
110+
in
111+
loop [] l
112+
103113
let take n list =
104114
let rec loop i acc = function
105115
| x :: xs when i < n ->

ocaml/libs/xapi-stdext/lib/xapi-stdext-std/listext.mli

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ module List : sig
5050
the [Ok] results, and the first [Error] result encountered, if it is
5151
encountered. *)
5252

53+
val try_map_any : ('a -> ('b, 'c) result) -> 'a list -> ('b, 'c list) result
54+
(** [try_map_any f l] applies [f] to elements of [l] in turn. Returns the
55+
first [Ok] result encountered or, if all elements produce errors, returns
56+
all the [Error] results in a list. *)
57+
5358
val rev_mapi : (int -> 'a -> 'b) -> 'a list -> 'b list
5459
(** [rev_map f l] gives the same result as {!Stdlib.List.rev}[ (]
5560
{!Stdlib.List.mapi}[ f l)], but is tail-recursive and more efficient. *)

ocaml/tests/test_extauth_plugin_ADwinbind.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ module Errtag = Generic.MakeStateless (struct
9090
"E_INVALID_OU"
9191
| E_INVALID_ACCOUNT ->
9292
"E_INVALID_ACCOUNT"
93+
| E_INVALID_CERTS ->
94+
"E_INVALID_CERTS"
9395
end
9496

9597
let transform = Extauth_plugin_ADwinbind.tag_from_err_msg

ocaml/xapi-consts/api_errors.ml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1023,6 +1023,8 @@ let auth_unknown_type = add_error "AUTH_UNKNOWN_TYPE"
10231023

10241024
let auth_is_disabled = add_error "AUTH_IS_DISABLED"
10251025

1026+
let auth_invalid_certs = add_error "AUTH_INVALID_CERTS"
1027+
10261028
let auth_suffix_wrong_credentials = "_WRONG_CREDENTIALS"
10271029

10281030
let auth_suffix_permission_denied = "_PERMISSION_DENIED"
@@ -1035,6 +1037,8 @@ let auth_suffix_invalid_ou = "_INVALID_OU"
10351037

10361038
let auth_suffix_invalid_account = "_INVALID_ACCOUNT"
10371039

1040+
let auth_suffix_invalid_certs = "_INVALID_CERTS"
1041+
10381042
let auth_enable_failed = add_error "AUTH_ENABLE_FAILED"
10391043

10401044
let auth_enable_failed_wrong_credentials =
@@ -1055,6 +1059,9 @@ let auth_enable_failed_invalid_ou =
10551059
let auth_enable_failed_invalid_account =
10561060
add_error $ auth_enable_failed ^ auth_suffix_invalid_account
10571061

1062+
let auth_enable_failed_invalid_certs =
1063+
add_error $ auth_enable_failed ^ auth_suffix_invalid_certs
1064+
10581065
let auth_disable_failed = add_error "AUTH_DISABLE_FAILED"
10591066

10601067
let auth_disable_failed_wrong_credentials =
@@ -1087,10 +1094,13 @@ let pool_auth_enable_failed_invalid_ou =
10871094
let pool_auth_enable_failed_invalid_account =
10881095
add_error $ pool_auth_enable_failed ^ auth_suffix_invalid_account
10891096

1097+
let pool_auth_enable_failed_invalid_certs =
1098+
add_error $ pool_auth_enable_failed ^ auth_suffix_invalid_certs
1099+
10901100
let pool_auth_enable_failed_duplicate_hostname =
10911101
add_error $ pool_auth_enable_failed ^ "_DUPLICATE_HOSTNAME"
10921102

1093-
let pool_auth_set_ldaps_failed = add_error "POOL_AUTH_SET_LDAPS_FAILED"
1103+
let auth_set_ldaps_failed = add_error "AUTH_SET_LDAPS_FAILED"
10941104

10951105
let pool_auth_disable_failed =
10961106
add_error $ pool_auth_prefix ^ auth_disable_failed

ocaml/xapi/auth_signature.ml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ type auth_service_error_tag =
3131
| E_UNAVAILABLE
3232
| E_INVALID_OU
3333
| E_INVALID_ACCOUNT
34+
| E_INVALID_CERTS
3435

3536
exception Auth_service_error of auth_service_error_tag * string
3637

@@ -52,6 +53,8 @@ let suffix_of_tag errtag =
5253
Api_errors.auth_suffix_invalid_ou
5354
| E_INVALID_ACCOUNT ->
5455
Api_errors.auth_suffix_invalid_account
56+
| E_INVALID_CERTS ->
57+
Api_errors.auth_suffix_invalid_certs
5558

5659
(* required fields in subject.other_config *)
5760
let subject_information_field_subject_name = "subject-name"

ocaml/xapi/extauth.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,8 @@ let call_with_exception_handler fn =
203203
raise (Api_errors.Server_error (Api_errors.auth_unknown_type, [msg]))
204204
| Not_found | Auth_signature.Subject_cannot_be_resolved ->
205205
raise (Api_errors.Server_error (Api_errors.subject_cannot_be_resolved, []))
206+
| Auth_signature.Auth_service_error (E_INVALID_CERTS, msg) ->
207+
raise (Api_errors.Server_error (Api_errors.auth_invalid_certs, [msg]))
206208
| Auth_signature.Auth_service_error (_, msg) ->
207209
raise (Api_errors.Server_error (Api_errors.auth_service_error, [msg]))
208210
| e ->

ocaml/xapi/extauth_plugin_ADwinbind.ml

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ end)
2222
open D
2323
open Xapi_stdext_std.Xstringext
2424
open Auth_signature
25+
module Listext = Xapi_stdext_std.Listext
2526
module Scheduler = Xapi_stdext_threads_scheduler.Scheduler
2627

2728
let finally = Xapi_stdext_pervasives.Pervasiveext.finally
@@ -81,9 +82,13 @@ let debug_level () =
8182
|> string_of_int
8283

8384
let err_msg_to_tag_map =
85+
let open Auth_signature in
8486
[
85-
("not a properly formed account name", Auth_signature.E_INVALID_ACCOUNT)
86-
; ("bad username or authentication", Auth_signature.E_CREDENTIALS)
87+
("not a properly formed account name", E_INVALID_ACCOUNT)
88+
; ("bad username or authentication", E_CREDENTIALS)
89+
; ( "Windows cannot verify the digital signature for this file"
90+
, E_INVALID_CERTS
91+
)
8792
(* Some other errors *)
8893
]
8994

@@ -265,6 +270,12 @@ let tag_from_err_msg msg =
265270
| None ->
266271
Auth_signature.E_GENERIC
267272

273+
let auth_ex_of_msg errmsg fmt =
274+
let tag = tag_from_err_msg errmsg in
275+
Printf.ksprintf
276+
(fun msg -> Auth_signature.(Auth_service_error (tag, msg)))
277+
fmt
278+
268279
let update_extauth_configuration ~__context ~k ~v =
269280
let self = Helpers.get_localhost ~__context in
270281
Db.Host.get_external_auth_configuration ~__context ~self |> fun value ->
@@ -549,24 +560,25 @@ module Ldap = struct
549560
|> Xapi_cmd_result.of_output ~sep:':' ~key
550561
|> fun x -> Ok x
551562
with
552-
| Forkhelpers.Spawn_internal_error (_, stdout, _) ->
553-
Error (generic_ex "Ldap query sid failed: %s" stdout)
563+
| Forkhelpers.Spawn_internal_error (err, out, _) ->
564+
Error
565+
(auth_ex_of_msg err "Failed to do ldap(s) query for %s %s" name out)
554566
| Not_found ->
555567
Error (generic_ex "%s not found in ldap result" key)
556568
| _ ->
557569
Error (generic_ex "Failed to lookup sid from username %s" name)
558570

559571
let ping_domain domain =
560-
match
561-
kdcs_of_domain domain
562-
|> List.find_opt (fun kdc ->
563-
query_sid ~name:krbtgt ~kdc:(KDC.server kdc) |> Result.is_ok
572+
kdcs_of_domain domain
573+
|> Listext.List.try_map_any (fun kdc ->
574+
query_sid ~name:krbtgt ~kdc:(KDC.server kdc)
575+
)
576+
|> Result.map_error (function
577+
| e :: _ ->
578+
e
579+
| [] ->
580+
generic_ex "Failed to ping domain %s" domain
564581
)
565-
with
566-
| Some _ ->
567-
Ok ()
568-
| None ->
569-
Error (generic_ex "Failed to ping domain %s: all kdcs failed" domain)
570582
end
571583

572584
module Wbinfo = struct
@@ -1161,24 +1173,22 @@ let set_ldaps ~__context ~ldaps ~force =
11611173
if old_domain_info.ldaps = Some ldaps && not force then
11621174
raise (generic_ex "ldaps is already %s" (string_of_bool ldaps)) ;
11631175

1176+
(* check certificate exists *)
11641177
let new_domain_info = {old_domain_info with ldaps= Some ldaps} in
11651178
(* Apply new configuration to winbind daemon for trial *)
11661179
Winbind.configure ~__context ~domain_info:new_domain_info () ;
11671180
(* Verify the new LDAP(S) setting works *)
11681181
match Ldap.ping_domain new_domain_info.service_name with
1169-
| Ok () ->
1182+
| Ok _ ->
11701183
(* Ping succeeded, persist the new domain_info *)
1184+
debug "%s ping domain succeed" __FUNCTION__ ;
11711185
DomainInfo.to_db ~__context ~domain_info:(Some new_domain_info)
11721186
| Error e ->
11731187
(* Ping failed, restore the old configuration *)
11741188
Winbind.configure ~__context ~domain_info:old_domain_info () ;
1175-
raise
1176-
(generic_ex
1177-
"ldap(s) verification failed for domain %s: %s, restored old \
1178-
configuration"
1179-
new_domain_info.service_name
1180-
(ExnHelper.string_of_exn e)
1181-
)
1189+
debug "%s ldap(s) verification failed, restored old configure"
1190+
__FUNCTION__ ;
1191+
raise e
11821192

11831193
module RotateMachinePassword = struct
11841194
let task_name = "Rotating machine password"

ocaml/xapi/xapi_host.ml

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1981,16 +1981,18 @@ let disable_external_auth ~__context ~host ~config ~force =
19811981
~force ()
19821982

19831983
(* Enable or disable LDAPS for external authentication on a host *)
1984-
let external_auth_set_ldaps ~__context ~host:_ ~ldaps ~force =
1985-
let assert_can_set_ldaps () =
1986-
(* Host level check *)
1987-
let assert_certs () = () in
1988-
assert_certs ()
1984+
let external_auth_set_ldaps ~__context ~host ~ldaps ~force =
1985+
let open Api_errors in
1986+
let auth_error_to_set_ldaps_error f =
1987+
try f ()
1988+
with Server_error (code, params) when code = auth_service_error ->
1989+
raise (Server_error (auth_set_ldaps_failed, Ref.string_of host :: params))
19891990
in
19901991

19911992
(* Just dispatch to the backend *)
19921993
with_lock serialize_host_enable_disable_extauth @@ fun () ->
1993-
assert_can_set_ldaps () ;
1994+
auth_error_to_set_ldaps_error @@ fun () ->
1995+
Extauth.call_with_exception_handler @@ fun () ->
19941996
(Ext_auth.d ()).set_ldaps ~__context ~ldaps ~force
19951997

19961998
module Static_vdis_list = Xapi_database.Static_vdis_list

ocaml/xapi/xapi_pool.ml

Lines changed: 11 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -3117,7 +3117,7 @@ let disable_external_auth ~__context ~pool:_ ~config =
31173117
)
31183118
)
31193119

3120-
(* Set or unset ldaps for external authentication on all hosts in the pool *)
3120+
(* Enable or disable LDAPS for external authentication on all hosts in the pool *)
31213121
let external_auth_set_ldaps ~__context ~pool:_ ~ldaps ~force =
31223122
let host = Helpers.get_master ~__context in
31233123
let current_ldaps =
@@ -3126,46 +3126,19 @@ let external_auth_set_ldaps ~__context ~pool:_ ~ldaps ~force =
31263126
in
31273127

31283128
let hosts = Xapi_pool_helpers.get_master_slaves_list ~__context in
3129-
let assert_can_set_ldaps () =
3130-
(* Pool level check *)
3131-
let assert_ad_enabled () =
3132-
List.find_opt
3133-
(fun host -> not (Helpers.is_ad_enabled ~__context ~host))
3134-
hosts
3135-
|> Option.fold ~none:() ~some:(fun host ->
3136-
let host = Ref.string_of host in
3137-
raise Api_errors.(Server_error (auth_is_disabled, [host]))
3138-
)
3139-
in
3140-
assert_ad_enabled ()
3141-
in
31423129
let set_ldap_on host =
31433130
try
31443131
call_fn_on_host ~__context
31453132
(Client.Host.external_auth_set_ldaps ~ldaps ~force)
31463133
host ;
31473134
Ok host
3148-
with
3149-
| Api_errors.Server_error (_, [host_msg]) ->
3150-
let msg = Printf.sprintf "%s: %s" (Ref.string_of host) host_msg in
3151-
debug "%s failed to set ldaps for host %s" __FUNCTION__ msg ;
3152-
Error (host, msg)
3153-
| e ->
3154-
let msg =
3155-
Printf.sprintf "%s: %s" (Ref.string_of host)
3156-
(ExnHelper.string_of_exn e)
3157-
in
3158-
debug "%s failed to set ldaps for host %s" __FUNCTION__ msg ;
3159-
Error (host, msg)
3135+
with e ->
3136+
debug "%s failed to set ldaps for host %s: %s" __FUNCTION__
3137+
(Ref.string_of host)
3138+
(ExnHelper.string_of_exn e) ;
3139+
Error (host, e)
31603140
in
31613141
with_lock Xapi_globs.serialize_pool_enable_disable_extauth @@ fun () ->
3162-
assert_can_set_ldaps () ;
3163-
let raise_failed host msg =
3164-
raise
3165-
Api_errors.(
3166-
Server_error (pool_auth_set_ldaps_failed, [Ref.string_of host; msg])
3167-
)
3168-
in
31693142
let revert host =
31703143
try
31713144
call_fn_on_host ~__context
@@ -3175,13 +3148,14 @@ let external_auth_set_ldaps ~__context ~pool:_ ~ldaps ~force =
31753148
warn "Failed to revert ldaps on host %s: %s" (Ref.string_of host)
31763149
(ExnHelper.string_of_exn e)
31773150
in
3151+
(* Set ldaps to host and host will perform the necessary checks *)
31783152
match Listext.List.try_map_collect set_ldap_on hosts with
31793153
| Ok _ ->
31803154
debug "%s succeed to set pool ldaps to %b" __FUNCTION__ ldaps
3181-
| Error (_, (host, msg)) when current_ldaps = ldaps ->
3182-
raise_failed host msg
3183-
| Error (hs, (host, msg)) ->
3184-
List.iter revert hs ; raise_failed host msg
3155+
| Error (_, (_, e)) when current_ldaps = ldaps ->
3156+
raise e
3157+
| Error (hs, (_, e)) ->
3158+
List.iter revert hs ; raise e
31853159

31863160
(* CA-24856: detect non-homogeneous external-authentication config in pool *)
31873161
let detect_nonhomogeneous_external_auth_in_pool ~__context =

0 commit comments

Comments
 (0)