Add certificate valid time to pages domain table
Save certificate validity time for pages domains on save Fill validity time for existing pages domains in background migration
This commit is contained in:
parent
bb02557cbd
commit
d1d05ae4f3
8 changed files with 163 additions and 2 deletions
|
@ -135,6 +135,14 @@ class PagesDomain < ApplicationRecord
|
|||
"#{VERIFICATION_KEY}=#{verification_code}"
|
||||
end
|
||||
|
||||
def certificate=(certificate)
|
||||
super(certificate)
|
||||
|
||||
# set nil, if certificate is nil
|
||||
self.certificate_valid_not_before = x509&.not_before
|
||||
self.certificate_valid_not_after = x509&.not_after
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_verification_code
|
||||
|
@ -187,7 +195,7 @@ class PagesDomain < ApplicationRecord
|
|||
end
|
||||
|
||||
def x509
|
||||
return unless certificate
|
||||
return unless certificate.present?
|
||||
|
||||
@x509 ||= OpenSSL::X509::Certificate.new(certificate)
|
||||
rescue OpenSSL::X509::CertificateError
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
|
||||
# for more information on how to write migrations for GitLab.
|
||||
|
||||
class AddSslValidPeriodToPagesDomain < ActiveRecord::Migration[5.1]
|
||||
include Gitlab::Database::MigrationHelpers
|
||||
|
||||
# Set this constant to true if this migration requires downtime.
|
||||
DOWNTIME = false
|
||||
|
||||
def change
|
||||
add_column :pages_domains, :certificate_valid_not_before, :datetime_with_timezone
|
||||
add_column :pages_domains, :certificate_valid_not_after, :datetime_with_timezone
|
||||
end
|
||||
end
|
|
@ -0,0 +1,34 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
|
||||
# for more information on how to write migrations for GitLab.
|
||||
|
||||
class ScheduleFillValidTimeForPagesDomainCertificates < ActiveRecord::Migration[5.1]
|
||||
include Gitlab::Database::MigrationHelpers
|
||||
|
||||
MIGRATION = 'FillValidTimeForPagesDomainCertificate'
|
||||
BATCH_SIZE = 500
|
||||
BATCH_TIME = 5.minutes
|
||||
|
||||
# Set this constant to true if this migration requires downtime.
|
||||
DOWNTIME = false
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
class PagesDomain < ActiveRecord::Base
|
||||
include ::EachBatch
|
||||
|
||||
self.table_name = 'pages_domains'
|
||||
end
|
||||
|
||||
def up
|
||||
queue_background_migration_jobs_by_range_at_intervals(
|
||||
PagesDomain.where.not(certificate: [nil, '']),
|
||||
MIGRATION,
|
||||
BATCH_TIME,
|
||||
batch_size: BATCH_SIZE)
|
||||
end
|
||||
|
||||
def down
|
||||
end
|
||||
end
|
|
@ -1597,6 +1597,8 @@ ActiveRecord::Schema.define(version: 20190530154715) do
|
|||
t.datetime_with_timezone "enabled_until"
|
||||
t.datetime_with_timezone "remove_at"
|
||||
t.boolean "auto_ssl_enabled", default: false, null: false
|
||||
t.datetime_with_timezone "certificate_valid_not_before"
|
||||
t.datetime_with_timezone "certificate_valid_not_after"
|
||||
t.index ["domain"], name: "index_pages_domains_on_domain", unique: true, using: :btree
|
||||
t.index ["project_id", "enabled_until"], name: "index_pages_domains_on_project_id_and_enabled_until", using: :btree
|
||||
t.index ["project_id"], name: "index_pages_domains_on_project_id", using: :btree
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module BackgroundMigration
|
||||
# save validity time pages domain
|
||||
class FillValidTimeForPagesDomainCertificate
|
||||
# define PagesDomain with only needed code
|
||||
class PagesDomain < ActiveRecord::Base
|
||||
self.table_name = 'pages_domains'
|
||||
|
||||
def x509
|
||||
return unless certificate.present?
|
||||
|
||||
@x509 ||= OpenSSL::X509::Certificate.new(certificate)
|
||||
rescue OpenSSL::X509::CertificateError
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def perform(start_id, stop_id)
|
||||
PagesDomain.where(id: start_id..stop_id).find_each do |domain|
|
||||
if Gitlab::Database.mysql?
|
||||
domain.update_columns(
|
||||
certificate_valid_not_before: domain.x509&.not_before,
|
||||
certificate_valid_not_after: domain.x509&.not_after
|
||||
)
|
||||
else
|
||||
# for some reason activerecord doesn't append timezone, iso8601 forces this
|
||||
domain.update_columns(
|
||||
certificate_valid_not_before: domain.x509&.not_before&.iso8601,
|
||||
certificate_valid_not_after: domain.x509&.not_after&.iso8601
|
||||
)
|
||||
end
|
||||
rescue => e
|
||||
Rails.logger.error "Failed to update pages domain certificate valid time. id: #{domain.id}, message: #{e.message}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -8,9 +8,13 @@ describe EnqueueVerifyPagesDomainWorkers, :sidekiq, :migration do
|
|||
end
|
||||
end
|
||||
|
||||
let(:domains_table) { table(:pages_domains) }
|
||||
|
||||
describe '#up' do
|
||||
it 'enqueues a verification worker for every domain' do
|
||||
domains = 1.upto(3).map { |i| PagesDomain.create!(domain: "my#{i}.domain.com") }
|
||||
domains = Array.new(3) do |i|
|
||||
domains_table.create!(domain: "my#{i}.domain.com", verification_code: "123#{i}")
|
||||
end
|
||||
|
||||
expect { migrate! }.to change(PagesDomainVerificationWorker.jobs, :size).by(3)
|
||||
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
require 'spec_helper'
|
||||
require Rails.root.join('db', 'post_migrate', '20190524073827_schedule_fill_valid_time_for_pages_domain_certificates.rb')
|
||||
|
||||
describe ScheduleFillValidTimeForPagesDomainCertificates, :migration, :sidekiq do
|
||||
let(:migration_class) { described_class::MIGRATION }
|
||||
let(:migration_name) { migration_class.to_s.demodulize }
|
||||
|
||||
let(:domains_table) { table(:pages_domains) }
|
||||
|
||||
let(:certificate) do
|
||||
File.read('spec/fixtures/passphrase_x509_certificate.crt')
|
||||
end
|
||||
|
||||
before do
|
||||
domains_table.create!(domain: "domain1.example.com", verification_code: "123")
|
||||
domains_table.create!(domain: "domain2.example.com", verification_code: "123", certificate: '')
|
||||
domains_table.create!(domain: "domain3.example.com", verification_code: "123", certificate: certificate)
|
||||
domains_table.create!(domain: "domain4.example.com", verification_code: "123", certificate: certificate)
|
||||
end
|
||||
|
||||
it 'correctly schedules background migrations' do
|
||||
Sidekiq::Testing.fake! do
|
||||
Timecop.freeze do
|
||||
migrate!
|
||||
|
||||
first_id = domains_table.find_by_domain("domain3.example.com").id
|
||||
last_id = domains_table.find_by_domain("domain4.example.com").id
|
||||
|
||||
expect(migration_name).to be_scheduled_delayed_migration(5.minutes, first_id, last_id)
|
||||
expect(BackgroundMigrationWorker.jobs.size).to eq(1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it 'sets certificate valid_not_before/not_after' do
|
||||
perform_enqueued_jobs do
|
||||
migrate!
|
||||
|
||||
domain = domains_table.find_by_domain("domain3.example.com")
|
||||
expect(domain.certificate_valid_not_before)
|
||||
.to eq(Time.parse("2018-03-23 14:02:08 UTC"))
|
||||
expect(domain.certificate_valid_not_after)
|
||||
.to eq(Time.parse("2019-03-23 14:02:08 UTC"))
|
||||
end
|
||||
end
|
||||
end
|
|
@ -81,6 +81,17 @@ describe PagesDomain do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'when certificate is specified' do
|
||||
let(:domain) { build(:pages_domain) }
|
||||
|
||||
it 'saves validity time' do
|
||||
domain.save
|
||||
|
||||
expect(domain.certificate_valid_not_before).to be_like_time(Time.parse("2016-02-12 14:32:00 UTC"))
|
||||
expect(domain.certificate_valid_not_after).to be_like_time(Time.parse("2020-04-12 14:32:00 UTC"))
|
||||
end
|
||||
end
|
||||
|
||||
describe 'validate certificate' do
|
||||
subject { domain }
|
||||
|
||||
|
|
Loading…
Reference in a new issue