Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/db
diff options
context:
space:
mode:
authorArturo Herrero <arturo.herrero@gmail.com>2019-11-05 13:08:31 +0300
committerArturo Herrero <arturo.herrero@gmail.com>2019-11-21 16:00:40 +0300
commita8855e2115dee85c7bc0056f538a770f6fabad27 (patch)
treef27dc2ada507e8104e2e61131cbd3a55e5c66ea7 /db
parent4d477238500c347c6553d335d920bedfc5a46869 (diff)
Encrypt application setting tokens
This is the plan to encrypt the plaintext tokens: First release (this commit): 1. Create new encrypted fields in the database. 2. Start populating new encrypted fields, read the encrypted fields or fallback to the plaintext fields. 3. Backfill the data removing the plaintext fields to the encrypted fields. Second release: 4. Remove the virtual attribute (created in step 2). 5. Drop plaintext columns from the database (empty columns after step 3).
Diffstat (limited to 'db')
-rw-r--r--db/migrate/20191120084627_add_encrypted_fields_to_application_settings.rb30
-rw-r--r--db/migrate/20191120115530_encrypt_plaintext_attributes_on_application_settings.rb93
-rw-r--r--db/schema.rb14
3 files changed, 136 insertions, 1 deletions
diff --git a/db/migrate/20191120084627_add_encrypted_fields_to_application_settings.rb b/db/migrate/20191120084627_add_encrypted_fields_to_application_settings.rb
new file mode 100644
index 00000000000..4e0886a5121
--- /dev/null
+++ b/db/migrate/20191120084627_add_encrypted_fields_to_application_settings.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+class AddEncryptedFieldsToApplicationSettings < ActiveRecord::Migration[5.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ PLAINTEXT_ATTRIBUTES = %w[
+ akismet_api_key
+ elasticsearch_aws_secret_access_key
+ recaptcha_private_key
+ recaptcha_site_key
+ slack_app_secret
+ slack_app_verification_token
+ ].freeze
+
+ def up
+ PLAINTEXT_ATTRIBUTES.each do |plaintext_attribute|
+ add_column :application_settings, "encrypted_#{plaintext_attribute}", :text
+ add_column :application_settings, "encrypted_#{plaintext_attribute}_iv", :string, limit: 255
+ end
+ end
+
+ def down
+ PLAINTEXT_ATTRIBUTES.each do |plaintext_attribute|
+ remove_column :application_settings, "encrypted_#{plaintext_attribute}"
+ remove_column :application_settings, "encrypted_#{plaintext_attribute}_iv"
+ end
+ end
+end
diff --git a/db/migrate/20191120115530_encrypt_plaintext_attributes_on_application_settings.rb b/db/migrate/20191120115530_encrypt_plaintext_attributes_on_application_settings.rb
new file mode 100644
index 00000000000..d7abb29fd75
--- /dev/null
+++ b/db/migrate/20191120115530_encrypt_plaintext_attributes_on_application_settings.rb
@@ -0,0 +1,93 @@
+# frozen_string_literal: true
+
+class EncryptPlaintextAttributesOnApplicationSettings < ActiveRecord::Migration[5.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ PLAINTEXT_ATTRIBUTES = %w[
+ akismet_api_key
+ elasticsearch_aws_secret_access_key
+ recaptcha_private_key
+ recaptcha_site_key
+ slack_app_secret
+ slack_app_verification_token
+ ].freeze
+
+ class ApplicationSetting < ActiveRecord::Base
+ self.table_name = 'application_settings'
+
+ def self.encryption_options_base_truncated_aes_256_gcm
+ {
+ mode: :per_attribute_iv,
+ key: Gitlab::Application.secrets.db_key_base[0..31],
+ algorithm: 'aes-256-gcm',
+ encode: true
+ }
+ end
+
+ attr_encrypted :akismet_api_key, encryption_options_base_truncated_aes_256_gcm
+ attr_encrypted :elasticsearch_aws_secret_access_key, encryption_options_base_truncated_aes_256_gcm
+ attr_encrypted :recaptcha_private_key, encryption_options_base_truncated_aes_256_gcm
+ attr_encrypted :recaptcha_site_key, encryption_options_base_truncated_aes_256_gcm
+ attr_encrypted :slack_app_secret, encryption_options_base_truncated_aes_256_gcm
+ attr_encrypted :slack_app_verification_token, encryption_options_base_truncated_aes_256_gcm
+
+ def akismet_api_key
+ decrypt(:akismet_api_key, self[:encrypted_akismet_api_key]) || self[:akismet_api_key]
+ end
+
+ def elasticsearch_aws_secret_access_key
+ decrypt(:elasticsearch_aws_secret_access_key, self[:encrypted_elasticsearch_aws_secret_access_key]) || self[:elasticsearch_aws_secret_access_key]
+ end
+
+ def recaptcha_private_key
+ decrypt(:recaptcha_private_key, self[:encrypted_recaptcha_private_key]) || self[:recaptcha_private_key]
+ end
+
+ def recaptcha_site_key
+ decrypt(:recaptcha_site_key, self[:encrypted_recaptcha_site_key]) || self[:recaptcha_site_key]
+ end
+
+ def slack_app_secret
+ decrypt(:slack_app_secret, self[:encrypted_slack_app_secret]) || self[:slack_app_secret]
+ end
+
+ def slack_app_verification_token
+ decrypt(:slack_app_verification_token, self[:encrypted_slack_app_verification_token]) || self[:slack_app_verification_token]
+ end
+ end
+
+ def up
+ ApplicationSetting.find_each do |application_setting|
+ # We are using the setter from attr_encrypted gem to encrypt the data.
+ # The gem updates the two columns needed to decrypt the value:
+ # - "encrypted_#{plaintext_attribute}"
+ # - "encrypted_#{plaintext_attribute}_iv"
+ application_setting.assign_attributes(
+ PLAINTEXT_ATTRIBUTES.each_with_object({}) do |plaintext_attribute, attributes|
+ attributes[plaintext_attribute] = application_setting.send(plaintext_attribute)
+ end
+ )
+ application_setting.save(validate: false)
+
+ application_setting.update_columns(
+ PLAINTEXT_ATTRIBUTES.each_with_object({}) do |plaintext_attribute, attributes|
+ attributes[plaintext_attribute] = nil
+ end
+ )
+ end
+ end
+
+ def down
+ ApplicationSetting.find_each do |application_setting|
+ application_setting.update_columns(
+ PLAINTEXT_ATTRIBUTES.each_with_object({}) do |plaintext_attribute, attributes|
+ attributes[plaintext_attribute] = application_setting.send(plaintext_attribute)
+ attributes["encrypted_#{plaintext_attribute}"] = nil
+ attributes["encrypted_#{plaintext_attribute}_iv"] = nil
+ end
+ )
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 95a4efb7e2a..2994fb20770 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 2019_10_26_041447) do
+ActiveRecord::Schema.define(version: 2019_11_20_115530) do
# These are extensions that must be enabled in order to support this database
enable_extension "pg_trgm"
@@ -341,6 +341,18 @@ ActiveRecord::Schema.define(version: 2019_10_26_041447) do
t.integer "push_event_hooks_limit", default: 3, null: false
t.integer "push_event_activities_limit", default: 3, null: false
t.string "custom_http_clone_url_root", limit: 511
+ t.text "encrypted_akismet_api_key"
+ t.string "encrypted_akismet_api_key_iv", limit: 255
+ t.text "encrypted_elasticsearch_aws_secret_access_key"
+ t.string "encrypted_elasticsearch_aws_secret_access_key_iv", limit: 255
+ t.text "encrypted_recaptcha_private_key"
+ t.string "encrypted_recaptcha_private_key_iv", limit: 255
+ t.text "encrypted_recaptcha_site_key"
+ t.string "encrypted_recaptcha_site_key_iv", limit: 255
+ t.text "encrypted_slack_app_secret"
+ t.string "encrypted_slack_app_secret_iv", limit: 255
+ t.text "encrypted_slack_app_verification_token"
+ t.string "encrypted_slack_app_verification_token_iv", limit: 255
t.index ["custom_project_templates_group_id"], name: "index_application_settings_on_custom_project_templates_group_id"
t.index ["file_template_project_id"], name: "index_application_settings_on_file_template_project_id"
t.index ["instance_administration_project_id"], name: "index_applicationsettings_on_instance_administration_project_id"