diff --git a/README.md b/README.md index c3fe45972..4b3c5c8d6 100644 --- a/README.md +++ b/README.md @@ -20,8 +20,8 @@ Documentation ### Updating documentation -AUTODOC=true rspec spec/requests -EPP_DOC=true rspec spec/epp --tag epp --require support/epp_doc.rb --format EppDoc > doc/epp-examples.md + AUTODOC=true rspec spec/requests + EPP_DOC=true rspec spec/epp --tag epp --require support/epp_doc.rb --format EppDoc > doc/epp-examples.md Installation ------------ @@ -32,41 +32,41 @@ Registry based on Rails 4 installation (rbenv install is under Debian build doc) Manual demo install and database setup: -cd /home/registry -git clone git@github.com:internetee/registry.git demo-registry -cd demo-registry -rbenv local 2.2.2 -bundle -cp config/application-example.yml config/application.yml # and edit it -cp config/database-example.yml config/database.yml # and edit it -bundle exec rake db:all:setup # for production, please follow deployment howto -bundle exec rake assets:precompile + cd /home/registry + git clone git@github.com:internetee/registry.git demo-registry + cd demo-registry + rbenv local 2.2.2 + bundle + cp config/application-example.yml config/application.yml # and edit it + cp config/database-example.yml config/database.yml # and edit it + bundle exec rake db:all:setup # for production, please follow deployment howto + bundle exec rake assets:precompile ### Apache with patched mod_epp (Debian 7/Ubuntu 14.04 LTS) -sudo apt-get install apache2 + sudo apt-get install apache2 -sudo apt-get install apache2-threaded-dev # needed to compile mod_epp -wget sourceforge.net/projects/aepps/files/mod_epp/1.10/mod_epp-1.10.tar.gz -tar -xzvf mod_epp-1.10.tar.gz -cd mod_epp-1.10 + sudo apt-get install apache2-threaded-dev # needed to compile mod_epp + wget sourceforge.net/projects/aepps/files/mod_epp/1.10/mod_epp-1.10.tar.gz + tar -xzvf mod_epp-1.10.tar.gz + cd mod_epp-1.10 Patch mod_epp for Rack. Beacause Rack multipart parser expects specifically formatted content boundaries, the mod_epp needs to be modified before building: -wget https://github.com/internetee/registry/raw/master/doc/patches/mod_epp_1.10-rack-friendly.patch -wget https://raw.githubusercontent.com/domify/registry/master/doc/patches/mod_epp_1.10-frame-size.patch -patch < mod_epp_1.10-rack-friendly.patch -patch < mod_epp_1.10-frame-size.patch -sudo apxs2 -a -c -i mod_epp.c + wget https://github.com/internetee/registry/raw/master/doc/patches/mod_epp_1.10-rack-friendly.patch + wget https://raw.githubusercontent.com/domify/registry/master/doc/patches/mod_epp_1.10-frame-size.patch + patch < mod_epp_1.10-rack-friendly.patch + patch < mod_epp_1.10-frame-size.patch + sudo apxs2 -a -c -i mod_epp.c Enable ssl: -sudo a2enmod proxy_http -sudo mkdir /etc/apache2/ssl -sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/apache2/ssl/apache.key -out /etc/apache2/ssl/apache.crt -sudo a2enmod ssl -sudo nano /etc/apache2/sites-enabled/epp_ssl.conf + sudo a2enmod proxy_http + sudo mkdir /etc/apache2/ssl + sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/apache2/ssl/apache.key -out /etc/apache2/ssl/apache.crt + sudo a2enmod ssl + sudo nano /etc/apache2/sites-enabled/epp_ssl.conf For Apache, registry admin goes to port 443 in production, /etc/apache2/sites-enabled/registry.conf short example: diff --git a/app/api/repp/api.rb b/app/api/repp/api.rb index e467534f0..8a2ac761f 100644 --- a/app/api/repp/api.rb +++ b/app/api/repp/api.rb @@ -8,6 +8,10 @@ module Repp end before do + unless Rails.env.development? + error! I18n.t('ip_is_not_whitelisted'), 401 unless @current_user.registrar.repp_ip_white?(request.ip) + end + next if Rails.env.test? || Rails.env.development? message = 'Certificate mismatch! Cert common name should be:' request_name = env['HTTP_SSL_CLIENT_S_DN_CN'] @@ -18,6 +22,7 @@ module Repp else error! "#{message} #{@current_user.username}", 401 if @current_user.username != request_name end + end helpers do diff --git a/app/controllers/admin/white_ips_controller.rb b/app/controllers/admin/white_ips_controller.rb new file mode 100644 index 000000000..7c0ecb184 --- /dev/null +++ b/app/controllers/admin/white_ips_controller.rb @@ -0,0 +1,56 @@ +class Admin::WhiteIpsController < AdminController + load_and_authorize_resource + + before_action :set_registrar, only: [:new, :show, :edit, :destroy, :update] + + def new + @white_ip = WhiteIp.new(registrar: @registrar) + end + + def show; end + + def edit; end + + def destroy + if @white_ip.destroy + flash[:notice] = I18n.t('record_deleted') + redirect_to admin_registrar_path(@registrar) + else + flash.now[:alert] = I18n.t('failed_to_delete_record') + render 'show' + end + end + + def create + @white_ip = WhiteIp.new(white_ip_params) + @registrar = @white_ip.registrar + + if @white_ip.save + flash[:notice] = I18n.t('record_created') + redirect_to [:admin, @registrar, @white_ip] + else + flash.now[:alert] = I18n.t('failed_to_create_record') + render 'new' + end + end + + def update + if @white_ip.update(white_ip_params) + flash[:notice] = I18n.t('record_updated') + redirect_to [:admin, @registrar, @white_ip] + else + flash.now[:alert] = I18n.t('failed_to_update_record') + render 'edit' + end + end + + private + + def set_registrar + @registrar = Registrar.find_by(id: params[:registrar_id]) + end + + def white_ip_params + params.require(:white_ip).permit(:ipv4, :ipv6, :interface, :registrar_id) + end +end diff --git a/app/controllers/epp/sessions_controller.rb b/app/controllers/epp/sessions_controller.rb index 47d10dbc2..96197835c 100644 --- a/app/controllers/epp/sessions_controller.rb +++ b/app/controllers/epp/sessions_controller.rb @@ -18,7 +18,7 @@ class Epp::SessionsController < EppController @api_user = ApiUser.find_by(login_params) end - if @api_user.try(:active) && cert_valid + if @api_user.try(:active) && cert_valid && ip_white? if parsed_frame.css('newPW').first unless @api_user.update(password: parsed_frame.css('newPW').first.text) response.headers['X-EPP-Returncode'] = '2200' @@ -33,6 +33,17 @@ class Epp::SessionsController < EppController render_epp_response('login_fail') end end + + def ip_white? + if @api_user + unless @api_user.registrar.epp_ip_white?(request.ip) + @msg = t('ip_is_not_whitelisted') + return false + end + end + true + end + # rubocop: enable Metrics/PerceivedComplexity # rubocop: enable Metrics/CyclomaticComplexity diff --git a/app/controllers/epp_controller.rb b/app/controllers/epp_controller.rb index 1cf54559e..c27ce1e6b 100644 --- a/app/controllers/epp_controller.rb +++ b/app/controllers/epp_controller.rb @@ -236,6 +236,8 @@ class EppController < ApplicationController end # rubocop: enable Style/PredicateName + # rubocop: disable Metrics/PerceivedComplexity + # rubocop: disable Metrics/CyclomaticComplexity def write_to_epp_log # return nil if EPP_LOG_ENABLED request_command = params[:command] || params[:action] # error receives :command, other methods receive :action @@ -257,4 +259,6 @@ class EppController < ApplicationController ip: request.ip }) end + # rubocop: enable Metrics/PerceivedComplexity + # rubocop: enable Metrics/CyclomaticComplexity end diff --git a/app/controllers/registrant/domain_update_confirms_controller.rb b/app/controllers/registrant/domain_update_confirms_controller.rb index 7cdcd3f4b..9830b5331 100644 --- a/app/controllers/registrant/domain_update_confirms_controller.rb +++ b/app/controllers/registrant/domain_update_confirms_controller.rb @@ -8,6 +8,8 @@ class Registrant::DomainUpdateConfirmsController < RegistrantController @domain = nil unless @domain.registrant_update_confirmable?(params[:token]) end + # rubocop: disable Metrics/PerceivedComplexity + # rubocop: disable Metrics/CyclomaticComplexity def update @domain = Domain.find(params[:id]) unless @domain.registrant_update_confirmable?(params[:token]) @@ -37,4 +39,6 @@ class Registrant::DomainUpdateConfirmsController < RegistrantController end end end + # rubocop: enable Metrics/PerceivedComplexity + # rubocop: enable Metrics/CyclomaticComplexity end diff --git a/app/controllers/registrar/domains_controller.rb b/app/controllers/registrar/domains_controller.rb index d7e7fa34a..5da13d089 100644 --- a/app/controllers/registrar/domains_controller.rb +++ b/app/controllers/registrar/domains_controller.rb @@ -24,7 +24,7 @@ class Registrar::DomainsController < Registrar::DeppController # EPP controller if response_ok? render 'info' else - flash[:alert] = t(:domain_not_found) + flash[:alert] = @data.css('msg').text redirect_to registrar_domains_url and return end end @@ -118,9 +118,9 @@ class Registrar::DomainsController < Registrar::DeppController # EPP controller end def init_contacts_autocomplete_map - @contacts_autocomplete_map ||= + @contacts_autocomplete_map ||= current_user.registrar.contacts.pluck(:name, :code).map { |c| ["#{c.second} #{c.first}", c.second] } - # @priv_contacts_autocomplete_map ||= + # @priv_contacts_autocomplete_map ||= # current_user.registrar.priv_contacts.pluck(:name, :code).map { |c| ["#{c.second} #{c.first}", c.second] } end end diff --git a/app/controllers/registrar/sessions_controller.rb b/app/controllers/registrar/sessions_controller.rb index 4490b0609..20f02e492 100644 --- a/app/controllers/registrar/sessions_controller.rb +++ b/app/controllers/registrar/sessions_controller.rb @@ -5,6 +5,8 @@ class Registrar::SessionsController < Devise::SessionsController false end + before_action :check_ip + def login @depp_user = Depp::User.new end @@ -139,4 +141,11 @@ class Registrar::SessionsController < Devise::SessionsController return User.new unless idc ApiUser.find_by(identity_code: idc) || User.new end + + private + + def check_ip + return if WhiteIp.registrar_ip_white?(request.ip) + render text: t('ip_is_not_whitelisted') and return + end end diff --git a/app/controllers/registrar_controller.rb b/app/controllers/registrar_controller.rb index e236814ad..8da12c3c1 100644 --- a/app/controllers/registrar_controller.rb +++ b/app/controllers/registrar_controller.rb @@ -1,5 +1,6 @@ class RegistrarController < ApplicationController - before_action :authenticate_user! + before_action :authenticate_user!, :check_ip + # before_action :check_ip layout 'registrar/application' include Registrar::ApplicationHelper @@ -9,6 +10,14 @@ class RegistrarController < ApplicationController false end + def check_ip + return unless current_user + return if current_user.registrar.registrar_ip_white?(request.ip) + flash[:alert] = t('ip_is_not_whitelisted') + sign_out(current_user) + redirect_to registrar_login_path and return + end + helper_method :head_title_sufix def head_title_sufix t(:registrar_head_title_sufix) diff --git a/app/models/ability.rb b/app/models/ability.rb index 3fa44e6b0..742463c37 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -98,6 +98,7 @@ class Ability can :manage, BankStatement can :manage, BankTransaction can :manage, Invoice + can :manage, WhiteIp can :read, ApiLog::EppLog can :read, ApiLog::ReppLog # can :index, :delayed_job diff --git a/app/models/certificate.rb b/app/models/certificate.rb index c5b18ebe7..a6fdd9b6b 100644 --- a/app/models/certificate.rb +++ b/app/models/certificate.rb @@ -14,9 +14,8 @@ class Certificate < ActiveRecord::Base validate :validate_csr_and_crt def validate_csr_and_crt - if csr.blank? && crt.blank? - errors.add(:base, I18n.t(:crt_or_csr_must_be_present)) - end + return if csr.present? || crt.present? + errors.add(:base, I18n.t(:crt_or_csr_must_be_present)) end def parsed_crt diff --git a/app/models/depp/user.rb b/app/models/depp/user.rb index 16eacb25b..fcce49c10 100644 --- a/app/models/depp/user.rb +++ b/app/models/depp/user.rb @@ -32,6 +32,8 @@ module Depp def request(xml) Nokogiri::XML(server.request(xml)).remove_namespaces! + rescue EppErrorResponse => e + Nokogiri::XML(e.response_xml.to_s).remove_namespaces! end def repp_request(path, params = {}) @@ -82,7 +84,7 @@ module Depp res = server.send_request(xml) if Nokogiri::XML(res).css('result').first['code'] != '1000' - errors.add(:base, :authorization_error) + errors.add(:base, Nokogiri::XML(res).css('result').text) end server.close_connection diff --git a/app/models/domain.rb b/app/models/domain.rb index 621f7f6e0..3355469f1 100644 --- a/app/models/domain.rb +++ b/app/models/domain.rb @@ -297,7 +297,6 @@ class Domain < ActiveRecord::Base registrant.try(:name) end - # rubocop:disable Lint/Loop def generate_auth_info begin diff --git a/app/models/registrar.rb b/app/models/registrar.rb index cb78c2ec4..7292b4bcb 100644 --- a/app/models/registrar.rb +++ b/app/models/registrar.rb @@ -10,6 +10,7 @@ class Registrar < ActiveRecord::Base has_many :nameservers, through: :domains has_many :whois_records has_many :priv_contacts, -> { privs }, class_name: 'Contact' + has_many :white_ips, dependent: :destroy validates :name, :reg_no, :country_code, :email, :code, presence: true validates :name, :reg_no, :reference_no, :code, uniqueness: true @@ -48,7 +49,7 @@ class Registrar < ActiveRecord::Base after_save :update_whois_records def update_whois_records - return true unless changed? && (changes.keys & WHOIS_TRIGGERS).present? + return true unless changed? && (changes.keys & WHOIS_TRIGGERS).present? whois_records.map(&:save) # slow currently end @@ -145,4 +146,20 @@ class Registrar < ActiveRecord::Base def code=(code) self[:code] = code.gsub(/[ :]/, '').upcase if new_record? && code.present? end + + def repp_ip_white?(ip) + white_ips.repp.pluck(:ipv4, :ipv6).flatten.include?(ip) || global_ip_white?(ip) + end + + def epp_ip_white?(ip) + white_ips.epp.pluck(:ipv4, :ipv6).flatten.include?(ip) || global_ip_white?(ip) + end + + def registrar_ip_white?(ip) + white_ips.registrar.pluck(:ipv4, :ipv6).flatten.include?(ip) || global_ip_white?(ip) + end + + def global_ip_white?(ip) + white_ips.global.pluck(:ipv4, :ipv6).flatten.include?(ip) + end end diff --git a/app/models/version/white_ip_version.rb b/app/models/version/white_ip_version.rb new file mode 100644 index 000000000..0f2ee8a53 --- /dev/null +++ b/app/models/version/white_ip_version.rb @@ -0,0 +1,5 @@ +class WhiteIpVersion < PaperTrail::Version + include VersionSession + self.table_name = :log_white_ips + self.sequence_name = :log_white_ips_id_seq +end diff --git a/app/models/white_ip.rb b/app/models/white_ip.rb new file mode 100644 index 000000000..b3f6e9922 --- /dev/null +++ b/app/models/white_ip.rb @@ -0,0 +1,40 @@ +class WhiteIp < ActiveRecord::Base + include Versions + belongs_to :registrar + + # rubocop: disable Metrics/LineLength + validates :ipv4, format: { with: /\A(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\z/, allow_blank: true } + validates :ipv6, format: { with: /(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]).){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))/, allow_blank: true } + # rubocop: enable Metrics/LineLength + + validate :validate_ipv4_and_ipv6 + def validate_ipv4_and_ipv6 + return if ipv4.present? || ipv6.present? + errors.add(:base, I18n.t(:ipv4_or_ipv6_must_be_present)) + end + + EPP = 'epp' + REPP = 'repp' + REGISTRAR = 'registrar' + GLOBAL = 'global' + + INTERFACES = [GLOBAL, EPP, REPP, REGISTRAR] + + scope :epp, -> { where(interface: EPP) } + scope :repp, -> { where(interface: REPP) } + scope :registrar, -> { where(interface: REGISTRAR) } + scope :global, -> { where(interface: GLOBAL) } + + class << self + def registrar_ip_white?(ip) + at = WhiteIp.arel_table + WhiteIp.where( + at[:interface].eq(REGISTRAR).or( + at[:interface].eq(GLOBAL) + ).and( + at[:ipv4].eq(ip) + ) + ) + end + end +end diff --git a/app/views/admin/registrars/show.haml b/app/views/admin/registrars/show.haml index c59401898..b0102344b 100644 --- a/app/views/admin/registrars/show.haml +++ b/app/views/admin/registrars/show.haml @@ -63,7 +63,7 @@ .pull-left = t(:api_users) .pull-right - = link_to(t(:create_new_api_user), new_admin_registrar_api_user_path(@registrar), class: 'btn btn-primary btn-xs') + = link_to(t(:create_new_api_user), new_admin_registrar_api_user_path(@registrar), class: 'btn btn-default btn-xs') .table-responsive %table.table.table-hover.table-bordered.table-condensed @@ -76,3 +76,26 @@ %tr %td= link_to(x, [:admin, x]) %td= x.active + +.row + .col-md-12 + #epp-users.panel.panel-default + .panel-heading.clearfix + .pull-left + = t(:white_ips) + .pull-right + = link_to(t(:create_new_white_ip), new_admin_registrar_white_ip_path(@registrar), class: 'btn btn-default btn-xs') + + .table-responsive + %table.table.table-hover.table-bordered.table-condensed + %thead + %tr + %th{class: 'col-xs-4'}= t(:ipv4) + %th{class: 'col-xs-6'}= t(:ipv6) + %th{class: 'col-xs-2'}= t(:interface) + %tbody + - @registrar.white_ips.order(:interface).each do |x| + %tr + %td= link_to(x.ipv4, [:admin, @registrar, x]) + %td= link_to(x.ipv6, [:admin, @registrar, x]) + %td= x.interface.upcase diff --git a/app/views/admin/white_ips/_form.haml b/app/views/admin/white_ips/_form.haml new file mode 100644 index 000000000..5432db9fa --- /dev/null +++ b/app/views/admin/white_ips/_form.haml @@ -0,0 +1,30 @@ += form_for([:admin, @registrar, @white_ip], html: {class: 'form-horizontal'}) do |f| + = render 'shared/full_errors', object: @white_ip + + .row + .col-md-8 + .form-group + .col-md-4.control-label + = f.label :registrar + .col-md-7 + = f.text_field(:registrar, class: 'form-control', disabled: :disabled) + = f.hidden_field(:registrar_id, class: 'js-registrar-id') + .form-group + .col-md-4.control-label + = f.label :ipv4 + .col-md-7 + = f.text_field(:ipv4, class: 'form-control', ipv4: true) + .form-group + .col-md-4.control-label + = f.label :ipv6 + .col-md-7 + = f.text_field(:ipv6, class: 'form-control', ipv6: true) + .form-group + .col-md-4.control-label + = f.label :interface + .col-md-7 + = f.select :interface, WhiteIp::INTERFACES.map {|x| [x.upcase, x]}, {}, class: 'form-control selectize' + %hr + .row + .col-md-8.text-right + = button_tag(t(:save), class: 'btn btn-primary') diff --git a/app/views/admin/white_ips/edit.haml b/app/views/admin/white_ips/edit.haml new file mode 100644 index 000000000..ace12a289 --- /dev/null +++ b/app/views/admin/white_ips/edit.haml @@ -0,0 +1,5 @@ +- content_for :actions do + = link_to(t(:back_to_registrar), admin_registrar_path(@registrar), class: 'btn btn-default') + += render 'shared/title', name: t(:edit_white_ip) += render 'form' diff --git a/app/views/admin/white_ips/new.haml b/app/views/admin/white_ips/new.haml new file mode 100644 index 000000000..99150a871 --- /dev/null +++ b/app/views/admin/white_ips/new.haml @@ -0,0 +1,5 @@ +- content_for :actions do + = link_to(t(:back_to_registrar), admin_registrar_path(@registrar), class: 'btn btn-default') + += render 'shared/title', name: t(:create_new_white_ip) += render 'form' diff --git a/app/views/admin/white_ips/show.haml b/app/views/admin/white_ips/show.haml new file mode 100644 index 000000000..da1da9616 --- /dev/null +++ b/app/views/admin/white_ips/show.haml @@ -0,0 +1,24 @@ +- content_for :actions do + = link_to(t(:edit), edit_admin_registrar_white_ip_path(@registrar, @white_ip), class: 'btn btn-primary') + = link_to(t(:delete), admin_registrar_white_ip_path(@registrar, @white_ip), + method: :delete, data: { confirm: t(:are_you_sure) }, class: 'btn btn-danger') += render 'shared/title', name: t('white_ip') + +.row + .col-md-12 + .panel.panel-default + .panel-heading + %h3.panel-title= t(:general) + .panel-body + %dl.dl-horizontal + %dt= t(:registrar) + %dd= link_to(@registrar, [:admin, @registrar]) + + %dt= t(:ipv4) + %dd= @white_ip.ipv4 + + %dt= t(:ipv6) + %dd= @white_ip.ipv6 + + %dt= t(:interface) + %dd= @white_ip.interface.upcase diff --git a/app/views/epp/sessions/login_fail.xml.builder b/app/views/epp/sessions/login_fail.xml.builder index 1deb05a1e..a76057270 100644 --- a/app/views/epp/sessions/login_fail.xml.builder +++ b/app/views/epp/sessions/login_fail.xml.builder @@ -1,7 +1,7 @@ xml.epp_head do xml.response do xml.result('code' => '2501') do - xml.msg('Authentication error; server closing connection') + xml.msg(@msg || 'Authentication error; server closing connection') end end diff --git a/bin/update-crl b/bin/update-crl deleted file mode 100755 index 202409988..000000000 --- a/bin/update-crl +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash - -CRL_PATH='/home/registry/registry/shared/ca/crl' - -mkdir -p $CRL_PATH/crl-temp -cd $CRL_PATH/crl-temp - -wget https://sk.ee/crls/esteid/esteid2007.crl -wget https://sk.ee/crls/juur/crl.crl -wget https://sk.ee/crls/eeccrca/eeccrca.crl -wget https://sk.ee/repository/crls/esteid2011.crl - -openssl crl -in esteid2007.crl -out esteid2007.crl -inform DER -openssl crl -in crl.crl -out crl.crl -inform DER -openssl crl -in eeccrca.crl -out eeccrca.crl -inform DER -openssl crl -in esteid2011.crl -out esteid2011.crl -inform DER - -ln -s crl.crl `openssl crl -hash -noout -in crl.crl`.r0 -ln -s esteid2007.crl `openssl crl -hash -noout -in esteid2007.crl`.r0 -ln -s eeccrca.crl `openssl crl -hash -noout -in eeccrca.crl`.r0 -ln -s esteid2011.crl `openssl crl -hash -noout -in esteid2011.crl`.r0 - -rm -rf ../*.crl ../*.r0 - -mv * .. -cd .. -rm -rf crl-temp -/etc/init.d/apache2 reload diff --git a/config/locales/en.yml b/config/locales/en.yml index b1c334c8c..c3bd4256e 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -225,6 +225,9 @@ en: state: 'State / Province' deposit: amount: 'Amount' + white_ip: + ipv4: 'IPv4' + ipv6: 'IPv6' errors: messages: @@ -560,8 +563,6 @@ en: code: 'Code' nameservers: 'Nameservers' hostname: 'Hostname' - ipv4: 'IPv4' - ipv6: 'IPv6' dnskeys: 'DNS Keys' flag: 'Flag' protocol: 'Protocol' @@ -772,6 +773,11 @@ en: not_valid_domain_verification_body: This could mean your verification has been expired or done already.

