mirror of
https://github.com/internetee/registry.git
synced 2025-08-03 00:12:03 +02:00
Merge pull request #2756 from internetee/registrar-p12-generator
Add UserCertificate model with tests
This commit is contained in:
commit
f64575d2b9
31 changed files with 654 additions and 76 deletions
|
@ -4,6 +4,8 @@ class Certificate < ApplicationRecord
|
|||
include Versions
|
||||
include Certificate::CertificateConcern
|
||||
|
||||
self.ignored_columns = ["p12_password_digest"]
|
||||
|
||||
belongs_to :api_user
|
||||
|
||||
SIGNED = 'signed'.freeze
|
||||
|
@ -20,6 +22,12 @@ class Certificate < ApplicationRecord
|
|||
scope 'registrar', -> { where(interface: REGISTRAR) }
|
||||
scope 'unrevoked', -> { where(revoked: false) }
|
||||
|
||||
REVOCATION_REASONS = {
|
||||
unspecified: 0,
|
||||
key_compromise: 1,
|
||||
cessation_of_operation: 5
|
||||
}.freeze
|
||||
|
||||
validate :validate_csr_and_crt_presence
|
||||
def validate_csr_and_crt_presence
|
||||
return if csr.try(:scrub).present? || crt.try(:scrub).present?
|
||||
|
@ -46,14 +54,39 @@ class Certificate < ApplicationRecord
|
|||
|
||||
def parsed_crt
|
||||
@p_crt ||= OpenSSL::X509::Certificate.new(crt) if crt
|
||||
rescue StandardError => e
|
||||
Rails.logger.error("Failed to parse CRT: #{e.message}")
|
||||
nil
|
||||
end
|
||||
|
||||
def parsed_csr
|
||||
@p_csr ||= OpenSSL::X509::Request.new(csr) if csr
|
||||
rescue StandardError => e
|
||||
Rails.logger.error("Failed to parse CSR: #{e.message}")
|
||||
nil
|
||||
end
|
||||
|
||||
def parsed_private_key
|
||||
return nil if private_key.blank?
|
||||
|
||||
OpenSSL::PKey::RSA.new(private_key)
|
||||
rescue StandardError => e
|
||||
Rails.logger.error("Failed to parse private key: #{e.message}")
|
||||
nil
|
||||
end
|
||||
|
||||
def parsed_p12
|
||||
return nil if p12.blank?
|
||||
|
||||
decoded_p12 = Base64.decode64(p12)
|
||||
OpenSSL::PKCS12.new(decoded_p12, p12_password)
|
||||
rescue StandardError => e
|
||||
Rails.logger.error("Failed to parse PKCS12: #{e.message}")
|
||||
nil
|
||||
end
|
||||
|
||||
def revoked?
|
||||
status == REVOKED
|
||||
revoked
|
||||
end
|
||||
|
||||
def revokable?
|
||||
|
@ -62,17 +95,10 @@ class Certificate < ApplicationRecord
|
|||
|
||||
def status
|
||||
return UNSIGNED if crt.blank?
|
||||
return @cached_status if @cached_status
|
||||
|
||||
@cached_status = SIGNED
|
||||
|
||||
if certificate_expired?
|
||||
@cached_status = EXPIRED
|
||||
elsif certificate_revoked?
|
||||
@cached_status = REVOKED
|
||||
end
|
||||
|
||||
@cached_status
|
||||
return REVOKED if revoked?
|
||||
return EXPIRED if expires_at && expires_at < Time.current
|
||||
|
||||
SIGNED
|
||||
end
|
||||
|
||||
def sign!(password:)
|
||||
|
@ -87,18 +113,14 @@ class Certificate < ApplicationRecord
|
|||
false
|
||||
end
|
||||
|
||||
def revoke!(password:)
|
||||
crt_file = create_tempfile('client_crt', crt)
|
||||
def revoke!(password:, reason: :unspecified)
|
||||
return false unless password == ENV['ca_key_password']
|
||||
|
||||
err_output = execute_openssl_revoke_command(password, crt_file.path)
|
||||
|
||||
if revocation_successful?(err_output)
|
||||
update_revocation_status
|
||||
self.class.update_crl
|
||||
return self
|
||||
end
|
||||
|
||||
handle_revocation_failure(err_output)
|
||||
update!(
|
||||
revoked: true,
|
||||
revoked_at: Time.current,
|
||||
revoked_reason: REVOCATION_REASONS[reason]
|
||||
)
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -112,7 +134,7 @@ class Certificate < ApplicationRecord
|
|||
cn = pc.scan(%r{\/CN=(.+)}).flatten.first
|
||||
self.common_name = cn.split('/').first
|
||||
self.md5 = OpenSSL::Digest::MD5.new(origin.to_der).to_s if crt
|
||||
self.interface = crt ? API : REGISTRAR
|
||||
self.interface = crt ? API : REGISTRAR if interface.blank?
|
||||
end
|
||||
|
||||
def create_tempfile(filename, content = '')
|
||||
|
|
|
@ -3,17 +3,6 @@ module Certificate::CertificateConcern
|
|||
extend ActiveSupport::Concern
|
||||
|
||||
class_methods do
|
||||
def tostdout(message)
|
||||
time = Time.zone.now.utc
|
||||
$stdout << "#{time} - #{message}\n" unless Rails.env.test?
|
||||
end
|
||||
|
||||
def update_crl
|
||||
tostdout('Running crlupdater')
|
||||
system('/bin/bash', ENV['crl_updater_path'].to_s)
|
||||
tostdout('Finished running crlupdater')
|
||||
end
|
||||
|
||||
def parse_md_from_string(crt)
|
||||
return if crt.blank?
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue