dns challenge for aliyun works
This commit is contained in:
156
src/ali_dns.rs
156
src/ali_dns.rs
@@ -1,11 +1,40 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use aliyun_openapi_core_rust_sdk::RPClient;
|
||||
use rust_util::XResult;
|
||||
|
||||
static ALI_DNS_ENDPOINT: &str = "https://alidns.aliyuncs.com";
|
||||
static ALI_DNS_API_VERSION: &str = "2015-01-09";
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AccessCredential {
|
||||
access_key_id: String,
|
||||
access_key_secret: String,
|
||||
}
|
||||
|
||||
// syntax: account://***:***@alibabacloud?id=dns
|
||||
pub fn simple_parse_aliyun_supplier(supplier: &str) -> XResult<AccessCredential> {
|
||||
if !supplier.starts_with("account://") {
|
||||
return simple_error!("Supplier syntax error: {}", supplier);
|
||||
}
|
||||
let access_key_id_and_secret: String = supplier.chars().skip("account://".len()).take_while(|c| *c != '@').collect();
|
||||
let c_pos = opt_value_result!(access_key_id_and_secret.find(":"), "Supplier syntax error: {}", supplier);
|
||||
|
||||
let access_key_id = access_key_id_and_secret.chars().take(c_pos).collect();
|
||||
let access_key_secret = access_key_id_and_secret.chars().skip(c_pos + 1).collect();
|
||||
|
||||
Ok(AccessCredential { access_key_id, access_key_secret })
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct ListDnsResponseErrorResponse {
|
||||
pub struct CommonSuccessResponse {
|
||||
#[serde(rename = "RequestId")]
|
||||
pub request_id: String,
|
||||
#[serde(rename = "RecordId")]
|
||||
pub record_id: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct CommonErrorResponse {
|
||||
#[serde(rename = "RequestId")]
|
||||
pub request_id: String,
|
||||
#[serde(rename = "Message")]
|
||||
@@ -29,7 +58,13 @@ pub struct ListDnsResponse {
|
||||
#[serde(rename = "PageNumber")]
|
||||
pub page_number: i32,
|
||||
#[serde(rename = "DomainRecords")]
|
||||
pub domain_records: Vec<DnsRecord>,
|
||||
pub domain_records: DnsRecords,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct DnsRecords {
|
||||
#[serde(rename = "Record")]
|
||||
pub record: Vec<DnsRecord>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
@@ -53,106 +88,69 @@ pub struct DnsRecord {
|
||||
#[serde(rename = "TTL")]
|
||||
pub ttl: i32,
|
||||
#[serde(rename = "Weight")]
|
||||
pub weight: i32,
|
||||
pub weight: Option<i32>,
|
||||
}
|
||||
|
||||
pub struct Response {
|
||||
#[serde(rename = "RequestId")]
|
||||
pub request_id: String,
|
||||
#[serde(rename = "RecordId")]
|
||||
pub record_id: String,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AccessCredential {
|
||||
access_key_id: String,
|
||||
access_key_secret: String,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
let a = AccessCredential {
|
||||
access_key_id: "***".to_string(),
|
||||
access_key_secret: "***".to_string(),
|
||||
};
|
||||
let client = create_dns_client(&a);
|
||||
println!("{}", list_dns(&client, "webauthn1.host").unwrap());
|
||||
// println!("{}", add_dns_txt(&client, "webauthn.host").unwrap());
|
||||
// println!("{}", delete_dns(&client, "744459160027659264").unwrap());
|
||||
}
|
||||
|
||||
// {
|
||||
// "TotalCount": 2,
|
||||
// "RequestId": "8993B447-F1FF-58ED-9D4B-1027B551DC5E",
|
||||
// "PageSize": 20,
|
||||
// "DomainRecords": {
|
||||
// "Record": [
|
||||
// {
|
||||
// "RR": "www",
|
||||
// "Line": "default",
|
||||
// "Status": "ENABLE",
|
||||
// "Locked": false,
|
||||
// "Type": "A",
|
||||
// "DomainName": "webauthn.host",
|
||||
// "Value": "47.52.7.223",
|
||||
// "RecordId": "714019124998091776",
|
||||
// "TTL": 1800,
|
||||
// "Weight": 1
|
||||
// },
|
||||
// {
|
||||
// "RR": "@",
|
||||
// "Line": "default",
|
||||
// "Status": "ENABLE",
|
||||
// "Locked": false,
|
||||
// "Type": "A",
|
||||
// "DomainName": "webauthn.host",
|
||||
// "Value": "47.52.7.223",
|
||||
// "RecordId": "714019101941960704",
|
||||
// "TTL": 1800,
|
||||
// "Weight": 1
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
// "PageNumber": 1
|
||||
// }
|
||||
pub fn list_dns(client: &RPClient, domain: &str) -> XResult<String> {
|
||||
Ok(client.get("DescribeDomainRecords")
|
||||
pub fn list_dns(client: &RPClient, domain: &str) -> XResult<Result<ListDnsResponse, CommonErrorResponse>> {
|
||||
let describe_domain_records_response = opt_result!(client.get("DescribeDomainRecords")
|
||||
.query(&[
|
||||
("RegionId", "cn-hangzhou"),
|
||||
("DomainName", domain)
|
||||
])
|
||||
.send()?)
|
||||
.send(), "List domain records: {}, failed: {}", domain);
|
||||
parse_result("DescribeDomainRecords", &describe_domain_records_response)
|
||||
}
|
||||
|
||||
// {"RequestId":"AD997158-68D2-5084-B6B9-5F5A0893DDC1","RecordId":"744459160027659264"}
|
||||
pub fn delete_dns(client: &RPClient, record_id: &str) -> XResult<String> {
|
||||
Ok(client.get("DeleteDomainRecord")
|
||||
pub fn delete_dns_record(client: &RPClient, record_id: &str) -> XResult<Result<CommonSuccessResponse, CommonErrorResponse>> {
|
||||
let delete_domain_record_response = opt_result!(client.get("DeleteDomainRecord")
|
||||
.query(&[
|
||||
("RegionId", "cn-hangzhou"),
|
||||
("RecordId", record_id)
|
||||
])
|
||||
.send()?)
|
||||
.send(), "Delete domain record id: {}, failed: {}", record_id);
|
||||
parse_result("DeleteDomainRecord", &delete_domain_record_response)
|
||||
}
|
||||
|
||||
// {"RequestId":"F3D54AB2-7058-54FD-AAF3-566FB8EC9BD1","RecordId":"744459160027659264"}
|
||||
pub fn add_dns_txt(client: &RPClient, domain: &str) -> XResult<String> {
|
||||
Ok(client.get("AddDomainRecord")
|
||||
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)
|
||||
}
|
||||
|
||||
// domain -> "example.com"
|
||||
// rr -> "@", "_acme-challenge"
|
||||
// t -> "TXT"
|
||||
// value -> "test"
|
||||
pub fn add_dns_record(client: &RPClient, domain: &str, rr: &str, t: &str, value: &str) -> XResult<Result<CommonSuccessResponse, CommonErrorResponse>> {
|
||||
let add_domain_record_response = opt_result!(client.get("AddDomainRecord")
|
||||
.query(&[
|
||||
("RegionId", "cn-hangzhou"),
|
||||
("DomainName", domain),
|
||||
("RR", "_acme-challenge_test"),
|
||||
("Type", "TXT"),
|
||||
("Value", "test")
|
||||
("RR", rr),
|
||||
("Type", t),
|
||||
("Value", value)
|
||||
])
|
||||
.send()?)
|
||||
.send(), "Add domain record: {}.{} -> {} {} ,failed: {}", rr, domain, t, value);
|
||||
parse_result("AddDomainRecord", &add_domain_record_response)
|
||||
}
|
||||
|
||||
fn create_dns_client(access_credential: &AccessCredential) -> RPClient {
|
||||
pub fn build_dns_client(access_credential: &AccessCredential) -> RPClient {
|
||||
RPClient::new(
|
||||
access_credential.access_key_id.clone(),
|
||||
access_credential.access_key_secret.clone(),
|
||||
String::from(ALI_DNS_ENDPOINT),
|
||||
String::from(ALI_DNS_API_VERSION),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_result<'a, S, E>(fn_name: &str, response: &'a str) -> XResult<Result<S, E>> where S: Deserialize<'a>, E: Deserialize<'a> {
|
||||
let describe_domain_records_result: serde_json::Result<S> = serde_json::from_str(&response);
|
||||
match describe_domain_records_result {
|
||||
Ok(r) => Ok(Ok(r)),
|
||||
Err(_) => {
|
||||
let describe_domain_records_error_result: serde_json::Result<E> = serde_json::from_str(&response);
|
||||
match describe_domain_records_error_result {
|
||||
Ok(r) => Ok(Err(r)),
|
||||
Err(_) => simple_error!("Parse {} response failed: {}", fn_name, response),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user