From 68a7c68d0c457ed3edb6f8dc42ef06c4e7d8ed09 Mon Sep 17 00:00:00 2001 From: Gang Ji Date: Fri, 13 Dec 2024 17:02:14 +0800 Subject: [PATCH] fixup Signed-off-by: Gang Ji --- ocaml/xapi/repository.ml | 180 ++++++++++++------------------- ocaml/xapi/repository_helpers.ml | 93 ++++++++++------ 2 files changed, 128 insertions(+), 145 deletions(-) diff --git a/ocaml/xapi/repository.ml b/ocaml/xapi/repository.ml index 305960fd56..3a267adebe 100644 --- a/ocaml/xapi/repository.ml +++ b/ocaml/xapi/repository.ml @@ -149,67 +149,67 @@ let get_proxy_params ~__context repo_name = | _ -> ("", "", "") -type client_auth_conf = - | CdnTokenAuthConf (* remote *) of {token: string; token_id: string} - | NoAuth (* bundle *) - | PoolExtHostAuthConf (* remote_pool *) of { - cert: string - ; remote_addr: string - ; username: string - ; password: string - } - -type server_auth_conf = - | DefaultAuth (* remote *) - | NoAuth (* bundle *) - | ServerAuthConf (* remote_pool *) of { - cert: string - ; remote_addr: string - ; remote_port: int - } - let sync ~__context ~self ~token ~token_id ~username ~password = try let repo_name = get_remote_repository_name ~__context ~self in remove_repo_conf_file repo_name ; let origin = Db.Repository.get_origin ~__context ~self in - let local_host = "127.0.0.1" in - let local_port = !Xapi_globs.local_yum_repo_port in - - let ( binary_url - , source_url - , repo_gpgcheck - , client_auth_config - , server_auth_config ) = + + let binary_url, source_url, repo_gpgcheck, client_auth, server_auth = match origin with | `remote -> ( Db.Repository.get_binary_url ~__context ~self , Some (Db.Repository.get_source_url ~__context ~self) , true - , CdnTokenAuthConf {token; token_id} + , (CdnTokenAuth {token_id; token}, "accesstoken") , DefaultAuth ) | `bundle -> let uri = Uri.make ~scheme:"file" ~path:!Xapi_globs.bundle_repository_dir () in - (Uri.to_string uri, None, true, NoAuth, NoAuth) + (Uri.to_string uri, None, true, (NoAuth, ""), NoAuth) | `remote_pool -> - let uri = - Uri.make ~scheme:"http" ~host:local_host - ~port:!Xapi_globs.local_yum_repo_port - ~path:Constants.get_enabled_repository_uri () - in let cert = Db.Repository.get_certificate ~__context ~self in + let repo_binary_url = Db.Repository.get_binary_url ~__context ~self in let remote_addr = - Db.Repository.get_binary_url ~__context ~self - |> Repository_helpers.get_remote_pool_coordinator_ip + repo_binary_url |> Repository_helpers.get_remote_pool_coordinator_ip + in + let verified_rpc = + try + Helpers.make_external_host_verified_rpc ~__context remote_addr + cert + with Xmlrpc_client.Connection_reset -> + raise + (Api_errors.Server_error + ( Api_errors + .update_syncing_remote_pool_coordinator_connection_failed + , [] + ) + ) + in + let session_id = + try + Client.Client.Session.login_with_password ~rpc:verified_rpc + ~uname:username ~pwd:password + ~version:Datamodel_common.api_version_string + ~originator:Xapi_version.xapi_user_agent + with + | Http_client.Http_request_rejected _ | Http_client.Http_error _ -> + raise + (Api_errors.Server_error + ( Api_errors + .update_syncing_remote_pool_coordinator_service_failed + , [] + ) + ) in - ( Uri.to_string uri + let xapi_token = session_id |> Ref.string_of in + ( repo_binary_url , None , false - , PoolExtHostAuthConf {cert; remote_addr; username; password} - , ServerAuthConf + , (PoolExtHostAuth {xapi_token}, "xapitoken") + , StunnelClientProxyAuth {cert; remote_addr; remote_port= Constants.default_ssl_port} ) in @@ -220,11 +220,10 @@ let sync ~__context ~self ~token ~token_id ~username ~password = | s -> s in - let write_initial_yum_config () = + let write_initial_yum_config ~binary_url = write_yum_config ~source_url ~binary_url ~repo_gpgcheck ~gpgkey_path ~repo_name in - write_initial_yum_config () ; clean_yum_cache repo_name ; (* Remove imported YUM repository GPG key *) if Pkgs.manager = Yum then @@ -243,21 +242,22 @@ let sync ~__context ~self ~token ~token_id ~username ~password = Printf.sprintf "--setopt=%s.%s=%s" repo_name yum_plugin (Uri.make ~scheme:"file" ~path:p () |> Uri.to_string) in - let proxy_url_param, proxy_username_param, proxy_password_param = - get_proxy_params ~__context repo_name + let proxy_params = + let proxy_url_param, proxy_username_param, proxy_password_param + = + get_proxy_params ~__context repo_name + in + [proxy_url_param; proxy_username_param; proxy_password_param] in - let Pkg_mgr.{cmd; params} = - [ - "--save" - ; proxy_url_param - ; proxy_username_param - ; proxy_password_param - ; token_param - ] - |> fun config -> Pkgs.config_repo ~repo_name ~config + let config_repo' params = + let Pkg_mgr.{cmd; params} = + "--save" :: params |> fun config -> + Pkgs.config_repo ~repo_name ~config + in + ignore + (Helpers.call_script ~log_output:Helpers.On_failure cmd params) in - ignore - (Helpers.call_script ~log_output:Helpers.On_failure cmd params) + config_repo' (token_param :: proxy_params) | None -> () in @@ -276,73 +276,25 @@ let sync ~__context ~self ~token ~token_id ~username ~password = ignore (Helpers.call_script cmd params) in - let server_auth conf f = - match conf with - | DefaultAuth | NoAuth -> - f () - | ServerAuthConf {cert; remote_addr; remote_port} -> - let ( let@ ) f x = f x in - let@ temp_file = - Helpers.with_temp_file_of_content "external-host-cert-" ".pem" - cert - in - Stunnel.with_client_proxy - ~verify_cert:(Stunnel_client.external_host temp_file) - ~remote_host:remote_addr ~remote_port ~local_host ~local_port - @@ fun () -> f () - in - - let auth = - match client_auth_config with - | CdnTokenAuthConf {token; token_id} -> - Some (CdnTokenAuth (token_id, token), "accesstoken") - | PoolExtHostAuthConf {cert; remote_addr; username; password} -> - let verified_rpc = - try - Helpers.make_external_host_verified_rpc ~__context remote_addr - cert - with Xmlrpc_client.Connection_reset -> - raise - (Api_errors.Server_error - ( Api_errors - .update_syncing_remote_pool_coordinator_connection_failed - , [] - ) - ) - in - let session_id = - try - Client.Client.Session.login_with_password ~rpc:verified_rpc - ~uname:username ~pwd:password - ~version:Datamodel_common.api_version_string - ~originator:Xapi_version.xapi_user_agent - with - | Http_client.Http_request_rejected _ | Http_client.Http_error _ - -> - raise - (Api_errors.Server_error - ( Api_errors - .update_syncing_remote_pool_coordinator_service_failed - , [] - ) - ) - in - let xapi_token = session_id |> Ref.string_of in - Some (ExtHostAuth xapi_token, "xapitoken") - | NoAuth -> - None - in - - with_sync_client_auth auth @@ fun yum_conf -> + with_sync_client_auth client_auth @@ fun yum_conf -> + with_sync_server_auth server_auth @@ fun binary_url' -> + write_initial_yum_config + ~binary_url:(Option.value binary_url' ~default:binary_url) ; config_repo yum_conf ; - server_auth server_auth_config @@ fun () -> make_cache () ; sync_repo () + make_cache () ; + sync_repo () ) (fun () -> (* Rewrite repo conf file as initial content to remove credential * related info, I.E. proxy username/password and temporary token file * path. + * One thing to note: for remote_repo, the binary_url used to + * re-initial yum repo is the url configed in the remote_pool repo, + * which is not the correct one for stunnel client proxy, while as we + * will always write_initial_yum_config every time before syncing repo, + * this should be ok. *) - write_initial_yum_config () + write_initial_yum_config ~binary_url ) ; (* The custom yum-utils will fully download repository metadata including * the repo gpg signature. diff --git a/ocaml/xapi/repository_helpers.ml b/ocaml/xapi/repository_helpers.ml index 05e052cf1a..fc8fce5453 100644 --- a/ocaml/xapi/repository_helpers.ml +++ b/ocaml/xapi/repository_helpers.ml @@ -1288,42 +1288,73 @@ let get_single_enabled_update_repository ~__context = in get_singleton enabled_update_repositories -type client_auth = ExtHostAuth of string | CdnTokenAuth of string * string +type client_auth = + | CdnTokenAuth (* remote *) of {token_id: string; token: string} + | NoAuth (* bundle *) + | PoolExtHostAuth (* remote_pool *) of {xapi_token: string} let with_sync_client_auth auth f = + let go_with_client_plugin cred plugin = + let ( let@ ) g x = g x in + let@ temp_file = + Helpers.with_temp_file_of_content ~mode:[Open_text] "token-" ".json" cred + in + f (Some (temp_file, plugin)) + in match auth with - | Some (client_auth, yum_plugin) -> ( - let secret = - match client_auth with - | ExtHostAuth session -> - Some (`Assoc [("xapitoken", `String session)]) - | CdnTokenAuth (token_id, token) when token_id = "" && token = "" -> - None - | CdnTokenAuth (token_id, token) when token_id <> "" && token <> "" -> - Some - (`Assoc [("token", `String token); ("token_id", `String token_id)]) - | CdnTokenAuth (token_id, _) -> - let msg = - if token_id = "" then - Printf.sprintf "%s: The token_id is empty" __LOC__ - else - Printf.sprintf "%s: The token is empty" __LOC__ - in - raise Api_errors.(Server_error (cdn_token_invalid, [msg])) + | CdnTokenAuth {token_id; token}, plugin when token_id = "" && token = "" -> + f (Some ("", plugin)) + | CdnTokenAuth {token_id; token}, plugin when token_id <> "" && token <> "" -> + let cred = + `Assoc [("token", `String token); ("token_id", `String token_id)] + |> Yojson.Basic.to_string in - match secret with - | None -> - f (Some ("", yum_plugin)) - | Some s -> - let ( let@ ) f x = f x in - let@ temp_file = - Helpers.with_temp_file_of_content ~mode:[Open_text] "token-" ".json" - (Yojson.Basic.to_string s) - in - f (Some (temp_file, yum_plugin)) - ) - | None -> + go_with_client_plugin cred plugin + | CdnTokenAuth {token_id; _}, _ -> + let msg = + if token_id = "" then + Printf.sprintf "%s: The token_id is empty" __LOC__ + else + Printf.sprintf "%s: The token is empty" __LOC__ + in + raise Api_errors.(Server_error (cdn_token_invalid, [msg])) + | PoolExtHostAuth {xapi_token}, plugin -> + let cred = + `Assoc [("xapitoken", `String xapi_token)] |> Yojson.Basic.to_string + in + go_with_client_plugin cred plugin + | NoAuth, _ -> + f None + +type server_auth = + | DefaultAuth (* remote *) + | NoAuth (* bundle *) + | StunnelClientProxyAuth (* remote_pool *) of { + cert: string + ; remote_addr: string + ; remote_port: int + } + +let with_sync_server_auth auth f = + match auth with + | DefaultAuth | NoAuth -> f None + | StunnelClientProxyAuth {cert; remote_addr; remote_port} -> + let local_host = "127.0.0.1" in + let local_port = !Xapi_globs.local_yum_repo_port in + let ( let@ ) f x = f x in + let@ temp_file = + Helpers.with_temp_file_of_content "external-host-cert-" ".pem" cert + in + let binary_url = + Uri.make ~scheme:"http" ~host:local_host ~port:local_port + ~path:Constants.get_enabled_repository_uri () + |> Uri.to_string + in + Stunnel.with_client_proxy + ~verify_cert:(Stunnel_client.external_host temp_file) + ~remote_host:remote_addr ~remote_port ~local_host ~local_port + @@ fun () -> f (Some binary_url) let prune_updateinfo_for_livepatches latest_lps updateinfo = let livepatches =