add basic record creation route
This commit is contained in:
parent
936addb624
commit
b7db84e9a8
3 changed files with 60 additions and 20 deletions
|
@ -18,7 +18,7 @@ use super::trust_dns_types::{self, Name};
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize, Clone)]
|
||||||
#[serde(tag = "Type")]
|
#[serde(tag = "Type")]
|
||||||
#[serde(rename_all = "UPPERCASE")]
|
#[serde(rename_all = "UPPERCASE")]
|
||||||
pub enum RData {
|
pub enum RData {
|
||||||
|
@ -101,6 +101,8 @@ pub enum RData {
|
||||||
data: String,
|
data: String,
|
||||||
},
|
},
|
||||||
// ZERO,
|
// ZERO,
|
||||||
|
|
||||||
|
// TODO: DS
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<trust_dns_types::RData> for RData {
|
impl From<trust_dns_types::RData> for RData {
|
||||||
|
@ -156,6 +158,7 @@ impl From<trust_dns_types::RData> for RData {
|
||||||
fingerprint: trust_dns_types::sshfp::HEX.encode(sshfp.fingerprint()),
|
fingerprint: trust_dns_types::sshfp::HEX.encode(sshfp.fingerprint()),
|
||||||
},
|
},
|
||||||
//TODO: This might alter data if not utf8 compatible, probably need to be replaced
|
//TODO: This might alter data if not utf8 compatible, probably need to be replaced
|
||||||
|
//TODO: check whether concatenating txt data is harmful or not
|
||||||
trust_dns_types::RData::TXT(txt) => RData::TXT { text: format!("{}", txt) },
|
trust_dns_types::RData::TXT(txt) => RData::TXT { text: format!("{}", txt) },
|
||||||
trust_dns_types::RData::DNSSEC(data) => RData::DNSSEC(data),
|
trust_dns_types::RData::DNSSEC(data) => RData::DNSSEC(data),
|
||||||
rdata => {
|
rdata => {
|
||||||
|
@ -284,7 +287,7 @@ impl<'a> fmt::Display for CAAValue<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize, Clone)]
|
||||||
pub enum DNSClass {
|
pub enum DNSClass {
|
||||||
IN,
|
IN,
|
||||||
CH,
|
CH,
|
||||||
|
@ -340,7 +343,7 @@ where
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize, Clone)]
|
||||||
pub struct Record {
|
pub struct Record {
|
||||||
#[serde(rename = "Name")]
|
#[serde(rename = "Name")]
|
||||||
pub name: SerdeName,
|
pub name: SerdeName,
|
||||||
|
@ -374,7 +377,7 @@ impl TryFrom<Record> for trust_dns_types::Record {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct SerdeName(Name);
|
pub struct SerdeName(Name);
|
||||||
|
|
||||||
impl<'de> Deserialize<'de> for SerdeName {
|
impl<'de> Deserialize<'de> for SerdeName {
|
||||||
|
|
|
@ -24,7 +24,7 @@ use crate::models::errors::{ErrorResponse, make_500};
|
||||||
use crate::models::dns::AbsoluteName;
|
use crate::models::dns::AbsoluteName;
|
||||||
|
|
||||||
const BEARER: &str = "Bearer ";
|
const BEARER: &str = "Bearer ";
|
||||||
const AUTH_HEADER: &str = "Authentication";
|
const AUTH_HEADER: &str = "Authorization";
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, DbEnum, Deserialize, Clone)]
|
#[derive(Debug, DbEnum, Deserialize, Clone)]
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
use std::convert::TryFrom;
|
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
use serde_json::json;
|
||||||
use rocket::Response;
|
use rocket::Response;
|
||||||
use rocket::http::Status;
|
use rocket::http::Status;
|
||||||
|
|
||||||
use rocket_contrib::json::Json;
|
use rocket_contrib::json::Json;
|
||||||
|
|
||||||
use serde_json::json;
|
|
||||||
|
|
||||||
use trust_dns_client::{client::ClientHandle, op::UpdateMessage};
|
use trust_dns_client::{client::ClientHandle, op::UpdateMessage};
|
||||||
use trust_dns_client::op::ResponseCode;
|
use trust_dns_client::op::ResponseCode;
|
||||||
use trust_dns_client::rr::{DNSClass, RecordType};
|
use trust_dns_client::rr::{DNSClass, RecordType};
|
||||||
|
@ -50,8 +47,10 @@ pub async fn get_zone_records(
|
||||||
println!("Querrying AXFR of zone {} failed with code {}", *zone, response.response_code());
|
println!("Querrying AXFR of zone {} failed with code {}", *zone, response.response_code());
|
||||||
return ErrorResponse::new(
|
return ErrorResponse::new(
|
||||||
Status::NotFound,
|
Status::NotFound,
|
||||||
format!("Zone {} could not be found", *zone)
|
"Zone could not be found".into()
|
||||||
).err()
|
).with_details(json!({
|
||||||
|
"zone_name": zone.to_utf8()
|
||||||
|
})).err();
|
||||||
}
|
}
|
||||||
|
|
||||||
let answers = response.answers();
|
let answers = response.answers();
|
||||||
|
@ -85,21 +84,46 @@ pub async fn create_zone_records(
|
||||||
user_info.get_zone(c, &zone_name)
|
user_info.get_zone(c, &zone_name)
|
||||||
}
|
}
|
||||||
}).await?;
|
}).await?;
|
||||||
|
|
||||||
// TODO: What about relative names (also in cnames and stuff)
|
// TODO: What about relative names (also in cnames and stuff)
|
||||||
// TODO: error handling
|
let mut bad_records = Vec::new();
|
||||||
let records: Vec<trust_dns_types::Record> = new_records.into_inner().into_iter().map(|r| r.try_into().unwrap()).collect();
|
let mut records: Vec<trust_dns_types::Record> = Vec::new();
|
||||||
|
|
||||||
|
for record in new_records.into_inner().into_iter() {
|
||||||
|
let this_record = record.clone();
|
||||||
|
if let Ok(record) = record.try_into() {
|
||||||
|
records.push(record);
|
||||||
|
} else {
|
||||||
|
bad_records.push(this_record.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let bad_zone_records: Vec<_> = records.iter().filter(|record| !zone.zone_of(record.name())).collect();
|
let bad_zone_records: Vec<_> = records.iter().filter(|record| !zone.zone_of(record.name())).collect();
|
||||||
// TODO: Get zone class from somewhere instead of always assuming IN
|
// TODO: Get zone class from somewhere instead of always assuming IN
|
||||||
let bad_class_records: Vec<_> = records.iter().filter(|record| record.dns_class() != DNSClass::IN).collect();
|
let bad_class_records: Vec<_> = records.iter().filter(|record| record.dns_class() != DNSClass::IN).collect();
|
||||||
|
|
||||||
|
if !bad_records.is_empty() {
|
||||||
|
return ErrorResponse::new(
|
||||||
|
Status::BadRequest,
|
||||||
|
"Record list contains records that could not been parsed into DNS records".into()
|
||||||
|
).with_details(
|
||||||
|
json!({
|
||||||
|
"zone_name": zone.to_utf8(),
|
||||||
|
"records": bad_records
|
||||||
|
})
|
||||||
|
).err();
|
||||||
|
}
|
||||||
|
|
||||||
if !bad_zone_records.is_empty() {
|
if !bad_zone_records.is_empty() {
|
||||||
return ErrorResponse::new(
|
return ErrorResponse::new(
|
||||||
Status::BadRequest,
|
Status::BadRequest,
|
||||||
format!("Record list contains records whose name that do not belong to the zone {}", *zone)
|
"Record list contains records whose name does not belong to the zone".into()
|
||||||
).with_details(
|
).with_details(
|
||||||
json!(bad_zone_records.into_iter().map(|r| r.name().to_utf8()).collect::<Vec<_>>())
|
json!({
|
||||||
).err()
|
"zone_name": zone.to_utf8(),
|
||||||
|
"records": bad_zone_records.into_iter().map(|r| r.clone().into()).collect::<Vec<dns::Record>>()
|
||||||
|
})
|
||||||
|
).err();
|
||||||
}
|
}
|
||||||
|
|
||||||
if !bad_class_records.is_empty() {
|
if !bad_class_records.is_empty() {
|
||||||
|
@ -107,8 +131,11 @@ pub async fn create_zone_records(
|
||||||
Status::BadRequest,
|
Status::BadRequest,
|
||||||
"Record list contains records whose class differs from the zone class `IN`".into()
|
"Record list contains records whose class differs from the zone class `IN`".into()
|
||||||
).with_details(
|
).with_details(
|
||||||
json!(bad_class_records.into_iter().map(|r| r.name().to_utf8()).collect::<Vec<_>>())
|
json!({
|
||||||
).err()
|
"zone_name": zone.to_utf8(),
|
||||||
|
"records": bad_class_records.into_iter().map(|r| r.clone().into()).collect::<Vec<dns::Record>>()
|
||||||
|
})
|
||||||
|
).err();
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut zone_query = Query::new();
|
let mut zone_query = Query::new();
|
||||||
|
@ -132,12 +159,22 @@ pub async fn create_zone_records(
|
||||||
edns.set_version(0);
|
edns.set_version(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: check if NOERROR or something
|
let response = {
|
||||||
let _response = {
|
|
||||||
let query = dns::ClientResponse(client.send(message));
|
let query = dns::ClientResponse(client.send(message));
|
||||||
query.await.map_err(make_500)?
|
query.await.map_err(make_500)?
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO: better error handling
|
||||||
|
if response.response_code() != ResponseCode::NoError {
|
||||||
|
println!("Update of zone {} failed with code {}", *zone, response.response_code());
|
||||||
|
return ErrorResponse::new(
|
||||||
|
Status::NotFound,
|
||||||
|
"Update of zone failed".into()
|
||||||
|
).with_details(json!({
|
||||||
|
"zone_name": zone.to_utf8()
|
||||||
|
})).err();
|
||||||
|
}
|
||||||
|
|
||||||
Ok(Json(()))
|
Ok(Json(()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue