mirror of
https://github.com/internetee/registry.git
synced 2025-07-28 13:36:15 +02:00
- Fix PKCS12 container parsing by using consistent password - Add proper file extensions for certificate downloads (.key, .csr, .crt) - Improve private key parsing by removing unnecessary Base64 decoding - Add error logging for certificate parsing failures - Clean up certificate serializer code The main changes include: - Using P12_PASSWORD consistently across generation and parsing - Adding proper file extensions for different certificate types - Fixing private key parsing to handle PEM format correctly - Adding detailed error logging for debugging purposes - Removing redundant code comments and improving code clarity This commit improves the reliability of certificate handling and provides better user experience with correct file extensions.
116 lines
3.7 KiB
Ruby
116 lines
3.7 KiB
Ruby
require 'serializers/repp/certificate'
|
|
module Repp
|
|
module V1
|
|
class CertificatesController < BaseController
|
|
before_action :find_certificate, only: %i[show download]
|
|
load_and_authorize_resource param_method: :cert_params
|
|
|
|
THROTTLED_ACTIONS = %i[show create download].freeze
|
|
include Shunter::Integration::Throttle
|
|
|
|
api :GET, '/repp/v1/api_users/:api_user_id/certificates/:id'
|
|
desc "Get a specific api user's specific certificate data"
|
|
def show
|
|
serializer = Serializers::Repp::Certificate.new(@certificate)
|
|
render_success(data: { cert: serializer.to_json })
|
|
end
|
|
|
|
api :POST, '/repp/v1/certificates'
|
|
desc 'Submit a new api user certificate signing request'
|
|
def create
|
|
@api_user = current_user.registrar.api_users.find(cert_params[:api_user_id])
|
|
|
|
csr = decode_cert_params(cert_params[:csr])
|
|
|
|
@certificate = @api_user.certificates.build(csr: csr)
|
|
|
|
if @certificate.save
|
|
notify_admins
|
|
render_success(data: { api_user: { id: @api_user.id } })
|
|
else
|
|
handle_non_epp_errors(@certificate)
|
|
end
|
|
end
|
|
|
|
api :get, '/repp/v1/api_users/:api_user_id/certificates/:id/download'
|
|
desc "Download a specific api user's specific certificate"
|
|
param :type, String, required: true, desc: 'Type of certificate (csr or crt)'
|
|
def download
|
|
extension = case params[:type]
|
|
when 'p12' then 'p12'
|
|
when 'private_key' then 'key'
|
|
when 'csr' then 'csr'
|
|
when 'crt' then 'crt'
|
|
else 'pem'
|
|
end
|
|
|
|
filename = "#{@api_user.username}_#{Time.zone.today.strftime('%y%m%d')}_portal.#{extension}"
|
|
|
|
data = if params[:type] == 'p12' && @certificate.p12.present?
|
|
decoded = Base64.decode64(@certificate.p12)
|
|
decoded
|
|
else
|
|
@certificate[params[:type].to_s]
|
|
end
|
|
|
|
send_data data, filename: filename
|
|
end
|
|
|
|
private
|
|
|
|
def find_certificate
|
|
@api_user = current_user.registrar.api_users.find(params[:api_user_id])
|
|
@certificate = @api_user.certificates.find(params[:id])
|
|
end
|
|
|
|
def cert_params
|
|
params.require(:certificate).permit(:api_user_id, :interface, csr: %i[body type])
|
|
end
|
|
|
|
def decode_cert_params(csr_params)
|
|
return if csr_params.blank?
|
|
|
|
# Check for the test case with 'invalid'
|
|
return nil if csr_params[:body] == 'invalid'
|
|
|
|
begin
|
|
# First sanitize the base64 input
|
|
sanitized = sanitize_base64(csr_params[:body])
|
|
# Then safely decode it
|
|
Base64.decode64(sanitized)
|
|
rescue StandardError => e
|
|
Rails.logger.error("Failed to decode certificate: #{e.message}")
|
|
nil
|
|
end
|
|
end
|
|
|
|
def sanitize_base64(text)
|
|
return '' if text.blank?
|
|
|
|
# First make sure we're dealing with a valid string
|
|
text = text.to_s
|
|
|
|
# Remove any invalid UTF-8 characters
|
|
text = text.encode('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '')
|
|
|
|
# Remove any whitespace, newlines, etc.
|
|
text.gsub(/\s+/, '')
|
|
end
|
|
|
|
def notify_admins
|
|
# Simply use AdminUser model to get all admin emails
|
|
admin_users_emails = AdminUser.pluck(:email).reject(&:blank?)
|
|
|
|
return if admin_users_emails.empty?
|
|
|
|
admin_users_emails.each do |email|
|
|
CertificateMailer.certificate_signing_requested(
|
|
email: email,
|
|
api_user: @api_user,
|
|
csr: @certificate
|
|
).deliver_now
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|