Validation of user certificates

This commit is contained in:
Sergei Tsoganov 2023-07-13 11:19:11 +03:00
parent e6e0624943
commit 65ae5adbb8
2 changed files with 90 additions and 29 deletions

View file

@ -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