diff --git a/app/models/alert_management/http_integration.rb b/app/models/alert_management/http_integration.rb index e98c770c36451df5328d86fefe150c881ec826b9..2caa9a184456d9f38f1ab475aa75d704c27babe0 100644 --- a/app/models/alert_management/http_integration.rb +++ b/app/models/alert_management/http_integration.rb @@ -10,7 +10,7 @@ class HttpIntegration < ApplicationRecord attr_encrypted :token, mode: :per_attribute_iv, - key: Settings.attr_encrypted_db_key_base_truncated, + key: Settings.attr_encrypted_db_key_base_32, algorithm: 'aes-256-gcm' default_value_for(:endpoint_identifier, allows_nil: false) { SecureRandom.hex(8) } diff --git a/app/models/alerting/project_alerting_setting.rb b/app/models/alerting/project_alerting_setting.rb index 8f8c38f11e40f3a4461b8162a7b01ef41e8fbf8f..34fa27eb29be9d74488794a806765a6321156e82 100644 --- a/app/models/alerting/project_alerting_setting.rb +++ b/app/models/alerting/project_alerting_setting.rb @@ -10,7 +10,7 @@ class ProjectAlertingSetting < ApplicationRecord attr_encrypted :token, mode: :per_attribute_iv, - key: Settings.attr_encrypted_db_key_base_truncated, + key: Settings.attr_encrypted_db_key_base_32, algorithm: 'aes-256-gcm' before_validation :ensure_token diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index f405f5ca5d318a2aba034305eeb35915c90d46bf..bf4acb40d9d61dc61822c0e26c973ed871e394bf 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -481,29 +481,29 @@ def self.kroki_formats_attributes algorithm: 'aes-256-cbc', insecure_mode: true - private_class_method def self.encryption_options_base_truncated_aes_256_gcm + private_class_method def self.encryption_options_base_32_aes_256_gcm { mode: :per_attribute_iv, - key: Settings.attr_encrypted_db_key_base_truncated, + key: Settings.attr_encrypted_db_key_base_32, algorithm: 'aes-256-gcm', encode: true } end - attr_encrypted :external_auth_client_key, encryption_options_base_truncated_aes_256_gcm - attr_encrypted :external_auth_client_key_pass, encryption_options_base_truncated_aes_256_gcm - attr_encrypted :lets_encrypt_private_key, encryption_options_base_truncated_aes_256_gcm - attr_encrypted :eks_secret_access_key, encryption_options_base_truncated_aes_256_gcm - 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 - attr_encrypted :ci_jwt_signing_key, encryption_options_base_truncated_aes_256_gcm - attr_encrypted :secret_detection_token_revocation_token, encryption_options_base_truncated_aes_256_gcm - attr_encrypted :cloud_license_auth_token, encryption_options_base_truncated_aes_256_gcm - attr_encrypted :external_pipeline_validation_service_token, encryption_options_base_truncated_aes_256_gcm + attr_encrypted :external_auth_client_key, encryption_options_base_32_aes_256_gcm + attr_encrypted :external_auth_client_key_pass, encryption_options_base_32_aes_256_gcm + attr_encrypted :lets_encrypt_private_key, encryption_options_base_32_aes_256_gcm + attr_encrypted :eks_secret_access_key, encryption_options_base_32_aes_256_gcm + attr_encrypted :akismet_api_key, encryption_options_base_32_aes_256_gcm + attr_encrypted :elasticsearch_aws_secret_access_key, encryption_options_base_32_aes_256_gcm + attr_encrypted :recaptcha_private_key, encryption_options_base_32_aes_256_gcm + attr_encrypted :recaptcha_site_key, encryption_options_base_32_aes_256_gcm + attr_encrypted :slack_app_secret, encryption_options_base_32_aes_256_gcm + attr_encrypted :slack_app_verification_token, encryption_options_base_32_aes_256_gcm + attr_encrypted :ci_jwt_signing_key, encryption_options_base_32_aes_256_gcm + attr_encrypted :secret_detection_token_revocation_token, encryption_options_base_32_aes_256_gcm + attr_encrypted :cloud_license_auth_token, encryption_options_base_32_aes_256_gcm + attr_encrypted :external_pipeline_validation_service_token, encryption_options_base_32_aes_256_gcm validates :disable_feed_token, inclusion: { in: [true, false], message: _('must be a boolean value') } diff --git a/app/models/atlassian/identity.rb b/app/models/atlassian/identity.rb index 906f2be0fbf31fc38e60b2bf821dc3194727167a..02bbe007e1b1fd5dfbbfd879898659108fe201ad 100644 --- a/app/models/atlassian/identity.rb +++ b/app/models/atlassian/identity.rb @@ -11,14 +11,14 @@ class Identity < ApplicationRecord attr_encrypted :token, mode: :per_attribute_iv, - key: Settings.attr_encrypted_db_key_base_truncated, + key: Settings.attr_encrypted_db_key_base_32, algorithm: 'aes-256-gcm', encode: false, encode_iv: false attr_encrypted :refresh_token, mode: :per_attribute_iv, - key: Settings.attr_encrypted_db_key_base_truncated, + key: Settings.attr_encrypted_db_key_base_32, algorithm: 'aes-256-gcm', encode: false, encode_iv: false diff --git a/app/models/bulk_imports/configuration.rb b/app/models/bulk_imports/configuration.rb index 4c6f745c2686b5bffd01bfd3da648034d7ca78ba..6d9f598583ea050eb8c32f759ffb13e9447739ae 100644 --- a/app/models/bulk_imports/configuration.rb +++ b/app/models/bulk_imports/configuration.rb @@ -12,11 +12,11 @@ class BulkImports::Configuration < ApplicationRecord allow_nil: true attr_encrypted :url, - key: Settings.attr_encrypted_db_key_base_truncated, + key: Settings.attr_encrypted_db_key_base_32, mode: :per_attribute_iv, algorithm: 'aes-256-gcm' attr_encrypted :access_token, - key: Settings.attr_encrypted_db_key_base_truncated, + key: Settings.attr_encrypted_db_key_base_32, mode: :per_attribute_iv, algorithm: 'aes-256-gcm' end diff --git a/app/models/clusters/applications/prometheus.rb b/app/models/clusters/applications/prometheus.rb index b9c136abab4062735b32a5549d4c309aa19a32dd..435a970294da1b584068436dcfdd6e9aa0d1be00 100644 --- a/app/models/clusters/applications/prometheus.rb +++ b/app/models/clusters/applications/prometheus.rb @@ -22,7 +22,7 @@ class Prometheus < ApplicationRecord attr_encrypted :alert_manager_token, mode: :per_attribute_iv, - key: Settings.attr_encrypted_db_key_base_truncated, + key: Settings.attr_encrypted_db_key_base_32, algorithm: 'aes-256-gcm' after_destroy do diff --git a/app/models/clusters/providers/aws.rb b/app/models/clusters/providers/aws.rb index bfd01775620d4834c3d17c2bdbba2929ec12d85f..af2eba427219fa66fa09584d978f2c0b4350cf07 100644 --- a/app/models/clusters/providers/aws.rb +++ b/app/models/clusters/providers/aws.rb @@ -18,7 +18,7 @@ class Aws < ApplicationRecord attr_encrypted :secret_access_key, mode: :per_attribute_iv, - key: Settings.attr_encrypted_db_key_base_truncated, + key: Settings.attr_encrypted_db_key_base_32, algorithm: 'aes-256-gcm' validates :role_arn, diff --git a/app/models/concerns/packages/debian/distribution.rb b/app/models/concerns/packages/debian/distribution.rb index 08fb9ccf3ea37c105ae4b259b638bcf6e442da4a..267c7a4d201f57693380c8fc74c4a73fb873a57e 100644 --- a/app/models/concerns/packages/debian/distribution.rb +++ b/app/models/concerns/packages/debian/distribution.rb @@ -84,7 +84,7 @@ def self.container_foreign_key attr_encrypted :signing_keys, mode: :per_attribute_iv, - key: Settings.attr_encrypted_db_key_base_truncated, + key: Settings.attr_encrypted_db_key_base_32, algorithm: 'aes-256-gcm', encode: false, encode_iv: false diff --git a/app/models/error_tracking/project_error_tracking_setting.rb b/app/models/error_tracking/project_error_tracking_setting.rb index 9a9fbc6a801ff1362c40975e433664f5de6190af..956b5d6470f02d9013260fbec6f1c6f265d845f1 100644 --- a/app/models/error_tracking/project_error_tracking_setting.rb +++ b/app/models/error_tracking/project_error_tracking_setting.rb @@ -38,7 +38,7 @@ class ProjectErrorTrackingSetting < ApplicationRecord attr_encrypted :token, mode: :per_attribute_iv, - key: Settings.attr_encrypted_db_key_base_truncated, + key: Settings.attr_encrypted_db_key_base_32, algorithm: 'aes-256-gcm' after_save :clear_reactive_cache! diff --git a/app/models/incident_management/project_incident_management_setting.rb b/app/models/incident_management/project_incident_management_setting.rb index 4887265be8889c87a122692782f25bb6b4cfc24c..3d4cb2f19122eff3b4146749ea2693a86cfaf2bd 100644 --- a/app/models/incident_management/project_incident_management_setting.rb +++ b/app/models/incident_management/project_incident_management_setting.rb @@ -12,7 +12,7 @@ class ProjectIncidentManagementSetting < ApplicationRecord attr_encrypted :pagerduty_token, mode: :per_attribute_iv, - key: ::Settings.attr_encrypted_db_key_base_truncated, + key: ::Settings.attr_encrypted_db_key_base_32, algorithm: 'aes-256-gcm', encode: false, # No need to encode for binary column https://github.com/attr-encrypted/attr_encrypted#the-encode-encode_iv-encode_salt-and-default_encoding-options encode_iv: false diff --git a/app/models/pages_domain_acme_order.rb b/app/models/pages_domain_acme_order.rb index 411456cc237bf61bf98d5ed090e86eef722def42..8427176fa72068926d2d0f8f3a34a1f26f30eafd 100644 --- a/app/models/pages_domain_acme_order.rb +++ b/app/models/pages_domain_acme_order.rb @@ -14,7 +14,7 @@ class PagesDomainAcmeOrder < ApplicationRecord attr_encrypted :private_key, mode: :per_attribute_iv, - key: Settings.attr_encrypted_db_key_base_truncated, + key: Settings.attr_encrypted_db_key_base_32, algorithm: 'aes-256-gcm', encode: true diff --git a/app/models/serverless/domain_cluster.rb b/app/models/serverless/domain_cluster.rb index 9f914d5c3f89d855a14803c32b949a1f7bfb26a9..0d54a97370e2efe3bdef38c37f13f19fd7cc7b35 100644 --- a/app/models/serverless/domain_cluster.rb +++ b/app/models/serverless/domain_cluster.rb @@ -12,7 +12,7 @@ class DomainCluster < ApplicationRecord attr_encrypted :key, mode: :per_attribute_iv, - key: Settings.attr_encrypted_db_key_base_truncated, + key: Settings.attr_encrypted_db_key_base_32, algorithm: 'aes-256-gcm' validates :pages_domain, :knative, presence: true diff --git a/config/secrets.yml.example b/config/secrets.yml.example index 6b408ac6031d9295c539e097a4a2d6c4872cb010..aadf13d53b2e60c22e172b8ed65e5b087700dcfa 100644 --- a/config/secrets.yml.example +++ b/config/secrets.yml.example @@ -1,7 +1,7 @@ production: # db_key_base is used to encrypt for Variables. Ensure that you don't lose it. # If you change or lose this key you will be unable to access variables stored in database. - # Make sure the secret is at least 30 characters and all random, + # Make sure the secret is at least 32 characters and all random, # no regular words or you'll be exposed to dictionary attacks. # db_key_base: diff --git a/config/settings.rb b/config/settings.rb index 3369f2a448053b924be473f2e3e671b70331e03b..a88f6d89ce421ca5d298c0aa748b36b3a29ef7b0 100644 --- a/config/settings.rb +++ b/config/settings.rb @@ -126,16 +126,18 @@ def absolute(path) File.expand_path(path, Rails.root) end - # Ruby 2.4+ requires passing in the exact required length for OpenSSL keys - # (https://github.com/ruby/ruby/commit/ce635262f53b760284d56bb1027baebaaec175d1). - # Previous versions quietly truncated the input. - # - # Use this when using :per_attribute_iv mode for attr_encrypted. - # We have to truncate the string to 32 bytes for a 256-bit cipher. + # Don't use this in new code, use attr_encrypted_db_key_base_32 instead! def attr_encrypted_db_key_base_truncated Gitlab::Application.secrets.db_key_base[0..31] end + # Ruby 2.4+ requires passing in the exact required length for OpenSSL keys + # (https://github.com/ruby/ruby/commit/ce635262f53b760284d56bb1027baebaaec175d1). + # Previous versions quietly truncated the input. + # + # Makes sure the key is exactly 32 bytes long, either by + # truncating or right-padding it with ASCII 0s. Use this when + # using :per_attribute_iv mode for attr_encrypted. def attr_encrypted_db_key_base_32 Gitlab::Utils.ensure_utf8_size(attr_encrypted_db_key_base, bytes: 32.bytes) 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 index e6b9a40ad4f97f526ac4d326b4a655ff7e720e4c..3ae5e3265e8330018fd370b02fbcd64812425c6c 100644 --- a/db/migrate/20191120115530_encrypt_plaintext_attributes_on_application_settings.rb +++ b/db/migrate/20191120115530_encrypt_plaintext_attributes_on_application_settings.rb @@ -17,21 +17,21 @@ class EncryptPlaintextAttributesOnApplicationSettings < ActiveRecord::Migration[ class ApplicationSetting < ActiveRecord::Base self.table_name = 'application_settings' - def self.encryption_options_base_truncated_aes_256_gcm + def self.encryption_options_base_32_aes_256_gcm { mode: :per_attribute_iv, - key: Gitlab::Application.secrets.db_key_base[0..31], + key: Gitlab::Utils.ensure_utf8_size(Rails.application.secrets.db_key_base, bytes: 32.bytes), 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 + attr_encrypted :akismet_api_key, encryption_options_base_32_aes_256_gcm + attr_encrypted :elasticsearch_aws_secret_access_key, encryption_options_base_32_aes_256_gcm + attr_encrypted :recaptcha_private_key, encryption_options_base_32_aes_256_gcm + attr_encrypted :recaptcha_site_key, encryption_options_base_32_aes_256_gcm + attr_encrypted :slack_app_secret, encryption_options_base_32_aes_256_gcm + attr_encrypted :slack_app_verification_token, encryption_options_base_32_aes_256_gcm def akismet_api_key decrypt(:akismet_api_key, self[:encrypted_akismet_api_key]) || self[:akismet_api_key] diff --git a/db/migrate/20201008013434_generate_ci_jwt_signing_key.rb b/db/migrate/20201008013434_generate_ci_jwt_signing_key.rb index 7983a56f439be11d69032078ff269ec6294aca3f..5d7b6349fe611408d6156ebcce0d263aeb4c3cef 100644 --- a/db/migrate/20201008013434_generate_ci_jwt_signing_key.rb +++ b/db/migrate/20201008013434_generate_ci_jwt_signing_key.rb @@ -8,7 +8,7 @@ class ApplicationSetting < ActiveRecord::Base attr_encrypted :ci_jwt_signing_key, { mode: :per_attribute_iv, - key: Rails.application.secrets.db_key_base[0..31], + key: Gitlab::Utils.ensure_utf8_size(Rails.application.secrets.db_key_base, bytes: 32.bytes), algorithm: 'aes-256-gcm', encode: true } diff --git a/ee/app/models/geo_node.rb b/ee/app/models/geo_node.rb index 09a2bdc40caacd1dd8581c4a8410445ab8c45c87..bdb0e6804420f9c201272589b0114809bea313fc 100644 --- a/ee/app/models/geo_node.rb +++ b/ee/app/models/geo_node.rb @@ -55,7 +55,7 @@ class GeoNode < ApplicationRecord scope :ordered, -> { order(:id) } attr_encrypted :secret_access_key, - key: Settings.attr_encrypted_db_key_base_truncated, + key: Settings.attr_encrypted_db_key_base_32, algorithm: 'aes-256-gcm', mode: :per_attribute_iv, encode: true diff --git a/spec/migrations/generate_ci_jwt_signing_key_spec.rb b/spec/migrations/generate_ci_jwt_signing_key_spec.rb index 4cfaa8701aa88984a195f5a3e357154a7b147921..249af3bcb5029be36ee91e5c545a007871bc7812 100644 --- a/spec/migrations/generate_ci_jwt_signing_key_spec.rb +++ b/spec/migrations/generate_ci_jwt_signing_key_spec.rb @@ -11,7 +11,7 @@ attr_encrypted :ci_jwt_signing_key, { mode: :per_attribute_iv, - key: Rails.application.secrets.db_key_base[0..31], + key: Gitlab::Utils.ensure_utf8_size(Rails.application.secrets.db_key_base, bytes: 32.bytes), algorithm: 'aes-256-gcm', encode: true }