From a2084c10a8600114fede9b24a3df6ff2acc93aaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodolphe=20Br=C3=A9ard?= Date: Thu, 16 Feb 2023 18:34:59 +0100 Subject: [PATCH] Bring async to the hooks and the file storage --- acmed/Cargo.toml | 1 + acmed/src/account.rs | 28 +++++++-------- acmed/src/account/storage.rs | 18 +++++----- acmed/src/acme_proto.rs | 25 +++++++++---- acmed/src/acme_proto/account.rs | 20 +++++++---- acmed/src/acme_proto/certificate.rs | 16 ++++----- acmed/src/certificate.rs | 20 ++++++----- acmed/src/config.rs | 6 +++- acmed/src/hooks.rs | 22 ++++++++---- acmed/src/main.rs | 2 +- acmed/src/main_event_loop.rs | 11 +++--- acmed/src/storage.rs | 56 +++++++++++++++-------------- 12 files changed, 134 insertions(+), 91 deletions(-) diff --git a/acmed/Cargo.toml b/acmed/Cargo.toml index b6e72c8..df2fe0a 100644 --- a/acmed/Cargo.toml +++ b/acmed/Cargo.toml @@ -22,6 +22,7 @@ openssl_vendored = ["crypto_openssl", "acme_common/openssl_vendored", "attohttpc [dependencies] acme_common = { path = "../acme_common" } async-lock = "2.6" +async-process = "1.6" attohttpc = { version = "0.24", default-features = false, features = ["charsets", "json"] } bincode = "1.3" clap = { version = "4.0", features = ["string"] } diff --git a/acmed/src/account.rs b/acmed/src/account.rs index 5582807..a8f3f29 100644 --- a/acmed/src/account.rs +++ b/acmed/src/account.rs @@ -151,7 +151,7 @@ impl Account { Err("key not found".into()) } - pub fn load( + pub async fn load( file_manager: &FileManager, name: &str, contacts: &[(String, String)], @@ -172,9 +172,9 @@ impl Account { None => key_type.get_default_signature_alg(), }; key_type.check_alg_compatibility(&signature_algorithm)?; - let account = match storage::fetch(file_manager, name)? { + let account = match storage::fetch(file_manager, name).await? { Some(mut a) => { - a.update_keys(key_type, signature_algorithm)?; + a.update_keys(key_type, signature_algorithm).await?; a.contacts = contacts; a.external_account = external_account.to_owned(); a @@ -202,7 +202,7 @@ impl Account { .or_insert_with(AccountEndpoint::new); } - pub fn synchronize(&mut self, endpoint: &mut Endpoint) -> Result<(), Error> { + pub async fn synchronize(&mut self, endpoint: &mut Endpoint) -> Result<(), Error> { let acc_ep = self.get_endpoint(&endpoint.name)?; if !acc_ep.account_url.is_empty() { if let Some(ec) = &self.external_account { @@ -213,7 +213,7 @@ impl Account { &endpoint.name ); self.info(&msg); - register_account(endpoint, self)?; + register_account(endpoint, self).await?; return Ok(()); } } @@ -222,23 +222,23 @@ impl Account { let contacts_changed = ct_hash != acc_ep.contacts_hash; let key_changed = key_hash != acc_ep.key_hash; if contacts_changed { - update_account_contacts(endpoint, self)?; + update_account_contacts(endpoint, self).await?; } if key_changed { - update_account_key(endpoint, self)?; + update_account_key(endpoint, self).await?; } } else { - register_account(endpoint, self)?; + register_account(endpoint, self).await?; } Ok(()) } - pub fn register(&mut self, endpoint: &mut Endpoint) -> Result<(), Error> { - register_account(endpoint, self) + pub async fn register(&mut self, endpoint: &mut Endpoint) -> Result<(), Error> { + register_account(endpoint, self).await } - pub fn save(&self) -> Result<(), Error> { - storage::save(&self.file_manager, self) + pub async fn save(&self) -> Result<(), Error> { + storage::save(&self.file_manager, self).await } pub fn set_account_url(&mut self, endpoint_name: &str, account_url: &str) -> Result<(), Error> { @@ -276,7 +276,7 @@ impl Account { Ok(()) } - fn update_keys( + async fn update_keys( &mut self, key_type: KeyType, signature_algorithm: JwsSignatureAlgorithm, @@ -287,7 +287,7 @@ impl Account { self.debug("account key has been changed in the configuration, creating a new one..."); self.past_keys.push(self.current_key.to_owned()); self.current_key = AccountKey::new(key_type, signature_algorithm)?; - self.save()?; + self.save().await?; let msg = format!("new {key_type} account key created, using {signature_algorithm} as signing algorithm"); self.info(&msg); } else { diff --git a/acmed/src/account/storage.rs b/acmed/src/account/storage.rs index 226a7dc..d3f045f 100644 --- a/acmed/src/account/storage.rs +++ b/acmed/src/account/storage.rs @@ -101,9 +101,9 @@ struct AccountStorage { external_account: Option, } -fn do_fetch(file_manager: &FileManager, name: &str) -> Result, Error> { +async fn do_fetch(file_manager: &FileManager, name: &str) -> Result, Error> { if account_files_exists(file_manager) { - let data = get_account_data(file_manager)?; + let data = get_account_data(file_manager).await?; let obj: AccountStorage = bincode::deserialize(&data[..]) .map_err(|e| Error::from(&e.to_string()).prefix(name))?; let endpoints = obj @@ -140,7 +140,7 @@ fn do_fetch(file_manager: &FileManager, name: &str) -> Result, E } } -fn do_save(file_manager: &FileManager, account: &Account) -> Result<(), Error> { +async fn do_save(file_manager: &FileManager, account: &Account) -> Result<(), Error> { let endpoints: HashMap = account .endpoints .iter() @@ -170,15 +170,17 @@ fn do_save(file_manager: &FileManager, account: &Account) -> Result<(), Error> { }; let encoded: Vec = bincode::serialize(&account_storage) .map_err(|e| Error::from(&e.to_string()).prefix(&account.name))?; - set_account_data(file_manager, &encoded) + set_account_data(file_manager, &encoded).await } -pub fn fetch(file_manager: &FileManager, name: &str) -> Result, Error> { - do_fetch(file_manager, name).map_err(|_| { +pub async fn fetch(file_manager: &FileManager, name: &str) -> Result, Error> { + do_fetch(file_manager, name).await.map_err(|_| { format!("account \"{name}\": unable to load account file: file may be corrupted").into() }) } -pub fn save(file_manager: &FileManager, account: &Account) -> Result<(), Error> { - do_save(file_manager, account).map_err(|e| format!("unable to save account file: {e}").into()) +pub async fn save(file_manager: &FileManager, account: &Account) -> Result<(), Error> { + do_save(file_manager, account) + .await + .map_err(|e| format!("unable to save account file: {e}").into()) } diff --git a/acmed/src/acme_proto.rs b/acmed/src/acme_proto.rs index ca04b66..1ddffd7 100644 --- a/acmed/src/acme_proto.rs +++ b/acmed/src/acme_proto.rs @@ -100,7 +100,8 @@ pub async fn request_certificate( account_s .write() .await - .synchronize(&mut *(endpoint_s.write().await))?; + .synchronize(&mut *(endpoint_s.write().await)) + .await?; // Create a new order let mut new_reg = false; @@ -117,10 +118,12 @@ pub async fn request_certificate( } Err(e) => { if !new_reg && e.is_acme_err(AcmeError::AccountDoesNotExist) { + drop(data_builder); account_s .write() .await - .register(&mut *(endpoint_s.write().await))?; + .register(&mut *(endpoint_s.write().await)) + .await?; new_reg = true; } else { return Err(HttpError::in_err(e)); @@ -136,6 +139,7 @@ pub async fn request_certificate( let auth = http::get_authorization(&mut *(endpoint_s.write().await), &data_builder, auth_url) .map_err(HttpError::in_err)?; + drop(data_builder); if let Some(e) = auth.get_error() { cert.warn(&e.prefix("error").message); } @@ -160,7 +164,9 @@ pub async fn request_certificate( let identifier = auth.identifier.value.to_owned(); // Call the challenge hook in order to complete it - let mut data = cert.call_challenge_hooks(&file_name, &proof, &identifier)?; + let mut data = cert + .call_challenge_hooks(&file_name, &proof, &identifier) + .await?; data.0.is_clean_hook = true; hook_datas.push(data); @@ -173,6 +179,7 @@ pub async fn request_certificate( &chall_url, ) .map_err(HttpError::in_err)?; + drop(data_builder); } } @@ -186,8 +193,10 @@ pub async fn request_certificate( auth_url, ) .map_err(HttpError::in_err)?; + drop(data_builder); for (data, hook_type) in hook_datas.iter() { - cert.call_challenge_hooks_clean(data, (*hook_type).to_owned())?; + cert.call_challenge_hooks_clean(data, (*hook_type).to_owned()) + .await?; } hook_datas.clear(); } @@ -203,9 +212,10 @@ pub async fn request_certificate( &order_url, ) .map_err(HttpError::in_err)?; + drop(data_builder); // Finalize the order by sending the CSR - let key_pair = certificate::get_key_pair(cert)?; + let key_pair = certificate::get_key_pair(cert).await?; let domains: Vec = cert .identifiers .iter() @@ -237,6 +247,7 @@ pub async fn request_certificate( &order.finalize, ) .map_err(HttpError::in_err)?; + drop(data_builder); if let Some(e) = order.get_error() { cert.warn(&e.prefix("error").message); } @@ -251,6 +262,7 @@ pub async fn request_certificate( &order_url, ) .map_err(HttpError::in_err)?; + drop(data_builder); // Download the certificate let crt_url = order @@ -259,7 +271,8 @@ pub async fn request_certificate( let data_builder = set_data_builder!(account_s, endpoint_name, b"").await; let crt = http::get_certificate(&mut *(endpoint_s.write().await), &data_builder, &crt_url) .map_err(HttpError::in_err)?; - storage::write_certificate(&cert.file_manager, crt.as_bytes())?; + drop(data_builder); + storage::write_certificate(&cert.file_manager, crt.as_bytes()).await?; cert.info(&format!( "certificate renewed (identifiers: {})", diff --git a/acmed/src/acme_proto/account.rs b/acmed/src/acme_proto/account.rs index a4f52f2..aace673 100644 --- a/acmed/src/acme_proto/account.rs +++ b/acmed/src/acme_proto/account.rs @@ -20,7 +20,7 @@ macro_rules! create_account_if_does_not_exist { $endpoint.name ); $account.debug(&msg); - return register_account($endpoint, $account); + return register_account($endpoint, $account).await; } _ => Err(HttpError::in_err(he.to_owned())), }, @@ -30,7 +30,10 @@ macro_rules! create_account_if_does_not_exist { }; } -pub fn register_account(endpoint: &mut Endpoint, account: &mut BaseAccount) -> Result<(), Error> { +pub async fn register_account( + endpoint: &mut Endpoint, + account: &mut BaseAccount, +) -> Result<(), Error> { account.debug(&format!( "creating account on endpoint \"{}\"...", &endpoint.name @@ -68,7 +71,7 @@ pub fn register_account(endpoint: &mut Endpoint, account: &mut BaseAccount) -> R account.update_key_hash(&endpoint.name)?; account.update_contacts_hash(&endpoint.name)?; account.update_external_account_hash(&endpoint.name)?; - account.save()?; + account.save().await?; account.info(&format!( "account created on endpoint \"{}\"", &endpoint.name @@ -76,7 +79,7 @@ pub fn register_account(endpoint: &mut Endpoint, account: &mut BaseAccount) -> R Ok(()) } -pub fn update_account_contacts( +pub async fn update_account_contacts( endpoint: &mut Endpoint, account: &mut BaseAccount, ) -> Result<(), Error> { @@ -97,14 +100,17 @@ pub fn update_account_contacts( account )?; account.update_contacts_hash(&endpoint_name)?; - account.save()?; + account.save().await?; account.info(&format!( "account contacts updated on endpoint \"{endpoint_name}\"" )); Ok(()) } -pub fn update_account_key(endpoint: &mut Endpoint, account: &mut BaseAccount) -> Result<(), Error> { +pub async fn update_account_key( + endpoint: &mut Endpoint, + account: &mut BaseAccount, +) -> Result<(), Error> { let endpoint_name = endpoint.name.clone(); account.debug(&format!( "updating account key on endpoint \"{endpoint_name}\"..." @@ -139,7 +145,7 @@ pub fn update_account_key(endpoint: &mut Endpoint, account: &mut BaseAccount) -> account )?; account.update_key_hash(&endpoint_name)?; - account.save()?; + account.save().await?; account.info(&format!( "account key updated on endpoint \"{endpoint_name}\"" )); diff --git a/acmed/src/acme_proto/certificate.rs b/acmed/src/acme_proto/certificate.rs index 93cafdc..c7ca47d 100644 --- a/acmed/src/acme_proto/certificate.rs +++ b/acmed/src/acme_proto/certificate.rs @@ -3,23 +3,23 @@ use crate::storage; use acme_common::crypto::{gen_keypair, KeyPair}; use acme_common::error::Error; -fn gen_key_pair(cert: &Certificate) -> Result { +async fn gen_key_pair(cert: &Certificate) -> Result { let key_pair = gen_keypair(cert.key_type)?; - storage::set_keypair(&cert.file_manager, &key_pair)?; + storage::set_keypair(&cert.file_manager, &key_pair).await?; Ok(key_pair) } -fn read_key_pair(cert: &Certificate) -> Result { - storage::get_keypair(&cert.file_manager) +async fn read_key_pair(cert: &Certificate) -> Result { + storage::get_keypair(&cert.file_manager).await } -pub fn get_key_pair(cert: &Certificate) -> Result { +pub async fn get_key_pair(cert: &Certificate) -> Result { if cert.kp_reuse { - match read_key_pair(cert) { + match read_key_pair(cert).await { Ok(key_pair) => Ok(key_pair), - Err(_) => gen_key_pair(cert), + Err(_) => gen_key_pair(cert).await, } } else { - gen_key_pair(cert) + gen_key_pair(cert).await } } diff --git a/acmed/src/certificate.rs b/acmed/src/certificate.rs index 1b0391e..739936a 100644 --- a/acmed/src/certificate.rs +++ b/acmed/src/certificate.rs @@ -110,7 +110,7 @@ impl Certificate { .join(",") } - pub fn should_renew(&self) -> Result { + pub async fn should_renew(&self) -> Result { self.debug(&format!( "checking for renewal (identifiers: {})", self.identifier_list() @@ -119,7 +119,7 @@ impl Certificate { self.debug("certificate does not exist: requesting one"); return Ok(true); } - let cert = get_certificate(&self.file_manager)?; + let cert = get_certificate(&self.file_manager).await?; let renew_ident = self.has_missing_identifiers(&cert); if renew_ident { @@ -139,7 +139,7 @@ impl Certificate { Ok(renew) } - pub fn call_challenge_hooks( + pub async fn call_challenge_hooks( &self, file_name: &str, proof: &str, @@ -165,19 +165,23 @@ impl Certificate { HookType::ChallengeTlsAlpn01Clean, ), }; - hooks::call(self, &self.hooks, &hook_data, hook_type.0)?; + hooks::call(self, &self.hooks, &hook_data, hook_type.0).await?; Ok((hook_data, hook_type.1)) } - pub fn call_challenge_hooks_clean( + pub async fn call_challenge_hooks_clean( &self, data: &ChallengeHookData, hook_type: HookType, ) -> Result<(), Error> { - hooks::call(self, &self.hooks, data, hook_type) + hooks::call(self, &self.hooks, data, hook_type).await } - pub fn call_post_operation_hooks(&self, status: &str, is_success: bool) -> Result<(), Error> { + pub async fn call_post_operation_hooks( + &self, + status: &str, + is_success: bool, + ) -> Result<(), Error> { let identifiers = self .identifiers .iter() @@ -191,7 +195,7 @@ impl Certificate { env: HashMap::new(), }; hook_data.set_env(&self.env); - hooks::call(self, &self.hooks, &hook_data, HookType::PostOperation)?; + hooks::call(self, &self.hooks, &hook_data, HookType::PostOperation).await?; Ok(()) } } diff --git a/acmed/src/config.rs b/acmed/src/config.rs index afa1a80..a1aa52f 100644 --- a/acmed/src/config.rs +++ b/acmed/src/config.rs @@ -381,7 +381,10 @@ impl Account { Ok(lst) } - pub fn to_generic(&self, file_manager: &FileManager) -> Result { + pub async fn to_generic( + &self, + file_manager: &FileManager, + ) -> Result { let contacts: Vec<(String, String)> = self .contacts .iter() @@ -399,6 +402,7 @@ impl Account { &self.signature_algorithm, &external_account, ) + .await } } diff --git a/acmed/src/hooks.rs b/acmed/src/hooks.rs index 675511e..626ef02 100644 --- a/acmed/src/hooks.rs +++ b/acmed/src/hooks.rs @@ -2,6 +2,8 @@ pub use crate::config::HookType; use crate::logs::HasLogger; use crate::template::render_template; use acme_common::error::Error; +use async_process::{Command, Stdio}; +use futures::AsyncWriteExt; use serde::Serialize; use std::collections::hash_map::Iter; use std::collections::{HashMap, HashSet}; @@ -9,7 +11,6 @@ use std::fs::File; use std::io::prelude::*; use std::io::BufReader; use std::path::PathBuf; -use std::process::{Command, Stdio}; use std::{env, fmt}; pub trait HookEnvData { @@ -115,7 +116,7 @@ macro_rules! get_hook_output { }}; } -fn call_single(logger: &L, data: &T, hook: &Hook) -> Result<(), Error> +async fn call_single(logger: &L, data: &T, hook: &Hook) -> Result<(), Error> where L: HasLogger, T: Clone + HookEnvData + Serialize, @@ -161,7 +162,7 @@ where let data_in = render_template(s, &data)?; logger.trace(&format!("hook \"{}\": string stdin: {data_in}", hook.name)); let stdin = cmd.stdin.as_mut().ok_or("stdin not found")?; - stdin.write_all(data_in.as_bytes())?; + stdin.write_all(data_in.as_bytes()).await?; } HookStdin::File(f) => { let file_name = render_template(f, &data)?; @@ -171,13 +172,13 @@ where let buf_reader = BufReader::new(file); for line in buf_reader.lines() { let line = format!("{}\n", line?); - stdin.write_all(line.as_bytes())?; + stdin.write_all(line.as_bytes()).await?; } } HookStdin::None => {} } // TODO: add a timeout - let status = cmd.wait()?; + let status = cmd.status().await?; if !status.success() && !hook.allow_failure { let msg = match status.code() { Some(code) => format!("unrecoverable failure: code {code}").into(), @@ -192,13 +193,20 @@ where Ok(()) } -pub fn call(logger: &L, hooks: &[Hook], data: &T, hook_type: HookType) -> Result<(), Error> +pub async fn call( + logger: &L, + hooks: &[Hook], + data: &T, + hook_type: HookType, +) -> Result<(), Error> where L: HasLogger, T: Clone + HookEnvData + Serialize, { for hook in hooks.iter().filter(|h| h.hook_type.contains(&hook_type)) { - call_single(logger, data, hook).map_err(|e| e.prefix(&hook.name))?; + call_single(logger, data, hook) + .await + .map_err(|e| e.prefix(&hook.name))?; } Ok(()) } diff --git a/acmed/src/main.rs b/acmed/src/main.rs index 8931a63..a933867 100644 --- a/acmed/src/main.rs +++ b/acmed/src/main.rs @@ -168,7 +168,7 @@ async fn inner_main() { init_server(matches.get_flag("foreground"), pid_file); - let mut srv = match MainEventLoop::new(config_file, &root_certs) { + let mut srv = match MainEventLoop::new(config_file, &root_certs).await { Ok(s) => s, Err(e) => { error!("{e}"); diff --git a/acmed/src/main_event_loop.rs b/acmed/src/main_event_loop.rs index cb9f6b6..85456c2 100644 --- a/acmed/src/main_event_loop.rs +++ b/acmed/src/main_event_loop.rs @@ -23,7 +23,7 @@ pub struct MainEventLoop { } impl MainEventLoop { - pub fn new(config_file: &str, root_certs: &[&str]) -> Result { + pub async fn new(config_file: &str, root_certs: &[&str]) -> Result { let cnf = config::from_file(config_file)?; let file_hooks = vec![ HookType::FilePreCreate, @@ -68,7 +68,7 @@ impl MainEventLoop { .collect(), env: acc.env.clone(), }; - let account = acc.to_generic(&fm)?; + let account = acc.to_generic(&fm).await?; let name = acc.name.clone(); accounts.insert(name, account); } @@ -180,7 +180,7 @@ async fn renew_certificate( endpoint_s: EndpointSync, ) -> (&mut Certificate, AccountSync, EndpointSync) { loop { - match certificate.should_renew() { + match certificate.should_renew().await { Ok(true) => break, Ok(false) => {} Err(e) => { @@ -198,7 +198,10 @@ async fn renew_certificate( (e.message, false) } }; - match certificate.call_post_operation_hooks(&status, is_success) { + match certificate + .call_post_operation_hooks(&status, is_success) + .await + { Ok(_) => {} Err(e) => { let e = e.prefix("post-operation hook error"); diff --git a/acmed/src/storage.rs b/acmed/src/storage.rs index 78c7f35..0896a69 100644 --- a/acmed/src/storage.rs +++ b/acmed/src/storage.rs @@ -7,12 +7,9 @@ use acme_common::error::Error; use serde::Serialize; use std::collections::HashMap; use std::fmt; -use std::fs::{File, OpenOptions}; -use std::io::{Read, Write}; use std::path::{Path, PathBuf}; - -#[cfg(target_family = "unix")] -use std::os::unix::fs::OpenOptionsExt; +use tokio::fs::{File, OpenOptions}; +use tokio::io::{AsyncReadExt, AsyncWriteExt}; #[derive(Clone, Debug)] pub struct FileManager { @@ -123,12 +120,13 @@ fn get_file_path(fm: &FileManager, file_type: FileType) -> Result Result, Error> { +async fn read_file(fm: &FileManager, path: &Path) -> Result, Error> { fm.trace(&format!("reading file {path:?}")); - let mut file = - File::open(path).map_err(|e| Error::from(e).prefix(&path.display().to_string()))?; + let mut file = File::open(path) + .await + .map_err(|e| Error::from(e).prefix(&path.display().to_string()))?; let mut contents = vec![]; - file.read_to_end(&mut contents)?; + file.read_to_end(&mut contents).await?; Ok(contents) } @@ -186,7 +184,7 @@ fn set_owner(fm: &FileManager, path: &Path, file_type: FileType) -> Result<(), E } } -fn write_file(fm: &FileManager, file_type: FileType, data: &[u8]) -> Result<(), Error> { +async fn write_file(fm: &FileManager, file_type: FileType, data: &[u8]) -> Result<(), Error> { let (file_directory, file_name, path) = get_file_full_path(fm, file_type.clone())?; let mut hook_data = FileStorageHookData { file_name, @@ -198,9 +196,9 @@ fn write_file(fm: &FileManager, file_type: FileType, data: &[u8]) -> Result<(), let is_new = !path.is_file(); if is_new { - hooks::call(fm, &fm.hooks, &hook_data, HookType::FilePreCreate)?; + hooks::call(fm, &fm.hooks, &hook_data, HookType::FilePreCreate).await?; } else { - hooks::call(fm, &fm.hooks, &hook_data, HookType::FilePreEdit)?; + hooks::call(fm, &fm.hooks, &hook_data, HookType::FilePreEdit).await?; } fm.trace(&format!("writing file {path:?}")); @@ -215,54 +213,58 @@ fn write_file(fm: &FileManager, file_type: FileType, data: &[u8]) -> Result<(), .write(true) .create(true) .open(&path) + .await .map_err(|e| Error::from(e).prefix(&path.display().to_string()))? } else { - File::create(&path).map_err(|e| Error::from(e).prefix(&path.display().to_string()))? + File::create(&path) + .await + .map_err(|e| Error::from(e).prefix(&path.display().to_string()))? }; file.write_all(data) + .await .map_err(|e| Error::from(e).prefix(&path.display().to_string()))?; if cfg!(unix) { set_owner(fm, &path, file_type).map_err(|e| e.prefix(&path.display().to_string()))?; } if is_new { - hooks::call(fm, &fm.hooks, &hook_data, HookType::FilePostCreate)?; + hooks::call(fm, &fm.hooks, &hook_data, HookType::FilePostCreate).await?; } else { - hooks::call(fm, &fm.hooks, &hook_data, HookType::FilePostEdit)?; + hooks::call(fm, &fm.hooks, &hook_data, HookType::FilePostEdit).await?; } Ok(()) } -pub fn get_account_data(fm: &FileManager) -> Result, Error> { +pub async fn get_account_data(fm: &FileManager) -> Result, Error> { let path = get_file_path(fm, FileType::Account)?; - read_file(fm, &path) + read_file(fm, &path).await } -pub fn set_account_data(fm: &FileManager, data: &[u8]) -> Result<(), Error> { - write_file(fm, FileType::Account, data) +pub async fn set_account_data(fm: &FileManager, data: &[u8]) -> Result<(), Error> { + write_file(fm, FileType::Account, data).await } -pub fn get_keypair(fm: &FileManager) -> Result { +pub async fn get_keypair(fm: &FileManager) -> Result { let path = get_file_path(fm, FileType::PrivateKey)?; - let raw_key = read_file(fm, &path)?; + let raw_key = read_file(fm, &path).await?; let key = KeyPair::from_pem(&raw_key)?; Ok(key) } -pub fn set_keypair(fm: &FileManager, key_pair: &KeyPair) -> Result<(), Error> { +pub async fn set_keypair(fm: &FileManager, key_pair: &KeyPair) -> Result<(), Error> { let data = key_pair.private_key_to_pem()?; - write_file(fm, FileType::PrivateKey, &data) + write_file(fm, FileType::PrivateKey, &data).await } -pub fn get_certificate(fm: &FileManager) -> Result { +pub async fn get_certificate(fm: &FileManager) -> Result { let path = get_file_path(fm, FileType::Certificate)?; - let raw_crt = read_file(fm, &path)?; + let raw_crt = read_file(fm, &path).await?; let crt = X509Certificate::from_pem(&raw_crt)?; Ok(crt) } -pub fn write_certificate(fm: &FileManager, data: &[u8]) -> Result<(), Error> { - write_file(fm, FileType::Certificate, data) +pub async fn write_certificate(fm: &FileManager, data: &[u8]) -> Result<(), Error> { + write_file(fm, FileType::Certificate, data).await } fn check_files(fm: &FileManager, file_types: &[FileType]) -> bool {