Please contact us if you think something is wrong. upload_crt: 'Upload CRT' crt_or_csr_must_be_present: 'CRT or CSR must be present' + white_ips: 'White IP-s' + create_new_white_ip: 'Create new white IP' + ipv4_or_ipv6_must_be_present: 'IPv4 or IPv6 must be present' + white_ip: 'White IP' + edit_white_ip: 'Edit white IP' confirm_domain_delete: 'Confirm domain delete' reject_domain_delete: 'Reject domain delete' confirm_domain_registrant_update: 'Confirm domain ownership change' @@ -780,7 +786,7 @@ en: domain_registrant_change_body: 'There is a request to change domain ownership. Before doing it we need your confirmation.' new_pending_registrant: 'New owner' current_registrant: 'Current owner' - registrant_domain_verification_failed: 'Domain verification not available' + registrant_domain_verification_failed: 'Domain verification not available' domain_registrant_change_confirmed_title: 'Domain owner change has been confirmed' domain_registrant_change_confirmed_body: 'You have successfully confirmed domain owner change.' registrant_domain_verification_confirmed: 'Domain owner change has successfully confirmed.' @@ -789,3 +795,4 @@ en: domain_registrant_change_rejected_body: 'You have rejected domain owner change.' registrant_domain_verification_rejected: 'Domain owner change has been rejected successfully.' registrant_domain_verification_rejected_failed: 'Something went wrong' + ip_is_not_whitelisted: 'IP is not whitelisted' diff --git a/config/routes.rb b/config/routes.rb index 70c991a7c..c8d4e0b0e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -181,8 +181,10 @@ Rails.application.routes.draw do end resources :settings + resources :registrars do resources :api_users + resources :white_ips collection do get :search end diff --git a/db/migrate/20150519115050_create_white_ip.rb b/db/migrate/20150519115050_create_white_ip.rb new file mode 100644 index 000000000..13a710f41 --- /dev/null +++ b/db/migrate/20150519115050_create_white_ip.rb @@ -0,0 +1,11 @@ +class CreateWhiteIp < ActiveRecord::Migration + def change + create_table :white_ips do |t| + t.integer :registrar_id + t.string :ipv4 + t.string :ipv6 + t.string :interface + t.timestamps + end + end +end diff --git a/db/migrate/20150519140853_create_white_ip_log.rb b/db/migrate/20150519140853_create_white_ip_log.rb new file mode 100644 index 000000000..b5f1e6e0b --- /dev/null +++ b/db/migrate/20150519140853_create_white_ip_log.rb @@ -0,0 +1,18 @@ +class CreateWhiteIpLog < ActiveRecord::Migration + def change + create_table :log_white_ips do |t| + t.string "item_type", null: false + t.integer "item_id", null: false + t.string "event", null: false + t.string "whodunnit" + t.json "object" + t.json "object_changes" + t.datetime "created_at" + t.string "session" + t.json "children" + end + + add_column :white_ips, :creator_str, :string + add_column :white_ips, :updator_str, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index c2666ade6..a34b0c750 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -797,6 +797,18 @@ ActiveRecord::Schema.define(version: 20150519144118) do add_index "log_users", ["item_type", "item_id"], name: "index_log_users_on_item_type_and_item_id", using: :btree add_index "log_users", ["whodunnit"], name: "index_log_users_on_whodunnit", using: :btree + create_table "log_white_ips", force: :cascade do |t| + t.string "item_type", null: false + t.integer "item_id", null: false + t.string "event", null: false + t.string "whodunnit" + t.json "object" + t.json "object_changes" + t.datetime "created_at" + t.string "session" + t.json "children" + end + create_table "log_zonefile_settings", force: :cascade do |t| t.string "item_type", null: false t.integer "item_id", null: false @@ -954,6 +966,17 @@ ActiveRecord::Schema.define(version: 20150519144118) do t.text "depricated_table_but_somehow_paper_trail_tests_fails_without_it" end + create_table "white_ips", force: :cascade do |t| + t.integer "registrar_id" + t.string "ipv4" + t.string "ipv6" + t.string "interface" + t.datetime "created_at" + t.datetime "updated_at" + t.string "creator_str" + t.string "updator_str" + end + create_table "whois_records", force: :cascade do |t| t.integer "domain_id" t.string "name" diff --git a/spec/epp/session_spec.rb b/spec/epp/session_spec.rb index 8fd1b2c67..ad1658710 100644 --- a/spec/epp/session_spec.rb +++ b/spec/epp/session_spec.rb @@ -39,6 +39,19 @@ describe 'EPP Session', epp: true do response[:result_code].should == '2501' end + it 'does not log in with ip that is not whitelisted' do + @registrar = Fabricate(:registrar, + { name: 'registrar123', reg_no: '1234', white_ips: [Fabricate(:white_ip_repp), Fabricate(:white_ip_registrar)] } + ) + Fabricate(:api_user, username: 'invalid-ip-user', registrar: @registrar) + + inactive = @epp_xml.session.login(clID: { value: 'invalid-ip-user' }, pw: { value: 'ghyt9e4fu' }) + response = epp_plain_request(inactive, :xml) + + response[:msg].should == 'IP is not whitelisted' + response[:result_code].should == '2501' + end + it 'prohibits further actions unless logged in' do response = epp_plain_request(@epp_xml.domain.create, :xml) response[:msg].should == 'You need to login first.' diff --git a/spec/fabricators/registrar_fabricator.rb b/spec/fabricators/registrar_fabricator.rb index 59fed19c5..09ee644e9 100644 --- a/spec/fabricators/registrar_fabricator.rb +++ b/spec/fabricators/registrar_fabricator.rb @@ -10,6 +10,7 @@ Fabricator(:registrar) do code { sequence(:code) { |i| "REGISTRAR#{i}" } } reference_no { sequence(:reference_no) { |i| "RF#{i}" } } accounts(count: 1) + white_ips { [Fabricate(:white_ip)] } end Fabricator(:registrar_with_no_account_activities, from: :registrar) do diff --git a/spec/fabricators/white_ip_fabricator.rb b/spec/fabricators/white_ip_fabricator.rb new file mode 100644 index 000000000..8c4783093 --- /dev/null +++ b/spec/fabricators/white_ip_fabricator.rb @@ -0,0 +1,16 @@ +Fabricator(:white_ip) do + ipv4 '127.0.0.1' + interface WhiteIp::GLOBAL +end + +Fabricator(:white_ip_repp, from: :white_ip) do + interface WhiteIp::REPP +end + +Fabricator(:white_ip_epp, from: :white_ip) do + interface WhiteIp::EPP +end + +Fabricator(:white_ip_registrar, from: :white_ip) do + interface WhiteIp::REGISTRAR +end diff --git a/spec/features/admin/api_user_spec.rb b/spec/features/admin/api_user_spec.rb index 36ba2a767..f37adc2b6 100644 --- a/spec/features/admin/api_user_spec.rb +++ b/spec/features/admin/api_user_spec.rb @@ -15,14 +15,14 @@ feature 'Api users', type: :feature do it 'should redirect to login path' do visit admin_api_user_url(@api_user) - + current_path.should == '/admin/login' end end context 'as logged in user' do - it 'should show index of contacts' do + it 'should show index of api users' do sign_in @user visit admin_api_users_url diff --git a/spec/features/admin/white_ip_spec.rb b/spec/features/admin/white_ip_spec.rb new file mode 100644 index 000000000..fb84b3d30 --- /dev/null +++ b/spec/features/admin/white_ip_spec.rb @@ -0,0 +1,63 @@ +require 'rails_helper' + +feature 'Api users', type: :feature do + before :all do + @user = Fabricate(:admin_user, username: 'user1', identity_code: '37810013087') + @registrar = Fabricate(:registrar) + end + + context 'as unknown user' do + it 'should redirect to login path' do + visit new_admin_registrar_white_ip_url(@registrar) + + current_path.should == '/admin/login' + end + end + + context 'as logged in user' do + before { sign_in @user } + + it 'should add new white ip to registrar' do + visit admin_registrar_url(@registrar) + + page.should_not have_text('192.168.1.1') + + click_link 'Create new white IP' + + fill_in 'IPv4', with: '192.168.1.1' + fill_in 'IPv6', with: 'FE80:0000:0000:0000:0202:B3FF:FE1E:8329' + select 'REPP', from: 'Interface' + click_button 'Save' + + page.should have_text('Record created') + page.should have_text('White IP') + page.should have_link(@registrar.to_s) + page.should have_text('192.168.1.1') + page.should have_text('FE80:0000:0000:0000:0202:B3FF:FE1E:8329') + page.should have_text('REPP') + + click_link @registrar.to_s + + current_path.should == "/admin/registrars/#{@registrar.id}" + page.should have_text('192.168.1.1') + page.should have_text('FE80:0000:0000:0000:0202:B3FF:FE1E:8329') + page.should have_text('REPP') + end + + it 'should not add invalid ip to registrar' do + visit new_admin_registrar_white_ip_url(@registrar) + + click_button 'Save' + page.should have_text('IPv4 or IPv6 must be present') + page.should have_text('Failed to create record') + + fill_in 'IPv4', with: 'bla' + fill_in 'IPv6', with: 'bla' + + click_button 'Save' + + page.should have_text('IPv4 is invalid') + page.should have_text('IPv6 is invalid') + end + end +end diff --git a/spec/models/registrar_spec.rb b/spec/models/registrar_spec.rb index 067c999af..e8d719e92 100644 --- a/spec/models/registrar_spec.rb +++ b/spec/models/registrar_spec.rb @@ -4,6 +4,7 @@ describe Registrar do it { should have_many(:domains) } it { should have_many(:api_users) } it { should have_many(:messages) } + it { should have_many(:white_ips) } context 'with invalid attribute' do before :all do diff --git a/spec/models/white_ip_spec.rb b/spec/models/white_ip_spec.rb new file mode 100644 index 000000000..7c169c539 --- /dev/null +++ b/spec/models/white_ip_spec.rb @@ -0,0 +1,54 @@ +require 'rails_helper' + +describe WhiteIp do + it { should belong_to(:registrar) } + + context 'with invalid attribute' do + before :all do + @white_ip = WhiteIp.new + end + + it 'is not valid' do + @white_ip.valid? + @white_ip.errors.full_messages.should match_array([ + 'IPv4 or IPv6 must be present' + ]) + end + + it 'returns an error with invalid ips' do + @white_ip.ipv4 = 'bla' + @white_ip.ipv6 = 'bla' + + @white_ip.valid? + @white_ip.errors[:ipv4].should == ['is invalid'] + @white_ip.errors[:ipv6].should == ['is invalid'] + end + end + + context 'with valid attributes' do + before :all do + @white_ip = Fabricate(:white_ip) + end + + it 'should be valid' do + @white_ip.valid? + @white_ip.errors.full_messages.should match_array([]) + end + + it 'should be valid twice' do + @white_ip = Fabricate(:white_ip) + @white_ip.valid? + @white_ip.errors.full_messages.should match_array([]) + end + + it 'should have one version' do + with_versioning do + @white_ip.versions.should == [] + @white_ip.ipv4 = '192.168.1.2' + @white_ip.save + @white_ip.errors.full_messages.should match_array([]) + @white_ip.versions.size.should == 1 + end + end + end +end diff --git a/spec/requests/v1/account_spec.rb b/spec/requests/v1/account_spec.rb index 3928ad64a..8754234f1 100644 --- a/spec/requests/v1/account_spec.rb +++ b/spec/requests/v1/account_spec.rb @@ -1,30 +1,43 @@ require 'rails_helper' describe Repp::AccountV1 do - before :all do - @registrar1 = Fabricate(:registrar1, accounts: - [Fabricate(:account, { balance: '324.45', account_activities: [] })] - ) - @api_user = Fabricate(:gitlab_api_user, registrar: @registrar1) + it 'should fail without whitelisted IP' do + @registrar1 = Fabricate(:registrar, white_ips: [Fabricate(:white_ip_epp), Fabricate(:white_ip_registrar)]) + @api_user = Fabricate(:api_user, registrar: @registrar1) + + get_with_auth '/repp/v1/accounts/balance', {}, @api_user + response.status.should == 401 + body = JSON.parse(response.body) + + body['error'].should == 'IP is not whitelisted' end - describe 'GET /repp/v1/accounts/balance' do - it 'returns account balance of the current registrar', autodoc: true, route_info_doc: true do - get_with_auth '/repp/v1/accounts/balance', {}, @api_user - response.status.should == 200 + context 'with valid registrar' do + before :all do + @registrar1 = Fabricate(:registrar1, accounts: + [Fabricate(:account, { balance: '324.45', account_activities: [] })] + ) + @api_user = Fabricate(:gitlab_api_user, registrar: @registrar1) + end - body = JSON.parse(response.body) - body['balance'].should == '324.45' - body['currency'].should == 'EUR' + describe 'GET /repp/v1/accounts/balance' do + it 'returns account balance of the current registrar', autodoc: true, route_info_doc: true do + get_with_auth '/repp/v1/accounts/balance', {}, @api_user + response.status.should == 200 - log = ApiLog::ReppLog.last - log[:request_path].should == '/repp/v1/accounts/balance' - log[:request_method].should == 'GET' - log[:request_params].should == '{}' - log[:response_code].should == '200' - log[:api_user_name].should == 'gitlab' - log[:api_user_registrar].should == 'registrar1' - log[:ip].should == '127.0.0.1' + body = JSON.parse(response.body) + body['balance'].should == '324.45' + body['currency'].should == 'EUR' + + log = ApiLog::ReppLog.last + log[:request_path].should == '/repp/v1/accounts/balance' + log[:request_method].should == 'GET' + log[:request_params].should == '{}' + log[:response_code].should == '200' + log[:api_user_name].should == 'gitlab' + log[:api_user_registrar].should == 'registrar1' + log[:ip].should == '127.0.0.1' + end end end end