feat: add dns.rs
This commit is contained in:
42
src/acme.rs
42
src/acme.rs
@@ -4,11 +4,10 @@ use std::collections::BTreeMap;
|
|||||||
use acme_lib::{Directory, create_p256_key, create_p384_key, create_rsa_key};
|
use acme_lib::{Directory, create_p256_key, create_p384_key, create_rsa_key};
|
||||||
use acme_lib::persist::FilePersist;
|
use acme_lib::persist::FilePersist;
|
||||||
use rust_util::XResult;
|
use rust_util::XResult;
|
||||||
use aliyun_openapi_core_rust_sdk::RPClient;
|
|
||||||
use crate::util::parse_dns_record;
|
use crate::util::parse_dns_record;
|
||||||
use crate::network::{get_resolver, resolve_first_ipv4};
|
use crate::network::{get_resolver, resolve_first_ipv4};
|
||||||
use crate::ali_dns::{add_txt_dns_record, build_dns_client, delete_dns_record, list_dns, simple_parse_aliyun_supplier};
|
|
||||||
use crate::config::{AcmeChallenge, AcmeMode};
|
use crate::config::{AcmeChallenge, AcmeMode};
|
||||||
|
use crate::dns::{DnsClient, DnsClientFactory, DnsRecord};
|
||||||
use crate::x509::{X509PublicKeyAlgo, X509EcPublicKeyAlgo};
|
use crate::x509::{X509PublicKeyAlgo, X509EcPublicKeyAlgo};
|
||||||
|
|
||||||
|
|
||||||
@@ -64,9 +63,9 @@ 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 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 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 ord_new = opt_result!( acc.new_order(acme_request.primary_name, acme_request.alt_names), "Create order failed: {}");
|
||||||
let ali_yun_client: Option<RPClient> = match acme_request.credential_supplier {
|
let mut dns_client: Option<Box<dyn DnsClient>> = match acme_request.credential_supplier {
|
||||||
Some(credential_supplier) => Some(build_dns_client(
|
Some(credential_supplier) => Some(
|
||||||
&opt_result!(simple_parse_aliyun_supplier(credential_supplier), "Parse credential supplier failed: {}"))),
|
opt_result!(DnsClientFactory::build(credential_supplier), "Build dns client failed: {}")),
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -107,18 +106,16 @@ pub fn request_acme_certificate(acme_request: AcmeRequest, dns_cleaned_domains:
|
|||||||
if !dns_cleaned_domains.contains(&rr_and_domain.1) {
|
if !dns_cleaned_domains.contains(&rr_and_domain.1) {
|
||||||
information!("Clearing domain: {}", &rr_and_domain.1);
|
information!("Clearing domain: {}", &rr_and_domain.1);
|
||||||
dns_cleaned_domains.push(rr_and_domain.1.clone());
|
dns_cleaned_domains.push(rr_and_domain.1.clone());
|
||||||
ali_yun_client.as_ref().map(|client| {
|
dns_client.as_mut().map(|client| {
|
||||||
match list_dns(client, &rr_and_domain.1) {
|
match client.list_dns(&rr_and_domain.1) {
|
||||||
Err(e) => warning!("List dns for: {}, failed: {}", &rr_and_domain.1, e),
|
Err(e) => warning!("List dns for: {}, failed: {}", &rr_and_domain.1, e),
|
||||||
Ok(Err(e)) => warning!("List dns for: {}, failed: {:?}", &rr_and_domain.1, e),
|
Ok(records) => {
|
||||||
Ok(Ok(s)) => {
|
for r in &records {
|
||||||
for r in &s.domain_records.record {
|
|
||||||
let rr = &r.rr;
|
let rr = &r.rr;
|
||||||
if rr == "_acme-challenge" || rr.starts_with("_acme-challenge.") {
|
if rr == "_acme-challenge" || rr.starts_with("_acme-challenge.") {
|
||||||
match delete_dns_record(client, &r.record_id) {
|
match client.delete_dns_record(&r.id) {
|
||||||
Err(e) => warning!("Delete dns: {}.{}, failed: {}", r.rr, r.domain_name, e),
|
Err(e) => warning!("Delete dns: {}.{}, failed: {}", r.rr, r.domain, e),
|
||||||
Ok(Err(e)) => warning!("Delete dns: {}.{}, failed: {:?}", r.rr, r.domain_name, e),
|
Ok(_) => success!("Delete dns: {}.{}", r.rr, r.domain),
|
||||||
Ok(Ok(_)) => success!("Delete dns: {}.{}", r.rr, r.domain_name),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -127,13 +124,18 @@ pub fn request_acme_certificate(acme_request: AcmeRequest, dns_cleaned_domains:
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
match &ali_yun_client {
|
match &mut dns_client {
|
||||||
Some(client) => {
|
Some(client) => {
|
||||||
let add_txt_dns_result = opt_result!(add_txt_dns_record(client, &rr_and_domain.1, &rr_and_domain.0, &proof), "Add DNS TXT record failed: {}");
|
let dns_record = DnsRecord {
|
||||||
match add_txt_dns_result {
|
id: String::new(),
|
||||||
Ok(s) => success!("Add dns txt record successes: {}", s.record_id),
|
domain: rr_and_domain.1,
|
||||||
Err(e) => return simple_error!("Add dns txt record failed: {:?}", e),
|
rr: rr_and_domain.0,
|
||||||
}
|
r#type: "TXT".into(),
|
||||||
|
ttl: -1,
|
||||||
|
value: proof,
|
||||||
|
};
|
||||||
|
let _ = opt_result!(client.add_dns_record(&dns_record), "Add DNS TXT record failed: {}");
|
||||||
|
success!("Add dns txt record successes: {}.{} -> {}", dns_record.rr, dns_record.domain, dns_record.value);
|
||||||
}
|
}
|
||||||
None => if acme_request.allow_interact {
|
None => if acme_request.allow_interact {
|
||||||
let mut line = String::new();
|
let mut line = String::new();
|
||||||
|
|||||||
@@ -1,10 +1,53 @@
|
|||||||
use rust_util::XResult;
|
use rust_util::XResult;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use aliyun_openapi_core_rust_sdk::RPClient;
|
use aliyun_openapi_core_rust_sdk::RPClient;
|
||||||
|
use crate::dns::DnsClient;
|
||||||
|
|
||||||
static ALI_DNS_ENDPOINT: &str = "https://alidns.aliyuncs.com";
|
static ALI_DNS_ENDPOINT: &str = "https://alidns.aliyuncs.com";
|
||||||
static ALI_DNS_API_VERSION: &str = "2015-01-09";
|
static ALI_DNS_API_VERSION: &str = "2015-01-09";
|
||||||
|
|
||||||
|
pub struct AlibabaCloudDnsClient {
|
||||||
|
client: RPClient,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AlibabaCloudDnsClient {
|
||||||
|
pub fn build(supplier: &str) -> XResult<AlibabaCloudDnsClient> {
|
||||||
|
let access_credential = simple_parse_aliyun_supplier(supplier)?;
|
||||||
|
Ok(AlibabaCloudDnsClient {
|
||||||
|
client: build_dns_client(&access_credential)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DnsClient for AlibabaCloudDnsClient {
|
||||||
|
fn list_dns(&mut self, domain: &str) -> XResult<Vec<crate::dns::DnsRecord>> {
|
||||||
|
let list_dns_response = opt_result!(list_dns(&self.client, domain)?, "List dns records failed: {:?}");
|
||||||
|
let mut dns_records = vec![];
|
||||||
|
list_dns_response.domain_records.record.into_iter().for_each(|record| {
|
||||||
|
dns_records.push(crate::dns::DnsRecord {
|
||||||
|
id: record.record_id,
|
||||||
|
domain: record.domain_name,
|
||||||
|
rr: record.rr,
|
||||||
|
r#type: record.r#type,
|
||||||
|
ttl: record.ttl,
|
||||||
|
value: record.value,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
Ok(dns_records)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn delete_dns_record(&mut self, record_id: &str) -> XResult<()> {
|
||||||
|
opt_result!(delete_dns_record(&self.client, record_id)?, "Delete dns record failed: {:?}");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_dns_record(&mut self, dns_record: &crate::dns::DnsRecord) -> XResult<()> {
|
||||||
|
let _ = opt_result!(add_dns_record(&self.client, &dns_record.domain, &dns_record.rr, &dns_record.r#type, &dns_record.value),
|
||||||
|
"Add dns record failed: {}");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct AccessCredential {
|
pub struct AccessCredential {
|
||||||
access_key_id: String,
|
access_key_id: String,
|
||||||
@@ -111,9 +154,9 @@ pub fn delete_dns_record(client: &RPClient, record_id: &str) -> XResult<Result<C
|
|||||||
parse_result("DeleteDomainRecord", &delete_domain_record_response)
|
parse_result("DeleteDomainRecord", &delete_domain_record_response)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_txt_dns_record(client: &RPClient, domain: &str, rr: &str, value: &str) -> XResult<Result<CommonSuccessResponse, CommonErrorResponse>> {
|
// pub fn add_txt_dns_record(client: &RPClient, domain: &str, rr: &str, value: &str) -> XResult<Result<CommonSuccessResponse, CommonErrorResponse>> {
|
||||||
add_dns_record(client, domain, rr, "TXT", value)
|
// add_dns_record(client, domain, rr, "TXT", value)
|
||||||
}
|
// }
|
||||||
|
|
||||||
// domain -> "example.com"
|
// domain -> "example.com"
|
||||||
// rr -> "@", "_acme-challenge"
|
// rr -> "@", "_acme-challenge"
|
||||||
|
|||||||
30
src/dns.rs
Normal file
30
src/dns.rs
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use rust_util::XResult;
|
||||||
|
use crate::ali_dns::AlibabaCloudDnsClient;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
pub struct DnsRecord {
|
||||||
|
pub id: String,
|
||||||
|
pub domain: String,
|
||||||
|
pub rr: String,
|
||||||
|
pub r#type: String,
|
||||||
|
pub ttl: i32,
|
||||||
|
pub value: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait DnsClient {
|
||||||
|
fn list_dns(&mut self, domain: &str) -> XResult<Vec<DnsRecord>>;
|
||||||
|
|
||||||
|
fn delete_dns_record(&mut self, record_id: &str) -> XResult<()>;
|
||||||
|
|
||||||
|
fn add_dns_record(&mut self, dns_record: &DnsRecord) -> XResult<()>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DnsClientFactory {}
|
||||||
|
|
||||||
|
impl DnsClientFactory {
|
||||||
|
pub fn build(supplier: &str) -> XResult<Box<dyn DnsClient>> {
|
||||||
|
Ok(Box::new(AlibabaCloudDnsClient::build(supplier)?))
|
||||||
|
//simple_error!("Build dns client failed: {}", supplier)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,6 +10,7 @@ mod x509;
|
|||||||
mod network;
|
mod network;
|
||||||
mod statics;
|
mod statics;
|
||||||
mod dingtalk;
|
mod dingtalk;
|
||||||
|
mod dns;
|
||||||
mod ali_dns;
|
mod ali_dns;
|
||||||
// mod simple_thread_pool;
|
// mod simple_thread_pool;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user