mirror of
https://github.com/internetee/registry.git
synced 2025-06-07 13:15:40 +02:00
Merge branch '1884-unable-to-apply-registry-lock' of https://github.com/internetee/registry into 1884-unable-to-apply-registry-lock
This commit is contained in:
commit
b7149387d9
29 changed files with 1591 additions and 113 deletions
|
@ -1,3 +1,6 @@
|
||||||
|
31.03.2021
|
||||||
|
* Implemented child to parent syncronisation (csync) for cdnskeys [#658](https://github.com/internetee/registry/issues/658)
|
||||||
|
|
||||||
29.03.2021
|
29.03.2021
|
||||||
* Full EPP functionality to REPP API [#1756](https://github.com/internetee/registry/issues/1756)
|
* Full EPP functionality to REPP API [#1756](https://github.com/internetee/registry/issues/1756)
|
||||||
|
|
||||||
|
|
3
Gemfile
3
Gemfile
|
@ -5,6 +5,8 @@ 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 'mime-types-data'
|
||||||
|
gem 'mimemagic', '0.3.10'
|
||||||
gem 'rails', '~> 6.0'
|
gem 'rails', '~> 6.0'
|
||||||
gem 'rest-client'
|
gem 'rest-client'
|
||||||
gem 'uglifier'
|
gem 'uglifier'
|
||||||
|
@ -39,6 +41,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'
|
||||||
|
|
116
Gemfile.lock
116
Gemfile.lock
|
@ -76,60 +76,60 @@ GIT
|
||||||
GEM
|
GEM
|
||||||
remote: https://rubygems.org/
|
remote: https://rubygems.org/
|
||||||
specs:
|
specs:
|
||||||
actioncable (6.0.3.5)
|
actioncable (6.0.3.6)
|
||||||
actionpack (= 6.0.3.5)
|
actionpack (= 6.0.3.6)
|
||||||
nio4r (~> 2.0)
|
nio4r (~> 2.0)
|
||||||
websocket-driver (>= 0.6.1)
|
websocket-driver (>= 0.6.1)
|
||||||
actionmailbox (6.0.3.5)
|
actionmailbox (6.0.3.6)
|
||||||
actionpack (= 6.0.3.5)
|
actionpack (= 6.0.3.6)
|
||||||
activejob (= 6.0.3.5)
|
activejob (= 6.0.3.6)
|
||||||
activerecord (= 6.0.3.5)
|
activerecord (= 6.0.3.6)
|
||||||
activestorage (= 6.0.3.5)
|
activestorage (= 6.0.3.6)
|
||||||
activesupport (= 6.0.3.5)
|
activesupport (= 6.0.3.6)
|
||||||
mail (>= 2.7.1)
|
mail (>= 2.7.1)
|
||||||
actionmailer (6.0.3.5)
|
actionmailer (6.0.3.6)
|
||||||
actionpack (= 6.0.3.5)
|
actionpack (= 6.0.3.6)
|
||||||
actionview (= 6.0.3.5)
|
actionview (= 6.0.3.6)
|
||||||
activejob (= 6.0.3.5)
|
activejob (= 6.0.3.6)
|
||||||
mail (~> 2.5, >= 2.5.4)
|
mail (~> 2.5, >= 2.5.4)
|
||||||
rails-dom-testing (~> 2.0)
|
rails-dom-testing (~> 2.0)
|
||||||
actionpack (6.0.3.5)
|
actionpack (6.0.3.6)
|
||||||
actionview (= 6.0.3.5)
|
actionview (= 6.0.3.6)
|
||||||
activesupport (= 6.0.3.5)
|
activesupport (= 6.0.3.6)
|
||||||
rack (~> 2.0, >= 2.0.8)
|
rack (~> 2.0, >= 2.0.8)
|
||||||
rack-test (>= 0.6.3)
|
rack-test (>= 0.6.3)
|
||||||
rails-dom-testing (~> 2.0)
|
rails-dom-testing (~> 2.0)
|
||||||
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
||||||
actiontext (6.0.3.5)
|
actiontext (6.0.3.6)
|
||||||
actionpack (= 6.0.3.5)
|
actionpack (= 6.0.3.6)
|
||||||
activerecord (= 6.0.3.5)
|
activerecord (= 6.0.3.6)
|
||||||
activestorage (= 6.0.3.5)
|
activestorage (= 6.0.3.6)
|
||||||
activesupport (= 6.0.3.5)
|
activesupport (= 6.0.3.6)
|
||||||
nokogiri (>= 1.8.5)
|
nokogiri (>= 1.8.5)
|
||||||
actionview (6.0.3.5)
|
actionview (6.0.3.6)
|
||||||
activesupport (= 6.0.3.5)
|
activesupport (= 6.0.3.6)
|
||||||
builder (~> 3.1)
|
builder (~> 3.1)
|
||||||
erubi (~> 1.4)
|
erubi (~> 1.4)
|
||||||
rails-dom-testing (~> 2.0)
|
rails-dom-testing (~> 2.0)
|
||||||
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
||||||
active_interaction (3.8.3)
|
active_interaction (3.8.3)
|
||||||
activemodel (>= 4, < 7)
|
activemodel (>= 4, < 7)
|
||||||
activejob (6.0.3.5)
|
activejob (6.0.3.6)
|
||||||
activesupport (= 6.0.3.5)
|
activesupport (= 6.0.3.6)
|
||||||
globalid (>= 0.3.6)
|
globalid (>= 0.3.6)
|
||||||
activemodel (6.0.3.5)
|
activemodel (6.0.3.6)
|
||||||
activesupport (= 6.0.3.5)
|
activesupport (= 6.0.3.6)
|
||||||
activerecord (6.0.3.5)
|
activerecord (6.0.3.6)
|
||||||
activemodel (= 6.0.3.5)
|
activemodel (= 6.0.3.6)
|
||||||
activesupport (= 6.0.3.5)
|
activesupport (= 6.0.3.6)
|
||||||
activerecord-import (1.0.8)
|
activerecord-import (1.0.8)
|
||||||
activerecord (>= 3.2)
|
activerecord (>= 3.2)
|
||||||
activestorage (6.0.3.5)
|
activestorage (6.0.3.6)
|
||||||
actionpack (= 6.0.3.5)
|
actionpack (= 6.0.3.6)
|
||||||
activejob (= 6.0.3.5)
|
activejob (= 6.0.3.6)
|
||||||
activerecord (= 6.0.3.5)
|
activerecord (= 6.0.3.6)
|
||||||
marcel (~> 0.3.1)
|
marcel (~> 1.0.0)
|
||||||
activesupport (6.0.3.5)
|
activesupport (6.0.3.6)
|
||||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||||
i18n (>= 0.7, < 2)
|
i18n (>= 0.7, < 2)
|
||||||
minitest (~> 5.1)
|
minitest (~> 5.1)
|
||||||
|
@ -215,6 +215,8 @@ GEM
|
||||||
railties (>= 4.1.0)
|
railties (>= 4.1.0)
|
||||||
responders
|
responders
|
||||||
warden (~> 1.2.3)
|
warden (~> 1.2.3)
|
||||||
|
dnsruby (1.61.5)
|
||||||
|
simpleidn (~> 0.1)
|
||||||
docile (1.3.5)
|
docile (1.3.5)
|
||||||
domain_name (0.5.20190701)
|
domain_name (0.5.20190701)
|
||||||
unf (>= 0.0.5, < 1.0.0)
|
unf (>= 0.0.5, < 1.0.0)
|
||||||
|
@ -277,14 +279,15 @@ GEM
|
||||||
nokogiri (>= 1.5.9)
|
nokogiri (>= 1.5.9)
|
||||||
mail (2.7.1)
|
mail (2.7.1)
|
||||||
mini_mime (>= 0.1.1)
|
mini_mime (>= 0.1.1)
|
||||||
marcel (0.3.3)
|
marcel (1.0.0)
|
||||||
mimemagic (~> 0.3.2)
|
|
||||||
method_source (0.8.2)
|
method_source (0.8.2)
|
||||||
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)
|
||||||
mini_mime (1.0.2)
|
nokogiri (~> 1)
|
||||||
|
rake
|
||||||
|
mini_mime (1.0.3)
|
||||||
mini_portile2 (2.4.0)
|
mini_portile2 (2.4.0)
|
||||||
minitest (5.14.4)
|
minitest (5.14.4)
|
||||||
monetize (1.9.4)
|
monetize (1.9.4)
|
||||||
|
@ -350,29 +353,29 @@ GEM
|
||||||
rack
|
rack
|
||||||
rack-test (1.1.0)
|
rack-test (1.1.0)
|
||||||
rack (>= 1.0, < 3)
|
rack (>= 1.0, < 3)
|
||||||
rails (6.0.3.5)
|
rails (6.0.3.6)
|
||||||
actioncable (= 6.0.3.5)
|
actioncable (= 6.0.3.6)
|
||||||
actionmailbox (= 6.0.3.5)
|
actionmailbox (= 6.0.3.6)
|
||||||
actionmailer (= 6.0.3.5)
|
actionmailer (= 6.0.3.6)
|
||||||
actionpack (= 6.0.3.5)
|
actionpack (= 6.0.3.6)
|
||||||
actiontext (= 6.0.3.5)
|
actiontext (= 6.0.3.6)
|
||||||
actionview (= 6.0.3.5)
|
actionview (= 6.0.3.6)
|
||||||
activejob (= 6.0.3.5)
|
activejob (= 6.0.3.6)
|
||||||
activemodel (= 6.0.3.5)
|
activemodel (= 6.0.3.6)
|
||||||
activerecord (= 6.0.3.5)
|
activerecord (= 6.0.3.6)
|
||||||
activestorage (= 6.0.3.5)
|
activestorage (= 6.0.3.6)
|
||||||
activesupport (= 6.0.3.5)
|
activesupport (= 6.0.3.6)
|
||||||
bundler (>= 1.3.0)
|
bundler (>= 1.3.0)
|
||||||
railties (= 6.0.3.5)
|
railties (= 6.0.3.6)
|
||||||
sprockets-rails (>= 2.0.0)
|
sprockets-rails (>= 2.0.0)
|
||||||
rails-dom-testing (2.0.3)
|
rails-dom-testing (2.0.3)
|
||||||
activesupport (>= 4.2.0)
|
activesupport (>= 4.2.0)
|
||||||
nokogiri (>= 1.6)
|
nokogiri (>= 1.6)
|
||||||
rails-html-sanitizer (1.3.0)
|
rails-html-sanitizer (1.3.0)
|
||||||
loofah (~> 2.3)
|
loofah (~> 2.3)
|
||||||
railties (6.0.3.5)
|
railties (6.0.3.6)
|
||||||
actionpack (= 6.0.3.5)
|
actionpack (= 6.0.3.6)
|
||||||
activesupport (= 6.0.3.5)
|
activesupport (= 6.0.3.6)
|
||||||
method_source
|
method_source
|
||||||
rake (>= 0.8.7)
|
rake (>= 0.8.7)
|
||||||
thor (>= 0.20.3, < 2.0)
|
thor (>= 0.20.3, < 2.0)
|
||||||
|
@ -519,6 +522,7 @@ DEPENDENCIES
|
||||||
devise (~> 4.7)
|
devise (~> 4.7)
|
||||||
digidoc_client!
|
digidoc_client!
|
||||||
directo!
|
directo!
|
||||||
|
dnsruby (~> 1.61)
|
||||||
domain_name
|
domain_name
|
||||||
e_invoice!
|
e_invoice!
|
||||||
epp!
|
epp!
|
||||||
|
@ -531,6 +535,8 @@ DEPENDENCIES
|
||||||
jquery-ui-rails (= 5.0.5)
|
jquery-ui-rails (= 5.0.5)
|
||||||
kaminari
|
kaminari
|
||||||
lhv!
|
lhv!
|
||||||
|
mime-types-data
|
||||||
|
mimemagic (= 0.3.10)
|
||||||
minitest (~> 5.14)
|
minitest (~> 5.14)
|
||||||
money-rails
|
money-rails
|
||||||
nokogiri (~> 1.10.0)
|
nokogiri (~> 1.10.0)
|
||||||
|
|
124
app/jobs/csync_job.rb
Normal file
124
app/jobs/csync_job.rb
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class CsyncJob < Que::Job
|
||||||
|
def run(generate: false)
|
||||||
|
@store = {}
|
||||||
|
@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
|
||||||
|
|
||||||
|
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 = []
|
||||||
|
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
|
||||||
|
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
|
||||||
|
end
|
||||||
|
cdnskey = key_bit && proto && alg && pub ? "#{key_bit} #{proto} #{alg} #{pub}" : nil
|
||||||
|
record = { domain: domain, type: type, ns: ns, ns_ip: ns_ip, flags: key_bit, proto: proto,
|
||||||
|
alg: alg, pub: pub, cdnskey: cdnskey }
|
||||||
|
records << record
|
||||||
|
end
|
||||||
|
records
|
||||||
|
end
|
||||||
|
|
||||||
|
# From this point we're working on generating input for cdnskey-scanner
|
||||||
|
def gather_pollable_domains
|
||||||
|
@logger.info 'CsyncJob Generate: Gathering current domain(s) data'
|
||||||
|
Nameserver.select(:hostname, :domain_id).all.each do |ns|
|
||||||
|
%i[secure insecure].each do |i|
|
||||||
|
@input_store[i][ns.hostname] = [] unless @input_store[i].key? ns.hostname
|
||||||
|
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
|
||||||
|
|
||||||
|
def generate_scanner_input
|
||||||
|
@logger.info 'CsyncJob Generate: Gathering current domain(s) data'
|
||||||
|
gather_pollable_domains
|
||||||
|
|
||||||
|
out_file = File.new(ENV['cdns_scanner_input_file'], 'w+')
|
||||||
|
|
||||||
|
%i[secure insecure].each do |state|
|
||||||
|
out_file.puts "[#{state}]"
|
||||||
|
create_input_lines(out_file, state)
|
||||||
|
end
|
||||||
|
|
||||||
|
out_file.close
|
||||||
|
@logger.info 'CsyncJob Generate: Finished writing output to ' + ENV['cdns_scanner_input_file']
|
||||||
|
end
|
||||||
|
|
||||||
|
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?
|
||||||
|
|
||||||
|
out_file.puts "#{nameserver} #{domains}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
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
|
||||||
|
|
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' %>
|
|
@ -39,8 +39,9 @@ ca_key_path: '/home/registry/registry/shared/ca/private/ca.key.pem'
|
||||||
ca_key_password: 'your-root-key-password'
|
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_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
|
398
db/structure.sql
398
db/structure.sql
|
@ -1988,6 +1988,40 @@ CREATE TABLE public.log_users (
|
||||||
uuid character varying
|
uuid character varying
|
||||||
);
|
);
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: csync_records; Type: TABLE; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE public.csync_records (
|
||||||
|
id bigint NOT NULL,
|
||||||
|
domain_id bigint NOT NULL,
|
||||||
|
cdnskey character varying NOT NULL,
|
||||||
|
action character varying NOT NULL,
|
||||||
|
times_scanned integer DEFAULT 0 NOT NULL,
|
||||||
|
last_scan timestamp without time zone NOT NULL,
|
||||||
|
created_at timestamp(6) without time zone NOT NULL,
|
||||||
|
updated_at timestamp(6) without time zone NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: csync_records_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE SEQUENCE public.csync_records_id_seq
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: csync_records_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER SEQUENCE public.csync_records_id_seq OWNED BY public.csync_records.id;
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: log_users_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
-- Name: log_users_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
||||||
|
@ -2251,6 +2285,12 @@ 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,
|
||||||
|
creator_id integer,
|
||||||
|
updater_id integer,
|
||||||
|
session character varying,
|
||||||
|
children json,
|
||||||
|
ident_updated_at timestamp without time zone,
|
||||||
|
uuid character varying,
|
||||||
creator_str character varying,
|
creator_str character varying,
|
||||||
updator_str character varying
|
updator_str character varying
|
||||||
);
|
);
|
||||||
|
@ -3017,21 +3057,40 @@ 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: 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 +3109,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);
|
||||||
|
|
||||||
|
|
||||||
|
@ -3369,22 +3707,6 @@ ALTER TABLE ONLY public.log_invoice_items
|
||||||
ADD CONSTRAINT log_invoice_items_pkey PRIMARY KEY (id);
|
ADD CONSTRAINT log_invoice_items_pkey PRIMARY KEY (id);
|
||||||
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Name: log_invoices_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
|
|
||||||
--
|
|
||||||
|
|
||||||
ALTER TABLE ONLY public.log_invoices
|
|
||||||
ADD CONSTRAINT log_invoices_pkey PRIMARY KEY (id);
|
|
||||||
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Name: log_nameservers_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
|
|
||||||
--
|
|
||||||
|
|
||||||
ALTER TABLE ONLY public.log_nameservers
|
|
||||||
ADD CONSTRAINT log_nameservers_pkey PRIMARY KEY (id);
|
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: log_notifications_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
|
-- Name: log_notifications_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
|
||||||
--
|
--
|
||||||
|
@ -3401,14 +3723,6 @@ ALTER TABLE ONLY public.log_payment_orders
|
||||||
ADD CONSTRAINT log_payment_orders_pkey PRIMARY KEY (id);
|
ADD CONSTRAINT log_payment_orders_pkey PRIMARY KEY (id);
|
||||||
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Name: log_prices_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
|
||||||
--
|
|
||||||
|
|
||||||
ALTER TABLE ONLY public.log_prices
|
|
||||||
ADD CONSTRAINT log_prices_pkey PRIMARY KEY (id);
|
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: log_registrant_verifications_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
-- Name: log_registrant_verifications_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||||
--
|
--
|
||||||
|
@ -4006,6 +4320,17 @@ CREATE INDEX index_log_contacts_on_whodunnit ON public.log_contacts USING btree
|
||||||
CREATE INDEX index_log_dnskeys_on_item_type_and_item_id ON public.log_dnskeys USING btree (item_type, item_id);
|
CREATE INDEX index_log_dnskeys_on_item_type_and_item_id ON public.log_dnskeys USING btree (item_type, item_id);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: csync_records id; Type: DEFAULT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
ALTER TABLE ONLY public.csync_records ALTER COLUMN id SET DEFAULT nextval('public.csync_records_id_seq'::regclass);
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: index_csync_records_on_domain_id; Type: INDEX; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX index_csync_records_on_domain_id ON public.csync_records USING btree (domain_id);
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: index_log_dnskeys_on_whodunnit; Type: INDEX; Schema: public; Owner: -; Tablespace:
|
-- Name: index_log_dnskeys_on_whodunnit; Type: INDEX; Schema: public; Owner: -; Tablespace:
|
||||||
--
|
--
|
||||||
|
@ -4313,9 +4638,8 @@ CREATE UNIQUE INDEX unique_data_migrations ON public.data_migrations USING btree
|
||||||
|
|
||||||
CREATE UNIQUE INDEX unique_schema_migrations ON public.schema_migrations USING btree (version);
|
CREATE UNIQUE INDEX unique_schema_migrations ON public.schema_migrations USING btree (version);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: contacts_registrar_id_fk; Type: FK CONSTRAINT; Schema: public; Owner: -
|
-- Name: contacts contacts_registrar_id_fk; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||||
--
|
--
|
||||||
|
|
||||||
ALTER TABLE ONLY public.contacts
|
ALTER TABLE ONLY public.contacts
|
||||||
|
@ -4521,6 +4845,19 @@ ALTER TABLE ONLY public.nameservers
|
||||||
ALTER TABLE ONLY public.users
|
ALTER TABLE ONLY public.users
|
||||||
ADD CONSTRAINT user_registrar_id_fk FOREIGN KEY (registrar_id) REFERENCES public.registrars(id);
|
ADD CONSTRAINT user_registrar_id_fk FOREIGN KEY (registrar_id) REFERENCES public.registrars(id);
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: csync_records csync_records_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.csync_records
|
||||||
|
ADD CONSTRAINT csync_records_pkey PRIMARY KEY (id);
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: csync_records fk_rails_5df85aeb13; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public.csync_records
|
||||||
|
ADD CONSTRAINT fk_rails_5df85aeb13 FOREIGN KEY (domain_id) REFERENCES public.domains(id);
|
||||||
|
|
||||||
--
|
--
|
||||||
-- PostgreSQL database dump complete
|
-- PostgreSQL database dump complete
|
||||||
|
@ -4951,6 +5288,7 @@ INSERT INTO "schema_migrations" (version) VALUES
|
||||||
('20200605100827'),
|
('20200605100827'),
|
||||||
('20200610090110'),
|
('20200610090110'),
|
||||||
('20200630081231'),
|
('20200630081231'),
|
||||||
|
('20200605125332'),
|
||||||
('20200714115338'),
|
('20200714115338'),
|
||||||
('20200807110611'),
|
('20200807110611'),
|
||||||
('20200811074839'),
|
('20200811074839'),
|
||||||
|
@ -4961,6 +5299,6 @@ INSERT INTO "schema_migrations" (version) VALUES
|
||||||
('20200910085157'),
|
('20200910085157'),
|
||||||
('20200910102028'),
|
('20200910102028'),
|
||||||
('20200916125326'),
|
('20200916125326'),
|
||||||
('20210215101019');
|
('20200917104213'),
|
||||||
|
('20210215101019'),
|
||||||
|
('20200921084356');
|
||||||
|
|
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 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_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