Add and replace RR.

This commit is contained in:
Philippe Pittoli 2023-05-08 17:34:50 +02:00
parent 05aa4421b3
commit 8528f74fae
6 changed files with 143 additions and 16 deletions

View File

@ -18,7 +18,7 @@ class DNSManager::Client < IPC
expected_messages.each do |e| expected_messages.each do |e|
em << e em << e
end end
em << DNSManager::Response::Error em << Response::Error
em.parse_ipc_json message em.parse_ipc_json message
end end
@ -27,35 +27,42 @@ class DNSManager::Client < IPC
# #
def login(token : String) def login(token : String)
request = DNSManager::Request::Login.new token request = Request::Login.new token
send_now request send_now request
parse_message [ Response::Success ], read parse_message [ Response::Success ], read
end end
# Adding a full zone. # Adding a full zone.
def user_zone_add(zone : DNSManager::Storage::Zone) def user_zone_add(zone : Storage::Zone)
request = DNSManager::Request::AddOrUpdateZone.new zone request = Request::AddOrUpdateZone.new zone
send_now request send_now request
parse_message [ Response::Success ], read parse_message [ Response::Success ], read
end end
# Removing a zone. # Removing a zone.
def user_zone_del(domain : String) def user_zone_del(domain : String)
request = DNSManager::Request::DeleteZone.new domain request = Request::DeleteZone.new domain
send_now request send_now request
parse_message [ Response::Success ], read parse_message [ Response::Success ], read
end end
# Get a zone. # Get a zone.
def user_zone_get(domain : String) def user_zone_get(domain : String)
request = DNSManager::Request::GetZone.new domain request = Request::GetZone.new domain
send_now request send_now request
parse_message [ Response::Zone ], read parse_message [ Response::Zone ], read
end end
# Add a RR.
def user_rr_add(domain : String, rr : Storage::Zone::ResourceRecord)
request = Request::AddRR.new domain, rr
send_now request
parse_message [ Response::Success ], read
end
# Get user domain list. # Get user domain list.
def user_domain_list() def user_domain_list()
request = DNSManager::Request::UserDomains.new request = Request::UserDomains.new
send_now request send_now request
parse_message [ Response::DomainList ], read parse_message [ Response::DomainList ], read
end end
@ -64,13 +71,13 @@ class DNSManager::Client < IPC
# Admin stuff. # Admin stuff.
# #
def admin_maintenance(key : String, subject : DNSManager::Request::Maintenance::Subject, value : Int32? = nil) def admin_maintenance(key : String, subject : Request::Maintenance::Subject, value : Int32? = nil)
request = DNSManager::Request::Maintenance.new(key,subject) request = Request::Maintenance.new(key,subject)
if value if value
request.value = value request.value = value
end end
send_now request send_now request
parse_message [ DNSManager::Response::Success ], read parse_message [ Response::Success ], read
end end
def send_now(msg : IPC::JSON) def send_now(msg : IPC::JSON)

View File

@ -35,12 +35,17 @@ class Actions
# Admin section. # Admin section.
# #
# Maintenance # Maintenance.
@the_call["admin-maintenance"] = ->admin_maintenance @the_call["admin-maintenance"] = ->admin_maintenance
# Zone operations.
@the_call["user-zone-add"] = ->user_zone_add @the_call["user-zone-add"] = ->user_zone_add
@the_call["user-zone-del"] = ->user_zone_del @the_call["user-zone-del"] = ->user_zone_del
@the_call["user-zone-get"] = ->user_zone_get @the_call["user-zone-get"] = ->user_zone_get
# Zone RR operations.
@the_call["user-rr-add-a"] = ->user_rr_add_a
@the_call["user-domain-list"] = ->user_domain_list @the_call["user-domain-list"] = ->user_domain_list
end end
@ -129,6 +134,16 @@ class Actions
puts "error for user_zone_del: #{e.message}" puts "error for user_zone_del: #{e.message}"
end end
def user_rr_add_a
domain, name, ttl, target = Context.args.not_nil!
begin
rr = DNSManager::Storage::Zone::A.new name, ttl.to_u32, target
pp! @dnsmanagerd.user_rr_add domain, rr
rescue e
puts "error for user_rr_add_a: #{e.message}"
end
end
end end
def main def main

View File

@ -143,6 +143,19 @@ def parsing_cli(authd_config : Baguette::Configuration::Auth)
end end
end end
parser.on("rr", "Zone Resource Record operations.") do
parser.on("add", "Add new RR.") do
Baguette::Log.info "Add RR."
parser.banner = "COMMAND: user rr add [A|AAAA|CNAME|MX|SRV|TXT|NS]"
parser.on("A", "Add new A RR.") do
Baguette::Log.info "add new A RR."
Context.command = "user-rr-add-a"
parser.banner = "COMMAND: user rr add A <domain> <NAME> <TTL> <TARGET>"
unrecognized_args_to_context_args.call parser, 4, nil
end
end
end
end end
opt_help.call parser opt_help.call parser

View File

@ -56,4 +56,34 @@ class DNSManager::Request
end end
end end
DNSManager.requests << UserDomains DNSManager.requests << UserDomains
IPC::JSON.message AddRR, 14 do
property domain : String
property rr : DNSManager::Storage::Zone::ResourceRecord
def initialize(@domain, @rr)
end
def handle(dnsmanagerd : DNSManager::Service, event : IPC::Event) : IPC::JSON
user = dnsmanagerd.get_logged_user event
raise NotLoggedException.new if user.nil?
dnsmanagerd.storage.add_rr user.uid, @domain, @rr
end
end
DNSManager.requests << AddRR
IPC::JSON.message UpdateRR, 15 do
property domain : String
property rr : DNSManager::Storage::Zone::ResourceRecord
def initialize(@domain, @rr)
end
def handle(dnsmanagerd : DNSManager::Service, event : IPC::Event) : IPC::JSON
user = dnsmanagerd.get_logged_user event
raise NotLoggedException.new if user.nil?
dnsmanagerd.storage.update_rr user.uid, @domain, @rr
end
end
DNSManager.requests << UpdateRR
end end

