basic zone configuration
This commit is contained in:
parent
76f222e1c4
commit
1f3aa12401
6 changed files with 111 additions and 10 deletions
24
dev-scripts/config/knot.conf
Normal file
24
dev-scripts/config/knot.conf
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
server:
|
||||||
|
listen: [ 0.0.0.0@5353, ::@5353 ]
|
||||||
|
|
||||||
|
log:
|
||||||
|
- target: stderr
|
||||||
|
any: debug
|
||||||
|
|
||||||
|
acl:
|
||||||
|
- id: example_acl
|
||||||
|
address: [ 127.0.0.1, ::1]
|
||||||
|
action: transfer
|
||||||
|
|
||||||
|
template:
|
||||||
|
- id: default
|
||||||
|
file: "zones/%s.zone"
|
||||||
|
journal-content: all
|
||||||
|
zonefile-load: difference-no-serial
|
||||||
|
zonefile-sync: -1
|
||||||
|
serial-policy: dateserial
|
||||||
|
|
||||||
|
zone:
|
||||||
|
- domain: example.com
|
||||||
|
acl: example_acl
|
||||||
|
template: default
|
8
dev-scripts/docker-compose.yml
Normal file
8
dev-scripts/docker-compose.yml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
services:
|
||||||
|
knot:
|
||||||
|
image: cznic/knot
|
||||||
|
volumes:
|
||||||
|
- $PWD/zones:/storage/zones:ro
|
||||||
|
- $PWD/config:/config:ro
|
||||||
|
command: knotd
|
||||||
|
network_mode: host
|
13
dev-scripts/zones/example.com.zone
Normal file
13
dev-scripts/zones/example.com.zone
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
example.com. IN SOA ns.example.com. admin.example.com. (
|
||||||
|
2020250101 ; serial
|
||||||
|
28800 ; refresh (8 hours)
|
||||||
|
7200 ; retry (2 hours)
|
||||||
|
2419200 ; expire (4 weeks)
|
||||||
|
300 ; minimum (5 minutes)
|
||||||
|
)
|
||||||
|
|
||||||
|
example.com. 84600 IN NS ns.example.com.
|
||||||
|
|
||||||
|
srv1.example.com. 600 IN A 198.51.100.3
|
||||||
|
srv1.example.com. 600 IN AAAA 2001:db8:cafe:bc68::2
|
||||||
|
www 600 IN CNAME srv1
|
|
@ -27,6 +27,7 @@ async fn rocket() -> rocket::Rocket {
|
||||||
.mount("/api/v1", routes![
|
.mount("/api/v1", routes![
|
||||||
get_zone_records,
|
get_zone_records,
|
||||||
get_zones,
|
get_zones,
|
||||||
|
create_zone,
|
||||||
add_member_to_zone,
|
add_member_to_zone,
|
||||||
create_auth_token,
|
create_auth_token,
|
||||||
create_user
|
create_user
|
||||||
|
|
|
@ -21,7 +21,7 @@ use crate::schema::*;
|
||||||
use crate::DbConn;
|
use crate::DbConn;
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
use crate::models::errors::{ErrorResponse, make_500};
|
use crate::models::errors::{ErrorResponse, make_500};
|
||||||
|
use crate::models::dns::AbsoluteName;
|
||||||
|
|
||||||
const BEARER: &str = "Bearer ";
|
const BEARER: &str = "Bearer ";
|
||||||
const AUTH_HEADER: &str = "Authentication";
|
const AUTH_HEADER: &str = "Authentication";
|
||||||
|
@ -82,6 +82,11 @@ pub struct AddZoneMemberRequest {
|
||||||
pub id: String,
|
pub id: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct CreateZoneRequest {
|
||||||
|
pub name: AbsoluteName,
|
||||||
|
}
|
||||||
|
|
||||||
// pub struct LdapUserAssociation {
|
// pub struct LdapUserAssociation {
|
||||||
// user_id: Uuid,
|
// user_id: Uuid,
|
||||||
// ldap_id: String
|
// ldap_id: String
|
||||||
|
@ -366,6 +371,25 @@ impl Zone {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn create_zone(conn: &diesel::SqliteConnection, zone_request: CreateZoneRequest) -> Result<Zone, UserError> {
|
||||||
|
use crate::schema::zone::dsl::*;
|
||||||
|
|
||||||
|
let new_zone = Zone {
|
||||||
|
id: Uuid::new_v4().to_simple().to_string(),
|
||||||
|
name: zone_request.name.to_utf8(),
|
||||||
|
};
|
||||||
|
|
||||||
|
diesel::insert_into(zone)
|
||||||
|
.values(&new_zone)
|
||||||
|
.execute(conn)
|
||||||
|
.map_err(|e| match e {
|
||||||
|
DieselError::DatabaseError(diesel::result::DatabaseErrorKind::UniqueViolation, _) => UserError::UserConflict,
|
||||||
|
other => UserError::DbError(other)
|
||||||
|
})?;
|
||||||
|
Ok(new_zone)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn add_member(&self, conn: &diesel::SqliteConnection, new_member: &UserInfo) -> Result<(), UserError> {
|
pub fn add_member(&self, conn: &diesel::SqliteConnection, new_member: &UserInfo) -> Result<(), UserError> {
|
||||||
use crate::schema::user_zone::dsl::*;
|
use crate::schema::user_zone::dsl::*;
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ use trust_dns_client::rr::{DNSClass, RecordType};
|
||||||
|
|
||||||
use crate::{DbConn, models::dns};
|
use crate::{DbConn, models::dns};
|
||||||
use crate::models::errors::{ErrorResponse, make_500};
|
use crate::models::errors::{ErrorResponse, make_500};
|
||||||
use crate::models::users::{LocalUser, UserInfo, Zone, AddZoneMemberRequest};
|
use crate::models::users::{LocalUser, UserInfo, Zone, AddZoneMemberRequest, CreateZoneRequest};
|
||||||
|
|
||||||
|
|
||||||
#[get("/zones/<zone>/records")]
|
#[get("/zones/<zone>/records")]
|
||||||
|
@ -21,22 +21,23 @@ pub async fn get_zone_records(
|
||||||
) -> Result<Json<Vec<dns::Record>>, ErrorResponse> {
|
) -> Result<Json<Vec<dns::Record>>, ErrorResponse> {
|
||||||
|
|
||||||
let user_info = user_info?;
|
let user_info = user_info?;
|
||||||
|
let zone_name = zone.to_string();
|
||||||
|
|
||||||
if !user_info.is_admin() {
|
|
||||||
let zone_name = zone.clone().to_string();
|
|
||||||
conn.run(move |c| {
|
conn.run(move |c| {
|
||||||
|
if user_info.is_admin() {
|
||||||
|
Zone::get_by_name(c, &zone_name)
|
||||||
|
} else {
|
||||||
user_info.get_zone(c, &zone_name)
|
user_info.get_zone(c, &zone_name)
|
||||||
}).await?;
|
|
||||||
}
|
}
|
||||||
|
}).await?;
|
||||||
|
|
||||||
let response = {
|
let response = {
|
||||||
let query = client.query(zone.clone(), DNSClass::IN, RecordType::AXFR);
|
let query = client.query(zone.clone(), DNSClass::IN, RecordType::AXFR);
|
||||||
query.await.map_err(make_500)?
|
query.await.map_err(make_500)?
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: Better error handling (ex. not authorized should be 500)
|
|
||||||
if response.response_code() != ResponseCode::NoError {
|
if response.response_code() != ResponseCode::NoError {
|
||||||
println!("Querrying 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)
|
format!("Zone {} could not be found", *zone)
|
||||||
|
@ -55,7 +56,6 @@ pub async fn get_zone_records(
|
||||||
Ok(Json(records))
|
Ok(Json(records))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: the post version of that
|
|
||||||
#[get("/zones")]
|
#[get("/zones")]
|
||||||
pub async fn get_zones(
|
pub async fn get_zones(
|
||||||
conn: DbConn,
|
conn: DbConn,
|
||||||
|
@ -74,6 +74,37 @@ pub async fn get_zones(
|
||||||
Ok(Json(zones))
|
Ok(Json(zones))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[post("/zones", data = "<zone_request>")]
|
||||||
|
pub async fn create_zone(
|
||||||
|
conn: DbConn,
|
||||||
|
mut client: dns::DnsClient,
|
||||||
|
user_info: Result<UserInfo, ErrorResponse>,
|
||||||
|
zone_request: Json<CreateZoneRequest>,
|
||||||
|
) -> Result<Json<Zone>, ErrorResponse> {
|
||||||
|
user_info?.check_admin()?;
|
||||||
|
|
||||||
|
|
||||||
|
// Check if the zone exists in the DNS server
|
||||||
|
let response = {
|
||||||
|
let query = client.query(zone_request.name.clone(), DNSClass::IN, RecordType::SOA);
|
||||||
|
query.await.map_err(make_500)?
|
||||||
|
};
|
||||||
|
|
||||||
|
if response.response_code() != ResponseCode::NoError {
|
||||||
|
println!("Querrying SOA of zone {} failed with code {}", *zone_request.name, response.response_code());
|
||||||
|
return ErrorResponse::new(
|
||||||
|
Status::NotFound,
|
||||||
|
format!("Zone {} could not be found", *zone_request.name)
|
||||||
|
).err()
|
||||||
|
}
|
||||||
|
|
||||||
|
let zone = conn.run(move |c| {
|
||||||
|
Zone::create_zone(c, zone_request.into_inner())
|
||||||
|
}).await?;
|
||||||
|
|
||||||
|
Ok(Json(zone))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[post("/zones/<zone>/members", data = "<zone_member_request>")]
|
#[post("/zones/<zone>/members", data = "<zone_member_request>")]
|
||||||
pub async fn add_member_to_zone<'r>(
|
pub async fn add_member_to_zone<'r>(
|
||||||
|
|
Loading…
Reference in a new issue