Merge branch 'master' of github.com:domify/registry

This commit is contained in:
Martin Lensment 2015-03-05 11:58:10 +02:00
commit 860d489e54
42 changed files with 616 additions and 319 deletions

4
.gitignore vendored
View file

@ -10,7 +10,6 @@ capybara-*.html
/spec/tmp /spec/tmp
**.orig **.orig
config/initializers/secret_token.rb config/initializers/secret_token.rb
config/application.yml
config/secrets.yml config/secrets.yml
config/database.yml config/database.yml
/export /export
@ -26,3 +25,6 @@ todo
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this: # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
.rvmrc .rvmrc
# Ignore application configuration
/config/application.yml

View file

@ -1,3 +1,8 @@
27.02.2015
* Simplified config/application-example.yml,
now system will check if all required settings are present in application.yml
19.02.2015 19.02.2015
* Cetrificate only enabled, please setup certificates following doc/certificate.md document. * Cetrificate only enabled, please setup certificates following doc/certificate.md document.

View file

@ -5,6 +5,9 @@ gem 'rails', '4.2.0'
gem 'iso8601', '~> 0.8.2' # for dates and times gem 'iso8601', '~> 0.8.2' # for dates and times
gem 'hashie_rails', '~> 0.0.1' gem 'hashie_rails', '~> 0.0.1'
# load env
gem 'figaro', '~> 1.1.0'
# model related # model related
gem 'pg', '~> 0.18.0' gem 'pg', '~> 0.18.0'
gem 'ransack', '~> 1.5.1' # for searching gem 'ransack', '~> 1.5.1' # for searching

View file

@ -152,6 +152,8 @@ GEM
i18n (~> 0.5) i18n (~> 0.5)
fastercsv (1.5.5) fastercsv (1.5.5)
ffi (1.9.6) ffi (1.9.6)
figaro (1.1.0)
thor (~> 0.14)
flay (2.4.0) flay (2.4.0)
ruby_parser (~> 3.0) ruby_parser (~> 3.0)
sexp_processor (~> 4.0) sexp_processor (~> 4.0)
@ -459,6 +461,7 @@ DEPENDENCIES
epp-xml (~> 0.10.4) epp-xml (~> 0.10.4)
fabrication (~> 2.12.2) fabrication (~> 2.12.2)
faker (~> 1.3.0) faker (~> 1.3.0)
figaro (~> 1.1.0)
grape (~> 0.10.1) grape (~> 0.10.1)
guard (~> 2.6.1) guard (~> 2.6.1)
guard-rails (~> 0.7.0) guard-rails (~> 0.7.0)

View file

@ -3,11 +3,11 @@ group :red_green_refactor, halt_on_fail: true do
# be sure you have apache2 configured to # be sure you have apache2 configured to
# accept EPP request on port 701, what proxy to 8989. # accept EPP request on port 701, what proxy to 8989.
# port and environment is just for correct notification, all is overwritten by CLI # port and environment is just for correct notification, all is overwritten by CLI
guard :rails, port: 8989, environment: 'test' do # guard :rails, port: 8989, environment: 'test' do
# guard :rails, port: 8989, environment: 'test', CLI: 'RAILS_ENV=test unicorn -p 8989' do # # guard :rails, port: 8989, environment: 'test', CLI: 'RAILS_ENV=test unicorn -p 8989' do
watch('Gemfile.lock') # watch('Gemfile.lock')
watch(%r{^(config|lib)/.*}) # watch(%r{^(config|lib)/.*})
end # end
guard :rspec, cmd: 'spring rspec', notification: false do guard :rspec, cmd: 'spring rspec', notification: false do
watch(%r{^spec/.+_spec\.rb$}) watch(%r{^spec/.+_spec\.rb$})

133
README.md
View file

@ -23,7 +23,7 @@ Installation
### Registry app ### Registry app
Usual Rails 4 app installation (rbenv install is under Debian build doc) Registry based on Rails 4 installation (rbenv install is under Debian build doc)
Manual demo install and database setup: Manual demo install and database setup:
@ -32,44 +32,11 @@ Manual demo install and database setup:
cd demo-registry cd demo-registry
rbenv local 2.2.0 rbenv local 2.2.0
bundle bundle
cp config/application-example.yml config/application.yml # and edit it
cp config/database-example.yml config/database.yml # and edit it cp config/database-example.yml config/database.yml # and edit it
cp config/initializers/devise_secret_example.rb.txt config/initializers/devise_secret.rb # and edit bundle exec rake db:all:setup # for production, please follow deployment howto
bundle exec rake assets:precompile bundle exec rake assets:precompile
Create registry database manually, example:
create database registry_production owner registry encoding 'UTF-8' LC_COLLATE 'et_EE.utf8' LC_CTYPE 'et_EE.utf8' template template0;
rake db:schema:load
rake db:seeds
Or create all databases:
rake db:all:setup # will create all databases and loads all schemas
rake db:all:create # creates all databases
rake db:all:schema:load # loads all schemas
rake db:all:schema:dump # dumps all schemas
Production install (database schema should be loaded and seeds should be present)
# at your local machine
git clone git@github.com:internetee/registry.git
cd registry
rbenv local 2.2.0 # more info about rbenv at debian doc
gem install mina
mina pr setup # one time, only creates missing directories
ssh registry
# at your server
cd registry
cp current/config/application-example.yml shared/config/application.yml # and edit it
cp current/config/database-example.yml shared/config/database.yml # and edit it
vi /etc/apache2/sites-enabled/registry.conf # add conf and all needed serts
vi /etc/apache2/sites-enabled/epp.conf # add epp conf, restart apache
exit
# at your local machine
mina pr deploy # this is command you use in every application code update
### Apache with patched mod_epp (Debian 7/Ubuntu 14.04 LTS) ### Apache with patched mod_epp (Debian 7/Ubuntu 14.04 LTS)
sudo apt-get install apache2 sudo apt-get install apache2
@ -186,11 +153,22 @@ All registry demo data can be found at:
Initially you can use two type of users: admin users and EPP users. Initially you can use two type of users: admin users and EPP users.
### Certificates setup ### Certificates setup
* [Certificates setup](/doc/certificates.md) * [Certificates setup](/doc/certificates.md)
### Deployment
* [Application build and update](/doc/application_build_doc.md)
### Autotesting
* [Testing](/doc/testing.md)
### EPP web client ### EPP web client
Please follow EPP web client readme: Please follow EPP web client readme:
@ -205,89 +183,6 @@ Please follow WHOIS server readme:
https://github.com/internetee/whois https://github.com/internetee/whois
Deployment
----------
* [Debian build](/doc/debian_build_doc.md)
* [Application build and update](/doc/application_build_doc.md)
CRON
----
Crontab can be setup after deploy. Jobs can be viewed [here](/config/schedule.rb).
mina pr cron:setup # to update the crontab.
mina pr cron:clear # to clear crontab.
Autotesting
-----------
* Before running tests for the first time: `RAILS_ENV=test rake db:seed`
* Run tests: `rake`
* Run EPP tests: `rake test:epp`
* Run all but EPP tests: `rake test:other`
To see internal errors while testing EPP
unicorn -E test -p 8989
rake spec:epp
### Apache mod_epp autotesting/debugging
Autotesting Apache mod_epp without Registry app.
sudo apt-get install apache2-dbg
Includes htpasswd command to generate authentication files
sudo apt-get install apache2-utils
For manual debugging purposes, standalone CGI scripts can be used:
This needs a static greeting file, so you will have to make /var/www writable.
```apache
<IfModule mod_epp.c>
<Directory "/usr/lib/cgi-bin/epp">
Options ExecCGI
SetHandler cgi-script
</Directory>
Listen 1700
<VirtualHost *:1700>
EPPEngine On
EPPCommandRoot /cgi-bin/epp/command
EPPSessionRoot /cgi-bin/epp/session
EPPErrorRoot /cgi-bin/epp/error
Alias /cgi-bin/epp/session/hello /var/www/html/epp/session-hello
Alias /cgi-bin/epp/session/login /usr/lib/cgi-bin/epp/session-login
Alias /cgi-bin/epp/session/logout /usr/lib/cgi-bin/epp/session-logout
Alias /cgi-bin/epp/error/schema /usr/lib/cgi-bin/epp/error-schema
Alias /cgi-bin/epp/command/create /usr/lib/cgi-bin/epp/create
Alias /cgi-bin/epp/command/info /usr/lib/cgi-bin/epp/info
EPPAuthURI /epp/auth/login
<Location /epp/auth>
AuthType Basic
AuthName "EPP"
AuthUserFile /etc/apache2/htpasswd
require valid-user
</Location>
</VirtualHost>
</IfModule>
```
sudo a2enmod cgi
sudo a2enmod authn_file # will be used for non implicit authentication URIs
sudo htpasswd -c /etc/apache2/htpasswd test
Type "test" when prompted
cd /usr/lib/cgi-bin
mkdir epp
Copy the files from $mod_epp/examples/cgis to /usr/lib/cgi-bin/epp
## Code Status ## Code Status
Alpha release status, only model tests: Alpha release status, only model tests:

View file

