From 63c82c7db57b4b96dc46dab1761cff79757968ef Mon Sep 17 00:00:00 2001 From: Hatter Jiang Date: Wed, 5 May 2021 14:07:24 +0800 Subject: [PATCH] feat: update --- README.md | 45 ++++++++++++++++++++++++++++++++++++++++++++- src/config.rs | 41 +++++++++++++++++++++++++---------------- src/main.rs | 4 ++-- 3 files changed, 71 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 02bb727..d544147 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,46 @@ # acme-client-rs -ACME Client in Rust \ No newline at end of file +ACME Client in Rust + +Acme client help: +```shell +$ acme-client --help +acme-client 0.3.0 +Hatter Jiang +Acme auto challenge client, acme-client can issue certificates from Let's encrypt + +USAGE: + acme-client [FLAGS] [OPTIONS] + +FLAGS: + --check Check cert config + -h, --help Prints help information + --hide-logo Hide logo + -v, --verbose Verbose + -V, --version Print version + +OPTIONS: + -a, --algo Pki algo [default: ec384] + -c, --config Cert config + --dir Account key dir [default: acme_dir] + -d, --domain ... Domains + --email Contract email + -m, --mode Mode [default: prod] + -p, --port Http port [default: 80] + --timeout Timeout (ms) [default: 5000] + -t, --type Type http or dns [default: http] +``` + +签发一张证书示例 +* 先将域名指向对应的服务器,保证服务器上的 `80` 端口可被互联网访问 +* `acme-client --email your-email@example.com --domain your-domain.example.com` + +使用参数 `--config` 时的配置文件示例: +```json +{ + "certItems": [{ + "path": "dir_cryptofan_org", + "dnsNames": ["cryptofan.org", "www.cryptofan.org"] + }] +} +``` diff --git a/src/config.rs b/src/config.rs index 47fbc28..eed972c 100644 --- a/src/config.rs +++ b/src/config.rs @@ -121,7 +121,7 @@ impl CertConfigItem { } } self.algo = None; - self.public_key_algo = Some(x509_certificate.public_key_algo.clone()); + self.public_key_algo = Some(x509_certificate.public_key_algo); Ok(Some(x509_certificate)) } else { if self.common_name.is_none() { @@ -141,24 +141,33 @@ impl CertConfigItem { if cert_path_buff.exists() { let pem = opt_result!(fs::read_to_string(cert_path_buff.clone()), "Read file: {:?}, failed: {}", cert_path_buff); let x509_certificate = opt_result!(x509::parse_x509(&format!("{}/{}", self.path, CERT_NAME), &pem), "Parse x509: {}/{}, faield: {}", self.path, CERT_NAME); + + let mut self_dns_names = vec![]; + let mut cert_dns_names = vec![]; + if let Some(common_name) = &self.common_name { - if common_name != &x509_certificate.common_name { - warning!("Cert: {}, common name mis-match: {} vs {}", self.path, common_name, x509_certificate.common_name); - return Ok(None); // request for new cert + self_dns_names.push(common_name.to_lowercase()); + } + cert_dns_names.push(x509_certificate.common_name.to_lowercase()); + + self.dns_names.as_ref().map(|dns_names| dns_names.iter().map(|n| n.to_lowercase()).map(|n| { + if !self_dns_names.contains(&n) { + self_dns_names.push(n); + } + })); + for n in &x509_certificate.alt_names { + let n = n.to_lowercase(); + if !cert_dns_names.contains(&n) { + cert_dns_names.push(n); } } - if let Some(dns_names) = &self.dns_names { - let mut sorted_dns_names = dns_names.clone(); - sorted_dns_names.sort(); - let mut cert_sorted_dns_names = x509_certificate.alt_names.clone(); - if let Some(pos) = cert_sorted_dns_names.iter().position(|n| n == self.common_name.as_ref().unwrap()) { - cert_sorted_dns_names.remove(pos); - } - cert_sorted_dns_names.sort(); - if sorted_dns_names != cert_sorted_dns_names { - warning!("Cert: {}, dns names mis-match: {:?} vs {:?}", self.path, sorted_dns_names, cert_sorted_dns_names); - return Ok(None); // request for new cert - } + + self_dns_names.sort(); + cert_dns_names.sort(); + + if self_dns_names != cert_dns_names { + warning!("Cert: {}, dns names mis-match, required: {:?} vs certs: {:?}", self.path, self_dns_names, cert_dns_names); + return Ok(None); // request for new cert } Ok(Some(x509_certificate)) } else { diff --git a/src/main.rs b/src/main.rs index 2a756dd..b94d391 100644 --- a/src/main.rs +++ b/src/main.rs @@ -188,8 +188,8 @@ async fn main() -> tide::Result<()> { } let filtered_cert_config = cert_config.filter_cert_config_items(30); for item in &filtered_cert_config.cert_items { - if item.common_name.as_ref().map(|n| n.contains("*")).unwrap_or(false) - || item.dns_names.as_ref().map(|dns_names| dns_names.iter().any(|n| n.contains("*"))).unwrap_or(false) { + if item.common_name.as_ref().map(|n| n.contains('*')).unwrap_or(false) + || item.dns_names.as_ref().map(|dns_names| dns_names.iter().any(|n| n.contains('*'))).unwrap_or(false) { warning!("Currently not support wide card domain name"); continue; }