DNSSEC refactor

This commit is contained in:
Martin Lensment 2014-10-09 13:59:52 +03:00
parent 6f12af5e0b
commit 3453b7f4a1
14 changed files with 150 additions and 30 deletions

View file

@ -94,7 +94,14 @@ module Epp::DomainsHelper
def validate_domain_create_request def validate_domain_create_request
@ph = params_hash['epp']['command']['create']['create'] @ph = params_hash['epp']['command']['create']['create']
# TODO: Verify contact presence if registrant is juridical # TODO: Verify contact presence if registrant is juridical
xml_attrs_present?(@ph, [['name'], ['ns'], ['registrant']]) attrs_present = xml_attrs_present?(@ph, [['name'], ['ns'], ['registrant']])
return false unless attrs_present
if parsed_frame.css('dsData').count > 0 && parsed_frame.css('create > keyData').count > 0
epp_errors << { code: '2306', msg: I18n.t('shared.ds_data_and_key_data_must_not_exists_together') }
return false
end
true
end end
def domain_create_params def domain_create_params

View file

@ -0,0 +1,3 @@
class DelegationSigner < ActiveRecord::Base
has_many :dnskeys
end

View file

@ -2,6 +2,7 @@ class Dnskey < ActiveRecord::Base
include EppErrors include EppErrors
belongs_to :domain belongs_to :domain
belongs_to :delegation_signer
validates :alg, :protocol, :flags, :public_key, presence: true validates :alg, :protocol, :flags, :public_key, presence: true
validate :validate_algorithm validate :validate_algorithm

View file

@ -174,9 +174,48 @@ class Epp::EppDomain < Domain
domain_statuses.delete(to_delete) domain_statuses.delete(to_delete)
end end
def attach_dnskeys(dnskey_list) def attach_dnskeys(dnssec_data)
dnskey_list.each do |dnskey_attrs| sg = SettingGroup.dnskeys
dnskeys.build(dnskey_attrs) ds_data_allowed = sg.setting(Setting::ALLOW_DS_DATA) == '0' ? false : true
ds_data_with_keys_allowed = sg.setting(Setting::ALLOW_DS_DATA_WITH_KEYS) == '0' ? false : true
key_data_allowed = sg.setting(Setting::ALLOW_KEY_DATA) == '0' ? false : true
if dnssec_data[:ds_data].any? && !ds_data_allowed
errors.add(:base, :ds_data_not_allowed)
return
end
dnssec_data[:ds_data].each do |ds_data|
if ds_data[:key_data].any? && !ds_data_with_keys_allowed
errors.add(:base, :ds_data_with_keys_not_allowed)
next
else
attach_ds(ds_data)
end
end
if dnssec_data[:key_data].any? && !key_data_allowed
errors.add(:base, :key_data_not_allowed)
return
end
attach_ds({
keyTag: SecureRandom.hex(5),
alg: 3,
digestType: sg.setting(Setting::DS_ALGORITHM),
key_data: dnssec_data[:key_data]
})
# dnskey_list.each do |dnskey_attrs|
# dnskeys.build(dnskey_attrs)
# end
end
def attach_ds(ds_data)
key_data = ds_data.delete(:key_data)
ds = delegation_signers.build(ds_data)
key_data.each do |x|
ds.dnskeys.build(x)
end end
end end
@ -358,16 +397,39 @@ class Epp::EppDomain < Domain
end end
def parse_dnskeys_from_frame(parsed_frame) def parse_dnskeys_from_frame(parsed_frame)
res = [] res = { ds_data: [], key_data: [] }
parsed_frame.css('dnskey').each do |x| res[:max_sig_life] = parsed_frame.css('maxSigLife').first.try(:text)
res << {
parsed_frame.css('dsData').each do |x|
keys = []
x.css('keyData').each do |kd|
keys << {
flags: kd.css('flags').first.try(:text),
protocol: kd.css('protocol').first.try(:text),
alg: kd.css('alg').first.try(:text),
public_key: kd.css('pubKey').first.try(:text)
}
end
res[:ds_data] << {
key_tag: x.css('keyTag').first.try(:text),
alg: x.css('alg').first.try(:text),
digest_type: x.css('digestType').first.try(:text),
digest: x.css('digest').first.try(:text),
key_data: keys
}
end
parsed_frame.css('create > keyData').each do |x|
res[:key_data] << {
flags: x.css('flags').first.try(:text), flags: x.css('flags').first.try(:text),
protocol: x.css('protocol').first.try(:text), protocol: x.css('protocol').first.try(:text),
alg: x.css('alg').first.try(:text), alg: x.css('alg').first.try(:text),
public_key: x.css('pubKey').first.try(:text) public_key: x.css('pubKey').first.try(:text)
} }
end end
res res
end end