View File

@ -48,7 +48,7 @@ class DNSManager::Storage
user_data = user_data_by_uid.get? user_id.to_s user_data = user_data_by_uid.get? user_id.to_s
unless user_data unless user_data
Baguette::Log.info "New user #{user_id}" Baguette::Log.info "New user #{user_id}"
@user_data << Storage::UserData.new user_id @user_data << UserData.new user_id
end end
Response::Success.new Response::Success.new
@ -58,7 +58,7 @@ class DNSManager::Storage
# Test zone validity. # Test zone validity.
if errors = zone.get_errors? if errors = zone.get_errors?
Baguette::Log.warning "zone #{zone.domain} update with errors: #{errors}" Baguette::Log.warning "zone #{zone.domain} update with errors: #{errors}"
return DNSManager::Response::InvalidZone.new errors return Response::InvalidZone.new errors
end end
# User must exist. # User must exist.
@ -92,6 +92,68 @@ class DNSManager::Storage
Response::Error.new "error while updating the domain #{zone.domain}" Response::Error.new "error while updating the domain #{zone.domain}"
end end
def add_rr(user_id : Int32, domain : String, rr : Zone::ResourceRecord) : IPC::JSON
# User must exist.
user_data = user_data_by_uid.get? user_id.to_s
unless user_data
Baguette::Log.warning "unknown user #{user_id} tries to add a RR in domain #{domain}"
return Response::UnknownUser.new
end
# Zone must exist.
zone = zones_by_domain.get? domain
unless zone
return Response::InvalidZone.new ["Domain not found."]
end
# User must own the zone.
unless user_data.domains.includes? domain
Baguette::Log.warning "user #{user_id} doesn't own domain #{domain}"
return Response::NoOwnership.new
end
zone << rr
# Update the zone.
zones_by_domain.update_or_create zone.domain, zone
Response::Success.new
rescue e
Baguette::Log.error "trying to add a resource record in domain #{domain}: #{e}"
Response::Error.new "error while adding a resource record in domain #{domain}"
end
def update_rr(user_id : Int32, domain : String, rr : Zone::ResourceRecord) : IPC::JSON
# User must exist.
user_data = user_data_by_uid.get? user_id.to_s
unless user_data
Baguette::Log.warning "unknown user #{user_id} tries to add -or update- zone #{domain}"
return Response::UnknownUser.new
end
# Zone must exist.
zone = zones_by_domain.get? domain
unless zone
return Response::InvalidZone.new ["Domain not found."]
end
# User must own the zone.
unless user_data.domains.includes? domain
Baguette::Log.warning "user #{user_id} doesn't own domain #{domain}"
return Response::NoOwnership.new
end
zone.resources.map { |x| x.rrid == rr.rrid ? rr : x }
# Update the zone.
zones_by_domain.update_or_create zone.domain, zone
Response::Success.new
rescue e
Baguette::Log.error "trying to replace a resource record in domain #{domain}: #{e}"
Response::Error.new "error while replacing a resource record in domain #{domain}"
end
def delete_domain(user_id : Int32, domain : String) : IPC::JSON def delete_domain(user_id : Int32, domain : String) : IPC::JSON
# User must exist. # User must exist.
user_data = user_data_by_uid.get? user_id.to_s user_data = user_data_by_uid.get? user_id.to_s

View File

@ -50,7 +50,7 @@ class DNSManager::Storage::Zone
end end
def to_s(io : IO) def to_s(io : IO)
io << "#{ "%30s" % @name} #{ "%6d" % @ttl} IN #{ "%10s" % @rrtype.upcase} #{ "%30s" % @target}\n" io << "(#{ "%4d" % @rrid }) #{ "%30s" % @name} #{ "%6d" % @ttl} IN #{ "%10s" % @rrtype.upcase} #{ "%30s" % @target}\n"
end end
end end
@ -70,7 +70,7 @@ class DNSManager::Storage::Zone
end end
def to_s(io : IO) def to_s(io : IO)
io << "#{name} #{ttl} #{target} #{@rrtype.upcase} (#{mname} #{rname}\n" io << "(#{ "%4d" % @rrid }) #{name} #{ttl} #{target} #{@rrtype.upcase} (#{mname} #{rname}\n"
io << "\t\t#{ "%10d" % serial} ; serial\n" io << "\t\t#{ "%10d" % serial} ; serial\n"
io << "\t\t#{ "%10d" % refresh} ; refresh\n" io << "\t\t#{ "%10d" % refresh} ; refresh\n"
io << "\t\t#{ "%10d" % retry} ; retry\n" io << "\t\t#{ "%10d" % retry} ; retry\n"
@ -225,7 +225,7 @@ class DNSManager::Storage::Zone
end end
def to_s(io : IO) def to_s(io : IO)
io << "#{ "%30s" % @name} #{ "%6d" % @ttl} IN MX #{ "%3d" % @priority} #{ "%30s" % @target}\n" io << "(#{ "%4d" % @rrid }) #{ "%30s" % @name} #{ "%6d" % @ttl} IN MX #{ "%3d" % @priority} #{ "%30s" % @target}\n"
end end
def get_errors : Array(Error) def get_errors : Array(Error)