Merge pull request #2597 from internetee/improve-white-ip-form

Modified white ip form
This commit is contained in:
Timo Võhmar 2023-07-12 14:36:15 +03:00 committed by GitHub
commit 124ad32608
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
33 changed files with 564 additions and 139 deletions

View file

@ -89,6 +89,7 @@ group :test do
gem 'capybara'
gem 'database_cleaner'
gem 'minitest', '~> 5.17'
gem 'minitest-stub_any_instance'
gem 'simplecov', '0.17.1', require: false # CC last supported v0.17
gem 'spy'
gem 'webdrivers'

View file

@ -311,6 +311,7 @@ GEM
mini_mime (1.1.2)
mini_portile2 (2.8.2)
minitest (5.18.1)
minitest-stub_any_instance (1.0.3)
monetize (1.9.4)
money (~> 6.12)
money (6.13.8)
@ -571,6 +572,7 @@ DEPENDENCIES
mime-types-data
mimemagic (= 0.4.3)
minitest (~> 5.17)
minitest-stub_any_instance
money-rails
newrelic-infinite_tracing
newrelic_rpm
@ -606,4 +608,4 @@ DEPENDENCIES
wkhtmltopdf-binary (~> 0.12.6.1)
BUNDLED WITH
2.4.13
2.4.14

View file

@ -1,6 +1,7 @@
module Admin
class BaseController < ApplicationController
before_action :authenticate_admin_user!
before_action :set_locale
helper_method :head_title_sufix
before_action :set_paper_trail_whodunnit
@ -33,5 +34,9 @@ module Admin
end
end
end
def set_locale
I18n.locale = params[:locale] || I18n.default_locale
end
end
end

View file

