diff --git a/app/controllers/repp/v1/base_controller.rb b/app/controllers/repp/v1/base_controller.rb index d2057599e..3da75c672 100644 --- a/app/controllers/repp/v1/base_controller.rb +++ b/app/controllers/repp/v1/base_controller.rb @@ -7,46 +7,78 @@ module Repp before_action :authenticate_user before_action :set_locale before_action :validate_webclient_ca - before_action :validate_client_certs + before_action :validate_api_user_cert before_action :check_ip_restriction before_action :set_paper_trail_whodunnit private + # rubocop:disable Metrics/MethodLength def log_request yield rescue ActiveRecord::RecordNotFound - @response = { code: 2303, message: 'Object does not exist' } - render(json: @response, status: :not_found) + handle_record_not_found rescue ActionController::ParameterMissing, Apipie::ParamMissing => e - @response = { code: 2003, message: e.message.gsub(/\n/, '. ') } - render(json: @response, status: :bad_request) + handle_parameter_missing(e) rescue Apipie::ParamInvalid => e - @response = { code: 2005, message: e.message.gsub(/\n/, '. ') } - render(json: @response, status: :bad_request) + handle_param_invalid(e) rescue CanCan::AccessDenied => e - @response = { code: 2201, message: 'Authorization error' } - logger.error e.to_s - render(json: @response, status: :unauthorized) + handle_access_denied(e) rescue Shunter::ThrottleError => e - @response = { code: 2502, message: Shunter.default_error_message } - logger.error e.to_s unless Rails.env.test? - render(json: @response, status: :bad_request) + handle_throttle_error(e) ensure create_repp_log end + # rubocop:enable Metrics/MethodLength + + def handle_record_not_found + @response = { code: 2303, message: 'Object does not exist' } + render(json: @response, status: :not_found) + end + + def handle_parameter_missing(e) + @response = { code: 2003, message: e.message.gsub(/\n/, '. ') } + render(json: @response, status: :bad_request) + end + + def handle_param_invalid(e) + @response = { code: 2005, message: e.message.gsub(/\n/, '. ') } + render(json: @response, status: :bad_request) + end + + def handle_access_denied(e) + @response = { code: 2201, message: 'Authorization error' } + logger.error e.to_s + render(json: @response, status: :unauthorized) + end + + def handle_throttle_error(e) + @response = { code: 2502, message: Shunter.default_error_message } + logger.error e.to_s unless Rails.env.test? + render(json: @response, status: :bad_request) + end - # rubocop:disable Metrics/AbcSize def create_repp_log - ApiLog::ReppLog.create( - request_path: request.path, request_method: request.request_method, - request_params: request.params.except('route_info').to_json, uuid: request.try(:uuid), - response: @response.to_json, response_code: response.status, ip: request.ip, + log_attributes = build_log_attributes + ApiLog::ReppLog.create(log_attributes) + end + + def build_log_attributes + { + request_path: request.path, ip: request.ip, + request_method: request.request_method, + request_params: build_request_params_json, + uuid: request.try(:uuid), + response: @response.to_json, + response_code: response.status, api_user_name: current_user.try(:username), api_user_registrar: current_user.try(:registrar).try(:to_s) - ) + } + end + + def build_request_params_json + request.params.except('route_info').to_json end - # rubocop:enable Metrics/AbcSize def set_domain registrar = current_user.registrar @@ -122,11 +154,11 @@ module Repp end def check_ip_restriction - ip = webclient_request? ? request.headers['X-Client-IP'] : request.ip + ip = webclient_request? ? request.headers['Request-IP'] : request.ip return if registrar_ip_white?(ip) && webclient_request? return if api_ip_white?(ip) && !webclient_request? - render_unauthorized_response(ip) + render_unauthorized_ip_response(ip) end def registrar_ip_white?(ip) @@ -139,7 +171,7 @@ module Repp @current_user.registrar.api_ip_white?(ip) end - def render_unauthorized_response(ip) + def render_unauthorized_ip_response(ip) @response = { code: 2202, message: I18n.t('registrar.authorization.ip_not_allowed', ip: ip) } render json: @response, status: :unauthorized end @@ -167,16 +199,41 @@ module Repp render(json: @response, status: :unauthorized) end - def validate_client_certs + def validate_api_user_cert return if Rails.env.development? || Rails.env.test? return if webclient_request? - return if @current_user.pki_ok?(request.env['HTTP_SSL_CLIENT_CERT'], - request.env['HTTP_SSL_CLIENT_S_DN_CN']) - @response = { code: 2202, message: 'Invalid certificate' } + crt = request.env['HTTP_SSL_CLIENT_CERT'] + com = request.env['HTTP_SSL_CLIENT_S_DN_CN'] + + return if @current_user.pki_ok?(crt, com) + + render_invalid_cert_response + end + + def validate_webclient_user_cert + return if skip_webclient_user_cert_validation? + + crt = request.headers['User-Certificate'] + com = request.headers['User-Certificate-CN'] + + return if @current_user.pki_ok?(crt, com, api: false) + + render_invalid_cert_response + end + + def render_invalid_cert_response + @response = { code: 2202, message: 'Invalid user certificate' } render(json: @response, status: :unauthorized) end + def skip_webclient_user_cert_validation? + Rails.env.development? || + Rails.env.test? || + !webclient_request? || + request.headers['Requester'] == 'tara' + end + def logger Rails.logger end diff --git a/app/controllers/repp/v1/registrar/auth_controller.rb b/app/controllers/repp/v1/registrar/auth_controller.rb index 5da1b3a38..0c7361f33 100644 --- a/app/controllers/repp/v1/registrar/auth_controller.rb +++ b/app/controllers/repp/v1/registrar/auth_controller.rb @@ -2,9 +2,10 @@ module Repp module V1 module Registrar class AuthController < BaseController + before_action :validate_webclient_user_cert, only: :index skip_before_action :authenticate_user, only: :tara_callback skip_before_action :check_ip_restriction, only: :tara_callback - skip_before_action :validate_client_certs, only: :tara_callback + skip_before_action :validate_api_user_cert, only: :tara_callback THROTTLED_ACTIONS = %i[index tara_callback].freeze include Shunter::Integration::Throttle @@ -21,7 +22,10 @@ module Repp def tara_callback user = ApiUser.from_omniauth(auth_params) response = { code: 401, message: I18n.t(:no_such_user), data: {} } - render(json: response, status: :unauthorized) and return unless user && user&.active + unless user&.active && webclient_request? + render(json: response, status: :unauthorized) + return + end token = Base64.urlsafe_encode64("#{user.username}:#{user.plain_text_password}") render_success(data: { token: token, username: user.username })