@ -17,9 +17,7 @@ class Epp::ContactsController < EppController
def create def create
authorize! :create, Epp::Contact authorize! :create, Epp::Contact
@contact = Epp::Contact.new(params[:parsed_frame], current_user.registrar)
@contact = Epp::Contact.new(params[:parsed_frame])
@contact.registrar = current_user.registrar
if @contact.save if @contact.save
render_epp_response '/epp/contacts/create' render_epp_response '/epp/contacts/create'

View file

@ -9,7 +9,7 @@ class Epp::SessionsController < EppController
# rubocop: disable Metrics/CyclomaticComplexity # rubocop: disable Metrics/CyclomaticComplexity
def login def login
cert_valid = true cert_valid = true
if request.ip == APP_CONFIG['webclient_ip'] if request.ip == ENV['webclient_ip']
@api_user = ApiUser.find_by(login_params) @api_user = ApiUser.find_by(login_params)
else else
if request.env['HTTP_SSL_CLIENT_S_DN_CN'] != login_params[:username] if request.env['HTTP_SSL_CLIENT_S_DN_CN'] != login_params[:username]

View file

@ -103,6 +103,7 @@ class EppController < ApplicationController
el, missing = nil, nil el, missing = nil, nil
selectors.each do |selector| selectors.each do |selector|
full_selector = [@prefix, selector].compact.join(' ') full_selector = [@prefix, selector].compact.join(' ')
attr = selector.split('>').last.strip.underscore
el = params[:parsed_frame].css(full_selector).first el = params[:parsed_frame].css(full_selector).first
if allow_blank if allow_blank
@ -112,7 +113,7 @@ class EppController < ApplicationController
end end
epp_errors << { epp_errors << {
code: '2003', code: '2003',
msg: I18n.t('errors.messages.required_parameter_missing', key: full_selector) msg: I18n.t('errors.messages.required_parameter_missing', key: "#{full_selector} [#{attr}]")
} if missing } if missing
end end

View file

@ -20,7 +20,7 @@ class ApiUser < User
after_initialize :set_defaults after_initialize :set_defaults
def set_defaults def set_defaults
return unless new_record? return unless new_record?
self.active = true self.active = true unless active_changed?
end end
def registrar_typeahead def registrar_typeahead

View file