View file

@ -3,4 +3,10 @@ class Setting < ActiveRecord::Base
has_many :domain_statuses has_many :domain_statuses
has_many :domains, through: :domain_statuses has_many :domains, through: :domain_statuses
validates :code, uniqueness: { scope: :setting_group_id } validates :code, uniqueness: { scope: :setting_group_id }
#dnskeys
DS_ALGORITHM = 'ds_algorithm'
ALLOW_DS_DATA = 'allow_ds_data'
ALLOW_DS_DATA_WITH_KEYS = 'allow_ds_data_with_keys'
ALLOW_KEY_DATA = 'allow_key_data'
end end

View file

@ -14,12 +14,12 @@ class SettingGroup < ActiveRecord::Base
find_by(code: 'domain_validation') find_by(code: 'domain_validation')
end end
def domain_statuses
find_by(code: 'domain_statuses')
end
def domain_general def domain_general
find_by(code: 'domain_general') find_by(code: 'domain_general')
end end
def dnskeys
find_by(code: 'dnskeys')
end
end end
end end

View file

@ -74,6 +74,9 @@ en:
base: base:
domain_status_prohibits_operation: 'Domain status prohibits operation' domain_status_prohibits_operation: 'Domain status prohibits operation'
domain_already_belongs_to_the_querying_registrar: 'Domain already belongs to the querying registrar' domain_already_belongs_to_the_querying_registrar: 'Domain already belongs to the querying registrar'
ds_data_not_allowed: 'dsData object is not allowed'
ds_data_with_keys_not_allowed: 'dsData object with key data is not allowed'
key_data_not_allowed: 'keyData object is not allowed'
name_dirty: name_dirty:
invalid: 'Domain name is invalid' invalid: 'Domain name is invalid'
reserved: 'Domain name is reserved or restricted' reserved: 'Domain name is reserved or restricted'
@ -424,3 +427,4 @@ en:
# sorry these need to be refactored - Andres # sorry these need to be refactored - Andres
authentication_error: 'Authentication error' authentication_error: 'Authentication error'
ds_data_and_key_data_must_not_exists_together: 'dsData and keyData objects must not exists together'

View file

@ -1,9 +1,9 @@
class AddDnskeySettings < ActiveRecord::Migration class AddDnskeySettings < ActiveRecord::Migration
def change def change
sg = SettingGroup.create(code: 'dnskeys') sg = SettingGroup.create(code: 'dnskeys')
sg.settings << Setting.create(code: 'ds_algorithm', value: 1) sg.settings << Setting.create(code: Setting::DS_ALGORITHM, value: 1)
sg.settings << Setting.create(code: 'allow_ds_data', value: 1) sg.settings << Setting.create(code: Setting::ALLOW_DS_DATA, value: 1)
sg.settings << Setting.create(code: 'allow_ds_data_with_keys', value: 1) sg.settings << Setting.create(code: Setting::ALLOW_DS_DATA_WITH_KEYS, value: 1)
sg.settings << Setting.create(code: 'allow_key_data', value: 1) sg.settings << Setting.create(code: Setting::ALLOW_KEY_DATA, value: 1)
end end
end end

View file

@ -0,0 +1,10 @@
class CreateDelegationSigner < ActiveRecord::Migration
def change
create_table :delegation_signers do |t|
t.integer :domain_id
t.string :key_tag
t.integer :digest_type
t.string :digest
end
end
end

View file

@ -0,0 +1,5 @@
class AddDelegationSignerToDnskey < ActiveRecord::Migration
def change
add_column :dnskeys, :delegation_signer_id, :integer
end
end

View file

