Page MenuHomeGRNET

No OneTemporary

File Metadata

Created
Tue, Sep 29, 5:02 PM
diff --git a/dnsworker/bin/dns-worker b/dnsworker/bin/dns-worker
index 125ab3c..1ed82e1 100755
--- a/dnsworker/bin/dns-worker
+++ b/dnsworker/bin/dns-worker
@@ -1,50 +1,50 @@
#!/usr/bin/env ruby
$:.unshift File.expand_path('../../lib', File.realpath(__FILE__))
require 'yaml'
require 'optparse'
require 'ostruct'
require 'dnsworker/worker'
options = OpenStruct.new
options.once = false
options.dry_run = false
options.extra = nil
OptionParser.new do |opts|
- opts.banner = 'Usage: webdns-worker [options]'
+ opts.banner = 'Usage: dns-worker [options]'
opts.on('-c', '--config CONFIG', 'Config file') do |c|
options[:config] = c
end
opts.on('-e', '--extra CONFIG', 'Extra config file') do |e|
options[:extra] = e
end
opts.on('-n', '--dry-run', 'Run but not execute or mark anything') do |n|
options[:dry_run] = n
end
opts.on('-o', '--once', 'Run once') do |o|
options[:once] = o
end
opts.on('-d', '--cmdline-dispatch TYPE:JSON') do |d|
options[:cmdline_type], options[:cmdline_body] = d.split(':', 2)
options.cmdline_body = JSON.parse(options.cmdline_body, symbolize_names: true) if options.cmdline_body
end
end.parse!
cfg = YAML.load_file(options.config)
cfg.merge!(YAML.load_file(options.extra)) if options.extra
w = DNSWorker::Worker.new(cfg)
if options.cmdline_type
w.send(:cmdline, options.cmdline_type, options.cmdline_body)
else
w.work(once: options.once, dry_run: options.dry_run)
end
diff --git a/dnsworker/bin/ds-schedule b/dnsworker/bin/ds-schedule
index 59053f8..6b1bfd2 100755
--- a/dnsworker/bin/ds-schedule
+++ b/dnsworker/bin/ds-schedule
@@ -1,105 +1,105 @@
#!/usr/bin/env ruby
require 'uri'
require 'rack/utils'
require 'net/http'
require 'open3'
class DSPusher
attr_reader :cfg
def initialize(cfg)
@cfg = cfg
end
def push_ds(zone=nil, dry_run=false)
fetch_dss(zone).each { |d, dss|
post_dss(d, dss, dry_run)
}
end
def fetch_dss(zone)
dss = Hash.new { |h, k| h[k] = [] }
cmd = cfg['get_ds']
cmd += " -z #{zone}" if zone
out, err = command(cmd)
out.each_line { |line|
line.strip!
next if line.nil? || line == ''
next if line.start_with?(';')
domain, _ttl, _f, rtype, rdata = line.split(/\s+/, 5)
next unless rtype == 'DS'
domain = domain.gsub(/\.+$/, '') # Remove trailing .
dss[domain] << rdata
}
dss
end
def post_dss(domain, dss, dry_run)
query = Rack::Utils.build_nested_query(
domain: domain,
event: 'push_ds',
args: dss,
)
uri = URI("#{cfg['webdns_base']}#{cfg['update_state']}" % { query: query })
if dry_run
p [:uri, uri]
return
end
Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
resp = http.request Net::HTTP::Put.new(uri.request_uri)
fail JobFailed if resp.code != '200'
end
end
private
def command(cmd)
out, err, status = Open3.capture3(cmd)
raise "Command error err='#{err.strip}' out='#{out.strip}'" if !status.success?
[out, err]
end
end
require 'yaml'
require 'optparse'
require 'ostruct'
options = OpenStruct.new
options.dry_run = false
options.extra = nil
options.zone = nil
OptionParser.new do |opts|
- opts.banner = 'Usage: push-ds [options]'
+ opts.banner = 'Usage: ds-schedule [options]'
opts.on('-c', '--config CONFIG', 'Config file') do |c|
options[:config] = c
end
opts.on('-e', '--extra CONFIG', 'Extra config file') do |e|
options[:extra] = e
end
opts.on('-n', '--dry-run', 'Run but not execute anything') do |n|
options[:dry_run] = n
end
opts.on('-z', '--zone ZONE', 'Zone') do |z|
options[:zone] = z
end
end.parse!
cfg = YAML.load_file(options.config)
cfg.merge!(YAML.load_file(options.extra)) if options.extra
w = DSPusher.new(cfg)
w.push_ds(options.zone, options.dry_run)
diff --git a/test/models/domain_test.rb b/test/models/domain_test.rb
index 2e6255b..1a96a28 100644
--- a/test/models/domain_test.rb
+++ b/test/models/domain_test.rb
@@ -1,305 +1,305 @@
require 'test_helper'
class DomainTest < ActiveSupport::TestCase
def setup
@domain = build(:domain)
end
test 'automatic SOA creation' do
@domain.save!
@domain.reload
assert_not_nil @domain.soa
end
test 'increment serial on new record' do
@domain.save!
soa = @domain.soa
assert_serial_update soa do
www = A.new(name: 'www', domain: @domain, content: '1.2.3.4')
www.save!
end
end
test 'increment serial on record update' do
@domain.save!
www = A.new(name: 'www', domain: @domain, content: '1.2.3.4')
www.save!
soa = @domain.soa.reload
assert_serial_update soa do
www.content = '1.2.3.5'
www.save!
end
end
test 'automatic NS creation' do
@domain.save!
@domain.reload
assert_equal WebDNS.settings[:default_ns].sort,
@domain.records.where(type: 'NS').pluck(:content).sort
end
test 'increment serial on record destroy' do
@domain.save!
www = A.new(name: 'www', domain: @domain, content: '1.2.3.4')
www.save!
soa = @domain.soa.reload
assert_serial_update soa do
www.destroy!
end
end
class SlaveDomainTest < ActiveSupport::TestCase
def setup
@domain = build(:slave)
end
test 'saves' do
@domain.save
assert_empty @domain.errors
end
test 'automatic SOA creation' do
@domain.save!
@domain.reload
assert_not_nil @domain.soa
assert_equal 1, @domain.soa.serial
end
test 'validates master' do
@domain.master = 'not-an-ip'
@domain.save
assert_not_empty @domain.errors['master']
end
test 'no records are allowed for users' do
@domain.save!
rec = build(:a, domain_id: @domain.id)
assert_not rec.valid?
assert_not_empty rec.errors[:type]
end
end
class StatesDomainTest < ActiveSupport::TestCase
def setup
@domain = build(:domain)
@policy = create(:dnssec_policy)
end
test 'domain lifetime' do
assert_equal 'initial', @domain.state
# Create
assert_jobs do
@domain.save! # user triggered
assert_equal 'pending_install', @domain.state
end
@domain.installed # job triggered
assert_equal 'operational', @domain.state
# Convert to dnssec (sign)
assert_jobs do
@domain.dnssec = true
@domain.dnssec_policy = @policy
@domain.dnssec_parent = @domain.name.split('.', 2).last
@domain.dnssec_parent_authority = 'test_authority'
@domain.save!
# After commit is not triggered in tests,
# so we have to trigger it manually
@domain.send(:after_commit_event)
assert_equal 'pending_signing', @domain.state
end
assert_jobs do
assert @domain.signed # job triggered
assert_equal 'wait_for_ready', @domain.state
end
# Convert to dnssec (publish ds)
assert_jobs do
- assert @domain.push_ds(['dss1', 'dss2']) # triggered by schedule-ds script
+ assert @domain.push_ds(['dss1', 'dss2']) # triggered by ds-schedule script
assert_equal 'pending_ds', @domain.state
end
assert @domain.converted # job triggered
assert_equal 'operational', @domain.state
# KSK rollover
assert_jobs do
- assert @domain.push_ds(['dss3', 'dss4']) # triggered by schedule-ds script
+ assert @domain.push_ds(['dss3', 'dss4']) # triggered by ds-schedule script
assert_equal 'pending_ds_rollover', @domain.state
end
assert @domain.complete_rollover # job triggered
assert_equal 'operational', @domain.state
# Convert to plain
assert_jobs do
assert @domain.plain_convert # user triggered
assert_equal 'pending_plain', @domain.state
end
assert @domain.converted # job triggered
assert_equal 'operational', @domain.state
# Remove
assert_jobs do
assert @domain.remove # user triggered
assert_equal 'pending_remove', @domain.state
end
assert @domain.cleaned_up # job triggered
assert_equal 'destroy', @domain.state
end
test 'domain lifetime #full-destroy' do
assert_equal 'initial', @domain.state
# Create
assert_jobs do
@domain.save! # user triggered
assert_equal 'pending_install', @domain.state
end
@domain.installed # job triggered
assert_equal 'operational', @domain.state
# Convert to dnssec (sign)
assert_jobs do
@domain.dnssec = true
@domain.dnssec_policy = @policy
@domain.dnssec_parent = @domain.name.split('.', 2).last
@domain.dnssec_parent_authority = 'test_authority'
@domain.save!
# After commit is not triggered in tests,
# so we have to trigger it manually
@domain.send(:after_commit_event)
assert_equal 'pending_signing', @domain.state
end
assert_jobs do
assert @domain.signed # job triggered
assert_equal 'wait_for_ready', @domain.state
end
# Convert to dnssec (publish ds)
assert_jobs do
- assert @domain.push_ds(['dss1', 'dss2']) # triggered by schedule-ds script
+ assert @domain.push_ds(['dss1', 'dss2']) # triggered by ds-schedule script
assert_equal 'pending_ds', @domain.state
end
assert @domain.converted # job triggered
assert_equal 'operational', @domain.state
# KSK rollover
assert_jobs do
- assert @domain.push_ds(['dss3', 'dss4']) # triggered by schedule-ds script
+ assert @domain.push_ds(['dss3', 'dss4']) # triggered by ds-schedule script
assert_equal 'pending_ds_rollover', @domain.state
end
assert @domain.complete_rollover # job triggered
assert_equal 'operational', @domain.state
# Full Remove (Drops DS records)
assert_jobs do
assert @domain.full_remove # user triggered
assert_equal 'pending_ds_removal', @domain.state
end
assert_jobs do
assert @domain.remove # job triggered
assert_equal 'pending_remove', @domain.state
end
assert @domain.cleaned_up # job triggered
assert_equal 'destroy', @domain.state
end
end
class DsDomainTest < ActiveSupport::TestCase
def setup
@domain = create(:domain)
@ds = [
'31406 8 1 189968811e6eba862dd6c209f75623d8d9ed9142',
'31406 8 2 f78cf3344f72137235098ecbbd08947c2c9001c7f6a085a17f518b5d8f6b916d',
]
@child = "dnssec.#{@domain.name}"
@extra = DS.create(domain: @domain, name: @child, content: 'other')
end
test 'add ds records' do
Domain.replace_ds(@domain.name, @child, @ds)
@extra.save! # Should be deleted
assert_equal @ds.size, DS.where(name: "dnssec.#{@domain.name}").count
@ds.each { |ds|
assert_equal 1, DS.where(name: "dnssec.#{@domain.name}", content: ds).count
}
end
test 'remove ds records' do
Domain.replace_ds(@domain.name, @child, [])
assert_equal 0, DS.where(name: "dnssec.#{@domain.name}").count
end
test 'check if child is a valid subdomain' do
assert_raise Domain::NotAChild do
Domain.replace_ds(@domain.name, 'dnssec.example.net', @ds)
end
end
end
class BulkTest < ActiveSupport::TestCase
def setup
@domain = create(:domain)
@a = create(:a, domain: @domain)
@aaaa = create(:aaaa, domain: @domain)
@new = build(:mx, domain: @domain)
end
def valid_changes
@valid_changes ||= begin
{}.tap { |c|
c[:deletes] = [@a.id]
c[:changes] = { @aaaa.id => { content: '::42' }}
c[:additions] = { 1 => @new.as_bulky_json }
}
end
end
def invalid_changes
@invalid_changes ||= begin
{}.tap { |c|
c[:deletes] = [Record.maximum(:id) + 1]
c[:changes] = { @aaaa.id => { content: '1.2.3.4' }}
c[:additions] = { 1 => @new.as_bulky_json.update(prio: -1) }
}
end
end
test 'apply changes not' do
err = @domain.bulk invalid_changes
assert_not_empty err
assert_includes err[:deletes][Record.maximum(:id) + 1], 'record not found'
assert_includes err[:changes][@aaaa.id], 'not a valid IPv6'
assert_includes err[:additions][1], 'not a valid DNS priority'
end
test 'apply changes' do
err = @domain.bulk valid_changes
@domain.reload
@aaaa.reload
assert_empty err
assert_empty @domain.records.where(id: @a.id)
assert_equal '::42', @aaaa.content
assert_equal 1, @domain.records.where(type: :mx).count
end
end
end

Event Timeline