@ -41,7 +41,7 @@ module Admin
def sign
if @certificate.sign!(password: certificate_params[:password])
flash[:notice] = I18n.t('record_updated')
notify_api_user
notify_registrar
redirect_to [:admin, @api_user, @certificate]
else
flash.now[:alert] = I18n.t('failed_to_update_record')
@ -88,10 +88,10 @@ module Admin
end
end
def notify_api_user
api_user_email = @api_user.registrar.email
def notify_registrar
email = @api_user.registrar.email
CertificateMailer.signed(email: api_user_email, api_user: @api_user,
CertificateMailer.signed(email: email, api_user: @api_user,
crt: OpenSSL::X509::Certificate.new(@certificate.crt))
.deliver_now
end

View file

@ -2,17 +2,15 @@ module Admin
class WhiteIpsController < BaseController
load_and_authorize_resource
before_action :set_registrar, only: [:new, :show, :edit, :destroy, :update]
before_action :set_registrar, only: %i[new show edit destroy update]
def new
@white_ip = WhiteIp.new(registrar: @registrar)
end
def show;
end
def show; end
def edit;
end
def edit; end
def destroy
if @white_ip.destroy
@ -38,7 +36,11 @@ module Admin
end
def update
previously_committed = @white_ip.committed
if @white_ip.update(white_ip_params)
notify_registrar if !previously_committed && @white_ip.committed
flash[:notice] = I18n.t('record_updated')
redirect_to [:admin, @registrar, @white_ip]
else
@ -54,7 +56,14 @@ module Admin
end
def white_ip_params
params.require(:white_ip).permit(:ipv4, :ipv6, :registrar_id, { interfaces: [] })
params.require(:white_ip).permit(:ipv4, :ipv6, :registrar_id, :committed, { interfaces: [] })
end
def notify_registrar
email = @white_ip.registrar.email
WhiteIpMailer.committed(email: email, ip: @white_ip)
.deliver_now
end
end
end

View file

@ -174,7 +174,7 @@ module Repp
end
def serialized_ips(ips)
ips.as_json(only: %i[id ipv4 ipv6 interfaces])
ips.as_json(only: %i[id ipv4 ipv6 interfaces committed])
end
end
end

View file

@ -5,6 +5,7 @@ module Repp
around_action :log_request
before_action :authenticate_user
before_action :set_locale
before_action :validate_webclient_ca
before_action :validate_client_certs
before_action :check_ip_restriction
@ -121,18 +122,36 @@ module Repp
end
def check_ip_restriction
return if webclient_request?
return if @current_user.registrar.api_ip_white?(request.ip)
ip = webclient_request? ? request.headers['X-Client-IP'] : request.ip
return if registrar_ip_white?(ip) && webclient_request?
return if api_ip_white?(ip) && !webclient_request?
@response = { code: 2202,
message: I18n.t('registrar.authorization.ip_not_allowed', ip: request.ip) }
render(json: @response, status: :unauthorized)
render_unauthorized_response(ip)
end
def registrar_ip_white?(ip)
return true unless ip
@current_user.registrar.registrar_ip_white?(ip)
end
def api_ip_white?(ip)
@current_user.registrar.api_ip_white?(ip)
end
def render_unauthorized_response(ip)
@response = { code: 2202, message: I18n.t('registrar.authorization.ip_not_allowed', ip: ip) }
render json: @response, status: :unauthorized
end
def webclient_request?
return false if Rails.env.test? || Rails.env.development?
ENV['webclient_ips'].split(',').map(&:strip).include?(request.ip)
webclient_ips.include?(request.ip)
end
def webclient_ips
ENV['webclient_ips'].to_s.split(',').map(&:strip)
end
def validate_webclient_ca
@ -143,8 +162,7 @@ module Repp
webclient_cn = ENV['webclient_cert_common_name'] || 'webclient'
return if request_name == webclient_cn
@response = { code: 2202,
message: I18n.t('registrar.authorization.ip_not_allowed', ip: request.ip) }
@response = { code: 2202, message: 'Invalid webclient certificate' }
render(json: @response, status: :unauthorized)
end
@ -176,6 +194,10 @@ module Repp
authorize!(:throttled_user, @domain) unless current_user || action_name == 'tara_callback'
current_user
end
def set_locale
I18n.locale = current_user&.try(:locale) || params[:locale] || I18n.default_locale
end
end
end
end

View file

@ -31,39 +31,63 @@ module Repp
return
end
uncommit_and_notify_admins if api_interface?(@white_ip)
render_success(data: { ip: { id: @white_ip.id } })
end
api :PUT, '/repp/v1/white_ips/:id'
desc 'Update whitelisted IP address'
def update
previously_api = api_interface?(@white_ip)
unless @white_ip.update(white_ip_params)
handle_non_epp_errors(@white_ip)
return
end
uncommit_and_notify_admins if api_interface?(@white_ip)
uncommit_and_notify_admins if previously_api && !api_interface?(@white_ip)
render_success(data: { ip: { id: @white_ip.id } })
end
api :DELETE, '/repp/v1/white_ips/:id'
desc 'Delete a specific whitelisted IP address'
def destroy
ip = @white_ip
unless @white_ip.destroy
handle_non_epp_errors(@white_ip)
return
end
uncommit_and_notify_admins(ip: ip, action: 'deleted') if api_interface?(ip)
render_success
end
private
def api_interface?(ip)
ip.interfaces.include? WhiteIp::API
end
def find_white_ip
@white_ip = current_user.registrar.white_ips.find(params[:id])
end
def white_ip_params
params.require(:white_ip).permit(:ipv4, :ipv6, interfaces: [])
params.require(:white_ip).permit(:address, interfaces: [])
end
def uncommit_and_notify_admins(ip: @white_ip, action: 'updated')
@white_ip.update(committed: false) if action == 'updated'
admin_users_emails = User.admin.pluck(:email).reject(&:blank?)
return if admin_users_emails.empty?
admin_users_emails.each do |email|
WhiteIpMailer.with(email: email, api_user: current_user,
white_ip: ip)
.send("api_ip_address_#{action}")
.deliver_now
end
end
end
end

View file

@ -0,0 +1,23 @@
class WhiteIpMailer < ApplicationMailer
def api_ip_address_updated
email = params[:email]
@api_user = params[:api_user]
@white_ip = params[:white_ip]
subject = '[Important] Whitelisted IP Address Change Notification'
mail(to: email, subject: subject)
end
def api_ip_address_deleted
email = params[:email]
@api_user = params[:api_user]
@white_ip = params[:white_ip]
subject = '[Important] Whitelisted IP Address Removal Notification'
mail(to: email, subject: subject)
end
def committed(email:, ip:)
@white_ip = ip
subject = 'Whitelisted IP Address Activation Confirmation'
mail(to: email, subject: subject)
end
end

View file

@ -0,0 +1,53 @@
# app/models/concerns/white_ip_concern.rb
module WhiteIp::WhiteIpConcern
extend ActiveSupport::Concern
class_methods do # rubocop:disable Metrics/BlockLength
def include_ip?(ip)
return false if ip.blank?
where(id: ids_including(ip)).any?
end
def ids_including(ip)
ipv4 = select_ipv4(ip)
ipv6 = select_ipv6(ip)
(ipv4 + ipv6).pluck(:id).flatten.uniq
end
# rubocop:disable Style/CaseEquality
def select_ipv4(ip)
return [] if check_ip4(ip).blank?
select { |white_ip| check_ip4(white_ip.ipv4) === check_ip4(ip) }
end
def select_ipv6(ip)
return [] if check_ip6(ip).blank?
select { |white_ip| check_ip6(white_ip.ipv6) === check_ip6(ip) }
end
# rubocop:enable Style/CaseEquality
def csv_header
%w[IPv4 IPv6 Interfaces Created Updated]
end
def ransackable_attributes(*)
authorizable_ransackable_attributes
end
def check_ip4(ip)
IPAddr.new(ip, Socket::AF_INET)
rescue StandardError => _e
nil
end
def check_ip6(ip)
IPAddr.new(ip, Socket::AF_INET6)
rescue StandardError => _e
nil
end
end
end

View file

@ -200,6 +200,12 @@ class Registrar < ApplicationRecord # rubocop:disable Metrics/ClassLength
white_ips.api.include_ip?(ip)
end
def registrar_ip_white?(ip)
return true unless Setting.registrar_ip_whitelist_enabled
white_ips.registrar_area.include_ip?(ip)
end
def accredited?
api_users.any? do |a|
return true unless a.accreditation_date.nil?

View file

@ -1,11 +1,15 @@
class WhiteIp < ApplicationRecord
include Versions
include WhiteIp::WhiteIpConcern
belongs_to :registrar
attr_accessor :address
validate :validate_address_format
validate :validate_only_one_ip
validate :valid_ipv4?
validate :valid_ipv6?
validate :validate_ipv4_and_ipv6
validate :validate_only_one_ip
validate :validate_max_ip_count
before_save :normalize_blank_values
@ -13,16 +17,35 @@ class WhiteIp < ApplicationRecord
%i[ipv4 ipv6].each { |c| self[c].present? || self[c] = nil }
end
def validate_ipv4_and_ipv6
return if ipv4.present? || ipv6.present?
def validate_address_format
return if address.blank?
errors.add(:base, I18n.t(:ipv4_or_ipv6_must_be_present))
ip_address = IPAddr.new(address)
ip_version = determine_ip_version(ip_address)
assign_ip_attributes(ip_version)
rescue IPAddr::InvalidAddressError
errors.add(:base, :address_invalid)
end
def validate_only_one_ip
return unless ipv4.present? && ipv6.present?
if ipv4.present? && ipv6.present?
errors.add(:base, :ip_must_be_one)
elsif ipv4.blank? && ipv6.blank?
errors.add(:base, :ipv4_or_ipv6_must_be_present)
end
end
errors.add(:base, I18n.t(:ip_must_be_one))
def validate_max_ip_count
return if errors.any?
total_exist = calculate_total_network_addresses(registrar.white_ips)
total_current = calculate_total_network_addresses([self])
total = total_exist + total_current
limit = Setting.ip_whitelist_max_count
return unless total >= limit
errors.add(:base, :ip_limit_exceeded, total: total, limit: limit)
end
def valid_ipv4?
@ -41,34 +64,9 @@ class WhiteIp < ApplicationRecord
errors.add(:ipv6, :invalid)
end
def validate_max_ip_count
return if errors.any?
ip_addresses = registrar.white_ips
total = ip_addresses.size + count_network_addresses(ipv4.presence || ipv6)
limit = Setting.ip_whitelist_max_count
return unless total >= limit
errors.add(:base, I18n.t(:ip_limit_exceeded, total: total, limit: limit))
end
def count_network_addresses(ip)
address = IPAddr.new(ip)
if address.ipv4?
subnet_mask = address.prefix
2**(32 - subnet_mask) - 2
elsif address.ipv6?
subnet_mask = address.prefix
2**(128 - subnet_mask) - 2
else
0
end
end
API = 'api'.freeze
REGISTRAR = 'registrar'.freeze
INTERFACES = [API, REGISTRAR].freeze
INTERFACES = [REGISTRAR, API].freeze
scope :api, -> { where('interfaces @> ?::varchar[]', "{#{API}}") }
scope :registrar_area, -> { where('interfaces @> ?::varchar[]', "{#{REGISTRAR}}") }
@ -77,52 +75,52 @@ class WhiteIp < ApplicationRecord
super(interfaces.reject(&:blank?))
end
class << self
# rubocop:disable Style/CaseEquality
# rubocop:disable Metrics/AbcSize
def include_ip?(ip)
return false if ip.blank?
where(id: ids_including(ip)).any?
end
def ids_including(ip)
ipv4 = ipv6 = []
ipv4 = select { |white_ip| check_ip4(white_ip.ipv4) === check_ip4(ip) } if check_ip4(ip).present?
ipv6 = select { |white_ip| check_ip6(white_ip.ipv6) === check_ip6(ip) } if check_ip6(ip).present?
(ipv4 + ipv6).pluck(:id).flatten.uniq
end
# rubocop:enable Style/CaseEquality
# rubocop:enable Metrics/AbcSize
def check_ip4(ip)
IPAddr.new(ip, Socket::AF_INET)
rescue StandardError => _e
nil
end
def check_ip6(ip)
IPAddr.new(ip, Socket::AF_INET6)
rescue StandardError => _e
nil
end
def csv_header
%w[IPv4 IPv6 Interfaces Created Updated]
end
def ransackable_attributes(*)
authorizable_ransackable_attributes
end
end
def as_csv_row
[
ipv4,
ipv6,
ipv4, ipv6,
interfaces.join(', ').upcase,
created_at,
updated_at,
updated_at
]
end
private
def determine_ip_version(ip_address)
return :ipv4 if ip_address.ipv4?
return :ipv6 if ip_address.ipv6?
nil
end
def assign_ip_attributes(ip_version)
case ip_version
when :ipv4
self.ipv4 = address
self.ipv6 = nil
when :ipv6
self.ipv6 = address
self.ipv4 = nil
else
errors.add(:base, :address_invalid)
end
end
def count_network_addresses(ip)
address = IPAddr.new(ip)
if address.ipv4?
subnet_mask = address.prefix
(2**(32 - subnet_mask) - 2).abs
elsif address.ipv6?
subnet_mask = address.prefix
(2**(128 - subnet_mask) - 2).abs
else
0
end
end
def calculate_total_network_addresses(ips)
ips.sum { |ip| count_network_addresses(ip.ipv4.presence || ip.ipv6) }
end
end

View file

@ -9,6 +9,7 @@
<th class="col-xs-4"><%= WhiteIp.human_attribute_name :ipv4 %></th>
<th class="col-xs-6"><%= WhiteIp.human_attribute_name :ipv6 %></th>
<th class="col-xs-2"><%= WhiteIp.human_attribute_name :interfaces %></th>
<th class="col-xs-2"><%= WhiteIp.human_attribute_name :committed %></th>
</tr>
</thead>
@ -26,6 +27,7 @@
<% end %>
</td>
<td><%= white_ip.interfaces.join(', ').upcase %></td>
<td class="text-right"><%= white_ip.committed %></td>
</tr>
<% end %>
</tbody>

View file

@ -26,7 +26,13 @@
.col-md-7
= f.check_box :interfaces, { multiple: true }, x, nil
= hidden_field_tag "white_ip[interfaces][]", nil
.form-group
.col-md-4.control-label
= f.label :committed
.col-md-7
= f.check_box :committed
%hr
.row
.col-md-8.text-right
= button_tag(t(:save), class: 'btn btn-primary')
= button_tag(t(:save), class: 'btn btn-primary')

View file

@ -22,3 +22,6 @@
%dt= WhiteIp.human_attribute_name :interfaces
%dd= @white_ip.interfaces.join(', ').upcase
%dt= WhiteIp.human_attribute_name :committed
%dd= @white_ip.committed

View file

@ -0,0 +1,10 @@
<p>This email is to inform you that an API Whitelisted IP address was deleted by Registrar Portal API user. Please review the details below:</p>
<ul>
<li>Registrar: <%= @api_user.registrar.name %></li>
<li>API User: <%= @api_user.username %></li>
<li>IP Address: <%= @white_ip.ipv4.presence || @white_ip.ipv6 %></li>
<li>Interface: <%= @white_ip.interfaces.join(', ') %></li>
</ul>
<p>Please take the necessary actions to ensure the security and integrity of the application's API access.</p>

View file

@ -0,0 +1,8 @@
This email is to inform you about an API Whitelisted IP address change by Registrar Portal API user. Please review the details below:
Registrar: <%= @api_user.registrar.name %>
API User: <%= @api_user.username %>
IP Address: <%= @white_ip.ipv4.presence || @white_ip.ipv6 %>
Interface: <%= @white_ip.interfaces.join(', ') %>
Please take the necessary actions to ensure the security and integrity of the application's API access.

View file

@ -0,0 +1,10 @@
<p>This email is to inform you about an API Whitelisted IP address change by Registrar Portal API user. Please review the details below:</p>
<ul>
<li>Registrar: <%= @api_user.registrar.name %></li>
<li>API User: <%= @api_user.username %></li>
<li>IP Address: <%= @white_ip.ipv4.presence || @white_ip.ipv6 %></li>
<li>Interface: <%= @white_ip.interfaces.join(', ') %></li>
</ul>
<p>Please take the necessary actions to ensure the security and integrity of the application's API access.</p>

View file

@ -0,0 +1,8 @@
This email is to inform you about an API Whitelisted IP address change by Registrar Portal API user. Please review the details below:
Registrar: <%= @api_user.registrar.name %>
API User: <%= @api_user.username %>
IP Address: <%= @white_ip.ipv4.presence || @white_ip.ipv6 %>
Interface: <%= @white_ip.interfaces.join(', ') %>
Please take the necessary actions to ensure the security and integrity of the application's API access.

View file

@ -0,0 +1,43 @@
Tere,
<br><br>
<p>
Anname teada, et Teie konto juurde kuuluv lubatud IP-aadress on edukalt aktiveeritud.
</p>
<h3>IP-aadressi andmed:</h3>
<ul>
<li><strong>IP-aadress:</strong> <%= @white_ip.ipv4.presence || @white_ip.ipv6 %></li>
<li><strong>Liidesed:</strong> <%= @white_ip.interfaces.join(', ') %></li>
</ul>
<p>
Päringud IP-aadressist <%= @white_ip.ipv4.presence || @white_ip.ipv6 %> jõuavad nüüd .ee registrisüsteemini.
Palun hoidke selle IP-aadressi turvalisust ja konfidentsiaalsust, et vältida volitamata juurdepääsu.
</p>
Kui Teil on küsimusi seoses Teie lubatud IP-aadressi aktiveerimisega, võtke meiega ühendust.
</p>
<p>
Parimate soovidega,
</p>
<%= render 'mailers/shared/signatures/signature.et.html' %>
<hr>
<br><br>
Hi,
<br><br>
<p>
We would like to inform you that the whitelisted IP address associated with your account has been successfully activated.
</p>
<h3>IP address Details:</h3>
<ul>
<li><strong>IP address:</strong> <%= @white_ip.ipv4.presence || @white_ip.ipv6 %></li>
<li><strong>Interfaces:</strong> <%= @white_ip.interfaces.join(', ') %></li>
</ul>
<p>
All requests originating from the IP address <%= @white_ip.ipv4.presence || @white_ip.ipv6 %> will now have access to our system.
Please ensure the security and confidentiality of this IP address to prevent unauthorized access.
</p>
If you have any questions regarding the activation of your whitelisted IP address, please contact us.
</p>
<p>
Best regards,
</p>
<%= render 'mailers/shared/signatures/signature.en.html' %>

View file

@ -0,0 +1,32 @@
Tere,
Anname teada, et Teie konto juurde kuuluv lubatud IP-aadress on edukalt aktiveeritud.
IP-aadressi andmed:
- IP-aadress: <%= @white_ip.ipv4.presence || @white_ip.ipv6 %>
- Liidesed: <%= @white_ip.interfaces.join(', ') %>
Päringud IP-aadressist <%= @white_ip.ipv4.presence || @white_ip.ipv6 %> jõuavad nüüd .ee registrisüsteemini.
Palun hoidke selle IP-aadressi turvalisust ja konfidentsiaalsust, et vältida volitamata juurdepääsu.
Kui Teil on küsimusi seoses Teie lubatud IP-aadressi aktiveerimisega, võtke meiega ühendust.
Parimate soovidega,
<%= render 'mailers/shared/signatures/signature.et.html' %>
---
Hi,
We would like to inform you that the whitelisted IP address associated with your account has been successfully activated.
IP address Details:
- IP address: <%= @white_ip.ipv4.presence || @white_ip.ipv6 %>
- Interfaces: <%= @white_ip.interfaces.join(', ') %>
All requests originating from the IP address <%= @white_ip.ipv4.presence || @white_ip.ipv6 %> will now have access to our system.
Please ensure the security and confidentiality of this IP address to prevent unauthorized access.
If you have any questions regarding the activation of your whitelisted IP address, please contact us.
Best regards,
<%= render 'mailers/shared/signatures/signature.en.html' %>

View file

@ -0,0 +1,64 @@
# Additional translations at https://github.com/plataformatec/devise/wiki/I18n
et:
devise:
confirmations:
confirmed: "Your email address has been successfully confirmed."
send_instructions: "You will receive an email with instructions for how to confirm your email address in a few minutes."
send_paranoid_instructions: "If your email address exists in our database, you will receive an email with instructions for how to confirm your email address in a few minutes."
failure:
already_authenticated: "You are already signed in."
inactive: "Your account is not activated yet."
invalid: "Invalid %{authentication_keys} or password."
locked: "Your account is locked."
last_attempt: "You have one more attempt before your account is locked."
not_found_in_database: "Invalid %{authentication_keys} or password."
timeout: "Your session expired. Please sign in again to continue."
unauthenticated: "You need to sign in before continuing."
unconfirmed: "You have to confirm your email address before continuing."
mailer:
confirmation_instructions:
subject: "Confirmation instructions"
reset_password_instructions:
subject: "Reset password instructions"
unlock_instructions:
subject: "Unlock instructions"
email_changed:
subject: "Email Changed"
password_change:
subject: "Password Changed"
omniauth_callbacks:
failure: "Could not authenticate you from %{kind} because \"%{reason}\"."
success: "Successfully authenticated from %{kind} account."
passwords:
no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided."
send_instructions: "You will receive an email with instructions on how to reset your password in a few minutes."
send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes."
updated: "Your password has been changed successfully. You are now signed in."
updated_not_active: "Your password has been changed successfully."
registrations:
destroyed: "Bye! Your account has been successfully cancelled. We hope to see you again soon."
signed_up: "Welcome! You have signed up successfully."
signed_up_but_inactive: "You have signed up successfully. However, we could not sign you in because your account is not yet activated."
signed_up_but_locked: "You have signed up successfully. However, we could not sign you in because your account is locked."
signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please follow the link to activate your account."
update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and follow the confirm link to confirm your new email address."
updated: "Your account has been updated successfully."
sessions:
signed_in: "Signed in successfully."
signed_out: "Signed out successfully."
already_signed_out: "Signed out successfully."
unlocks:
send_instructions: "You will receive an email with instructions for how to unlock your account in a few minutes."
send_paranoid_instructions: "If your account exists, you will receive an email with instructions for how to unlock it in a few minutes."
unlocked: "Your account has been unlocked successfully. Please sign in to continue."
errors:
messages:
already_confirmed: "was already confirmed, please try signing in"
confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one"
expired: "has expired, please request a new one"
not_found: "not found"
not_locked: "was not locked"
not_saved:
one: "1 error prohibited this %{resource} from being saved:"
other: "%{count} errors prohibited this %{resource} from being saved:"

View file

@ -147,6 +147,18 @@ en:
length_more_than: 'Parameter value policy error: Legaldoc size is less than minimum allowed size of 3kB'
length_less_than: 'Parameter value policy error: Legaldoc size exceeds maximum allowed size of 8mB'
white_ip:
attributes:
base:
address_invalid: 'IP Address is invalid'
ipv4_or_ipv6_must_be_present: 'IPv4 or IPv6 must be present'
ip_must_be_one: 'Please enter only one IP address'
ip_limit_exceeded: 'IP address limit exceeded. Total addresses: %{total}. Limit: %{limit}.'
ipv4:
taken: 'has already been taken'
ipv6:
taken: 'has already been taken'
attributes:
epp_domain: &epp_domain_attributes
@ -548,9 +560,6 @@ en:
not_valid_domain_verification_body: This could mean your verification has been expired or done already.<br><br>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'
ipv4_or_ipv6_must_be_present: 'IPv4 or IPv6 must be present'
ip_must_be_one: 'Please enter only one IP address'
ip_limit_exceeded: 'IP address limit exceeded. Total addresses: %{total}. Limit: %{limit}.'
white_ip: 'White IP'
edit_white_ip: 'Edit white IP'
confirm_domain_delete: 'Confirm domain delete'

View file

@ -2,6 +2,14 @@ et:
username: 'Kasutajanimi'
password: 'Parool'
time:
formats:
default: "%Y-%m-%d %H:%M"
long: "%A, %e. %B %Y, %H:%M"
short: "%d.%m.%y, %H:%M"
date: "%Y-%m-%d"
date_long: "%d. %B %Y"
filename: "%Y-%m-%d_%H.%M"
date:
month_names:
[~, Jaanuar, Veebruar, Märts, April, Mai, Juuni, Juuli, August, September, Oktoober, November, Detsember]
@ -17,3 +25,18 @@ et:
you_have_a_new_invoice: 'Teil on uus arve.'
monthly_invoice: "Siit tuleb aruanne möödunud kuul ettemaksukontoga seotud tasuliste toimingutega."
sincerely: 'Lugupidamisega'
activerecord:
errors:
models:
white_ip:
attributes:
base:
address_invalid: 'IP-aadress on vale'
ipv4_or_ipv6_must_be_present: 'Peab olema vähemalt üks IPv4 või IPv6'
ip_must_be_one: 'Palun sisestage ainult üks IP-aadress'
ip_limit_exceeded: 'IP-aadressi piirang ületatud. Kokku aadresse: %{total}. Limiit: %{limit}.'
ipv4:
taken: 'on juba lisatud'
ipv6:
taken: 'on juba lisatud'

View file

@ -0,0 +1,5 @@
class AddCommittedToWhiteIps < ActiveRecord::Migration[6.1]
def change
add_column :white_ips, :committed, :boolean, default: true
end
end

View file

@ -2806,7 +2806,8 @@ CREATE TABLE public.white_ips (
created_at timestamp without time zone,
updated_at timestamp without time zone,
creator_str character varying,
updator_str character varying
updator_str character varying,
committed boolean DEFAULT true
);
@ -5468,6 +5469,7 @@ INSERT INTO "schema_migrations" (version) VALUES
('20221207102831'),
('20221214073933'),
('20221214074252'),
('20230531111154');
('20230531111154'),
('20230707084741');

View file

@ -46,9 +46,21 @@ class AdminAreaWhiteIpsIntegrationTest < JavaScriptApplicationSystemTestCase
fill_in 'IPv4', with: '127.0.0.2'
find(:css, '#white_ip_interfaces_api').set(false)
find(:css, '#white_ip_committed').set(false)
click_on 'Save'
assert_text 'Record updated'
click_on 'Edit'
find(:css, '#white_ip_interfaces_api').set(false)
find(:css, '#white_ip_committed').set(true)
click_on 'Save'
assert_text 'Record updated'
last_email = ActionMailer::Base.deliveries.last
assert last_email.subject.include?('Whitelisted IP Address Activation Confirmation')
assert last_email.to.include?(@registrar.email)
end
def test_failed_to_update_whitelisted_ip

View file

@ -51,13 +51,39 @@ class ReppV1BaseTest < ActionDispatch::IntegrationTest
whiteip.update(ipv4: '1.1.1.1')
get repp_v1_contacts_path, headers: @auth_headers
assert_unauthorized_ip
Setting.api_ip_whitelist_enabled = false
Setting.registrar_ip_whitelist_enabled = false
end
def test_takes_ip_whitelist_into_account_if_webclient_request
Setting.api_ip_whitelist_enabled = true
Setting.registrar_ip_whitelist_enabled = true
whiteip = white_ips(:one)
whiteip.update(interfaces: ['api'])
Repp::V1::BaseController.stub_any_instance(:webclient_request?, true) do
Repp::V1::BaseController.stub_any_instance(:validate_webclient_ca, true) do
get repp_v1_contacts_path, headers: @auth_headers.merge!({ 'X-Client-IP' => whiteip.ipv4 })
end
end
assert_unauthorized_ip
Setting.api_ip_whitelist_enabled = false
Setting.registrar_ip_whitelist_enabled = false
end
private
def assert_unauthorized_ip
response_json = JSON.parse(response.body, symbolize_names: true)
assert_response :unauthorized
assert_equal 2202, response_json[:code]
assert response_json[:message].include? 'Access denied from IP'
Setting.api_ip_whitelist_enabled = false
Setting.registrar_ip_whitelist_enabled = false
end
end

View file

@ -8,7 +8,7 @@ class ReppV1RegistrarAuthCheckInfoTest < ActionDispatch::IntegrationTest
@auth_headers = { 'Authorization' => token }
adapter = ENV["shunter_default_adapter"].constantize.new
adapter = ENV['shunter_default_adapter'].constantize.new
adapter&.clear!
end
@ -40,8 +40,8 @@ class ReppV1RegistrarAuthCheckInfoTest < ActionDispatch::IntegrationTest
end
def test_returns_error_response_if_throttled
ENV["shunter_default_threshold"] = '1'
ENV["shunter_enabled"] = 'true'
ENV['shunter_default_threshold'] = '1'
ENV['shunter_enabled'] = 'true'
get '/repp/v1/registrar/auth', headers: @auth_headers
get '/repp/v1/registrar/auth', headers: @auth_headers
@ -50,7 +50,7 @@ class ReppV1RegistrarAuthCheckInfoTest < ActionDispatch::IntegrationTest
assert_response :bad_request
assert_equal json[:code], 2502
assert response.body.include?(Shunter.default_error_message)
ENV["shunter_default_threshold"] = '10000'
ENV["shunter_enabled"] = 'false'
ENV['shunter_default_threshold'] = '10000'
ENV['shunter_enabled'] = 'false'
end
end

View file

@ -15,9 +15,8 @@ class ReppV1WhiteIpsCreateTest < ActionDispatch::IntegrationTest
def test_creates_new_white_ip
request_body = {
white_ip: {
ipv4: '127.0.0.1',
ipv6: '',
interfaces: ['API'],
address: '127.1.1.1',
interfaces: ['api'],
},
}
@ -31,15 +30,42 @@ class ReppV1WhiteIpsCreateTest < ActionDispatch::IntegrationTest
white_ip = WhiteIp.find(json[:data][:ip][:id])
assert white_ip.present?
assert_equal(request_body[:white_ip][:ipv4], white_ip.ipv4)
assert_equal(request_body[:white_ip][:address], white_ip.ipv4)
refute white_ip.committed
last_email = ActionMailer::Base.deliveries.last
assert last_email.subject.include?('Whitelisted IP Address Change Notification')
end
def test_creates_new_white_ip_with_registrar_interface
request_body = {
white_ip: {
address: '127.1.1.1',
interfaces: ['registrar'],
},
}
post '/repp/v1/white_ips', headers: @auth_headers, params: request_body
json = JSON.parse(response.body, symbolize_names: true)
assert_response :ok
assert_equal 1000, json[:code]
assert_equal 'Command completed successfully', json[:message]
white_ip = WhiteIp.find(json[:data][:ip][:id])
assert white_ip.present?
assert_equal(request_body[:white_ip][:address], white_ip.ipv4)
assert white_ip.committed
refute ActionMailer::Base.deliveries.last
end
def test_validates_ip_max_count
request_body = {
white_ip: {
ipv4: '',
ipv6: '2001:db8::/120',
interfaces: ['API'],
address: '2001:db8::/120',
interfaces: ['api'],
},
}
@ -56,9 +82,8 @@ class ReppV1WhiteIpsCreateTest < ActionDispatch::IntegrationTest
request_body = {
white_ip: {
ipv4: '127.0.0.1',
ipv6: '',
interfaces: ['API'],
address: '127.0.0.1',
interfaces: ['api'],
},
}

View file

@ -21,6 +21,9 @@ class ReppV1WhiteIpsDeleteTest < ActionDispatch::IntegrationTest
assert_equal 1000, json[:code]
assert_equal 'Command completed successfully', json[:message]
refute WhiteIp.exists?(ip.id)
last_email = ActionMailer::Base.deliveries.last
assert last_email.subject.include?('Whitelisted IP Address Removal Notification')
end
def test_returns_error_response_if_throttled

View file

@ -16,7 +16,7 @@ class ReppV1ApiWhiteIpsUpdateTest < ActionDispatch::IntegrationTest
def test_updates_white_ip
request_body = {
white_ip: {
ipv4: '127.0.0.1',
address: '127.0.0.2',
},
}
@ -28,13 +28,17 @@ class ReppV1ApiWhiteIpsUpdateTest < ActionDispatch::IntegrationTest
assert_equal 'Command completed successfully', json[:message]
ip = WhiteIp.find(json[:data][:ip][:id])
assert_equal ip.ipv4, @white_ip.ipv4
assert_equal ip.ipv4, '127.0.0.2'
refute ip.committed
last_email = ActionMailer::Base.deliveries.last
assert last_email.subject.include?('Whitelisted IP Address Change Notification')
end
def test_returns_error_if_ipv4_wrong_format
request_body = {
white_ip: {
ipv4: 'wrongip',
address: 'wrongip',
},
}
@ -42,21 +46,7 @@ class ReppV1ApiWhiteIpsUpdateTest < ActionDispatch::IntegrationTest
json = JSON.parse(response.body, symbolize_names: true)
assert_response :bad_request
assert json[:message].include? 'IPv4 is invalid'
end
def test_returns_error_if_both_ips
request_body = {
white_ip: {
ipv6: '2001:0db8:85a3:0000:0000:8a2e:0370:7334',
},
}
put "/repp/v1/white_ips/#{@white_ip.id}", headers: @auth_headers, params: request_body
json = JSON.parse(response.body, symbolize_names: true)
assert_response :bad_request
assert json[:message].include? 'Please enter only one IP address'
assert json[:message].include? 'Address is invalid'
end
def test_returns_error_response_if_throttled
@ -65,7 +55,7 @@ class ReppV1ApiWhiteIpsUpdateTest < ActionDispatch::IntegrationTest
request_body = {
white_ip: {
ipv4: '127.0.0.1',
address: '127.0.0.1',
},
}

View file

@ -19,6 +19,7 @@ require 'webmock/minitest'
require 'support/assertions/epp_assertions'
require 'sidekiq/testing'
require 'spy/integration'
require 'minitest/stub_any_instance'
Sidekiq::Testing.fake!