Delegation WIP.

This commit is contained in:
Philippe Pittoli 2025-07-17 23:49:52 +02:00
parent 09a97386a9
commit c5433bb95a
2 changed files with 69 additions and 14 deletions

View file

@ -15,6 +15,7 @@ class DNSManager::Storage
getter zones : DODB::Storage::Common(Zone)
getter zones_by_domain : DODB::Trigger::IndexCached(Zone)
getter zones_by_delegation : DODB::Trigger::Tags(Zone)
getter tokens : DODB::Storage::Common(Token)
getter tokens_by_uuid : DODB::Trigger::IndexCached(Token)
@ -51,6 +52,13 @@ class DNSManager::Storage
@domains_by_owners = @domains.new_tags "owners", &.owners.map &.to_s
@zones = DODB::Storage::Common(Zone).new "#{@root}/zones", 5_000
@zones_by_domain = @zones.new_index "domain", &.domain
@zones_by_delegation = @zones.new_tags "delegation", do |z|
if delegation = z.delegation
[ delegation.nameserver1, delegation.nameserver2 ]
else
DODB.no_index
end
end
@tokens = DODB::Storage::Common(Token).new "#{@root}/tokens", 5_000
@tokens_by_uuid = @tokens.new_index "uuid", &.uuid
@tokens_by_domain = @tokens.new_partition "domain", &.domain
@ -77,6 +85,11 @@ class DNSManager::Storage
def generate_bind9_zonefile(domain : String) : Nil
zone = zone_must_exist! domain
if delegation = zone.delegation
Baguette::Log.info "zone #{domain} is delegated"
return
end
# Safe write.
filename_final = "#{@zonefiledir}/#{zone.domain}"
filename_wip = "#{filename_final}.wip"
@ -433,12 +446,29 @@ class DNSManager::Storage
Response::Zone.new zone
end
# TODO, FIXME: verifications + actually delegate the domain.
def delegate_domain(user_id : UserDataID, domain : String, nameserver1 : String, nameserver2 : String) : IPC::JSON
zone = zone_must_exist! domain
user_should_own! user_id, domain
# Deletes the zone and its tokens to wipe the zone data then delegates the domain.
def delegate_domain(user_id : UserDataID, domain_name : String,
nameserver1 : String, nameserver2 : String) : IPC::JSON
_ = zone_must_exist! domain_name
user_should_own! user_id, domain_name
Response::DomainDelegated.new domain, nameserver1, nameserver2
# Name server domains verification.
return Response::InvalidDomainName.new unless Zone.is_domain_valid? nameserver1
return Response::InvalidDomainName.new unless Zone.is_domain_valid? nameserver2
# Remove the related zone and their registered tokens.
zones_by_domain.delete domain_name
# The domain may not have tokens.
tokens_by_domain.delete? domain_name
# TODO, FIXME: actually delegate the domain.
zone = Zone.new domain_name
zone.delegation = Zone::Delegation.new nameserver1, nameserver2
zones_by_domain.update_or_create zone.domain, zone
Response::DomainDelegated.new domain_name, nameserver1, nameserver2
end
# Removes user data.

View file

@ -29,6 +29,8 @@ class DNSManager::Storage::Zone
property resources = [] of DNSManager::Storage::Zone::ResourceRecord
property current_rrid : UInt32 = 0
property delegation : Delegation? = nil
# We don't want to accept less than 30 seconds TTL.
class_property ttl_limit_min = 30
@ -37,6 +39,22 @@ class DNSManager::Storage::Zone
def_clone
class Delegation
include JSON::Serializable
property nameserver1 : String
property nameserver2 : String
def initialize(@nameserver1, @nameserver2)
end
def to_s(io : IO)
io << "#{@nameserver1} #{@nameserver2}\n"
end
def_clone
end
alias Error = String
# Store a Resource Record: A, AAAA, TXT, PTR, CNAME…
@ -918,14 +936,21 @@ class DNSManager::Storage::Zone
def to_s(io : IO)
io << "ZONE #{@domain} (#{@resources.size} rr)"
if delegation = @delegation
io << " delegated"
end
end
def pretty_print(io : IO)
io << "DOMAIN #{@domain}.\n"
if delegation = @delegation
io << "ZONE #{@domain} delegated (to '#{delegation.nameserver1}' and '#{delegation.nameserver2}')\n"
else
io << "ZONE #{@domain}.\n"
@resources.each do |rr|
io << rr
end
end
end
def to_bind9(io : IO)
io << "$ORIGIN #{@domain}.\n"