@ -32,10 +32,10 @@ class ApiUserDeprecated < ActiveRecord::Base
csr_file.rewind csr_file.rewind
crt_file = Tempfile.new('client_crt') crt_file = Tempfile.new('client_crt')
_out, err, _st = Open3.capture3("openssl ca -keyfile #{APP_CONFIG['ca_key_path']} \ _out, err, _st = Open3.capture3("openssl ca -keyfile #{ENV['ca_key_path']} \
-cert #{APP_CONFIG['ca_cert_path']} \ -cert #{ENV['ca_cert_path']} \
-extensions usr_cert -notext -md sha256 \ -extensions usr_cert -notext -md sha256 \
-in #{csr_file.path} -out #{crt_file.path} -key '#{APP_CONFIG['ca_key_password']}' -batch") -in #{csr_file.path} -out #{crt_file.path} -key '#{ENV['ca_key_password']}' -batch")
if err.match(/Data Base Updated/) if err.match(/Data Base Updated/)
crt_file.rewind crt_file.rewind

View file

@ -33,7 +33,7 @@ class Certificate < ActiveRecord::Base
@cached_status = EXPIRED @cached_status = EXPIRED
end end
crl = OpenSSL::X509::CRL.new(File.open(APP_CONFIG['crl_path']).read) crl = OpenSSL::X509::CRL.new(File.open(ENV['crl_path']).read)
return @cached_status unless crl.revoked.map(&:serial).include?(parsed_crt.serial) return @cached_status unless crl.revoked.map(&:serial).include?(parsed_crt.serial)
@cached_status = REVOKED @cached_status = REVOKED
@ -45,10 +45,10 @@ class Certificate < ActiveRecord::Base
csr_file.rewind csr_file.rewind
crt_file = Tempfile.new('client_crt') crt_file = Tempfile.new('client_crt')
_out, err, _st = Open3.capture3("openssl ca -keyfile #{APP_CONFIG['ca_key_path']} \ _out, err, _st = Open3.capture3("openssl ca -keyfile #{ENV['ca_key_path']} \
-cert #{APP_CONFIG['ca_cert_path']} \ -cert #{ENV['ca_cert_path']} \
-extensions usr_cert -notext -md sha256 \ -extensions usr_cert -notext -md sha256 \
-in #{csr_file.path} -out #{crt_file.path} -key '#{APP_CONFIG['ca_key_password']}' -batch") -in #{csr_file.path} -out #{crt_file.path} -key '#{ENV['ca_key_password']}' -batch")
if err.match(/Data Base Updated/) if err.match(/Data Base Updated/)
crt_file.rewind crt_file.rewind
@ -67,9 +67,9 @@ class Certificate < ActiveRecord::Base
crt_file.write(crt) crt_file.write(crt)
crt_file.rewind crt_file.rewind
_out, err, _st = Open3.capture3("openssl ca -keyfile #{APP_CONFIG['ca_key_path']} \ _out, err, _st = Open3.capture3("openssl ca -keyfile #{ENV['ca_key_path']} \
-cert #{APP_CONFIG['ca_cert_path']} \ -cert #{ENV['ca_cert_path']} \
-revoke #{crt_file.path} -key '#{APP_CONFIG['ca_key_password']}' -batch") -revoke #{crt_file.path} -key '#{ENV['ca_key_password']}' -batch")
if err.match(/Data Base Updated/) || err.match(/ERROR:Already revoked/) if err.match(/Data Base Updated/) || err.match(/ERROR:Already revoked/)
save! save!
@ -81,8 +81,8 @@ class Certificate < ActiveRecord::Base
return false return false
end end
_out, _err, _st = Open3.capture3("openssl ca -keyfile #{APP_CONFIG['ca_key_path']} \ _out, _err, _st = Open3.capture3("openssl ca -keyfile #{ENV['ca_key_path']} \
-cert #{APP_CONFIG['ca_cert_path']} \ -cert #{ENV['ca_cert_path']} \
-gencrl -out #{APP_CONFIG['crl_path']} -key '#{APP_CONFIG['ca_key_password']}' -batch") -gencrl -out #{ENV['crl_path']} -key '#{ENV['ca_key_password']}' -batch")
end end
end end

View file

@ -3,42 +3,43 @@ module EppErrors
def construct_epp_errors def construct_epp_errors
epp_errors = [] epp_errors = []
errors.messages.each do |key, values| errors.messages.each do |attr, errors|
key = key.to_s.split('.')[0].to_sym attr = attr.to_s.split('.')[0].to_sym
next if key == :epp_errors next if attr == :epp_errors
if self.class.reflect_on_association(key) if self.class.reflect_on_association(attr)
epp_errors << collect_child_errors(key) epp_errors << collect_child_errors(attr)
end end
epp_errors << collect_parent_errors(values) epp_errors << collect_parent_errors(attr, errors)
end end
errors[:epp_errors] = epp_errors errors[:epp_errors] = epp_errors
errors[:epp_errors].flatten! errors[:epp_errors].flatten!
end end
def collect_parent_errors(values) def collect_parent_errors(attr, errors)
epp_errors = [] errors = [errors] if errors.is_a?(String)
values = [values] if values.is_a?(String)
values.each do |err| epp_errors = []
errors.each do |err|
code, value = find_epp_code_and_value(err) code, value = find_epp_code_and_value(err)
next unless code next unless code
epp_errors << { code: code, msg: err, value: value } msg = attr.to_sym == :base ? err : "#{err} [#{attr}]"
epp_errors << { code: code, msg: msg, value: value }
end end
epp_errors epp_errors
end end
def collect_child_errors(key) def collect_child_errors(attr)
macro = self.class.reflect_on_association(key).macro macro = self.class.reflect_on_association(attr).macro
multi = [:has_and_belongs_to_many, :has_many] multi = [:has_and_belongs_to_many, :has_many]
# single = [:belongs_to, :has_one] # single = [:belongs_to, :has_one]
epp_errors = [] epp_errors = []
send(key).each do |x| send(attr).each do |x|
x.errors.messages.each do |_key, values| x.errors.messages.each do |attribute, errors|
epp_errors << x.collect_parent_errors(values) epp_errors << x.collect_parent_errors(attribute, errors)
end end
end if multi.include?(macro) end if multi.include?(macro)

View file

@ -22,7 +22,11 @@ class Contact < ActiveRecord::Base
format: { with: /\d{4}-\d{2}-\d{2}/, message: :invalid_birthday_format }, format: { with: /\d{4}-\d{2}-\d{2}/, message: :invalid_birthday_format },
if: proc { |c| c.ident_type == 'birthday' } if: proc { |c| c.ident_type == 'birthday' }
validates :ident_country_code, presence: true, if: proc { |c| %w(bic priv).include? c.ident_type } validates :ident_country_code, presence: true, if: proc { |c| %w(bic priv).include? c.ident_type }
validates :code, uniqueness: { message: :epp_id_taken } validates :code,
uniqueness: { message: :epp_id_taken },
format: { with: /\A[\w\-\:]*\Z/i },
length: { maximum: 100 }
validate :ident_valid_format? validate :ident_valid_format?
delegate :street, to: :address delegate :street, to: :address
@ -99,15 +103,27 @@ class Contact < ActiveRecord::Base
ident_type != IDENT_TYPE_BIC ident_type != IDENT_TYPE_BIC
end end
# generate random id for contact
def generate_code def generate_code
self.code = SecureRandom.hex(4) self.code = SecureRandom.hex(4) if code.blank?
end end
def generate_auth_info def generate_auth_info
return if @generate_auth_info_disabled
self.auth_info = SecureRandom.hex(16) self.auth_info = SecureRandom.hex(16)
end end
def disable_generate_auth_info! # needed for testing
@generate_auth_info_disabled = true
end
def auth_info=(pw)
self[:auth_info] = pw if new_record?
end
def code=(code)
self[:code] = code if new_record?
end
# Find a way to use self.domains with contact # Find a way to use self.domains with contact
def domains_owned def domains_owned
Domain.where(owner_contact_id: id) Domain.where(owner_contact_id: id)

View file

@ -45,9 +45,22 @@ class Epp::Contact < Contact
# rubocop: enable Metrics/PerceivedComplexity # rubocop: enable Metrics/PerceivedComplexity
# rubocop: enable Metrics/CyclomaticComplexity # rubocop: enable Metrics/CyclomaticComplexity
def new(frame) def new(frame, registrar)
return super if frame.blank? return super if frame.blank?
super(attrs_from(frame))
custom_code =
if frame.css('id').present?
"#{registrar.code}:#{frame.css('id').text.parameterize}"
else
nil
end
super(
attrs_from(frame).merge(
code: custom_code,
registrar: registrar
)
)
end end
def legal_document_attrs(legal_frame) def legal_document_attrs(legal_frame)

View file

@ -9,10 +9,18 @@ class Registrar < ActiveRecord::Base
validates :name, :reg_no, :country_code, :email, presence: true validates :name, :reg_no, :country_code, :email, presence: true
validates :name, :reg_no, uniqueness: true validates :name, :reg_no, uniqueness: true
validate :set_code, if: :new_record?
after_save :touch_domains_version after_save :touch_domains_version
validates :email, :billing_email, format: /@/, allow_blank: true validates :email, :billing_email, format: /@/, allow_blank: true
class << self
def search_by_query(query)
res = search(name_or_reg_no_cont: query).result
res.reduce([]) { |o, v| o << { id: v[:id], display_key: "#{v[:name]} (#{v[:reg_no]})" } }
end
end
def domain_transfers def domain_transfers
at = DomainTransfer.arel_table at = DomainTransfer.arel_table
DomainTransfer.where( DomainTransfer.where(
@ -34,10 +42,23 @@ class Registrar < ActiveRecord::Base
Country.new(country_code) Country.new(country_code)
end end
class << self def code=(code)
def search_by_query(query) self[:code] = code if new_record?
res = search(name_or_reg_no_cont: query).result
res.reduce([]) { |o, v| o << { id: v[:id], display_key: "#{v[:name]} (#{v[:reg_no]})" } }
end end
private
def set_code
return false if name.blank?
new_code = name.parameterize
# ensure code is always uniq automatically for a new record
seq = 1
while self.class.find_by_code(new_code)
new_code += seq.to_s
seq += 1
end
self.code = new_code
end end
end end

View file

@ -18,7 +18,7 @@ class ZonefileSetting < ActiveRecord::Base
"select generate_zonefile('#{origin}')" "select generate_zonefile('#{origin}')"
)[0]['generate_zonefile'] )[0]['generate_zonefile']
File.open("#{APP_CONFIG['zonefile_export_dir']}/#{filename}", 'w') { |f| f.write(zf) } File.open("#{ENV['zonefile_export_dir']}/#{filename}", 'w') { |f| f.write(zf) }
STDOUT << "#{Time.now.utc} - Successfully generated zonefile #{filename}\n" STDOUT << "#{Time.now.utc} - Successfully generated zonefile #{filename}\n"
end end

View file

@ -21,7 +21,7 @@
%span.icon-bar %span.icon-bar
%span.icon-bar %span.icon-bar
= link_to admin_dashboard_path, class: 'navbar-brand' do = link_to admin_dashboard_path, class: 'navbar-brand' do
= APP_CONFIG['app_name'] = ENV['app_name']
- if unstable_env.present? - if unstable_env.present?
.text-center .text-center
%small{style: 'color: #0074B3;'}= unstable_env %small{style: 'color: #0074B3;'}= unstable_env

View file

@ -1,10 +0,0 @@
#!/bin/bash
#
# For docker
#
# cd to Rails root directory
cd "$(dirname "$0")"; cd ..
bin/update-repo
bin/robot

View file

@ -16,14 +16,14 @@ export RAILS_ENV=test
cd "$(dirname "$0")"; cd .. cd "$(dirname "$0")"; cd ..
cp config/application-example.yml config/application.yml cp config/application-example.yml config/application.yml
# create manually config/database.yml cp config/secrets-example.yml config/secrets.yml
cp config/database-robot.yml config/database.yml
# under jenkins use rbenv-plugin wrapper
bundle install bundle install
RAILS_ENV=test bundle exec rake db:drop RAILS_ENV=test bundle exec rake db:all:drop
RAILS_ENV=test bundle exec rake db:all:create RAILS_ENV=test bundle exec rake db:all:setup
RAILS_ENV=test bundle exec rake db:all:schema:load
RAILS_ENV=test bundle exec rake db:seed
RAILS_ENV=test bundle exec rake assets:precompile RAILS_ENV=test bundle exec rake assets:precompile
echo "GIT_LAST_COMMITS" echo "GIT_LAST_COMMITS"
@ -36,6 +36,10 @@ RCODE=$?
echo "END_OF_RUBOCOP_RESULTS" echo "END_OF_RUBOCOP_RESULTS"
echo "TEST_RESULTS" echo "TEST_RESULTS"
# basic test
# ROBOT=true bundle exec rake
# all tests with EPP
ROBOT=true bundle exec rake test ROBOT=true bundle exec rake test
TCODE=$? TCODE=$?
echo "END_OF_TEST_RESULTS" echo "END_OF_TEST_RESULTS"
@ -45,7 +49,7 @@ bundle exec bundle-audit update
bundle exec bundle-audit bundle exec bundle-audit
BCODE=$? BCODE=$?
BCODE=0 # tmp BCODE=0 # tmp
bundle exec brakeman bundle exec brakeman -q
echo "END_OF_SECURITY_RESULTS" echo "END_OF_SECURITY_RESULTS"
# update code review # update code review

View file

@ -1,33 +1,28 @@
defaults: &defaults # Be sure to restart your server when you modify settings.
app_name: .EE Registry
zonefile_export_dir: 'export/zonefiles'
# You can use `rake secret` to generate a secure secret key. app_name: .EE Registry
# Your secret key is used for verifying the integrity of signed cookies. zonefile_export_dir: 'export/zonefiles'
# If you change this key, all old signed cookies will become invalid!
secret_key_base: please-change-it-you-can-generate-it-with-rake-secret
devise_secret: please-change-it-you-can-generate-it-with-rake-secret
# Used by registry admin server: # You can use `rake secret` to generate a secure secret key.
crl_path: '/home/registry/registry/shared/ca/crl/crl.pem' # Your secret key is used for verifying the integrity of signed cookies.
ca_cert_path: '/home/registry/registry/shared/ca/certs/ca.crt.pem' # If you change this key, all old signed cookies will become invalid!
ca_key_path: '/home/registry/registry/shared/ca/private/ca.key.pem' secret_key_base: please-change-it-you-can-generate-it-with-rake-secret
ca_key_password: 'your-root-key-password' devise_secret: please-change-it-you-can-generate-it-with-rake-secret
# Used by EPP server # Used by admin server, you can leave those empty for when running EPP server:
webclient_ip: '54.154.91.240' crl_path: '/home/registry/registry/shared/ca/crl/crl.pem'
ca_cert_path: '/home/registry/registry/shared/ca/certs/ca.crt.pem'
ca_key_path: '/home/registry/registry/shared/ca/private/ca.key.pem'
ca_key_password: 'your-root-key-password'
development: # Used only by EPP server, you can leave it empty when running admin server:
<<: *defaults webclient_ip: '127.0.0.1'
# autotest config overwrites
test: test:
<<: *defaults webclient_ip: '127.0.0.1' # it should match to localhost ip address
crl_path: '/var/lib/jenkins/workspace/registry/ca/crl/crl.pem'
ca_cert_path: '/var/lib/jenkins/workspace/registry/ca/certs/ca.crt.pem'
ca_key_path: '/var/lib/jenkins/workspace/registry/ca/private/ca.key.pem'
ca_key_password: 'test'
alpha:
<<: *defaults
staging:
<<: *defaults
production:
<<: *defaults

19
config/database-robot.yml Normal file
View file

@ -0,0 +1,19 @@
default: &default
host: localhost
adapter: postgresql
encoding: unicode
pool: 5
username: test
password: test
test:
<<: *default
database: registry_test
whois_test:
<<: *default
database: registry_whois_test
api_log_test:
<<: *default
database: registry_api_log_test

View file

@ -1,2 +0,0 @@
APP_CONFIG = YAML.load_file("#{Rails.root}/config/application.yml")[Rails.env]
Registry::Application.config.secret_token = APP_CONFIG['secret_key_base']

View file

@ -4,7 +4,7 @@ Devise.setup do |config|
# The secret key used by Devise. Devise uses this key to generate # The secret key used by Devise. Devise uses this key to generate
# random tokens. Changing this key will render invalid all existing # random tokens. Changing this key will render invalid all existing
# confirmation, reset password and unlock tokens in the database. # confirmation, reset password and unlock tokens in the database.
config.secret_key = APP_CONFIG['devise_secret'] config.secret_key = ENV['devise_secret']
# ==> Mailer Configuration # ==> Mailer Configuration
# Configure the e-mail address which will be shown in Devise::Mailer, # Configure the e-mail address which will be shown in Devise::Mailer,

View file

@ -0,0 +1,13 @@
required = %w(
app_name
zonefile_export_dir
secret_key_base
devise_secret
crl_path
ca_cert_path
ca_key_path
ca_key_password
webclient_ip
)
Figaro.require_keys(required)

View file

@ -1,4 +1,5 @@
if ActiveRecord::Base.connected? && ActiveRecord::Base.connection.table_exists?('settings') # otherwise rake not working 100% # otherwise rake not working 100%
if ActiveRecord::Base.connected? && ActiveRecord::Base.connection.table_exists?('settings')
Setting.disclosure_name = true if Setting.disclosure_name.nil? Setting.disclosure_name = true if Setting.disclosure_name.nil?
Setting.disclosure_name = true if Setting.disclosure_name.nil? Setting.disclosure_name = true if Setting.disclosure_name.nil?
Setting.disclosure_org_name = true if Setting.disclosure_org_name.nil? Setting.disclosure_org_name = true if Setting.disclosure_org_name.nil?

View file

@ -0,0 +1 @@
Registry::Application.config.secret_token = ENV['secret_key_base']

View file

@ -0,0 +1,5 @@
class ChangeApiUserDefaultValue < ActiveRecord::Migration
def change
change_column_default :users, :active, nil
end
end

View file

@ -0,0 +1,6 @@
class AddCodeToRegistrar < ActiveRecord::Migration
def change
add_column :registrars, :code, :string
add_index :registrars, :code
end
end

View file

@ -0,0 +1,11 @@
class DataUpdateRegisntrarCodes < ActiveRecord::Migration
def change
puts 'Registrar code updates:'
Registrar.all.each do |r|
next if r.code.present?
r[:code] = r.name.parameterize
puts "#{r.id}: #{r.changes.inspect}"
r.save!
end
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: 20150223104842) do ActiveRecord::Schema.define(version: 20150303151224) 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"
@ -611,8 +611,11 @@ ActiveRecord::Schema.define(version: 20150223104842) do
t.string "city" t.string "city"
t.string "street" t.string "street"
t.string "zip" t.string "zip"
t.string "code"
end end
add_index "registrars", ["code"], name: "index_registrars_on_code", using: :btree
create_table "reserved_domains", force: :cascade do |t| create_table "reserved_domains", force: :cascade do |t|
t.string "name" t.string "name"
t.datetime "created_at" t.datetime "created_at"
@ -652,7 +655,7 @@ ActiveRecord::Schema.define(version: 20150223104842) do
t.string "updator_str" t.string "updator_str"
t.string "country_code" t.string "country_code"
t.integer "registrar_id" t.integer "registrar_id"
t.boolean "active", default: false t.boolean "active"
t.text "csr" t.text "csr"
t.text "crt" t.text "crt"
t.string "type" t.string "type"

View file

@ -1,7 +1,48 @@
### Application build and update Application build and update
----------------------------
For application deployment we are using faster [Mina](https://github.com/mina-deploy/mina) ### Debian setup
instead of Capistrano.
* [Debian build](/doc/debian_build_doc.md)
### Certificates setup
* [Certificates setup](/doc/certificates.md)
### Production env setup
For production you probably would like to create databases to your locale, example:
create database registry_production owner registry encoding 'UTF-8' LC_COLLATE 'et_EE.utf8' LC_CTYPE 'et_EE.utf8' template template0;
Deploy overview: (database schema should be loaded and seeds should be present)
# at your local machine
git clone git@github.com:internetee/registry.git
cd registry
rbenv local 2.2.0 # more info about rbenv at debian doc
gem install mina
mina pr setup # one time, only creates missing directories
ssh registry
# at your server
cd registry
cp current/config/application-example.yml shared/config/application.yml # and edit it
cp current/config/database-example.yml shared/config/database.yml # and edit it
vi /etc/apache2/sites-enabled/registry.conf # add conf and all needed serts
vi /etc/apache2/sites-enabled/epp.conf # add epp conf, restart apache
exit
# at your local machine
mina pr deploy # this is command you use in every application code update
### Deploy script setup
We recommend [Mina](https://github.com/mina-deploy/mina) instead of Capistrano for deployment.
All deploy code locates at config/deploy.rb file. All deploy code locates at config/deploy.rb file.
@ -68,3 +109,13 @@ General rake and mina tips:
rake -T # list all rake commands rake -T # list all rake commands
rake -T db # list all database related commands rake -T db # list all database related commands
mina -T # list all mina deploy commands mina -T # list all mina deploy commands
CRON
----
Crontab can be setup after deploy. Jobs can be viewed [here](/config/schedule.rb).
mina pr cron:setup # to update the crontab.
mina pr cron:clear # to clear crontab.

View file

@ -16,6 +16,16 @@ Private key and certificate must be packaged to pkcs12 and added to user browser
### Registry setup ### Registry setup
Setup CA directory in shared directory:
cd /home/registry/registry/shared
mkdir ca ca/certs ca/crl ca/newcerts ca/private ca/csrs
cd ca
chmod 700 private
touch index.txt
echo 1000 > serial
echo 1000 > crlnumber
Configure OpenSSL: Configure OpenSSL:
sudo cp /etc/ssl/openssl.cnf /etc/ssl/openssl.cnf.bak sudo cp /etc/ssl/openssl.cnf /etc/ssl/openssl.cnf.bak
@ -53,17 +63,6 @@ Make sure the following options are in place:
basicConstraints = CA:true # around line nr 240 basicConstraints = CA:true # around line nr 240
keyUsage = cRLSign, keyCertSign # around line nr 245 keyUsage = cRLSign, keyCertSign # around line nr 245
Setup CA directory in shared directory:
cd /home/registry/registry/shared
mkdir ca
cd ca
mkdir certs crl newcerts private csrs
chmod 700 private
touch index.txt
echo 1000 > serial
echo 1000 > crlnumber
Generate the root key and remember your password, you need it later in application.yml: Generate the root key and remember your password, you need it later in application.yml:
openssl genrsa -aes256 -out private/ca.key.pem 4096 openssl genrsa -aes256 -out private/ca.key.pem 4096
@ -90,10 +89,10 @@ Create certificate revocation list (prompts for pass phrase):
Configure registry registry/shared/config/application.yml to match the CA settings: Configure registry registry/shared/config/application.yml to match the CA settings:
crl_path: '/home/registry/registry/shared/ca/crl/crl.pem'
ca_cert_path: '/home/registry/registry/shared/ca/certs/ca.crt.pem' ca_cert_path: '/home/registry/registry/shared/ca/certs/ca.crt.pem'
ca_key_path: '/home/registry/registry/shared/ca/private/ca.key.pem' ca_key_path: '/home/registry/registry/shared/ca/private/ca.key.pem'
ca_key_password: 'your-root-key-password' ca_key_password: 'your-root-key-password'
crl_path: '/home/registry/registry/shared/ca/crl/crl.pem'
### Registry EPP setup ### Registry EPP setup
@ -162,6 +161,29 @@ Reload apache:
sudo /etc/init.d/apache2 restart sudo /etc/init.d/apache2 restart
### ApiUser browser setup
In short:
* Upload CSR file to api user at admin page /admin/api_users
* Sign it
* Generate p12 file and install into user browser
#### Creating CSR file
openssl genrsa -out private/api-user.key.pem 4096
chmod 400 private/api-user.key.pem
openssl req -sha256 -new -days 3653 -key private/api-user.key.pem -out csrs/api-user.csr.pem
Upload api-user.csr.pem file to api user at admin interface.
Sign it
Download CRT file and create p12 file.
openssl pkcs12 -export -inkey private/api-user.key.pem -in certs/api-user.crt.pem -out pkcs/api_user.p12
Add api_user.p12 to your browser.
Development env Development env
--------------- ---------------

View file

@ -1,6 +1,6 @@
## Contact related functions ## Contact related functions
Please study official Cantact Mapping protocol: Please study official Contact Mapping protocol:
http://tools.ietf.org/html/rfc5733 http://tools.ietf.org/html/rfc5733
More info at http://en.wikipedia.org/wiki/Extensible_Provisioning_Protocol More info at http://en.wikipedia.org/wiki/Extensible_Provisioning_Protocol
@ -13,6 +13,7 @@ Contact Mapping protocol short version:
----------------------- ------- ----------------- ----------------------- ------- -----------------
<create> 1 <create> 1
<contact:create> 1 Attribute: xmlns:contact="urn:ietf:params:xml:ns:contact-1.0" <contact:create> 1 Attribute: xmlns:contact="urn:ietf:params:xml:ns:contact-1.0"
<contact:id> 0-1 Contact id, optional, generated automatically if missing
<contact:postalInfo> 1 Postal information container <contact:postalInfo> 1 Postal information container
<contact:name> 1 Full name of the contact <contact:name> 1 Full name of the contact
<contact:org> 0-1 Name of organization <contact:org> 0-1 Name of organization
@ -42,7 +43,7 @@ Contact Mapping protocol short version:
----------------------- ------- ----------------- ----------------------- ------- -----------------
<update> 1 <update> 1
<contact:update> 1 Attribute: xmlns:contact="urn:ietf:params:xml:ns:contact-1.0" <contact:update> 1 Attribute: xmlns:contact="urn:ietf:params:xml:ns:contact-1.0"
<contact:id> 1 contact id, required <contact:id> 1 Contact id, required
<contact:chg> 1 Change container <contact:chg> 1 Change container
<contact:postalInfo> 1 Postal information container <contact:postalInfo> 1 Postal information container
<contact:name> 0-1 Full name of the contact <contact:name> 0-1 Full name of the contact

114
doc/testing.md Normal file
View file

@ -0,0 +1,114 @@
Testing
-------
Setup test databases:
RAILS_ENV=test rake db:all:setup
Run basic test (no EPP tests):
rake
Testing EPP
===========
In order to test EPP, you have to configure apache to handle EPP request correctly.
### Apache site config
First you should have mod_epp installed, please follow main README for doing it.
Apache site config for autotest, add file to /etc/apache2/sites-enabled/epp-autotest.conf
```apache
<IfModule mod_epp.c>
Listen 701
<VirtualHost *:701>
SSLEngine on
SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
SSLCertificateFile /etc/apache2/ssl/apache.crt
SSLCertificateKeyFile /etc/apache2/ssl/apache.key
SSLVerifyClient optional_no_ca
EPPEngine On
EPPCommandRoot /proxy/command
EPPSessionRoot /proxy/session
EPPErrorRoot /proxy/error
EPPRawFrame raw_frame
ProxyPass /proxy/ http://localhost:8989/epp/
EPPAuthURI implicit
EPPReturncodeHeader X-EPP-Returncode
</VirtualHost>
</IfModule>
```
* Run all tests with temp server running automatically on port 8989:
rake test
Manual debugging
================
### Apache mod_epp manual debugging
Debugging Apache mod_epp without Registry app.
sudo apt-get install apache2-dbg
Includes htpasswd command to generate authentication files
sudo apt-get install apache2-utils
For manual debugging purposes, standalone CGI scripts can be used:
This needs a static greeting file, so you will have to make /var/www writable.
```apache
<IfModule mod_epp.c>
<Directory "/usr/lib/cgi-bin/epp">
Options ExecCGI
SetHandler cgi-script
</Directory>
Listen 1700
<VirtualHost *:1700>
EPPEngine On
EPPCommandRoot /cgi-bin/epp/command
EPPSessionRoot /cgi-bin/epp/session
EPPErrorRoot /cgi-bin/epp/error
Alias /cgi-bin/epp/session/hello /var/www/html/epp/session-hello
Alias /cgi-bin/epp/session/login /usr/lib/cgi-bin/epp/session-login
Alias /cgi-bin/epp/session/logout /usr/lib/cgi-bin/epp/session-logout
Alias /cgi-bin/epp/error/schema /usr/lib/cgi-bin/epp/error-schema
Alias /cgi-bin/epp/command/create /usr/lib/cgi-bin/epp/create
Alias /cgi-bin/epp/command/info /usr/lib/cgi-bin/epp/info
EPPAuthURI /epp/auth/login
<Location /epp/auth>
AuthType Basic
AuthName "EPP"
AuthUserFile /etc/apache2/htpasswd
require valid-user
</Location>
</VirtualHost>
</IfModule>
```
sudo a2enmod cgi
sudo a2enmod authn_file # will be used for non implicit authentication URIs
sudo htpasswd -c /etc/apache2/htpasswd test
Type "test" when prompted
cd /usr/lib/cgi-bin
mkdir epp
Copy the files from $mod_epp/examples/cgis to /usr/lib/cgi-bin/epp

View file

@ -13,10 +13,8 @@ describe 'EPP Contact', epp: true do
login_as :registrar1 login_as :registrar1
Contact.skip_callback(:create, :before, :generate_code)
Contact.skip_callback(:create, :before, :generate_auth_info)
@contact = Fabricate(:contact, registrar: @registrar1) @contact = Fabricate(:contact, registrar: @registrar1)
@legal_document = { @legal_document = {
legalDocument: { legalDocument: {
value: 'JVBERi0xLjQKJcOkw7zDtsOfCjIgMCBvYmoKPDwvTGVuZ3RoIDMgMCBSL0Zp==', value: 'JVBERi0xLjQKJcOkw7zDtsOfCjIgMCBvYmoKPDwvTGVuZ3RoIDMgMCBSL0Zp==',
@ -25,11 +23,6 @@ describe 'EPP Contact', epp: true do
} }
end end
after :all do
Contact.set_callback(:create, :before, :generate_code)
Contact.set_callback(:create, :before, :generate_auth_info)
end
context 'with valid user' do context 'with valid user' do
context 'create command' do context 'create command' do
def create_request(overwrites = {}) def create_request(overwrites = {})
@ -53,19 +46,19 @@ describe 'EPP Contact', epp: true do
it 'fails if request xml is missing' do it 'fails if request xml is missing' do
response = epp_plain_request(@epp_xml.create, :xml) response = epp_plain_request(@epp_xml.create, :xml)
response[:results][0][:msg].should == response[:results][0][:msg].should ==
'Required parameter missing: create > create > postalInfo > name' 'Required parameter missing: create > create > postalInfo > name [name]'
response[:results][1][:msg].should == response[:results][1][:msg].should ==
'Required parameter missing: create > create > postalInfo > addr > city' 'Required parameter missing: create > create > postalInfo > addr > city [city]'
response[:results][2][:msg].should == response[:results][2][:msg].should ==
'Required parameter missing: create > create > postalInfo > addr > cc' 'Required parameter missing: create > create > postalInfo > addr > cc [cc]'
response[:results][3][:msg].should == response[:results][3][:msg].should ==
'Required parameter missing: create > create > ident' 'Required parameter missing: create > create > ident [ident]'
response[:results][4][:msg].should == response[:results][4][:msg].should ==
'Required parameter missing: create > create > voice' 'Required parameter missing: create > create > voice [voice]'
response[:results][5][:msg].should == response[:results][5][:msg].should ==
'Required parameter missing: create > create > email' 'Required parameter missing: create > create > email [email]'
response[:results][6][:msg].should == response[:results][6][:msg].should ==
'Required parameter missing: extension > extdata > legalDocument' 'Required parameter missing: extension > extdata > legalDocument [legal_document]'
response[:results][0][:result_code].should == '2003' response[:results][0][:result_code].should == '2003'
response[:results][1][:result_code].should == '2003' response[:results][1][:result_code].should == '2003'
@ -133,6 +126,17 @@ describe 'EPP Contact', epp: true do
# 5 seconds for what-ever weird lag reasons might happen # 5 seconds for what-ever weird lag reasons might happen
cr_date.text.to_time.should be_within(5).of(Time.now) cr_date.text.to_time.should be_within(5).of(Time.now)
end end
it 'successfully saves custom code' do
response = create_request(
{ id: { value: '12345' } }
)
response[:msg].should == 'Command completed successfully'
response[:result_code].should == '1000'
Contact.last.code.should == 'registrar1:12345'
end
end end
context 'update command' do context 'update command' do
@ -140,11 +144,9 @@ describe 'EPP Contact', epp: true do
@contact = @contact =
Fabricate( Fabricate(
:contact, :contact,
# created_by_id: 1,
registrar: @registrar1, registrar: @registrar1,
email: 'not_updated@test.test', email: 'not_updated@test.test',
code: 'sh8013', code: 'sh8013'
auth_info: 'password'
) )
end end
@ -177,13 +179,13 @@ describe 'EPP Contact', epp: true do
'Required parameter missing: add, rem or chg' 'Required parameter missing: add, rem or chg'
response[:results][0][:result_code].should == '2003' response[:results][0][:result_code].should == '2003'
response[:results][1][:msg].should == response[:results][1][:msg].should ==
'Required parameter missing: update > update > id' 'Required parameter missing: update > update > id [id]'
response[:results][1][:result_code].should == '2003' response[:results][1][:result_code].should == '2003'
response[:results][2][:msg].should == response[:results][2][:msg].should ==
'Required parameter missing: update > update > authInfo > pw' 'Required parameter missing: update > update > authInfo > pw [pw]'
response[:results][2][:result_code].should == '2003' response[:results][2][:result_code].should == '2003'
response[:results][3][:msg].should == response[:results][3][:msg].should ==
'Required parameter missing: extension > extdata > legalDocument' 'Required parameter missing: extension > extdata > legalDocument [legal_document]'
response[:results][3][:result_code].should == '2003' response[:results][3][:result_code].should == '2003'
response[:results].count.should == 4 response[:results].count.should == 4
end end
@ -221,11 +223,25 @@ describe 'EPP Contact', epp: true do
} }
}) })
response[:results][0][:msg].should == 'Phone nr is invalid' response[:results][0][:msg].should == 'Phone nr is invalid [phone]'
response[:results][0][:result_code].should == '2005' response[:results][0][:result_code].should == '2005'
response[:results][1][:msg].should == 'Email is invalid' response[:results][1][:msg].should == 'Email is invalid [email]'
response[:results][1][:result_code].should == '2005' response[:results][1][:result_code].should == '2005'
end end
it 'should not update code with custom string' do
response = update_request(
id: { value: 'sh8013' },
chg: {
id: { value: 'notpossibletoupdate' }
}
)
response[:msg].should == 'Object does not exist'
response[:result_code].should == '2303'
@contact.reload.code.should == 'sh8013'
end
end end
context 'delete command' do context 'delete command' do
@ -246,13 +262,13 @@ describe 'EPP Contact', epp: true do
response = epp_plain_request(@epp_xml.delete, :xml) response = epp_plain_request(@epp_xml.delete, :xml)
response[:results][0][:msg].should == response[:results][0][:msg].should ==
'Required parameter missing: delete > delete > id' 'Required parameter missing: delete > delete > id [id]'
response[:results][0][:result_code].should == '2003' response[:results][0][:result_code].should == '2003'
response[:results][1][:msg].should == response[:results][1][:msg].should ==
'Required parameter missing: delete > delete > authInfo > pw' 'Required parameter missing: delete > delete > authInfo > pw [pw]'
response[:results][1][:result_code].should == '2003' response[:results][1][:result_code].should == '2003'
response[:results][2][:msg].should == response[:results][2][:msg].should ==
'Required parameter missing: extension > extdata > legalDocument' 'Required parameter missing: extension > extdata > legalDocument [legal_document]'
response[:results][2][:result_code].should == '2003' response[:results][2][:result_code].should == '2003'
response[:results].count.should == 3 response[:results].count.should == 3
end end
@ -278,7 +294,7 @@ describe 'EPP Contact', epp: true do
@domain.owner_contact.address.present?.should == true @domain.owner_contact.address.present?.should == true
response = delete_request response = delete_request
response[:msg].should == 'Object association prohibits operation' response[:msg].should == 'Object association prohibits operation [domains]'
response[:result_code].should == '2305' response[:result_code].should == '2305'
response[:results].count.should == 1 response[:results].count.should == 1
@ -308,7 +324,7 @@ describe 'EPP Contact', epp: true do
it 'fails if request is invalid' do it 'fails if request is invalid' do
response = epp_plain_request(@epp_xml.check, :xml) response = epp_plain_request(@epp_xml.check, :xml)
response[:results][0][:msg].should == 'Required parameter missing: check > check > id' response[:results][0][:msg].should == 'Required parameter missing: check > check > id [id]'
response[:results][0][:result_code].should == '2003' response[:results][0][:result_code].should == '2003'
response[:results].count.should == 1 response[:results].count.should == 1
end end
@ -343,7 +359,7 @@ describe 'EPP Contact', epp: true do
it 'fails if request invalid' do it 'fails if request invalid' do
response = epp_plain_request(@epp_xml.info, :xml) response = epp_plain_request(@epp_xml.info, :xml)
response[:results][0][:msg].should == response[:results][0][:msg].should ==
'Required parameter missing: info > info > id' 'Required parameter missing: info > info > id [id]'
response[:results][0][:result_code].should == '2003' response[:results][0][:result_code].should == '2003'
response[:results].count.should == 1 response[:results].count.should == 1
end end

View file

@ -11,8 +11,6 @@ describe 'EPP Domain', epp: true do
login_as :registrar1 login_as :registrar1
Contact.skip_callback(:create, :before, :generate_code)
Fabricate(:contact, code: 'citizen_1234') Fabricate(:contact, code: 'citizen_1234')
Fabricate(:contact, code: 'sh8013') Fabricate(:contact, code: 'sh8013')
Fabricate(:contact, code: 'sh801333') Fabricate(:contact, code: 'sh801333')
@ -61,16 +59,20 @@ describe 'EPP Domain', epp: true do
response = epp_plain_request(xml, :xml) response = epp_plain_request(xml, :xml)
response[:results][0][:result_code].should == '2003' response[:results][0][:result_code].should == '2003'
response[:results][0][:msg].should == 'Required parameter missing: create > create > ns' response[:results][0][:msg].should ==
'Required parameter missing: create > create > ns [ns]'
response[:results][1][:result_code].should == '2003' response[:results][1][:result_code].should == '2003'
response[:results][1][:msg].should == 'Required parameter missing: create > create > registrant' response[:results][1][:msg].should ==
'Required parameter missing: create > create > registrant [registrant]'
response[:results][2][:result_code].should == '2003' response[:results][2][:result_code].should == '2003'
response[:results][2][:msg].should == 'Required parameter missing: create > create > ns > hostAttr' response[:results][2][:msg].should ==
'Required parameter missing: create > create > ns > hostAttr [host_attr]'
response[:results][3][:result_code].should == '2003' response[:results][3][:result_code].should == '2003'
response[:results][3][:msg].should == 'Required parameter missing: extension > extdata > legalDocument' response[:results][3][:msg].should ==
'Required parameter missing: extension > extdata > legalDocument [legal_document]'
end end
context 'with citizen as an owner' do context 'with citizen as an owner' do
@ -169,7 +171,7 @@ describe 'EPP Domain', epp: true do
response = epp_plain_request(xml, :xml) response = epp_plain_request(xml, :xml)
response[:result_code].should == '2306' response[:result_code].should == '2306'
response[:msg].should == 'IPv4 is missing' response[:msg].should == 'IPv4 is missing [ipv4]'
end end
# it 'does not create duplicate domain' do # it 'does not create duplicate domain' do
@ -191,7 +193,7 @@ describe 'EPP Domain', epp: true do
response = epp_plain_request(xml, :xml) response = epp_plain_request(xml, :xml)
response[:result_code].should == '2302' response[:result_code].should == '2302'
response[:msg].should == 'Domain name is reserved or restricted' response[:msg].should == 'Domain name is reserved or restricted [name_dirty]'
response[:clTRID].should == 'ABC-12345' response[:clTRID].should == 'ABC-12345'
end end
@ -200,7 +202,8 @@ describe 'EPP Domain', epp: true do
response = epp_plain_request(xml, :xml) response = epp_plain_request(xml, :xml)
response[:results][0][:result_code].should == '2003' response[:results][0][:result_code].should == '2003'
response[:results][0][:msg].should == 'Required parameter missing: create > create > registrant' response[:results][0][:msg].should ==
'Required parameter missing: create > create > registrant [registrant]'
end end
it 'does not create domain without nameservers' do it 'does not create domain without nameservers' do
@ -208,11 +211,11 @@ describe 'EPP Domain', epp: true do
response = epp_plain_request(xml, :xml) response = epp_plain_request(xml, :xml)
response[:results][0][:msg].should == response[:results][0][:msg].should ==
'Required parameter missing: create > create > ns' 'Required parameter missing: create > create > ns [ns]'
response[:results][0][:result_code].should == '2003' response[:results][0][:result_code].should == '2003'
response[:results][1][:msg].should == response[:results][1][:msg].should ==
'Required parameter missing: create > create > ns > hostAttr' 'Required parameter missing: create > create > ns > hostAttr [host_attr]'
response[:results][1][:result_code].should == '2003' response[:results][1][:result_code].should == '2003'
response[:results].count.should == 2 response[:results].count.should == 2
@ -234,7 +237,7 @@ describe 'EPP Domain', epp: true do
response = epp_plain_request(xml, :xml) response = epp_plain_request(xml, :xml)
response[:result_code].should == '2004' response[:result_code].should == '2004'
response[:msg].should == 'Nameservers count must be between 2-11' response[:msg].should == 'Nameservers count must be between 2-11 [nameservers]'
end end
it 'returns error when invalid nameservers are present' do it 'returns error when invalid nameservers are present' do
@ -254,8 +257,8 @@ describe 'EPP Domain', epp: true do
}) })
response = epp_plain_request(xml, :xml) response = epp_plain_request(xml, :xml)
response[:msg].should == 'Hostname is invalid [hostname]'
response[:result_code].should == '2005' response[:result_code].should == '2005'
response[:msg].should == 'Hostname is invalid'
end end
it 'checks hostAttr presence' do it 'checks hostAttr presence' do
@ -271,8 +274,8 @@ describe 'EPP Domain', epp: true do
}) })
response = epp_plain_request(xml, :xml) response = epp_plain_request(xml, :xml)
response[:msg].should == 'Required parameter missing: create > create > ns > hostAttr [host_attr]'
response[:result_code].should == '2003' response[:result_code].should == '2003'
response[:msg].should == 'Required parameter missing: create > create > ns > hostAttr'
end end
it 'creates domain with nameservers with ips' do it 'creates domain with nameservers with ips' do
@ -288,10 +291,10 @@ describe 'EPP Domain', epp: true do
nameserver_count = Nameserver.count nameserver_count = Nameserver.count
response = epp_plain_request(domain_create_with_invalid_ns_ip_xml, :xml) response = epp_plain_request(domain_create_with_invalid_ns_ip_xml, :xml)
response[:results][0][:result_code].should == '2005' response[:results][0][:result_code].should == '2005'
response[:results][0][:msg].should == 'IPv4 is invalid' response[:results][0][:msg].should == 'IPv4 is invalid [ipv4]'
response[:results][0][:value].should == '192.0.2.2.invalid' response[:results][0][:value].should == '192.0.2.2.invalid'
response[:results][1][:result_code].should == '2005' response[:results][1][:result_code].should == '2005'
response[:results][1][:msg].should == 'IPv6 is invalid' response[:results][1][:msg].should == 'IPv6 is invalid [ipv6]'
response[:results][1][:value].should == 'INVALID_IPV6' response[:results][1][:value].should == 'INVALID_IPV6'
# ensure nothing gets saved to db: # ensure nothing gets saved to db:
Domain.count.should == domain_count Domain.count.should == domain_count
@ -314,7 +317,7 @@ describe 'EPP Domain', epp: true do
response = epp_plain_request(xml, :xml) response = epp_plain_request(xml, :xml)
response[:results][0][:result_code].should == '2004' response[:results][0][:result_code].should == '2004'
response[:results][0][:msg].should == 'Period must add up to 1, 2 or 3 years' response[:results][0][:msg].should == 'Period must add up to 1, 2 or 3 years [period]'
response[:results][0][:value].should == '367' response[:results][0][:value].should == '367'
end end
@ -399,24 +402,25 @@ describe 'EPP Domain', epp: true do
response = epp_plain_request(xml, :xml) response = epp_plain_request(xml, :xml)
response[:results][0][:msg].should == 'Valid algorithms are: 3, 5, 6, 7, 8, 252, 253, 254, 255' response[:results][0][:msg].should ==
'Valid algorithms are: 3, 5, 6, 7, 8, 252, 253, 254, 255 [alg]'
response[:results][0][:value].should == '9' response[:results][0][:value].should == '9'
response[:results][1][:msg].should == 'Valid protocols are: 3' response[:results][1][:msg].should == 'Valid protocols are: 3 [protocol]'
response[:results][1][:value].should == '4' response[:results][1][:value].should == '4'
response[:results][2][:msg].should == 'Valid flags are: 0, 256, 257' response[:results][2][:msg].should == 'Valid flags are: 0, 256, 257 [flags]'
response[:results][2][:value].should == '250' response[:results][2][:value].should == '250'
response[:results][3][:msg].should == 'Valid algorithms are: 3, 5, 6, 7, 8, 252, 253, 254, 255' response[:results][3][:msg].should == 'Valid algorithms are: 3, 5, 6, 7, 8, 252, 253, 254, 255 [alg]'
response[:results][3][:value].should == '10' response[:results][3][:value].should == '10'
response[:results][4][:msg].should == 'Valid flags are: 0, 256, 257' response[:results][4][:msg].should == 'Valid flags are: 0, 256, 257 [flags]'
response[:results][4][:value].should == '1' response[:results][4][:value].should == '1'
response[:results][5][:msg].should == 'Public key is missing' response[:results][5][:msg].should == 'Public key is missing [public_key]'
response[:results][6][:msg].should == 'Valid protocols are: 3' response[:results][6][:msg].should == 'Valid protocols are: 3 [protocol]'
response[:results][6][:value].should == '5' response[:results][6][:value].should == '5'
end end
@ -443,7 +447,7 @@ describe 'EPP Domain', epp: true do
response = epp_plain_request(xml, :xml) response = epp_plain_request(xml, :xml)
response[:result_code].should == '2302' response[:result_code].should == '2302'
response[:msg].should == 'Public key already exists' response[:msg].should == 'Public key already exists [public_key]'
response[:results][0][:value].should == '700b97b591ed27ec2590d19f06f88bba700b97b591ed27ec2590d19f' response[:results][0][:value].should == '700b97b591ed27ec2590d19f06f88bba700b97b591ed27ec2590d19f'
end end
@ -472,7 +476,7 @@ describe 'EPP Domain', epp: true do
response = epp_plain_request(xml, :xml) response = epp_plain_request(xml, :xml)
response[:result_code].should == '2004' response[:result_code].should == '2004'
response[:msg].should == 'DNS keys count must be between 0-1' response[:msg].should == 'DNS keys count must be between 0-1 [dnskeys]'
create_settings create_settings
end end
@ -669,7 +673,7 @@ describe 'EPP Domain', epp: true do
}) })
response = epp_plain_request(xml, :xml) response = epp_plain_request(xml, :xml)
response[:msg].should == 'Admin contacts count must be between 1-10' response[:msg].should == 'Admin contacts count must be between 1-10 [admin_contacts]'
response[:result_code].should == '2004' response[:result_code].should == '2004'
response[:clTRID].should == 'ABC-12345' response[:clTRID].should == 'ABC-12345'
@ -861,7 +865,8 @@ describe 'EPP Domain', epp: true do
login_as :registrar2 do login_as :registrar2 do
response = epp_plain_request(xml, :xml) response = epp_plain_request(xml, :xml)
response[:result_code].should == '2003' response[:result_code].should == '2003'
response[:msg].should == 'Required parameter missing: extension > extdata > legalDocument' response[:msg].should ==
'Required parameter missing: extension > extdata > legalDocument [legal_document]'
end end
end end
@ -978,7 +983,7 @@ describe 'EPP Domain', epp: true do
response = epp_plain_request(xml, :xml) response = epp_plain_request(xml, :xml)
response[:result_code].should == '2201' response[:result_code].should == '2201'
response[:msg].should == 'Authorization error' response[:msg].should == 'Authorization error [auth_info]'
end end
it 'ignores transfer when owner registrar requests transfer' do it 'ignores transfer when owner registrar requests transfer' do
@ -1025,7 +1030,7 @@ describe 'EPP Domain', epp: true do
epp_plain_request(xml, :xml) # transfer domain epp_plain_request(xml, :xml) # transfer domain
response = epp_plain_request(xml, :xml) # attempt second transfer response = epp_plain_request(xml, :xml) # attempt second transfer
response[:result_code].should == '2201' response[:result_code].should == '2201'
response[:msg].should == 'Authorization error' response[:msg].should == 'Authorization error [auth_info]'
end end
end end
@ -1128,27 +1133,27 @@ describe 'EPP Domain', epp: true do
response = epp_plain_request(xml, :xml) response = epp_plain_request(xml, :xml)
response[:results][0][:result_code].should == '2302' response[:results][0][:result_code].should == '2302'
response[:results][0][:msg].should == 'Nameserver already exists on this domain' response[:results][0][:msg].should == 'Nameserver already exists on this domain [hostname]'
response[:results][0][:value].should == 'ns1.example.com' response[:results][0][:value].should == 'ns1.example.com'
response[:results][1][:result_code].should == '2302' response[:results][1][:result_code].should == '2302'
response[:results][1][:msg].should == 'Nameserver already exists on this domain' response[:results][1][:msg].should == 'Nameserver already exists on this domain [hostname]'
response[:results][1][:value].should == 'ns2.example.com' response[:results][1][:value].should == 'ns2.example.com'
response[:results][2][:result_code].should == '2302' response[:results][2][:result_code].should == '2302'
response[:results][2][:msg].should == 'Contact already exists on this domain' response[:results][2][:msg].should == 'Contact already exists on this domain [contact_code_cache]'
response[:results][2][:value].should == 'mak21' response[:results][2][:value].should == 'mak21'
response[:results][3][:msg].should == 'Status already exists on this domain' response[:results][3][:msg].should == 'Status already exists on this domain [value]'
response[:results][3][:value].should == 'clientHold' response[:results][3][:value].should == 'clientHold'
response[:results][4][:msg].should == 'Status already exists on this domain' response[:results][4][:msg].should == 'Status already exists on this domain [value]'
response[:results][4][:value].should == 'clientUpdateProhibited' response[:results][4][:value].should == 'clientUpdateProhibited'
response[:results][5][:msg].should == 'Public key already exists' response[:results][5][:msg].should == 'Public key already exists [public_key]'
response[:results][5][:value].should == '700b97b591ed27ec2590d19f06f88bba700b97b591ed27ec2590d19f' response[:results][5][:value].should == '700b97b591ed27ec2590d19f06f88bba700b97b591ed27ec2590d19f'
response[:results][6][:msg].should == 'Public key already exists' response[:results][6][:msg].should == 'Public key already exists [public_key]'
response[:results][6][:value].should == '841936717ae427ace63c28d04918569a841936717ae427ace63c28d0' response[:results][6][:value].should == '841936717ae427ace63c28d04918569a841936717ae427ace63c28d0'
d.domain_statuses.count.should == 2 d.domain_statuses.count.should == 2
@ -1300,11 +1305,11 @@ describe 'EPP Domain', epp: true do
response = epp_plain_request(xml, :xml) response = epp_plain_request(xml, :xml)
response[:results][0][:result_code].should == '2302' response[:results][0][:result_code].should == '2302'
response[:results][0][:msg].should == 'Nameserver already exists on this domain' response[:results][0][:msg].should == 'Nameserver already exists on this domain [hostname]'
response[:results][0][:value].should == n.hostname response[:results][0][:value].should == n.hostname
response[:results][1][:result_code].should == '2302' response[:results][1][:result_code].should == '2302'
response[:results][1][:msg].should == 'Contact already exists on this domain' response[:results][1][:msg].should == 'Contact already exists on this domain [contact_code_cache]'
response[:results][1][:value].should == c.code response[:results][1][:value].should == c.code
end end
@ -1317,7 +1322,8 @@ describe 'EPP Domain', epp: true do
} }
response = epp_plain_request(domain_update_xml(xml_params), :xml) response = epp_plain_request(domain_update_xml(xml_params), :xml)
response[:results][0][:msg].should == 'Required parameter missing: extension > extdata > legalDocument' response[:results][0][:msg].should ==
'Required parameter missing: extension > extdata > legalDocument [legal_document]'
response[:results][0][:result_code].should == '2003' response[:results][0][:result_code].should == '2003'
end end
@ -1374,7 +1380,7 @@ describe 'EPP Domain', epp: true do
response = epp_plain_request(xml, :xml) response = epp_plain_request(xml, :xml)
response[:results][0][:result_code].should == '2004' response[:results][0][:result_code].should == '2004'
response[:results][0][:msg].should == 'Period must add up to 1, 2 or 3 years' response[:results][0][:msg].should == 'Period must add up to 1, 2 or 3 years [period]'
response[:results][0][:value].should == '4' response[:results][0][:value].should == '4'
end end
@ -1526,7 +1532,8 @@ describe 'EPP Domain', epp: true do
it 'does not delete domain without legal document' do it 'does not delete domain without legal document' do
response = epp_plain_request(@epp_xml.domain.delete(name: { value: 'example.ee' }), :xml) response = epp_plain_request(@epp_xml.domain.delete(name: { value: 'example.ee' }), :xml)
response[:result_code].should == '2003' response[:result_code].should == '2003'
response[:msg].should == 'Required parameter missing: extension > extdata > legalDocument' response[:msg].should ==
'Required parameter missing: extension > extdata > legalDocument [legal_document]'
end end
### CHECK ### ### CHECK ###

