feat: ref

This commit is contained in:
2021-05-05 11:21:57 +08:00
parent 618c97942d
commit 3e09332a2e
3 changed files with 82 additions and 56 deletions

View File

@@ -7,12 +7,14 @@ mod config;
mod x509;
// mod simple_thread_pool;
use std::env;
use rust_util::XResult;
use acme_lib::Directory;
use acme_lib::{create_p384_key, create_p256_key, create_rsa_key};
use acme_lib::persist::FilePersist;
use clap::{App, Arg};
use std::fs;
use std::str::FromStr;
use std::sync::RwLock;
use std::collections::BTreeMap;
use tide::Request;
@@ -21,9 +23,9 @@ use std::time::Duration;
use async_std::task;
use async_std::channel;
use async_std::channel::Sender;
use config::AcmeAlgo;
use config::AcmeMode;
use crate::config::{CertConfig, CERT_NAME, KEY_NAME};
use crate::x509::{X509PublicKeyAlgo, X509EcPublicKeyAlgo};
const NAME: &str = env!("CARGO_PKG_NAME");
const VERSION: &str = env!("CARGO_PKG_VERSION");
@@ -39,7 +41,7 @@ struct AcmeRequest<'a> {
contract_email: &'a str,
primary_name: &'a str,
alt_names: &'a [&'a str],
algo: AcmeAlgo,
algo: X509PublicKeyAlgo,
mode: AcmeMode,
account_dir: &'a str,
timeout: u64,
@@ -49,8 +51,6 @@ struct AcmeRequest<'a> {
#[async_std::main]
async fn main() -> tide::Result<()> {
println!("{}", include_str!("logo.txt"));
let matches = App::new(NAME)
.version(VERSION)
.about(DESCRIPTION)
@@ -66,21 +66,36 @@ async fn main() -> tide::Result<()> {
.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("Cert config"))
.arg(Arg::with_name("hide-logo").long("hide-logo").help("Hide logo"))
.get_matches();
if matches.is_present("verbose") {
env::set_var("LOGGER_LEVEL", "*");
}
if matches.is_present("version") {
println!("{}", include_str!("logo.txt"));
information!("{} v{}", NAME, VERSION);
exit(1);
}
if !matches.is_present("hide-logo") {
println!("{}", include_str!("logo.txt"));
}
debugging!("Clap matches: {:?}", matches);
let email = matches.value_of("email").unwrap_or_else(|| {
failure!("Email is not assigned.");
exit(1);
});
if let None = matches.value_of("type") {
failure!("Type is not assigned.");
exit(1);
match matches.value_of("type") {
Some("http") => {}
_ => {
failure!("Type is not assigned or must be http.");
exit(1);
}
}
let port: u16 = match matches.value_of("port") {
Some(p) => p.parse().unwrap_or_else(|e| {
@@ -103,7 +118,7 @@ async fn main() -> tide::Result<()> {
}
};
let algo = match matches.value_of("algo") {
Some(a) => AcmeAlgo::parse(a).unwrap_or_else(|e| {
Some(a) => X509PublicKeyAlgo::from_str(a).unwrap_or_else(|e| {
failure!("{}", e);
exit(1);
}),
@@ -150,7 +165,7 @@ async fn main() -> tide::Result<()> {
timeout,
..Default::default()
};
if let Err(e) = request_domains(acme_request) {
if let Err(e) = request_acme_certificate(acme_request) {
failure!("Request certificate by acme failed: {}", e);
exit(1);
}
@@ -179,7 +194,7 @@ async fn main() -> tide::Result<()> {
cert_file: Some(format!("{}/{}", item.path, CERT_NAME)),
key_file: Some(format!("{}/{}", item.path, KEY_NAME)),
};
if let Err(e) = request_domains(acme_request) {
if let Err(e) = request_acme_certificate(acme_request) {
failure!("Request certificate: {}, by acme failed: {}", item.path, e);
}
}
@@ -190,7 +205,7 @@ async fn main() -> tide::Result<()> {
Ok(())
}
fn request_domains(acme_request: AcmeRequest) -> XResult<()> {
fn request_acme_certificate(acme_request: AcmeRequest) -> XResult<()> {
information!("Acme mode: {:?}", acme_request.mode);
let url = acme_request.mode.directory_url();
information!("Acme dir: {}", acme_request.account_dir);
@@ -203,41 +218,48 @@ fn request_domains(acme_request: AcmeRequest) -> XResult<()> {
let mut order_csr_index = 0;
let ord_csr = loop {
if let Some(ord_csr) = ord_new.confirm_validations() {
debugging!("Valid acme certificate http challenge success");
break ord_csr;
}
information!("Loop for acme challenge auth, #{}", order_csr_index);
order_csr_index += 1;
debugging!("Start acme certificate http challenge");
let auths = opt_result!(ord_new.authorizations(), "Order auth failed: {}");
for auth in &auths {
let chall = auth.http_challenge();
let token = chall.http_token();
// let path = format!(".well-known/acme-challenge/{}", token);
let proof = chall.http_proof();
{
information!("Add acme challenge: {} -> {}",token, proof);
information!("Add acme http challenge: {} -> {}",token, proof);
TOKEN_MAP.write().unwrap().insert(token.to_string(), proof);
}
opt_result!(chall.validate(acme_request.timeout), "Validate challenge failed: {}");
debugging!("Valid acme certificate http challenge");
opt_result!(chall.validate(acme_request.timeout), "Validate http challenge failed: {}");
}
debugging!("Refresh acme certificate order");
opt_result!(ord_new.refresh(), "Refresh order failed: {}");
};
information!("Generate private key, type: {:?}", acme_request.algo);
information!("Generate private key, key type: {:?}", acme_request.algo);
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),
X509PublicKeyAlgo::EcKey(X509EcPublicKeyAlgo::Secp256r1) => create_p256_key(),
X509PublicKeyAlgo::EcKey(X509EcPublicKeyAlgo::Secp384r1) => create_p384_key(),
X509PublicKeyAlgo::EcKey(X509EcPublicKeyAlgo::Secp521r1) => return simple_error!("Algo ec521 is not supported"),
X509PublicKeyAlgo::Rsa(bits) => create_rsa_key(bits),
};
debugging!("Invoking csr finalize pkey");
let ord_cert = opt_result!( ord_csr.finalize_pkey(pkey_pri, acme_request.timeout), "Submit CSR failed: {}");
debugging!("Downloading and save cert");
let cert = opt_result!( ord_cert.download_and_save_cert(), "Download and save certificate failed: {}");
if let (Some(cert_file), Some(key_file)) = (&acme_request.cert_file, &acme_request.key_file) {
debugging!("Certificate key: {}", cert.private_key());
debugging!("Certificate pem: {}", cert.certificate());
information!("Write file: {}", cert_file);
if let Err(e) = fs::write(cert_file, cert.certificate()) {
failure!("Write file: {}, failed: {}", cert_file, e);
@@ -246,6 +268,7 @@ fn request_domains(acme_request: AcmeRequest) -> XResult<()> {
if let Err(e) = fs::write(key_file, cert.private_key()) {
failure!("Write file: {}, failed: {}", key_file, e);
}
success!("Write files success: {} and {}", cert_file, key_file);
} else {
information!("Certificate key: {}", cert.private_key());
information!("Certificate pem: {}", cert.certificate());