mirror of
https://github.com/internetee/registry.git
synced 2025-06-06 20:55:44 +02:00
parent 64e3bc885a2cb8b46a1aaa4bf4f121ee7f5d44a6
author Karl Erik Õunapuu <karlerik@kreative.ee> 1591359032 +0300 committer Alex Sherman <yul.golem@gmail.com> 1617029320 +0500 CsyncJob: Don't respect IPv6 if nessecary
This commit is contained in:
parent
e46fdd57af
commit
88e1bc3727
33 changed files with 1475 additions and 119 deletions
2
Gemfile
2
Gemfile
|
@ -5,6 +5,7 @@ gem 'active_interaction', '~> 3.8'
|
||||||
gem 'apipie-rails', '~> 0.5.18'
|
gem 'apipie-rails', '~> 0.5.18'
|
||||||
gem 'bootsnap', '>= 1.1.0', require: false
|
gem 'bootsnap', '>= 1.1.0', require: false
|
||||||
gem 'iso8601', '0.12.1' # for dates and times
|
gem 'iso8601', '0.12.1' # for dates and times
|
||||||
|
gem 'mimemagic', '~> 0.3.7'
|
||||||
gem 'rails', '~> 6.0'
|
gem 'rails', '~> 6.0'
|
||||||
gem 'rest-client'
|
gem 'rest-client'
|
||||||
gem 'uglifier'
|
gem 'uglifier'
|
||||||
|
@ -39,6 +40,7 @@ gem 'devise', '~> 4.7'
|
||||||
|
|
||||||
# registry specfic
|
# registry specfic
|
||||||
gem 'data_migrate', '~> 6.1'
|
gem 'data_migrate', '~> 6.1'
|
||||||
|
gem 'dnsruby', '~> 1.61'
|
||||||
gem 'isikukood' # for EE-id validation
|
gem 'isikukood' # for EE-id validation
|
||||||
gem 'simpleidn', '0.1.1' # For punycode
|
gem 'simpleidn', '0.1.1' # For punycode
|
||||||
gem 'money-rails'
|
gem 'money-rails'
|
||||||
|
|
17
Gemfile.lock
17
Gemfile.lock
|
@ -54,13 +54,22 @@ GIT
|
||||||
|
|
||||||
GIT
|
GIT
|
||||||
remote: https://github.com/internetee/omniauth-tara.git
|
remote: https://github.com/internetee/omniauth-tara.git
|
||||||
revision: cec845ec3794532144c4976104a07e206d759aa6
|
revision: 75c369dd86a5fe1a2ee4c2a6246252d79431071c
|
||||||
|
branch: extended-logging
|
||||||
specs:
|
specs:
|
||||||
omniauth-tara (0.3.0)
|
omniauth-tara (0.3.0)
|
||||||
addressable (~> 2.5)
|
addressable (~> 2.5)
|
||||||
omniauth (~> 1.3)
|
omniauth (~> 1.3)
|
||||||
openid_connect (~> 1.1)
|
openid_connect (~> 1.1)
|
||||||
|
|
||||||
|
GIT
|
||||||
|
remote: https://github.com/karlerikounapuu/dnsruby.git
|
||||||
|
revision: f54986268ba3109ecf7a7af0d41a78cddfce9847
|
||||||
|
branch: master
|
||||||
|
specs:
|
||||||
|
dnsruby (1.61.3)
|
||||||
|
simpleidn (~> 0.1)
|
||||||
|
|
||||||
GIT
|
GIT
|
||||||
remote: https://github.com/tarmotalu/digidoc_client.git
|
remote: https://github.com/tarmotalu/digidoc_client.git
|
||||||
revision: 1645e83a5a548addce383f75703b0275c5310c32
|
revision: 1645e83a5a548addce383f75703b0275c5310c32
|
||||||
|
@ -283,7 +292,9 @@ GEM
|
||||||
mime-types (3.3.1)
|
mime-types (3.3.1)
|
||||||
mime-types-data (~> 3.2015)
|
mime-types-data (~> 3.2015)
|
||||||
mime-types-data (3.2021.0225)
|
mime-types-data (3.2021.0225)
|
||||||
mimemagic (0.3.5)
|
mimemagic (0.3.10)
|
||||||
|
nokogiri (~> 1)
|
||||||
|
rake
|
||||||
mini_mime (1.0.2)
|
mini_mime (1.0.2)
|
||||||
mini_portile2 (2.4.0)
|
mini_portile2 (2.4.0)
|
||||||
minitest (5.14.4)
|
minitest (5.14.4)
|
||||||
|
@ -519,6 +530,7 @@ DEPENDENCIES
|
||||||
devise (~> 4.7)
|
devise (~> 4.7)
|
||||||
digidoc_client!
|
digidoc_client!
|
||||||
directo!
|
directo!
|
||||||
|
dnsruby!
|
||||||
domain_name
|
domain_name
|
||||||
e_invoice!
|
e_invoice!
|
||||||
epp!
|
epp!
|
||||||
|
@ -531,6 +543,7 @@ DEPENDENCIES
|
||||||
jquery-ui-rails (= 5.0.5)
|
jquery-ui-rails (= 5.0.5)
|
||||||
kaminari
|
kaminari
|
||||||
lhv!
|
lhv!
|
||||||
|
mimemagic (~> 0.3.7)
|
||||||
minitest (~> 5.14)
|
minitest (~> 5.14)
|
||||||
money-rails
|
money-rails
|
||||||
nokogiri (~> 1.10.0)
|
nokogiri (~> 1.10.0)
|
||||||
|
|
|
@ -2,18 +2,78 @@
|
||||||
|
|
||||||
class CsyncJob < Que::Job
|
class CsyncJob < Que::Job
|
||||||
def run(generate: false)
|
def run(generate: false)
|
||||||
@logger = Logger.new(STDOUT)
|
@store = {}
|
||||||
generate ? generate_scanner_input : scanner_results
|
@input_store = { secure: {}, insecure: {} }
|
||||||
|
@results = {}
|
||||||
|
@logger = Rails.env.test? ? Rails.logger : Logger.new(STDOUT)
|
||||||
|
generate ? generate_scanner_input : process_scanner_results
|
||||||
|
|
||||||
|
@logger.info 'CsyncJob: Finished.'
|
||||||
|
end
|
||||||
|
|
||||||
|
def qualified_for_monitoring?(domain, data)
|
||||||
|
result_types = data[:ns].map { |ns| ns[:type] }.uniq
|
||||||
|
ns_ok = redundant_data_for?(nameserver: true, input: result_types)
|
||||||
|
key_ok = redundant_data_for?(nameserver: false, input: data)
|
||||||
|
|
||||||
|
return true if ns_ok && key_ok
|
||||||
|
|
||||||
|
@logger.info "CsyncJob: #{domain}: Reseting state. Reason: " +
|
||||||
|
unqualification_reason(ns_ok, key_ok, result_types)
|
||||||
|
|
||||||
|
CsyncRecord.where(domain: Domain.where(name: domain)).delete_all
|
||||||
|
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
def redundant_data_for?(nameserver: false, input:)
|
||||||
|
if nameserver
|
||||||
|
input.size == 1 && (input & %w[secure insecure]).any?
|
||||||
|
else
|
||||||
|
input[:ns].map { |ns| ns[:cdnskey] }.uniq.size == 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def unqualification_reason(nss, key, result_types)
|
||||||
|
return 'no CDNSKEY / nameservers reported different CDNSKEYs' unless key
|
||||||
|
|
||||||
|
if result_types.include? 'untrustworthy'
|
||||||
|
return 'current DNSSEC config invalid (required for rollover/delete)'
|
||||||
|
end
|
||||||
|
|
||||||
|
"Nameserver(s) not reachable / invalid data (#{result_types.join(', ')})" unless nss
|
||||||
|
end
|
||||||
|
|
||||||
|
def process_scanner_results
|
||||||
|
scanner_results
|
||||||
|
|
||||||
|
@results.keys.each do |domain|
|
||||||
|
next unless qualified_for_monitoring?(domain, @results[domain])
|
||||||
|
|
||||||
|
CsyncRecord.by_domain_name(domain)&.record_new_scan(@results[domain][:ns].first)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def scanner_results
|
def scanner_results
|
||||||
|
scanner_line_results.each do |fetch|
|
||||||
|
domain_name = fetch[:domain]
|
||||||
|
@results[domain_name] = { ns: [] } unless @results[domain_name]
|
||||||
|
@results[domain_name][:ns] << fetch.except(:domain)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def scanner_line_results
|
||||||
records = []
|
records = []
|
||||||
File.open(ENV['cdns_scanner_output_file'], 'r').each_line do |line|
|
File.open(ENV['cdns_scanner_output_file'], 'r').each_line do |line|
|
||||||
# Input type, NS host, NS IP, Domain name, Key type, Protocol, Algorithm, Public key
|
# Input type, NS host, NS IP, Domain name, Key type, Protocol, Algorithm, Public key
|
||||||
data = line.strip.split(' ')
|
data = line.strip.split(' ')
|
||||||
|
if data[0] == 'secure'
|
||||||
|
type, domain, key_bit, proto, alg, pub, ns, ns_ip = data
|
||||||
|
else
|
||||||
type, ns, ns_ip, domain, key_bit, proto, alg, pub = data
|
type, ns, ns_ip, domain, key_bit, proto, alg, pub = data
|
||||||
|
end
|
||||||
cdnskey = key_bit && proto && alg && pub ? "#{key_bit} #{proto} #{alg} #{pub}" : nil
|
cdnskey = key_bit && proto && alg && pub ? "#{key_bit} #{proto} #{alg} #{pub}" : nil
|
||||||
record = { domain: domain, type: type, ns: ns, ns_ip: ns_ip, key_bit: key_bit, proto: proto,
|
record = { domain: domain, type: type, ns: ns, ns_ip: ns_ip, flags: key_bit, proto: proto,
|
||||||
alg: alg, pub: pub, cdnskey: cdnskey }
|
alg: alg, pub: pub, cdnskey: cdnskey }
|
||||||
records << record
|
records << record
|
||||||
end
|
end
|
||||||
|
@ -23,38 +83,39 @@ class CsyncJob < Que::Job
|
||||||
# From this point we're working on generating input for cdnskey-scanner
|
# From this point we're working on generating input for cdnskey-scanner
|
||||||
def gather_pollable_domains
|
def gather_pollable_domains
|
||||||
@logger.info 'CsyncJob Generate: Gathering current domain(s) data'
|
@logger.info 'CsyncJob Generate: Gathering current domain(s) data'
|
||||||
@store = { secure: {}, insecure: {} }
|
|
||||||
Nameserver.select(:hostname, :domain_id).all.each do |ns|
|
Nameserver.select(:hostname, :domain_id).all.each do |ns|
|
||||||
@store[:secure][ns.hostname] = [] unless @store[:secure].key? ns.hostname
|
%i[secure insecure].each do |i|
|
||||||
@store[:insecure][ns.hostname] = [] unless @store[:insecure].key? ns.hostname
|
@input_store[i][ns.hostname] = [] unless @input_store[i].key? ns.hostname
|
||||||
|
|
||||||
Domain.where(id: ns.domain_id).all.each do |domain|
|
|
||||||
state = domain.dnskeys.any? ? :secure : :insecure
|
|
||||||
@store[state][ns.hostname].push domain.name
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
append_domains_to_list(ns)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def append_domains_to_list(nameserver)
|
||||||
|
Domain.where(id: nameserver.domain_id).all.each do |domain|
|
||||||
|
@input_store[domain.dnskeys.any? ? :secure : :insecure][nameserver.hostname].push domain.name
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def generate_scanner_input
|
def generate_scanner_input
|
||||||
|
@logger.info 'CsyncJob Generate: Gathering current domain(s) data'
|
||||||
gather_pollable_domains
|
gather_pollable_domains
|
||||||
|
|
||||||
@logger.info 'CsyncJob Generate: Writing input for cdnskey-scanner to ' \
|
|
||||||
"#{ENV['cdns_scanner_input_file']}"
|
|
||||||
out_file = File.new(ENV['cdns_scanner_input_file'], 'w+')
|
out_file = File.new(ENV['cdns_scanner_input_file'], 'w+')
|
||||||
|
|
||||||
out_file.puts '[secure]'
|
%i[secure insecure].each do |state|
|
||||||
create_input_lines(out_file, secure: true)
|
out_file.puts "[#{state}]"
|
||||||
out_file.puts '[insecure]'
|
create_input_lines(out_file, state)
|
||||||
create_input_lines(out_file, secure: false)
|
|
||||||
|
|
||||||
out_file.close
|
|
||||||
@logger.info 'CsyncJob Generate: Finished writing output.'
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_input_lines(out_file, secure: false)
|
out_file.close
|
||||||
state = secure ? :secure : :insecure
|
@logger.info 'CsyncJob Generate: Finished writing output to ' + ENV['cdns_scanner_input_file']
|
||||||
@store[state].keys.each do |nameserver|
|
end
|
||||||
domains = @store[state][nameserver].join(' ')
|
|
||||||
|
def create_input_lines(out_file, state)
|
||||||
|
@input_store[state].keys.each do |nameserver|
|
||||||
|
domains = @input_store[state][nameserver].join(' ')
|
||||||
next unless domains.length.positive?
|
next unless domains.length.positive?
|
||||||
|
|
||||||
out_file.puts "#{nameserver} #{domains}"
|
out_file.puts "#{nameserver} #{domains}"
|
||||||
|
|
23
app/mailers/csync_mailer.rb
Normal file
23
app/mailers/csync_mailer.rb
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
class CsyncMailer < ApplicationMailer
|
||||||
|
def dnssec_updated(domain:)
|
||||||
|
@domain = domain
|
||||||
|
emails = contact_emails(domain)
|
||||||
|
|
||||||
|
subject = default_i18n_subject(domain_name: domain.name)
|
||||||
|
mail(to: emails, subject: subject)
|
||||||
|
end
|
||||||
|
|
||||||
|
def dnssec_deleted(domain:)
|
||||||
|
@domain = domain
|
||||||
|
emails = contact_emails(domain)
|
||||||
|
|
||||||
|
subject = default_i18n_subject(domain_name: domain.name)
|
||||||
|
mail(to: emails, subject: subject)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def contact_emails(domain)
|
||||||
|
(domain.contacts.map(&:email) << domain.registrant.email).uniq
|
||||||
|
end
|
||||||
|
end
|
81
app/models/actions/contact_create.rb
Normal file
81
app/models/actions/contact_create.rb
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
module Actions
|
||||||
|
class ContactCreate
|
||||||
|
attr_reader :contact, :legal_document, :ident
|
||||||
|
|
||||||
|
def initialize(contact, legal_document, ident)
|
||||||
|
@contact = contact
|
||||||
|
@legal_document = legal_document
|
||||||
|
@ident = ident
|
||||||
|
end
|
||||||
|
|
||||||
|
def call
|
||||||
|
maybe_remove_address
|
||||||
|
maybe_attach_legal_doc
|
||||||
|
validate_ident
|
||||||
|
commit
|
||||||
|
end
|
||||||
|
|
||||||
|
def maybe_remove_address
|
||||||
|
return if Contact.address_processing?
|
||||||
|
|
||||||
|
contact.city = nil
|
||||||
|
contact.zip = nil
|
||||||
|
contact.street = nil
|
||||||
|
contact.state = nil
|
||||||
|
contact.country_code = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def validate_ident
|
||||||
|
validate_ident_integrity
|
||||||
|
validate_ident_birthday
|
||||||
|
|
||||||
|
identifier = ::Contact::Ident.new(code: ident[:ident], type: ident[:ident_type],
|
||||||
|
country_code: ident[:ident_country_code])
|
||||||
|
|
||||||
|
identifier.validate
|
||||||
|
contact.identifier = identifier
|
||||||
|
end
|
||||||
|
|
||||||
|
def validate_ident_integrity
|
||||||
|
return if ident.blank?
|
||||||
|
|
||||||
|
if ident[:ident_type].blank?
|
||||||
|
contact.add_epp_error('2003', nil, 'ident_type',
|
||||||
|
I18n.t('errors.messages.required_ident_attribute_missing'))
|
||||||
|
@error = true
|
||||||
|
elsif !%w[priv org birthday].include?(ident[:ident_type])
|
||||||
|
contact.add_epp_error('2003', nil, 'ident_type', 'Invalid ident type')
|
||||||
|
@error = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def validate_ident_birthday
|
||||||
|
return if ident.blank?
|
||||||
|
return unless ident[:ident_type] != 'birthday' && ident[:ident_country_code].blank?
|
||||||
|
|
||||||
|
contact.add_epp_error('2003', nil, 'ident_country_code',
|
||||||
|
I18n.t('errors.messages.required_ident_attribute_missing'))
|
||||||
|
@error = true
|
||||||
|
end
|
||||||
|
|
||||||
|
def maybe_attach_legal_doc
|
||||||
|
return unless legal_document
|
||||||
|
|
||||||
|
doc = LegalDocument.create(
|
||||||
|
documentable_type: Contact,
|
||||||
|
document_type: legal_document[:type], body: legal_document[:body]
|
||||||
|
)
|
||||||
|
|
||||||
|
contact.legal_documents = [doc]
|
||||||
|
contact.legal_document_id = doc.id
|
||||||
|
end
|
||||||
|
|
||||||
|
def commit
|
||||||
|
contact.id = nil # new record
|
||||||
|
return false if @error
|
||||||
|
|
||||||
|
contact.generate_code
|
||||||
|
contact.save
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
46
app/models/actions/contact_delete.rb
Normal file
46
app/models/actions/contact_delete.rb
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
module Actions
|
||||||
|
class ContactDelete
|
||||||
|
attr_reader :contact
|
||||||
|
attr_reader :new_attributes
|
||||||
|
attr_reader :legal_document
|
||||||
|
attr_reader :ident
|
||||||
|
attr_reader :user
|
||||||
|
|
||||||
|
def initialize(contact, legal_document = nil)
|
||||||
|
@legal_document = legal_document
|
||||||
|
@contact = contact
|
||||||
|
end
|
||||||
|
|
||||||
|
def call
|
||||||
|
maybe_attach_legal_doc
|
||||||
|
|
||||||
|
if contact.linked?
|
||||||
|
contact.errors.add(:domains, :exist)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if contact.delete_prohibited?
|
||||||
|
contact.errors.add(:statuses, :delete_prohibited)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
commit
|
||||||
|
end
|
||||||
|
|
||||||
|
def maybe_attach_legal_doc
|
||||||
|
return unless legal_document
|
||||||
|
|
||||||
|
document = contact.legal_documents.create(
|
||||||
|
document_type: legal_document[:type],
|
||||||
|
body: legal_document[:body]
|
||||||
|
)
|
||||||
|
|
||||||
|
contact.legal_document_id = document.id
|
||||||
|
contact.save
|
||||||
|
end
|
||||||
|
|
||||||
|
def commit
|
||||||
|
contact.destroy
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
109
app/models/actions/contact_update.rb
Normal file
109
app/models/actions/contact_update.rb
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
module Actions
|
||||||
|
class ContactUpdate
|
||||||
|
attr_reader :contact
|
||||||
|
attr_reader :new_attributes
|
||||||
|
attr_reader :legal_document
|
||||||
|
attr_reader :ident
|
||||||
|
attr_reader :user
|
||||||
|
|
||||||
|
def initialize(contact, new_attributes, legal_document, ident, user)
|
||||||
|
@contact = contact
|
||||||
|
@new_attributes = new_attributes
|
||||||
|
@legal_document = legal_document
|
||||||
|
@ident = ident
|
||||||
|
@user = user
|
||||||
|
end
|
||||||
|
|
||||||
|
def call
|
||||||
|
maybe_remove_address
|
||||||
|
maybe_update_statuses
|
||||||
|
maybe_update_ident if ident.present?
|
||||||
|
maybe_attach_legal_doc
|
||||||
|
commit
|
||||||
|
end
|
||||||
|
|
||||||
|
def maybe_remove_address
|
||||||
|
return if Contact.address_processing?
|
||||||
|
|
||||||
|
new_attributes.delete(:city)
|
||||||
|
new_attributes.delete(:zip)
|
||||||
|
new_attributes.delete(:street)
|
||||||
|
new_attributes.delete(:state)
|
||||||
|
new_attributes.delete(:country_code)
|
||||||
|
end
|
||||||
|
|
||||||
|
def maybe_update_statuses
|
||||||
|
return unless Setting.client_status_editing_enabled
|
||||||
|
|
||||||
|
new_statuses =
|
||||||
|
contact.statuses - new_attributes[:statuses_to_remove] + new_attributes[:statuses_to_add]
|
||||||
|
|
||||||
|
new_attributes[:statuses] = new_statuses
|
||||||
|
end
|
||||||
|
|
||||||
|
def maybe_attach_legal_doc
|
||||||
|
return unless legal_document
|
||||||
|
|
||||||
|
document = contact.legal_documents.create(
|
||||||
|
document_type: legal_document[:type],
|
||||||
|
body: legal_document[:body]
|
||||||
|
)
|
||||||
|
|
||||||
|
contact.legal_document_id = document.id
|
||||||
|
end
|
||||||
|
|
||||||
|
def maybe_update_ident
|
||||||
|
unless ident.is_a?(Hash)
|
||||||
|
contact.add_epp_error('2308', nil, nil, I18n.t('epp.contacts.errors.valid_ident'))
|
||||||
|
@error = true
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if contact.identifier.valid?
|
||||||
|
submitted_ident = ::Contact::Ident.new(code: ident[:ident],
|
||||||
|
type: ident[:ident_type],
|
||||||
|
country_code: ident[:ident_country_code])
|
||||||
|
|
||||||
|
if submitted_ident != contact.identifier
|
||||||
|
contact.add_epp_error('2308', nil, nil, I18n.t('epp.contacts.errors.valid_ident'))
|
||||||
|
@error = true
|
||||||
|
end
|
||||||
|
else
|
||||||
|
ident_update_attempt = ident[:ident] != contact.ident
|
||||||
|
|
||||||
|
if ident_update_attempt
|
||||||
|
contact.add_epp_error('2308', nil, nil, I18n.t('epp.contacts.errors.ident_update'))
|
||||||
|
@error = true
|
||||||
|
end
|
||||||
|
|
||||||
|
identifier = ::Contact::Ident.new(code: ident[:ident],
|
||||||
|
type: ident[:ident_type],
|
||||||
|
country_code: ident[:ident_country_code])
|
||||||
|
|
||||||
|
identifier.validate
|
||||||
|
|
||||||
|
contact.identifier = identifier
|
||||||
|
contact.ident_updated_at ||= Time.zone.now
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def commit
|
||||||
|
return false if @error
|
||||||
|
|
||||||
|
contact.upid = user.registrar&.id
|
||||||
|
contact.up_date = Time.zone.now
|
||||||
|
|
||||||
|
contact.attributes = new_attributes
|
||||||
|
|
||||||
|
email_changed = contact.will_save_change_to_email?
|
||||||
|
old_email = contact.email_was
|
||||||
|
updated = contact.save
|
||||||
|
|
||||||
|
if updated && email_changed && contact.registrant?
|
||||||
|
ContactMailer.email_changed(contact: contact, old_email: old_email).deliver_now
|
||||||
|
end
|
||||||
|
|
||||||
|
updated
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
74
app/models/actions/domain_transfer.rb
Normal file
74
app/models/actions/domain_transfer.rb
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
module Actions
|
||||||
|
class DomainTransfer
|
||||||
|
attr_reader :domain
|
||||||
|
attr_reader :transfer_code
|
||||||
|
attr_reader :legal_document
|
||||||
|
attr_reader :ident
|
||||||
|
attr_reader :user
|
||||||
|
|
||||||
|
def initialize(domain, transfer_code, user)
|
||||||
|
@domain = domain
|
||||||
|
@transfer_code = transfer_code
|
||||||
|
@user = user
|
||||||
|
end
|
||||||
|
|
||||||
|
def call
|
||||||
|
return unless domain_exists?
|
||||||
|
return unless valid_transfer_code?
|
||||||
|
|
||||||
|
run_validations
|
||||||
|
|
||||||
|
# return domain.pending_transfer if domain.pending_transfer
|
||||||
|
# attach_legal_document(::Deserializers::Xml::LegalDocument.new(frame).call)
|
||||||
|
|
||||||
|
return if domain.errors[:epp_errors].any?
|
||||||
|
|
||||||
|
commit
|
||||||
|
end
|
||||||
|
|
||||||
|
def domain_exists?
|
||||||
|
return true if domain.persisted?
|
||||||
|
|
||||||
|
domain.add_epp_error('2303', nil, nil, 'Object does not exist')
|
||||||
|
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
def run_validations
|
||||||
|
validate_registrar
|
||||||
|
validate_eligilibty
|
||||||
|
validate_not_discarded
|
||||||
|
end
|
||||||
|
|
||||||
|
def valid_transfer_code?
|
||||||
|
return true if transfer_code == domain.transfer_code
|
||||||
|
|
||||||
|
domain.add_epp_error('2202', nil, nil, 'Invalid authorization information')
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
def validate_registrar
|
||||||
|
return unless user == domain.registrar
|
||||||
|
|
||||||
|
domain.add_epp_error('2002', nil, nil,
|
||||||
|
I18n.t(:domain_already_belongs_to_the_querying_registrar))
|
||||||
|
end
|
||||||
|
|
||||||
|
def validate_eligilibty
|
||||||
|
return unless domain.non_transferable?
|
||||||
|
|
||||||
|
domain.add_epp_error('2304', nil, nil, 'Object status prohibits operation')
|
||||||
|
end
|
||||||
|
|
||||||
|
def validate_not_discarded
|
||||||
|
return unless domain.discarded?
|
||||||
|
|
||||||
|
domain.add_epp_error('2106', nil, nil, 'Object is not eligible for transfer')
|
||||||
|
end
|
||||||
|
|
||||||
|
def commit
|
||||||
|
bare_domain = Domain.find(domain.id)
|
||||||
|
::DomainTransfer.request(bare_domain, user)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
45
app/models/concerns/csync_record/diggable.rb
Normal file
45
app/models/concerns/csync_record/diggable.rb
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
module CsyncRecord::Diggable
|
||||||
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
|
def valid_security_level?(post: false)
|
||||||
|
res = post ? valid_post_action? : valid_pre_action?
|
||||||
|
|
||||||
|
log_dnssec_entry(valid: res, post: post)
|
||||||
|
res
|
||||||
|
rescue Dnsruby::NXDomain
|
||||||
|
log.info("CsyncRecord: #{domain.name}: Could not resolve (NXDomain)")
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
def valid_pre_action?
|
||||||
|
case domain.dnssec_security_level
|
||||||
|
when Dnsruby::Message::SecurityLevel.SECURE
|
||||||
|
return true if %w[rollover deactivate].include?(action)
|
||||||
|
when Dnsruby::Message::SecurityLevel.INSECURE, Dnsruby::Message::SecurityLevel.BOGUS
|
||||||
|
return true if action == 'initialized'
|
||||||
|
end
|
||||||
|
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
def valid_post_action?
|
||||||
|
secure_msg = Dnsruby::Message::SecurityLevel.SECURE
|
||||||
|
security_level = domain.dnssec_security_level(stubber: dnskey)
|
||||||
|
return true if action == 'deactivate' && security_level != secure_msg
|
||||||
|
return true if %w[rollover initialized].include?(action) && security_level == secure_msg
|
||||||
|
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
def dnssec_validates?
|
||||||
|
return false unless dnskey.valid?
|
||||||
|
return true if valid_security_level? && valid_security_level?(post: true)
|
||||||
|
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
def log_dnssec_entry(valid:, post:)
|
||||||
|
log.info("#{domain.name}: #{post ? 'Post' : 'Pre'} DNSSEC validation " \
|
||||||
|
"#{valid ? 'PASSED' : 'FAILED'} for action '#{action}'")
|
||||||
|
end
|
||||||
|
end
|
132
app/models/csync_record.rb
Normal file
132
app/models/csync_record.rb
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class CsyncRecord < ApplicationRecord
|
||||||
|
include CsyncRecord::Diggable
|
||||||
|
belongs_to :domain, optional: false
|
||||||
|
validates :domain, uniqueness: true
|
||||||
|
validates :cdnskey, :action, :last_scan, presence: true
|
||||||
|
validate :validate_unique_pub_key
|
||||||
|
validate :validate_csync_action
|
||||||
|
validate :validate_cdnskey_format
|
||||||
|
after_save :process_new_dnskey, if: proc { pushable? && !disable_requested? }
|
||||||
|
after_save :remove_dnskeys, if: proc { pushable? && disable_requested? }
|
||||||
|
|
||||||
|
SCAN_CYCLES = 3
|
||||||
|
|
||||||
|
def record_new_scan(result)
|
||||||
|
assign_scanner_data!(result)
|
||||||
|
prefix = "CsyncRecord: #{domain.name}:"
|
||||||
|
|
||||||
|
if save
|
||||||
|
log.info "#{prefix} Cycle done."
|
||||||
|
else
|
||||||
|
log.info "#{prefix}: not processing. Reason: #{errors.full_messages.join(' .')}"
|
||||||
|
CsyncRecord.where(domain: domain).delete_all
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def assign_scanner_data!(result)
|
||||||
|
state = result[:type]
|
||||||
|
self.last_scan = Time.zone.now
|
||||||
|
self.times_scanned = (persisted? && cdnskey != result[:cdnskey] ? 1 : times_scanned + 1)
|
||||||
|
self.cdnskey = result[:cdnskey]
|
||||||
|
self.action = initializes_dnssec?(state) ? 'initialized' : determine_csync_intention(state)
|
||||||
|
end
|
||||||
|
|
||||||
|
def dnskey
|
||||||
|
key = Dnskey.new_from_csync(domain: domain, cdnskey: cdnskey)
|
||||||
|
log.info "DNSKEY not valid. #{key.errors.full_messages.join('. ')}." unless key.valid?
|
||||||
|
|
||||||
|
key
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy_all_but_last_one
|
||||||
|
domain.dnskeys.order(id: :desc).offset(1).destroy_all
|
||||||
|
end
|
||||||
|
|
||||||
|
def process_new_dnskey
|
||||||
|
return unless dnssec_validates?
|
||||||
|
|
||||||
|
if dnskey.save
|
||||||
|
destroy_all_but_last_one
|
||||||
|
finalize_and_notify
|
||||||
|
else
|
||||||
|
log.info "Failed to save DNSKEY. Errors: #{dnskey.errors.full_messages.join('. ')}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def finalize_and_notify
|
||||||
|
CsyncMailer.dnssec_updated(domain: domain).deliver_now
|
||||||
|
notify_registrar_about_csync
|
||||||
|
CsyncRecord.where(domain: domain).destroy_all
|
||||||
|
log.info "CsyncRecord: #{domain.name}: DNSKEYs updated."
|
||||||
|
end
|
||||||
|
|
||||||
|
def pushable?
|
||||||
|
return true if domain.dnskeys.any? || times_scanned >= SCAN_CYCLES
|
||||||
|
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
def disable_requested?
|
||||||
|
['0 3 0 AA==', '0 3 0 0'].include? cdnskey
|
||||||
|
end
|
||||||
|
|
||||||
|
def remove_dnskeys
|
||||||
|
log.info "CsyncJob: Removing DNSKEYs for domain '#{domain.name}'"
|
||||||
|
domain.dnskeys.destroy_all
|
||||||
|
CsyncMailer.dnssec_deleted(domain: domain).deliver_now
|
||||||
|
notify_registrar_about_csync
|
||||||
|
|
||||||
|
destroy
|
||||||
|
end
|
||||||
|
|
||||||
|
def notify_registrar_about_csync
|
||||||
|
domain.update_whois_record
|
||||||
|
domain.registrar.notifications.create!(text: I18n.t('notifications.texts.csync',
|
||||||
|
domain: domain.name, action: action))
|
||||||
|
end
|
||||||
|
|
||||||
|
def validate_unique_pub_key
|
||||||
|
return false unless domain
|
||||||
|
return true if disable_requested?
|
||||||
|
return true unless domain.dnskeys.where(public_key: dnskey.public_key).any?
|
||||||
|
|
||||||
|
errors.add(:public_key, 'already tied to this domain')
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.by_domain_name(domain_name)
|
||||||
|
domain = Domain.find_by(name: domain_name)
|
||||||
|
log.info "CsyncRecord: '#{domain_name}' not in zone. Not initializing record." unless domain
|
||||||
|
CsyncRecord.find_or_initialize_by(domain: domain) if domain
|
||||||
|
end
|
||||||
|
|
||||||
|
def determine_csync_intention(scan_state)
|
||||||
|
return unless domain.dnskeys.any? && scan_state == 'secure'
|
||||||
|
|
||||||
|
disable_requested? ? 'deactivate' : 'rollover'
|
||||||
|
end
|
||||||
|
|
||||||
|
def initializes_dnssec?(scan_state)
|
||||||
|
true if domain.dnskeys.empty? && !disable_requested? && scan_state == 'insecure'
|
||||||
|
end
|
||||||
|
|
||||||
|
def log
|
||||||
|
@log ||= Rails.env.test? ? logger : Logger.new(STDOUT)
|
||||||
|
@log
|
||||||
|
end
|
||||||
|
|
||||||
|
def validate_csync_action
|
||||||
|
return true if %w[initialized rollover].include? action
|
||||||
|
return true if action == 'deactivate' && disable_requested?
|
||||||
|
|
||||||
|
errors.add(:action, :invalid)
|
||||||
|
end
|
||||||
|
|
||||||
|
def validate_cdnskey_format
|
||||||
|
return true if disable_requested?
|
||||||
|
return true if dnskey.valid?
|
||||||
|
|
||||||
|
errors.add(:cdnskey, :invalid)
|
||||||
|
end
|
||||||
|
end
|
|
@ -28,7 +28,7 @@ class Dnskey < ApplicationRecord
|
||||||
PROTOCOLS = %w(3)
|
PROTOCOLS = %w(3)
|
||||||
FLAGS = %w(0 256 257) # 256 = ZSK, 257 = KSK
|
FLAGS = %w(0 256 257) # 256 = ZSK, 257 = KSK
|
||||||
DS_DIGEST_TYPE = [1,2]
|
DS_DIGEST_TYPE = [1,2]
|
||||||
|
RESOLVERS = ENV['dnssec_resolver_ips'].to_s.strip.split(', ').freeze
|
||||||
self.ignored_columns = %w[legacy_domain_id]
|
self.ignored_columns = %w[legacy_domain_id]
|
||||||
|
|
||||||
def epp_code_map
|
def epp_code_map
|
||||||
|
@ -122,6 +122,26 @@ class Dnskey < ApplicationRecord
|
||||||
errors.add(:public_key, :invalid)
|
errors.add(:public_key, :invalid)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.new_from_csync(cdnskey:, domain:)
|
||||||
|
cdnskey ||= '' # avoid strip() issues for gibberish key
|
||||||
|
|
||||||
|
flags, proto, alg, pub = cdnskey.strip.split(' ')
|
||||||
|
Dnskey.new(domain: domain, flags: flags, protocol: proto, alg: alg, public_key: pub)
|
||||||
|
end
|
||||||
|
|
||||||
|
def ds_rr
|
||||||
|
# Break the DNSSEC trust chain as we are not able to fake RRSIG's
|
||||||
|
Dnsruby::Dnssec.clear_trust_anchors
|
||||||
|
Dnsruby::Dnssec.clear_trusted_keys
|
||||||
|
|
||||||
|
# Basically let's configure domain as root anchor. We can still verify
|
||||||
|
# RRSIG's / DNSKEY targeted by DS of this domain
|
||||||
|
generate_digest
|
||||||
|
generate_ds_key_tag
|
||||||
|
Dnsruby::RR.create("#{domain.name}. 3600 IN DS #{ds_key_tag} #{ds_alg} " \
|
||||||
|
"#{ds_digest_type} #{ds_digest}")
|
||||||
|
end
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
def int_to_hex(s)
|
def int_to_hex(s)
|
||||||
s = s.to_s(16)
|
s = s.to_s(16)
|
||||||
|
|
|
@ -58,6 +58,7 @@ class Domain < ApplicationRecord
|
||||||
|
|
||||||
has_many :legal_documents, as: :documentable
|
has_many :legal_documents, as: :documentable
|
||||||
has_many :registrant_verifications, dependent: :destroy
|
has_many :registrant_verifications, dependent: :destroy
|
||||||
|
has_one :csync_record, dependent: :destroy
|
||||||
|
|
||||||
after_initialize do
|
after_initialize do
|
||||||
self.pending_json = {} if pending_json.blank?
|
self.pending_json = {} if pending_json.blank?
|
||||||
|
@ -167,6 +168,35 @@ class Domain < ApplicationRecord
|
||||||
validate :validate_nameserver_ips
|
validate :validate_nameserver_ips
|
||||||
|
|
||||||
validate :statuses_uniqueness
|
validate :statuses_uniqueness
|
||||||
|
|
||||||
|
def security_level_resolver
|
||||||
|
resolver = Dnsruby::Resolver.new(nameserver: Dnskey::RESOLVERS)
|
||||||
|
resolver.do_validation = true
|
||||||
|
resolver.do_caching = false
|
||||||
|
resolver.dnssec = true
|
||||||
|
resolver
|
||||||
|
end
|
||||||
|
|
||||||
|
def dnssec_security_level(stubber: nil)
|
||||||
|
Dnsruby::Dnssec.reset
|
||||||
|
resolver = security_level_resolver
|
||||||
|
Dnsruby::Recursor.clear_caches(resolver)
|
||||||
|
if Rails.env.staging?
|
||||||
|
clear_dnssec_trusted_anchors_and_keys
|
||||||
|
elsif stubber
|
||||||
|
Dnsruby::Dnssec.add_trust_anchor(stubber.ds_rr)
|
||||||
|
end
|
||||||
|
recursor = Dnsruby::Recursor.new(resolver)
|
||||||
|
recursor.dnssec = true
|
||||||
|
recursor.query(name, 'A', 'IN').security_level
|
||||||
|
end
|
||||||
|
|
||||||
|
def clear_dnssec_trusted_anchors_and_keys
|
||||||
|
Dnsruby::Dnssec.clear_trust_anchors
|
||||||
|
Dnsruby::Dnssec.clear_trusted_keys
|
||||||
|
Dnsruby::Dnssec.add_trust_anchor(Dnsruby::RR.create(ENV['trusted_dnskey']))
|
||||||
|
end
|
||||||
|
|
||||||
def statuses_uniqueness
|
def statuses_uniqueness
|
||||||
return if statuses.uniq == statuses
|
return if statuses.uniq == statuses
|
||||||
errors.add(:statuses, :taken)
|
errors.add(:statuses, :taken)
|
||||||
|
|
|
@ -44,6 +44,8 @@ class Epp::Contact < Contact
|
||||||
|
|
||||||
def check_availability(codes, reg:)
|
def check_availability(codes, reg:)
|
||||||
codes = [codes] if codes.is_a?(String)
|
codes = [codes] if codes.is_a?(String)
|
||||||
|
codes = codes.map { |c| c.include?(':') ? c : "#{reg}:#{c}" }
|
||||||
|
|
||||||
res = []
|
res = []
|
||||||
codes.map { |c| c.include?(':') ? c : "#{reg}:#{c}" }.map { |c| c.strip.upcase }.each do |x|
|
codes.map { |c| c.include?(':') ? c : "#{reg}:#{c}" }.map { |c| c.strip.upcase }.each do |x|
|
||||||
c = find_by_epp_code(x)
|
c = find_by_epp_code(x)
|
||||||
|
|
|
@ -58,8 +58,8 @@ class Nameserver < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def hostname=(hostname)
|
def hostname=(hostname)
|
||||||
self[:hostname] = SimpleIDN.to_unicode(hostname)
|
self[:hostname] = SimpleIDN.to_unicode(hostname).gsub(/\.+$/, '')
|
||||||
self[:hostname_puny] = SimpleIDN.to_ascii(hostname)
|
self[:hostname_puny] = SimpleIDN.to_ascii(hostname).gsub(/\.+$/, '')
|
||||||
end
|
end
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
.panel.panel-default
|
|
||||||
.panel-heading.clearfix
|
|
||||||
= t(:dnskeys)
|
|
||||||
.table-responsive
|
|
||||||
%table.table.table-hover.table-bordered.table-condensed
|
|
||||||
%thead
|
|
||||||
%tr
|
|
||||||
%th{class: 'col-xs-1'}= t(:flag)
|
|
||||||
%th{class: 'col-xs-1'}= t(:protocol)
|
|
||||||
%th{class: 'col-xs-1'}= t(:algorithm)
|
|
||||||
%th{class: 'col-xs-9'}= t(:public_key)
|
|
||||||
%tbody
|
|
||||||
- @domain.dnskeys.each do |x|
|
|
||||||
%tr
|
|
||||||
%td= x.flags
|
|
||||||
%td= x.protocol
|
|
||||||
%td= x.alg
|
|
||||||
%td= x.public_key
|
|
|
@ -1,14 +0,0 @@
|
||||||
.panel.panel-default
|
|
||||||
.panel-heading.clearfix
|
|
||||||
= t(:legal_documents)
|
|
||||||
.table-responsive
|
|
||||||
%table.table.table-hover.table-bordered.table-condensed
|
|
||||||
%thead
|
|
||||||
%tr
|
|
||||||
%th{class: 'col-xs-8'}= t(:created_at)
|
|
||||||
%th{class: 'col-xs-4'}= t(:type)
|
|
||||||
%tbody
|
|
||||||
- legal_documents.each do |x|
|
|
||||||
%tr
|
|
||||||
%td= link_to(x.created_at, [:admin, x])
|
|
||||||
%td= x.document_type
|
|
|
@ -1,16 +0,0 @@
|
||||||
.panel.panel-default
|
|
||||||
.panel-heading.clearfix
|
|
||||||
= t(:nameservers)
|
|
||||||
.table-responsive
|
|
||||||
%table.table.table-hover.table-bordered.table-condensed
|
|
||||||
%thead
|
|
||||||
%tr
|
|
||||||
%th{class: 'col-xs-4'}= t(:hostname)
|
|
||||||
%th{class: 'col-xs-4'}= t(:ipv4)
|
|
||||||
%th{class: 'col-xs-4'}= t(:ipv6)
|
|
||||||
%tbody
|
|
||||||
- @domain.nameservers.each do |x|
|
|
||||||
%tr
|
|
||||||
%td= x
|
|
||||||
%td= x.ipv4
|
|
||||||
%td= x.ipv6
|
|
|
@ -1,18 +0,0 @@
|
||||||
#domain_statuses.panel.panel-default
|
|
||||||
.panel-heading.clearfix
|
|
||||||
= t(:statuses)
|
|
||||||
.table-responsive
|
|
||||||
%table.table.table-hover.table-bordered.table-condensed
|
|
||||||
%thead
|
|
||||||
%tr
|
|
||||||
%th{class: 'col-xs-6'}= t(:status)
|
|
||||||
%th{class: 'col-xs-6'}= t(:notes)
|
|
||||||
%tbody
|
|
||||||
- @domain.statuses.each do |status|
|
|
||||||
%tr
|
|
||||||
%td
|
|
||||||
- if @domain.pending_json.present? && [DomainStatus::PENDING_UPDATE, DomainStatus::PENDING_DELETE].include?(status)
|
|
||||||
= link_to status, admin_domain_domain_versions_path(@domain.id)
|
|
||||||
- else
|
|
||||||
= status
|
|
||||||
%td= @domain.status_notes[status]
|
|
14
app/views/mailers/csync_mailer/dnssec_deleted.html.erb
Normal file
14
app/views/mailers/csync_mailer/dnssec_deleted.html.erb
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
Tere,
|
||||||
|
<br><br>
|
||||||
|
Oleme eemaldanud Teie domeeni <%= @domain.name %> DNSSEC kirjed registrist.
|
||||||
|
|
||||||
|
Domeeni <%= @domain.name %> DNSSEC on nüüd välja lülitatud.
|
||||||
|
<%= render 'mailers/shared/signatures/signature.et.html' %>
|
||||||
|
<hr>
|
||||||
|
<br><br>
|
||||||
|
Hi,
|
||||||
|
<br><br>
|
||||||
|
We have removed DNSSEC data in our registry for domain <%= @domain.name %>.
|
||||||
|
<br>
|
||||||
|
DNSSEC has been turned off for <%= @domain.name %> as of now.
|
||||||
|
<%= render 'mailers/shared/signatures/signature.en.html' %>
|
14
app/views/mailers/csync_mailer/dnssec_updated.html.erb
Normal file
14
app/views/mailers/csync_mailer/dnssec_updated.html.erb
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
Tere,
|
||||||
|
<br><br>
|
||||||
|
Oleme uuendatud Teie domeeni <%= @domain.name %> DNSSEC andmeid registris.
|
||||||
|
<br>
|
||||||
|
Lisasime CDNSKEY väärtuses kajastatud võtme oma tsoonifaili ning on nüüd aktiveeritud.
|
||||||
|
<%= render 'mailers/shared/signatures/signature.et.html' %>
|
||||||
|
<hr>
|
||||||
|
<br><br>
|
||||||
|
Hi,
|
||||||
|
<br><br>
|
||||||
|
We have updated DNSSEC data in our registry for domain <%= @domain.name %>.
|
||||||
|
<br>
|
||||||
|
DNS key specified in CDNSKEY has been added to our zone file and is now taking effect.
|
||||||
|
<%= render 'mailers/shared/signatures/signature.en.html' %>
|
|
@ -41,6 +41,7 @@ ca_key_password: 'your-root-key-password'
|
||||||
directo_invoice_url: 'https://domain/ddddd.asp'
|
directo_invoice_url: 'https://domain/ddddd.asp'
|
||||||
cdns_scanner_input_file: '/opt/cdns/input.txt'
|
cdns_scanner_input_file: '/opt/cdns/input.txt'
|
||||||
cdns_scanner_output_file: '/opt/cdns/output.txt'
|
cdns_scanner_output_file: '/opt/cdns/output.txt'
|
||||||
|
dnssec_resolver_ips: 8.8.8.8, 8.8.4.4
|
||||||
#
|
#
|
||||||
# EPP
|
# EPP
|
||||||
#
|
#
|
||||||
|
@ -192,6 +193,10 @@ test:
|
||||||
action_mailer_force_delete_from: 'legal@registry.test'
|
action_mailer_force_delete_from: 'legal@registry.test'
|
||||||
lhv_p12_keystore: 'test/fixtures/files/keystore.p12'
|
lhv_p12_keystore: 'test/fixtures/files/keystore.p12'
|
||||||
lhv_keystore_password: 'testtest'
|
lhv_keystore_password: 'testtest'
|
||||||
|
lhv_keystore_alias: 'testtest'
|
||||||
|
cdns_scanner_input_file: 'tmp/cdns_input.txt'
|
||||||
|
cdns_scanner_output_file: 'test/fixtures/files/cdns_output.txt'
|
||||||
|
dnssec_resolver_ips: 8.8.8.8, 8.8.4.4
|
||||||
legal_documents_dir: 'test/fixtures/files'
|
legal_documents_dir: 'test/fixtures/files'
|
||||||
|
|
||||||
# Airbrake // Errbit:
|
# Airbrake // Errbit:
|
||||||
|
|
|
@ -16,6 +16,7 @@ en:
|
||||||
disputed_domains: Disputed domains
|
disputed_domains: Disputed domains
|
||||||
bulk_actions: Bulk actions
|
bulk_actions: Bulk actions
|
||||||
bounced_email_addresses: Bounced emails
|
bounced_email_addresses: Bounced emails
|
||||||
|
mass_actions: Mass actions
|
||||||
epp_log: EPP log
|
epp_log: EPP log
|
||||||
repp_log: REPP log
|
repp_log: REPP log
|
||||||
que: Que
|
que: Que
|
||||||
|
|
|
@ -6,3 +6,4 @@ en:
|
||||||
reset_btn: Reset
|
reset_btn: Reset
|
||||||
show:
|
show:
|
||||||
title: REPP log
|
title: REPP log
|
||||||
|
|
||||||
|
|
10
config/locales/mailers/csync.en.yml
Normal file
10
config/locales/mailers/csync.en.yml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
en:
|
||||||
|
csync_mailer:
|
||||||
|
dnssec_updated:
|
||||||
|
subject: >-
|
||||||
|
Teie domeeni %{domain_name} DNSSEC andmed on uuendatud
|
||||||
|
/ DNSSEC data for %{domain_name} has been updated
|
||||||
|
dnssec_deleted:
|
||||||
|
subject: >-
|
||||||
|
Teie domeeni %{domain_name} DNSSEC andmed on eemaldatud
|
||||||
|
/ DNSSEC data for %{domain_name} has been removed
|
|
@ -6,5 +6,6 @@ en:
|
||||||
It was associated with registrant %{old_registrant_code}
|
It was associated with registrant %{old_registrant_code}
|
||||||
and contacts %{old_contacts_codes}.
|
and contacts %{old_contacts_codes}.
|
||||||
contact_update: Contact %{contact} has been updated by registrant
|
contact_update: Contact %{contact} has been updated by registrant
|
||||||
|
csync: CSYNC DNSSEC %{action} for domain %{domain}
|
||||||
registrar_locked: Domain %{domain_name} has been locked by registrant
|
registrar_locked: Domain %{domain_name} has been locked by registrant
|
||||||
registrar_unlocked: Domain %{domain_name} has been unlocked by registrant
|
registrar_unlocked: Domain %{domain_name} has been unlocked by registrant
|
||||||
|
|
12
db/migrate/20200605125332_create_csync_records.rb
Normal file
12
db/migrate/20200605125332_create_csync_records.rb
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
class CreateCsyncRecords < ActiveRecord::Migration[6.0]
|
||||||
|
def change
|
||||||
|
create_table :csync_records do |t|
|
||||||
|
t.belongs_to :domain, foreign_key: true, null: false, index: { unique: true }
|
||||||
|
t.string :cdnskey, null: false
|
||||||
|
t.string :action, null: false
|
||||||
|
t.integer :times_scanned, null: false, default: 0
|
||||||
|
t.datetime :last_scan, null: false
|
||||||
|
t.timestamps
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
339
db/structure.sql
339
db/structure.sql
|
@ -2251,6 +2251,15 @@ CREATE TABLE public.registrant_verifications (
|
||||||
action character varying NOT NULL,
|
action character varying NOT NULL,
|
||||||
domain_id integer NOT NULL,
|
domain_id integer NOT NULL,
|
||||||
action_type character varying NOT NULL,
|
action_type character varying NOT NULL,
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
creator_id integer,
|
||||||
|
updater_id integer
|
||||||
|
session character varying,
|
||||||
|
children json,
|
||||||
|
ident_updated_at timestamp without time zone,
|
||||||
|
uuid character varying
|
||||||
|
>>>>>>> parent 64e3bc885a2cb8b46a1aaa4bf4f121ee7f5d44a6
|
||||||
creator_str character varying,
|
creator_str character varying,
|
||||||
updator_str character varying
|
updator_str character varying
|
||||||
);
|
);
|
||||||
|
@ -3017,21 +3026,52 @@ ALTER TABLE ONLY public.que_jobs ALTER COLUMN job_id SET DEFAULT nextval('public
|
||||||
|
|
||||||
ALTER TABLE ONLY public.registrant_verifications ALTER COLUMN id SET DEFAULT nextval('public.registrant_verifications_id_seq'::regclass);
|
ALTER TABLE ONLY public.registrant_verifications ALTER COLUMN id SET DEFAULT nextval('public.registrant_verifications_id_seq'::regclass);
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: users_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE SEQUENCE public.users_id_seq
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: id; Type: DEFAULT; Schema: public; Owner: -
|
-- Name: id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
--
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.accounts ALTER COLUMN id SET DEFAULT nextval('public.accounts_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.log_invoices
|
||||||
|
ADD CONSTRAINT log_invoices_pkey PRIMARY KEY (id);
|
||||||
|
|
||||||
|
|
||||||
ALTER TABLE ONLY public.registrars ALTER COLUMN id SET DEFAULT nextval('public.registrars_id_seq'::regclass);
|
ALTER TABLE ONLY public.registrars ALTER COLUMN id SET DEFAULT nextval('public.registrars_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: id; Type: DEFAULT; Schema: public; Owner: -
|
-- Name: id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
--
|
--
|
||||||
|
ALTER TABLE ONLY public.disputes ALTER COLUMN id SET DEFAULT nextval('public.disputes_id_seq'::regclass);
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.log_nameservers
|
||||||
|
ADD CONSTRAINT log_nameservers_pkey PRIMARY KEY (id);
|
||||||
|
|
||||||
|
|
||||||
ALTER TABLE ONLY public.reserved_domains ALTER COLUMN id SET DEFAULT nextval('public.reserved_domains_id_seq'::regclass);
|
ALTER TABLE ONLY public.reserved_domains ALTER COLUMN id SET DEFAULT nextval('public.reserved_domains_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.setting_entries ALTER COLUMN id SET DEFAULT nextval('public.setting_entries_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: id; Type: DEFAULT; Schema: public; Owner: -
|
-- Name: id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
--
|
--
|
||||||
|
@ -3050,6 +3090,285 @@ ALTER TABLE ONLY public.settings ALTER COLUMN id SET DEFAULT nextval('public.set
|
||||||
-- Name: id; Type: DEFAULT; Schema: public; Owner: -
|
-- Name: id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
--
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.domains ALTER COLUMN id SET DEFAULT nextval('public.domains_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: versions id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.email_address_verifications ALTER COLUMN id SET DEFAULT nextval('public.email_address_verifications_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: white_ips id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.email_addresses_validations ALTER COLUMN id SET DEFAULT nextval('public.email_addresses_validations_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: whois_records id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.email_addresses_verifications ALTER COLUMN id SET DEFAULT nextval('public.email_addresses_verifications_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: zones id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.epp_sessions ALTER COLUMN id SET DEFAULT nextval('public.epp_sessions_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.invoice_items ALTER COLUMN id SET DEFAULT nextval('public.invoice_items_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: invoices id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.invoices ALTER COLUMN id SET DEFAULT nextval('public.invoices_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: legal_documents id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.legal_documents ALTER COLUMN id SET DEFAULT nextval('public.legal_documents_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: log_account_activities id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.log_account_activities ALTER COLUMN id SET DEFAULT nextval('public.log_account_activities_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: log_accounts id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.log_accounts ALTER COLUMN id SET DEFAULT nextval('public.log_accounts_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: log_actions id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.log_actions ALTER COLUMN id SET DEFAULT nextval('public.log_actions_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: log_bank_statements id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.log_bank_statements ALTER COLUMN id SET DEFAULT nextval('public.log_bank_statements_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: log_bank_transactions id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.log_bank_transactions ALTER COLUMN id SET DEFAULT nextval('public.log_bank_transactions_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: log_blocked_domains id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.log_blocked_domains ALTER COLUMN id SET DEFAULT nextval('public.log_blocked_domains_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: log_certificates id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.log_certificates ALTER COLUMN id SET DEFAULT nextval('public.log_certificates_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: log_contacts id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.log_contacts ALTER COLUMN id SET DEFAULT nextval('public.log_contacts_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: log_dnskeys id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.log_dnskeys ALTER COLUMN id SET DEFAULT nextval('public.log_dnskeys_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: log_domain_contacts id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.log_domain_contacts ALTER COLUMN id SET DEFAULT nextval('public.log_domain_contacts_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: log_domains id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.log_domains ALTER COLUMN id SET DEFAULT nextval('public.log_domains_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: log_invoice_items id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.log_invoice_items ALTER COLUMN id SET DEFAULT nextval('public.log_invoice_items_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: log_invoices id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.log_invoices ALTER COLUMN id SET DEFAULT nextval('public.log_invoices_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: log_nameservers id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.log_nameservers ALTER COLUMN id SET DEFAULT nextval('public.log_nameservers_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: log_notifications id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.log_notifications ALTER COLUMN id SET DEFAULT nextval('public.log_notifications_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: log_payment_orders id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.log_payment_orders ALTER COLUMN id SET DEFAULT nextval('public.log_payment_orders_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: log_registrant_verifications id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.log_registrant_verifications ALTER COLUMN id SET DEFAULT nextval('public.log_registrant_verifications_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: log_registrars id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.log_registrars ALTER COLUMN id SET DEFAULT nextval('public.log_registrars_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: log_reserved_domains id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.log_reserved_domains ALTER COLUMN id SET DEFAULT nextval('public.log_reserved_domains_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: log_settings id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.log_settings ALTER COLUMN id SET DEFAULT nextval('public.log_settings_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: log_users id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.log_users ALTER COLUMN id SET DEFAULT nextval('public.log_users_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: log_white_ips id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.log_white_ips ALTER COLUMN id SET DEFAULT nextval('public.log_white_ips_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: nameservers id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.nameservers ALTER COLUMN id SET DEFAULT nextval('public.nameservers_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: notifications id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.notifications ALTER COLUMN id SET DEFAULT nextval('public.notifications_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: payment_orders id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.payment_orders ALTER COLUMN id SET DEFAULT nextval('public.payment_orders_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: prices id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.prices ALTER COLUMN id SET DEFAULT nextval('public.prices_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: que_jobs job_id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.que_jobs ALTER COLUMN job_id SET DEFAULT nextval('public.que_jobs_job_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: registrant_verifications id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.registrant_verifications ALTER COLUMN id SET DEFAULT nextval('public.registrant_verifications_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: registrars id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.registrars ALTER COLUMN id SET DEFAULT nextval('public.registrars_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: reserved_domains id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.reserved_domains ALTER COLUMN id SET DEFAULT nextval('public.reserved_domains_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: settings id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.settings ALTER COLUMN id SET DEFAULT nextval('public.settings_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: users id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.users ALTER COLUMN id SET DEFAULT nextval('public.users_id_seq'::regclass);
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.log_prices
|
||||||
|
ADD CONSTRAINT log_prices_pkey PRIMARY KEY (id);
|
||||||
|
|
||||||
|
|
||||||
ALTER TABLE ONLY public.users ALTER COLUMN id SET DEFAULT nextval('public.users_id_seq'::regclass);
|
ALTER TABLE ONLY public.users ALTER COLUMN id SET DEFAULT nextval('public.users_id_seq'::regclass);
|
||||||
|
|
||||||
|
|
||||||
|
@ -4318,6 +4637,19 @@ CREATE UNIQUE INDEX unique_schema_migrations ON public.schema_migrations USING b
|
||||||
-- Name: contacts_registrar_id_fk; Type: FK CONSTRAINT; Schema: public; Owner: -
|
-- Name: contacts_registrar_id_fk; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||||
--
|
--
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX unique_schema_migrations ON public.schema_migrations USING btree (version);
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: contacts process_contact_audit; Type: TRIGGER; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TRIGGER process_contact_audit AFTER INSERT OR DELETE OR UPDATE ON public.contacts FOR EACH ROW EXECUTE PROCEDURE public.process_contact_audit();
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: contacts contacts_registrar_id_fk; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
ALTER TABLE ONLY public.contacts
|
ALTER TABLE ONLY public.contacts
|
||||||
ADD CONSTRAINT contacts_registrar_id_fk FOREIGN KEY (registrar_id) REFERENCES public.registrars(id);
|
ADD CONSTRAINT contacts_registrar_id_fk FOREIGN KEY (registrar_id) REFERENCES public.registrars(id);
|
||||||
|
|
||||||
|
@ -4951,6 +5283,7 @@ INSERT INTO "schema_migrations" (version) VALUES
|
||||||
('20200605100827'),
|
('20200605100827'),
|
||||||
('20200610090110'),
|
('20200610090110'),
|
||||||
('20200630081231'),
|
('20200630081231'),
|
||||||
|
('20200605125332'),
|
||||||
('20200714115338'),
|
('20200714115338'),
|
||||||
('20200807110611'),
|
('20200807110611'),
|
||||||
('20200811074839'),
|
('20200811074839'),
|
||||||
|
@ -4961,6 +5294,6 @@ INSERT INTO "schema_migrations" (version) VALUES
|
||||||
('20200910085157'),
|
('20200910085157'),
|
||||||
('20200910102028'),
|
('20200910102028'),
|
||||||
('20200916125326'),
|
('20200916125326'),
|
||||||
('20210215101019');
|
('20200917104213'),
|
||||||
|
('20210215101019'),
|
||||||
|
('20200921084356');
|
||||||
|
|
9
test/fixtures/dns/zones.yml
vendored
9
test/fixtures/dns/zones.yml
vendored
|
@ -9,3 +9,12 @@ one:
|
||||||
minimum_ttl: 1
|
minimum_ttl: 1
|
||||||
email: admin@registry.test
|
email: admin@registry.test
|
||||||
master_nameserver: ns.test
|
master_nameserver: ns.test
|
||||||
|
subzone:
|
||||||
|
origin: 'sub.zone'
|
||||||
|
ttl: 1
|
||||||
|
refresh: 1
|
||||||
|
retry: 1
|
||||||
|
expire: 1
|
||||||
|
minimum_ttl: 1
|
||||||
|
email: admin@registry.test
|
||||||
|
master_nameserver: ns.test
|
||||||
|
|
10
test/fixtures/dnskeys.yml
vendored
Normal file
10
test/fixtures/dnskeys.yml
vendored
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
one:
|
||||||
|
domain:
|
||||||
|
flags: 257
|
||||||
|
protocol: 3
|
||||||
|
alg: 13
|
||||||
|
public_key: mdsswUyr3DPW132mOi8V9xESWE8jTo0dxCjjnopKl+GqJxpVXckHAeF+KkxLbxILfDLUT0rAK9iUzy1L53eKGQ==
|
||||||
|
ds_key_tag: 2371
|
||||||
|
ds_alg: 13
|
||||||
|
ds_digest_type: 2
|
||||||
|
ds_digest: 39456058862EA09DD96992ED2BDAFAEDE8C7E949589E3DA903A46F4F9CD373EA
|
4
test/fixtures/files/cdns_output.txt
vendored
Normal file
4
test/fixtures/files/cdns_output.txt
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
insecure-empty ns1.bestnames.test 127.0.0.1 airport.test
|
||||||
|
insecure-empty ns2.bestnames.test 127.0.0.1 airport.test
|
||||||
|
insecure ns1.bestnames.test 127.0.0.1 shop.test 257 3 13 mdsswUyr3DPW132mOi8V9xESWE8jTo0dxCjjnopKl+GqJxpVXckHAeF+KkxLbxILfDLUT0rAK9iUzy1L53eKGQ==
|
||||||
|
insecure ns2.bestnames.test 127.0.0.1 shop.test 257 3 13 mdsswUyr3DPW132mOi8V9xESWE8jTo0dxCjjnopKl+GqJxpVXckHAeF+KkxLbxILfDLUT0rAK9iUzy1L53eKGQ==
|
73
test/jobs/csync_job_test.rb
Normal file
73
test/jobs/csync_job_test.rb
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
require 'test_helper'
|
||||||
|
|
||||||
|
class CsyncJobTest < ActiveSupport::TestCase
|
||||||
|
include ActionMailer::TestHelper
|
||||||
|
|
||||||
|
setup do
|
||||||
|
@dnskey = dnskeys(:one)
|
||||||
|
@domain = domains(:shop)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_generates_input_file_for_cdnskey_scanner
|
||||||
|
@dnskey.update(domain: domains(:shop))
|
||||||
|
|
||||||
|
expected_contents = "[secure]\nns1.bestnames.test shop.test\nns2.bestnames.test shop.test\n" \
|
||||||
|
"[insecure]\nns1.bestnames.test airport.test metro.test\nns2.bestnames.test airport.test\n"
|
||||||
|
|
||||||
|
CsyncJob.run(generate: true)
|
||||||
|
|
||||||
|
assert_equal expected_contents, IO.read(ENV['cdns_scanner_input_file'])
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_creates_csync_record_when_new_cdnskey_discovered
|
||||||
|
assert_nil @domain.csync_record
|
||||||
|
CsyncJob.run
|
||||||
|
|
||||||
|
@domain.reload
|
||||||
|
assert @domain.csync_record
|
||||||
|
csync_record = @domain.csync_record
|
||||||
|
assert_equal 1, csync_record.times_scanned
|
||||||
|
assert_equal '257 3 13 mdsswUyr3DPW132mOi8V9xESWE8jTo0dxCjjnopKl+GqJxpVXckHAeF+KkxLbxILfDLUT0rAK9iUzy1L53eKGQ==', csync_record.cdnskey
|
||||||
|
|
||||||
|
assert_not @domain.dnskeys.any?
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_creates_dnskey_after_required_cycles
|
||||||
|
assert_equal 0, @domain.dnskeys.count
|
||||||
|
assert_nil @domain.csync_record
|
||||||
|
CsyncJob.run # Creates initial CsyncRecord for domain
|
||||||
|
|
||||||
|
@domain.reload
|
||||||
|
assert @domain.csync_record.present?
|
||||||
|
|
||||||
|
@domain.csync_record.update(times_scanned: 2) # 3rd time trigger DNSKEY push
|
||||||
|
assert_equal 0, @domain.dnskeys.count
|
||||||
|
assert_equal 2, @domain.csync_record.times_scanned
|
||||||
|
|
||||||
|
CsyncRecord.stub :by_domain_name, @domain.csync_record do
|
||||||
|
@domain.csync_record.stub :dnssec_validates?, true do
|
||||||
|
CsyncJob.run
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@domain.reload
|
||||||
|
assert_equal 1, @domain.dnskeys.count
|
||||||
|
assert_equal 'mdsswUyr3DPW132mOi8V9xESWE8jTo0dxCjjnopKl+GqJxpVXckHAeF+KkxLbxILfDLUT0rAK9iUzy1L53eKGQ==', @domain.dnskeys.last.public_key
|
||||||
|
assert_nil @domain.csync_record
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_sends_mail_to_contacts_if_dnskey_updated
|
||||||
|
assert_emails 1 do
|
||||||
|
CsyncJob.run
|
||||||
|
@domain.reload
|
||||||
|
|
||||||
|
CsyncRecord.stub :by_domain_name, @domain.csync_record do
|
||||||
|
@domain.csync_record.stub :dnssec_validates?, true do
|
||||||
|
2.times do
|
||||||
|
CsyncJob.run
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -291,37 +291,45 @@ class ContactTest < ActiveSupport::TestCase
|
||||||
assert_equal 'US', contact.country_code
|
assert_equal 'US', contact.country_code
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_normalizes_ident_country_code
|
def test_linked_scope_returns_contact_that_acts_as_admin_contact
|
||||||
contact = Contact.new(ident_country_code: 'us')
|
domains(:shop).admin_contacts = [@contact]
|
||||||
contact.validate
|
assert Contact.linked.include?(@contact), 'Contact should be included'
|
||||||
assert_equal 'US', contact.ident_country_code
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_generates_code
|
def test_linked_scope_returns_contact_that_acts_as_tech_contact
|
||||||
contact = Contact.new(registrar: registrars(:bestnames))
|
domains(:shop).tech_contacts = [@contact]
|
||||||
assert_nil contact.code
|
assert Contact.linked.include?(@contact), 'Contact should be included'
|
||||||
|
|
||||||
contact.generate_code
|
|
||||||
|
|
||||||
assert_not_empty contact.code
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_prohibits_code_change
|
def test_linked_scope_skips_unlinked_contact
|
||||||
assert_no_changes -> { @contact.code } do
|
contact = unlinked_contact
|
||||||
@contact.code = 'new'
|
assert_not Contact.linked.include?(contact), 'Contact should be excluded'
|
||||||
@contact.save!
|
|
||||||
@contact.reload
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_removes_duplicate_statuses
|
def test_unlinked_scope_returns_unlinked_contact
|
||||||
contact = Contact.new(statuses: %w[ok ok])
|
contact = unlinked_contact
|
||||||
assert_equal %w[ok], contact.statuses
|
assert Contact.unlinked.include?(contact), 'Contact should be included'
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_default_status
|
def test_unlinked_scope_skips_contact_that_is_linked_as_registrant
|
||||||
contact = Contact.new
|
contact = unlinked_contact
|
||||||
assert_equal %w[ok], contact.statuses
|
domains(:shop).update_columns(registrant_id: contact.becomes(Registrant).id)
|
||||||
|
|
||||||
|
assert Contact.unlinked.exclude?(contact), 'Contact should be excluded'
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_unlinked_scope_skips_contact_that_is_linked_as_admin_contact
|
||||||
|
contact = unlinked_contact
|
||||||
|
domains(:shop).admin_contacts = [contact]
|
||||||
|
|
||||||
|
assert Contact.unlinked.exclude?(contact), 'Contact should be excluded'
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_unlinked_scope_skips_contact_that_is_linked_as_tech_contact
|
||||||
|
contact = unlinked_contact
|
||||||
|
domains(:shop).tech_contacts = [contact]
|
||||||
|
|
||||||
|
assert Contact.unlinked.exclude?(contact), 'Contact should be excluded'
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_whois_gets_updated_after_contact_save
|
def test_whois_gets_updated_after_contact_save
|
||||||
|
|
289
test/models/csync_record_test.rb
Normal file
289
test/models/csync_record_test.rb
Normal file
|
@ -0,0 +1,289 @@
|
||||||
|
require 'test_helper'
|
||||||
|
|
||||||
|
class CsyncRecordTest < ActiveSupport::TestCase
|
||||||
|
setup do
|
||||||
|
@domain = domains(:shop)
|
||||||
|
|
||||||
|
@csync_record = CsyncRecord.new
|
||||||
|
@csync_record.cdnskey = '257 3 13 mdsswUyr3DPW132mOi8V9xESWE8jTo0dxCjjnopKl+GqJxpVXckHAeF+KkxLbxILfDLUT0rAK9iUzy1L53eKGQ=='
|
||||||
|
@csync_record.action = 'initialized'
|
||||||
|
@csync_record.domain = domains(:shop)
|
||||||
|
@csync_record.last_scan = Time.now
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_domain_must_be_present
|
||||||
|
assert @csync_record.valid?
|
||||||
|
@csync_record.domain = nil
|
||||||
|
assert_not @csync_record.valid?
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_action_must_be_present_and_valid
|
||||||
|
@csync_record.action = nil
|
||||||
|
assert_not @csync_record.valid?
|
||||||
|
|
||||||
|
@csync_record.action = 'definitely invalid action'
|
||||||
|
assert_not @csync_record.valid?
|
||||||
|
|
||||||
|
@csync_record.action = 'initialized'
|
||||||
|
assert @csync_record.valid?
|
||||||
|
|
||||||
|
@csync_record.action = 'rollover'
|
||||||
|
assert @csync_record.valid?
|
||||||
|
|
||||||
|
@csync_record.action = 'deactivate'
|
||||||
|
assert_not @csync_record.valid?
|
||||||
|
|
||||||
|
@csync_record.action = 'deactivate'
|
||||||
|
@csync_record.cdnskey = '0 3 0 AA=='
|
||||||
|
assert @csync_record.valid?
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_cdnskey_must_be_unique_for_domain
|
||||||
|
dnskey = @csync_record.dnskey
|
||||||
|
dnskey.save!
|
||||||
|
|
||||||
|
assert_not @csync_record.valid?
|
||||||
|
assert_includes @csync_record.errors.full_messages, 'Public key already tied to this domain'
|
||||||
|
|
||||||
|
@csync_record.cdnskey = nil
|
||||||
|
assert_not @csync_record.valid?
|
||||||
|
assert_includes @csync_record.errors.full_messages, 'Cdnskey is missing'
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_cdnskey_must_be_parsable
|
||||||
|
@csync_record.cdnskey = 'gibberish'
|
||||||
|
assert_not @csync_record.valid?
|
||||||
|
|
||||||
|
@csync_record.cdnskey = nil
|
||||||
|
assert_not @csync_record.valid?
|
||||||
|
@csync_record.cdnskey = ''
|
||||||
|
assert_not @csync_record.valid?
|
||||||
|
|
||||||
|
@csync_record.cdnskey = '257 3 13 KlHFYV42UtxC7LpsolDpoUZ9DNPDRYQypalBRIqlubBg/zg78aqciLk+NaWUbrkN7AUaM7h7tx91sLN+ORVPxA=='
|
||||||
|
assert @csync_record.valid?
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_initializes_valid_record_with_scanner_input
|
||||||
|
scanner_result = {
|
||||||
|
type: 'insecure', ns: 'ns1.bestnames.test', ns_ip: '127.0.0.1', flags: '257', proto: '3', alg: '13',
|
||||||
|
pub: 'mdsswUyr3DPW132mOi8V9xESWE8jTo0dxCjjnopKl+GqJxpVXckHAeF+KkxLbxILfDLUT0rAK9iUzy1L53eKGQ==',
|
||||||
|
cdnskey: '257 3 13 mdsswUyr3DPW132mOi8V9xESWE8jTo0dxCjjnopKl+GqJxpVXckHAeF+KkxLbxILfDLUT0rAK9iUzy1L53eKGQ=='
|
||||||
|
}
|
||||||
|
|
||||||
|
csync_record = CsyncRecord.by_domain_name(@domain.name)
|
||||||
|
csync_record.assign_scanner_data!(scanner_result)
|
||||||
|
|
||||||
|
assert csync_record.valid?
|
||||||
|
assert_equal scanner_result[:cdnskey], csync_record.cdnskey
|
||||||
|
assert_equal 'initialized', csync_record.action
|
||||||
|
assert_equal 1, csync_record.times_scanned
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_creates_rollover_record_with_scanner_input
|
||||||
|
# Rollover always requires valid dnssec conf beforehand
|
||||||
|
dnskey = @csync_record.dnskey
|
||||||
|
dnskey.save!
|
||||||
|
|
||||||
|
# Type 'secure' reflects from cdnskey-scanner that custom domain security level is SECURE (dnssec valid)
|
||||||
|
scanner_result = {
|
||||||
|
type: 'secure', ns: 'ns1.bestnames.test', ns_ip: '127.0.0.1', flags: '256', proto: '3', alg: '13',
|
||||||
|
pub: 'PiVTNvqOTrCSoXf5obNEPrDe0yhrKPmjyv+MWfoscBHF49rRIH1/yDdAXY3SyUD86qq/AiXDzsTQIqOjvak7gw==',
|
||||||
|
cdnskey: '256 3 13 PiVTNvqOTrCSoXf5obNEPrDe0yhrKPmjyv+MWfoscBHF49rRIH1/yDdAXY3SyUD86qq/AiXDzsTQIqOjvak7gw=='
|
||||||
|
}
|
||||||
|
|
||||||
|
csync_record = CsyncRecord.by_domain_name(@domain.name)
|
||||||
|
csync_record.assign_scanner_data!(scanner_result)
|
||||||
|
assert_equal 'rollover', csync_record.action
|
||||||
|
assert csync_record.valid?
|
||||||
|
|
||||||
|
scanner_result[:type] = 'insecure'
|
||||||
|
csync_record.assign_scanner_data!(scanner_result)
|
||||||
|
assert_not csync_record.valid?
|
||||||
|
assert_includes csync_record.errors.full_messages, 'Action is invalid'
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_creates_deactivate_record_with_scanner_input
|
||||||
|
# Deactivate always requires valid dnssec conf beforehand
|
||||||
|
dnskey = @csync_record.dnskey
|
||||||
|
dnskey.save!
|
||||||
|
|
||||||
|
# Type 'secure' reflects from cdnskey-scanner that custom domain security level is SECURE (dnssec valid)
|
||||||
|
scanner_result = {
|
||||||
|
type: 'secure', ns: 'ns1.bestnames.test', ns_ip: '127.0.0.1', flags: '0', proto: '3', alg: '0',
|
||||||
|
pub: 'AA==',
|
||||||
|
cdnskey: '0 3 0 AA=='
|
||||||
|
}
|
||||||
|
|
||||||
|
csync_record = CsyncRecord.by_domain_name(@domain.name)
|
||||||
|
csync_record.assign_scanner_data!(scanner_result)
|
||||||
|
assert_equal 'deactivate', csync_record.action
|
||||||
|
assert csync_record.valid?
|
||||||
|
|
||||||
|
scanner_result[:type] = 'insecure'
|
||||||
|
csync_record.assign_scanner_data!(scanner_result)
|
||||||
|
assert_not csync_record.valid?
|
||||||
|
assert_includes csync_record.errors.full_messages, 'Action is invalid'
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_initializes_dnssec_for_domain
|
||||||
|
scanner_result = {
|
||||||
|
type: 'insecure', ns: 'ns1.bestnames.test', ns_ip: '127.0.0.1', flags: '257', proto: '3', alg: '13',
|
||||||
|
pub: 'mdsswUyr3DPW132mOi8V9xESWE8jTo0dxCjjnopKl+GqJxpVXckHAeF+KkxLbxILfDLUT0rAK9iUzy1L53eKGQ==',
|
||||||
|
cdnskey: '257 3 13 mdsswUyr3DPW132mOi8V9xESWE8jTo0dxCjjnopKl+GqJxpVXckHAeF+KkxLbxILfDLUT0rAK9iUzy1L53eKGQ=='
|
||||||
|
}
|
||||||
|
|
||||||
|
2.times { CsyncRecord.by_domain_name(@domain.name).record_new_scan(scanner_result) }
|
||||||
|
@domain.reload
|
||||||
|
|
||||||
|
CsyncRecord.stub :by_domain_name, @domain.csync_record do
|
||||||
|
@domain.csync_record.stub :dnssec_validates?, true do
|
||||||
|
CsyncRecord.by_domain_name(@domain.name).record_new_scan(scanner_result)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_equal 1, @domain.dnskeys.count
|
||||||
|
assert_equal scanner_result[:pub], @domain.dnskeys.last.public_key
|
||||||
|
|
||||||
|
mail = ActionMailer::Base.deliveries.last
|
||||||
|
assert_equal (@domain.contacts.map(&:email) << @domain.registrant.email).uniq, mail.to
|
||||||
|
assert_equal mail.subject, "Teie domeeni #{@domain.name} DNSSEC andmed on uuendatud / DNSSEC data for #{@domain.name} has been updated"
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_rollovers_dnssec_for_domain
|
||||||
|
dnskey = @csync_record.dnskey
|
||||||
|
dnskey.save!
|
||||||
|
|
||||||
|
scanner_result = {
|
||||||
|
type: 'secure', ns: 'ns1.bestnames.test', ns_ip: '127.0.0.1', flags: '256', proto: '3', alg: '13',
|
||||||
|
pub: 'PiVTNvqOTrCSoXf5obNEPrDe0yhrKPmjyv+MWfoscBHF49rRIH1/yDdAXY3SyUD86qq/AiXDzsTQIqOjvak7gw==',
|
||||||
|
cdnskey: '256 3 13 PiVTNvqOTrCSoXf5obNEPrDe0yhrKPmjyv+MWfoscBHF49rRIH1/yDdAXY3SyUD86qq/AiXDzsTQIqOjvak7gw=='
|
||||||
|
}
|
||||||
|
|
||||||
|
stub_any_instance(CsyncRecord, :dnssec_validates?, true) do
|
||||||
|
CsyncRecord.by_domain_name(@domain.name).record_new_scan(scanner_result)
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_equal 2, @domain.dnskeys.count
|
||||||
|
assert_equal scanner_result[:pub], @domain.dnskeys.last.public_key
|
||||||
|
|
||||||
|
mail = ActionMailer::Base.deliveries.last
|
||||||
|
assert_equal (@domain.contacts.map(&:email) << @domain.registrant.email).uniq, mail.to
|
||||||
|
assert_equal mail.subject, "Teie domeeni #{@domain.name} DNSSEC andmed on uuendatud / DNSSEC data for #{@domain.name} has been updated"
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_deactivates_dnssec_for_domain
|
||||||
|
dnskey = @csync_record.dnskey
|
||||||
|
dnskey.save!
|
||||||
|
|
||||||
|
scanner_result = {
|
||||||
|
type: 'secure', ns: 'ns1.bestnames.test', ns_ip: '127.0.0.1', flags: '0', proto: '3', alg: '0',
|
||||||
|
pub: 'AA==',
|
||||||
|
cdnskey: '0 3 0 AA=='
|
||||||
|
}
|
||||||
|
|
||||||
|
stub_any_instance(CsyncRecord, :dnssec_validates?, true) do
|
||||||
|
CsyncRecord.by_domain_name(@domain.name).record_new_scan(scanner_result)
|
||||||
|
end
|
||||||
|
|
||||||
|
assert @domain.dnskeys.empty?
|
||||||
|
|
||||||
|
mail = ActionMailer::Base.deliveries.last
|
||||||
|
assert_equal (@domain.contacts.map(&:email) << @domain.registrant.email).uniq, mail.to
|
||||||
|
assert_equal mail.subject, "Teie domeeni #{@domain.name} DNSSEC andmed on eemaldatud / DNSSEC data for #{@domain.name} has been removed"
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_validates_security_level_for_initialize_action
|
||||||
|
@csync_record.action = 'initialized'
|
||||||
|
@domain.stub :dnssec_security_level, Dnsruby::Message::SecurityLevel.INSECURE do
|
||||||
|
assert @csync_record.valid_pre_action?
|
||||||
|
assert_not @csync_record.valid_post_action?
|
||||||
|
end
|
||||||
|
|
||||||
|
@domain.stub :dnssec_security_level, Dnsruby::Message::SecurityLevel.BOGUS do
|
||||||
|
assert @csync_record.valid_pre_action?
|
||||||
|
assert_not @csync_record.valid_post_action?
|
||||||
|
end
|
||||||
|
|
||||||
|
@domain.stub :dnssec_security_level, Dnsruby::Message::SecurityLevel.SECURE do
|
||||||
|
assert @csync_record.valid_post_action?
|
||||||
|
assert_not @csync_record.valid_pre_action?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_validates_security_level_for_rollover_action
|
||||||
|
@csync_record.action = 'rollover'
|
||||||
|
@domain.stub :dnssec_security_level, Dnsruby::Message::SecurityLevel.INSECURE do
|
||||||
|
assert_not @csync_record.valid_pre_action?
|
||||||
|
assert_not @csync_record.valid_post_action?
|
||||||
|
end
|
||||||
|
|
||||||
|
@domain.stub :dnssec_security_level, Dnsruby::Message::SecurityLevel.BOGUS do
|
||||||
|
assert_not @csync_record.valid_pre_action?
|
||||||
|
assert_not @csync_record.valid_post_action?
|
||||||
|
end
|
||||||
|
|
||||||
|
@domain.stub :dnssec_security_level, Dnsruby::Message::SecurityLevel.SECURE do
|
||||||
|
assert @csync_record.valid_pre_action?
|
||||||
|
assert @csync_record.valid_post_action?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_validates_security_level_for_deactivate_action
|
||||||
|
@csync_record.action = 'deactivate'
|
||||||
|
@domain.stub :dnssec_security_level, Dnsruby::Message::SecurityLevel.INSECURE do
|
||||||
|
assert @csync_record.valid_post_action?
|
||||||
|
assert_not @csync_record.valid_pre_action?
|
||||||
|
end
|
||||||
|
|
||||||
|
@domain.stub :dnssec_security_level, Dnsruby::Message::SecurityLevel.BOGUS do
|
||||||
|
assert @csync_record.valid_post_action?
|
||||||
|
assert_not @csync_record.valid_pre_action?
|
||||||
|
end
|
||||||
|
|
||||||
|
@domain.stub :dnssec_security_level, Dnsruby::Message::SecurityLevel.SECURE do
|
||||||
|
assert @csync_record.valid_pre_action?
|
||||||
|
assert_not @csync_record.valid_post_action?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_returns_correct_result_if_pre_and_post_actions_succeed
|
||||||
|
stub_any_instance(CsyncRecord, :valid_post_action?, true) do
|
||||||
|
stub_any_instance(CsyncRecord, :valid_pre_action?, true) do
|
||||||
|
assert @csync_record.dnssec_validates?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
stub_any_instance(CsyncRecord, :valid_post_action?, false) do
|
||||||
|
stub_any_instance(CsyncRecord, :valid_pre_action?, false) do
|
||||||
|
assert_not @csync_record.dnssec_validates?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_dnssec_validation_fails_if_domain_unreachable
|
||||||
|
@domain.name = 'definitely.not.valid.domain.123'
|
||||||
|
assert_not @csync_record.dnssec_validates?
|
||||||
|
end
|
||||||
|
|
||||||
|
def stub_any_instance(klass, method, value)
|
||||||
|
klass.class_eval do
|
||||||
|
alias_method :"new_#{method}", method
|
||||||
|
|
||||||
|
define_method(method) do
|
||||||
|
if value.respond_to?(:call)
|
||||||
|
value.call
|
||||||
|
else
|
||||||
|
value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
yield
|
||||||
|
ensure
|
||||||
|
klass.class_eval do
|
||||||
|
undef_method method
|
||||||
|
alias_method method, :"new_#{method}"
|
||||||
|
undef_method :"new_#{method}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Add table
Add a link
Reference in a new issue