Commit 4687ff7c authored by Vladimir Shushlin's avatar Vladimir Shushlin Committed by Stan Hu

Store Let's Encrypt private key in settings

Storing this key in secrets.yml was a bad idea,
it would require users using HA setups to manually
replicate secrets across nodes during update,
it also needed support from omnibus package

* Revert "Generate Let's Encrypt private key"
  This reverts commit 444959bf.

* Add Let's Encrypt private key to settings
  as encrypted attribute

* Generate Let's Encrypt private key
  in database migration
parent af439708
...@@ -257,6 +257,12 @@ class ApplicationSetting < ApplicationRecord ...@@ -257,6 +257,12 @@ class ApplicationSetting < ApplicationRecord
algorithm: 'aes-256-gcm', algorithm: 'aes-256-gcm',
encode: true encode: true
attr_encrypted :lets_encrypt_private_key,
mode: :per_attribute_iv,
key: Settings.attr_encrypted_db_key_base_truncated,
algorithm: 'aes-256-gcm',
encode: true
before_validation :ensure_uuid! before_validation :ensure_uuid!
before_validation :strip_sentry_values before_validation :strip_sentry_values
......
...@@ -39,8 +39,7 @@ def create_tokens ...@@ -39,8 +39,7 @@ def create_tokens
secret_key_base: file_secret_key || generate_new_secure_token, secret_key_base: file_secret_key || generate_new_secure_token,
otp_key_base: env_secret_key || file_secret_key || generate_new_secure_token, otp_key_base: env_secret_key || file_secret_key || generate_new_secure_token,
db_key_base: generate_new_secure_token, db_key_base: generate_new_secure_token,
openid_connect_signing_key: generate_new_rsa_private_key, openid_connect_signing_key: generate_new_rsa_private_key
lets_encrypt_private_key: generate_lets_encrypt_private_key
} }
missing_secrets = set_missing_keys(defaults) missing_secrets = set_missing_keys(defaults)
...@@ -61,10 +60,6 @@ def generate_new_rsa_private_key ...@@ -61,10 +60,6 @@ def generate_new_rsa_private_key
OpenSSL::PKey::RSA.new(2048).to_pem OpenSSL::PKey::RSA.new(2048).to_pem
end end
def generate_lets_encrypt_private_key
OpenSSL::PKey::RSA.new(4096).to_pem
end
def warn_missing_secret(secret) def warn_missing_secret(secret)
warn "Missing Rails.application.secrets.#{secret} for #{Rails.env} environment. The secret will be generated and stored in config/secrets.yml." warn "Missing Rails.application.secrets.#{secret} for #{Rails.env} environment. The secret will be generated and stored in config/secrets.yml."
end end
......
# 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 AddLetsEncryptPrivateKeyToApplicationSettings < ActiveRecord::Migration[5.1]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
DOWNTIME = false
def change
add_column :application_settings, :encrypted_lets_encrypt_private_key, :text
add_column :application_settings, :encrypted_lets_encrypt_private_key_iv, :text
end
end
# 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 GenerateLetsEncryptPrivateKey < ActiveRecord::Migration[5.1]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
DOWNTIME = false
class ApplicationSetting < ActiveRecord::Base
self.table_name = 'application_settings'
attr_encrypted :lets_encrypt_private_key,
mode: :per_attribute_iv,
key: Settings.attr_encrypted_db_key_base_truncated,
algorithm: 'aes-256-gcm',
encode: true
end
def up
ApplicationSetting.reset_column_information
private_key = OpenSSL::PKey::RSA.new(4096).to_pem
ApplicationSetting.find_each do |setting|
setting.update!(lets_encrypt_private_key: private_key)
end
end
def down
end
end
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20190516011213) do ActiveRecord::Schema.define(version: 20190524062810) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
...@@ -191,6 +191,8 @@ ActiveRecord::Schema.define(version: 20190516011213) do ...@@ -191,6 +191,8 @@ ActiveRecord::Schema.define(version: 20190516011213) do
t.boolean "lets_encrypt_terms_of_service_accepted", default: false, null: false t.boolean "lets_encrypt_terms_of_service_accepted", default: false, null: false
t.integer "elasticsearch_shards", default: 5, null: false t.integer "elasticsearch_shards", default: 5, null: false
t.integer "elasticsearch_replicas", default: 1, null: false t.integer "elasticsearch_replicas", default: 1, null: false
t.text "encrypted_lets_encrypt_private_key"
t.text "encrypted_lets_encrypt_private_key_iv"
t.index ["usage_stats_set_by_user_id"], name: "index_application_settings_on_usage_stats_set_by_user_id", using: :btree t.index ["usage_stats_set_by_user_id"], name: "index_application_settings_on_usage_stats_set_by_user_id", using: :btree
end end
......
...@@ -45,7 +45,7 @@ module Gitlab ...@@ -45,7 +45,7 @@ module Gitlab
end end
def private_key def private_key
@private_key ||= OpenSSL::PKey.read(Gitlab::Application.secrets.lets_encrypt_private_key) @private_key ||= OpenSSL::PKey.read(Gitlab::CurrentSettings.lets_encrypt_private_key)
end end
def admin_email def admin_email
......
...@@ -45,21 +45,11 @@ describe 'create_tokens' do ...@@ -45,21 +45,11 @@ describe 'create_tokens' do
expect(keys).to all(match(RSA_KEY)) expect(keys).to all(match(RSA_KEY))
end end
it "generates private key for Let's Encrypt" do
create_tokens
keys = secrets.values_at(:lets_encrypt_private_key)
expect(keys.uniq).to eq(keys)
expect(keys).to all(match(RSA_KEY))
end
it 'warns about the secrets to add to secrets.yml' do it 'warns about the secrets to add to secrets.yml' do
expect(self).to receive(:warn_missing_secret).with('secret_key_base') expect(self).to receive(:warn_missing_secret).with('secret_key_base')
expect(self).to receive(:warn_missing_secret).with('otp_key_base') expect(self).to receive(:warn_missing_secret).with('otp_key_base')
expect(self).to receive(:warn_missing_secret).with('db_key_base') expect(self).to receive(:warn_missing_secret).with('db_key_base')
expect(self).to receive(:warn_missing_secret).with('openid_connect_signing_key') expect(self).to receive(:warn_missing_secret).with('openid_connect_signing_key')
expect(self).to receive(:warn_missing_secret).with('lets_encrypt_private_key')
create_tokens create_tokens
end end
...@@ -88,7 +78,6 @@ describe 'create_tokens' do ...@@ -88,7 +78,6 @@ describe 'create_tokens' do
before do before do
secrets.db_key_base = 'db_key_base' secrets.db_key_base = 'db_key_base'
secrets.openid_connect_signing_key = 'openid_connect_signing_key' secrets.openid_connect_signing_key = 'openid_connect_signing_key'
secrets.lets_encrypt_private_key = 'lets_encrypt_private_key'
allow(File).to receive(:exist?).with('.secret').and_return(true) allow(File).to receive(:exist?).with('.secret').and_return(true)
allow(File).to receive(:read).with('.secret').and_return('file_key') allow(File).to receive(:read).with('.secret').and_return('file_key')
......
...@@ -5,12 +5,14 @@ require 'spec_helper' ...@@ -5,12 +5,14 @@ require 'spec_helper'
describe ::Gitlab::LetsEncrypt::Client do describe ::Gitlab::LetsEncrypt::Client do
include LetsEncryptHelpers include LetsEncryptHelpers
set(:private_key) { OpenSSL::PKey::RSA.new(4096).to_pem }
let(:client) { described_class.new } let(:client) { described_class.new }
before do before do
stub_application_setting( stub_application_setting(
lets_encrypt_notification_email: 'myemail@test.example.com', lets_encrypt_notification_email: 'myemail@test.example.com',
lets_encrypt_terms_of_service_accepted: true lets_encrypt_terms_of_service_accepted: true,
lets_encrypt_private_key: private_key
) )
end end
......
require 'spec_helper'
require Rails.root.join('db', 'migrate', '20190524062810_generate_lets_encrypt_private_key.rb')
describe GenerateLetsEncryptPrivateKey, :migration do
describe '#up' do
let(:applications_settings) { table(:applications_settings) }
it 'generates RSA private key and saves it in application settings' do
application_setting = described_class::ApplicationSetting.create!
described_class.new.up
application_setting.reload
expect(application_setting.lets_encrypt_private_key).to be_present
expect do
OpenSSL::PKey::RSA.new(application_setting.lets_encrypt_private_key)
end.not_to raise_error
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment