Seperated Code into different Files and functions Part 2
Dieser Commit ist enthalten in:
Ursprung
dd026c901f
Commit
bd3f0ad2ac
6 geänderte Dateien mit 225 neuen und 220 gelöschten Zeilen
138
src/main.rs
138
src/main.rs
|
@ -5,17 +5,22 @@
|
|||
|
||||
pub(crate) mod consts;
|
||||
pub(crate) mod macros;
|
||||
pub(crate) mod prelude;
|
||||
pub(crate) mod process;
|
||||
pub(crate) mod types;
|
||||
pub(crate) mod utils;
|
||||
|
||||
use crate::{
|
||||
consts::*,
|
||||
macros::match_error,
|
||||
prelude::*,
|
||||
process::{
|
||||
process_accounts,
|
||||
process_site,
|
||||
services,
|
||||
},
|
||||
types::{
|
||||
config,
|
||||
config::{
|
||||
CA,
|
||||
GeneralConfig,
|
||||
SiteConfig,
|
||||
},
|
||||
structs::{
|
||||
|
@ -23,14 +28,8 @@ use crate::{
|
|||
ProcessorArgs,
|
||||
},
|
||||
},
|
||||
utils::prefix_emails,
|
||||
};
|
||||
use acme2_eab::{
|
||||
Account,
|
||||
AccountBuilder,
|
||||
Directory,
|
||||
DirectoryBuilder,
|
||||
};
|
||||
use acme2_eab::Directory;
|
||||
use async_scoped::TokioScope;
|
||||
use clap::Parser;
|
||||
use env_logger::init as log_init;
|
||||
|
@ -43,14 +42,7 @@ use openssl::{
|
|||
Private,
|
||||
},
|
||||
};
|
||||
use process::{
|
||||
process_site,
|
||||
services,
|
||||
};
|
||||
use reqwest::{
|
||||
Client,
|
||||
tls::Version,
|
||||
};
|
||||
use reqwest::tls::Version;
|
||||
use std::{
|
||||
collections::{
|
||||
HashMap,
|
||||
|
@ -69,20 +61,13 @@ use tokio::{
|
|||
create_dir_all,
|
||||
read_dir,
|
||||
},
|
||||
io::{
|
||||
AsyncReadExt,
|
||||
AsyncWriteExt,
|
||||
},
|
||||
io::AsyncReadExt,
|
||||
sync::Mutex,
|
||||
};
|
||||
use tokio_stream::{
|
||||
StreamExt,
|
||||
wrappers::ReadDirStream,
|
||||
};
|
||||
use types::{
|
||||
config::GeneralConfig,
|
||||
traits::FromFile as _,
|
||||
};
|
||||
|
||||
|
||||
fn default_client() -> reqwest::Client {
|
||||
|
@ -105,107 +90,6 @@ async fn load_privkey(path: PathBuf) -> Result<PKey<Private>, ()> {
|
|||
}
|
||||
}
|
||||
|
||||
async fn process_accounts(
|
||||
name: &String,
|
||||
ca: &CA,
|
||||
directories: &mut HashMap<String, Arc<Directory>>,
|
||||
accounts: &mut HashMap<String, Arc<Account>>,
|
||||
client: &Client,
|
||||
accountpath: PathBuf,
|
||||
) {
|
||||
let directory = match directories.get(&ca.directory) {
|
||||
Some(directory) => directory.to_owned(),
|
||||
None => {
|
||||
match DirectoryBuilder::new(ca.directory.clone()).http_client(client.clone()).build().await {
|
||||
Ok(dir) => {
|
||||
directories.insert(ca.directory.clone(), Arc::clone(&dir));
|
||||
dir
|
||||
},
|
||||
Err(error) => {
|
||||
error!("Failed to initialize directory for ca {name}: {error}");
|
||||
return;
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
let mut ac = AccountBuilder::new(Arc::clone(&directory));
|
||||
match ca.email_addresses.clone() {
|
||||
Some(addr) => {
|
||||
ac.contact(prefix_emails(addr));
|
||||
},
|
||||
None => {
|
||||
ac.contact(Vec::new());
|
||||
debug!("No Email address given")
|
||||
},
|
||||
}
|
||||
let accountkey = accountpath.join("file.pem").with_file_name(name.clone());
|
||||
let mut accountkeyfile = None;
|
||||
if accountkey.exists() {
|
||||
if let Ok(key) = load_privkey(accountkey).await {
|
||||
ac.private_key(key);
|
||||
}
|
||||
} else {
|
||||
info!("Registering for the CA {}", name.clone());
|
||||
accountkeyfile = match FILE_MODE_WRITE.open(accountkey).await {
|
||||
Ok(file) => Some(file),
|
||||
Err(error) => {
|
||||
error!("Failed to open the file for the accountkey: {error}");
|
||||
return;
|
||||
},
|
||||
}
|
||||
}
|
||||
if let Some(meta) = &directory.meta {
|
||||
// Collecting the errors about the metadata before annoying the admin about errors at different stages
|
||||
let mut errors = false;
|
||||
if let Some(tos) = &meta.terms_of_service {
|
||||
if !ca.tos_accepted {
|
||||
error!("Terms of Services were not agreed into: {tos}");
|
||||
errors = true;
|
||||
} else {
|
||||
ac.terms_of_service_agreed(true);
|
||||
}
|
||||
}
|
||||
if meta.external_account_required.unwrap_or(false) {
|
||||
if let Some(eab) = &ca.eab {
|
||||
match eab.key() {
|
||||
Ok(private) => {
|
||||
trace!("EAB Key info: Type={:?} Bits={}, Security-Bits={}", private.id(), private.bits(), private.security_bits());
|
||||
ac.external_account_binding(eab.token.clone(), private);
|
||||
},
|
||||
Err(error) => {
|
||||
error!("{error}");
|
||||
errors = true;
|
||||
},
|
||||
}
|
||||
} else {
|
||||
error!("eab_token and/or eab_key are unset, but the CA requires those.");
|
||||
errors = true;
|
||||
}
|
||||
} else if ca.eab.is_some() {
|
||||
warn!("The CA doesn't need EAB Tokens but they were configured")
|
||||
}
|
||||
if errors {
|
||||
return;
|
||||
}
|
||||
}
|
||||
let account = match ac.build().await {
|
||||
Ok(account) => {
|
||||
accounts.insert(name.clone(), Arc::clone(&account));
|
||||
account
|
||||
},
|
||||
Err(error) => {
|
||||
error!("Failed to get/create account: {error}");
|
||||
return;
|
||||
},
|
||||
};
|
||||
if let Some(mut keyfile) = accountkeyfile {
|
||||
let keydata = match_error!(account.private_key().private_key_to_pem_pkcs8()=>Err(error)-> "Failed to convert the private key to an pem: {error}");
|
||||
if let Err(error) = keyfile.write(keydata.as_slice()).await {
|
||||
error!("Failed to write the accountkey: {error}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn racme(flags: Arguments) {
|
||||
let client = default_client();
|
||||
let systemd_access = daemon::booted();
|
||||
|
|
8
src/prelude.rs
Normale Datei
8
src/prelude.rs
Normale Datei
|
@ -0,0 +1,8 @@
|
|||
pub(crate) use crate::{
|
||||
macros::*,
|
||||
types::traits::{
|
||||
FromFile as _,
|
||||
MatchAlgorithm as _,
|
||||
MatchX509 as _,
|
||||
},
|
||||
};
|
140
src/process.rs
140
src/process.rs
|
@ -1,8 +1,12 @@
|
|||
use std::{
|
||||
collections::HashSet,
|
||||
collections::{
|
||||
HashMap,
|
||||
HashSet,
|
||||
},
|
||||
fs::Permissions,
|
||||
os::unix::fs::PermissionsExt,
|
||||
path::PathBuf,
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
|
@ -13,25 +17,31 @@ use crate::{
|
|||
WAIT_TIME,
|
||||
},
|
||||
load_privkey,
|
||||
macros::match_error,
|
||||
prelude::*,
|
||||
types::{
|
||||
config::Dns,
|
||||
config::{
|
||||
CA,
|
||||
Dns,
|
||||
},
|
||||
cryptography::Algorithm,
|
||||
structs::{
|
||||
ProcessorArgs,
|
||||
San,
|
||||
},
|
||||
traits::{
|
||||
MatchAlgorithm as _,
|
||||
MatchX509,
|
||||
},
|
||||
utils::{
|
||||
gen_key,
|
||||
prefix_emails,
|
||||
},
|
||||
utils::gen_key,
|
||||
};
|
||||
use acme2_eab::{
|
||||
Account,
|
||||
AccountBuilder,
|
||||
Authorization,
|
||||
ChallengeStatus,
|
||||
Csr,
|
||||
Directory,
|
||||
DirectoryBuilder,
|
||||
Identifier,
|
||||
OrderBuilder,
|
||||
OrderStatus,
|
||||
|
@ -54,6 +64,7 @@ use openssl::{
|
|||
},
|
||||
},
|
||||
};
|
||||
use reqwest::Client;
|
||||
use tokio::{
|
||||
fs::{
|
||||
create_dir_all,
|
||||
|
@ -86,6 +97,107 @@ fn gen_stack(args: &ProcessorArgs, context: X509v3Context) -> Stack<X509Extensio
|
|||
stack
|
||||
}
|
||||
|
||||
pub async fn process_accounts(
|
||||
name: &String,
|
||||
ca: &CA,
|
||||
directories: &mut HashMap<String, Arc<Directory>>,
|
||||
accounts: &mut HashMap<String, Arc<Account>>,
|
||||
client: &Client,
|
||||
accountpath: PathBuf,
|
||||
) {
|
||||
let directory = match directories.get(&ca.directory) {
|
||||
Some(directory) => directory.to_owned(),
|
||||
None => {
|
||||
match DirectoryBuilder::new(ca.directory.clone()).http_client(client.clone()).build().await {
|
||||
Ok(dir) => {
|
||||
directories.insert(ca.directory.clone(), Arc::clone(&dir));
|
||||
dir
|
||||
},
|
||||
Err(error) => {
|
||||
error!("Failed to initialize directory for ca {name}: {error}");
|
||||
return;
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
let mut ac = AccountBuilder::new(Arc::clone(&directory));
|
||||
match ca.email_addresses.clone() {
|
||||
Some(addr) => {
|
||||
ac.contact(prefix_emails(addr));
|
||||
},
|
||||
None => {
|
||||
ac.contact(Vec::new());
|
||||
debug!("No Email address given")
|
||||
},
|
||||
}
|
||||
let accountkey = accountpath.join("file.pem").with_file_name(name.clone());
|
||||
let mut accountkeyfile = None;
|
||||
if accountkey.exists() {
|
||||
if let Ok(key) = load_privkey(accountkey).await {
|
||||
ac.private_key(key);
|
||||
}
|
||||
} else {
|
||||
info!("Registering for the CA {}", name.clone());
|
||||
accountkeyfile = match FILE_MODE_WRITE.open(accountkey).await {
|
||||
Ok(file) => Some(file),
|
||||
Err(error) => {
|
||||
error!("Failed to open the file for the accountkey: {error}");
|
||||
return;
|
||||
},
|
||||
}
|
||||
}
|
||||
if let Some(meta) = &directory.meta {
|
||||
// Collecting the errors about the metadata before annoying the admin about errors at different stages
|
||||
let mut errors = false;
|
||||
if let Some(tos) = &meta.terms_of_service {
|
||||
if !ca.tos_accepted {
|
||||
error!("Terms of Services were not agreed into: {tos}");
|
||||
errors = true;
|
||||
} else {
|
||||
ac.terms_of_service_agreed(true);
|
||||
}
|
||||
}
|
||||
if meta.external_account_required.unwrap_or(false) {
|
||||
if let Some(eab) = &ca.eab {
|
||||
match eab.key() {
|
||||
Ok(private) => {
|
||||
trace!("EAB Key info: Type={:?} Bits={}, Security-Bits={}", private.id(), private.bits(), private.security_bits());
|
||||
ac.external_account_binding(eab.token.clone(), private);
|
||||
},
|
||||
Err(error) => {
|
||||
error!("{error}");
|
||||
errors = true;
|
||||
},
|
||||
}
|
||||
} else {
|
||||
error!("eab_token and/or eab_key are unset, but the CA requires those.");
|
||||
errors = true;
|
||||
}
|
||||
} else if ca.eab.is_some() {
|
||||
warn!("The CA doesn't need EAB Tokens but they were configured")
|
||||
}
|
||||
if errors {
|
||||
return;
|
||||
}
|
||||
}
|
||||
let account = match ac.build().await {
|
||||
Ok(account) => {
|
||||
accounts.insert(name.clone(), Arc::clone(&account));
|
||||
account
|
||||
},
|
||||
Err(error) => {
|
||||
error!("Failed to get/create account: {error}");
|
||||
return;
|
||||
},
|
||||
};
|
||||
if let Some(mut keyfile) = accountkeyfile {
|
||||
let keydata = match_error!(account.private_key().private_key_to_pem_pkcs8()=>Err(error)-> "Failed to convert the private key to an pem: {error}");
|
||||
if let Err(error) = keyfile.write(keydata.as_slice()).await {
|
||||
error!("Failed to write the accountkey: {error}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub async fn process_site(args: ProcessorArgs<'_>) {
|
||||
let mut cert_renew = false;
|
||||
|
@ -98,8 +210,10 @@ pub async fn process_site(args: ProcessorArgs<'_>) {
|
|||
};
|
||||
cert_renew = true;
|
||||
}
|
||||
let private_key_file = directory.join("privkey.pem");
|
||||
let mut private_key;
|
||||
// Private key block
|
||||
{
|
||||
let private_key_file = directory.join("privkey.pem");
|
||||
let mut write_pkey = false;
|
||||
if !private_key_file.exists() {
|
||||
cert_renew = true;
|
||||
|
@ -124,6 +238,7 @@ pub async fn process_site(args: ProcessorArgs<'_>) {
|
|||
let mut file = match_error!(FILE_MODE_WRITE.open(private_key_file.clone()).await=>Err(error)-> "Failed to write new private key: {error}");
|
||||
match_error!(file.write_all(&pkey).await=>Err(error)->"Failed to write new private key: {error}");
|
||||
}
|
||||
}
|
||||
let pubkey_filename = directory.join("pubkey.pem");
|
||||
if pubkey_filename.exists() {
|
||||
let mut file = match_error!(FILE_MODE.open(pubkey_filename.clone()).await=>Err(error)-> "Failed to open publickey. Aborting processing: {error}");
|
||||
|
@ -151,10 +266,13 @@ pub async fn process_site(args: ProcessorArgs<'_>) {
|
|||
info!("Site {} doesn't need an update for the certificate.", args.name());
|
||||
return;
|
||||
}
|
||||
// Requesting a new cert
|
||||
let mut order;
|
||||
{
|
||||
info!("Renewing Certificate for site {}", args.name());
|
||||
let mut builder = OrderBuilder::new(args.account());
|
||||
builder.set_identifiers(args.san().iter().map(|s| s.to_owned().into()).collect::<Vec<Identifier>>());
|
||||
let mut order = match_error!(builder.build().await=>Err(error)-> "Failed order the certificate: {error}");
|
||||
order = match_error!(builder.build().await=>Err(error)-> "Failed order the certificate: {error}");
|
||||
let authorizations = match_error!(order.authorizations().await=>Err(error)-> "Failed to get the authorizations: {error}");
|
||||
let (_, result) = tokio::join! {
|
||||
unsafe {
|
||||
|
@ -197,7 +315,8 @@ pub async fn process_site(args: ProcessorArgs<'_>) {
|
|||
debug!("Received {} certificates.", certs.len());
|
||||
let mut pubkey_file = match_error!(FILE_MODE_WRITE.open(pubkey_filename).await=>Err(error)-> "Failed to open the file for the publickey: {error}");
|
||||
match_error!(pubkey_file.write_all(&certs[0].to_pem().unwrap()).await=>Err(error)-> "Failed to write the publickey: {error}");
|
||||
let mut fullchain = match_error!(FILE_MODE_WRITE.open(directory.join("fullchain.pem")).await=>Err(error)-> "failed to open the fullchain.pem: {error}");
|
||||
let mut fullchain =
|
||||
match_error!(FILE_MODE_WRITE.open(directory.join("fullchain.pem")).await=>Err(error)-> "failed to open the fullchain.pem: {error}");
|
||||
for cert in certs.clone() {
|
||||
let _ = fullchain.write_all(&cert.to_pem().unwrap()).await;
|
||||
}
|
||||
|
@ -205,6 +324,7 @@ pub async fn process_site(args: ProcessorArgs<'_>) {
|
|||
let _ = bundle.write_all(&private_key.private_key_to_pem_pkcs8().unwrap()).await;
|
||||
let _ = bundle.write_all(&certs[0].to_pem().unwrap()).await;
|
||||
info!("Processing of {} successful", args.name());
|
||||
}
|
||||
let mut services = args.reload_list().await;
|
||||
for service in &args.reload_services() {
|
||||
services.insert(service.to_owned());
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
use crate::{
|
||||
macros::{
|
||||
DefDer,
|
||||
match_error,
|
||||
},
|
||||
prelude::*,
|
||||
types::{
|
||||
VString,
|
||||
cryptography::{
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use macro_rules_attribute::macro_rules_derive;
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::macros::DefDer;
|
||||
use crate::prelude::*;
|
||||
|
||||
|
||||
#[macro_rules_derive(DefDer)]
|
||||
|
|
|
@ -11,14 +11,10 @@ use macro_rules_attribute::macro_rules_derive;
|
|||
use tokio::sync::MutexGuard;
|
||||
|
||||
use crate::{
|
||||
config::SiteConfig,
|
||||
macros::{
|
||||
DefDer,
|
||||
Hashable,
|
||||
attr_function,
|
||||
},
|
||||
prelude::*,
|
||||
types::{
|
||||
SafeSet,
|
||||
config::SiteConfig,
|
||||
cryptography::{
|
||||
Algorithm,
|
||||
Strength,
|
||||
|
@ -26,7 +22,7 @@ use crate::{
|
|||
},
|
||||
};
|
||||
|
||||
use super::config::Dns;
|
||||
use crate::types::config::Dns;
|
||||
|
||||
|
||||
#[macro_rules_derive(DefDer)]
|
||||
|
|
Laden …
Tabelle hinzufügen
In neuem Issue referenzieren