Skip to content

Commit

Permalink
fixup
Browse files Browse the repository at this point in the history
Signed-off-by: Gang Ji <[email protected]>
  • Loading branch information
gangj committed Dec 13, 2024
1 parent 63c06fe commit 1298e2b
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 162 deletions.
2 changes: 0 additions & 2 deletions ocaml/idl/datamodel_errors.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1903,8 +1903,6 @@ let _ =
~doc:"The base url in the repository is invalid." () ;
error Api_errors.invalid_gpgkey_path ["gpgkey_path"]
~doc:"The GPG public key file name in the repository is invalid." () ;
error Api_errors.cdn_token_invalid ["message"]
~doc:"The provided CDN token or token_id is empty." () ;
error Api_errors.repository_already_exists ["ref"]
~doc:"The repository already exists." () ;
error Api_errors.bundle_repository_already_exists ["ref"]
Expand Down
2 changes: 0 additions & 2 deletions ocaml/xapi-consts/api_errors.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1314,8 +1314,6 @@ let invalid_base_url = add_error "INVALID_BASE_URL"

let invalid_gpgkey_path = add_error "INVALID_GPGKEY_PATH"

let cdn_token_invalid = add_error "CDN_TOKEN_INVALID"

let repository_already_exists = add_error "REPOSITORY_ALREADY_EXISTS"

let bundle_repository_already_exists =
Expand Down
212 changes: 85 additions & 127 deletions ocaml/xapi/repository.ml
Original file line number Diff line number Diff line change
Expand Up @@ -149,67 +149,76 @@ 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 ) =
, use_proxy
, client_auth
, server_auth ) =
match origin with
| `remote ->
let plugin = "accesstoken" in
( Db.Repository.get_binary_url ~__context ~self
, Some (Db.Repository.get_source_url ~__context ~self)
, true
, CdnTokenAuthConf {token; token_id}
, true
, CdnTokenAuth {token_id; token; plugin}
, 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, false, 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
let plugin = "xapitoken" in
( repo_binary_url
, None
, false
, PoolExtHostAuthConf {cert; remote_addr; username; password}
, ServerAuthConf
, true
, PoolExtHostAuth {xapi_token; plugin}
, StunnelClientProxyAuth
{cert; remote_addr; remote_port= Constants.default_ssl_port}
)
in
Expand All @@ -220,46 +229,18 @@ 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
Xapi_stdext_unix.Unixext.rm_rec (get_repo_config repo_name "gpgdir") ;
Xapi_stdext_pervasives.Pervasiveext.finally
(fun () ->
let config_repo yum_conf =
match yum_conf with
| Some (token_path, yum_plugin) ->
(* Configure proxy and token *)
let token_param =
match token_path with
| "" ->
""
| p ->
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
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
in
ignore
(Helpers.call_script ~log_output:Helpers.On_failure cmd params)
| None ->
()
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

let make_cache () =
Expand All @@ -276,73 +257,50 @@ 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
with_sync_client_auth client_auth @@ fun client_auth ->
with_sync_server_auth server_auth @@ fun binary_url' ->
write_initial_yum_config
~binary_url:(Option.value binary_url' ~default:binary_url) ;
clean_yum_cache repo_name ;
(* Remove imported YUM repository GPG key *)
if Pkgs.manager = Yum then
Xapi_stdext_unix.Unixext.rm_rec (get_repo_config repo_name "gpgdir") ;
let auth_params =
match client_auth with
| Some (auth_file, plugin) ->
let token_param =
Printf.sprintf "--setopt=%s.%s=%s" repo_name plugin
(Uri.make ~scheme:"file" ~path:auth_file () |> 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 ()
[token_param]
| None ->
[]
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
, []
)
)
let proxy_params =
match use_proxy with
| true ->
let proxy_url_param, proxy_username_param, proxy_password_param =
get_proxy_params ~__context repo_name
in
let xapi_token = session_id |> Ref.string_of in
Some (ExtHostAuth xapi_token, "xapitoken")
| NoAuth ->
None
[proxy_url_param; proxy_username_param; proxy_password_param]
| false ->
[]
in

with_sync_client_auth auth @@ fun yum_conf ->
config_repo yum_conf ;
server_auth server_auth_config @@ fun () -> make_cache () ; sync_repo ()
config_repo (auth_params @ proxy_params) ;
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.
Expand Down
89 changes: 58 additions & 31 deletions ocaml/xapi/repository_helpers.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1288,43 +1288,70 @@ 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
; plugin: string
}
| NoAuth (* bundle *)
| PoolExtHostAuth (* remote_pool *) of {xapi_token: string; plugin: 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; _} when token_id = "" && token = "" ->
f None
| CdnTokenAuth {token_id; token; plugin} ->
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
| 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 =
let open LivePatch in
Expand Down

0 comments on commit 1298e2b

Please sign in to comment.