feat: cert config
This commit is contained in:
103
src/main.rs
103
src/main.rs
@@ -5,7 +5,7 @@ extern crate rust_util;
|
||||
|
||||
mod config;
|
||||
mod x509;
|
||||
mod simple_thread_pool;
|
||||
// mod simple_thread_pool;
|
||||
|
||||
use rust_util::XResult;
|
||||
use acme_lib::{DirectoryUrl, Directory};
|
||||
@@ -23,6 +23,7 @@ use async_std::channel;
|
||||
use async_std::channel::Sender;
|
||||
use config::AcmeAlgo;
|
||||
use config::AcmeMode;
|
||||
use crate::config::{CertConfig, CERT_NAME, KEY_NAME};
|
||||
|
||||
const NAME: &str = env!("CARGO_PKG_NAME");
|
||||
const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
@@ -40,7 +41,7 @@ struct AcmeRequest<'a> {
|
||||
alt_names: &'a [&'a str],
|
||||
algo: AcmeAlgo,
|
||||
mode: AcmeMode,
|
||||
dir: &'a str,
|
||||
account_dir: &'a str,
|
||||
timeout: u64,
|
||||
key_file: Option<String>,
|
||||
cert_file: Option<String>,
|
||||
@@ -64,6 +65,8 @@ async fn main() -> tide::Result<()> {
|
||||
.arg(Arg::with_name("timeout").long("timeout").takes_value(true).default_value("5000").help("Timeout (ms)"))
|
||||
.arg(Arg::with_name("mode").short("m").long("mode").takes_value(true).default_value("prod").help("Mode"))
|
||||
.arg(Arg::with_name("dir").long("dir").takes_value(true).default_value("acme_dir").help("Account key dir"))
|
||||
.arg(Arg::with_name("config").short("c").long("config").takes_value(true).help("Acme config"))
|
||||
.arg(Arg::with_name("cert-config").long("cert-config").takes_value(true).help("Cert config"))
|
||||
.get_matches();
|
||||
|
||||
if matches.is_present("version") {
|
||||
@@ -120,7 +123,7 @@ async fn main() -> tide::Result<()> {
|
||||
exit(1);
|
||||
}
|
||||
};
|
||||
let dir = matches.value_of("dir").unwrap_or("acme_dir");
|
||||
let account_dir = matches.value_of("dir").unwrap_or("acme_dir");
|
||||
|
||||
let domains_val = matches.values_of("domain").unwrap_or_else(|| {
|
||||
failure!("Domains is not assigned.");
|
||||
@@ -132,33 +135,72 @@ async fn main() -> tide::Result<()> {
|
||||
r.recv().await.ok();
|
||||
task::sleep(Duration::from_millis(500)).await;
|
||||
|
||||
let domains: Vec<&str> = domains_val.collect::<Vec<_>>();
|
||||
let primary_name = domains[0];
|
||||
let alt_names: Vec<&str> = domains.into_iter().skip(1).collect();
|
||||
information!("Domains, main: {}, alt: {:?}", primary_name, alt_names);
|
||||
let acme_request = AcmeRequest {
|
||||
contract_email: email,
|
||||
primary_name,
|
||||
alt_names: &alt_names,
|
||||
algo,
|
||||
mode,
|
||||
dir,
|
||||
timeout,
|
||||
..Default::default()
|
||||
};
|
||||
if let Err(e) = request_domains(acme_request) {
|
||||
failure!("Request certificate by acme failed: {}", e);
|
||||
exit(1);
|
||||
// TODO ......
|
||||
let config = matches.value_of("config");
|
||||
|
||||
let cert_config = matches.value_of("cert-config");
|
||||
match cert_config {
|
||||
None => { // cert config is not assigned
|
||||
let domains: Vec<&str> = domains_val.collect::<Vec<_>>();
|
||||
let primary_name = domains[0];
|
||||
let alt_names: Vec<&str> = domains.into_iter().skip(1).collect();
|
||||
information!("Domains, main: {}, alt: {:?}", primary_name, alt_names);
|
||||
let acme_request = AcmeRequest {
|
||||
contract_email: email,
|
||||
primary_name,
|
||||
alt_names: &alt_names,
|
||||
algo,
|
||||
mode,
|
||||
account_dir,
|
||||
timeout,
|
||||
..Default::default()
|
||||
};
|
||||
if let Err(e) = request_domains(acme_request) {
|
||||
failure!("Request certificate by acme failed: {}", e);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
Some(cert_config) => { // cert config is assigned
|
||||
let cert_config = {
|
||||
CertConfig::load(cert_config).unwrap_or_else(|e| {
|
||||
failure!("Load cert config: {}, failed: {}", cert_config, e);
|
||||
exit(1);
|
||||
})
|
||||
};
|
||||
let filtered_cert_config = cert_config.filter_cert_config_items(30);
|
||||
|
||||
for item in &filtered_cert_config.cert_items {
|
||||
if let (Some(common_name), Some(dns_names)) = (&item.common_name, &item.dns_names) {
|
||||
information!("Domains, main: {}, alt: {:?}", common_name, dns_names);
|
||||
let alt_names: Vec<&str> = dns_names.iter().map(|n| n.as_str()).collect();
|
||||
let acme_request = AcmeRequest {
|
||||
contract_email: email,
|
||||
primary_name: common_name,
|
||||
alt_names: &alt_names,
|
||||
algo,
|
||||
mode,
|
||||
account_dir,
|
||||
timeout,
|
||||
cert_file: Some(format!("{}/{}", item.path, CERT_NAME)),
|
||||
key_file: Some(format!("{}/{}", item.path, KEY_NAME)),
|
||||
};
|
||||
if let Err(e) = request_domains(acme_request) {
|
||||
failure!("Request certificate: {}, by acme failed: {}", item.path, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn request_domains(acme_request: AcmeRequest) -> XResult<()> {
|
||||
information!("Acme mode: {:?}", acme_request.mode);
|
||||
let url = acme_request.mode.directory_url();
|
||||
information!("Acme dir: {}", acme_request.dir);
|
||||
fs::create_dir_all(acme_request.dir).ok();
|
||||
let persist = FilePersist::new(acme_request.dir);
|
||||
information!("Acme dir: {}", acme_request.account_dir);
|
||||
fs::create_dir_all(acme_request.account_dir).ok();
|
||||
let persist = FilePersist::new(acme_request.account_dir);
|
||||
let dir = opt_result!(Directory::from_url(persist, url), "Create directory from url failed: {}");
|
||||
let acc = opt_result!(dir.account(acme_request.contract_email), "Directory set account failed: {}");
|
||||
let mut ord_new = opt_result!( acc.new_order(acme_request.primary_name, acme_request.alt_names), "Create order failed: {}");
|
||||
@@ -193,14 +235,25 @@ fn request_domains(acme_request: AcmeRequest) -> XResult<()> {
|
||||
let pkey_pri = match acme_request.algo {
|
||||
AcmeAlgo::Ec256 => create_p256_key(),
|
||||
AcmeAlgo::Ec384 => create_p384_key(),
|
||||
AcmeAlgo::Ec521 => return simple_error!("Algo ec521 is not supported"),
|
||||
AcmeAlgo::Rsa(bits) => create_rsa_key(bits),
|
||||
};
|
||||
|
||||
let ord_cert = opt_result!( ord_csr.finalize_pkey(pkey_pri, acme_request.timeout), "Submit CSR failed: {}");
|
||||
let cert = opt_result!( ord_cert.download_and_save_cert(), "Download and save certificate failed: {}");
|
||||
|
||||
information!("Certificate key: {}", cert.private_key());
|
||||
information!("Certificate pem: {}", cert.certificate());
|
||||
|
||||
if let (Some(cert_file), Some(key_file)) = (&acme_request.cert_file, &acme_request.key_file) {
|
||||
if let Err(e) = fs::write(cert_file, cert.certificate()) {
|
||||
failure!("Write file: {}, failed: {}", cert_file, e);
|
||||
}
|
||||
if let Err(e) = fs::write(key_file, cert.private_key()) {
|
||||
failure!("Write file: {}, failed: {}", key_file, e);
|
||||
}
|
||||
} else {
|
||||
information!("Certificate key: {}", cert.private_key());
|
||||
information!("Certificate pem: {}", cert.certificate());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user