From 4519ba4894d9d0aa2dcd72c61eeae51e2d090686 Mon Sep 17 00:00:00 2001 From: olegphenomenon Date: Wed, 29 Dec 2021 15:20:49 +0200 Subject: [PATCH] updated validator for nameserver --- app/interactions/actions/domain_create.rb | 19 ++++++ app/interactions/actions/domain_update.rb | 21 +++++++ app/interactions/actions/email_check.rb | 3 +- .../domains/nameserver_validator.rb | 44 +++++++++++++ app/jobs/nameserver_record_validation_job.rb | 63 ++++++++++++++----- 5 files changed, 132 insertions(+), 18 deletions(-) create mode 100644 app/interactions/domains/nameserver_validator.rb diff --git a/app/interactions/actions/domain_create.rb b/app/interactions/actions/domain_create.rb index 8fd25df0f..e27c4e38e 100644 --- a/app/interactions/actions/domain_create.rb +++ b/app/interactions/actions/domain_create.rb @@ -14,6 +14,7 @@ module Actions assign_registrant assign_nameservers + check_for_valid_nameserver assign_domain_contacts domain.attach_default_contacts assign_expiry_time @@ -22,6 +23,24 @@ module Actions commit end + def check_for_valid_nameserver + nameservers_data = params[:nameservers_attributes] + + nameservers_data.each do |nameserver| + result = parse_nameserver_hash(nameserver) + + next unless result + end + end + + def parse_nameserver_hash(nameserver) + result = Domains::NameserverValidator.run(hostname: nameserver[:hostname]) + + return true if result[:result] + + domain.add_epp_error('2303', nil, result[:reason], 'Problem with nameserver: ') + end + def check_contact_duplications if check_for_same_contacts(@admin_contacts, 'admin') && check_for_same_contacts(@tech_contacts, 'tech') diff --git a/app/interactions/actions/domain_update.rb b/app/interactions/actions/domain_update.rb index 40b7876f6..080f98e75 100644 --- a/app/interactions/actions/domain_update.rb +++ b/app/interactions/actions/domain_update.rb @@ -14,6 +14,7 @@ module Actions assign_new_registrant if params[:registrant] assign_relational_modifications assign_requested_statuses + check_for_valid_nameserver ::Actions::BaseAction.maybe_attach_legal_doc(domain, params[:legal_document]) commit @@ -28,6 +29,26 @@ module Actions assign_tech_contact_changes end + def check_for_valid_nameserver + nameservers_data = params[:nameservers] + + nameservers_data.each do |nameserver| + result = parse_nameserver_hash(nameserver) + + next unless result + end + end + + def parse_nameserver_hash(nameserver) + return false unless nameserver[:action] == "add" + + result = Domains::NameserverValidator.run(hostname: nameserver[:hostname]) + + return true if result[:result] + + domain.add_epp_error('2303', nil, result[:reason], 'Problem with nameserver: ') + end + def check_for_same_contacts(contacts, contact_type) return unless contacts.uniq.count != contacts.count diff --git a/app/interactions/actions/email_check.rb b/app/interactions/actions/email_check.rb index b358db08d..ceab888ff 100644 --- a/app/interactions/actions/email_check.rb +++ b/app/interactions/actions/email_check.rb @@ -82,7 +82,8 @@ module Actions dns_servers = ENV['dnssec_resolver_ips'].to_s.split(',').map(&:strip) Resolv::DNS.open({ nameserver: dns_servers }) do |dns| - dns.timeouts = ENV['a_and_aaaa_validation_timeout'].to_i || 1 + dns.timeouts = ENV['a_and_aaaa_validation_timeout'] || 1 + dns.timeouts = dns.timeouts.to_i ress = nil case value diff --git a/app/interactions/domains/nameserver_validator.rb b/app/interactions/domains/nameserver_validator.rb new file mode 100644 index 000000000..6021c0a75 --- /dev/null +++ b/app/interactions/domains/nameserver_validator.rb @@ -0,0 +1,44 @@ +module Domains + module NameserverValidator + include Dnsruby + + extend self + + def run(hostname:) + validate(hostname) + end + + private + + def validate(hostname) + resolver = setup_resolver + result = resolver.query(hostname, Dnsruby::Types.SOA) + + return { result: false, reason: 'authority' } if result.authority.empty? + + decision = result.authority.all? do |a| + a.serial.present? + end + + return { result: false, reason: 'serial' } unless decision + + { result: true, reason: '' } + rescue Dnsruby::NXDomain => e + logger.info "#{e} - seems hostname don't found" + return { result: false, reason: 'not found' } + rescue StandardError => e + logger.info e + return { result: false, reason: 'exception', error_info: e } + end + + def setup_resolver + timeout = ENV['a_and_aaaa_validation_timeout'] || 1 + dns_servers = ENV['dnssec_resolver_ips'].to_s.split(',').map(&:strip) + Resolver.new({nameserver: dns_servers, timeout: timeout.to_i}) + end + + def logger + @logger ||= Rails.logger + end + end +end diff --git a/app/jobs/nameserver_record_validation_job.rb b/app/jobs/nameserver_record_validation_job.rb index fca365cbb..ad39f684b 100644 --- a/app/jobs/nameserver_record_validation_job.rb +++ b/app/jobs/nameserver_record_validation_job.rb @@ -3,37 +3,66 @@ require 'resolv' class NameserverRecordValidationJob < ApplicationJob + include Dnsruby + def perform(nameserver = nil) if nameserver.nil? Nameserver.all.map do |nameserver| - result = validate(nameserver) - inform_to_registrar(nameserver) unless result + result = Domains::NameserverValidator.run(hostname: nameserver.hostname) + + if result[:result] + true + else + parse_result(result, nameserver) + false + end end else - result = validate(nameserver) - inform_to_registrar(nameserver) unless result + result = Domains::NameserverValidator.run(hostname: nameserver.hostname) + return parse_result(result, nameserver) unless result[:result] + + true end end private - def validate(nameserver) - return true if Resolv.getaddress nameserver.hostname - rescue Resolv::ResolvError - false + def parse_result(result, nameserver) + text = "" + case result[:reason] + when 'authority' + text = "Authority information about nameserver hostname **#{nameserver.hostname}** doesn't present" + when 'serial' + text = "Serial number for nameserver hostname **#{nameserver.hostname}** doesn't present" + when 'not found' + text = "Seems nameserver hostname **#{nameserver.hostname}** doesn't exist" + when 'exception' + text = "Something goes wrong, exception name: **#{result[:error_info]}**" + end + + logger.info text + failed_log(text: text, nameserver: nameserver) + + false end - # def glue_record_required?(nameserver) - # return false unless nameserver.hostname? && nameserver.domain - # - # DomainName(nameserver.hostname).domain == nameserver.domain.name - # end + def failed_log(text:, nameserver:) + inform_to_tech_contact(text) + inform_to_registrar(text: text, nameserver: nameserver) - def inform_to_tech_contact - return + false end - def inform_to_registrar(nameserver) - nameserver.domain.registrar.notifications.create!(text: "Nameserver doesn't response") + def inform_to_tech_contact(text) + "NEED TO DO!" + text + end + + def inform_to_registrar(text:, nameserver:) + nameserver.domain.registrar.notifications.create!(text: text) + end + + def logger + @logger ||= Rails.logger end end