diff --git a/.rubocop.yml b/.rubocop.yml index 9358026..858f4b3 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -21,7 +21,6 @@ Layout/EmptyLinesAroundArguments: Enabled: false Metrics/AbcSize: - Max: 15.5 Exclude: - 'db/migrate/*.rb' @@ -48,7 +47,6 @@ Metrics/MethodLength: Naming/PredicateName: Exclude: - - 'app/forms/application_form.rb' - 'app/models/application_record.rb' Rails: diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 83917e4..d051891 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -21,12 +21,7 @@ private @current_account ||= current_user&.account end - def pundit_user - @pundit_user ||= ApplicationPolicy::Context.new( - account: current_account, - params: params, - ) - end + alias pundit_user current_account def set_raven_context Raven.user_context( diff --git a/app/controllers/asymmetric_keys_controller.rb b/app/controllers/asymmetric_keys_controller.rb deleted file mode 100644 index e09743f..0000000 --- a/app/controllers/asymmetric_keys_controller.rb +++ /dev/null @@ -1,60 +0,0 @@ -# frozen_string_literal: true - -class AsymmetricKeysController < ApplicationController - before_action :set_asymmetric_key, except: %i[index new create] - - # GET /asymmetric_keys - def index - authorize AsymmetricKey - @asymmetric_keys = policy_scope(AsymmetricKey).page(params[:page]) - end - - # GET /asymmetric_keys/:id - def show - authorize @asymmetric_key - - respond_to do |format| - format.html - format.pem do - send_data @asymmetric_key.public_key_pem, filename: 'public.pem' - end - end - end - - # GET /asymmetric_keys/new - def new - @asymmetric_key_form = AsymmetricKeyForm.new - authorize @asymmetric_key_form - end - - # POST /asymmetric_keys - def create - @asymmetric_key_form = AsymmetricKeyForm.new asymmetric_key_form_params - authorize @asymmetric_key_form - - result = ImportAsymmetricKey.call @asymmetric_key_form.attributes - - if result.failure? - @asymmetric_key_form.errors.add :public_key_pem - return render :new - end - - redirect_to after_create_url result.asymmetric_key - end - -private - - def set_asymmetric_key - @asymmetric_key = AsymmetricKey.find params[:id] - end - - def asymmetric_key_form_params - params.require(:asymmetric_key).permit( - :public_key_pem, - ) - end - - def after_create_url(asymmetric_key) - asymmetric_key_url(asymmetric_key) - end -end diff --git a/app/controllers/private_keys_controller.rb b/app/controllers/private_keys_controller.rb deleted file mode 100644 index e8f5ced..0000000 --- a/app/controllers/private_keys_controller.rb +++ /dev/null @@ -1,30 +0,0 @@ -# frozen_string_literal: true - -class PrivateKeysController < ApplicationController - before_action :set_asymmetric_key - before_action :set_secret - - # GET /asymmetric_keys/:asymmetric_key_id/private_key - def show - authorize PrivateKey.new(@asymmetric_key) - - @asymmetric_key.decrypt_private_key_pem - - respond_to do |format| - format.key do - send_data @asymmetric_key.private_key_pem, filename: 'private.key' - end - end - end - -private - - def set_asymmetric_key - @asymmetric_key = AsymmetricKey.find params[:asymmetric_key_id] - end - - def set_secret - @asymmetric_key.private_key_pem_secret = - Base64.urlsafe_decode64 params[:private_key_pem_secret] - end -end diff --git a/app/controllers/staffs/x509_certificates_controller.rb b/app/controllers/staffs/x509_certificates_controller.rb deleted file mode 100644 index 5d9ce25..0000000 --- a/app/controllers/staffs/x509_certificates_controller.rb +++ /dev/null @@ -1,63 +0,0 @@ -# frozen_string_literal: true - -class Staffs::X509CertificatesController < ApplicationController - before_action :set_x509_certificate, except: %i[index new create] - - # GET /staff/x509_certificates - def index - authorize %i[staff x509_certificate] - @x509_certificates = policy_scope( - X509Certificate, - policy_scope_class: Staff::X509CertificatePolicy::Scope, - ).page(params[:page]) - end - - # GET /staff/x509_certificates/:id - def show - authorize [:staff, @x509_certificate] - end - - # GET /staff/x509_certificates/new - def new - @x509_certificate_form = X509CertificateForm.new - authorize [:staff, @x509_certificate_form] - end - - # POST /staff/x509_certificates - def create - @x509_certificate_form = - X509CertificateForm.new x509_certificate_form_params - - authorize [:staff, @x509_certificate_form] - - return render :new unless @x509_certificate_form.valid? - - result = CreateRSAKeysAndX509SelfSignedCertificate.call \ - @x509_certificate_form.attributes.merge(account: current_account) - - redirect_to after_create_url result.certificate - end - -private - - def set_x509_certificate - @x509_certificate = X509Certificate.find params[:id] - end - - def x509_certificate_form_params - params.require(:x509_certificate).permit( - :distinguished_name, - :not_before, - :not_after, - ) - end - - def after_create_url(certificate) - staff_x509_certificate_url( - certificate, - private_key_pem_secret: Base64.urlsafe_encode64( - certificate.asymmetric_key.private_key_pem_secret, - ), - ) - end -end diff --git a/app/forms/application_form.rb b/app/forms/application_form.rb deleted file mode 100644 index f1f54ce..0000000 --- a/app/forms/application_form.rb +++ /dev/null @@ -1,16 +0,0 @@ -# frozen_string_literal: true - -class ApplicationForm - include ActiveModel::Model - include ActiveModel::Attributes - include ActiveModel::Validations::Callbacks - include ActiveRecord::AttributeAssignment - - def has_attribute?(name) - attributes.key?(name.to_s) - end - - def type_for_attribute(name) - self.class.attribute_types[name.to_s] - end -end diff --git a/app/forms/asymmetric_key_form.rb b/app/forms/asymmetric_key_form.rb deleted file mode 100644 index d8a3577..0000000 --- a/app/forms/asymmetric_key_form.rb +++ /dev/null @@ -1,13 +0,0 @@ -# frozen_string_literal: true - -class AsymmetricKeyForm < ApplicationForm - attribute :public_key_pem, :string - - def self.model_name - ActiveModel::Name.new(self, nil, AsymmetricKey.name) - end - - def self.policy_class - 'AsymmetricKeyPolicy' - end -end diff --git a/app/forms/x509_certificate_form.rb b/app/forms/x509_certificate_form.rb deleted file mode 100644 index a3b108d..0000000 --- a/app/forms/x509_certificate_form.rb +++ /dev/null @@ -1,31 +0,0 @@ -# frozen_string_literal: true - -class X509CertificateForm < ApplicationForm - attribute :distinguished_name, :string - attribute :not_before, :datetime - attribute :not_after, :datetime - - validates :distinguished_name, presence: true - - validates :not_before, presence: true - - validates :not_after, presence: true - - validate :can_be_parsed_with_openssl - - def self.model_name - ActiveModel::Name.new(self, nil, X509Certificate.name) - end - - def self.policy_class - 'X509CertificatePolicy' - end - -private - - def can_be_parsed_with_openssl - OpenSSL::X509::Name.parse distinguished_name if distinguished_name.present? - rescue - errors.add :distinguished_name - end -end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 0f37098..62522f6 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -module ApplicationHelper # rubocop:disable Metrics/ModuleLength +module ApplicationHelper def federal_subjects_controller? controller_path == 'federal_subjects' end @@ -13,34 +13,6 @@ module ApplicationHelper # rubocop:disable Metrics/ModuleLength [*negative_timezones_collection, *positive_timezones_collection].freeze end - def display_sha1(str) - str = String(str).upcase - raise 'Invalid format for SHA-1' unless str.match?(/\A[A-F0-9]{40}\z/) - - tag.small do - concat display_fingerprint str[0...20] - concat tag.br - concat display_fingerprint str[20..-1] - end - end - - def display_sha256(str) - str = String(str).upcase - raise 'Invalid format for SHA-256' unless str.match?(/\A[A-F0-9]{64}\z/) - - tag.small do - concat display_fingerprint str[0...32] - concat tag.br - concat display_fingerprint str[32..-1] - end - end - - def display_fingerprint(str) - tag.samp do - String(str).strip.upcase.each_char.each_slice(2).map(&:join).join(':') - end - end - def positive_timezones_collection 0.upto(11).flat_map do |n| s = n.to_s.rjust(2, '0') diff --git a/app/interactors/create_ecurve_keys.rb b/app/interactors/create_ecurve_keys.rb deleted file mode 100644 index 65c0634..0000000 --- a/app/interactors/create_ecurve_keys.rb +++ /dev/null @@ -1,77 +0,0 @@ -# frozen_string_literal: true - -class CreateEcurveKeys - include Interactor - - DEFAULT_CURVE = 'prime256v1' - - before :set_curve - - def call - context.asymmetric_key = - EcurveKey.create!(attributes, &:encrypt_private_key_pem) - - ClearAsymmetricPrivateKeyJob - .set(wait: AsymmetricKey::PRIVATE_KEY_CLEAR_DELAY) - .perform_later context.asymmetric_key.id - end - -private - - def set_curve - context.curve ||= DEFAULT_CURVE - context.curve = String(context.curve).freeze - raise 'Invalid curve' unless EcurveKey::CURVES.include? context.curve - end - - def pkey - @pkey ||= OpenSSL::PKey::EC.generate context.curve - end - - def pkey_public - @pkey_public ||= - OpenSSL::PKey::EC.new(pkey.public_key.group).tap do |pkey_public| - pkey_public.public_key = pkey.public_key - end - end - - def attributes - { - account: context.account, - - public_key_pem: public_key_pem, - public_key_der: public_key_der, - private_key_pem: private_key_pem, - - has_password: context.password.present?, - curve: context.curve, - sha1: sha1, - sha256: sha256, - } - end - - def sha1 - @sha1 ||= Digest::SHA1.hexdigest(pkey_public.to_der).freeze - end - - def sha256 - @sha256 ||= Digest::SHA256.hexdigest(pkey_public.to_der).freeze - end - - def public_key_pem - @public_key_pem ||= pkey_public.to_pem.freeze - end - - def public_key_der - @public_key_der ||= pkey_public.to_der.freeze - end - - def private_key_pem - @private_key_pem ||= - if context.password.present? - pkey.to_pem(OpenSSL::Cipher::AES256.new, context.password).freeze - else - pkey.to_pem.freeze - end - end -end diff --git a/app/interactors/create_rsa_keys.rb b/app/interactors/create_rsa_keys.rb deleted file mode 100644 index acd599a..0000000 --- a/app/interactors/create_rsa_keys.rb +++ /dev/null @@ -1,70 +0,0 @@ -# frozen_string_literal: true - -class CreateRSAKeys - include Interactor - - DEFAULT_BITS = 4096 - - before :set_bits - - def call - context.asymmetric_key = - RSAKey.create!(attributes, &:encrypt_private_key_pem) - - ClearAsymmetricPrivateKeyJob - .set(wait: AsymmetricKey::PRIVATE_KEY_CLEAR_DELAY) - .perform_later context.asymmetric_key.id - end - -private - - def set_bits - context.bits ||= DEFAULT_BITS - context.bits = Integer(context.bits) - raise 'Invalid key size' unless RSAKey::BITS.include? context.bits - end - - def pkey - @pkey ||= OpenSSL::PKey::RSA.new context.bits - end - - def attributes - { - account: context.account, - - public_key_pem: public_key_pem, - public_key_der: public_key_der, - private_key_pem: private_key_pem, - - has_password: context.password.present?, - bits: context.bits, - sha1: sha1, - sha256: sha256, - } - end - - def sha1 - @sha1 ||= Digest::SHA1.hexdigest(pkey.public_key.to_der).freeze - end - - def sha256 - @sha256 ||= Digest::SHA256.hexdigest(pkey.public_key.to_der).freeze - end - - def public_key_pem - @public_key_pem ||= pkey.public_key.to_pem.freeze - end - - def public_key_der - @public_key_der ||= pkey.public_key.to_der.freeze - end - - def private_key_pem - @private_key_pem ||= - if context.password.present? - pkey.to_pem(OpenSSL::Cipher::AES256.new, context.password).freeze - else - pkey.to_pem.freeze - end - end -end diff --git a/app/interactors/create_rsa_keys_and_x509_self_signed_certificate.rb b/app/interactors/create_rsa_keys_and_x509_self_signed_certificate.rb deleted file mode 100644 index df1ccc0..0000000 --- a/app/interactors/create_rsa_keys_and_x509_self_signed_certificate.rb +++ /dev/null @@ -1,13 +0,0 @@ -# frozen_string_literal: true - -class CreateRSAKeysAndX509SelfSignedCertificate - include Interactor::Organizer - - organize CreateRSAKeys, CreateX509SelfSignedCertificate - - around do |interactor| - ActiveRecord::Base.transaction do - interactor.call - end - end -end diff --git a/app/interactors/create_x509_self_signed_certificate.rb b/app/interactors/create_x509_self_signed_certificate.rb deleted file mode 100644 index 8c603fe..0000000 --- a/app/interactors/create_x509_self_signed_certificate.rb +++ /dev/null @@ -1,117 +0,0 @@ -# frozen_string_literal: true - -class CreateX509SelfSignedCertificate - include Interactor - - before do - context.not_before = Time.at(context.not_before).utc - context.not_after = Time.at(context.not_after).utc - end - - def call # rubocop:disable Metrics/AbcSize - context.certificate = X509Certificate.create!( - asymmetric_key: context.asymmetric_key, - pem: cert.to_pem, - subject: cert.subject.to_s, - issuer: cert.issuer.to_s, - not_before: cert.not_before, - not_after: cert.not_after, - ) - end - -private - - def private_key_pkey - @private_key_pkey ||= OpenSSL::PKey::RSA.new( - context.asymmetric_key.private_key_pem, - String(context.password), - ) - end - - def public_key_pkey - @public_key_pkey ||= OpenSSL::PKey::RSA.new( - context.asymmetric_key.public_key_pem, - String(context.password), - ) - end - - def subject - @subject ||= OpenSSL::X509::Name.parse context.distinguished_name - end - - def cert # rubocop:disable Metrics/AbcSize, Metrics/MethodLength - @cert ||= OpenSSL::X509::Certificate.new.tap do |cert| - cert.version = 2 - cert.serial = SecureRandom.rand 0...(2**16) - cert.subject = subject - cert.issuer = cert.subject - cert.public_key = public_key_pkey - cert.not_before = context.not_before - cert.not_after = context.not_after - - AddExtensions.call cert - - cert.sign private_key_pkey, OpenSSL::Digest::SHA256.new - end - end - - class AddExtensions - def self.call(cert) - new(cert).call - end - - def initialize(cert) - @cert = cert - end - - def call - cert.add_extension basic_constraints - cert.add_extension key_usage - cert.add_extension subject_key_ident - cert.add_extension authority_key_ident - end - - private - - attr_reader :cert - - def ext_factory - @ext_factory ||= OpenSSL::X509::ExtensionFactory.new.tap do |ext_factory| - ext_factory.subject_certificate = cert - ext_factory.issuer_certificate = cert - end - end - - def basic_constraints - @basic_constraints ||= ext_factory.create_extension( - 'basicConstraints', - 'CA:TRUE', - true, - ) - end - - def key_usage - @key_usage ||= ext_factory.create_extension( - 'keyUsage', - 'keyCertSign, cRLSign', - true, - ) - end - - def subject_key_ident - @subject_key_ident ||= ext_factory.create_extension( - 'subjectKeyIdentifier', - 'hash', - false, - ) - end - - def authority_key_ident - @authority_key_ident ||= ext_factory.create_extension( - 'authorityKeyIdentifier', - 'keyid:always,issuer:always', - false, - ) - end - end -end diff --git a/app/interactors/import_asymmetric_key.rb b/app/interactors/import_asymmetric_key.rb deleted file mode 100644 index 6e926c4..0000000 --- a/app/interactors/import_asymmetric_key.rb +++ /dev/null @@ -1,98 +0,0 @@ -# frozen_string_literal: true - -class ImportAsymmetricKey - include Interactor - - RSA_BITS_RE = /^RSA Public-Key: \((\d+) bit\)$/.freeze - ECURVE_CURVE_RE = /^ASN1 OID: ((-|\w)+)$/.freeze - - before :unset_asymmetric_key - before :sanitize_public_key_der - before :sanitize_public_key_pem - before :set_public_key_openssl_pkey - before :validate_public_key_der - before :validate_public_key_pem - - def call - if context.public_key_openssl_pkey.private? - context.fail! - end - - find_asymmetric_key - - return unless context.asymmetric_key.nil? - - case context.public_key_openssl_pkey - when OpenSSL::PKey::RSA then create_rsa_key - when OpenSSL::PKey::EC then create_ecurve_key - else context.fail! - end - end - - def find_asymmetric_key - context.asymmetric_key = AsymmetricKey.find_by( - public_key_der: context.public_key_openssl_pkey.to_der, - ) - end - - def create_rsa_key - context.asymmetric_key = RSAKey.create!( - public_key_pem: context.public_key_openssl_pkey.to_pem, - public_key_der: context.public_key_openssl_pkey.to_der, - sha1: Digest::SHA1.hexdigest(context.public_key_openssl_pkey.to_der), - sha256: Digest::SHA256.hexdigest(context.public_key_openssl_pkey.to_der), - bits: context.public_key_openssl_pkey.to_text.lines - .grep(RSA_BITS_RE).first.match(RSA_BITS_RE)[1].to_i, - ) - end - - def create_ecurve_key - context.asymmetric_key = EcurveKey.create!( - public_key_pem: context.public_key_openssl_pkey.to_pem, - public_key_der: context.public_key_openssl_pkey.to_der, - sha1: Digest::SHA1.hexdigest(context.public_key_openssl_pkey.to_der), - sha256: Digest::SHA256.hexdigest(context.public_key_openssl_pkey.to_der), - curve: context.public_key_openssl_pkey.to_text.lines - .grep(ECURVE_CURVE_RE).first.match(ECURVE_CURVE_RE)[1], - ) - end - -private - - def unset_asymmetric_key - context.asymmetric_key = nil - end - - def sanitize_public_key_der - context.public_key_der = String(context.public_key_der).presence&.dup.freeze - end - - def sanitize_public_key_pem - context.public_key_pem = String(context.public_key_pem).lines.map do |line| - "#{line.strip}\n" - end.join.presence.freeze - end - - def set_public_key_openssl_pkey - context.public_key_openssl_pkey ||= OpenSSL::PKey.read( - context.public_key_der || context.public_key_pem || '', - '', - ) - rescue OpenSSL::PKey::PKeyError - context.fail! - end - - def validate_public_key_der - return if context.public_key_der.blank? - return if context.public_key_der == context.public_key_openssl_pkey.to_der - - raise 'Invalid DER' - end - - def validate_public_key_pem - return if context.public_key_pem.blank? - return if context.public_key_pem == context.public_key_openssl_pkey.to_pem - - raise 'Invalid PEM' - end -end diff --git a/app/jobs/clear_asymmetric_private_key_job.rb b/app/jobs/clear_asymmetric_private_key_job.rb deleted file mode 100644 index e42309b..0000000 --- a/app/jobs/clear_asymmetric_private_key_job.rb +++ /dev/null @@ -1,11 +0,0 @@ -# frozen_string_literal: true - -class ClearAsymmetricPrivateKeyJob < ApplicationJob - queue_as :default - - def perform(asymmetric_key_id) - AsymmetricKey - .find(asymmetric_key_id) - .update! private_key_pem_iv: nil, private_key_pem_ciphertext: nil - end -end diff --git a/app/models/asymmetric_key.rb b/app/models/asymmetric_key.rb deleted file mode 100644 index 492673f..0000000 --- a/app/models/asymmetric_key.rb +++ /dev/null @@ -1,84 +0,0 @@ -# frozen_string_literal: true - -class AsymmetricKey < ApplicationRecord - PRIVATE_KEY_CLEAR_DELAY = 1.hour.freeze - - attr_accessor :private_key_pem, :private_key_pem_secret - - ################ - # Associations # - ################ - - belongs_to :account, optional: true - - ############### - # Validations # - ############### - - validates :public_key_pem, - presence: true, - uniqueness: true - - validates :public_key_der, - presence: true, - uniqueness: true - - validates :bits, - allow_nil: true, - numericality: { - only_integer: true, - greater_than: 0, - } - - validates :sha1, - presence: true, - uniqueness: { case_sensitive: false } - - validates :sha256, - presence: true, - uniqueness: { case_sensitive: false } - - ########### - # Methods # - ########### - - def self.policy_class - AsymmetricKeyPolicy - end - - def algo_class - raise NotImplementedError, "#{self.class}#algo_class" - end - - def algo_variant - raise NotImplementedError, "#{self.class}#algo_variant" - end - - def encrypt_private_key_pem - cipher = OpenSSL::Cipher::AES256.new - cipher.encrypt - - self.private_key_pem_iv = cipher.random_iv.freeze - self.private_key_pem_secret = cipher.random_key.freeze - - self.private_key_pem_ciphertext = [ - cipher.update(private_key_pem), - cipher.final, - ].join.freeze - - private_key_pem_secret - end - - def decrypt_private_key_pem - cipher = OpenSSL::Cipher::AES256.new - cipher.decrypt - - cipher.iv = private_key_pem_iv - cipher.key = private_key_pem_secret - - self.private_key_pem = [ - cipher.update(private_key_pem_ciphertext), - cipher.final, - ].join.freeze - end -end diff --git a/app/models/ecurve_key.rb b/app/models/ecurve_key.rb deleted file mode 100644 index c51a692..0000000 --- a/app/models/ecurve_key.rb +++ /dev/null @@ -1,26 +0,0 @@ -# frozen_string_literal: true - -class EcurveKey < AsymmetricKey - ALGO_CLASS = 'Elliptic curve' - CURVES = %w[prime256v1 secp384r1].freeze - - ############### - # Validations # - ############### - - validates :curve, inclusion: { in: CURVES } - - validates :bits, absence: true - - ########### - # Methods # - ########### - - def algo_class - ALGO_CLASS - end - - def algo_variant - curve - end -end diff --git a/app/models/rsa_key.rb b/app/models/rsa_key.rb deleted file mode 100644 index ecae296..0000000 --- a/app/models/rsa_key.rb +++ /dev/null @@ -1,26 +0,0 @@ -# frozen_string_literal: true - -class RSAKey < AsymmetricKey - ALGO_CLASS = 'RSA' - BITS = [2048, 4096].freeze - - ############### - # Validations # - ############### - - validates :bits, inclusion: { in: BITS } - - validates :curve, absence: true - - ########### - # Methods # - ########### - - def algo_class - ALGO_CLASS - end - - def algo_variant - "#{bits} bits" - end -end diff --git a/app/models/x509_certificate.rb b/app/models/x509_certificate.rb deleted file mode 100644 index 341ac85..0000000 --- a/app/models/x509_certificate.rb +++ /dev/null @@ -1,33 +0,0 @@ -# frozen_string_literal: true - -class X509Certificate < ApplicationRecord - ################ - # Associations # - ################ - - belongs_to :asymmetric_key - - ############### - # Validations # - ############### - - validates :pem, presence: true - - validates :subject, presence: true - - validates :issuer, presence: true - - validates :not_before, presence: true - - validates :not_after, presence: true - - validate :can_be_parsed_and_exported_with_openssl - -private - - def can_be_parsed_and_exported_with_openssl - OpenSSL::X509::Certificate.new(pem)&.to_text if pem.present? - rescue - errors.add :pem - end -end diff --git a/app/policies/application_policy.rb b/app/policies/application_policy.rb index 7f7c50b..b104255 100644 --- a/app/policies/application_policy.rb +++ b/app/policies/application_policy.rb @@ -1,12 +1,10 @@ # frozen_string_literal: true class ApplicationPolicy - attr_reader :context, :record + attr_reader :account, :record - delegate :account, :params, to: :context, allow_nil: true - - def initialize(context, record) - @context = context + def initialize(account, record) + @account = account @record = record end @@ -53,12 +51,10 @@ private end class Scope - attr_reader :context, :scope + attr_reader :account, :scope - delegate :account, :params, to: :context, allow_nil: true - - def initialize(context, scope) - @context = context + def initialize(account, scope) + @account = account @scope = scope end @@ -76,13 +72,4 @@ private Rails.application.restricted? end end - - class Context - attr_reader :account, :params - - def initialize(account:, params:) - @account = account - @params = params - end - end end diff --git a/app/policies/asymmetric_key_policy.rb b/app/policies/asymmetric_key_policy.rb deleted file mode 100644 index c9a766c..0000000 --- a/app/policies/asymmetric_key_policy.rb +++ /dev/null @@ -1,21 +0,0 @@ -# frozen_string_literal: true - -class AsymmetricKeyPolicy < ApplicationPolicy - def index? - true - end - - def show? - true - end - - def create? - true - end - - class Scope < Scope - def resolve - scope.all - end - end -end diff --git a/app/policies/private_key_policy.rb b/app/policies/private_key_policy.rb deleted file mode 100644 index e7df983..0000000 --- a/app/policies/private_key_policy.rb +++ /dev/null @@ -1,14 +0,0 @@ -# frozen_string_literal: true - -class PrivateKeyPolicy < ApplicationPolicy - def show? - show_alert? && record.exist? - end - - def show_alert? - return false if account.nil? - - params[:private_key_pem_secret].present? && - (account.superuser? || account == record.account) - end -end diff --git a/app/policies/staff/x509_certificate_policy.rb b/app/policies/staff/x509_certificate_policy.rb deleted file mode 100644 index 17fc68a..0000000 --- a/app/policies/staff/x509_certificate_policy.rb +++ /dev/null @@ -1,31 +0,0 @@ -# frozen_string_literal: true - -class Staff::X509CertificatePolicy < ApplicationPolicy - def index? - return false if restricted? - - account&.superuser? - end - - def show? - return false if restricted? - - account&.superuser? - end - - def create? - return false if restricted? - - account&.superuser? - end - - class Scope < Scope - def resolve - return scope.none if restricted? - - return scope.all if account&.superuser? - - scope.none - end - end -end diff --git a/app/primitives/private_key.rb b/app/primitives/private_key.rb deleted file mode 100644 index 441cf05..0000000 --- a/app/primitives/private_key.rb +++ /dev/null @@ -1,20 +0,0 @@ -# frozen_string_literal: true - -class PrivateKey - attr_reader :asymmetric_key - - delegate :account, to: :asymmetric_key - - def self.policy_class - 'PrivateKeyPolicy' - end - - def initialize(asymmetric_key) - @asymmetric_key = asymmetric_key or raise - end - - def exist? - asymmetric_key.private_key_pem_iv.present? && - asymmetric_key.private_key_pem_ciphertext.present? - end -end diff --git a/app/views/asymmetric_keys/_table.html.erb b/app/views/asymmetric_keys/_table.html.erb deleted file mode 100644 index 1859764..0000000 --- a/app/views/asymmetric_keys/_table.html.erb +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - <% asymmetric_keys.each do |asymmetric_key| %> - - - - - - - <% end %> - -
- <%= AsymmetricKey.human_attribute_name :id %> - - <%= AsymmetricKey.human_attribute_name :algo_class %> - - <%= AsymmetricKey.human_attribute_name :algo_variant %> -
<%= asymmetric_key.id %><%= asymmetric_key.algo_class %><%= asymmetric_key.algo_variant %> - <% if policy(asymmetric_key).show? %> - <%= open_action asymmetric_key_path(asymmetric_key) %> - <% end %> -
diff --git a/app/views/asymmetric_keys/index.html.erb b/app/views/asymmetric_keys/index.html.erb deleted file mode 100644 index 315ef60..0000000 --- a/app/views/asymmetric_keys/index.html.erb +++ /dev/null @@ -1,20 +0,0 @@ -
- <%= nav_breadcrumb AsymmetricKey.model_name.human count: 0 %> - - <% if policy(AsymmetricKey).new? %> -
- <% if policy(AsymmetricKey).new? %> - <%= link_to translate(:add_existing), - new_asymmetric_key_path, - class: 'btn btn-primary', - role: :button %> - <% end %> -
- <% end %> - -
- <%= render partial: 'table', - locals: { asymmetric_keys: @asymmetric_keys } %> - <%= pagination @asymmetric_keys %> -
-
diff --git a/app/views/asymmetric_keys/new.html.erb b/app/views/asymmetric_keys/new.html.erb deleted file mode 100644 index 2a409a3..0000000 --- a/app/views/asymmetric_keys/new.html.erb +++ /dev/null @@ -1,14 +0,0 @@ -
- <%= nav_breadcrumb( - [AsymmetricKey.model_name.human(count: 0), asymmetric_keys_path], - translate(:add_existing), - ) %> - - <%= simple_form_for @asymmetric_key_form do |f| %> - <%= f.error_notification %> - - <%= f.input :public_key_pem, as: :text %> - - <%= f.button :submit %> - <% end %> -
diff --git a/app/views/asymmetric_keys/show.html.erb b/app/views/asymmetric_keys/show.html.erb deleted file mode 100644 index f4321c0..0000000 --- a/app/views/asymmetric_keys/show.html.erb +++ /dev/null @@ -1,35 +0,0 @@ -
- <%= nav_breadcrumb( - [AsymmetricKey.model_name.human(count: 0), asymmetric_keys_path], - AsymmetricKey.model_name.human(count: 1), - ) %> - -
-
-
-
<%= AsymmetricKey.human_attribute_name :id %>
-
<%= @asymmetric_key.id %>
- -
<%= AsymmetricKey.human_attribute_name :algo_class %>
-
<%= @asymmetric_key.algo_class %>
- -
<%= AsymmetricKey.human_attribute_name :algo_variant %>
-
<%= @asymmetric_key.algo_variant %>
- -
<%= AsymmetricKey.human_attribute_name :sha1 %>
-
<%= display_sha1 @asymmetric_key.sha1 %>
- -
<%= AsymmetricKey.human_attribute_name :sha256 %>
-
<%= display_sha256 @asymmetric_key.sha256 %>
-
-
- -
- <%= render partial: 'private_keys/alert', - locals: { - asymmetric_key: @asymmetric_key, - } - %> -
-
-
diff --git a/app/views/private_keys/_alert.html.erb b/app/views/private_keys/_alert.html.erb deleted file mode 100644 index d7ab38e..0000000 --- a/app/views/private_keys/_alert.html.erb +++ /dev/null @@ -1,40 +0,0 @@ -<% if policy(PrivateKey.new(asymmetric_key)).show_alert? %> - <% if policy(PrivateKey.new(asymmetric_key)).show? %> - - <% else %> - - <% end %> -<% end %> diff --git a/app/views/staffs/home/show.html.erb b/app/views/staffs/home/show.html.erb index cc92109..1810054 100644 --- a/app/views/staffs/home/show.html.erb +++ b/app/views/staffs/home/show.html.erb @@ -26,12 +26,5 @@ staff_contact_networks_path %> <% end %> - - <% if policy(%i[staff x509_certificate]).index? %> -
  • - <%= link_to X509Certificate.model_name.human(count: 0), - staff_x509_certificates_path %> -
  • - <% end %> diff --git a/app/views/staffs/x509_certificates/_table.html.erb b/app/views/staffs/x509_certificates/_table.html.erb deleted file mode 100644 index 03b2ea3..0000000 --- a/app/views/staffs/x509_certificates/_table.html.erb +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - <% x509_certificates.each do |x509_certificate| %> - - - - - - - <% end %> - -
    - <%= X509Certificate.human_attribute_name :id %> - - <%= X509Certificate.human_attribute_name :not_before %> - - <%= X509Certificate.human_attribute_name :not_after %> -
    <%= x509_certificate.id %><%= localize x509_certificate.not_before, format: :long %><%= localize x509_certificate.not_after, format: :long %> - <% if policy([:staff, x509_certificate]).show? %> - <%= open_action [:staff, x509_certificate] %> - <% end %> -
    diff --git a/app/views/staffs/x509_certificates/index.html.erb b/app/views/staffs/x509_certificates/index.html.erb deleted file mode 100644 index 1ea7bdc..0000000 --- a/app/views/staffs/x509_certificates/index.html.erb +++ /dev/null @@ -1,23 +0,0 @@ -
    - <%= nav_breadcrumb( - [translate(:staff_services), staff_root_path], - X509Certificate.model_name.human(count: 0), - ) %> - - <% if policy([:staff, X509Certificate]).new? %> -
    - <% if policy([:staff, X509Certificate]).new? %> - <%= link_to translate(:create), - new_staff_x509_certificate_path, - class: 'btn btn-primary', - role: :button %> - <% end %> -
    - <% end %> - -
    - <%= render partial: 'table', - locals: { x509_certificates: @x509_certificates } %> - <%= pagination @x509_certificates %> -
    -
    diff --git a/app/views/staffs/x509_certificates/new.html.erb b/app/views/staffs/x509_certificates/new.html.erb deleted file mode 100644 index 0ca5429..0000000 --- a/app/views/staffs/x509_certificates/new.html.erb +++ /dev/null @@ -1,17 +0,0 @@ -
    - <%= nav_breadcrumb( - [translate(:staff_services), staff_root_path], - [X509Certificate.model_name.human(count: 0), staff_x509_certificates_path], - translate(:create), - ) %> - - <%= simple_form_for [:staff, @x509_certificate_form] do |f| %> - <%= f.error_notification %> - - <%= f.input :distinguished_name %> - <%= f.input :not_before %> - <%= f.input :not_after %> - - <%= f.button :submit %> - <% end %> -
    diff --git a/app/views/staffs/x509_certificates/show.html.erb b/app/views/staffs/x509_certificates/show.html.erb deleted file mode 100644 index 19d16f7..0000000 --- a/app/views/staffs/x509_certificates/show.html.erb +++ /dev/null @@ -1,86 +0,0 @@ -
    - <%= nav_breadcrumb( - [translate(:staff_services), staff_root_path], - [X509Certificate.model_name.human(count: 0), staff_x509_certificates_path], - X509Certificate.model_name.human(count: 1), - ) %> - -
    - -
    - -
    -
    -
    -
    -
    -
    <%= X509Certificate.human_attribute_name :id %>
    -
    <%= @x509_certificate.id %>
    - -
    <%= X509Certificate.human_attribute_name :subject %>
    -
    <%= truncate @x509_certificate.subject %>
    - -
    <%= X509Certificate.human_attribute_name :issuer %>
    -
    <%= truncate @x509_certificate.issuer %>
    - -
    <%= X509Certificate.human_attribute_name :not_before %>
    -
    <%= localize @x509_certificate.not_before, format: :long %>
    - -
    <%= X509Certificate.human_attribute_name :not_after %>
    -
    <%= localize @x509_certificate.not_after, format: :long %>
    -
    -
    - -
    - <%= render partial: 'private_keys/alert', - locals: { - asymmetric_key: @x509_certificate.asymmetric_key, - } - %> -
    -
    -
    - -
    -
    <%= @x509_certificate.pem %>
    -
    - -
    -
    <%= OpenSSL::X509::Certificate.new(@x509_certificate.pem).to_text %>
    -
    -
    -
    diff --git a/config/application.rb b/config/application.rb index 3f6bf6a..b261096 100644 --- a/config/application.rb +++ b/config/application.rb @@ -26,7 +26,6 @@ module Partynest confirmation_token password password_confirmation - private_key_pem_secret reset_password_token secret unlock_token @@ -61,7 +60,6 @@ module Partynest # Custom directories with classes and modules you want to be autoloadable. config.autoload_paths += [ - config.root.join('app', 'forms'), config.root.join('app', 'primitives'), config.root.join('app', 'validators'), config.root.join('lib'), diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb index 04d25ad..dc84742 100644 --- a/config/initializers/inflections.rb +++ b/config/initializers/inflections.rb @@ -12,6 +12,7 @@ # inflect.uncountable %w( fish sheep ) # end -ActiveSupport::Inflector.inflections :en do |inflect| - inflect.acronym 'RSA' -end +# These inflection rules are supported but not enabled by default: +# ActiveSupport::Inflector.inflections(:en) do |inflect| +# inflect.acronym 'RESTful' +# end diff --git a/config/initializers/mime_types.rb b/config/initializers/mime_types.rb index b979bfa..be6fedc 100644 --- a/config/initializers/mime_types.rb +++ b/config/initializers/mime_types.rb @@ -2,5 +2,5 @@ # Be sure to restart your server when you modify this file. -Mime::Type.register 'application/pkcs8', :key -Mime::Type.register 'application/x-pem-file', :pem +# Add new mime types for use in respond_to blocks: +# Mime::Type.register "text/richtext", :rtf diff --git a/config/locales/activemodel/en.yml b/config/locales/activemodel/en.yml deleted file mode 100644 index c32c675..0000000 --- a/config/locales/activemodel/en.yml +++ /dev/null @@ -1,9 +0,0 @@ -en: - activemodel: - attributes: - asymmetric_key: - public_key_pem: Public key in PEM format - x509_certificate: - distinguished_name: Distinguished name - not_before: Active since - not_after: Expires at diff --git a/config/locales/activemodel/ru.yml b/config/locales/activemodel/ru.yml deleted file mode 100644 index 773cc00..0000000 --- a/config/locales/activemodel/ru.yml +++ /dev/null @@ -1,9 +0,0 @@ -ru: - activemodel: - attributes: - asymmetric_key: - public_key_pem: Публичный ключ в формате PEM - x509_certificate: - distinguished_name: Уникальное имя (distinguished name) - not_before: Активен с - not_after: Истекает diff --git a/config/locales/activerecord/en.yml b/config/locales/activerecord/en.yml index bce4556..325ea66 100644 --- a/config/locales/activerecord/en.yml +++ b/config/locales/activerecord/en.yml @@ -4,10 +4,6 @@ en: account: one: Account many: Accounts - asymmetric_key: - one: Public key - few: Public keys - many: Public keys contact: one: Contact few: Contacts @@ -40,10 +36,6 @@ en: user: one: User many: Users - x509_certificate: - one: X509 certificate - few: X509 certificates - many: X509 certificates attributes: account: id: ID @@ -53,12 +45,6 @@ en: avatar: Avatar person: Person timezone: Timezone - asymmetric_key: - id: ID - algo_class: Algorithm class - algo_variant: Variant - sha1: SHA-1 fingerprint - sha256: SHA-256 fingerprint contact: id: ID contact_network: Contact network @@ -145,13 +131,6 @@ en: unconfirmed_email: Unconfirmed email unlock_token: Unlock token updated_at: Updated at - x509_certificate: - id: ID - pem: PEM - subject: Subject - issuer: Issuer - not_before: Active since - not_after: Expires at errors: messages: image_size: 'has too big size' diff --git a/config/locales/activerecord/ru.yml b/config/locales/activerecord/ru.yml index 62192b8..3dd6ffc 100644 --- a/config/locales/activerecord/ru.yml +++ b/config/locales/activerecord/ru.yml @@ -4,10 +4,6 @@ ru: account: one: Аккаунт many: Аккаунты - asymmetric_key: - one: Публичный ключ - few: Публичных ключа - many: Публичные ключи contact: one: Контакт few: Контакта @@ -40,10 +36,6 @@ ru: user: one: Пользователь many: Пользователи - x509_certificate: - one: Сертификат X509 - few: Сертификатов X509 - many: Сертификаты X509 attributes: account: id: ID @@ -53,12 +45,6 @@ ru: avatar: Аватар person: Человек timezone: Часовой пояс - asymmetric_key: - id: ID - algo_class: Класс алгоритма - algo_variant: Вариант - sha1: Отпечаток SHA-1 - sha256: Отпечаток SHA-256 contact: id: ID contact_network: Сеть контактов @@ -145,13 +131,6 @@ ru: unconfirmed_email: Неподтвержденный email unlock_token: Токен разблокировки updated_at: Дата обновления - x509_certificate: - id: ID - pem: PEM - subject: Имя субъекта - issuer: Имя издателя - not_before: Активен с - not_after: Истекает errors: messages: image_size: 'имеет слишком большой размер' diff --git a/config/locales/helpers/en.yml b/config/locales/helpers/en.yml index c5b4d2b..c0c2bf6 100644 --- a/config/locales/helpers/en.yml +++ b/config/locales/helpers/en.yml @@ -11,8 +11,6 @@ en: display_entries: 'Displaying %{entry_name} %{first} - %{last} of %{total} in total' submit: - asymmetric_key: - create: Add person: create: Send person_comment: diff --git a/config/locales/helpers/ru.yml b/config/locales/helpers/ru.yml index 055425a..6c69312 100644 --- a/config/locales/helpers/ru.yml +++ b/config/locales/helpers/ru.yml @@ -11,8 +11,6 @@ ru: display_entries: 'Отображение %{entry_name} %{first} - %{last} из %{total} всего' submit: - asymmetric_key: - create: Добавить person: create: Отправить person_comment: diff --git a/config/locales/lazy/en.yml b/config/locales/lazy/en.yml index 39ba432..03e56cf 100644 --- a/config/locales/lazy/en.yml +++ b/config/locales/lazy/en.yml @@ -16,23 +16,6 @@ en: If this was you, you can ignore this alert. If you suspect any suspicious activity on your account, please change your password and enable two-factor authentication - private_keys: - alert: - link: Download - primary_header: >- - Your private key is ready, but you have to download it right now! - secondary_header: >- - Your private key was deleted. - primary_text: >- - For better security we have encrypted your private key - with temporary secret token. You can download it until - you leave this page. Also note that key will be deleted - in %{delay} after creation anyway. - secondary_text: >- - For better security we have deleted your private key. - Hope you have downloaded it, because we can not restore it. - If you haven't downloaded it, you have to repeat the whole - procedure to generate new private key. staffs: people: show: diff --git a/config/locales/lazy/ru.yml b/config/locales/lazy/ru.yml index f909bb7..0b44b79 100644 --- a/config/locales/lazy/ru.yml +++ b/config/locales/lazy/ru.yml @@ -17,23 +17,6 @@ ru: Если это были вы, можете проигнорировать это предупреждение. Если вы заметили подозрительную активность вашего аккаунта, пожалуйста измените пароль и включите двухфакторную аутентификацию - private_keys: - alert: - link: Скачать - primary_header: >- - Ваш приватный ключ готов, но вы должны скачать его прямо сейчас! - secondary_header: >- - Ваш приватный ключ был удалён. - primary_text: >- - Для большей безопасности мы зашифровали ваш приватный ключ - с помощью временного токена. Вы можете скачать его пока не покините - эту страницу. Также учтите, что ключ будет уничтожен через %{delay} - после создания в любом случае. - secondary_text: >- - Для большей безопасности мы удалили ваш приватный ключ. - Надеемся, что вы его скачали, потому что мы не можем его восстановить. - Если вы не скачали его, вам придётся повторить всю процедуру сначала - чтобы сгенерировать новый приватный ключ. settings: people: show: diff --git a/config/locales/nav_tabs/en.yml b/config/locales/nav_tabs/en.yml index 7c6e165..9556546 100644 --- a/config/locales/nav_tabs/en.yml +++ b/config/locales/nav_tabs/en.yml @@ -12,7 +12,3 @@ en: person: Person contacts: Contacts sessions: Sessions - x509_certificate: - overview: Overview - pem: PEM - text: Text diff --git a/config/locales/nav_tabs/ru.yml b/config/locales/nav_tabs/ru.yml index 7001dfd..fa58b02 100644 --- a/config/locales/nav_tabs/ru.yml +++ b/config/locales/nav_tabs/ru.yml @@ -12,7 +12,3 @@ ru: person: Личность contacts: Контакты sessions: Сессии - x509_certificate: - overview: Обзор - pem: PEM - text: Текст diff --git a/config/locales/other/en.yml b/config/locales/other/en.yml index 89615ed..667c040 100644 --- a/config/locales/other/en.yml +++ b/config/locales/other/en.yml @@ -12,4 +12,3 @@ en: save: Save hello: Hello new_sign_in: New sign in to your account - add_existing: Add existing diff --git a/config/locales/other/ru.yml b/config/locales/other/ru.yml index 6489f90..4bef694 100644 --- a/config/locales/other/ru.yml +++ b/config/locales/other/ru.yml @@ -12,4 +12,3 @@ ru: save: Сохранить hello: Здравствуйте new_sign_in: Произведён вход в ваш аккаунт - add_existing: Добавить существующий diff --git a/config/routes.rb b/config/routes.rb index 44c6783..ee43e8a 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -13,10 +13,6 @@ Rails.application.routes.draw do resources :federal_subjects, param: :number, only: %i[index show] - resources :asymmetric_keys, only: %i[index show new create] do - resource :private_key, only: :show - end - ############### # User routes # ############### @@ -65,8 +61,6 @@ Rails.application.routes.draw do resources :accounts, param: :nickname, only: %i[index show] - resources :x509_certificates, only: %i[index show new create] - resources :people, only: %i[index show new create] do resources :person_comments, path: 'comments', diff --git a/db/migrate/20190915131325_drop_x509_tables.rb b/db/migrate/20190915131325_drop_x509_tables.rb new file mode 100644 index 0000000..686c537 --- /dev/null +++ b/db/migrate/20190915131325_drop_x509_tables.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +class DropX509Tables < ActiveRecord::Migration[6.0] + def change + drop_table :x509_certificates + drop_table :asymmetric_keys + end +end diff --git a/db/structure.sql b/db/structure.sql index 9886492..5b119a5 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -364,49 +364,6 @@ CREATE TABLE public.ar_internal_metadata ( ); --- --- Name: asymmetric_keys; Type: TABLE; Schema: public; Owner: - --- - -CREATE TABLE public.asymmetric_keys ( - id bigint NOT NULL, - created_at timestamp(6) without time zone NOT NULL, - updated_at timestamp(6) without time zone NOT NULL, - type character varying NOT NULL, - account_id bigint, - public_key_pem text NOT NULL, - public_key_der bytea NOT NULL, - private_key_pem_iv bytea, - private_key_pem_ciphertext bytea, - has_password boolean, - sha1 character varying NOT NULL, - sha256 character varying NOT NULL, - bits integer, - curve character varying, - CONSTRAINT bits CHECK (((bits IS NULL) OR (bits = ANY (ARRAY[2048, 4096])))), - CONSTRAINT curve CHECK (((curve IS NULL) OR ((curve)::text = ANY ((ARRAY['prime256v1'::character varying, 'secp384r1'::character varying])::text[])))) -); - - --- --- Name: asymmetric_keys_id_seq; Type: SEQUENCE; Schema: public; Owner: - --- - -CREATE SEQUENCE public.asymmetric_keys_id_seq - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - --- --- Name: asymmetric_keys_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - --- - -ALTER SEQUENCE public.asymmetric_keys_id_seq OWNED BY public.asymmetric_keys.id; - - -- -- Name: contact_lists; Type: TABLE; Schema: public; Owner: - -- @@ -924,42 +881,6 @@ CREATE SEQUENCE public.users_id_seq ALTER SEQUENCE public.users_id_seq OWNED BY public.users.id; --- --- Name: x509_certificates; Type: TABLE; Schema: public; Owner: - --- - -CREATE TABLE public.x509_certificates ( - id bigint NOT NULL, - created_at timestamp(6) without time zone NOT NULL, - updated_at timestamp(6) without time zone NOT NULL, - asymmetric_key_id bigint NOT NULL, - pem text NOT NULL, - subject character varying NOT NULL, - issuer character varying NOT NULL, - not_before timestamp without time zone NOT NULL, - not_after timestamp without time zone NOT NULL -); - - --- --- Name: x509_certificates_id_seq; Type: SEQUENCE; Schema: public; Owner: - --- - -CREATE SEQUENCE public.x509_certificates_id_seq - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - --- --- Name: x509_certificates_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - --- - -ALTER SEQUENCE public.x509_certificates_id_seq OWNED BY public.x509_certificates.id; - - -- -- Name: accounts id; Type: DEFAULT; Schema: public; Owner: - -- @@ -981,13 +902,6 @@ ALTER TABLE ONLY public.active_storage_attachments ALTER COLUMN id SET DEFAULT n ALTER TABLE ONLY public.active_storage_blobs ALTER COLUMN id SET DEFAULT nextval('public.active_storage_blobs_id_seq'::regclass); --- --- Name: asymmetric_keys id; Type: DEFAULT; Schema: public; Owner: - --- - -ALTER TABLE ONLY public.asymmetric_keys ALTER COLUMN id SET DEFAULT nextval('public.asymmetric_keys_id_seq'::regclass); - - -- -- Name: contact_lists id; Type: DEFAULT; Schema: public; Owner: - -- @@ -1079,13 +993,6 @@ ALTER TABLE ONLY public.user_omniauths ALTER COLUMN id SET DEFAULT nextval('publ ALTER TABLE ONLY public.users ALTER COLUMN id SET DEFAULT nextval('public.users_id_seq'::regclass); --- --- Name: x509_certificates id; Type: DEFAULT; Schema: public; Owner: - --- - -ALTER TABLE ONLY public.x509_certificates ALTER COLUMN id SET DEFAULT nextval('public.x509_certificates_id_seq'::regclass); - - -- -- Name: accounts accounts_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- @@ -1118,14 +1025,6 @@ ALTER TABLE ONLY public.ar_internal_metadata ADD CONSTRAINT ar_internal_metadata_pkey PRIMARY KEY (key); --- --- Name: asymmetric_keys asymmetric_keys_pkey; Type: CONSTRAINT; Schema: public; Owner: - --- - -ALTER TABLE ONLY public.asymmetric_keys - ADD CONSTRAINT asymmetric_keys_pkey PRIMARY KEY (id); - - -- -- Name: contact_lists contact_lists_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- @@ -1238,14 +1137,6 @@ ALTER TABLE ONLY public.users ADD CONSTRAINT users_pkey PRIMARY KEY (id); --- --- Name: x509_certificates x509_certificates_pkey; Type: CONSTRAINT; Schema: public; Owner: - --- - -ALTER TABLE ONLY public.x509_certificates - ADD CONSTRAINT x509_certificates_pkey PRIMARY KEY (id); - - -- -- Name: index_accounts_on_contact_list_id; Type: INDEX; Schema: public; Owner: - -- @@ -1288,48 +1179,6 @@ CREATE UNIQUE INDEX index_active_storage_attachments_uniqueness ON public.active CREATE UNIQUE INDEX index_active_storage_blobs_on_key ON public.active_storage_blobs USING btree (key); --- --- Name: index_asymmetric_keys_on_account_id; Type: INDEX; Schema: public; Owner: - --- - -CREATE INDEX index_asymmetric_keys_on_account_id ON public.asymmetric_keys USING btree (account_id); - - --- --- Name: index_asymmetric_keys_on_public_key_der; Type: INDEX; Schema: public; Owner: - --- - -CREATE UNIQUE INDEX index_asymmetric_keys_on_public_key_der ON public.asymmetric_keys USING btree (public_key_der); - - --- --- Name: index_asymmetric_keys_on_public_key_pem; Type: INDEX; Schema: public; Owner: - --- - -CREATE UNIQUE INDEX index_asymmetric_keys_on_public_key_pem ON public.asymmetric_keys USING btree (public_key_pem); - - --- --- Name: index_asymmetric_keys_on_sha1; Type: INDEX; Schema: public; Owner: - --- - -CREATE UNIQUE INDEX index_asymmetric_keys_on_sha1 ON public.asymmetric_keys USING btree (sha1); - - --- --- Name: index_asymmetric_keys_on_sha256; Type: INDEX; Schema: public; Owner: - --- - -CREATE UNIQUE INDEX index_asymmetric_keys_on_sha256 ON public.asymmetric_keys USING btree (sha256); - - --- --- Name: index_asymmetric_keys_on_type_and_id; Type: INDEX; Schema: public; Owner: - --- - -CREATE UNIQUE INDEX index_asymmetric_keys_on_type_and_id ON public.asymmetric_keys USING btree (type, id); - - -- -- Name: index_contact_networks_on_codename; Type: INDEX; Schema: public; Owner: - -- @@ -1575,13 +1424,6 @@ CREATE UNIQUE INDEX index_users_on_reset_password_token ON public.users USING bt CREATE UNIQUE INDEX index_users_on_unlock_token ON public.users USING btree (unlock_token); --- --- Name: index_x509_certificates_on_asymmetric_key_id; Type: INDEX; Schema: public; Owner: - --- - -CREATE INDEX index_x509_certificates_on_asymmetric_key_id ON public.x509_certificates USING btree (asymmetric_key_id); - - -- -- Name: accounts ensure_contact_list_id_matches_related_person; Type: TRIGGER; Schema: public; Owner: - -- @@ -1619,14 +1461,6 @@ ALTER TABLE ONLY public.relationships ADD CONSTRAINT fk_rails_124c042ac0 FOREIGN KEY (initiator_account_id) REFERENCES public.accounts(id); --- --- Name: x509_certificates fk_rails_1671512c40; Type: FK CONSTRAINT; Schema: public; Owner: - --- - -ALTER TABLE ONLY public.x509_certificates - ADD CONSTRAINT fk_rails_1671512c40 FOREIGN KEY (asymmetric_key_id) REFERENCES public.asymmetric_keys(id); - - -- -- Name: people fk_rails_4f02f930eb; Type: FK CONSTRAINT; Schema: public; Owner: - -- @@ -1683,14 +1517,6 @@ ALTER TABLE ONLY public.regional_offices ADD CONSTRAINT fk_rails_7a6d5fdd9a FOREIGN KEY (federal_subject_id) REFERENCES public.federal_subjects(id); --- --- Name: asymmetric_keys fk_rails_7d85781ea1; Type: FK CONSTRAINT; Schema: public; Owner: - --- - -ALTER TABLE ONLY public.asymmetric_keys - ADD CONSTRAINT fk_rails_7d85781ea1 FOREIGN KEY (account_id) REFERENCES public.accounts(id); - - -- -- Name: user_omniauths fk_rails_8c1c9cb22e; Type: FK CONSTRAINT; Schema: public; Owner: - -- @@ -1759,6 +1585,7 @@ INSERT INTO "schema_migrations" (version) VALUES ('20190910040709'), ('20190911081459'), ('20190914050858'), -('20190915085803'); +('20190915085803'), +('20190915131325'); diff --git a/factories/ecurve_keys.rb b/factories/ecurve_keys.rb deleted file mode 100644 index 7d07794..0000000 --- a/factories/ecurve_keys.rb +++ /dev/null @@ -1,27 +0,0 @@ -# frozen_string_literal: true - -FactoryBot.define do - factory :ecurve_key do - association :account, factory: :usual_account - - public_key_pem do - point = OpenSSL::PKey::EC.generate(curve).public_key - pkey = OpenSSL::PKey::EC.new point.group - pkey.public_key = point - pkey.to_pem - end - - public_key_der do - point = OpenSSL::PKey::EC.generate(curve).public_key - pkey = OpenSSL::PKey::EC.new point.group - pkey.public_key = point - pkey.to_der - end - - has_password { [false, true].sample } - sha1 { Digest::SHA1.hexdigest SecureRandom.hex } - sha256 { Digest::SHA256.hexdigest SecureRandom.hex } - - curve { EcurveKey::CURVES.sample } - end -end diff --git a/factories/rsa_keys.rb b/factories/rsa_keys.rb deleted file mode 100644 index f75309d..0000000 --- a/factories/rsa_keys.rb +++ /dev/null @@ -1,16 +0,0 @@ -# frozen_string_literal: true - -FactoryBot.define do - factory :rsa_key do - association :account, factory: :usual_account - - public_key_pem { OpenSSL::PKey::RSA.new(bits).public_key.to_pem } - public_key_der { OpenSSL::PKey::RSA.new(bits).public_key.to_der } - - has_password { [false, true].sample } - sha1 { Digest::SHA1.hexdigest SecureRandom.hex } - sha256 { Digest::SHA256.hexdigest SecureRandom.hex } - - bits { RSAKey::BITS.sample } - end -end diff --git a/factories/x509_certificates.rb b/factories/x509_certificates.rb deleted file mode 100644 index cd397dd..0000000 --- a/factories/x509_certificates.rb +++ /dev/null @@ -1,13 +0,0 @@ -# frozen_string_literal: true - -FactoryBot.define do - factory :self_signed_x509_certificate, class: X509Certificate do - association :asymmetric_key, factory: :rsa_key - - pem { File.read Rails.root.join 'fixtures', 'ca.crt' } - subject { '/CN=example.com' } - issuer { subject } - not_before { Faker::Time.backward.utc } - not_after { Faker::Time.forward.utc } - end -end diff --git a/fixtures/ca.crt b/fixtures/ca.crt deleted file mode 100644 index 87a6799..0000000 --- a/fixtures/ca.crt +++ /dev/null @@ -1,30 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIFLzCCAxegAwIBAgIDAOcoMA0GCSqGSIb3DQEBCwUAMBYxFDASBgNVBAMMC2V4 -YW1wbGUuY29tMB4XDTE5MDkxMTEwMDcxMloXDTIwMDkxMDEwMDcxMlowFjEUMBIG -A1UEAwwLZXhhbXBsZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC -AQDSzS7+xkHL2KsB7P6jzbLPpAAqV7PCbuxqQsxWDHnadmJ4VCRNP8VuecT2hN1Q -tJRHb3FpooB+nFvjLt7b1rUoAoaBUF389UBsmCNPiAttGNGnRib0m4wVhxWhHLZ+ -rTuXrKjZjWci06aFj+rybQJjMYrcSx9/2MhaZpL7o7bsQ9gxV7ohmbEtNCLSGxAP -vfhNrhgx8aZi1ZHusior51pt35bhLst+ixvfG/fW8SrJ4rd6nAYlI52RXtkxOanX -wJYKDzsJC5lVptjP/s/PuZuYhTDiYlI69w0qK7dMu2HygzmMdCVmzsFVOyCPCZa6 -SbCSkntS0oSLugY7XSIRp6tD1Lz/FoaQcF8GswDkt4qE5lPOfT6y2xREv6rpTcrZ -kC1g/ztfcphkCAdSBHhM1WfZdx2RjpMnyjOGAVTiORX0qgXJ+WKIlzAf0JAmPAB+ -FM53hPqf+Py4v0jTYAjs+kR8lIoiPUaPIxIWbHFSHmPzQvtmh8V43N3GAXEMCGRw -seKoUvInUaq/EEtSoG6qBkXO7FSTwLGF6++VNa57ZGtqgDebf3OTvNQSrhGQRi1x -qp9yk+6ob8m2WLHjN6FNnA8R4J+X0RJNiyztTcQxa1BEeDS1fhk3zmsJyMCSa7RE -+Q8HPdY08JSUgcVqFazu9CFjv/NNGkaaWXoqSkdQKIlYGwIDAQABo4GFMIGCMA8G -A1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTkEQS/jMRY -5qI4Vm82EJ+qU0bXMjBABgNVHSMEOTA3gBTkEQS/jMRY5qI4Vm82EJ+qU0bXMqEa -pBgwFjEUMBIGA1UEAwwLZXhhbXBsZS5jb22CAwDnKDANBgkqhkiG9w0BAQsFAAOC -AgEAdlzNvT5JNGMKX7IStrAprY4rWpd3UkM36n2CriMrQHfyv0zWS277eiY+DNHf -Hx1qscYSA6YyKj5ow9BwVgKz0NoEjbX5CAN2EebmqKePXDNTgHkhx2h2+1S8JeQp -bOei0TANSiQpqCR8lO9kEi8+4vcHdfYC9Hn7EFXuW4xvYbxJ3YVmkRZDQ/3oUX0q -HevogupOtH6ZpemSkQx81VOMPoloCCwq9wU+yHDMcYRIxp8ySdsxEAMHTlBXW1wB -86eZ6TotzSgiK4VzYTth67O4dQaWYASA/CGBURVWuwV1kzMrDaZn+V8oySDBo9Ct -TM3K+UWjNuLlEwgpCMF8ze/TNaJQHg5R0ap34hb0nfdOnIComxM8kzXzmbODSinz -/VgndXjnlxiw+JTgR8Fuc5mBolnyZddj9QXTO83Ze0/u2lUU/RP93MrgPQAYGOa2 -IdnKhkiEvS0xhBdQWevgLLL3aRqfzdiHxXMZ3dtEAo2X5iAZtyH/ZFR8XNeFb2xm -yNjID1691R7HHzA/KIh89vimv47H1XdjpTlKS21WcS82pOPZndq4B0q788KZ2npo -33dSAd7PlWfzZQjooKEWXVbfTewkN5DIHmWZG8ZMqxLHtf0vzPy5UKe2KVLcZ3N1 -chdoswVOLa4omXy+pYGiLuhv+xEp/zev18hjcwz1b0Piuds= ------END CERTIFICATE----- diff --git a/spec/forms/x509_certificate_form_spec.rb b/spec/forms/x509_certificate_form_spec.rb deleted file mode 100644 index 3eb6bdd..0000000 --- a/spec/forms/x509_certificate_form_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -RSpec.describe X509CertificateForm, type: :model do - pending "add some examples to (or delete) #{__FILE__}" -end diff --git a/spec/interactors/create_ecurve_keys_spec.rb b/spec/interactors/create_ecurve_keys_spec.rb deleted file mode 100644 index 4f53096..0000000 --- a/spec/interactors/create_ecurve_keys_spec.rb +++ /dev/null @@ -1,194 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -RSpec.describe CreateEcurveKeys do - subject do - described_class.call account: account, password: password, curve: curve - end - - let(:account) { create :initial_account } - let(:password) { Faker::Internet.password } - let(:curve) { EcurveKey::CURVES.sample } - - specify do - expect { subject }.to change(AsymmetricKey, :count).by(1) - end - - specify do - expect { subject }.to change(EcurveKey, :count).by(1) - end - - specify do - expect { subject }.to( - have_enqueued_job(ClearAsymmetricPrivateKeyJob) - .with do |asymmetric_key_id| - expect(asymmetric_key_id).to equal AsymmetricKey.last.id - end, - ) - end - - specify do - expect(subject.asymmetric_key).to be_instance_of EcurveKey - end - - specify do - expect(subject.asymmetric_key.curve).to eq curve - end - - specify do - expect(subject.asymmetric_key.bits).to equal nil - end - - specify do - expect(subject.asymmetric_key.has_password).to equal true - end - - specify do - expect(subject.asymmetric_key.sha1).not_to be_blank - end - - specify do - expect(subject.asymmetric_key.sha256).not_to be_blank - end - - specify do - expect(subject.asymmetric_key.private_key_pem).not_to be_blank - end - - specify do - expect(subject.asymmetric_key.private_key_pem_secret).not_to be_blank - end - - specify do - expect(subject.asymmetric_key.account).to eq account - end - - specify do - expect do - OpenSSL::PKey::EC.new( - subject.asymmetric_key.private_key_pem, - String(password), - ) - end.not_to raise_error - end - - specify do - expect do - OpenSSL::PKey::EC.new( - subject.asymmetric_key.public_key_pem, - String(password), - ) - end.not_to raise_error - end - - specify do - expect(subject.asymmetric_key.sha1).to eq( - Digest::SHA1.hexdigest( - OpenSSL::PKey::EC.new( - subject.asymmetric_key.public_key_pem, - String(password), - ).to_der, - ), - ) - end - - specify do - expect(subject.asymmetric_key.sha256).to eq( - Digest::SHA256.hexdigest( - OpenSSL::PKey::EC.new( - subject.asymmetric_key.public_key_pem, - String(password), - ).to_der, - ), - ) - end - - specify do - private_key = OpenSSL::PKey::EC.new( - subject.asymmetric_key.private_key_pem, - String(password), - ) - - public_key = OpenSSL::PKey::EC.new private_key.public_key.group - public_key.public_key = private_key.public_key - - expect(subject.asymmetric_key.public_key_pem).to eq public_key.to_pem - end - - specify do - expect(subject.asymmetric_key.private_key_pem_iv).not_to be_blank - end - - specify do - expect(subject.asymmetric_key.private_key_pem_ciphertext).not_to be_blank - end - - specify do - cipher = OpenSSL::Cipher::AES256.new - cipher.decrypt - cipher.iv = subject.asymmetric_key.private_key_pem_iv - cipher.key = subject.asymmetric_key.private_key_pem_secret - - cleartext = [ - cipher.update(subject.asymmetric_key.private_key_pem_ciphertext), - cipher.final, - ].join.freeze - - expect(cleartext).to eq subject.asymmetric_key.private_key_pem - end - - context 'when owner is not specified' do - let(:account) { nil } - - specify do - expect(subject.asymmetric_key.account).to equal nil - end - end - - context 'when password is nil' do - let(:password) { nil } - - specify do - expect(subject.asymmetric_key.has_password).to equal false - end - end - - context 'when password is blank' do - let(:password) { ' ' * rand(1..3) } - - specify do - expect(subject.asymmetric_key.has_password).to equal false - end - end - - context 'when password.to_s returns nil' do - let :password do - Class.new do - def to_s - nil - end - end.new - end - - specify do - expect { subject }.to raise_error TypeError - end - end - - context 'when curve value is invalid' do - let(:curve) { 'secp521r1' } - - specify do - expect { subject }.to raise_error RuntimeError, 'Invalid curve' - end - end - - context 'when curve value is nil' do - let(:curve) { nil } - - specify do - expect(subject.asymmetric_key.curve).to eq 'prime256v1' - end - end -end diff --git a/spec/interactors/create_rsa_keys_and_x509_self_signed_certificate_spec.rb b/spec/interactors/create_rsa_keys_and_x509_self_signed_certificate_spec.rb deleted file mode 100644 index 5724d60..0000000 --- a/spec/interactors/create_rsa_keys_and_x509_self_signed_certificate_spec.rb +++ /dev/null @@ -1,90 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -RSpec.describe CreateRSAKeysAndX509SelfSignedCertificate do - subject do - described_class.call( - account: account, - password: password, - distinguished_name: distinguished_name, - not_before: not_before, - not_after: not_after, - ) - end - - let(:account) { create :initial_account } - let(:password) { Faker::Internet.password } - let(:distinguished_name) { "CN=#{Faker::Internet.domain_name}" } - let(:not_before) { Faker::Time.backward.utc } - let(:not_after) { Faker::Time.forward.utc } - - specify do - expect { subject }.to change(AsymmetricKey, :count).by(1) - end - - specify do - expect { subject }.to change(RSAKey, :count).by(1) - end - - specify do - expect { subject }.to change(X509Certificate, :count).by(1) - end - - specify do - expect { subject }.to( - have_enqueued_job(ClearAsymmetricPrivateKeyJob) - .with do |asymmetric_key_id| - expect(asymmetric_key_id).to equal AsymmetricKey.last.id - end, - ) - end - - specify do - expect(subject.asymmetric_key).to be_instance_of RSAKey - end - - specify do - expect(subject.asymmetric_key.has_password).to equal true - end - - specify do - expect(subject.certificate).to be_instance_of X509Certificate - end - - specify do - expect(subject.asymmetric_key.private_key_pem).not_to be_blank - end - - specify do - expect(subject.asymmetric_key.private_key_pem_secret).not_to be_blank - end - - specify do - expect(subject.asymmetric_key.account).to eq account - end - - context 'when owner is not specified' do - let(:account) { nil } - - specify do - expect(subject.asymmetric_key.account).to equal nil - end - end - - context 'when password is nil' do - let(:password) { nil } - - specify do - expect(subject.asymmetric_key.has_password).to equal false - end - end - - context 'when password is blank' do - let(:password) { ' ' * rand(1..3) } - - specify do - expect(subject.asymmetric_key.has_password).to equal false - end - end -end diff --git a/spec/interactors/create_rsa_keys_spec.rb b/spec/interactors/create_rsa_keys_spec.rb deleted file mode 100644 index d3fb302..0000000 --- a/spec/interactors/create_rsa_keys_spec.rb +++ /dev/null @@ -1,192 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -RSpec.describe CreateRSAKeys do - subject do - described_class.call account: account, password: password, bits: bits - end - - let(:account) { create :initial_account } - let(:password) { Faker::Internet.password } - let(:bits) { RSAKey::BITS.sample } - - specify do - expect { subject }.to change(AsymmetricKey, :count).by(1) - end - - specify do - expect { subject }.to change(RSAKey, :count).by(1) - end - - specify do - expect { subject }.to( - have_enqueued_job(ClearAsymmetricPrivateKeyJob) - .with do |asymmetric_key_id| - expect(asymmetric_key_id).to equal AsymmetricKey.last.id - end, - ) - end - - specify do - expect(subject.asymmetric_key).to be_instance_of RSAKey - end - - specify do - expect(subject.asymmetric_key.bits).to equal bits - end - - specify do - expect(subject.asymmetric_key.curve).to equal nil - end - - specify do - expect(subject.asymmetric_key.has_password).to equal true - end - - specify do - expect(subject.asymmetric_key.sha1).not_to be_blank - end - - specify do - expect(subject.asymmetric_key.sha256).not_to be_blank - end - - specify do - expect(subject.asymmetric_key.private_key_pem).not_to be_blank - end - - specify do - expect(subject.asymmetric_key.private_key_pem_secret).not_to be_blank - end - - specify do - expect(subject.asymmetric_key.account).to eq account - end - - specify do - expect do - OpenSSL::PKey::RSA.new( - subject.asymmetric_key.private_key_pem, - String(password), - ) - end.not_to raise_error - end - - specify do - expect do - OpenSSL::PKey::RSA.new( - subject.asymmetric_key.public_key_pem, - String(password), - ) - end.not_to raise_error - end - - specify do - expect(subject.asymmetric_key.sha1).to eq( - Digest::SHA1.hexdigest( - OpenSSL::PKey::RSA.new( - subject.asymmetric_key.public_key_pem, - String(password), - ).to_der, - ), - ) - end - - specify do - expect(subject.asymmetric_key.sha256).to eq( - Digest::SHA256.hexdigest( - OpenSSL::PKey::RSA.new( - subject.asymmetric_key.public_key_pem, - String(password), - ).to_der, - ), - ) - end - - specify do - expect(subject.asymmetric_key.public_key_pem).to eq( - OpenSSL::PKey::RSA.new( - subject.asymmetric_key.private_key_pem, - String(password), - ) - .public_key.to_pem, - ) - end - - specify do - expect(subject.asymmetric_key.private_key_pem_iv).not_to be_blank - end - - specify do - expect(subject.asymmetric_key.private_key_pem_ciphertext).not_to be_blank - end - - specify do - cipher = OpenSSL::Cipher::AES256.new - cipher.decrypt - cipher.iv = subject.asymmetric_key.private_key_pem_iv - cipher.key = subject.asymmetric_key.private_key_pem_secret - - cleartext = [ - cipher.update(subject.asymmetric_key.private_key_pem_ciphertext), - cipher.final, - ].join.freeze - - expect(cleartext).to eq subject.asymmetric_key.private_key_pem - end - - context 'when owner is not specified' do - let(:account) { nil } - - specify do - expect(subject.asymmetric_key.account).to equal nil - end - end - - context 'when password is nil' do - let(:password) { nil } - - specify do - expect(subject.asymmetric_key.has_password).to equal false - end - end - - context 'when password is blank' do - let(:password) { ' ' * rand(1..3) } - - specify do - expect(subject.asymmetric_key.has_password).to equal false - end - end - - context 'when password.to_s returns nil' do - let :password do - Class.new do - def to_s - nil - end - end.new - end - - specify do - expect { subject }.to raise_error TypeError - end - end - - context 'when bits value is invalid' do - let(:bits) { 1024 } - - specify do - expect { subject }.to raise_error RuntimeError, 'Invalid key size' - end - end - - context 'when bits value is nil' do - let(:bits) { nil } - - specify do - expect(subject.asymmetric_key.bits).to equal 4096 - end - end -end diff --git a/spec/interactors/create_x509_self_signed_certificate_spec.rb b/spec/interactors/create_x509_self_signed_certificate_spec.rb deleted file mode 100644 index 070f942..0000000 --- a/spec/interactors/create_x509_self_signed_certificate_spec.rb +++ /dev/null @@ -1,52 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -RSpec.describe CreateX509SelfSignedCertificate do - subject do - described_class.call( - asymmetric_key: asymmetric_key, - distinguished_name: distinguished_name, - not_before: not_before, - not_after: not_after, - ) - end - - let(:asymmetric_key) { CreateRSAKeys.call.asymmetric_key } - let(:distinguished_name) { "CN=#{Faker::Internet.domain_name}" } - let(:not_before) { Faker::Time.backward.utc } - let(:not_after) { Faker::Time.forward.utc } - - specify do - expect { subject }.to change(X509Certificate, :count).by(1) - end - - specify do - expect(subject.certificate).to be_instance_of X509Certificate - end - - specify do - expect(subject.certificate.asymmetric_key).to eq asymmetric_key - end - - specify do - expect(subject.certificate.pem).to \ - be_start_with "-----BEGIN CERTIFICATE-----\n" - end - - specify do - expect(subject.certificate.subject).to eq "/#{distinguished_name}" - end - - specify do - expect(subject.certificate.issuer).to eq "/#{distinguished_name}" - end - - specify do - expect(subject.certificate.not_before).to eq not_before - end - - specify do - expect(subject.certificate.not_after).to eq not_after - end -end diff --git a/spec/interactors/import_asymmetric_key_spec.rb b/spec/interactors/import_asymmetric_key_spec.rb deleted file mode 100644 index 28c44ca..0000000 --- a/spec/interactors/import_asymmetric_key_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -RSpec.describe ImportAsymmetricKey do - pending "add some examples to (or delete) #{__FILE__}" -end diff --git a/spec/jobs/clear_asymmetric_private_key_job_spec.rb b/spec/jobs/clear_asymmetric_private_key_job_spec.rb deleted file mode 100644 index 2e5338c..0000000 --- a/spec/jobs/clear_asymmetric_private_key_job_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -RSpec.describe ClearAsymmetricPrivateKeyJob do - pending "add some examples to (or delete) #{__FILE__}" -end diff --git a/spec/models/asymmetric_key_spec.rb b/spec/models/asymmetric_key_spec.rb deleted file mode 100644 index 5fb7d02..0000000 --- a/spec/models/asymmetric_key_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -RSpec.describe AsymmetricKey do - pending "add some examples to (or delete) #{__FILE__}" -end diff --git a/spec/models/ecurve_key_spec.rb b/spec/models/ecurve_key_spec.rb deleted file mode 100644 index 769a00d..0000000 --- a/spec/models/ecurve_key_spec.rb +++ /dev/null @@ -1,20 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -RSpec.describe EcurveKey do - subject { create :ecurve_key } - - it_behaves_like 'asymmetric_key' - - describe '#curve' do - it do - is_expected.to \ - validate_inclusion_of(:curve).in_array(%w[prime256v1 secp384r1]) - end - end - - describe '#bits' do - it { is_expected.to validate_absence_of :bits } - end -end diff --git a/spec/models/rsa_key_spec.rb b/spec/models/rsa_key_spec.rb deleted file mode 100644 index f902d1a..0000000 --- a/spec/models/rsa_key_spec.rb +++ /dev/null @@ -1,212 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -RSpec.describe RSAKey do - subject { create :rsa_key } - - it_behaves_like 'asymmetric_key' - - describe '#bits' do - it { is_expected.to validate_inclusion_of(:bits).in_array([2048, 4096]) } - end - - describe '#curve' do - it { is_expected.to validate_absence_of :curve } - end - - describe '#encrypt_private_key_pem' do - subject { create :rsa_key, private_key_pem: cleartext } - - let(:cleartext) { OpenSSL::PKey::RSA.new.to_pem.freeze } - - specify do - expect(subject.encrypt_private_key_pem).to be_instance_of String - end - - specify do - expect(subject.encrypt_private_key_pem).to be_frozen - end - - specify do - expect(subject.encrypt_private_key_pem).to \ - equal subject.private_key_pem_secret - end - - specify do - expect { subject.encrypt_private_key_pem }.to \ - change(subject, :private_key_pem_iv) - .from(nil) - end - - specify do - expect { subject.encrypt_private_key_pem }.to \ - change(subject, :private_key_pem_secret) - .from(nil) - end - - specify do - expect { subject.encrypt_private_key_pem }.to \ - change(subject, :private_key_pem_ciphertext) - .from(nil) - end - - context 'after call' do - before { subject.encrypt_private_key_pem } - - specify do - expect(subject.private_key_pem).to be_instance_of String - end - - specify do - expect(subject.private_key_pem_iv).to be_instance_of String - end - - specify do - expect(subject.private_key_pem_secret).to be_instance_of String - end - - specify do - expect(subject.private_key_pem_ciphertext).to be_instance_of String - end - - specify do - expect(subject.private_key_pem).to be_frozen - end - - specify do - expect(subject.private_key_pem_iv).to be_frozen - end - - specify do - expect(subject.private_key_pem_secret).to be_frozen - end - - specify do - expect(subject.private_key_pem_ciphertext).to be_frozen - end - - specify do - expect(subject.private_key_pem).to eq cleartext - end - - specify do - expect(subject.private_key_pem_iv).not_to be_blank - end - - specify do - expect(subject.private_key_pem_secret).not_to be_blank - end - - specify do - expect(subject.private_key_pem_ciphertext).not_to be_blank - end - - specify do - cipher = OpenSSL::Cipher::AES256.new - cipher.encrypt - - cipher.iv = subject.private_key_pem_iv - cipher.key = subject.private_key_pem_secret - - ciphertext = [ - cipher.update(cleartext), - cipher.final, - ].join.freeze - - expect(subject.private_key_pem_ciphertext).to eq ciphertext - end - end - end - - describe '#decrypt_private_key_pem' do - subject do - create( - :rsa_key, - private_key_pem_iv: iv, - private_key_pem_secret: secret, - private_key_pem_ciphertext: ciphertext, - ) - end - - let(:cleartext) { OpenSSL::PKey::RSA.new.to_pem.freeze } - - let!(:cipher) { OpenSSL::Cipher::AES256.new.tap(&:encrypt) } - - let!(:iv) { cipher.random_iv.freeze } - let!(:secret) { cipher.random_key.freeze } - - let!(:ciphertext) { [cipher.update(cleartext), cipher.final].join.freeze } - - specify do - expect(subject.decrypt_private_key_pem).to be_instance_of String - end - - specify do - expect(subject.decrypt_private_key_pem).to be_frozen - end - - specify do - expect(subject.decrypt_private_key_pem).to equal subject.private_key_pem - end - - specify do - expect { subject.decrypt_private_key_pem }.to \ - change(subject, :private_key_pem) - .from(nil) - .to(cleartext) - end - - context 'after call' do - before { subject.decrypt_private_key_pem } - - specify do - expect(subject.private_key_pem).to be_instance_of String - end - - specify do - expect(subject.private_key_pem_iv).to be_instance_of String - end - - specify do - expect(subject.private_key_pem_secret).to be_instance_of String - end - - specify do - expect(subject.private_key_pem_ciphertext).to be_instance_of String - end - - specify do - expect(subject.private_key_pem).to be_frozen - end - - specify do - expect(subject.private_key_pem_iv).to be_frozen - end - - specify do - expect(subject.private_key_pem_secret).to be_frozen - end - - specify do - expect(subject.private_key_pem_ciphertext).to be_frozen - end - - specify do - expect(subject.private_key_pem).to eq cleartext - end - - specify do - expect(subject.private_key_pem_iv).to equal iv - end - - specify do - expect(subject.private_key_pem_secret).to equal secret - end - - specify do - expect(subject.private_key_pem_ciphertext).to equal ciphertext - end - end - end -end diff --git a/spec/models/shared_examples/asymmetric_key.rb b/spec/models/shared_examples/asymmetric_key.rb deleted file mode 100644 index 8828f25..0000000 --- a/spec/models/shared_examples/asymmetric_key.rb +++ /dev/null @@ -1,52 +0,0 @@ -# frozen_string_literal: true - -RSpec.shared_examples 'asymmetric_key' do - describe '#account' do - it { is_expected.to belong_to(:account).optional } - - it { is_expected.not_to validate_presence_of :account } - it { is_expected.not_to validate_uniqueness_of :account } - end - - describe '#public_key_pem' do - it { is_expected.to validate_presence_of :public_key_pem } - it { is_expected.to validate_uniqueness_of :public_key_pem } - end - - describe '#public_key_der' do - it { is_expected.to validate_presence_of :public_key_der } - it { is_expected.to validate_uniqueness_of :public_key_der } - end - - describe '#has_password' do - it { is_expected.not_to validate_presence_of :has_password } - end - - describe '#bits' do - it do - is_expected.to \ - validate_numericality_of(:bits) - .allow_nil - .only_integer - .is_greater_than(0) - end - end - - describe '#sha1' do - it { is_expected.to validate_presence_of :sha1 } - it { is_expected.to validate_uniqueness_of(:sha1).case_insensitive } - end - - describe '#sha256' do - it { is_expected.to validate_presence_of :sha256 } - it { is_expected.to validate_uniqueness_of(:sha256).case_insensitive } - end - - describe '#private_key_pem_iv' do - it { is_expected.not_to validate_presence_of :private_key_pem_iv } - end - - describe '#private_key_pem_ciphertext' do - it { is_expected.not_to validate_presence_of :private_key_pem_ciphertext } - end -end diff --git a/spec/models/x509_certificate_spec.rb b/spec/models/x509_certificate_spec.rb deleted file mode 100644 index adff7c7..0000000 --- a/spec/models/x509_certificate_spec.rb +++ /dev/null @@ -1,50 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -RSpec.describe X509Certificate do - subject { create :self_signed_x509_certificate } - - describe '#asymmetric_key' do - it { is_expected.to belong_to(:asymmetric_key).required } - - it do - is_expected.to \ - validate_presence_of(:asymmetric_key).with_message(:required) - end - - it { is_expected.not_to validate_uniqueness_of :asymmetric_key } - end - - describe '#pem' do - def allow_value(*) - super.for :pem - end - - it { is_expected.to validate_presence_of :pem } - - it 'is allowed to be a valid certificate' do - is_expected.to allow_value File.read Rails.root.join 'fixtures', 'ca.crt' - end - - it 'is not allowed to be an invalid certificate' do - is_expected.not_to allow_value OpenSSL::X509::Certificate.new.to_pem - end - end - - describe '#subject' do - it { is_expected.to validate_presence_of :subject } - end - - describe '#issuer' do - it { is_expected.to validate_presence_of :issuer } - end - - describe '#not_before' do - it { is_expected.to validate_presence_of :not_before } - end - - describe '#not_after' do - it { is_expected.to validate_presence_of :not_after } - end -end diff --git a/spec/policies/asymmetric_key_policy_spec.rb b/spec/policies/asymmetric_key_policy_spec.rb deleted file mode 100644 index 8925add..0000000 --- a/spec/policies/asymmetric_key_policy_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -RSpec.describe AsymmetricKeyPolicy do - pending "add some examples to (or delete) #{__FILE__}" -end diff --git a/spec/policies/private_key_policy_spec.rb b/spec/policies/private_key_policy_spec.rb deleted file mode 100644 index 1a9d1df..0000000 --- a/spec/policies/private_key_policy_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -RSpec.describe PrivateKeyPolicy do - pending "add some examples to (or delete) #{__FILE__}" -end diff --git a/spec/policies/staff/x509_certificate_policy_spec.rb b/spec/policies/staff/x509_certificate_policy_spec.rb deleted file mode 100644 index b46a2c9..0000000 --- a/spec/policies/staff/x509_certificate_policy_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -RSpec.describe Staff::X509CertificatePolicy do - pending "add some examples to (or delete) #{__FILE__}" -end diff --git a/spec/primitives/private_key_spec.rb b/spec/primitives/private_key_spec.rb deleted file mode 100644 index 92d17f3..0000000 --- a/spec/primitives/private_key_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -RSpec.describe PrivateKey, type: :model do - pending "add some examples to (or delete) #{__FILE__}" -end diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 2477dc5..6323306 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -37,7 +37,6 @@ require_relative 'support/database_cleaner' require_relative 'support/devise' require_relative 'support/pundit' -require_relative 'models/shared_examples/asymmetric_key' require_relative 'models/shared_examples/nameable' require_relative 'models/shared_examples/required_nameable' diff --git a/spec/requests/asymmetric_keys/create_spec.rb b/spec/requests/asymmetric_keys/create_spec.rb deleted file mode 100644 index 58d975a..0000000 --- a/spec/requests/asymmetric_keys/create_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -RSpec.describe 'POST /asymmetric_keys' do - pending "add some examples to (or delete) #{__FILE__}" -end diff --git a/spec/requests/asymmetric_keys/index_spec.rb b/spec/requests/asymmetric_keys/index_spec.rb deleted file mode 100644 index 56255e8..0000000 --- a/spec/requests/asymmetric_keys/index_spec.rb +++ /dev/null @@ -1,69 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -RSpec.describe 'GET /asymmetric_keys' do - let(:current_account) { create :superuser_account } - - let :asymmetric_keys_count do - [0, 1, rand(2..4), rand(5..10), rand(20..40)].sample - end - - let(:rsa_keys_count) { rand(1...asymmetric_keys_count) || 0 } - let(:ecurve_keys_count) { asymmetric_keys_count - rsa_keys_count } - - before do - sign_in current_account.user if current_account&.user - - create_list :rsa_key, rsa_keys_count - create_list :ecurve_key, ecurve_keys_count - - get '/asymmetric_keys' - end - - for_account_types nil, :usual, :superuser do - specify do - expect(response).to have_http_status :ok - end - end - - context 'when there are no asymmetric keys' do - let(:asymmetric_keys_count) { 0 } - - specify do - expect(response).to have_http_status :ok - end - end - - context 'when there is one asymmetric key' do - let(:asymmetric_keys_count) { 1 } - - specify do - expect(response).to have_http_status :ok - end - end - - context 'when there are few asymmetric keys' do - let(:asymmetric_keys_count) { rand 2..4 } - - specify do - expect(response).to have_http_status :ok - end - end - - context 'when there are many asymmetric keys' do - let(:asymmetric_keys_count) { rand 5..10 } - - specify do - expect(response).to have_http_status :ok - end - end - - context 'when there are lot of asymmetric keys' do - let(:asymmetric_keys_count) { rand 20..40 } - - specify do - expect(response).to have_http_status :ok - end - end -end diff --git a/spec/requests/asymmetric_keys/new_spec.rb b/spec/requests/asymmetric_keys/new_spec.rb deleted file mode 100644 index 74950fd..0000000 --- a/spec/requests/asymmetric_keys/new_spec.rb +++ /dev/null @@ -1,17 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -RSpec.describe 'GET /asymmetric_keys/new' do - before do - sign_in current_account.user if current_account&.user - - get '/asymmetric_keys/new' - end - - for_account_types nil, :usual, :superuser do - specify do - expect(response).to have_http_status :ok - end - end -end diff --git a/spec/requests/asymmetric_keys/show_spec.rb b/spec/requests/asymmetric_keys/show_spec.rb deleted file mode 100644 index 06cbc75..0000000 --- a/spec/requests/asymmetric_keys/show_spec.rb +++ /dev/null @@ -1,40 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -RSpec.describe 'GET /asymmetric_keys/:id' do - let(:current_account) { nil } - - let(:asymmetric_key) { create %i[rsa_key ecurve_key].sample } - - def make_request - get "/asymmetric_keys/#{asymmetric_key.id}" - end - - before do - sign_in current_account.user if current_account&.user - make_request - end - - for_account_types nil, :usual, :superuser do - specify do - expect(response).to have_http_status :ok - end - end - - context 'for RSA key' do - let(:asymmetric_key) { create :rsa_key } - - specify do - expect(response).to have_http_status :ok - end - end - - context 'for elliptic-curve key' do - let(:asymmetric_key) { create :ecurve_key } - - specify do - expect(response).to have_http_status :ok - end - end -end diff --git a/spec/requests/private_keys/show_spec.rb b/spec/requests/private_keys/show_spec.rb deleted file mode 100644 index c14e4ca..0000000 --- a/spec/requests/private_keys/show_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -RSpec.describe 'GET /private_keys/:id' do - pending "add some examples to (or delete) #{__FILE__}" -end diff --git a/spec/requests/staff/x509_certificates/create_spec.rb b/spec/requests/staff/x509_certificates/create_spec.rb deleted file mode 100644 index 65b4146..0000000 --- a/spec/requests/staff/x509_certificates/create_spec.rb +++ /dev/null @@ -1,140 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -RSpec.describe 'POST /staff/x509_certificates' do - let(:current_account) { create :superuser_account } - - let :x509_certificate_form_attributes do - { - distinguished_name: distinguished_name, - not_before: not_before, - not_after: not_after, - } - end - - let :x509_certificate_attributes do - { - subject: distinguished_name, - issuer: distinguished_name, - not_before: not_before, - not_after: not_after, - } - end - - let(:distinguished_name) { "/CN=#{Faker::Internet.domain_name}" } - let(:not_before) { Faker::Time.backward.utc } - let(:not_after) { Faker::Time.forward.utc } - - def make_request - post '/staff/x509_certificates', - params: { x509_certificate: x509_certificate_form_attributes } - end - - before do - sign_in current_account.user if current_account&.user - end - - for_account_types nil, :usual do - specify do - expect { make_request }.not_to change(X509Certificate, :count) - end - - context 'after request' do - before { make_request } - - specify do - expect(response).to have_http_status :forbidden - end - end - end - - for_account_types :superuser do - specify do - expect { make_request }.to change(X509Certificate, :count).by(1) - end - - context 'after request' do - before { make_request } - - specify do - expect(response).to \ - redirect_to(/\A#{staff_x509_certificate_url(X509Certificate.last)}\?/) - end - - specify do - expect(X509Certificate.last).to \ - have_attributes x509_certificate_attributes - end - - specify do - expect(X509Certificate.last.asymmetric_key.account).to \ - eq current_account - end - end - end - - context 'when distinguished name is missing' do - let(:distinguished_name) { nil } - - specify do - expect { make_request }.not_to change(X509Certificate, :count) - end - - context 'after request' do - before { make_request } - - specify do - expect(response).to have_http_status :ok - end - end - end - - context 'when activation time is missing' do - let(:not_before) { nil } - - specify do - expect { make_request }.not_to change(X509Certificate, :count) - end - - context 'after request' do - before { make_request } - - specify do - expect(response).to have_http_status :ok - end - end - end - - context 'when expiration time is missing' do - let(:not_after) { nil } - - specify do - expect { make_request }.not_to change(X509Certificate, :count) - end - - context 'after request' do - before { make_request } - - specify do - expect(response).to have_http_status :ok - end - end - end - - context 'when distinguished name is invalid' do - let(:distinguished_name) { 'Hello!' } - - specify do - expect { make_request }.not_to change(X509Certificate, :count) - end - - context 'after request' do - before { make_request } - - specify do - expect(response).to have_http_status :ok - end - end - end -end diff --git a/spec/requests/staff/x509_certificates/index_spec.rb b/spec/requests/staff/x509_certificates/index_spec.rb deleted file mode 100644 index c48e885..0000000 --- a/spec/requests/staff/x509_certificates/index_spec.rb +++ /dev/null @@ -1,71 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -RSpec.describe 'GET /staff/x509_certificates' do - let(:current_account) { create :superuser_account } - - let :x509_certificates_count do - [0, 1, rand(2..4), rand(5..10), rand(20..40)].sample - end - - before do - sign_in current_account.user if current_account&.user - - create_list :self_signed_x509_certificate, x509_certificates_count - - get '/staff/x509_certificates' - end - - for_account_types nil, :usual do - specify do - expect(response).to have_http_status :forbidden - end - end - - for_account_types :superuser do - specify do - expect(response).to have_http_status :ok - end - end - - context 'when there are no X509 certificates' do - let(:x509_certificates_count) { 0 } - - specify do - expect(response).to have_http_status :ok - end - end - - context 'when there is one X509 certificate' do - let(:x509_certificates_count) { 1 } - - specify do - expect(response).to have_http_status :ok - end - end - - context 'when there are few X509 certificates' do - let(:x509_certificates_count) { rand 2..4 } - - specify do - expect(response).to have_http_status :ok - end - end - - context 'when there are many X509 certificates' do - let(:x509_certificates_count) { rand 5..10 } - - specify do - expect(response).to have_http_status :ok - end - end - - context 'when there are lot of X509 certificates' do - let(:x509_certificates_count) { rand 20..40 } - - specify do - expect(response).to have_http_status :ok - end - end -end diff --git a/spec/requests/staff/x509_certificates/new_spec.rb b/spec/requests/staff/x509_certificates/new_spec.rb deleted file mode 100644 index aff2d01..0000000 --- a/spec/requests/staff/x509_certificates/new_spec.rb +++ /dev/null @@ -1,23 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -RSpec.describe 'GET /staff/x509_certificates/new' do - before do - sign_in current_account.user if current_account&.user - - get '/staff/x509_certificates/new' - end - - for_account_types nil, :usual do - specify do - expect(response).to have_http_status :forbidden - end - end - - for_account_types :superuser do - specify do - expect(response).to have_http_status :ok - end - end -end diff --git a/spec/requests/staff/x509_certificates/show_spec.rb b/spec/requests/staff/x509_certificates/show_spec.rb deleted file mode 100644 index 2d83924..0000000 --- a/spec/requests/staff/x509_certificates/show_spec.rb +++ /dev/null @@ -1,28 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -RSpec.describe 'GET /staff/x509_certificates/:id' do - let(:x509_certificate) { create :self_signed_x509_certificate } - - def make_request - get "/staff/x509_certificates/#{x509_certificate.id}" - end - - before do - sign_in current_account.user if current_account&.user - make_request - end - - for_account_types nil, :usual do - specify do - expect(response).to have_http_status :forbidden - end - end - - for_account_types :superuser do - specify do - expect(response).to have_http_status :ok - end - end -end