View file

@ -64,7 +64,7 @@ describe 'EPP Keyrelay', epp: true do
}) })
response = epp_plain_request(xml, :xml) response = epp_plain_request(xml, :xml)
response[:msg].should == 'Required parameter missing: keyrelay > keyData > flags' response[:msg].should == 'Required parameter missing: keyrelay > keyData > flags [flags]'
@registrar2.messages.queued.count.should == msg_count @registrar2.messages.queued.count.should == msg_count
end end

View file

@ -35,6 +35,7 @@ describe 'EPP Session', epp: true do
inactive = @epp_xml.session.login(clID: { value: 'inactive-user' }, pw: { value: 'ghyt9e4fu' }) inactive = @epp_xml.session.login(clID: { value: 'inactive-user' }, pw: { value: 'ghyt9e4fu' })
response = epp_plain_request(inactive, :xml) response = epp_plain_request(inactive, :xml)
response[:msg].should == 'Authentication error; server closing connection'
response[:result_code].should == '2501' response[:result_code].should == '2501'
end end

View file

@ -1,13 +1,16 @@
Fabricator(:contact) do Fabricator(:contact) do
code { "sh#{Faker::Number.number(8)}" } code { "sh#{Faker::Number.number(8)}" }
auth_info 'password'
name { sequence(:name) { |i| "#{Faker::Name.name}#{i}" } } name { sequence(:name) { |i| "#{Faker::Name.name}#{i}" } }
phone '+372.12345678' phone '+372.12345678'
email Faker::Internet.email email Faker::Internet.email
ident '37605030299' ident '37605030299'
ident_type 'priv' ident_type 'priv'
ident_country_code 'EE' ident_country_code 'EE'
auth_info 'ccds4324pok'
address address
registrar { Fabricate(:registrar, name: Faker::Company.name, reg_no: Faker::Company.duns_number) } registrar { Fabricate(:registrar, name: Faker::Company.name, reg_no: Faker::Company.duns_number) }
disclosure { Fabricate(:contact_disclosure) } disclosure { Fabricate(:contact_disclosure) }
# rubocop: disable Style/SymbolProc
after_validation { |c| c.disable_generate_auth_info! }
# rubocop: enamble Style/SymbolProc
end end

View file

@ -91,6 +91,12 @@ describe Contact do
it 'should not have any versions' do it 'should not have any versions' do
@contact.versions.should == [] @contact.versions.should == []
end end
it 'should not accept long code' do
@contact.code = 'verylongcode' * 100
@contact.valid?
@contact.errors[:code].should == ['is too long (maximum is 100 characters)']
end
end end
context 'with valid attributes' do context 'with valid attributes' do
@ -130,6 +136,17 @@ describe Contact do
@contact.errors.full_messages.should match_array([]) @contact.errors.full_messages.should match_array([])
end end
it 'should not accept new custom code' do
old_code = @contact.code
@contact.code = 'CID:REG1:12345'
@contact.save.should == true
@contact.code.should == old_code
end
it 'should have static password' do
@contact.auth_info.should == 'password'
end
context 'as birthday' do context 'as birthday' do
before :all do before :all do
@contact.ident_type = 'birthday' @contact.ident_type = 'birthday'
@ -182,20 +199,56 @@ describe Contact do
end end
context 'after create' do context 'after create' do
it 'should generate a new code and password' do it 'should not generate a new code when code is present' do
@contact = Fabricate.build(:contact, code: '123asd', auth_info: 'qwe321') @contact = Fabricate.build(:contact, code: '123asd', auth_info: 'qwe321')
@contact.code.should == '123asd' @contact.code.should == '123asd'
@contact.save.should == true
@contact.code.should == '123asd'
end
it 'should generate a new password' do
@contact = Fabricate.build(:contact, code: '123asd', auth_info: 'qwe321')
@contact.auth_info.should == 'qwe321' @contact.auth_info.should == 'qwe321'
@contact.save! @contact.save.should == true
@contact.code.should_not == '123asd'
@contact.auth_info.should_not == 'qwe321' @contact.auth_info.should_not == 'qwe321'
end end
it 'should not allow same code' do
@double_contact = Fabricate.build(:contact, code: @contact.code)
@double_contact.valid?
@double_contact.errors.full_messages.should == ["Code Contact id already exists"]
end
it 'should allow supported code format' do
@contact = Fabricate.build(:contact, code: 'CID:REG1:12345')
@contact.valid?
@contact.errors.full_messages.should == []
end
it 'should not allow unsupported characters in code' do
@contact = Fabricate.build(:contact, code: 'unsupported!ÄÖÜ~?')
@contact.valid?
@contact.errors.full_messages.should == ['Code is invalid']
end
it 'should generate code if empty code is given' do
@contact = Fabricate(:contact, code: '')
@contact.code.should_not == ''
end
it 'should not allow empty spaces as code' do
@contact = Fabricate.build(:contact, code: ' ')
@contact.valid?
@contact.errors.full_messages.should == ['Code is invalid']
end
end end
context 'after update' do context 'after update' do
before :all do before :all do
@contact.code = '123asd' @contact = Fabricate.build(:contact, code: '123asd', auth_info: 'qwe321')
@contact.auth_info = 'qwe321' @contact.save
@contact.code.should == '123asd'
@auth_info = @contact.auth_info
end end
it 'should not generate new code' do it 'should not generate new code' do
@ -205,7 +258,7 @@ describe Contact do
it 'should not generate new auth_info' do it 'should not generate new auth_info' do
@contact.update_attributes(name: 'fvrsgbqevciherot23') @contact.update_attributes(name: 'fvrsgbqevciherot23')
@contact.auth_info.should == 'qwe321' @contact.auth_info.should == @auth_info
end end
end end
end end

View file

@ -28,6 +28,10 @@ describe Registrar do
@registrar.errors[:email].should == ['is invalid'] @registrar.errors[:email].should == ['is invalid']
@registrar.errors[:billing_email].should == ['is invalid'] @registrar.errors[:billing_email].should == ['is invalid']
end end
it 'should not have valid code' do
@registrar.code.should == nil
end
end end
context 'with valid attributes' do context 'with valid attributes' do
@ -59,5 +63,26 @@ describe Registrar do
it 'should return full address' do it 'should return full address' do
@registrar.address.should == 'Street 999, Town, County, Postal' @registrar.address.should == 'Street 999, Town, County, Postal'
end end
it 'should have code' do
@registrar.code.should =~ /registrar/
end
it 'should not be able to change code' do
@registrar.code = 'not-updated'
@registrar.code.should =~ /registrar/
end
it 'should automatically add next code if original is taken' do
@registrar = Fabricate(:registrar, name: 'uniq')
@registrar.name = 'New name'
@registrar.code.should == 'uniq'
@registrar.save
@new_registrar = Fabricate.build(:registrar, name: 'uniq')
@new_registrar.valid?
@new_registrar.errors.full_messages.should == []
@new_registrar.code.should == 'uniq1'
end
end end
end end