WIP: Tokens. Can create tokens for RRs and their indexes + partitions.
parent
0c817e1f96
commit
088980109d
|
@ -0,0 +1,35 @@
|
||||||
|
require "ipc/json"
|
||||||
|
require "grok"
|
||||||
|
|
||||||
|
class DNSManager::Request
|
||||||
|
IPC::JSON.message NewToken, 18 do
|
||||||
|
property domain : String
|
||||||
|
property rrid : UInt32
|
||||||
|
|
||||||
|
def initialize(@domain, @rrid)
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle(dnsmanagerd : DNSManager::Service, event : IPC::Event) : IPC::JSON
|
||||||
|
user = dnsmanagerd.get_logged_user event
|
||||||
|
return Response::ErrorUserNotLogged.new unless user
|
||||||
|
dnsmanagerd.storage.new_token user.uid, @domain, @rrid
|
||||||
|
end
|
||||||
|
end
|
||||||
|
DNSManager.requests << NewToken
|
||||||
|
|
||||||
|
IPC::JSON.message UseToken, 19 do
|
||||||
|
property token : String
|
||||||
|
property address : String
|
||||||
|
|
||||||
|
def initialize(@token, @address)
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle(dnsmanagerd : DNSManager::Service, event : IPC::Event) : IPC::JSON
|
||||||
|
user = dnsmanagerd.get_logged_user event
|
||||||
|
return Response::ErrorUserNotLogged.new unless user
|
||||||
|
return Response::InsufficientRights.new unless user.admin
|
||||||
|
dnsmanagerd.storage.use_token user.uid, @token, @address
|
||||||
|
end
|
||||||
|
end
|
||||||
|
DNSManager.requests << UseToken
|
||||||
|
end
|
|
@ -12,6 +12,10 @@ class DNSManager::Storage
|
||||||
getter zones : DODB::CachedDataBase(Zone)
|
getter zones : DODB::CachedDataBase(Zone)
|
||||||
getter zones_by_domain : DODB::Index(Zone)
|
getter zones_by_domain : DODB::Index(Zone)
|
||||||
|
|
||||||
|
getter tokens : DODB::CachedDataBase(Token)
|
||||||
|
getter tokens_by_uuid : DODB::Index(Token)
|
||||||
|
getter tokens_by_domain : DODB::Partition(Token)
|
||||||
|
|
||||||
getter root : String
|
getter root : String
|
||||||
getter zonefiledir : String
|
getter zonefiledir : String
|
||||||
|
|
||||||
|
@ -20,6 +24,9 @@ class DNSManager::Storage
|
||||||
@user_data_by_uid = @user_data.new_index "uid", &.uid.to_s
|
@user_data_by_uid = @user_data.new_index "uid", &.uid.to_s
|
||||||
@zones = DODB::CachedDataBase(Zone).new "#{@root}/zones"
|
@zones = DODB::CachedDataBase(Zone).new "#{@root}/zones"
|
||||||
@zones_by_domain = @zones.new_index "domain", &.domain
|
@zones_by_domain = @zones.new_index "domain", &.domain
|
||||||
|
@tokens = DODB::CachedDataBase(Token).new "#{@root}/tokens"
|
||||||
|
@tokens_by_uuid = @tokens.new_index "uuid", &.uuid
|
||||||
|
@tokens_by_domain = @tokens.new_partition "domain", &.domain
|
||||||
|
|
||||||
@zonefiledir = "#{@root}/bind9-zones"
|
@zonefiledir = "#{@root}/bind9-zones"
|
||||||
# TODO: create the directory
|
# TODO: create the directory
|
||||||
|
@ -32,6 +39,8 @@ class DNSManager::Storage
|
||||||
@user_data.reindex_everything!
|
@user_data.reindex_everything!
|
||||||
Baguette::Log.debug "Reindexing zones..."
|
Baguette::Log.debug "Reindexing zones..."
|
||||||
@zones.reindex_everything!
|
@zones.reindex_everything!
|
||||||
|
Baguette::Log.debug "Reindexing tokens..."
|
||||||
|
@tokens.reindex_everything!
|
||||||
Baguette::Log.debug "Reindexed!"
|
Baguette::Log.debug "Reindexed!"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -331,8 +340,9 @@ class DNSManager::Storage
|
||||||
# Update on-disk user data.
|
# Update on-disk user data.
|
||||||
update_user_data user_data
|
update_user_data user_data
|
||||||
|
|
||||||
# Remove the related zone.
|
# Remove the related zone and their registered tokens.
|
||||||
zones_by_domain.delete domain
|
zones_by_domain.delete domain
|
||||||
|
tokens_by_domain.delete domain
|
||||||
|
|
||||||
Response::DomainDeleted.new domain
|
Response::DomainDeleted.new domain
|
||||||
rescue e
|
rescue e
|
||||||
|
@ -378,6 +388,60 @@ class DNSManager::Storage
|
||||||
Baguette::Log.error "trying to list all user #{user_id} domains: #{e}"
|
Baguette::Log.error "trying to list all user #{user_id} domains: #{e}"
|
||||||
Response::Error.new "error while listing domains"
|
Response::Error.new "error while listing domains"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def new_token(user_id : Int32, domain : String, rrid : UInt32) : IPC::JSON
|
||||||
|
puts "new token for domain #{domain} rrid #{rrid}"
|
||||||
|
|
||||||
|
# 0. verifications: must exist: user, zone, RR. Zone must be owned by user.
|
||||||
|
|
||||||
|
# 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 get a new token for a RR in domain #{domain}"
|
||||||
|
return Response::UnknownUser.new
|
||||||
|
end
|
||||||
|
|
||||||
|
# Zone must exist.
|
||||||
|
zone = zones_by_domain.get? domain
|
||||||
|
return Response::DomainNotFound.new unless zone
|
||||||
|
|
||||||
|
# User should own it.
|
||||||
|
unless user_data.domains.includes?(domain) || user_data.admin
|
||||||
|
Baguette::Log.warning "user #{user_id} doesn't own domain #{domain}"
|
||||||
|
return Response::NoOwnership.new
|
||||||
|
end
|
||||||
|
|
||||||
|
# RR must exist.
|
||||||
|
rr = zone.get_rr rrid
|
||||||
|
return Response::RRNotFound.new unless rr
|
||||||
|
|
||||||
|
old_token = rr.token
|
||||||
|
|
||||||
|
# 1. create token
|
||||||
|
token = Token.new domain, rrid
|
||||||
|
|
||||||
|
# 2. add token to the RR.
|
||||||
|
rr.token = token.uuid
|
||||||
|
zone.update_rr rr
|
||||||
|
|
||||||
|
# 3. update the zone (no need to call `update_zone` to change the zone serial).
|
||||||
|
zones_by_domain.update_or_create zone.domain, zone
|
||||||
|
|
||||||
|
# 4. if there is an old token, remove it.
|
||||||
|
if old_token_uuid = old_token
|
||||||
|
tokens_by_uuid.delete old_token_uuid
|
||||||
|
end
|
||||||
|
|
||||||
|
# 5. add token to the db.
|
||||||
|
@tokens << token
|
||||||
|
|
||||||
|
Response::RRUpdated.new domain, rr
|
||||||
|
end
|
||||||
|
|
||||||
|
def use_token(user_id : Int32, token : String, address : String) : IPC::JSON
|
||||||
|
puts "use token #{token} address #{address}"
|
||||||
|
Response::Error.new "unimplemented"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
require "./storage/*"
|
require "./storage/*"
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
require "uuid"
|
||||||
|
|
||||||
|
class DNSManager::Storage::Token
|
||||||
|
include JSON::Serializable
|
||||||
|
|
||||||
|
property uuid : String
|
||||||
|
property domain : String
|
||||||
|
property rrid : UInt32
|
||||||
|
|
||||||
|
def initialize(@domain, @rrid)
|
||||||
|
@uuid = UUID.random.to_s
|
||||||
|
end
|
||||||
|
end
|
|
@ -55,8 +55,12 @@ class DNSManager::Storage::Zone
|
||||||
# Yes. It already happened. Many, MANY times. I WANT MY FUCKING TIME BACK.
|
# Yes. It already happened. Many, MANY times. I WANT MY FUCKING TIME BACK.
|
||||||
property readonly : Bool = false
|
property readonly : Bool = false
|
||||||
|
|
||||||
|
# RR entries can have an update token.
|
||||||
|
# This way, users can automatically update their IP address using a simple HTTP request (ex: with `wget`).
|
||||||
|
property token : String? = nil
|
||||||
|
|
||||||
# zone class is omited, it always will be IN in our case.
|
# zone class is omited, it always will be IN in our case.
|
||||||
def initialize(@name, @ttl, @target)
|
def initialize(@name, @ttl, @target, @token = nil)
|
||||||
@rrtype = self.class.name.upcase.gsub /DNSMANAGER::STORAGE::ZONE::/, ""
|
@rrtype = self.class.name.upcase.gsub /DNSMANAGER::STORAGE::ZONE::/, ""
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -619,6 +623,18 @@ class DNSManager::Storage::Zone
|
||||||
@current_rrid += 1
|
@current_rrid += 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def get_rr(rrid : UInt32) : ResourceRecord?
|
||||||
|
@resources.each do |rr|
|
||||||
|
return rr if rr.rrid = rrid
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def update_rr(rr : ResourceRecord)
|
||||||
|
puts "updating rr #{rr.rrid}"
|
||||||
|
@resources.select! { |x| x.rrid == rr.rrid }
|
||||||
|
@resources << rr
|
||||||
|
end
|
||||||
|
|
||||||
def to_s(io : IO)
|
def to_s(io : IO)
|
||||||
io << "DOMAIN #{@domain}.\n"
|
io << "DOMAIN #{@domain}.\n"
|
||||||
@resources.each do |rr|
|
@resources.each do |rr|
|
||||||
|
@ -754,6 +770,17 @@ class DNSManager::Storage::Zone
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def new_token(rrid : UInt32, token : String)
|
||||||
|
old_token : String? = nil
|
||||||
|
@resources.each do |rr|
|
||||||
|
if rr.rrid == rrid
|
||||||
|
old_token = rr.token
|
||||||
|
rr.token = token
|
||||||
|
end
|
||||||
|
end
|
||||||
|
old_token
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def qualifier_to_char(qualifier : DNSManager::Storage::Zone::SPF::Qualifier) : Char
|
def qualifier_to_char(qualifier : DNSManager::Storage::Zone::SPF::Qualifier) : Char
|
||||||
|
|
Loading…
Reference in New Issue