@ -11,7 +11,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20141008134959) do ActiveRecord::Schema.define(version: 20141009101337) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
@ -91,12 +91,20 @@ ActiveRecord::Schema.define(version: 20141008134959) do
t.datetime "updated_at" t.datetime "updated_at"
end end
create_table "delegation_signers", force: true do |t|
t.integer "domain_id"
t.string "key_tag"
t.integer "digest_type"
t.string "digest"
end
create_table "dnskeys", force: true do |t| create_table "dnskeys", force: true do |t|
t.integer "domain_id" t.integer "domain_id"
t.integer "flags" t.integer "flags"
t.integer "protocol" t.integer "protocol"
t.integer "alg" t.integer "alg"
t.string "public_key" t.string "public_key"
t.integer "delegation_signer_id"
end end
create_table "domain_contacts", force: true do |t| create_table "domain_contacts", force: true do |t|

View file

@ -13,6 +13,7 @@ describe 'EPP Domain', epp: true do
Fabricate(:domain_validation_setting_group) Fabricate(:domain_validation_setting_group)
Fabricate(:domain_statuses_setting_group) Fabricate(:domain_statuses_setting_group)
Fabricate(:dnskeys_setting_group)
end end
it 'returns error if contact does not exists' do it 'returns error if contact does not exists' do
@ -314,7 +315,7 @@ describe 'EPP Domain', epp: true do
it 'does not create a domain with invalid period' do it 'does not create a domain with invalid period' do
xml = domain_create_xml({ xml = domain_create_xml({
period: {value: '367', attrs: { unit: 'd' } } period: { value: '367', attrs: { unit: 'd' } }
}) })
response = epp_request(xml, :xml) response = epp_request(xml, :xml)
@ -324,18 +325,17 @@ describe 'EPP Domain', epp: true do
end end
it 'creates a domain with multiple dnskeys' do it 'creates a domain with multiple dnskeys' do
xml = domain_create_xml({ xml = domain_create_xml({}, {
dnssec: [ _other: [
{ { keyData: {
dnskey: {
flags: { value: '257' }, flags: { value: '257' },
protocol: { value: '3' }, protocol: { value: '3' },
alg: { value: '3' }, alg: { value: '5' },
pubKey: { value: 'AwEAAddt2AkLfYGKgiEZB5SmIF8EvrjxNMH6HtxWEA4RJ9Ao6LCWheg8' } pubKey: { value: 'AwEAAddt2AkLfYGKgiEZB5SmIF8EvrjxNMH6HtxWEA4RJ9Ao6LCWheg8' }
} }
}, },
{ {
dnskey: { keyData: {
flags: { value: '0' }, flags: { value: '0' },
protocol: { value: '3' }, protocol: { value: '3' },
alg: { value: '5' }, alg: { value: '5' },
@ -343,7 +343,7 @@ describe 'EPP Domain', epp: true do
} }
}, },
{ {
dnskey: { keyData: {
flags: { value: '256' }, flags: { value: '256' },
protocol: { value: '3' }, protocol: { value: '3' },
alg: { value: '254' }, alg: { value: '254' },

View file

@ -38,3 +38,15 @@ Fabricator(:domain_general_setting_group, from: :setting_group) do
] ]
end end
end end
Fabricator(:dnskeys_setting_group, from: :setting_group) do
code 'dnskeys'
settings do
[
Fabricate(:setting, code: Setting::DS_ALGORITHM, value: 1),
Fabricate(:setting, code: Setting::ALLOW_DS_DATA, value: 1),
Fabricate(:setting, code: Setting::ALLOW_DS_DATA_WITH_KEYS, value: 1),
Fabricate(:setting, code: Setting::ALLOW_KEY_DATA, value: 1)
]
end
end

View file

@ -72,12 +72,14 @@ module Epp
xml_params = defaults.deep_merge(xml_params) xml_params = defaults.deep_merge(xml_params)
dsnsec_defaults = { dsnsec_defaults = {
keyData: [ _other: [
{ keyData: {
flags: { value: '257' }, flags: { value: '257' },
protocol: { value: '3' }, protocol: { value: '3' },
alg: { value: '5' }, alg: { value: '5' },
pubKey: { value: 'AwEAAddt2AkLfYGKgiEZB5SmIF8EvrjxNMH6HtxWEA4RJ9Ao6LCWheg8' } pubKey: { value: 'AwEAAddt2AkLfYGKgiEZB5SmIF8EvrjxNMH6HtxWEA4RJ9Ao6LCWheg8' }
] }
}]
} }
dnssec_params = dsnsec_defaults.deep_merge(dnssec_params) if dnssec_params != false dnssec_params = dsnsec_defaults.deep_merge(dnssec_params) if dnssec_params != false