v1.0.1
This commit is contained in:
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -4,7 +4,7 @@ version = 3
|
||||
|
||||
[[package]]
|
||||
name = "acme-client"
|
||||
version = "1.0.0"
|
||||
version = "1.0.1"
|
||||
dependencies = [
|
||||
"acme-lib",
|
||||
"async-std",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "acme-client"
|
||||
version = "1.0.0"
|
||||
version = "1.0.1"
|
||||
authors = ["Hatter Jiang <jht5945@gmail.com>"]
|
||||
edition = "2018"
|
||||
description = "Acme auto challenge client, acme-client can issue certificates from Let's encrypt"
|
||||
|
||||
37
README.md
37
README.md
@@ -5,7 +5,7 @@ ACME Client in Rust
|
||||
Acme client help:
|
||||
```shell
|
||||
$ acme-client --help
|
||||
acme-client 0.5.0
|
||||
acme-client 1.0.1
|
||||
Hatter Jiang <jht5945@gmail.com>
|
||||
Acme auto challenge client, acme-client can issue certificates from Let's encrypt
|
||||
|
||||
@@ -13,23 +13,25 @@ USAGE:
|
||||
acme-client [FLAGS] [OPTIONS]
|
||||
|
||||
FLAGS:
|
||||
--check Check cert config
|
||||
-h, --help Prints help information
|
||||
--hide-logo Hide logo
|
||||
--skip-verify-ip Skip verify public ip
|
||||
-v, --verbose Verbose
|
||||
-V, --version Print version
|
||||
--check Check cert config
|
||||
-h, --help Prints help information
|
||||
--hide-logo Hide logo
|
||||
-K, --skip-verify-certificate Skip verify certificate
|
||||
-k, --skip-verify-ip Skip verify public ip
|
||||
-v, --verbose Verbose
|
||||
-V, --version Print version
|
||||
|
||||
OPTIONS:
|
||||
-a, --algo <algo> Pki algo [default: ec384]
|
||||
-c, --config <config> Cert config
|
||||
--dir <dir> Account key dir [default: acme_dir]
|
||||
-d, --domain <domain>... Domains
|
||||
--email <email> Contract email
|
||||
-m, --mode <mode> Mode [default: prod]
|
||||
-p, --port <port> Http port [default: 80]
|
||||
--timeout <timeout> Timeout (ms) [default: 5000]
|
||||
-t, --type <type> Type http or dns [default: http]
|
||||
-a, --algo <algo> Pki algo [default: ec384]
|
||||
--cert-dir <cert-dir> Certificate dir
|
||||
-c, --config <config> Cert config
|
||||
--dir <dir> Account key dir [default: acme_dir]
|
||||
-d, --domain <domain>... Domains
|
||||
--email <email> Contract email
|
||||
-m, --mode <mode> Mode [default: prod]
|
||||
-p, --port <port> Http port [default: 80]
|
||||
--timeout <timeout> Timeout (ms) [default: 5000]
|
||||
-t, --type <type> Type http or dns [default: http]
|
||||
```
|
||||
|
||||
签发一张证书示例
|
||||
@@ -39,6 +41,9 @@ OPTIONS:
|
||||
使用参数 `--config` 时的配置文件示例:
|
||||
```json
|
||||
{
|
||||
"port": 18342,
|
||||
"triggerAfterUpdate": ["/usr/local/nginx/nginx", "-s", "reload"],
|
||||
"notifyToken": "dingtalk:access_token?sec_token",
|
||||
"certItems": [{
|
||||
"path": "dir_cryptofan_org",
|
||||
"dnsNames": ["cryptofan.org", "www.cryptofan.org"]
|
||||
|
||||
12
src/main.rs
12
src/main.rs
@@ -79,6 +79,7 @@ async fn main() -> tide::Result<()> {
|
||||
.arg(Arg::with_name("check").long("check").help("Check cert config"))
|
||||
.arg(Arg::with_name("hide-logo").long("hide-logo").help("Hide logo"))
|
||||
.arg(Arg::with_name("skip-verify-ip").short("k").long("skip-verify-ip").help("Skip verify public ip"))
|
||||
.arg(Arg::with_name("skip-verify-certificate").short("K").long("skip-verify-certificate").help("Skip verify certificate"))
|
||||
.get_matches();
|
||||
|
||||
if matches.is_present("verbose") {
|
||||
@@ -99,7 +100,8 @@ async fn main() -> tide::Result<()> {
|
||||
let local_public_ip = if skip_verify_ip {
|
||||
None
|
||||
} else {
|
||||
Some(get_local_public_ip().unwrap_or_else(|e| {
|
||||
let skip_verify_certificate = matches.is_present("skip-verify-certificate");
|
||||
Some(get_local_public_ip(skip_verify_certificate).unwrap_or_else(|e| {
|
||||
failure!("Get local public ip failed: {}", e);
|
||||
exit(1);
|
||||
}))
|
||||
@@ -309,18 +311,18 @@ async fn main() -> tide::Result<()> {
|
||||
match run_command_and_wait(&mut cmd) {
|
||||
Ok(_) => {
|
||||
success!("Restart nginx success");
|
||||
dingtalk_message.push_str("\n\nrestart nginx success");
|
||||
dingtalk_message.push_str(&format!("\n\ntrigger after update success: {:?}", cmd));
|
||||
}
|
||||
Err(err) => {
|
||||
failure!("Restart nginx failed: {:?}", err);
|
||||
dingtalk_message.push_str(&format!("\n\nrestart nginx failed: {:?}", err));
|
||||
dingtalk_message.push_str(&format!("\n\ntrigger after update failed: {:?}, message: {:?}", cmd, err));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
warning!("No trigger after update is configed but is empty");
|
||||
warning!("No trigger after update is configured but is empty");
|
||||
}
|
||||
} else {
|
||||
warning!("No trigger after update configed");
|
||||
warning!("No trigger after update configured");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,8 +12,51 @@ pub struct PublicIpResponse {
|
||||
pub user_agent: Option<String>,
|
||||
}
|
||||
|
||||
pub fn get_local_public_ip() -> XResult<String> {
|
||||
let response = opt_result!(reqwest::blocking::get("https://hatter.ink/ip/ip.jsonp"), "Get local public ip failed: {}");
|
||||
pub fn get_local_public_ip(skip_verify_certificate: bool) -> XResult<String> {
|
||||
let mut client_builder = reqwest::blocking::Client::builder();
|
||||
if skip_verify_certificate {
|
||||
warning!("Skip verify certificate is turned on");
|
||||
client_builder = client_builder.danger_accept_invalid_certs(true);
|
||||
}
|
||||
let root_certificate_isrg_x_pem = r#"-----BEGIN CERTIFICATE-----
|
||||
MIIFYDCCBEigAwIBAgIQQAF3ITfU6UK47naqPGQKtzANBgkqhkiG9w0BAQsFADA/
|
||||
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
|
||||
DkRTVCBSb290IENBIFgzMB4XDTIxMDEyMDE5MTQwM1oXDTI0MDkzMDE4MTQwM1ow
|
||||
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
|
||||
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwggIiMA0GCSqGSIb3DQEB
|
||||
AQUAA4ICDwAwggIKAoICAQCt6CRz9BQ385ueK1coHIe+3LffOJCMbjzmV6B493XC
|
||||
ov71am72AE8o295ohmxEk7axY/0UEmu/H9LqMZshftEzPLpI9d1537O4/xLxIZpL
|
||||
wYqGcWlKZmZsj348cL+tKSIG8+TA5oCu4kuPt5l+lAOf00eXfJlII1PoOK5PCm+D
|
||||
LtFJV4yAdLbaL9A4jXsDcCEbdfIwPPqPrt3aY6vrFk/CjhFLfs8L6P+1dy70sntK
|
||||
4EwSJQxwjQMpoOFTJOwT2e4ZvxCzSow/iaNhUd6shweU9GNx7C7ib1uYgeGJXDR5
|
||||
bHbvO5BieebbpJovJsXQEOEO3tkQjhb7t/eo98flAgeYjzYIlefiN5YNNnWe+w5y
|
||||
sR2bvAP5SQXYgd0FtCrWQemsAXaVCg/Y39W9Eh81LygXbNKYwagJZHduRze6zqxZ
|
||||
Xmidf3LWicUGQSk+WT7dJvUkyRGnWqNMQB9GoZm1pzpRboY7nn1ypxIFeFntPlF4
|
||||
FQsDj43QLwWyPntKHEtzBRL8xurgUBN8Q5N0s8p0544fAQjQMNRbcTa0B7rBMDBc
|
||||
SLeCO5imfWCKoqMpgsy6vYMEG6KDA0Gh1gXxG8K28Kh8hjtGqEgqiNx2mna/H2ql
|
||||
PRmP6zjzZN7IKw0KKP/32+IVQtQi0Cdd4Xn+GOdwiK1O5tmLOsbdJ1Fu/7xk9TND
|
||||
TwIDAQABo4IBRjCCAUIwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw
|
||||
SwYIKwYBBQUHAQEEPzA9MDsGCCsGAQUFBzAChi9odHRwOi8vYXBwcy5pZGVudHJ1
|
||||
c3QuY29tL3Jvb3RzL2RzdHJvb3RjYXgzLnA3YzAfBgNVHSMEGDAWgBTEp7Gkeyxx
|
||||
+tvhS5B1/8QVYIWJEDBUBgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEEAYLfEwEB
|
||||
ATAwMC4GCCsGAQUFBwIBFiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2VuY3J5cHQu
|
||||
b3JnMDwGA1UdHwQ1MDMwMaAvoC2GK2h0dHA6Ly9jcmwuaWRlbnRydXN0LmNvbS9E
|
||||
U1RST09UQ0FYM0NSTC5jcmwwHQYDVR0OBBYEFHm0WeZ7tuXkAXOACIjIGlj26Ztu
|
||||
MA0GCSqGSIb3DQEBCwUAA4IBAQAKcwBslm7/DlLQrt2M51oGrS+o44+/yQoDFVDC
|
||||
5WxCu2+b9LRPwkSICHXM6webFGJueN7sJ7o5XPWioW5WlHAQU7G75K/QosMrAdSW
|
||||
9MUgNTP52GE24HGNtLi1qoJFlcDyqSMo59ahy2cI2qBDLKobkx/J3vWraV0T9VuG
|
||||
WCLKTVXkcGdtwlfFRjlBz4pYg1htmf5X6DYO8A4jqv2Il9DjXA6USbW1FzXSLr9O
|
||||
he8Y4IWS6wY7bCkjCWDcRQJMEhg76fsO3txE+FiYruq9RUWhiF1myv4Q6W+CyBFC
|
||||
Dfvp7OOGAN6dEOM4+qR9sdjoSYKEBpsr6GtPAQw4dy753ec5
|
||||
-----END CERTIFICATE-----"#;
|
||||
match reqwest::Certificate::from_pem(root_certificate_isrg_x_pem.as_bytes()) {
|
||||
Err(err) => { warning!("Add ISRG X1 root failed: {}", err); },
|
||||
Ok(certificate) => {
|
||||
client_builder = client_builder.add_root_certificate(certificate);
|
||||
},
|
||||
}
|
||||
let client = opt_result!(client_builder.build(), "Build http client failed: {}");
|
||||
let response = opt_result!(client.get("https://hatter.ink/ip/ip.jsonp").send(), "Get local public ip failed: {}");
|
||||
let response_text = opt_result!(response.text(), "Get local public ip failed: {}");
|
||||
debugging!("Get local public ip response: {}", response_text);
|
||||
let response_json: PublicIpResponse = opt_result!(deser_hjson::from_str(&response_text), "Parse get public ip response failed: {}");
|
||||
@@ -32,6 +75,6 @@ pub fn resolve_first_ipv4(resolver: &Resolver, domain: &str) -> XResult<Option<S
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
println!("{:?}", resolve_first_ipv4(&get_resolver().unwrap(),"hatter.ink"));
|
||||
println!("{:?}", get_local_public_ip());
|
||||
println!("{:?}", resolve_first_ipv4(&get_resolver().unwrap(), "hatter.ink"));
|
||||
println!("{:?}", get_local_public_ip(false));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user