You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

149 lines
4.4 KiB

use crate::account::Account as BaseAccount;
use crate::acme_proto::http;
use crate::acme_proto::structs::{Account, AccountKeyRollover, AccountUpdate, AcmeError};
use crate::endpoint::Endpoint;
use crate::http::HttpError;
use crate::jws::{encode_jwk, encode_kid};
use crate::logs::HasLogger;
use crate::set_data_builder;
use acme_common::error::Error;
macro_rules! create_account_if_does_not_exist {
($e: expr, $endpoint: ident, $account: ident) => {
match $e {
Ok(r) => Ok(r),
Err(he) => match he {
HttpError::ApiError(ref e) => match e.get_acme_type() {
AcmeError::AccountDoesNotExist => {
let msg = format!(
"account has been dropped by endpoint \"{}\"",
$endpoint.name
);
$account.debug(&msg);
return register_account($endpoint, $account);
}
_ => Err(HttpError::in_err(he.to_owned())),
},
HttpError::GenericError(e) => Err(e),
},
}
};
}
pub fn register_account(endpoint: &mut Endpoint, account: &mut BaseAccount) -> Result<(), Error> {
account.debug(&format!(
"creating account on endpoint \"{}\"...",
&endpoint.name
));
let account_struct = Account::new(account, endpoint)?;
let account_struct = serde_json::to_string(&account_struct)?;
let acc_ref = &account_struct;
let kp_ref = &account.current_key.key;
let signature_algorithm = &account.current_key.signature_algorithm;
let data_builder = |n: &str, url: &str| {
encode_jwk(
kp_ref,
signature_algorithm,
acc_ref.as_bytes(),
url,
Some(n.to_string()),
)
};
let (acc_rep, account_url) =
http::new_account(endpoint, &data_builder).map_err(HttpError::in_err)?;
account.set_account_url(&endpoint.name, &account_url)?;
let orders_url = match acc_rep.orders {
Some(url) => url,
None => {
let msg = format!(
"endpoint \"{}\": account \"{}\": the server has not provided an order URL upon account creation",
&endpoint.name,
&account.name
);
account.warn(&msg);
String::new()
}
};
account.set_orders_url(&endpoint.name, &orders_url)?;
account.update_key_hash(&endpoint.name)?;
account.update_contacts_hash(&endpoint.name)?;
account.update_external_account_hash(&endpoint.name)?;
account.save()?;
account.info(&format!(
"account created on endpoint \"{}\"",
&endpoint.name
));
Ok(())
}
pub fn update_account_contacts(
endpoint: &mut Endpoint,
account: &mut BaseAccount,
) -> Result<(), Error> {
let endpoint_name = endpoint.name.clone();
account.debug(&format!(
"updating account contacts on endpoint \"{}\"...",
&endpoint_name
));
let new_contacts: Vec<String> = account.contacts.iter().map(|c| c.to_string()).collect();
let acc_up_struct = AccountUpdate::new(&new_contacts);
let acc_up_struct = serde_json::to_string(&acc_up_struct)?;
let data_builder = set_data_builder!(account, endpoint_name, acc_up_struct.as_bytes());
let url = account.get_endpoint(&endpoint_name)?.account_url.clone();
create_account_if_does_not_exist!(
http::post_jose_no_response(endpoint, &data_builder, &url),
endpoint,
account
)?;
account.update_contacts_hash(&endpoint_name)?;
account.save()?;
account.info(&format!(
"account contacts updated on endpoint \"{}\"",
&endpoint_name
));
Ok(())
}
pub 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
));
let url = endpoint.dir.key_change.clone();
let ep = account.get_endpoint(&endpoint_name)?;
let old_account_key = account.get_past_key(&ep.key_hash)?;
let old_key = &old_account_key.key;
let account_url = account.get_endpoint(&endpoint_name)?.account_url.clone();
let rollover_struct = AccountKeyRollover::new(&account_url, old_key)?;
let rollover_struct = serde_json::to_string(&rollover_struct)?;
let rollover_payload = encode_jwk(
&account.current_key.key,
&account.current_key.signature_algorithm,
rollover_struct.as_bytes(),
&url,
None,
)?;
let data_builder = |n: &str, url: &str| {
encode_kid(
old_key,
&old_account_key.signature_algorithm,
&account_url,
rollover_payload.as_bytes(),
url,
n,
)
};
create_account_if_does_not_exist!(
http::post_jose_no_response(endpoint, &data_builder, &url),
endpoint,
account
)?;
account.update_key_hash(&endpoint_name)?;
account.save()?;
account.info(&format!(
"account key updated on endpoint \"{}\"",
&endpoint_name
));
Ok(())
}