From a1c7bcba30220c0106b38baefdfa7a9bfb5dc7a4 Mon Sep 17 00:00:00 2001 From: Hatter Jiang Date: Sat, 5 Apr 2025 00:58:16 +0800 Subject: [PATCH] feat: v1.3.9, kms encrypts dns credential --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/acme.rs | 4 ++-- src/kms.rs | 29 +++++++++++++++++++++++++++++ src/main.rs | 11 +++++++++-- 5 files changed, 42 insertions(+), 6 deletions(-) create mode 100644 src/kms.rs diff --git a/Cargo.lock b/Cargo.lock index 92b3663..5b6746d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,7 +4,7 @@ version = 4 [[package]] name = "acme-client" -version = "1.3.8" +version = "1.3.9" dependencies = [ "acme-lib", "aliyun-openapi-core-rust-sdk", diff --git a/Cargo.toml b/Cargo.toml index 5c4b16e..fba3115 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "acme-client" -version = "1.3.8" +version = "1.3.9" authors = ["Hatter Jiang "] edition = "2018" description = "Acme auto challenge client, acme-client can issue certificates from Let's encrypt" diff --git a/src/acme.rs b/src/acme.rs index 9c04ee6..c18dc1f 100644 --- a/src/acme.rs +++ b/src/acme.rs @@ -19,7 +19,7 @@ lazy_static! { pub struct AcmeRequest<'a> { pub challenge: AcmeChallenge, // issue, single acme request can only process one supplier - pub credential_supplier: Option<&'a str>, + pub credential_supplier: Option, pub allow_interact: bool, pub contract_email: &'a str, pub primary_name: &'a str, @@ -69,7 +69,7 @@ pub fn request_acme_certificate(acme_request: AcmeRequest, dns_cleaned_domains: 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: {}"); - let mut dns_client: Option> = match acme_request.credential_supplier { + let mut dns_client: Option> = match &acme_request.credential_supplier { Some(credential_supplier) => Some( opt_result!(DnsClientFactory::build(credential_supplier), "Build dns client failed: {}")), None => None, diff --git a/src/kms.rs b/src/kms.rs new file mode 100644 index 0000000..166feee --- /dev/null +++ b/src/kms.rs @@ -0,0 +1,29 @@ +use reqwest::blocking::{Body, Client, Request}; +use reqwest::{Method, Url}; +use rust_util::XResult; +use serde::Deserialize; +use serde_json::json; + +#[derive(Debug, Deserialize)] +struct DecryptResponse { + value: String, +} + +pub fn try_kms_decrypt(ciphertext: &str) -> XResult { + if !ciphertext.starts_with("LKMS:") { + return Ok(ciphertext.to_string()); + } + debugging!("Try decrypt: {}", ciphertext); + let body = json!({ "encrypted_value": ciphertext }); + let body = serde_json::to_string(&body)?; + let client = Client::new(); + let uri = format!("http://{}/{}", "127.0.0.1:5567", "decrypt"); + let mut request = Request::new(Method::POST, Url::parse(&uri)?); + let _ = request.body_mut().insert(Body::from(body)); + let response = client.execute(request)?; + let response_text = response.text()?; + debugging!("KMS response text: {}", &response_text); + let decrypt_response: DecryptResponse = serde_json::from_str(&response_text)?; + debugging!("Decrypt value: {}", &decrypt_response.value); + Ok(decrypt_response.value) +} diff --git a/src/main.rs b/src/main.rs index 0788b1a..88dc806 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,6 +10,7 @@ mod x509; mod network; mod statistics; mod notification; +mod kms; mod dns; mod ali_dns; // mod simple_thread_pool; @@ -216,7 +217,7 @@ async fn main() -> tide::Result<()> { let acme_request = AcmeRequest { challenge: AcmeChallenge::from_str(matches.value_of("challenge-type")), - credential_supplier: matches.value_of("dns-supplier"), + credential_supplier: matches.value_of("dns-supplier").map(ToString::to_string), allow_interact: matches.is_present("allow-interact"), contract_email: &email, primary_name, @@ -268,7 +269,13 @@ async fn main() -> tide::Result<()> { warning!("DNS challenge no credential supplier found"); None } - Some(credential_supplier) => Some(credential_supplier.as_str()), + Some(credential_supplier) => match kms::try_kms_decrypt(credential_supplier) { + Ok(credential_supplier) => Some(credential_supplier), + Err(e) => { + failure!("Decrypt DNS challenge credential supplier failed: {}", e); + None + } + }, } } }