diff options
author | Kamil Trzcinski <ayufan@ayufan.eu> | 2016-02-10 17:06:31 +0300 |
---|---|---|
committer | James Edwards-Jones <jedwardsjones@gitlab.com> | 2017-02-01 01:53:57 +0300 |
commit | 13b6bad17ec46eb78878f6972da1e7e34be86bb5 (patch) | |
tree | 745e04a26813be3e65200bc4ab6ece3fe73e6069 /app/models/pages_domain.rb | |
parent | 6e99226cca41f36d92c4ccb2cd398d2256091adc (diff) |
Implement extra domains and save pages configuration
Diffstat (limited to 'app/models/pages_domain.rb')
-rw-r--r-- | app/models/pages_domain.rb | 84 |
1 files changed, 80 insertions, 4 deletions
diff --git a/app/models/pages_domain.rb b/app/models/pages_domain.rb index eebdf7501de..810af4e832a 100644 --- a/app/models/pages_domain.rb +++ b/app/models/pages_domain.rb @@ -2,19 +2,25 @@ class PagesDomain < ActiveRecord::Base belongs_to :project validates :domain, hostname: true - validates_uniqueness_of :domain, allow_nil: true, allow_blank: true + validates_uniqueness_of :domain, case_sensitive: false validates :certificate, certificate: true, allow_nil: true, allow_blank: true validates :key, certificate_key: true, allow_nil: true, allow_blank: true - attr_encrypted :pages_custom_certificate_key, mode: :per_attribute_iv_and_salt, key: Gitlab::Application.secrets.db_key_base + validate :validate_matching_key, if: ->(domain) { domain.certificate.present? && domain.key.present? } + validate :validate_intermediates, if: ->(domain) { domain.certificate.present? } + + attr_encrypted :key, mode: :per_attribute_iv_and_salt, key: Gitlab::Application.secrets.db_key_base after_create :update after_save :update after_destroy :update + def to_param + domain + end + def url return unless domain - return unless Dir.exist?(project.public_pages_path) if certificate return "https://#{domain}" @@ -23,7 +29,77 @@ class PagesDomain < ActiveRecord::Base end end + def has_matching_key? + return unless x509 + return unless pkey + + # We compare the public key stored in certificate with public key from certificate key + x509.check_private_key(pkey) + end + + def has_intermediates? + return false unless x509 + + store = OpenSSL::X509::Store.new + store.set_default_paths + + # This forces to load all intermediate certificates stored in `certificate` + Tempfile.open('certificate_chain') do |f| + f.write(certificate) + f.flush + store.add_file(f.path) + end + + store.verify(x509) + rescue OpenSSL::X509::StoreError + false + end + + def expired? + return false unless x509 + current = Time.new + return current < x509.not_before || x509.not_after < current + end + + def subject + return unless x509 + return x509.subject.to_s + end + + def fingerprint + return unless x509 + @fingeprint ||= OpenSSL::Digest::SHA256.new(x509.to_der).to_s + end + + private + + def x509 + return unless certificate + @x509 ||= OpenSSL::X509::Certificate.new(certificate) + rescue OpenSSL::X509::CertificateError + nil + end + + def pkey + return unless key + @pkey ||= OpenSSL::PKey::RSA.new(key) + rescue OpenSSL::PKey::PKeyError, OpenSSL::Cipher::CipherError + nil + end + def update - UpdatePagesConfigurationService.new(project).execute + ::Projects::UpdatePagesConfigurationService.new(project).execute + end + + def validate_matching_key + unless has_matching_key? + self.errors.add(:key, "doesn't match the certificate") + end + end + + def validate_intermediates + unless has_intermediates? + self.errors.add(:certificate, 'misses intermediates') + end end end |