@@ -2672,26 +2672,47 @@ let with_temp_file_contents ~contents f =
26722672 )
26732673 (fun () -> Sys. remove filename)
26742674
2675- let write_uefi_certificates_to_disk ~__context ~host :_ =
2676- if
2677- Sys. file_exists ! Xapi_globs. varstore_dir
2678- && Sys. is_directory ! Xapi_globs. varstore_dir
2679- then
2680- match
2681- Base64. decode
2682- (Db.Pool. get_uefi_certificates ~__context
2683- ~self: (Helpers. get_pool ~__context)
2684- )
2685- with
2675+ let ( let@ ) f x = f x
2676+
2677+ let ( // ) = Filename. concat
2678+
2679+ let really_read_uefi_certificates_from_disk ~__context ~host :_ from_path =
2680+ let certs_files = Sys. readdir from_path |> Array. map (( // ) from_path) in
2681+ let @ temp_file, with_temp_out_ch =
2682+ Helpers. with_temp_out_ch_of_temp_file ~mode: [Open_binary ]
2683+ " pool-uefi-certificates" " tar"
2684+ in
2685+ if Array. length certs_files > 0 then (
2686+ let @ temp_out_ch = with_temp_out_ch in
2687+ Tar_unix.Archive. create
2688+ (certs_files |> Array. to_list)
2689+ (temp_out_ch |> Unix. descr_of_out_channel) ;
2690+ debug " UEFI tar file %s populated from directory %s" temp_file from_path
2691+ ) else
2692+ debug " UEFI tar file %s empty from directory %s" temp_file from_path ;
2693+ temp_file |> Unixext. string_of_file |> Base64. encode_string
2694+
2695+ let really_write_uefi_certificates_to_disk ~__context ~host :_ ~value =
2696+ match value with
2697+ | "" ->
2698+ (* from an existing directory *)
2699+ Sys. readdir ! Xapi_globs. default_auth_dir
2700+ |> Array. iter (fun file ->
2701+ let src = ! Xapi_globs. default_auth_dir // file in
2702+ let dst = ! Xapi_globs. varstore_dir // file in
2703+ let @ src_fd = Unixext. with_file src [Unix. O_RDONLY ] 0o400 in
2704+ let @ dst_fd =
2705+ Unixext. with_file dst
2706+ [Unix. O_WRONLY ; Unix. O_CREAT ; Unix. O_TRUNC ]
2707+ 0o644
2708+ in
2709+ debug " override_uefi_certs: copy_file %s->%s" src dst ;
2710+ ignore (Unixext. copy_file src_fd dst_fd)
2711+ )
2712+ | base64_value -> (
2713+ (* from an existing base64 tar file *)
2714+ match Base64. decode base64_value with
26862715 | Ok contents ->
2687- (* Remove existing certs before extracting xapi ones
2688- * to avoid a extract override issue. *)
2689- List. iter
2690- (fun name ->
2691- let path = Filename. concat ! Xapi_globs. varstore_dir name in
2692- Unixext. unlink_safe path
2693- )
2694- [" KEK.auth" ; " db.auth" ] ;
26952716 (* No uefi certificates, nothing to do. *)
26962717 if contents <> " " then (
26972718 with_temp_file_contents ~contents
@@ -2702,14 +2723,75 @@ let write_uefi_certificates_to_disk ~__context ~host:_ =
27022723 | Error _ ->
27032724 debug
27042725 " UEFI tar file was not extracted: it was not base64-encoded correctly"
2726+ )
2727+
2728+ let write_uefi_certificates_to_disk ~__context ~host =
2729+ let with_valid_symlink ~from_path ~to_path fn =
2730+ debug " override_uefi_certs: with_valid_symlink %s->%s" from_path to_path ;
2731+ if Helpers.FileSys. realpathm from_path <> to_path then (
2732+ Helpers.FileSys. rmrf ~rm_top: true from_path ;
2733+ Unix. symlink to_path from_path
2734+ ) ;
2735+ fn from_path
2736+ in
2737+ let with_empty_dir path fn =
2738+ debug " override_uefi_certs: with_empty_dir %s" path ;
2739+ Helpers.FileSys. rmrf ~rm_top: false path ;
2740+ Unixext. mkdir_rec path 0o755 ;
2741+ fn path
2742+ in
2743+ let check_valid_uefi_certs_in path =
2744+ let uefi_certs_in_disk = path |> Helpers.FileSys. realpathm |> Sys. readdir in
2745+ (* check expected uefi certificates are present *)
2746+ [" KEK.auth" ; " db.auth" ]
2747+ |> List. iter (fun cert ->
2748+ let log_of found =
2749+ (if found then info else error)
2750+ " check_valid_uefi_certs: %s %s in %s"
2751+ (if found then " found" else " missing" )
2752+ cert path
2753+ in
2754+ uefi_certs_in_disk |> Array. mem cert |> log_of
2755+ )
2756+ in
2757+ match ! Xapi_globs. override_uefi_certs with
2758+ | false ->
2759+ let @ path =
2760+ with_valid_symlink ~from_path: ! Xapi_globs. varstore_dir
2761+ ~to_path: ! Xapi_globs. default_auth_dir
2762+ in
2763+ check_valid_uefi_certs_in path ;
2764+ if Pool_role. is_master () then
2765+ let disk_uefi_certs_tar =
2766+ really_read_uefi_certificates_from_disk ~__context ~host
2767+ ! Xapi_globs. varstore_dir
2768+ in
2769+ (* synchronize read-only field with contents in disk *)
2770+ Db.Pool. set_uefi_certificates ~__context
2771+ ~self: (Helpers. get_pool ~__context)
2772+ ~value: disk_uefi_certs_tar
2773+ | true ->
2774+ let @ path = with_empty_dir ! Xapi_globs. varstore_dir in
2775+ (* get from pool for consistent results across hosts *)
2776+ let pool_uefi_certs =
2777+ Db.Pool. get_uefi_certificates ~__context
2778+ ~self: (Helpers. get_pool ~__context)
2779+ in
2780+ really_write_uefi_certificates_to_disk ~__context ~host
2781+ ~value: pool_uefi_certs ;
2782+ check_valid_uefi_certs_in path
27052783
27062784let set_uefi_certificates ~__context ~host ~value =
2707- Db.Host. set_uefi_certificates ~__context ~self: host ~value ;
2708- Helpers. call_api_functions ~__context (fun rpc session_id ->
2709- Client.Client.Pool. set_uefi_certificates ~rpc ~session_id
2710- ~self: (Helpers. get_pool ~__context)
2711- ~value
2712- )
2785+ match ! Xapi_globs. override_uefi_certs with
2786+ | false ->
2787+ raise Api_errors. (Server_error (Api_errors. operation_not_allowed, [" " ]))
2788+ | true ->
2789+ Db.Host. set_uefi_certificates ~__context ~self: host ~value ;
2790+ Helpers. call_api_functions ~__context (fun rpc session_id ->
2791+ Client.Client.Pool. set_uefi_certificates ~rpc ~session_id
2792+ ~self: (Helpers. get_pool ~__context)
2793+ ~value
2794+ )
27132795
27142796let set_iscsi_iqn ~__context ~host ~value =
27152797 if value = " " then
0 commit comments