From f637b94dbbfb15ff2092189c521313adcd29c211 Mon Sep 17 00:00:00 2001
From: olegphenomenon
Date: Thu, 4 Nov 2021 13:52:00 +0200
Subject: [PATCH 01/33] added validation before update
---
app/interactions/actions/domain_update.rb | 45 +++++++++++++++++++++++
config/locales/en.yml | 1 +
2 files changed, 46 insertions(+)
diff --git a/app/interactions/actions/domain_update.rb b/app/interactions/actions/domain_update.rb
index 40b7876f6..3178de8c5 100644
--- a/app/interactions/actions/domain_update.rb
+++ b/app/interactions/actions/domain_update.rb
@@ -14,11 +14,56 @@ module Actions
assign_new_registrant if params[:registrant]
assign_relational_modifications
assign_requested_statuses
+ validate_dnskey unless Rails.env.test?
::Actions::BaseAction.maybe_attach_legal_doc(domain, params[:legal_document])
commit
end
+ def validate_dnskey
+ domain = Domain.find_by(name: @params[:domain])
+ dns = prepare_resolver
+ update_params_info = parse_data_from_update_request(@params[:dns_keys][0])
+
+ domain.add_epp_error('2308', nil, nil, I18n.t(:dns_policy_violation)) if domain.nameservers.empty?
+
+ domain.nameservers.each do |n|
+ zone_info = parse_data_from_zonefile(dns_resolver: dns, hostname: n.hostname)
+
+ domain.add_epp_error('2308', nil, nil, I18n.t(:dns_policy_violation)) unless zone_info == update_params_info
+ end
+
+ true
+ end
+
+ def parse_data_from_update_request(data)
+ {
+ flags: data[:flags],
+ algorithm: data[:alg],
+ protocol: data[:protocol],
+ }
+ end
+
+ def parse_data_from_zonefile(dns_resolver:, hostname:)
+ alg = dns_resolver.query(hostname, 'DS').answer[0].rdata[1]
+ result = dns_resolver.query(hostname, 'DNSKEY').answer[0]
+
+ {
+ flags: result.flags.to_s,
+ algorithm: alg.to_s,
+ protocol: result.protocol.to_s,
+ }
+ end
+
+ def prepare_resolver
+ dns = Dnsruby::Resolver.new(nameserver: ['8.8.8.8', '8.8.4.4'])
+ dns.do_validation = true
+ dns.do_caching = true
+ dns.dnssec = true
+
+ dns
+ end
+
def assign_relational_modifications
assign_nameserver_modifications if params[:nameservers]
assign_dnssec_modifications if params[:dns_keys]
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 31947350d..2f7e8a0aa 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -666,6 +666,7 @@ en:
user_not_authenticated: "user not authenticated"
actions: Actions
contact_has_been_archived: 'Contact with code %{contact_code} has been archieved because it has been orphaned for longer than %{orphan_months} months.'
+ dns_policy_violation: "Data management policy violation: DNSKEY does not match or not found in the authoritative nameservers"
number:
currency:
From 46042020e4bfb42e60abc134466a15323d444d9b Mon Sep 17 00:00:00 2001
From: olegphenomenon
Date: Fri, 5 Nov 2021 08:35:21 +0200
Subject: [PATCH 02/33] add condition if zoen return nil answer
---
app/interactions/actions/domain_update.rb | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/app/interactions/actions/domain_update.rb b/app/interactions/actions/domain_update.rb
index 3178de8c5..ae671da70 100644
--- a/app/interactions/actions/domain_update.rb
+++ b/app/interactions/actions/domain_update.rb
@@ -14,7 +14,7 @@ module Actions
assign_new_registrant if params[:registrant]
assign_relational_modifications
assign_requested_statuses
- validate_dnskey unless Rails.env.test?
+ validate_dnskey unless Rails.env.test? || Rails.env.development?
::Actions::BaseAction.maybe_attach_legal_doc(domain, params[:legal_document])
commit
@@ -27,10 +27,10 @@ module Actions
domain.add_epp_error('2308', nil, nil, I18n.t(:dns_policy_violation)) if domain.nameservers.empty?
- domain.nameservers.each do |n|
- zone_info = parse_data_from_zonefile(dns_resolver: dns, hostname: n.hostname)
+ zone_info = parse_data_from_zonefile(dns_resolver: dns, hostname: domain.name)
- domain.add_epp_error('2308', nil, nil, I18n.t(:dns_policy_violation)) unless zone_info == update_params_info
+ unless zone_info == update_params_info || zone_info.nil?
+ domain.add_epp_error('2308', nil, nil, I18n.t(:dns_policy_violation))
end
true
@@ -46,12 +46,14 @@ module Actions
def parse_data_from_zonefile(dns_resolver:, hostname:)
alg = dns_resolver.query(hostname, 'DS').answer[0].rdata[1]
- result = dns_resolver.query(hostname, 'DNSKEY').answer[0]
+ result = dns_resolver.query(hostname, 'DNSKEY').answer
+
+ return nil if answer.empty?
{
- flags: result.flags.to_s,
+ flags: result[0].flags.to_s,
algorithm: alg.to_s,
- protocol: result.protocol.to_s,
+ protocol: result[0].protocol.to_s,
}
end
From ff2531ac1f2f76171660a6b48b748e857ae51e1b Mon Sep 17 00:00:00 2001
From: olegphenomenon
Date: Tue, 16 Nov 2021 12:53:43 +0200
Subject: [PATCH 03/33] added dns_servers_keys in application.yml.sample
---
app/interactions/actions/domain_update.rb | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/app/interactions/actions/domain_update.rb b/app/interactions/actions/domain_update.rb
index ae671da70..aa310f052 100644
--- a/app/interactions/actions/domain_update.rb
+++ b/app/interactions/actions/domain_update.rb
@@ -58,7 +58,8 @@ module Actions
end
def prepare_resolver
- dns = Dnsruby::Resolver.new(nameserver: ['8.8.8.8', '8.8.4.4'])
+ dns_servers = ENV['dnssec_resolver_ips'].to_s.split(',').map(&:strip)
+ dns = Dnsruby::Resolver.new(nameserver: dns_servers || ['8.8.8.8, 8.8.4.4'])
dns.do_validation = true
dns.do_caching = true
dns.dnssec = true
From 9e023354520bc05d5078aec2376de3653e61ac73 Mon Sep 17 00:00:00 2001
From: olegphenomenon
Date: Tue, 16 Nov 2021 15:36:40 +0200
Subject: [PATCH 04/33] hardcoded ip_resolver for test purpose
---
app/interactions/actions/domain_update.rb | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/app/interactions/actions/domain_update.rb b/app/interactions/actions/domain_update.rb
index aa310f052..86d6a43f1 100644
--- a/app/interactions/actions/domain_update.rb
+++ b/app/interactions/actions/domain_update.rb
@@ -14,7 +14,7 @@ module Actions
assign_new_registrant if params[:registrant]
assign_relational_modifications
assign_requested_statuses
- validate_dnskey unless Rails.env.test? || Rails.env.development?
+ validate_dnskey unless Rails.env.test?
::Actions::BaseAction.maybe_attach_legal_doc(domain, params[:legal_document])
commit
@@ -59,7 +59,7 @@ module Actions
def prepare_resolver
dns_servers = ENV['dnssec_resolver_ips'].to_s.split(',').map(&:strip)
- dns = Dnsruby::Resolver.new(nameserver: dns_servers || ['8.8.8.8, 8.8.4.4'])
+ dns = Dnsruby::Resolver.new({nameserver: ['192.168.99.97']})
dns.do_validation = true
dns.do_caching = true
dns.dnssec = true
From 1c1c28a55c9f51075bbdedbbc0b63f42e30895c1 Mon Sep 17 00:00:00 2001
From: olegphenomenon
Date: Tue, 16 Nov 2021 16:32:29 +0200
Subject: [PATCH 05/33] updated error handler
---
app/interactions/actions/domain_update.rb | 22 +++++++++++++---------
1 file changed, 13 insertions(+), 9 deletions(-)
diff --git a/app/interactions/actions/domain_update.rb b/app/interactions/actions/domain_update.rb
index 86d6a43f1..91c41fcde 100644
--- a/app/interactions/actions/domain_update.rb
+++ b/app/interactions/actions/domain_update.rb
@@ -21,7 +21,7 @@ module Actions
end
def validate_dnskey
- domain = Domain.find_by(name: @params[:domain])
+ # domain = Domain.find_by(name: @params[:domain])
dns = prepare_resolver
update_params_info = parse_data_from_update_request(@params[:dns_keys][0])
@@ -45,16 +45,20 @@ module Actions
end
def parse_data_from_zonefile(dns_resolver:, hostname:)
- alg = dns_resolver.query(hostname, 'DS').answer[0].rdata[1]
- result = dns_resolver.query(hostname, 'DNSKEY').answer
+ begin
+ alg = dns_resolver.query(hostname, 'DS').answer[0].rdata[1]
+ result = dns_resolver.query(hostname, 'DNSKEY').answer
- return nil if answer.empty?
+ return nil if answer.empty?
- {
- flags: result[0].flags.to_s,
- algorithm: alg.to_s,
- protocol: result[0].protocol.to_s,
- }
+ {
+ flags: result[0].flags.to_s,
+ algorithm: alg.to_s,
+ protocol: result[0].protocol.to_s,
+ }
+ rescue Dnsruby::NXDomain
+ domain.add_epp_error('2308', nil, nil, I18n.t(:dns_policy_violation))
+ end
end
def prepare_resolver
From e34d84103ca82bdf2a013e9e93a6f8a1a7bbd9b3 Mon Sep 17 00:00:00 2001
From: olegphenomenon
Date: Tue, 23 Nov 2021 10:28:39 +0200
Subject: [PATCH 06/33] tests
---
app/interactions/actions/domain_update.rb | 161 +++++++++++++++-------
1 file changed, 109 insertions(+), 52 deletions(-)
diff --git a/app/interactions/actions/domain_update.rb b/app/interactions/actions/domain_update.rb
index 91c41fcde..81c9953aa 100644
--- a/app/interactions/actions/domain_update.rb
+++ b/app/interactions/actions/domain_update.rb
@@ -14,63 +14,12 @@ module Actions
assign_new_registrant if params[:registrant]
assign_relational_modifications
assign_requested_statuses
- validate_dnskey unless Rails.env.test?
+ validate_dnssec unless Rails.env.test?
::Actions::BaseAction.maybe_attach_legal_doc(domain, params[:legal_document])
commit
end
- def validate_dnskey
- # domain = Domain.find_by(name: @params[:domain])
- dns = prepare_resolver
- update_params_info = parse_data_from_update_request(@params[:dns_keys][0])
-
- domain.add_epp_error('2308', nil, nil, I18n.t(:dns_policy_violation)) if domain.nameservers.empty?
-
- zone_info = parse_data_from_zonefile(dns_resolver: dns, hostname: domain.name)
-
- unless zone_info == update_params_info || zone_info.nil?
- domain.add_epp_error('2308', nil, nil, I18n.t(:dns_policy_violation))
- end
-
- true
- end
-
- def parse_data_from_update_request(data)
- {
- flags: data[:flags],
- algorithm: data[:alg],
- protocol: data[:protocol],
- }
- end
-
- def parse_data_from_zonefile(dns_resolver:, hostname:)
- begin
- alg = dns_resolver.query(hostname, 'DS').answer[0].rdata[1]
- result = dns_resolver.query(hostname, 'DNSKEY').answer
-
- return nil if answer.empty?
-
- {
- flags: result[0].flags.to_s,
- algorithm: alg.to_s,
- protocol: result[0].protocol.to_s,
- }
- rescue Dnsruby::NXDomain
- domain.add_epp_error('2308', nil, nil, I18n.t(:dns_policy_violation))
- end
- end
-
- def prepare_resolver
- dns_servers = ENV['dnssec_resolver_ips'].to_s.split(',').map(&:strip)
- dns = Dnsruby::Resolver.new({nameserver: ['192.168.99.97']})
- dns.do_validation = true
- dns.do_caching = true
- dns.dnssec = true
-
- dns
- end
-
def assign_relational_modifications
assign_nameserver_modifications if params[:nameservers]
assign_dnssec_modifications if params[:dns_keys]
@@ -165,6 +114,114 @@ module Actions
end
end
+ # ============================
+ # str.unpack("H*").first
+ # irb(main):111:0> res.answer[0].public_key.to_jwk
+ # => {"kty"=>:EC, "crv"=>:"P-256", "x"=>"Qib532jY06DaPgJQP9k4B8hjYGMKxgICf_QxsIxLp_A", "y"=>"A67HVgWBrj1mEkIT7OJxXAY263DFf5t7gu7a1hNUzw4", "kid"=>"rzgBwFog0-1Eopl1J9kBm0YU8lEsws_jJnh-Se8UcAg"}
+ # вот этат x и есть public key
+ # irb(main):122:0> res.answer[0].public_key.export
+ # => "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEQib532jY06DaPgJQP9k4B8hjYGMK\nxgICf/QxsIxLp/ADrsdWBYGuPWYSQhPs4nFcBjbrcMV/m3uC7trWE1TPDg==\n-----END PUBLIC KEY-----\n"
+
+ def prepare_resolver
+ dns_servers = ENV['dnssec_resolver_ips'].to_s.split(',').map(&:strip)
+ dns = Dnsruby::Resolver.new({nameserver: ['192.168.99.97']})
+ dns.do_validation = true
+ dns.do_caching = true
+ dns.dnssec = true
+
+ dns
+ end
+
+ def validate_dnssec
+ dns = prepare_resolver
+ ds_record = dns.query(@params[:domain], 'DS').answer[0].rdata
+ ds_digest = dns.query(@params[:domain], 'DS').answer[0].digest
+
+ p "++++++++++++++"
+ p ds_digest.upcase!
+ # @params[:dns_keys][0]
+ p generate_ds_digest(@params[:dns_keys][0])
+ p "++++++++++++++"
+ end
+
+ def generate_ds_digest(data)
+ flags_hex = int_to_hex(data[:flags].to_i)
+ protocol_hex = int_to_hex(data[:protocol].to_i)
+ alg_hex = int_to_hex(data[:alg].to_i)
+ public_key_hex = bin_to_hex(Base64.decode64(data[:public_key]))
+
+ domain = Domain.find_by(name: @params[:domain])
+
+ hex = [domain.name_in_wire_format, flags_hex, protocol_hex, alg_hex, public_key_hex].join
+ bin = hex_to_bin(hex)
+
+ ds_digest_type = Setting.ds_digest_type if ds_digest_type.blank? || !DS_DIGEST_TYPE.include?(ds_digest_type)
+
+ case ds_digest_type
+ when 1
+ ds_digest = Digest::SHA1.hexdigest(bin).upcase
+ when 2
+ ds_digest = Digest::SHA256.hexdigest(bin).upcase
+ end
+
+ ds_digest
+ end
+
+ def int_to_hex(num)
+ num = num.to_s(16)
+ num.prepend('0') if num.length.odd?
+ end
+
+ def hex_to_bin(num)
+ num.scan(/../).map(&:hex).pack('c*')
+ end
+
+ def bin_to_hex(num)
+ num.each_byte.map { |b| format('%02X', b) }.join
+ end
+
+ #
+ # def validate_dnskey
+ # # domain = Domain.find_by(name: @params[:domain])
+ # dns = prepare_resolver
+ # update_params_info = parse_data_from_update_request(@params[:dns_keys][0])
+ #
+ # domain.add_epp_error('2308', nil, nil, I18n.t(:dns_policy_violation)) if domain.nameservers.empty?
+ #
+ # zone_info = parse_data_from_zonefile(dns_resolver: dns, hostname: domain.name)
+ #
+ # unless zone_info == update_params_info || zone_info.nil?
+ # domain.add_epp_error('2308', nil, nil, I18n.t(:dns_policy_violation))
+ # end
+ #
+ # true
+ # end
+ #
+ # def parse_data_from_update_request(data)
+ # {
+ # flags: data[:flags],
+ # algorithm: data[:alg],
+ # protocol: data[:protocol],
+ # }
+ # end
+ #
+ # def parse_data_from_zonefile(dns_resolver:, hostname:)
+ # begin
+ # alg = dns_resolver.query(hostname, 'DS').answer[0].rdata[1]
+ # result = dns_resolver.query(hostname, 'DNSKEY').answer
+ #
+ # return nil if answer.empty?
+ #
+ # {
+ # flags: result[0].flags.to_s,
+ # algorithm: alg.to_s,
+ # protocol: result[0].protocol.to_s,
+ # }
+ # rescue Dnsruby::NXDomain
+ # domain.add_epp_error('2308', nil, nil, I18n.t(:dns_policy_violation))
+ # end
+ # end
+
def assign_removable_dnskey(key)
dnkey = domain.dnskeys.find_by(key.except(:action))
domain.add_epp_error(2303, nil, nil, %i[dnskeys not_found]) unless dnkey
From 6527ef6e607dc8f805f8f12d7ab596d989752dd4 Mon Sep 17 00:00:00 2001
From: olegphenomenon
Date: Wed, 24 Nov 2021 16:40:00 +0200
Subject: [PATCH 07/33] updated dns check of dubzone
---
app/interactions/actions/domain_update.rb | 140 ++++++++++------------
1 file changed, 60 insertions(+), 80 deletions(-)
diff --git a/app/interactions/actions/domain_update.rb b/app/interactions/actions/domain_update.rb
index 81c9953aa..da74a538e 100644
--- a/app/interactions/actions/domain_update.rb
+++ b/app/interactions/actions/domain_update.rb
@@ -114,14 +114,6 @@ module Actions
end
end
- # ============================
- # str.unpack("H*").first
- # irb(main):111:0> res.answer[0].public_key.to_jwk
- # => {"kty"=>:EC, "crv"=>:"P-256", "x"=>"Qib532jY06DaPgJQP9k4B8hjYGMKxgICf_QxsIxLp_A", "y"=>"A67HVgWBrj1mEkIT7OJxXAY263DFf5t7gu7a1hNUzw4", "kid"=>"rzgBwFog0-1Eopl1J9kBm0YU8lEsws_jJnh-Se8UcAg"}
- # вот этат x и есть public key
- # irb(main):122:0> res.answer[0].public_key.export
- # => "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEQib532jY06DaPgJQP9k4B8hjYGMK\nxgICf/QxsIxLp/ADrsdWBYGuPWYSQhPs4nFcBjbrcMV/m3uC7trWE1TPDg==\n-----END PUBLIC KEY-----\n"
-
def prepare_resolver
dns_servers = ENV['dnssec_resolver_ips'].to_s.split(',').map(&:strip)
dns = Dnsruby::Resolver.new({nameserver: ['192.168.99.97']})
@@ -134,93 +126,81 @@ module Actions
def validate_dnssec
dns = prepare_resolver
- ds_record = dns.query(@params[:domain], 'DS').answer[0].rdata
- ds_digest = dns.query(@params[:domain], 'DS').answer[0].digest
+ subzone_records = get_dnskey_records_from_subzone(resolver: dns, hostname: @params[:domain])
+ form_extension_records = extensional_dnskeys_data
- p "++++++++++++++"
- p ds_digest.upcase!
- # @params[:dns_keys][0]
- p generate_ds_digest(@params[:dns_keys][0])
- p "++++++++++++++"
+ validate_data(subzone_records: subzone_records, form_extension_records: form_extension_records)
end
- def generate_ds_digest(data)
- flags_hex = int_to_hex(data[:flags].to_i)
- protocol_hex = int_to_hex(data[:protocol].to_i)
- alg_hex = int_to_hex(data[:alg].to_i)
- public_key_hex = bin_to_hex(Base64.decode64(data[:public_key]))
+ def make_magic(subzone_records:, form_data:)
+ subzone_records.any? do |subzone_data|
+ subzone_data[:basic] == form_data[:basic] &&
+ subzone_data[:public_key].include?(form_data[:public_key])
+ end
+ end
- domain = Domain.find_by(name: @params[:domain])
+ def validate_data(subzone_records:, form_extension_records:)
- hex = [domain.name_in_wire_format, flags_hex, protocol_hex, alg_hex, public_key_hex].join
- bin = hex_to_bin(hex)
+ flag = false
+ form_extension_records.each do |form_data|
+ flag = make_magic(subzone_records: subzone_records, form_data: form_data)
- ds_digest_type = Setting.ds_digest_type if ds_digest_type.blank? || !DS_DIGEST_TYPE.include?(ds_digest_type)
-
- case ds_digest_type
- when 1
- ds_digest = Digest::SHA1.hexdigest(bin).upcase
- when 2
- ds_digest = Digest::SHA256.hexdigest(bin).upcase
+ break if flag
end
- ds_digest
+ return validation_dns_key_error unless flag
+
+ flag
end
- def int_to_hex(num)
- num = num.to_s(16)
- num.prepend('0') if num.length.odd?
+ def get_dnskey_records_from_subzone(resolver:, hostname:)
+ begin
+ ds_records_answers = resolver.query(hostname, 'DNSKEY').answer
+
+ result_container = []
+
+ ds_records_answers.each do |ds|
+ next unless ds.type == Dnsruby::Types.DNSKEY
+
+ result_container << {
+ basic: {
+ flags: ds.flags.to_s,
+ algorithm: ds.algorithm.code.to_s,
+ protocol: ds.protocol.to_s
+ },
+ public_key: ds.public_key.export.gsub!(/\s+/, '')
+ }
+ end
+
+ return result_container
+
+ rescue Dnsruby::NXDomain
+ domain.add_epp_error('2308', nil, nil, I18n.t(:dns_policy_violation))
+ end
end
- def hex_to_bin(num)
- num.scan(/../).map(&:hex).pack('c*')
+ def validation_dns_key_error
+ domain.add_epp_error('2308', nil, nil, I18n.t(:dns_policy_violation))
end
- def bin_to_hex(num)
- num.each_byte.map { |b| format('%02X', b) }.join
- end
+ def extensional_dnskeys_data
+ dnskeys_data = @params[:dns_keys]
- #
- # def validate_dnskey
- # # domain = Domain.find_by(name: @params[:domain])
- # dns = prepare_resolver
- # update_params_info = parse_data_from_update_request(@params[:dns_keys][0])
- #
- # domain.add_epp_error('2308', nil, nil, I18n.t(:dns_policy_violation)) if domain.nameservers.empty?
- #
- # zone_info = parse_data_from_zonefile(dns_resolver: dns, hostname: domain.name)
- #
- # unless zone_info == update_params_info || zone_info.nil?
- # domain.add_epp_error('2308', nil, nil, I18n.t(:dns_policy_violation))
- # end
- #
- # true
- # end
- #
- # def parse_data_from_update_request(data)
- # {
- # flags: data[:flags],
- # algorithm: data[:alg],
- # protocol: data[:protocol],
- # }
- # end
- #
- # def parse_data_from_zonefile(dns_resolver:, hostname:)
- # begin
- # alg = dns_resolver.query(hostname, 'DS').answer[0].rdata[1]
- # result = dns_resolver.query(hostname, 'DNSKEY').answer
- #
- # return nil if answer.empty?
- #
- # {
- # flags: result[0].flags.to_s,
- # algorithm: alg.to_s,
- # protocol: result[0].protocol.to_s,
- # }
- # rescue Dnsruby::NXDomain
- # domain.add_epp_error('2308', nil, nil, I18n.t(:dns_policy_violation))
- # end
- # end
+ result_container = []
+
+ dnskeys_data.each do |ds|
+ result_container << {
+ basic: {
+ flags: ds[:flags].to_s,
+ algorithm: ds[:alg].to_s,
+ protocol: ds[:protocol].to_s,
+ },
+ public_key: ds[:public_key]
+ }
+ end
+
+ result_container
+ end
def assign_removable_dnskey(key)
dnkey = domain.dnskeys.find_by(key.except(:action))
From a49da009663dab95436ac608c666c912c1830e21 Mon Sep 17 00:00:00 2001
From: olegphenomenon
Date: Thu, 25 Nov 2021 12:57:13 +0200
Subject: [PATCH 08/33] dnskey can be removed
---
app/interactions/actions/domain_update.rb | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/app/interactions/actions/domain_update.rb b/app/interactions/actions/domain_update.rb
index da74a538e..7bea60ccb 100644
--- a/app/interactions/actions/domain_update.rb
+++ b/app/interactions/actions/domain_update.rb
@@ -124,11 +124,17 @@ module Actions
dns
end
+ # {:domain=>"dnssec.ee", :registrar_id=>2, :dns_keys=>[{:flags=>"256", :protocol=>"3", :alg=>"13", :public_key=>"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE6JSqRM8bzEhp7jJbpor44JjEXPfsLBEEFviJ1fnRl85XrT9QiLtmkWk8/YcQggenUxWPvbkmFGbP17wsrbrKyg==", :action=>"rem"}]}
+
def validate_dnssec
+ return if @params[:action] == 'rem'
+
dns = prepare_resolver
subzone_records = get_dnskey_records_from_subzone(resolver: dns, hostname: @params[:domain])
form_extension_records = extensional_dnskeys_data
+ return true if form_extension_records.empty?
+
validate_data(subzone_records: subzone_records, form_extension_records: form_extension_records)
end
@@ -143,6 +149,7 @@ module Actions
flag = false
form_extension_records.each do |form_data|
+
flag = make_magic(subzone_records: subzone_records, form_data: form_data)
break if flag
@@ -189,6 +196,8 @@ module Actions
result_container = []
dnskeys_data.each do |ds|
+ next if ds[:action] == 'rem'
+
result_container << {
basic: {
flags: ds[:flags].to_s,
From 6dc552536e19d279dc2a7c022991b3a16f93a11d Mon Sep 17 00:00:00 2001
From: olegphenomenon
Date: Thu, 25 Nov 2021 13:20:01 +0200
Subject: [PATCH 09/33] added conditions if form data is empty
---
app/interactions/actions/domain_update.rb | 2 ++
1 file changed, 2 insertions(+)
diff --git a/app/interactions/actions/domain_update.rb b/app/interactions/actions/domain_update.rb
index 7bea60ccb..bf197f296 100644
--- a/app/interactions/actions/domain_update.rb
+++ b/app/interactions/actions/domain_update.rb
@@ -193,6 +193,8 @@ module Actions
def extensional_dnskeys_data
dnskeys_data = @params[:dns_keys]
+ return [] if dnskeys_data.nil?
+
result_container = []
dnskeys_data.each do |ds|
From 9b07b5ff0f75023e915628c88b155744f0de7852 Mon Sep 17 00:00:00 2001
From: olegphenomenon
Date: Fri, 31 Dec 2021 11:18:06 +0200
Subject: [PATCH 10/33] refactored
---
app/interactions/actions/domain_update.rb | 31 +++++++++--------------
1 file changed, 12 insertions(+), 19 deletions(-)
diff --git a/app/interactions/actions/domain_update.rb b/app/interactions/actions/domain_update.rb
index bf197f296..efd63e96f 100644
--- a/app/interactions/actions/domain_update.rb
+++ b/app/interactions/actions/domain_update.rb
@@ -116,7 +116,7 @@ module Actions
def prepare_resolver
dns_servers = ENV['dnssec_resolver_ips'].to_s.split(',').map(&:strip)
- dns = Dnsruby::Resolver.new({nameserver: ['192.168.99.97']})
+ dns = Dnsruby::Resolver.new({ nameserver: dns_servers })
dns.do_validation = true
dns.do_caching = true
dns.dnssec = true
@@ -124,8 +124,6 @@ module Actions
dns
end
- # {:domain=>"dnssec.ee", :registrar_id=>2, :dns_keys=>[{:flags=>"256", :protocol=>"3", :alg=>"13", :public_key=>"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE6JSqRM8bzEhp7jJbpor44JjEXPfsLBEEFviJ1fnRl85XrT9QiLtmkWk8/YcQggenUxWPvbkmFGbP17wsrbrKyg==", :action=>"rem"}]}
-
def validate_dnssec
return if @params[:action] == 'rem'
@@ -146,10 +144,8 @@ module Actions
end
def validate_data(subzone_records:, form_extension_records:)
-
flag = false
form_extension_records.each do |form_data|
-
flag = make_magic(subzone_records: subzone_records, form_data: form_data)
break if flag
@@ -161,7 +157,6 @@ module Actions
end
def get_dnskey_records_from_subzone(resolver:, hostname:)
- begin
ds_records_answers = resolver.query(hostname, 'DNSKEY').answer
result_container = []
@@ -173,17 +168,15 @@ module Actions
basic: {
flags: ds.flags.to_s,
algorithm: ds.algorithm.code.to_s,
- protocol: ds.protocol.to_s
+ protocol: ds.protocol.to_s,
},
- public_key: ds.public_key.export.gsub!(/\s+/, '')
+ public_key: ds.public_key.export.gsub!(/\s+/, ''),
}
end
- return result_container
-
- rescue Dnsruby::NXDomain
- domain.add_epp_error('2308', nil, nil, I18n.t(:dns_policy_violation))
- end
+ result_container
+ rescue Dnsruby::NXDomain
+ domain.add_epp_error('2308', nil, nil, I18n.t(:dns_policy_violation))
end
def validation_dns_key_error
@@ -201,12 +194,12 @@ module Actions
next if ds[:action] == 'rem'
result_container << {
- basic: {
- flags: ds[:flags].to_s,
- algorithm: ds[:alg].to_s,
- protocol: ds[:protocol].to_s,
- },
- public_key: ds[:public_key]
+ basic: {
+ flags: ds[:flags].to_s,
+ algorithm: ds[:alg].to_s,
+ protocol: ds[:protocol].to_s,
+ },
+ public_key: ds[:public_key],
}
end
From ae269c6772caafce1fe363ee6bc3645b5bbd4da8 Mon Sep 17 00:00:00 2001
From: olegphenomenon
Date: Fri, 31 Dec 2021 13:03:17 +0200
Subject: [PATCH 11/33] move on functionality for separate service object and
updated tests
---
app/interactions/actions/domain_update.rb | 94 +-----------------
app/services/validate_dnssec.rb | 97 +++++++++++++++++++
.../registrant_api_verifications_test.rb | 2 +-
.../epp/domain/update/base_test.rb | 1 +
.../epp/domain/update/rem_dns_test.rb | 1 +
.../repp/v1/domains/contacts_test.rb | 1 +
.../repp/v1/domains/dnssec_test.rb | 1 +
.../repp/v1/domains/nameservers_test.rb | 1 +
.../repp/v1/domains/update_test.rb | 1 +
test/jobs/domain_update_confirm_job_test.rb | 1 +
10 files changed, 106 insertions(+), 94 deletions(-)
create mode 100644 app/services/validate_dnssec.rb
diff --git a/app/interactions/actions/domain_update.rb b/app/interactions/actions/domain_update.rb
index efd63e96f..505989c06 100644
--- a/app/interactions/actions/domain_update.rb
+++ b/app/interactions/actions/domain_update.rb
@@ -14,7 +14,7 @@ module Actions
assign_new_registrant if params[:registrant]
assign_relational_modifications
assign_requested_statuses
- validate_dnssec unless Rails.env.test?
+ ValidateDnssec.validate_dnssec(params: params, domain: domain)
::Actions::BaseAction.maybe_attach_legal_doc(domain, params[:legal_document])
commit
@@ -114,98 +114,6 @@ module Actions
end
end
- def prepare_resolver
- dns_servers = ENV['dnssec_resolver_ips'].to_s.split(',').map(&:strip)
- dns = Dnsruby::Resolver.new({ nameserver: dns_servers })
- dns.do_validation = true
- dns.do_caching = true
- dns.dnssec = true
-
- dns
- end
-
- def validate_dnssec
- return if @params[:action] == 'rem'
-
- dns = prepare_resolver
- subzone_records = get_dnskey_records_from_subzone(resolver: dns, hostname: @params[:domain])
- form_extension_records = extensional_dnskeys_data
-
- return true if form_extension_records.empty?
-
- validate_data(subzone_records: subzone_records, form_extension_records: form_extension_records)
- end
-
- def make_magic(subzone_records:, form_data:)
- subzone_records.any? do |subzone_data|
- subzone_data[:basic] == form_data[:basic] &&
- subzone_data[:public_key].include?(form_data[:public_key])
- end
- end
-
- def validate_data(subzone_records:, form_extension_records:)
- flag = false
- form_extension_records.each do |form_data|
- flag = make_magic(subzone_records: subzone_records, form_data: form_data)
-
- break if flag
- end
-
- return validation_dns_key_error unless flag
-
- flag
- end
-
- def get_dnskey_records_from_subzone(resolver:, hostname:)
- ds_records_answers = resolver.query(hostname, 'DNSKEY').answer
-
- result_container = []
-
- ds_records_answers.each do |ds|
- next unless ds.type == Dnsruby::Types.DNSKEY
-
- result_container << {
- basic: {
- flags: ds.flags.to_s,
- algorithm: ds.algorithm.code.to_s,
- protocol: ds.protocol.to_s,
- },
- public_key: ds.public_key.export.gsub!(/\s+/, ''),
- }
- end
-
- result_container
- rescue Dnsruby::NXDomain
- domain.add_epp_error('2308', nil, nil, I18n.t(:dns_policy_violation))
- end
-
- def validation_dns_key_error
- domain.add_epp_error('2308', nil, nil, I18n.t(:dns_policy_violation))
- end
-
- def extensional_dnskeys_data
- dnskeys_data = @params[:dns_keys]
-
- return [] if dnskeys_data.nil?
-
- result_container = []
-
- dnskeys_data.each do |ds|
- next if ds[:action] == 'rem'
-
- result_container << {
- basic: {
- flags: ds[:flags].to_s,
- algorithm: ds[:alg].to_s,
- protocol: ds[:protocol].to_s,
- },
- public_key: ds[:public_key],
- }
- end
-
- result_container
- end
-
def assign_removable_dnskey(key)
dnkey = domain.dnskeys.find_by(key.except(:action))
domain.add_epp_error(2303, nil, nil, %i[dnskeys not_found]) unless dnkey
diff --git a/app/services/validate_dnssec.rb b/app/services/validate_dnssec.rb
new file mode 100644
index 000000000..1cc2a9422
--- /dev/null
+++ b/app/services/validate_dnssec.rb
@@ -0,0 +1,97 @@
+module ValidateDnssec
+ include Dnsruby
+
+ extend self
+
+ def prepare_resolver
+ dns_servers = ENV['dnssec_resolver_ips'].to_s.split(',').map(&:strip)
+ dns = Dnsruby::Resolver.new({ nameserver: dns_servers })
+ dns.do_validation = false
+ dns.do_caching = false
+ dns.dnssec = true
+
+ dns
+ end
+
+ def validate_dnssec(params:, domain:)
+ return if params[:action] == 'rem'
+
+ dns = prepare_resolver
+ subzone_records = get_dnskey_records_from_subzone(resolver: dns, hostname: params[:domain], domain: domain)
+ form_extension_records = extensional_dnskeys_data(params)
+
+ return true if form_extension_records.empty?
+
+ validate_data(subzone_records: subzone_records, form_extension_records: form_extension_records, domain: domain)
+ end
+
+ def make_magic(subzone_records:, form_data:)
+ subzone_records.any? do |subzone_data|
+ subzone_data[:basic] == form_data[:basic] &&
+ subzone_data[:public_key].include?(form_data[:public_key])
+ end
+ end
+
+ def validate_data(subzone_records:, form_extension_records:, domain:)
+ flag = false
+ form_extension_records.each do |form_data|
+ flag = make_magic(subzone_records: subzone_records, form_data: form_data)
+
+ break if flag
+ end
+
+ return validation_dns_key_error(domain) unless flag
+
+ flag
+ end
+
+ def get_dnskey_records_from_subzone(resolver:, hostname:, domain:)
+ ds_records_answers = resolver.query(hostname, 'DNSKEY').answer
+
+ result_container = []
+
+ ds_records_answers.each do |ds|
+ next unless ds.type == Dnsruby::Types.DNSKEY
+
+ result_container << {
+ basic: {
+ flags: ds.flags.to_s,
+ algorithm: ds.algorithm.code.to_s,
+ protocol: ds.protocol.to_s,
+ },
+ public_key: ds.public_key.export.gsub!(/\s+/, ''),
+ }
+ end
+
+ result_container
+ rescue Dnsruby::NXDomain
+ domain.add_epp_error('2308', nil, nil, I18n.t(:dns_policy_violation))
+ end
+
+ def validation_dns_key_error(domain)
+ domain.add_epp_error('2308', nil, nil, I18n.t(:dns_policy_violation))
+ end
+
+ def extensional_dnskeys_data(params)
+ dnskeys_data = params[:dns_keys]
+
+ return [] if dnskeys_data.nil?
+
+ result_container = []
+
+ dnskeys_data.each do |ds|
+ next if ds[:action] == 'rem'
+
+ result_container << {
+ basic: {
+ flags: ds[:flags].to_s,
+ algorithm: ds[:alg].to_s,
+ protocol: ds[:protocol].to_s,
+ },
+ public_key: ds[:public_key],
+ }
+ end
+
+ result_container
+ end
+end
diff --git a/test/integration/api/registrant/registrant_api_verifications_test.rb b/test/integration/api/registrant/registrant_api_verifications_test.rb
index 821d0dee0..8db49410f 100644
--- a/test/integration/api/registrant/registrant_api_verifications_test.rb
+++ b/test/integration/api/registrant/registrant_api_verifications_test.rb
@@ -15,7 +15,7 @@ class RegistrantApiVerificationsTest < ApplicationIntegrationTest
@domain.update!(statuses: [DomainStatus::PENDING_UPDATE],
registrant_verification_asked_at: Time.zone.now - 1.day,
registrant_verification_token: @token)
-
+ Spy.on_instance_method(ValidateDnssec, :validate_dnssec).and_return(true)
end
def test_fetches_registrant_change_request
diff --git a/test/integration/epp/domain/update/base_test.rb b/test/integration/epp/domain/update/base_test.rb
index d021b496d..aaa7e1767 100644
--- a/test/integration/epp/domain/update/base_test.rb
+++ b/test/integration/epp/domain/update/base_test.rb
@@ -10,6 +10,7 @@ class EppDomainUpdateBaseTest < EppTestCase
@original_registrant_change_verification =
Setting.request_confirmation_on_registrant_change_enabled
ActionMailer::Base.deliveries.clear
+ Spy.on_instance_method(ValidateDnssec, :validate_dnssec).and_return(true)
end
teardown do
diff --git a/test/integration/epp/domain/update/rem_dns_test.rb b/test/integration/epp/domain/update/rem_dns_test.rb
index 6e079b126..ecd660fa6 100644
--- a/test/integration/epp/domain/update/rem_dns_test.rb
+++ b/test/integration/epp/domain/update/rem_dns_test.rb
@@ -12,6 +12,7 @@ class EppDomainUpdateRemDnsTest < EppTestCase
@original_registrant_change_verification =
Setting.request_confirmation_on_registrant_change_enabled
ActionMailer::Base.deliveries.clear
+ Spy.on_instance_method(ValidateDnssec, :validate_dnssec).and_return(true)
end
teardown do
diff --git a/test/integration/repp/v1/domains/contacts_test.rb b/test/integration/repp/v1/domains/contacts_test.rb
index b9b26a745..540514853 100644
--- a/test/integration/repp/v1/domains/contacts_test.rb
+++ b/test/integration/repp/v1/domains/contacts_test.rb
@@ -8,6 +8,7 @@ class ReppV1DomainsContactsTest < ActionDispatch::IntegrationTest
token = "Basic #{token}"
@auth_headers = { 'Authorization' => token }
+ Spy.on_instance_method(ValidateDnssec, :validate_dnssec).and_return(true)
end
def test_shows_existing_domain_contacts
diff --git a/test/integration/repp/v1/domains/dnssec_test.rb b/test/integration/repp/v1/domains/dnssec_test.rb
index 6835e2600..79480c3b8 100644
--- a/test/integration/repp/v1/domains/dnssec_test.rb
+++ b/test/integration/repp/v1/domains/dnssec_test.rb
@@ -8,6 +8,7 @@ class ReppV1DomainsDnssecTest < ActionDispatch::IntegrationTest
token = "Basic #{token}"
@auth_headers = { 'Authorization' => token }
+ Spy.on_instance_method(ValidateDnssec, :validate_dnssec).and_return(true)
end
def test_shows_dnssec_keys_associated_with_domain
diff --git a/test/integration/repp/v1/domains/nameservers_test.rb b/test/integration/repp/v1/domains/nameservers_test.rb
index 780e889c1..4c7a1dcc5 100644
--- a/test/integration/repp/v1/domains/nameservers_test.rb
+++ b/test/integration/repp/v1/domains/nameservers_test.rb
@@ -8,6 +8,7 @@ class ReppV1DomainsNameserversTest < ActionDispatch::IntegrationTest
token = "Basic #{token}"
@auth_headers = { 'Authorization' => token }
+ Spy.on_instance_method(ValidateDnssec, :validate_dnssec).and_return(true)
end
def test_can_add_new_nameserver
diff --git a/test/integration/repp/v1/domains/update_test.rb b/test/integration/repp/v1/domains/update_test.rb
index d924fe7a3..595d094fe 100644
--- a/test/integration/repp/v1/domains/update_test.rb
+++ b/test/integration/repp/v1/domains/update_test.rb
@@ -8,6 +8,7 @@ class ReppV1DomainsUpdateTest < ActionDispatch::IntegrationTest
token = "Basic #{token}"
@auth_headers = { 'Authorization' => token }
+ Spy.on_instance_method(ValidateDnssec, :validate_dnssec).and_return(true)
end
def test_updates_transfer_code_for_domain
diff --git a/test/jobs/domain_update_confirm_job_test.rb b/test/jobs/domain_update_confirm_job_test.rb
index 158729ae3..a5999cd36 100644
--- a/test/jobs/domain_update_confirm_job_test.rb
+++ b/test/jobs/domain_update_confirm_job_test.rb
@@ -14,6 +14,7 @@ class DomainUpdateConfirmJobTest < ActiveSupport::TestCase
new_registrant_name: @new_registrant.name,
new_registrant_email: @new_registrant.email,
current_user_id: @user.id })
+ Spy.on_instance_method(ValidateDnssec, :validate_dnssec).and_return(true)
end
def teardown
From b2519b86a423eccb72d8a84a20a35a51f25a0d7d Mon Sep 17 00:00:00 2001
From: olegphenomenon
Date: Fri, 31 Dec 2021 13:34:58 +0200
Subject: [PATCH 12/33] added test for service dnssec validate object
---
test/services/validate_dnssec_test.rb | 48 +++++++++++++++++++++++++++
1 file changed, 48 insertions(+)
create mode 100644 test/services/validate_dnssec_test.rb
diff --git a/test/services/validate_dnssec_test.rb b/test/services/validate_dnssec_test.rb
new file mode 100644
index 000000000..b3e939ee4
--- /dev/null
+++ b/test/services/validate_dnssec_test.rb
@@ -0,0 +1,48 @@
+require 'test_helper'
+
+class ValidateDnssecTest < ActiveSupport::TestCase
+ setup do
+ @dnskey = dnskeys(:one)
+ @domain = domains(:shop)
+
+ @result_container = [{
+ basic: {
+ flags: @dnskey.flags.to_s,
+ algorithm: @dnskey.alg.to_s,
+ protocol: @dnskey.protocol.to_s,
+ },
+ public_key: @dnskey.public_key.to_s
+ }]
+
+ Spy.on_instance_method(ValidateDnssec, :validation_dns_key_error).and_return(false)
+ end
+
+ def test_should_return_true_if_dnssec_data_are_matches
+ Spy.on_instance_method(ValidateDnssec, :get_dnskey_records_from_subzone).and_return(@result_container)
+ match_params = build_params(@dnskey.flags)
+ validate_result = ValidateDnssec.validate_dnssec(params: match_params, domain: @domain)
+
+ assert validate_result
+ end
+
+ def test_should_return_false_if_dnssec_data_does_not_matcher
+ Spy.on_instance_method(ValidateDnssec, :get_dnskey_records_from_subzone).and_return(@result_container)
+ match_params = build_params(256)
+ validate_result = ValidateDnssec.validate_dnssec(params: match_params, domain: @domain)
+
+ refute validate_result
+ end
+
+ def build_params(flag)
+ {
+ action: "add",
+ domain: @domain,
+ dns_keys: [{
+ flags: flag,
+ alg: @dnskey.alg,
+ protocol: @dnskey.protocol,
+ public_key: @dnskey.public_key
+ }]
+ }
+ end
+end
From 8a6ea167c251b2f5183653aa5c123d8cd8e5f92d Mon Sep 17 00:00:00 2001
From: olegphenomenon
Date: Mon, 3 Jan 2022 13:52:25 +0200
Subject: [PATCH 13/33] added new field to nameserver and job
---
app/interactions/actions/domain_update.rb | 2 +-
app/jobs/validate_dnssec.rb | 25 +++++++++++++++++++
...13934_add_validation_datetime_to_dnskey.rb | 5 ++++
db/structure.sql | 1 +
4 files changed, 32 insertions(+), 1 deletion(-)
create mode 100644 app/jobs/validate_dnssec.rb
create mode 100644 db/migrate/20211231113934_add_validation_datetime_to_dnskey.rb
diff --git a/app/interactions/actions/domain_update.rb b/app/interactions/actions/domain_update.rb
index 505989c06..2e44a015c 100644
--- a/app/interactions/actions/domain_update.rb
+++ b/app/interactions/actions/domain_update.rb
@@ -14,7 +14,7 @@ module Actions
assign_new_registrant if params[:registrant]
assign_relational_modifications
assign_requested_statuses
- ValidateDnssec.validate_dnssec(params: params, domain: domain)
+ # ValidateDnssec.validate_dnssec(params: params, domain: domain)
::Actions::BaseAction.maybe_attach_legal_doc(domain, params[:legal_document])
commit
diff --git a/app/jobs/validate_dnssec.rb b/app/jobs/validate_dnssec.rb
new file mode 100644
index 000000000..286495f23
--- /dev/null
+++ b/app/jobs/validate_dnssec.rb
@@ -0,0 +1,25 @@
+class ValidateDnssecJob < ApplicationJob
+ discard_on StandardError
+
+ def perform(domain_name:)
+
+ rescue StandardError => e
+ logger.error e.message
+ raise e
+ end
+
+ private
+
+ def prepare_resolver
+ dns_servers = ENV['dnssec_resolver_ips'].to_s.split(',').map(&:strip)
+ dns = Dnsruby::Resolver.new({ nameserver: dns_servers })
+ dns.do_validation = false
+ dns.do_caching = false
+ dns.dnssec = true
+
+ dns
+ end
+
+
+
+end
diff --git a/db/migrate/20211231113934_add_validation_datetime_to_dnskey.rb b/db/migrate/20211231113934_add_validation_datetime_to_dnskey.rb
new file mode 100644
index 000000000..a0ad82332
--- /dev/null
+++ b/db/migrate/20211231113934_add_validation_datetime_to_dnskey.rb
@@ -0,0 +1,5 @@
+class AddValidationDatetimeToDnskey < ActiveRecord::Migration[6.1]
+ def change
+ add_column :dnskeys, :validation_datetime, :datetime
+ end
+end
diff --git a/db/structure.sql b/db/structure.sql
index 9afc1742f..4403facfb 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -5398,3 +5398,4 @@ INSERT INTO "schema_migrations" (version) VALUES
('20220106123143');
+
From dd59fc76e21c7b40c1afdced1f162c597335fbbc Mon Sep 17 00:00:00 2001
From: olegphenomenon
Date: Mon, 3 Jan 2022 14:58:26 +0200
Subject: [PATCH 14/33] added job
---
app/jobs/validate_dnssec.rb | 25 ---------
app/jobs/validate_dnssec_job.rb | 93 +++++++++++++++++++++++++++++++++
2 files changed, 93 insertions(+), 25 deletions(-)
delete mode 100644 app/jobs/validate_dnssec.rb
create mode 100644 app/jobs/validate_dnssec_job.rb
diff --git a/app/jobs/validate_dnssec.rb b/app/jobs/validate_dnssec.rb
deleted file mode 100644
index 286495f23..000000000
--- a/app/jobs/validate_dnssec.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-class ValidateDnssecJob < ApplicationJob
- discard_on StandardError
-
- def perform(domain_name:)
-
- rescue StandardError => e
- logger.error e.message
- raise e
- end
-
- private
-
- def prepare_resolver
- dns_servers = ENV['dnssec_resolver_ips'].to_s.split(',').map(&:strip)
- dns = Dnsruby::Resolver.new({ nameserver: dns_servers })
- dns.do_validation = false
- dns.do_caching = false
- dns.dnssec = true
-
- dns
- end
-
-
-
-end
diff --git a/app/jobs/validate_dnssec_job.rb b/app/jobs/validate_dnssec_job.rb
new file mode 100644
index 000000000..de818280f
--- /dev/null
+++ b/app/jobs/validate_dnssec_job.rb
@@ -0,0 +1,93 @@
+class ValidateDnssecJob < ApplicationJob
+ discard_on StandardError
+
+ def perform(domain_name: nil)
+ unless domain_name.nil?
+ domain = Domain.find_by(name: domain_name)
+
+ return logger.info "No domain found" if domain.nil?
+
+ return logger.info "No related dnskeys for this domain" if domain.dnskeys.empty?
+
+ flag = iterate_domain_data(domain: domain)
+ logger.info "#{domain_name} " + log_templates[flag.to_s]
+ else
+ Dnskey.all.each do |key|
+ domain = Domain.find(key.domain_id)
+
+ flag = iterate_domain_data(domain: domain)
+ logger.info "#{domain.name} " + log_templates[flag.to_s]
+ end
+ end
+ rescue StandardError => e
+ logger.error e.message
+ raise e
+ end
+
+ private
+
+ def iterate_domain_data(domain:)
+ zone_datas = get_data_from_zone(domain: domain)
+ flag = domain.dnskeys.all? { |key| validate(zone_datas: zone_datas, domain_dnskey: key) }
+
+ flag
+ end
+
+ def get_data_from_zone(domain:)
+ resolver = prepare_resolver
+ ds_records_answers = resolver.query(domain.name, 'DNSKEY').answer
+
+ result_container = []
+
+ ds_records_answers.each do |ds|
+ next unless ds.type == Dnsruby::Types.DNSKEY
+
+ result_container << {
+ flags: ds.flags.to_s,
+ algorithm: ds.algorithm.code.to_s,
+ protocol: ds.protocol.to_s,
+ public_key: ds.public_key.export.gsub!(/\s+/, ''),
+ }
+ end
+
+ result_container
+ rescue Dnsruby::NXDomain
+ domain.add_epp_error('2308', nil, nil, I18n.t(:dns_policy_violation))
+ end
+
+ def validate(zone_datas:, domain_dnskey:)
+ flag = zone_datas.any? do |zone_data|
+ zone_data[:flags] == domain_dnskey.flags.to_s &&
+ zone_data[:algorithm] == domain_dnskey.alg.to_s &&
+ zone_data[:protocol] == domain_dnskey.protocol.to_s &&
+ zone_data[:public_key].include?(domain_dnskey[:public_key].to_s)
+ end
+
+ text = "#{domain_dnskey.flags} - #{domain_dnskey.alg} -
+ #{domain_dnskey.protocol} - #{domain_dnskey.public_key} "
+ logger.info text + log_templates[flag.to_s]
+
+ flag
+ end
+
+ def prepare_resolver
+ dns_servers = ENV['dnssec_resolver_ips'].to_s.split(',').map(&:strip)
+ dns = Dnsruby::Resolver.new({ nameserver: dns_servers })
+ dns.do_validation = false
+ dns.do_caching = false
+ dns.dnssec = true
+
+ dns
+ end
+
+ def log_templates
+ {
+ "true" => "validated successfully",
+ "false" => "validated fail"
+ }
+ end
+
+ def logger
+ @logger ||= Rails.logger
+ end
+end
From d2082a30211caa34dae7d46f64573d7aaa4e1347 Mon Sep 17 00:00:00 2001
From: olegphenomenon
Date: Tue, 4 Jan 2022 11:09:24 +0200
Subject: [PATCH 15/33] downgrade ruby version
---
app/jobs/validate_dnssec_job.rb | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/app/jobs/validate_dnssec_job.rb b/app/jobs/validate_dnssec_job.rb
index de818280f..8fdfb3177 100644
--- a/app/jobs/validate_dnssec_job.rb
+++ b/app/jobs/validate_dnssec_job.rb
@@ -73,8 +73,8 @@ class ValidateDnssecJob < ApplicationJob
def prepare_resolver
dns_servers = ENV['dnssec_resolver_ips'].to_s.split(',').map(&:strip)
dns = Dnsruby::Resolver.new({ nameserver: dns_servers })
- dns.do_validation = false
- dns.do_caching = false
+ dns.do_validation = true
+ dns.do_caching = true
dns.dnssec = true
dns
From 30b7ca940d0ee72c8c01e626d32b2f5fad88edb6 Mon Sep 17 00:00:00 2001
From: olegphenomenon
Date: Tue, 4 Jan 2022 13:46:56 +0200
Subject: [PATCH 16/33] change validate logic: going through all nameserver
---
app/jobs/validate_dnssec_job.rb | 146 +++++++++++++++++++++-----------
1 file changed, 95 insertions(+), 51 deletions(-)
diff --git a/app/jobs/validate_dnssec_job.rb b/app/jobs/validate_dnssec_job.rb
index 8fdfb3177..1d3981fe1 100644
--- a/app/jobs/validate_dnssec_job.rb
+++ b/app/jobs/validate_dnssec_job.rb
@@ -7,16 +7,14 @@ class ValidateDnssecJob < ApplicationJob
return logger.info "No domain found" if domain.nil?
- return logger.info "No related dnskeys for this domain" if domain.dnskeys.empty?
+ return logger.info "No related nameservers for this domain" if domain.nameservers.empty?
- flag = iterate_domain_data(domain: domain)
- logger.info "#{domain_name} " + log_templates[flag.to_s]
+ iterate_nameservers(domain)
else
- Dnskey.all.each do |key|
- domain = Domain.find(key.domain_id)
+ domain_list = Domain.all.reject { |d| d.nameservers.empty? }
- flag = iterate_domain_data(domain: domain)
- logger.info "#{domain.name} " + log_templates[flag.to_s]
+ domain_list.each do |d|
+ iterate_nameservers(d)
end
end
rescue StandardError => e
@@ -26,58 +24,45 @@ class ValidateDnssecJob < ApplicationJob
private
- def iterate_domain_data(domain:)
- zone_datas = get_data_from_zone(domain: domain)
- flag = domain.dnskeys.all? { |key| validate(zone_datas: zone_datas, domain_dnskey: key) }
+ def iterate_nameservers(domain)
+ domain.nameservers.each do |n|
+ text = "Hostname nameserver #{n.hostname}"
+ flag = validate(name: n.hostname)
+ if flag.nil?
+ logger.info "#{text} - #{log_templates['false']}"
+ else
+ logger.info "#{text} - #{log_templates['true']}"
+ end
- flag
- end
-
- def get_data_from_zone(domain:)
- resolver = prepare_resolver
- ds_records_answers = resolver.query(domain.name, 'DNSKEY').answer
-
- result_container = []
-
- ds_records_answers.each do |ds|
- next unless ds.type == Dnsruby::Types.DNSKEY
-
- result_container << {
- flags: ds.flags.to_s,
- algorithm: ds.algorithm.code.to_s,
- protocol: ds.protocol.to_s,
- public_key: ds.public_key.export.gsub!(/\s+/, ''),
- }
+ logger.info "----------------------------"
end
-
- result_container
- rescue Dnsruby::NXDomain
- domain.add_epp_error('2308', nil, nil, I18n.t(:dns_policy_violation))
end
- def validate(zone_datas:, domain_dnskey:)
- flag = zone_datas.any? do |zone_data|
- zone_data[:flags] == domain_dnskey.flags.to_s &&
- zone_data[:algorithm] == domain_dnskey.alg.to_s &&
- zone_data[:protocol] == domain_dnskey.protocol.to_s &&
- zone_data[:public_key].include?(domain_dnskey[:public_key].to_s)
- end
-
- text = "#{domain_dnskey.flags} - #{domain_dnskey.alg} -
- #{domain_dnskey.protocol} - #{domain_dnskey.public_key} "
- logger.info text + log_templates[flag.to_s]
-
- flag
+ def validate(name:, resolver: prepare_validator, type: 'DNSKEY', klass: 'IN')
+ # make_query(name: hostname)
+ resolver.query(name, type, klass)
+ rescue Exception => e
+ logger.error e.message
+ nil
end
- def prepare_resolver
+ def prepare_validator
dns_servers = ENV['dnssec_resolver_ips'].to_s.split(',').map(&:strip)
- dns = Dnsruby::Resolver.new({ nameserver: dns_servers })
- dns.do_validation = true
- dns.do_caching = true
- dns.dnssec = true
+ inner_resolver = Dnsruby::Resolver.new
+ inner_resolver.do_validation = true
+ inner_resolver.dnssec = true
+ inner_resolver.nameserver = dns_servers
+ resolver = Dnsruby::Recursor.new(inner_resolver)
+ resolver.dnssec = true
- dns
+ resolver
+ end
+
+ def make_query(name:, resolver: prepare_validator, type: 'DNSKEY', klass: 'IN')
+ logger.info "DNS query to #{name}; type: #{type}"
+ resolver.query(name, type, klass)
+ rescue Dnsruby::NXDomain
+ false
end
def log_templates
@@ -90,4 +75,63 @@ class ValidateDnssecJob < ApplicationJob
def logger
@logger ||= Rails.logger
end
+
+
+ #
+ #
+ # def iterate_domain_data(domain:)
+ # zone_datas = get_data_from_zone(domain: domain)
+ # flag = domain.dnskeys.all? { |key| validate(zone_datas: zone_datas, domain_dnskey: key) }
+ #
+ # flag
+ # end
+ #
+ # def get_data_from_zone(domain:)
+ # resolver = prepare_resolver
+ # ds_records_answers = resolver.query(domain.name, 'DNSKEY').answer
+ #
+ # result_container = []
+ #
+ # ds_records_answers.each do |ds|
+ # next unless ds.type == Dnsruby::Types.DNSKEY
+ #
+ # result_container << {
+ # flags: ds.flags.to_s,
+ # algorithm: ds.algorithm.code.to_s,
+ # protocol: ds.protocol.to_s,
+ # public_key: ds.public_key.export.gsub!(/\s+/, ''),
+ # }
+ # end
+ #
+ # result_container
+ # rescue Dnsruby::NXDomain
+ # domain.add_epp_error('2308', nil, nil, I18n.t(:dns_policy_violation))
+ # end
+ #
+ # def validate(zone_datas:, domain_dnskey:)
+ # flag = zone_datas.any? do |zone_data|
+ # zone_data[:flags] == domain_dnskey.flags.to_s &&
+ # zone_data[:algorithm] == domain_dnskey.alg.to_s &&
+ # zone_data[:protocol] == domain_dnskey.protocol.to_s &&
+ # zone_data[:public_key].include?(domain_dnskey[:public_key].to_s)
+ # end
+ #
+ # text = "#{domain_dnskey.flags} - #{domain_dnskey.alg} -
+ # #{domain_dnskey.protocol} - #{domain_dnskey.public_key} "
+ # logger.info text + log_templates[flag.to_s]
+ #
+ # flag
+ # end
+ #
+ # def prepare_resolver
+ # dns_servers = ENV['dnssec_resolver_ips'].to_s.split(',').map(&:strip)
+ # dns = Dnsruby::Resolver.new({ nameserver: dns_servers })
+ # dns.do_validation = true
+ # dns.do_caching = true
+ # dns.dnssec = true
+ #
+ # dns
+ # end
+
+
end
From b25ef62d7827e35f9c2b768fc6314670333dee48 Mon Sep 17 00:00:00 2001
From: olegphenomenon
Date: Wed, 5 Jan 2022 12:54:18 +0200
Subject: [PATCH 17/33] updated validator job
---
app/jobs/validate_dnssec_job.rb | 144 ++++++++++++++------------------
1 file changed, 64 insertions(+), 80 deletions(-)
diff --git a/app/jobs/validate_dnssec_job.rb b/app/jobs/validate_dnssec_job.rb
index 1d3981fe1..1f418e43c 100644
--- a/app/jobs/validate_dnssec_job.rb
+++ b/app/jobs/validate_dnssec_job.rb
@@ -26,45 +26,88 @@ class ValidateDnssecJob < ApplicationJob
def iterate_nameservers(domain)
domain.nameservers.each do |n|
- text = "Hostname nameserver #{n.hostname}"
- flag = validate(name: n.hostname)
- if flag.nil?
- logger.info "#{text} - #{log_templates['false']}"
- else
- logger.info "#{text} - #{log_templates['true']}"
- end
+ validate(hostname: n.hostname, domain: domain)
logger.info "----------------------------"
end
end
- def validate(name:, resolver: prepare_validator, type: 'DNSKEY', klass: 'IN')
- # make_query(name: hostname)
- resolver.query(name, type, klass)
+ def validate(hostname:, domain:, type: 'DNSKEY', klass: 'IN')
+ resolver = prepare_validator(hostname)
+ answer = resolver.query(domain.name, type, klass)
+
+ return logger.info "no any data for #{domain.name} | hostname - #{hostname}" if answer.nil?
+
+ logger.info "-----------"
+ logger.info "data for domain name - #{domain.name} | hostname - #{hostname}"
+ logger.info "-----------"
+
+ response_container = parse_response(answer)
+ compare_dnssec_data(response_container: response_container, domain: domain)
rescue Exception => e
- logger.error e.message
+ logger.error "#{e.message} - domain name: #{domain.name} - hostname: #{hostname}"
nil
end
- def prepare_validator
- dns_servers = ENV['dnssec_resolver_ips'].to_s.split(',').map(&:strip)
+ def compare_dnssec_data(response_container:, domain:)
+ domain.dnskeys.each do |key|
+ next unless key.flags.to_s == '257'
+
+ flag = make_magic(response_container: response_container, dnskey: key)
+ text = "#{key.flags} - #{key.protocol} - #{key.alg} - #{key.public_key}"
+ if flag
+ logger.info text + " ------->> succesfully!"
+ else
+ logger.info text + " ------->> not found in zone!"
+ end
+ end
+ end
+
+ def make_magic(response_container:, dnskey:)
+ response_container.any? do |r|
+ r[:flags].to_s == dnskey.flags.to_s &&
+ r[:protocol].to_s == dnskey.protocol.to_s &&
+ r[:alg].to_s == dnskey.alg.to_s &&
+ r[:public_key] == dnskey.public_key
+ end
+ end
+
+ def parse_response(answer)
+ response_container = []
+ answer.each_answer do |a|
+ a_string = a.to_s
+ a_string = a_string.gsub /\t/, ' '
+ a_string = a_string.split(' ')
+
+ next unless a_string[4] == '257'
+
+ protocol = a.protocol
+ alg = a.algorithm.code
+
+ response_container << {
+ flags: a_string[4],
+ protocol: protocol,
+ alg: alg,
+ public_key: a_string[8]
+ }
+ end
+
+ response_container
+ end
+
+ def prepare_validator(nameserver)
inner_resolver = Dnsruby::Resolver.new
inner_resolver.do_validation = true
inner_resolver.dnssec = true
- inner_resolver.nameserver = dns_servers
+ inner_resolver.nameserver = nameserver
+ inner_resolver.packet_timeout = ENV['a_and_aaaa_validation_timeout'].to_i
+ inner_resolver.query_timeout = ENV['a_and_aaaa_validation_timeout'].to_i
resolver = Dnsruby::Recursor.new(inner_resolver)
resolver.dnssec = true
resolver
end
- def make_query(name:, resolver: prepare_validator, type: 'DNSKEY', klass: 'IN')
- logger.info "DNS query to #{name}; type: #{type}"
- resolver.query(name, type, klass)
- rescue Dnsruby::NXDomain
- false
- end
-
def log_templates
{
"true" => "validated successfully",
@@ -75,63 +118,4 @@ class ValidateDnssecJob < ApplicationJob
def logger
@logger ||= Rails.logger
end
-
-
- #
- #
- # def iterate_domain_data(domain:)
- # zone_datas = get_data_from_zone(domain: domain)
- # flag = domain.dnskeys.all? { |key| validate(zone_datas: zone_datas, domain_dnskey: key) }
- #
- # flag
- # end
- #
- # def get_data_from_zone(domain:)
- # resolver = prepare_resolver
- # ds_records_answers = resolver.query(domain.name, 'DNSKEY').answer
- #
- # result_container = []
- #
- # ds_records_answers.each do |ds|
- # next unless ds.type == Dnsruby::Types.DNSKEY
- #
- # result_container << {
- # flags: ds.flags.to_s,
- # algorithm: ds.algorithm.code.to_s,
- # protocol: ds.protocol.to_s,
- # public_key: ds.public_key.export.gsub!(/\s+/, ''),
- # }
- # end
- #
- # result_container
- # rescue Dnsruby::NXDomain
- # domain.add_epp_error('2308', nil, nil, I18n.t(:dns_policy_violation))
- # end
- #
- # def validate(zone_datas:, domain_dnskey:)
- # flag = zone_datas.any? do |zone_data|
- # zone_data[:flags] == domain_dnskey.flags.to_s &&
- # zone_data[:algorithm] == domain_dnskey.alg.to_s &&
- # zone_data[:protocol] == domain_dnskey.protocol.to_s &&
- # zone_data[:public_key].include?(domain_dnskey[:public_key].to_s)
- # end
- #
- # text = "#{domain_dnskey.flags} - #{domain_dnskey.alg} -
- # #{domain_dnskey.protocol} - #{domain_dnskey.public_key} "
- # logger.info text + log_templates[flag.to_s]
- #
- # flag
- # end
- #
- # def prepare_resolver
- # dns_servers = ENV['dnssec_resolver_ips'].to_s.split(',').map(&:strip)
- # dns = Dnsruby::Resolver.new({ nameserver: dns_servers })
- # dns.do_validation = true
- # dns.do_caching = true
- # dns.dnssec = true
- #
- # dns
- # end
-
-
end
From ca9ca115eb433d5021787b027cee0ee8607df0f1 Mon Sep 17 00:00:00 2001
From: olegphenomenon
Date: Wed, 5 Jan 2022 14:40:33 +0200
Subject: [PATCH 18/33] added notify class and mail action for inform
---
app/jobs/validate_dnssec_job.rb | 20 ++++++++++++++++++-
app/mailers/contact_inform_mailer.rb | 16 +++++++++++++++
app/services/contact_notification.rb | 17 ++++++++++++++++
.../contact_inform_mailer/notify.html.erb | 1 +
.../contact_inform_mailer/notify.text.erb | 1 +
5 files changed, 54 insertions(+), 1 deletion(-)
create mode 100644 app/mailers/contact_inform_mailer.rb
create mode 100644 app/services/contact_notification.rb
create mode 100644 app/views/mailers/contact_inform_mailer/notify.html.erb
create mode 100644 app/views/mailers/contact_inform_mailer/notify.text.erb
diff --git a/app/jobs/validate_dnssec_job.rb b/app/jobs/validate_dnssec_job.rb
index 1f418e43c..3292f505d 100644
--- a/app/jobs/validate_dnssec_job.rb
+++ b/app/jobs/validate_dnssec_job.rb
@@ -28,10 +28,23 @@ class ValidateDnssecJob < ApplicationJob
domain.nameservers.each do |n|
validate(hostname: n.hostname, domain: domain)
+ notify_contacts(domain)
logger.info "----------------------------"
end
end
+ def notify_contacts(domain)
+ flag = domain.dnskeys.any? { |k| k.validation_datetime.present? }
+
+ return if flag
+
+ text = "DNSKEYS for #{domain.name} are invalid!"
+ logger.info text
+ ContactNotification.notify_registrar(domain: domain, text: text)
+ ContactNotification.notify_tech_contact(domain: domain)
+
+ end
+
def validate(hostname:, domain:, type: 'DNSKEY', klass: 'IN')
resolver = prepare_validator(hostname)
answer = resolver.query(domain.name, type, klass)
@@ -51,16 +64,21 @@ class ValidateDnssecJob < ApplicationJob
def compare_dnssec_data(response_container:, domain:)
domain.dnskeys.each do |key|
- next unless key.flags.to_s == '257'
+ next unless key.flags.to_s == '257' || key.validation_datetime.nil?
flag = make_magic(response_container: response_container, dnskey: key)
text = "#{key.flags} - #{key.protocol} - #{key.alg} - #{key.public_key}"
if flag
+ key.validation_datetime = Time.zone.now
+ key.save
+
logger.info text + " ------->> succesfully!"
else
logger.info text + " ------->> not found in zone!"
end
end
+
+
end
def make_magic(response_container:, dnskey:)
diff --git a/app/mailers/contact_inform_mailer.rb b/app/mailers/contact_inform_mailer.rb
new file mode 100644
index 000000000..5c6f28f2c
--- /dev/null
+++ b/app/mailers/contact_inform_mailer.rb
@@ -0,0 +1,16 @@
+class ContactInformMailer < ApplicationMailer
+ helper_method :address_processing
+
+ def notify(contact:, subject:)
+ @contact = email
+ @subject = subject
+
+ mail(to: contact.email, subject: subject)
+ end
+
+ private
+
+ def address_processing
+ Contact.address_processing?
+ end
+end
diff --git a/app/services/contact_notification.rb b/app/services/contact_notification.rb
new file mode 100644
index 000000000..c5e8a7b0c
--- /dev/null
+++ b/app/services/contact_notification.rb
@@ -0,0 +1,17 @@
+module ContactNotification
+ extend self
+
+ def notify_registrar(domain:, text:)
+ domain.registrar.notifications.create(text: text)
+ end
+
+ def notify_tech_contact(domain:)
+ text = "DNSKEYS for #{domain.name} are invalid!"
+ domain.tech_domain_contacts.each do |tech|
+ contact = Contact.find(tech.id)
+
+ ContactInformMailer.notify(contact: contact, subject: text)
+ end
+ end
+
+end
diff --git a/app/views/mailers/contact_inform_mailer/notify.html.erb b/app/views/mailers/contact_inform_mailer/notify.html.erb
new file mode 100644
index 000000000..224584706
--- /dev/null
+++ b/app/views/mailers/contact_inform_mailer/notify.html.erb
@@ -0,0 +1 @@
+DNSKEYS for <%= @domain.name %> are invalid!
diff --git a/app/views/mailers/contact_inform_mailer/notify.text.erb b/app/views/mailers/contact_inform_mailer/notify.text.erb
new file mode 100644
index 000000000..224584706
--- /dev/null
+++ b/app/views/mailers/contact_inform_mailer/notify.text.erb
@@ -0,0 +1 @@
+DNSKEYS for <%= @domain.name %> are invalid!
From 374c434de42e53646bc0b873fcc0002d40cbc0b6 Mon Sep 17 00:00:00 2001
From: olegphenomenon
Date: Wed, 5 Jan 2022 14:51:18 +0200
Subject: [PATCH 19/33] added skip for succesfully validated dnskeys
---
app/jobs/validate_dnssec_job.rb | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/app/jobs/validate_dnssec_job.rb b/app/jobs/validate_dnssec_job.rb
index 3292f505d..2778b97e6 100644
--- a/app/jobs/validate_dnssec_job.rb
+++ b/app/jobs/validate_dnssec_job.rb
@@ -64,7 +64,8 @@ class ValidateDnssecJob < ApplicationJob
def compare_dnssec_data(response_container:, domain:)
domain.dnskeys.each do |key|
- next unless key.flags.to_s == '257' || key.validation_datetime.nil?
+ next unless key.flags.to_s == '257'
+ next if key.validation_datetime.present?
flag = make_magic(response_container: response_container, dnskey: key)
text = "#{key.flags} - #{key.protocol} - #{key.alg} - #{key.public_key}"
@@ -77,8 +78,6 @@ class ValidateDnssecJob < ApplicationJob
logger.info text + " ------->> not found in zone!"
end
end
-
-
end
def make_magic(response_container:, dnskey:)
From d4fd8dc0eeb98194127ba4d723531c272065aa35 Mon Sep 17 00:00:00 2001
From: olegphenomenon
Date: Wed, 5 Jan 2022 15:58:32 +0200
Subject: [PATCH 20/33] update contact notification
---
app/services/contact_notification.rb | 2 +-
test/jobs/validate_dnssec_job_test.rb | 38 +++++++++++++++++++++++++++
2 files changed, 39 insertions(+), 1 deletion(-)
create mode 100644 test/jobs/validate_dnssec_job_test.rb
diff --git a/app/services/contact_notification.rb b/app/services/contact_notification.rb
index c5e8a7b0c..6c5648f74 100644
--- a/app/services/contact_notification.rb
+++ b/app/services/contact_notification.rb
@@ -7,7 +7,7 @@ module ContactNotification
def notify_tech_contact(domain:)
text = "DNSKEYS for #{domain.name} are invalid!"
- domain.tech_domain_contacts.each do |tech|
+ domain.tech_contacts.each do |tech|
contact = Contact.find(tech.id)
ContactInformMailer.notify(contact: contact, subject: text)
diff --git a/test/jobs/validate_dnssec_job_test.rb b/test/jobs/validate_dnssec_job_test.rb
new file mode 100644
index 000000000..f5388b186
--- /dev/null
+++ b/test/jobs/validate_dnssec_job_test.rb
@@ -0,0 +1,38 @@
+$VERBOSE=nil
+require 'test_helper'
+
+class ValidateDnssecJobTest < ActiveJob::TestCase
+ setup do
+ @domain = domains(:shop)
+ @dnskey = dnskeys(:one)
+ end
+
+ # def test_job_should_return_successfully_validated_dnskeys
+ # @domain.dnskeys << @dnskey
+ # @domain.save
+ # @domain.reload
+ #
+ # mock_zone_data = [
+ # {
+ # flags: @dnskey.flags,
+ # protocol: @dnskey.protocol,
+ # alg: @dnskey.alg,
+ # public_key: @dnskey.public_key
+ # }]
+ #
+ # Spy.on_instance_method(ValidateDnssecJob, :parse_response).and_return(mock_zone_data)
+ #
+ # ValidateDnssecJob.perform_now(domain_name: @domain.name)
+ #
+ # @domain.reload
+ # p @domain.dnskeys
+ # end
+
+ # def test_job_discarded_after_error
+ # assert_no_enqueued_jobs
+ # assert_performed_jobs 1 do
+ # TestDiscardedJob.perform_later
+ # end
+ # assert_no_enqueued_jobs
+ # end
+end
From 3f0c1211da867419ffde8a5c20f7f29ad64d82ff Mon Sep 17 00:00:00 2001
From: olegphenomenon
Date: Wed, 5 Jan 2022 16:02:48 +0200
Subject: [PATCH 21/33] updated filter for domains
---
app/jobs/validate_dnssec_job.rb | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/app/jobs/validate_dnssec_job.rb b/app/jobs/validate_dnssec_job.rb
index 2778b97e6..695b17315 100644
--- a/app/jobs/validate_dnssec_job.rb
+++ b/app/jobs/validate_dnssec_job.rb
@@ -11,9 +11,15 @@ class ValidateDnssecJob < ApplicationJob
iterate_nameservers(domain)
else
- domain_list = Domain.all.reject { |d| d.nameservers.empty? }
+ domain_list = Domain.all.reject { |d| d.dnskeys.empty? }
domain_list.each do |d|
+ if d.nameservers.empty?
+ logger.info "#{d.name} has no nameserver"
+
+ next
+ end
+
iterate_nameservers(d)
end
end
From 57e653e9e69f528b1da0c10d84cd4b6d7af3d46b Mon Sep 17 00:00:00 2001
From: olegphenomenon
Date: Thu, 6 Jan 2022 13:45:15 +0200
Subject: [PATCH 22/33] added soa nameserver validator
---
app/jobs/validate_dnssec_job.rb | 4 +++
app/services/soa_nameserver_query.rb | 49 +++++++++++++++++++++++++++
test/jobs/validate_dnssec_job_test.rb | 44 +++++++++++++-----------
3 files changed, 77 insertions(+), 20 deletions(-)
create mode 100644 app/services/soa_nameserver_query.rb
diff --git a/app/jobs/validate_dnssec_job.rb b/app/jobs/validate_dnssec_job.rb
index 695b17315..9a8a049d3 100644
--- a/app/jobs/validate_dnssec_job.rb
+++ b/app/jobs/validate_dnssec_job.rb
@@ -32,6 +32,10 @@ class ValidateDnssecJob < ApplicationJob
def iterate_nameservers(domain)
domain.nameservers.each do |n|
+ result_nameserver_validation = SoaNameserverQuery.validate(domain_name: domain.name, hostname: n.hostname)
+
+ return unless result_nameserver_validation
+
validate(hostname: n.hostname, domain: domain)
notify_contacts(domain)
diff --git a/app/services/soa_nameserver_query.rb b/app/services/soa_nameserver_query.rb
new file mode 100644
index 000000000..01d6db77b
--- /dev/null
+++ b/app/services/soa_nameserver_query.rb
@@ -0,0 +1,49 @@
+module SoaNameserverQuery
+ include Dnsruby
+
+ extend self
+
+ def validate(domain_name:, hostname:)
+
+ resolver = create_resolver(hostname)
+
+ answers = resolver.query(domain_name, 'SOA', 'IN')
+ answers.answer.each do |a|
+
+ if a.serial.nil?
+ logger.info "No serial number of nameserver found"
+
+ return false
+ end
+
+ serial_number = a.serial.to_s
+
+ p "-------------- >>"
+ p "serial number #{serial_number} of #{hostname} - domain name: #{domain_name}"
+ p "<< --------------"
+ true
+ end
+
+ rescue StandardError => e
+ logger.error e.message
+ logger.error "failed #{hostname} validation of #{domain_name} domain name"
+
+ false
+ end
+
+ private
+
+ def create_resolver(nameserver)
+ resolver = Dnsruby::Resolver.new
+ resolver.retry_times = 3
+ resolver.recurse = 0 # Send out non-recursive queries
+ # disable caching otherwise SOA is cached from first nameserver queried
+ resolver.do_caching = false
+ resolver.nameserver = nameserver
+ resolver
+ end
+
+ def logger
+ @logger ||= Rails.logger
+ end
+end
diff --git a/test/jobs/validate_dnssec_job_test.rb b/test/jobs/validate_dnssec_job_test.rb
index f5388b186..d8207492c 100644
--- a/test/jobs/validate_dnssec_job_test.rb
+++ b/test/jobs/validate_dnssec_job_test.rb
@@ -7,26 +7,30 @@ class ValidateDnssecJobTest < ActiveJob::TestCase
@dnskey = dnskeys(:one)
end
- # def test_job_should_return_successfully_validated_dnskeys
- # @domain.dnskeys << @dnskey
- # @domain.save
- # @domain.reload
- #
- # mock_zone_data = [
- # {
- # flags: @dnskey.flags,
- # protocol: @dnskey.protocol,
- # alg: @dnskey.alg,
- # public_key: @dnskey.public_key
- # }]
- #
- # Spy.on_instance_method(ValidateDnssecJob, :parse_response).and_return(mock_zone_data)
- #
- # ValidateDnssecJob.perform_now(domain_name: @domain.name)
- #
- # @domain.reload
- # p @domain.dnskeys
- # end
+ def test_job_should_return_successfully_validated_dnskeys
+ # @domain.dnskeys << @dnskey
+ # @domain.save
+ # @domain.reload
+ #
+ # mock_zone_data = [
+ # {
+ # flags: @dnskey.flags,
+ # protocol: @dnskey.protocol,
+ # alg: @dnskey.alg,
+ # public_key: @dnskey.public_key
+ # }]
+ #
+ # resolver = Spy.mock(Dnsruby::Recursor)
+ # Spy.on(resolver, :query).and_return true
+ # Spy.on_instance_method(ValidateDnssecJob, :parse_response).and_return(mock_zone_data)
+ # # Spy.on_instance_method(ValidateDnssecJob, :prepare_validator).and_return(true)
+ #
+ #
+ # ValidateDnssecJob.perform_now(domain_name: @domain.name)
+ #
+ # @domain.reload
+ # p @domain.dnskeys
+ end
# def test_job_discarded_after_error
# assert_no_enqueued_jobs
From aff950aa97c05e2c53fb765ea77c4f95b6391758 Mon Sep 17 00:00:00 2001
From: olegphenomenon
Date: Sat, 8 Jan 2022 09:22:34 +0200
Subject: [PATCH 23/33] refactored job
---
app/jobs/validate_dnssec_job.rb | 9 ++-
app/services/soa_nameserver_query.rb | 49 --------------
app/services/validate_dnssec.rb | 97 ----------------------------
3 files changed, 4 insertions(+), 151 deletions(-)
delete mode 100644 app/services/soa_nameserver_query.rb
delete mode 100644 app/services/validate_dnssec.rb
diff --git a/app/jobs/validate_dnssec_job.rb b/app/jobs/validate_dnssec_job.rb
index 9a8a049d3..ad6b4b768 100644
--- a/app/jobs/validate_dnssec_job.rb
+++ b/app/jobs/validate_dnssec_job.rb
@@ -32,9 +32,7 @@ class ValidateDnssecJob < ApplicationJob
def iterate_nameservers(domain)
domain.nameservers.each do |n|
- result_nameserver_validation = SoaNameserverQuery.validate(domain_name: domain.name, hostname: n.hostname)
-
- return unless result_nameserver_validation
+ next unless n.validated?
validate(hostname: n.hostname, domain: domain)
@@ -124,11 +122,12 @@ class ValidateDnssecJob < ApplicationJob
def prepare_validator(nameserver)
inner_resolver = Dnsruby::Resolver.new
+ timeouts = ENV['nameserver_validation_timeout'] || 4
inner_resolver.do_validation = true
inner_resolver.dnssec = true
inner_resolver.nameserver = nameserver
- inner_resolver.packet_timeout = ENV['a_and_aaaa_validation_timeout'].to_i
- inner_resolver.query_timeout = ENV['a_and_aaaa_validation_timeout'].to_i
+ inner_resolver.packet_timeout = timeouts.to_i
+ inner_resolver.query_timeout = timeouts.to_i
resolver = Dnsruby::Recursor.new(inner_resolver)
resolver.dnssec = true
diff --git a/app/services/soa_nameserver_query.rb b/app/services/soa_nameserver_query.rb
deleted file mode 100644
index 01d6db77b..000000000
--- a/app/services/soa_nameserver_query.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-module SoaNameserverQuery
- include Dnsruby
-
- extend self
-
- def validate(domain_name:, hostname:)
-
- resolver = create_resolver(hostname)
-
- answers = resolver.query(domain_name, 'SOA', 'IN')
- answers.answer.each do |a|
-
- if a.serial.nil?
- logger.info "No serial number of nameserver found"
-
- return false
- end
-
- serial_number = a.serial.to_s
-
- p "-------------- >>"
- p "serial number #{serial_number} of #{hostname} - domain name: #{domain_name}"
- p "<< --------------"
- true
- end
-
- rescue StandardError => e
- logger.error e.message
- logger.error "failed #{hostname} validation of #{domain_name} domain name"
-
- false
- end
-
- private
-
- def create_resolver(nameserver)
- resolver = Dnsruby::Resolver.new
- resolver.retry_times = 3
- resolver.recurse = 0 # Send out non-recursive queries
- # disable caching otherwise SOA is cached from first nameserver queried
- resolver.do_caching = false
- resolver.nameserver = nameserver
- resolver
- end
-
- def logger
- @logger ||= Rails.logger
- end
-end
diff --git a/app/services/validate_dnssec.rb b/app/services/validate_dnssec.rb
deleted file mode 100644
index 1cc2a9422..000000000
--- a/app/services/validate_dnssec.rb
+++ /dev/null
@@ -1,97 +0,0 @@
-module ValidateDnssec
- include Dnsruby
-
- extend self
-
- def prepare_resolver
- dns_servers = ENV['dnssec_resolver_ips'].to_s.split(',').map(&:strip)
- dns = Dnsruby::Resolver.new({ nameserver: dns_servers })
- dns.do_validation = false
- dns.do_caching = false
- dns.dnssec = true
-
- dns
- end
-
- def validate_dnssec(params:, domain:)
- return if params[:action] == 'rem'
-
- dns = prepare_resolver
- subzone_records = get_dnskey_records_from_subzone(resolver: dns, hostname: params[:domain], domain: domain)
- form_extension_records = extensional_dnskeys_data(params)
-
- return true if form_extension_records.empty?
-
- validate_data(subzone_records: subzone_records, form_extension_records: form_extension_records, domain: domain)
- end
-
- def make_magic(subzone_records:, form_data:)
- subzone_records.any? do |subzone_data|
- subzone_data[:basic] == form_data[:basic] &&
- subzone_data[:public_key].include?(form_data[:public_key])
- end
- end
-
- def validate_data(subzone_records:, form_extension_records:, domain:)
- flag = false
- form_extension_records.each do |form_data|
- flag = make_magic(subzone_records: subzone_records, form_data: form_data)
-
- break if flag
- end
-
- return validation_dns_key_error(domain) unless flag
-
- flag
- end
-
- def get_dnskey_records_from_subzone(resolver:, hostname:, domain:)
- ds_records_answers = resolver.query(hostname, 'DNSKEY').answer
-
- result_container = []
-
- ds_records_answers.each do |ds|
- next unless ds.type == Dnsruby::Types.DNSKEY
-
- result_container << {
- basic: {
- flags: ds.flags.to_s,
- algorithm: ds.algorithm.code.to_s,
- protocol: ds.protocol.to_s,
- },
- public_key: ds.public_key.export.gsub!(/\s+/, ''),
- }
- end
-
- result_container
- rescue Dnsruby::NXDomain
- domain.add_epp_error('2308', nil, nil, I18n.t(:dns_policy_violation))
- end
-
- def validation_dns_key_error(domain)
- domain.add_epp_error('2308', nil, nil, I18n.t(:dns_policy_violation))
- end
-
- def extensional_dnskeys_data(params)
- dnskeys_data = params[:dns_keys]
-
- return [] if dnskeys_data.nil?
-
- result_container = []
-
- dnskeys_data.each do |ds|
- next if ds[:action] == 'rem'
-
- result_container << {
- basic: {
- flags: ds[:flags].to_s,
- algorithm: ds[:alg].to_s,
- protocol: ds[:protocol].to_s,
- },
- public_key: ds[:public_key],
- }
- end
-
- result_container
- end
-end
From 053382ffa35189be45fec4bcea0886c0a6313688 Mon Sep 17 00:00:00 2001
From: olegphenomenon
Date: Mon, 10 Jan 2022 09:39:14 +0200
Subject: [PATCH 24/33] updated tests
---
app/interactions/actions/domain_update.rb | 1 -
.../registrant_api_verifications_test.rb | 1 -
.../epp/domain/update/base_test.rb | 1 -
.../epp/domain/update/rem_dns_test.rb | 1 -
.../repp/v1/domains/contacts_test.rb | 1 -
.../repp/v1/domains/dnssec_test.rb | 1 -
.../repp/v1/domains/nameservers_test.rb | 1 -
.../repp/v1/domains/update_test.rb | 1 -
test/jobs/domain_update_confirm_job_test.rb | 1 -
test/services/validate_dnssec_test.rb | 48 -------------------
10 files changed, 57 deletions(-)
delete mode 100644 test/services/validate_dnssec_test.rb
diff --git a/app/interactions/actions/domain_update.rb b/app/interactions/actions/domain_update.rb
index 2e44a015c..40b7876f6 100644
--- a/app/interactions/actions/domain_update.rb
+++ b/app/interactions/actions/domain_update.rb
@@ -14,7 +14,6 @@ module Actions
assign_new_registrant if params[:registrant]
assign_relational_modifications
assign_requested_statuses
- # ValidateDnssec.validate_dnssec(params: params, domain: domain)
::Actions::BaseAction.maybe_attach_legal_doc(domain, params[:legal_document])
commit
diff --git a/test/integration/api/registrant/registrant_api_verifications_test.rb b/test/integration/api/registrant/registrant_api_verifications_test.rb
index 8db49410f..612006eb9 100644
--- a/test/integration/api/registrant/registrant_api_verifications_test.rb
+++ b/test/integration/api/registrant/registrant_api_verifications_test.rb
@@ -15,7 +15,6 @@ class RegistrantApiVerificationsTest < ApplicationIntegrationTest
@domain.update!(statuses: [DomainStatus::PENDING_UPDATE],
registrant_verification_asked_at: Time.zone.now - 1.day,
registrant_verification_token: @token)
- Spy.on_instance_method(ValidateDnssec, :validate_dnssec).and_return(true)
end
def test_fetches_registrant_change_request
diff --git a/test/integration/epp/domain/update/base_test.rb b/test/integration/epp/domain/update/base_test.rb
index aaa7e1767..d021b496d 100644
--- a/test/integration/epp/domain/update/base_test.rb
+++ b/test/integration/epp/domain/update/base_test.rb
@@ -10,7 +10,6 @@ class EppDomainUpdateBaseTest < EppTestCase
@original_registrant_change_verification =
Setting.request_confirmation_on_registrant_change_enabled
ActionMailer::Base.deliveries.clear
- Spy.on_instance_method(ValidateDnssec, :validate_dnssec).and_return(true)
end
teardown do
diff --git a/test/integration/epp/domain/update/rem_dns_test.rb b/test/integration/epp/domain/update/rem_dns_test.rb
index ecd660fa6..6e079b126 100644
--- a/test/integration/epp/domain/update/rem_dns_test.rb
+++ b/test/integration/epp/domain/update/rem_dns_test.rb
@@ -12,7 +12,6 @@ class EppDomainUpdateRemDnsTest < EppTestCase
@original_registrant_change_verification =
Setting.request_confirmation_on_registrant_change_enabled
ActionMailer::Base.deliveries.clear
- Spy.on_instance_method(ValidateDnssec, :validate_dnssec).and_return(true)
end
teardown do
diff --git a/test/integration/repp/v1/domains/contacts_test.rb b/test/integration/repp/v1/domains/contacts_test.rb
index 540514853..b9b26a745 100644
--- a/test/integration/repp/v1/domains/contacts_test.rb
+++ b/test/integration/repp/v1/domains/contacts_test.rb
@@ -8,7 +8,6 @@ class ReppV1DomainsContactsTest < ActionDispatch::IntegrationTest
token = "Basic #{token}"
@auth_headers = { 'Authorization' => token }
- Spy.on_instance_method(ValidateDnssec, :validate_dnssec).and_return(true)
end
def test_shows_existing_domain_contacts
diff --git a/test/integration/repp/v1/domains/dnssec_test.rb b/test/integration/repp/v1/domains/dnssec_test.rb
index 79480c3b8..6835e2600 100644
--- a/test/integration/repp/v1/domains/dnssec_test.rb
+++ b/test/integration/repp/v1/domains/dnssec_test.rb
@@ -8,7 +8,6 @@ class ReppV1DomainsDnssecTest < ActionDispatch::IntegrationTest
token = "Basic #{token}"
@auth_headers = { 'Authorization' => token }
- Spy.on_instance_method(ValidateDnssec, :validate_dnssec).and_return(true)
end
def test_shows_dnssec_keys_associated_with_domain
diff --git a/test/integration/repp/v1/domains/nameservers_test.rb b/test/integration/repp/v1/domains/nameservers_test.rb
index 4c7a1dcc5..780e889c1 100644
--- a/test/integration/repp/v1/domains/nameservers_test.rb
+++ b/test/integration/repp/v1/domains/nameservers_test.rb
@@ -8,7 +8,6 @@ class ReppV1DomainsNameserversTest < ActionDispatch::IntegrationTest
token = "Basic #{token}"
@auth_headers = { 'Authorization' => token }
- Spy.on_instance_method(ValidateDnssec, :validate_dnssec).and_return(true)
end
def test_can_add_new_nameserver
diff --git a/test/integration/repp/v1/domains/update_test.rb b/test/integration/repp/v1/domains/update_test.rb
index 595d094fe..d924fe7a3 100644
--- a/test/integration/repp/v1/domains/update_test.rb
+++ b/test/integration/repp/v1/domains/update_test.rb
@@ -8,7 +8,6 @@ class ReppV1DomainsUpdateTest < ActionDispatch::IntegrationTest
token = "Basic #{token}"
@auth_headers = { 'Authorization' => token }
- Spy.on_instance_method(ValidateDnssec, :validate_dnssec).and_return(true)
end
def test_updates_transfer_code_for_domain
diff --git a/test/jobs/domain_update_confirm_job_test.rb b/test/jobs/domain_update_confirm_job_test.rb
index a5999cd36..158729ae3 100644
--- a/test/jobs/domain_update_confirm_job_test.rb
+++ b/test/jobs/domain_update_confirm_job_test.rb
@@ -14,7 +14,6 @@ class DomainUpdateConfirmJobTest < ActiveSupport::TestCase
new_registrant_name: @new_registrant.name,
new_registrant_email: @new_registrant.email,
current_user_id: @user.id })
- Spy.on_instance_method(ValidateDnssec, :validate_dnssec).and_return(true)
end
def teardown
diff --git a/test/services/validate_dnssec_test.rb b/test/services/validate_dnssec_test.rb
deleted file mode 100644
index b3e939ee4..000000000
--- a/test/services/validate_dnssec_test.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-require 'test_helper'
-
-class ValidateDnssecTest < ActiveSupport::TestCase
- setup do
- @dnskey = dnskeys(:one)
- @domain = domains(:shop)
-
- @result_container = [{
- basic: {
- flags: @dnskey.flags.to_s,
- algorithm: @dnskey.alg.to_s,
- protocol: @dnskey.protocol.to_s,
- },
- public_key: @dnskey.public_key.to_s
- }]
-
- Spy.on_instance_method(ValidateDnssec, :validation_dns_key_error).and_return(false)
- end
-
- def test_should_return_true_if_dnssec_data_are_matches
- Spy.on_instance_method(ValidateDnssec, :get_dnskey_records_from_subzone).and_return(@result_container)
- match_params = build_params(@dnskey.flags)
- validate_result = ValidateDnssec.validate_dnssec(params: match_params, domain: @domain)
-
- assert validate_result
- end
-
- def test_should_return_false_if_dnssec_data_does_not_matcher
- Spy.on_instance_method(ValidateDnssec, :get_dnskey_records_from_subzone).and_return(@result_container)
- match_params = build_params(256)
- validate_result = ValidateDnssec.validate_dnssec(params: match_params, domain: @domain)
-
- refute validate_result
- end
-
- def build_params(flag)
- {
- action: "add",
- domain: @domain,
- dns_keys: [{
- flags: flag,
- alg: @dnskey.alg,
- protocol: @dnskey.protocol,
- public_key: @dnskey.public_key
- }]
- }
- end
-end
From 35f60e53e59e2ceafd26269e050d5c18cd7efb39 Mon Sep 17 00:00:00 2001
From: olegphenomenon
Date: Mon, 10 Jan 2022 12:05:32 +0200
Subject: [PATCH 25/33] improve notification feature
---
app/jobs/nameserver_record_validation_job.rb | 16 +++++++-------
app/jobs/validate_dnssec_job.rb | 3 +--
app/mailers/contact_inform_mailer.rb | 5 +++--
app/services/contact_notification.rb | 7 +++----
test/services/contact_notification_test.rb | 22 ++++++++++++++++++++
5 files changed, 37 insertions(+), 16 deletions(-)
create mode 100644 test/services/contact_notification_test.rb
diff --git a/app/jobs/nameserver_record_validation_job.rb b/app/jobs/nameserver_record_validation_job.rb
index a1787e9d7..5a32ce133 100644
--- a/app/jobs/nameserver_record_validation_job.rb
+++ b/app/jobs/nameserver_record_validation_job.rb
@@ -95,27 +95,27 @@ class NameserverRecordValidationJob < ApplicationJob
end
logger.info text
- failed_log(text: text, nameserver: nameserver)
+ failed_log(text: text, nameserver: nameserver, domain: domain)
add_nameserver_to_failed(nameserver: nameserver, reason: text)
false
end
- def failed_log(text:, nameserver:)
- inform_to_tech_contact(text)
+ def failed_log(text:, nameserver:, domain:)
+ inform_to_tech_contact(domain: domain, text: text)
inform_to_registrar(text: text, nameserver: nameserver)
false
end
- def inform_to_tech_contact(text)
- "NEED TO DO!"
- text
+ def inform_to_tech_contact(domain:, text:)
+ ContactNotification.notify_tech_contact(domain: domain, text: text)
end
def inform_to_registrar(text:, nameserver:)
- # nameserver.domain.registrar.notifications.create!(text: text)
- "NEED TO DO!"
+ # text = "DNSKEYS for #{domain.name} are invalid!"
+ logger.info text
+ ContactNotification.notify_registrar(domain: nameserver.domain, text: text)
end
def logger
diff --git a/app/jobs/validate_dnssec_job.rb b/app/jobs/validate_dnssec_job.rb
index ad6b4b768..54f7818c5 100644
--- a/app/jobs/validate_dnssec_job.rb
+++ b/app/jobs/validate_dnssec_job.rb
@@ -49,8 +49,7 @@ class ValidateDnssecJob < ApplicationJob
text = "DNSKEYS for #{domain.name} are invalid!"
logger.info text
ContactNotification.notify_registrar(domain: domain, text: text)
- ContactNotification.notify_tech_contact(domain: domain)
-
+ ContactNotification.notify_tech_contact(domain: domain, text: text)
end
def validate(hostname:, domain:, type: 'DNSKEY', klass: 'IN')
diff --git a/app/mailers/contact_inform_mailer.rb b/app/mailers/contact_inform_mailer.rb
index 5c6f28f2c..00834a8ae 100644
--- a/app/mailers/contact_inform_mailer.rb
+++ b/app/mailers/contact_inform_mailer.rb
@@ -1,9 +1,10 @@
class ContactInformMailer < ApplicationMailer
helper_method :address_processing
- def notify(contact:, subject:)
- @contact = email
+ def notify(contact:, domain:, subject:)
+ @contact = contact
@subject = subject
+ @domain = domain
mail(to: contact.email, subject: subject)
end
diff --git a/app/services/contact_notification.rb b/app/services/contact_notification.rb
index 6c5648f74..d14526fea 100644
--- a/app/services/contact_notification.rb
+++ b/app/services/contact_notification.rb
@@ -5,13 +5,12 @@ module ContactNotification
domain.registrar.notifications.create(text: text)
end
- def notify_tech_contact(domain:)
- text = "DNSKEYS for #{domain.name} are invalid!"
+ def notify_tech_contact(domain:, text:)
+ # text = "DNSKEYS for #{domain.name} are invalid!"
domain.tech_contacts.each do |tech|
contact = Contact.find(tech.id)
- ContactInformMailer.notify(contact: contact, subject: text)
+ ContactInformMailer.notify(contact: contact, domain: domain, subject: text).deliver_now
end
end
-
end
diff --git a/test/services/contact_notification_test.rb b/test/services/contact_notification_test.rb
new file mode 100644
index 000000000..317cbb470
--- /dev/null
+++ b/test/services/contact_notification_test.rb
@@ -0,0 +1,22 @@
+require 'test_helper'
+
+class ContactNotificationTest < ActionMailer::TestCase
+
+ setup do
+ @domain = domains(:shop)
+ @text = 'text'
+ end
+
+ def test_notify_registrar
+ assert_difference -> { @domain.registrar.notifications.count } do
+ ContactNotification.notify_registrar(domain: @domain, text: @text)
+ end
+ end
+
+ def test_notify_tech_contacts
+ ContactNotification.notify_tech_contact(domain: @domain, text: @text)
+ assert_equal @domain.tech_contacts.count, 2
+ assert_emails 2
+ end
+end
+
From 09ba0a25113f6f6541e8b820862a2ea649bcc231 Mon Sep 17 00:00:00 2001
From: olegphenomenon
Date: Wed, 12 Jan 2022 12:24:44 +0200
Subject: [PATCH 26/33] update mail templates
---
app/jobs/nameserver_record_validation_job.rb | 8 ++--
app/jobs/validate_dnssec_job.rb | 4 +-
app/mailers/contact_inform_mailer.rb | 13 +++++-
app/services/contact_notification.rb | 18 +++++---
.../contact_inform_mailer/notify.html.erb | 1 -
.../contact_inform_mailer/notify.text.erb | 1 -
.../notify_dnssec.html.erb | 40 +++++++++++++++++
.../notify_dnssec.text.erb | 29 +++++++++++++
.../notify_nameserver.html.erb | 43 +++++++++++++++++++
.../notify_nameserver.text.erb | 29 +++++++++++++
10 files changed, 171 insertions(+), 15 deletions(-)
delete mode 100644 app/views/mailers/contact_inform_mailer/notify.html.erb
delete mode 100644 app/views/mailers/contact_inform_mailer/notify.text.erb
create mode 100644 app/views/mailers/contact_inform_mailer/notify_dnssec.html.erb
create mode 100644 app/views/mailers/contact_inform_mailer/notify_dnssec.text.erb
create mode 100644 app/views/mailers/contact_inform_mailer/notify_nameserver.html.erb
create mode 100644 app/views/mailers/contact_inform_mailer/notify_nameserver.text.erb
diff --git a/app/jobs/nameserver_record_validation_job.rb b/app/jobs/nameserver_record_validation_job.rb
index 5a32ce133..d4c9b194d 100644
--- a/app/jobs/nameserver_record_validation_job.rb
+++ b/app/jobs/nameserver_record_validation_job.rb
@@ -108,12 +108,12 @@ class NameserverRecordValidationJob < ApplicationJob
false
end
- def inform_to_tech_contact(domain:, text:)
- ContactNotification.notify_tech_contact(domain: domain, text: text)
+ def inform_to_tech_contact(domain:, text: nil)
+ ContactNotification.notify_tech_contact(domain: domain, reason: 'nameserver')
end
- def inform_to_registrar(text:, nameserver:)
- # text = "DNSKEYS for #{domain.name} are invalid!"
+ def inform_to_registrar(nameserver:, text: nil)
+ text = "Host record #{nameserver.hostname} of a domain #{nameserver.domain} is invalid. Please fix or contact the registrant."
logger.info text
ContactNotification.notify_registrar(domain: nameserver.domain, text: text)
end
diff --git a/app/jobs/validate_dnssec_job.rb b/app/jobs/validate_dnssec_job.rb
index 54f7818c5..3277914f1 100644
--- a/app/jobs/validate_dnssec_job.rb
+++ b/app/jobs/validate_dnssec_job.rb
@@ -46,10 +46,10 @@ class ValidateDnssecJob < ApplicationJob
return if flag
- text = "DNSKEYS for #{domain.name} are invalid!"
+ text = "DNSKEY record of a domain #{domain.name} is invalid. Please fix or contact the registrant."
logger.info text
ContactNotification.notify_registrar(domain: domain, text: text)
- ContactNotification.notify_tech_contact(domain: domain, text: text)
+ ContactNotification.notify_tech_contact(domain: domain, reason: 'dnssec')
end
def validate(hostname:, domain:, type: 'DNSKEY', klass: 'IN')
diff --git a/app/mailers/contact_inform_mailer.rb b/app/mailers/contact_inform_mailer.rb
index 00834a8ae..7423da791 100644
--- a/app/mailers/contact_inform_mailer.rb
+++ b/app/mailers/contact_inform_mailer.rb
@@ -1,11 +1,20 @@
class ContactInformMailer < ApplicationMailer
helper_method :address_processing
- def notify(contact:, domain:, subject:)
+ def notify_dnssec(contact:, domain:)
@contact = contact
- @subject = subject
@domain = domain
+ subject = "Domeeni #{@domain.name} DNSSEC kirjed ei ole korrektsed / The DNSKEY records of the domain #{@domain.name} are invalid"
+
+ mail(to: contact.email, subject: subject)
+ end
+
+ def notify_nameserver(contact:, domain:)
+ @contact = contact
+ @domain = domain
+
+ subject = "Domeeni #{@domain.name} nimeserveri kirjed ei ole korrektsed / The host records of the domain #{@domain.name} are invalid"
mail(to: contact.email, subject: subject)
end
diff --git a/app/services/contact_notification.rb b/app/services/contact_notification.rb
index d14526fea..16765d65d 100644
--- a/app/services/contact_notification.rb
+++ b/app/services/contact_notification.rb
@@ -5,12 +5,20 @@ module ContactNotification
domain.registrar.notifications.create(text: text)
end
- def notify_tech_contact(domain:, text:)
- # text = "DNSKEYS for #{domain.name} are invalid!"
- domain.tech_contacts.each do |tech|
- contact = Contact.find(tech.id)
+ def notify_tech_contact(domain:, reason: nil)
+ case reason
+ when 'dnssec'
+ domain.tech_contacts.each do |tech|
+ contact = Contact.find(tech.id)
- ContactInformMailer.notify(contact: contact, domain: domain, subject: text).deliver_now
+ ContactInformMailer.notify_dnssec(contact: contact, domain: domain).deliver_now
+ end
+ when 'nameserver'
+ domain.tech_contacts.each do |tech|
+ contact = Contact.find(tech.id)
+
+ ContactInformMailer.notify_nameserver(contact: contact, domain: domain).deliver_now
+ end
end
end
end
diff --git a/app/views/mailers/contact_inform_mailer/notify.html.erb b/app/views/mailers/contact_inform_mailer/notify.html.erb
deleted file mode 100644
index 224584706..000000000
--- a/app/views/mailers/contact_inform_mailer/notify.html.erb
+++ /dev/null
@@ -1 +0,0 @@
-DNSKEYS for <%= @domain.name %> are invalid!
diff --git a/app/views/mailers/contact_inform_mailer/notify.text.erb b/app/views/mailers/contact_inform_mailer/notify.text.erb
deleted file mode 100644
index 224584706..000000000
--- a/app/views/mailers/contact_inform_mailer/notify.text.erb
+++ /dev/null
@@ -1 +0,0 @@
-DNSKEYS for <%= @domain.name %> are invalid!
diff --git a/app/views/mailers/contact_inform_mailer/notify_dnssec.html.erb b/app/views/mailers/contact_inform_mailer/notify_dnssec.html.erb
new file mode 100644
index 000000000..4b506b9e8
--- /dev/null
+++ b/app/views/mailers/contact_inform_mailer/notify_dnssec.html.erb
@@ -0,0 +1,40 @@
+Lugupeetud domeeni <%= @domain.name %> tehniline kontakt,
+
+
+Eesti Interneti Sihtasutusele (EIS) juhib tähelepanu, et domeeni <%= @domain.name %> DNSKEY kirjed on puudulikud ning domeeniga seotud teenuse ei pruugi korrektselt toimida.
+
+
+Andmete parandamiseks vaadake palun üle domeeni nimeserverite seaditused või pöörduge palun oma registripidaja <%= @domain.registrar.name %> või nimeserveri teenuse pakkuja poole.
+
+
+Lisaküsimuste korral võtke palun ühendust oma registripidajaga:
+
+<%= @domain.registrar.name %>
+Email: <%= @domain.registrar.email %>
+Telefon:<%= @domain.registrar.phone %>
+Veebileht:<%= @domain.registrar.website %>
+
+Lugupidamisega
+Eesti Interneti Sihtasutus
+
+---
+
+
+Dear technical contact of <%= @domain.name %> domain,
+
+
+Estonian Internet Foundation points out that the DNSKEY record(s) for the domain <%= @domain.name %> are invalid and the service related to the domain may not work correctly.
+
+
+Please check the DNSKEY records of the domain or contact your registrar <%= @domain.registrar.name%> or your name server service provider to correct this information.
+
+
+Should you have additional questions, please contact your registrar:
+
+<%= @domain.registrar.name %>
+Email: <%= @domain.registrar.email %>
+Phone: <%= @domain.registrar.phone %>
+Website: <%= @domain.registrar.website %>
+
+Best Regards,
+Estonian Internet Foundation
diff --git a/app/views/mailers/contact_inform_mailer/notify_dnssec.text.erb b/app/views/mailers/contact_inform_mailer/notify_dnssec.text.erb
new file mode 100644
index 000000000..09b243854
--- /dev/null
+++ b/app/views/mailers/contact_inform_mailer/notify_dnssec.text.erb
@@ -0,0 +1,29 @@
+Lugupeetud domeeni <%= @domain.name %> tehniline kontakt,
+
+Eesti Interneti Sihtasutusele (EIS) juhib tähelepanu, et domeeni <%= @domain.name %> DNSKEY kirjed on puudulikud ning domeeniga seotud teenuse ei pruugi korrektselt toimida.
+Andmete parandamiseks vaadake palun üle domeeni nimeserverite seaditused või pöörduge palun oma registripidaja <%= @domain.registrar.name %> või nimeserveri teenuse pakkuja poole.
+
+Lisaküsimuste korral võtke palun ühendust oma registripidajaga:
+<%= @domain.registrar.name%>
+Email: <%= @domain.registrar.email %>
+Telefon: <%= @domain.registrar.phone %>
+Veebileht: <%= @domain.registrar.website %>
+
+Lugupidamisega
+Eesti Interneti Sihtasutus
+
+---
+
+Dear technical contact of <%= @domain.name %> domain,
+
+Estonian Internet Foundation points out that the DNSKEY record(s) for the domain <%= @domain.name %> are invalid and the service related to the domain may not work correctly.
+Please check the DNSKEY records of the domain or contact your registrar <%= @domain.registrar.name%> or your name server service provider to correct this information.
+
+Should you have additional questions, please contact your registrar:
+<%= @domain.registrar.name%>
+Email: <%= @domain.registrar.email %>
+Phone: <%= @domain.registrar.phone %>
+Website: <%= @domain.registrar.website %>
+
+Best Regards,
+Estonian Internet Foundation
diff --git a/app/views/mailers/contact_inform_mailer/notify_nameserver.html.erb b/app/views/mailers/contact_inform_mailer/notify_nameserver.html.erb
new file mode 100644
index 000000000..ce6b968a0
--- /dev/null
+++ b/app/views/mailers/contact_inform_mailer/notify_nameserver.html.erb
@@ -0,0 +1,43 @@
+Lugupeetud domeeni <%= @domain.name %> tehniline kontakt
+
+
+Eesti Interneti Sihtasutusele (EIS) juhib tähelepanu, et domeeni <%= @domain.name %> nimeserverite seaded on puudulikud ning domeeniga seotud teenuse ei pruugi korrektselt toimida.
+
+Andmete parandamiseks vaadake palun üle domeeni nimeserverite seaditused või pöörduge palun oma registripidaja <%= @domain.registrar.name%> või nimeserveri teenuse pakkuja poole.
+
+
+
+Lisaküsimuste korral võtke palun ühendust oma registripidajaga:
+
+
+<%= @domain.registrar.name %>
+Email: <%= @domain.registrar.email %>
+Telefon: <%= @domain.registrar.phone %>
+Veebileht: <%= @domain.registrar.website %>
+
+Lugupidamisega
+Eesti Interneti Sihtasutus
+
+---
+
+
+Dear technical contact of <%= @domain.name %> domain,
+
+
+ Estonian Internet Foundation points out that the settings for the name servers of the domain <%= @domain.name %> are incomplete and the service related to the domain may not work correctly.
+
+
+Please check the name server settings of the domain or contact your registrar <%= @domain.registrar.name%> or your name server service provider to correct this information.
+
+
+
+Should you have additional questions, please contact your registrar:
+
+
+<%= @domain.registrar.name%>
+Email: <%= @domain.registrar.email %>
+Phone: <%= @domain.registrar.phone %>
+Website: <%= @domain.registrar.website %>
+
+Best Regards,
+Estonian Internet Foundation
diff --git a/app/views/mailers/contact_inform_mailer/notify_nameserver.text.erb b/app/views/mailers/contact_inform_mailer/notify_nameserver.text.erb
new file mode 100644
index 000000000..3a6734402
--- /dev/null
+++ b/app/views/mailers/contact_inform_mailer/notify_nameserver.text.erb
@@ -0,0 +1,29 @@
+Lugupeetud domeeni <%= @domain.name %> tehniline kontakt
+
+Eesti Interneti Sihtasutusele (EIS) juhib tähelepanu, et domeeni <%= @domain.name %> nimeserverite seaded on puudulikud ning domeeniga seotud teenuse ei pruugi korrektselt toimida.
+Andmete parandamiseks vaadake palun üle domeeni nimeserverite seaditused või pöörduge palun oma registripidaja <%= @domain.registrar.name%> või nimeserveri teenuse pakkuja poole.
+
+Lisaküsimuste korral võtke palun ühendust oma registripidajaga:
+<%= @domain.registrar.name%>
+Email: <%= @domain.registrar.email %>
+Telefon: <%= @domain.registrar.phone %>
+Veebileht: <%= @domain.registrar.website %>
+
+Lugupidamisega
+Eesti Interneti Sihtasutus
+
+---
+
+Dear technical contact of <%= @domain.name %> domain,
+
+Estonian Internet Foundation points out that the settings for the name servers of the domain <%= @domain.name %> are incomplete and the service related to the domain may not work correctly.
+Please check the name server settings of the domain or contact your registrar <%= @domain.registrar.name%> or your name server service provider to correct this information.
+
+Should you have additional questions, please contact your registrar:
+<%= @domain.registrar.name%>
+Email: <%= @domain.registrar.email %>
+Phone: <%= @domain.registrar.phone %>
+Website: <%= @domain.registrar.website %>
+
+Best Regards,
+Estonian Internet Foundation
From 635e7b9c4fc36b9f17c3b55e5877afc555f1df67 Mon Sep 17 00:00:00 2001
From: olegphenomenon
Date: Wed, 12 Jan 2022 12:53:45 +0200
Subject: [PATCH 27/33] added schedule for running job
---
config/schedule.rb | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/config/schedule.rb b/config/schedule.rb
index 0106cc97d..cffe61d37 100644
--- a/config/schedule.rb
+++ b/config/schedule.rb
@@ -66,6 +66,10 @@ if @cron_group == 'registry'
rake 'verify_email:all_domains'
end
+ every 5.minutes do
+ runner 'NameserverRecordValidationJob.perform_now'
+ end
+
# Should be at least once every 4 days, since according to LHV specs:
# "Unread messages older than 5 days are automatically scheduled for deletion"
# https://partners.lhv.ee/en/connect/#messaging
From fff7bcb1cff04330e38ee7c4f49eeb1a4207931a Mon Sep 17 00:00:00 2001
From: olegphenomenon
Date: Wed, 12 Jan 2022 13:11:10 +0200
Subject: [PATCH 28/33] updated tests
---
config/schedule.rb | 4 ----
test/services/contact_notification_test.rb | 10 ++++++++--
2 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/config/schedule.rb b/config/schedule.rb
index cffe61d37..0106cc97d 100644
--- a/config/schedule.rb
+++ b/config/schedule.rb
@@ -66,10 +66,6 @@ if @cron_group == 'registry'
rake 'verify_email:all_domains'
end
- every 5.minutes do
- runner 'NameserverRecordValidationJob.perform_now'
- end
-
# Should be at least once every 4 days, since according to LHV specs:
# "Unread messages older than 5 days are automatically scheduled for deletion"
# https://partners.lhv.ee/en/connect/#messaging
diff --git a/test/services/contact_notification_test.rb b/test/services/contact_notification_test.rb
index 317cbb470..0e75fb548 100644
--- a/test/services/contact_notification_test.rb
+++ b/test/services/contact_notification_test.rb
@@ -13,8 +13,14 @@ class ContactNotificationTest < ActionMailer::TestCase
end
end
- def test_notify_tech_contacts
- ContactNotification.notify_tech_contact(domain: @domain, text: @text)
+ def test_notify_tech_contacts_that_nameserver_is_broken
+ ContactNotification.notify_tech_contact(domain: @domain, reason: 'nameserver')
+ assert_equal @domain.tech_contacts.count, 2
+ assert_emails 2
+ end
+
+ def test_notify_tech_contacts_that_dnssec_is_broken
+ ContactNotification.notify_tech_contact(domain: @domain, reason: 'dnssec')
assert_equal @domain.tech_contacts.count, 2
assert_emails 2
end
From f6b352a087068ef2dcc4f9233a34c26c739668a4 Mon Sep 17 00:00:00 2001
From: olegphenomenon
Date: Wed, 12 Jan 2022 13:40:01 +0200
Subject: [PATCH 29/33] updated nameserver letter
---
app/jobs/nameserver_record_validation_job.rb | 17 +++++++++--------
app/jobs/validate_dnssec_job.rb | 7 -------
app/mailers/contact_inform_mailer.rb | 3 ++-
app/models/nameserver.rb | 2 +-
app/services/contact_notification.rb | 4 ++--
.../notify_nameserver.html.erb | 4 ++++
.../nameserver_record_validation_job_test.rb | 2 +-
test/services/contact_notification_test.rb | 3 ++-
8 files changed, 21 insertions(+), 21 deletions(-)
diff --git a/app/jobs/nameserver_record_validation_job.rb b/app/jobs/nameserver_record_validation_job.rb
index d4c9b194d..9271d94d7 100644
--- a/app/jobs/nameserver_record_validation_job.rb
+++ b/app/jobs/nameserver_record_validation_job.rb
@@ -12,7 +12,7 @@ class NameserverRecordValidationJob < ApplicationJob
domains.each do |domain|
domain.nameservers.each do |nameserver|
- next if nameserver.nameserver_failed_validation? || nameserver.validated?
+ next if nameserver.failed_validation? || nameserver.validated?
result = NameserverValidator.run(domain_name: domain.name, nameserver: nameserver)
@@ -38,7 +38,7 @@ class NameserverRecordValidationJob < ApplicationJob
return logger.info 'Domain not has nameservers' if domain.nameservers.empty?
domain.nameservers.each do |nameserver|
- next if nameserver.nameserver_failed_validation?
+ next if nameserver.failed_validation?
result = NameserverValidator.run(domain_name: domain.name, nameserver: nameserver)
@@ -73,6 +73,8 @@ class NameserverRecordValidationJob < ApplicationJob
nameserver.failed_validation_reason = reason
nameserver.save
+
+ failed_log(text: reason, nameserver: nameserver, domain: nameserver.domain) if nameserver.failed_validation?
end
def parse_result(result, nameserver)
@@ -95,25 +97,24 @@ class NameserverRecordValidationJob < ApplicationJob
end
logger.info text
- failed_log(text: text, nameserver: nameserver, domain: domain)
add_nameserver_to_failed(nameserver: nameserver, reason: text)
-
false
end
def failed_log(text:, nameserver:, domain:)
- inform_to_tech_contact(domain: domain, text: text)
+ inform_to_tech_contact(domain: domain, nameserver: nameserver, text: text)
inform_to_registrar(text: text, nameserver: nameserver)
false
end
- def inform_to_tech_contact(domain:, text: nil)
- ContactNotification.notify_tech_contact(domain: domain, reason: 'nameserver')
+ def inform_to_tech_contact(domain:, nameserver:, text: nil)
+ ContactNotification.notify_tech_contact(domain: domain, nameserver: nameserver, reason: 'nameserver')
end
def inform_to_registrar(nameserver:, text: nil)
- text = "Host record #{nameserver.hostname} of a domain #{nameserver.domain} is invalid. Please fix or contact the registrant."
+ text = "Host record #{nameserver.hostname} of a domain #{nameserver.domain} is invalid.
+ Please fix or contact the registrant. Problem with nameserver #{nameserver} - #{nameserver.failed_validation_reason}"
logger.info text
ContactNotification.notify_registrar(domain: nameserver.domain, text: text)
end
diff --git a/app/jobs/validate_dnssec_job.rb b/app/jobs/validate_dnssec_job.rb
index 3277914f1..b5357bead 100644
--- a/app/jobs/validate_dnssec_job.rb
+++ b/app/jobs/validate_dnssec_job.rb
@@ -133,13 +133,6 @@ class ValidateDnssecJob < ApplicationJob
resolver
end
- def log_templates
- {
- "true" => "validated successfully",
- "false" => "validated fail"
- }
- end
-
def logger
@logger ||= Rails.logger
end
diff --git a/app/mailers/contact_inform_mailer.rb b/app/mailers/contact_inform_mailer.rb
index 7423da791..bf5037cbf 100644
--- a/app/mailers/contact_inform_mailer.rb
+++ b/app/mailers/contact_inform_mailer.rb
@@ -10,9 +10,10 @@ class ContactInformMailer < ApplicationMailer
mail(to: contact.email, subject: subject)
end
- def notify_nameserver(contact:, domain:)
+ def notify_nameserver(contact:, domain:, nameserver:)
@contact = contact
@domain = domain
+ @nameserver = nameserver
subject = "Domeeni #{@domain.name} nimeserveri kirjed ei ole korrektsed / The host records of the domain #{@domain.name} are invalid"
mail(to: contact.email, subject: subject)
diff --git a/app/models/nameserver.rb b/app/models/nameserver.rb
index 20d4656c6..ababd84cf 100644
--- a/app/models/nameserver.rb
+++ b/app/models/nameserver.rb
@@ -55,7 +55,7 @@ class Nameserver < ApplicationRecord
}
end
- def nameserver_failed_validation?
+ def failed_validation?
return false if validation_counter.nil?
validation_counter >= NameserverValidator::VALID_NAMESERVER_COUNT_THRESHOLD
diff --git a/app/services/contact_notification.rb b/app/services/contact_notification.rb
index 16765d65d..e9b00c575 100644
--- a/app/services/contact_notification.rb
+++ b/app/services/contact_notification.rb
@@ -5,7 +5,7 @@ module ContactNotification
domain.registrar.notifications.create(text: text)
end
- def notify_tech_contact(domain:, reason: nil)
+ def notify_tech_contact(domain:, nameserver: nil, reason: nil)
case reason
when 'dnssec'
domain.tech_contacts.each do |tech|
@@ -17,7 +17,7 @@ module ContactNotification
domain.tech_contacts.each do |tech|
contact = Contact.find(tech.id)
- ContactInformMailer.notify_nameserver(contact: contact, domain: domain).deliver_now
+ ContactInformMailer.notify_nameserver(contact: contact, domain: domain, nameserver: nameserver).deliver_now
end
end
end
diff --git a/app/views/mailers/contact_inform_mailer/notify_nameserver.html.erb b/app/views/mailers/contact_inform_mailer/notify_nameserver.html.erb
index ce6b968a0..c9df4f6f0 100644
--- a/app/views/mailers/contact_inform_mailer/notify_nameserver.html.erb
+++ b/app/views/mailers/contact_inform_mailer/notify_nameserver.html.erb
@@ -6,6 +6,8 @@ Eesti Interneti Sihtasutusele (EIS) juhib tähelepanu, et domeeni <%= @domain.na
Andmete parandamiseks vaadake palun üle domeeni nimeserverite seaditused või pöörduge palun oma registripidaja <%= @domain.registrar.name%> või nimeserveri teenuse pakkuja poole.
+Viga nimesereriga <%= @nameserver %> - <%= @nameserver.failed_validation_reason %>
+
Lisaküsimuste korral võtke palun ühendust oma registripidajaga:
@@ -30,6 +32,8 @@ Lugupidamisega
Please check the name server settings of the domain or contact your registrar <%= @domain.registrar.name%> or your name server service provider to correct this information.
+Problem with nameserver <%= @nameserver %> - <%= @nameserver.failed_validation_reason %>"
+
Should you have additional questions, please contact your registrar:
diff --git a/test/jobs/nameserver_record_validation_job_test.rb b/test/jobs/nameserver_record_validation_job_test.rb
index a8d625ca1..1f39c6d33 100644
--- a/test/jobs/nameserver_record_validation_job_test.rb
+++ b/test/jobs/nameserver_record_validation_job_test.rb
@@ -93,6 +93,6 @@ class NameserverRecordValidationJobTest < ActiveSupport::TestCase
assert @nameserver.validation_counter, 1
assert @nameserver.failed_validation_reason.include? "Serial number for nameserver hostname **#{@nameserver.hostname}** doesn't present. SOA validation failed."
- assert @nameserver.nameserver_failed_validation?
+ assert @nameserver.failed_validation?
end
end
diff --git a/test/services/contact_notification_test.rb b/test/services/contact_notification_test.rb
index 0e75fb548..ec3d975e6 100644
--- a/test/services/contact_notification_test.rb
+++ b/test/services/contact_notification_test.rb
@@ -4,6 +4,7 @@ class ContactNotificationTest < ActionMailer::TestCase
setup do
@domain = domains(:shop)
+ @nameserver = nameservers(:shop_ns1)
@text = 'text'
end
@@ -14,7 +15,7 @@ class ContactNotificationTest < ActionMailer::TestCase
end
def test_notify_tech_contacts_that_nameserver_is_broken
- ContactNotification.notify_tech_contact(domain: @domain, reason: 'nameserver')
+ ContactNotification.notify_tech_contact(domain: @domain, reason: 'nameserver', nameserver: @nameserver)
assert_equal @domain.tech_contacts.count, 2
assert_emails 2
end
From aba8c1fb1746dc6841349b61af61e583116d92a4 Mon Sep 17 00:00:00 2001
From: olegphenomenon
Date: Wed, 12 Jan 2022 17:09:53 +0200
Subject: [PATCH 30/33] addede test for dnssec validator
---
app/jobs/validate_dnssec_job.rb | 4 ++
test/jobs/validate_dnssec_job_test.rb | 91 ++++++++++++++++++---------
2 files changed, 64 insertions(+), 31 deletions(-)
diff --git a/app/jobs/validate_dnssec_job.rb b/app/jobs/validate_dnssec_job.rb
index b5357bead..07728eff1 100644
--- a/app/jobs/validate_dnssec_job.rb
+++ b/app/jobs/validate_dnssec_job.rb
@@ -63,6 +63,7 @@ class ValidateDnssecJob < ApplicationJob
logger.info "-----------"
response_container = parse_response(answer)
+
compare_dnssec_data(response_container: response_container, domain: domain)
rescue Exception => e
logger.error "#{e.message} - domain name: #{domain.name} - hostname: #{hostname}"
@@ -76,6 +77,7 @@ class ValidateDnssecJob < ApplicationJob
flag = make_magic(response_container: response_container, dnskey: key)
text = "#{key.flags} - #{key.protocol} - #{key.alg} - #{key.public_key}"
+
if flag
key.validation_datetime = Time.zone.now
key.save
@@ -98,7 +100,9 @@ class ValidateDnssecJob < ApplicationJob
def parse_response(answer)
response_container = []
+
answer.each_answer do |a|
+
a_string = a.to_s
a_string = a_string.gsub /\t/, ' '
a_string = a_string.split(' ')
diff --git a/test/jobs/validate_dnssec_job_test.rb b/test/jobs/validate_dnssec_job_test.rb
index d8207492c..cd207e03a 100644
--- a/test/jobs/validate_dnssec_job_test.rb
+++ b/test/jobs/validate_dnssec_job_test.rb
@@ -1,42 +1,71 @@
-$VERBOSE=nil
require 'test_helper'
+class ZoneAnswer
+ def initialize(valid_response: true)
+ @answer = []
+
+ algorithm = OpenStruct.new(code: 13)
+
+ answer = OpenStruct.new
+ answer.data = "some0 some1 some2 257 some4 some5 some6 mdsswUyr3DPW132mOi8V9xESWE8jTo0dxCjjnopKl+GqJxpVXckHAeF+KkxLbxILfDLUT0rAK9iUzy1L53eKGQ== some"
+ answer.flags = 257
+ answer.protocol = 3
+ answer.protocol = 7 unless valid_response
+ answer.algorithm = algorithm
+
+ @answer << answer
+ end
+
+ def each_answer
+ @answer.each {|rec|
+ yield rec
+ }
+ end
+end
+
class ValidateDnssecJobTest < ActiveJob::TestCase
setup do
@domain = domains(:shop)
@dnskey = dnskeys(:one)
end
- def test_job_should_return_successfully_validated_dnskeys
- # @domain.dnskeys << @dnskey
- # @domain.save
- # @domain.reload
- #
- # mock_zone_data = [
- # {
- # flags: @dnskey.flags,
- # protocol: @dnskey.protocol,
- # alg: @dnskey.alg,
- # public_key: @dnskey.public_key
- # }]
- #
- # resolver = Spy.mock(Dnsruby::Recursor)
- # Spy.on(resolver, :query).and_return true
- # Spy.on_instance_method(ValidateDnssecJob, :parse_response).and_return(mock_zone_data)
- # # Spy.on_instance_method(ValidateDnssecJob, :prepare_validator).and_return(true)
- #
- #
- # ValidateDnssecJob.perform_now(domain_name: @domain.name)
- #
- # @domain.reload
- # p @domain.dnskeys
+ def test_job_should_set_validation_datetime_if_validation_is_valid
+ @domain.nameservers.each do |n|
+ n.update(validation_datetime: Time.zone.now - 1.minute)
+ end
+ @domain.dnskeys << @dnskey
+ @domain.save
+
+ @domain.reload
+
+ mock_zone_data = ZoneAnswer.new
+
+ Spy.on_instance_method(ValidateDnssecJob, :prepare_validator).and_return(Dnsruby::Resolver.new)
+ Spy.on_instance_method(Dnsruby::Resolver, :query).and_return(mock_zone_data)
+
+ ValidateDnssecJob.perform_now(domain_name: @domain.name)
+
+ @domain.reload
+ assert_not_nil @domain.dnskeys.first.validation_datetime
end
- # def test_job_discarded_after_error
- # assert_no_enqueued_jobs
- # assert_performed_jobs 1 do
- # TestDiscardedJob.perform_later
- # end
- # assert_no_enqueued_jobs
- # end
+ def test_job_should_not_set_validation_datetime_if_validation_is_invalid
+ @domain.nameservers.each do |n|
+ n.update(validation_datetime: Time.zone.now - 1.minute)
+ end
+ @domain.dnskeys << @dnskey
+ @domain.save
+
+ @domain.reload
+
+ mock_zone_data = ZoneAnswer.new(valid_response: false)
+
+ Spy.on_instance_method(ValidateDnssecJob, :prepare_validator).and_return(Dnsruby::Resolver.new)
+ Spy.on_instance_method(Dnsruby::Resolver, :query).and_return(mock_zone_data)
+
+ ValidateDnssecJob.perform_now(domain_name: @domain.name)
+
+ @domain.reload
+ assert_nil @domain.dnskeys.first.validation_datetime
+ end
end
From e3b370e7c138c709062b0ff03dc283e25ab44f93 Mon Sep 17 00:00:00 2001
From: olegphenomenon
Date: Thu, 27 Jan 2022 09:31:45 +0200
Subject: [PATCH 31/33] updated condition
---
app/services/nameserver_validator.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/services/nameserver_validator.rb b/app/services/nameserver_validator.rb
index 410448472..c45003cd3 100644
--- a/app/services/nameserver_validator.rb
+++ b/app/services/nameserver_validator.rb
@@ -18,7 +18,7 @@ module NameserverValidator
# result_response = validate(domain_name: domain_name, hostname: nameserver.ipv6)
end
- return { result: false, reason: 'glup record' } if result.answer.empty? if result_response[:result]
+ return { result: false, reason: 'glup record' } unless result_response[:result]
return result_response
end
From d2e7148f4f0b216a0c7c8313e8572c4f88e8788c Mon Sep 17 00:00:00 2001
From: olegphenomenon
Date: Wed, 2 Feb 2022 13:44:30 +0200
Subject: [PATCH 32/33] added condition to skip single domain dnssec check if
it does not have any dnskeys
---
app/jobs/validate_dnssec_job.rb | 2 ++
1 file changed, 2 insertions(+)
diff --git a/app/jobs/validate_dnssec_job.rb b/app/jobs/validate_dnssec_job.rb
index 07728eff1..452f6b4cb 100644
--- a/app/jobs/validate_dnssec_job.rb
+++ b/app/jobs/validate_dnssec_job.rb
@@ -5,6 +5,8 @@ class ValidateDnssecJob < ApplicationJob
unless domain_name.nil?
domain = Domain.find_by(name: domain_name)
+ return logger.info "This domain not contain any dnskeys" if domain.dnskeys.empty?
+
return logger.info "No domain found" if domain.nil?
return logger.info "No related nameservers for this domain" if domain.nameservers.empty?
From d99330a098b0de6eaf2cc886b193e402c902ce80 Mon Sep 17 00:00:00 2001
From: olegphenomenon
Date: Wed, 9 Feb 2022 11:05:23 +0200
Subject: [PATCH 33/33] comment out notifications
---
app/jobs/nameserver_record_validation_job.rb | 4 ++--
app/jobs/validate_dnssec_job.rb | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/app/jobs/nameserver_record_validation_job.rb b/app/jobs/nameserver_record_validation_job.rb
index 9271d94d7..7dd2211a4 100644
--- a/app/jobs/nameserver_record_validation_job.rb
+++ b/app/jobs/nameserver_record_validation_job.rb
@@ -109,14 +109,14 @@ class NameserverRecordValidationJob < ApplicationJob
end
def inform_to_tech_contact(domain:, nameserver:, text: nil)
- ContactNotification.notify_tech_contact(domain: domain, nameserver: nameserver, reason: 'nameserver')
+ # ContactNotification.notify_tech_contact(domain: domain, nameserver: nameserver, reason: 'nameserver')
end
def inform_to_registrar(nameserver:, text: nil)
text = "Host record #{nameserver.hostname} of a domain #{nameserver.domain} is invalid.
Please fix or contact the registrant. Problem with nameserver #{nameserver} - #{nameserver.failed_validation_reason}"
logger.info text
- ContactNotification.notify_registrar(domain: nameserver.domain, text: text)
+ # ContactNotification.notify_registrar(domain: nameserver.domain, text: text)
end
def logger
diff --git a/app/jobs/validate_dnssec_job.rb b/app/jobs/validate_dnssec_job.rb
index 452f6b4cb..623513768 100644
--- a/app/jobs/validate_dnssec_job.rb
+++ b/app/jobs/validate_dnssec_job.rb
@@ -50,8 +50,8 @@ class ValidateDnssecJob < ApplicationJob
text = "DNSKEY record of a domain #{domain.name} is invalid. Please fix or contact the registrant."
logger.info text
- ContactNotification.notify_registrar(domain: domain, text: text)
- ContactNotification.notify_tech_contact(domain: domain, reason: 'dnssec')
+ # ContactNotification.notify_registrar(domain: domain, text: text)
+ # ContactNotification.notify_tech_contact(domain: domain, reason: 'dnssec')
end
def validate(hostname:, domain:, type: 'DNSKEY', klass: 'IN')