From 546c74e5a037600cd7ca95012a99a6ce0872fd15 Mon Sep 17 00:00:00 2001 From: Jason Young Date: Thu, 26 Jan 2023 20:40:09 -0500 Subject: [PATCH 01/14] Extend encrypted secrets support to incoming and service desk email This makes use of the encrypted settings in order to encrypt the incoming email and service desk email user/password Changelog: added Signed-off-by: Jason Young --- .rubocop_todo/gitlab/namespaced_class.yml | 2 + config/gitlab.yml.example | 4 + config/initializers/1_settings.rb | 2 + lib/gitlab/email/common.rb | 4 + .../encrypted_incoming_email_command.rb | 23 ++++++ .../encrypted_service_desk_email_command.rb | 23 ++++++ lib/gitlab/mail_room.rb | 76 +++++++++++++++++++ lib/tasks/gitlab/incoming_email.rake | 23 ++++++ lib/tasks/gitlab/service_desk_email.rake | 23 ++++++ 9 files changed, 180 insertions(+) create mode 100644 lib/gitlab/encrypted_incoming_email_command.rb create mode 100644 lib/gitlab/encrypted_service_desk_email_command.rb create mode 100644 lib/tasks/gitlab/incoming_email.rake create mode 100644 lib/tasks/gitlab/service_desk_email.rake diff --git a/.rubocop_todo/gitlab/namespaced_class.yml b/.rubocop_todo/gitlab/namespaced_class.yml index 54bb5d459e0716..4ce1b36a93abf3 100644 --- a/.rubocop_todo/gitlab/namespaced_class.yml +++ b/.rubocop_todo/gitlab/namespaced_class.yml @@ -1131,7 +1131,9 @@ Gitlab/NamespacedClass: - 'lib/gitlab/empty_search_results.rb' - 'lib/gitlab/encrypted_command_base.rb' - 'lib/gitlab/encrypted_configuration.rb' + - 'lib/gitlab/encrypted_incoming_email_command.rb' - 'lib/gitlab/encrypted_ldap_command.rb' + - 'lib/gitlab/encrypted_service_desk_email_command.rb' - 'lib/gitlab/encrypted_smtp_command.rb' - 'lib/gitlab/environment_logger.rb' - 'lib/gitlab/exceptions_app.rb' diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index 7342fe4821a0f6..1b18f977e4f259 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -271,6 +271,10 @@ production: &base # Default is '.gitlab_mailroom_secret' relative to Rails.root (i.e. root of the GitLab app). # secret_file: /home/git/gitlab/.gitlab_mailroom_secret + # File location to read encrypted incoming email secrets from + # encrypted_secret_file: /mnt/gitlab/smtp.yaml.enc + # Default: shared/encrypted_settings/incoming_email.yaml.enc + ## Consolidated object store config ## This will only take effect if the object_store sections are not defined ## within the types (e.g. artifacts, lfs, etc.). diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb index ea768b20990361..0afe09fa0a5b04 100644 --- a/config/initializers/1_settings.rb +++ b/config/initializers/1_settings.rb @@ -280,12 +280,14 @@ Settings['incoming_email'] ||= Settingslogic.new({}) Settings.incoming_email['enabled'] = false if Settings.incoming_email['enabled'].nil? Settings.incoming_email['inbox_method'] ||= 'imap' +Settings.incoming_email['encrypted_secret_file'] = Settings.absolute(Settings.incoming_email['encrypted_secret_file'] || File.join(Settings.encrypted_settings['path'], "incoming_email.yaml.enc")) # # Service desk email # Settings['service_desk_email'] ||= Settingslogic.new({}) Settings.service_desk_email['enabled'] = false if Settings.service_desk_email['enabled'].nil? +Settings.service_desk_email['encrypted_secret_file'] = Settings.absolute(Settings.service_desk_email['encrypted_secret_file'] || File.join(Settings.encrypted_settings['path'], "service_desk_email.yaml.enc")) # # Build Artifacts diff --git a/lib/gitlab/email/common.rb b/lib/gitlab/email/common.rb index afee8d9cd3d838..01316995c4d437 100644 --- a/lib/gitlab/email/common.rb +++ b/lib/gitlab/email/common.rb @@ -54,6 +54,10 @@ def scan_fallback_references(references) # It's looking for each <...> references.scan(/(?!<)[^<>]+(?=>)/) end + + def encrypted_secrets + Settings.encrypted(config.encrypted_secret_file) + end end end end diff --git a/lib/gitlab/encrypted_incoming_email_command.rb b/lib/gitlab/encrypted_incoming_email_command.rb new file mode 100644 index 00000000000000..a18382439d6875 --- /dev/null +++ b/lib/gitlab/encrypted_incoming_email_command.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +# rubocop:disable Rails/Output +module Gitlab + class EncryptedIncomingEmailCommand < EncryptedCommandBase + DISPLAY_NAME = "INCOMING_EMAIL" + EDIT_COMMAND_NAME = "gitlab:incoming_email:secret:edit" + + class << self + def encrypted_secrets + Gitlab::IncomingEmail.encrypted_secrets + end + + def encrypted_file_template + <<~YAML + # password: '123' + # user: 'gitlab-incoming@gmail.com' + YAML + end + end + end +end +# rubocop:enable Rails/Output diff --git a/lib/gitlab/encrypted_service_desk_email_command.rb b/lib/gitlab/encrypted_service_desk_email_command.rb new file mode 100644 index 00000000000000..ece6da7c1b3d94 --- /dev/null +++ b/lib/gitlab/encrypted_service_desk_email_command.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +# rubocop:disable Rails/Output +module Gitlab + class EncryptedServiceDeskEmailCommand < EncryptedCommandBase + DISPLAY_NAME = "SERVICE_DESK_EMAIL" + EDIT_COMMAND_NAME = "gitlab:service_desk_email:secret:edit" + + class << self + def encrypted_secrets + Gitlab::ServiceDeskEmail.encrypted_secrets + end + + def encrypted_file_template + <<~YAML + # password: '123' + # user: 'gitlab-incoming@gmail.com' + YAML + end + end + end +end +# rubocop:enable Rails/Output diff --git a/lib/gitlab/mail_room.rb b/lib/gitlab/mail_room.rb index f7cd28df5c9b5f..9ebcdf5610c704 100644 --- a/lib/gitlab/mail_room.rb +++ b/lib/gitlab/mail_room.rb @@ -3,6 +3,9 @@ require 'yaml' require 'json' require 'pathname' +require 'active_support' +require "active_support/core_ext/module/delegation" +require_relative 'encrypted_configuration' unless defined?(Gitlab::EncryptedConfiguration) require_relative 'redis/queues' unless defined?(Gitlab::Redis::Queues) # This service is run independently of the main Rails process, @@ -42,6 +45,20 @@ module MailRoom } }.freeze + # default path strings ( this is a data duplication + # with Settings which is not pulled in - see the service + # comment at the top of this file) + DEFAULT_PATHS = { + shared_path: 'shared', + encrypted_settings_path: 'encrypted_settings', + incoming_email: { + encrypted_secret_filename: 'incoming_email.yaml.enc' + }, + service_desk_email: { + encrypted_secret_filename: 'service_desk_email.yaml.enc' + } + }.freeze + class << self def enabled_configs @enabled_configs ||= configs.select { |_key, config| enabled?(config) } @@ -74,6 +91,12 @@ def fetch_config(config_key) config[:log_path] = File.expand_path(config[:log_path], RAILS_ROOT_DIR) + # override password/user from any encrypted secrets + if secrets = decrypted_secrets(config_key) + config[:password] = secrets[:password] if secrets[:password] + config[:user] = secrets[:user] if secrets[:user] + end + config end @@ -108,6 +131,59 @@ def config_file def load_yaml @yaml ||= YAML.load_file(config_file)[rails_env].deep_symbolize_keys end + + def application_secrets_file + File.expand_path('../../config/secrets.yml', __dir__) + end + + def application_secrets + return @application_secrets if @application_secrets + + @application_secrets = {} + # Uses Rails::Secret.parse + # from: https://github.com/rails/rails/blob/v6.1.6.1/railties/lib/rails/secrets.rb#L24 + erb_processed_yaml = ERB.new(File.read(application_secrets_file)).result + yaml_secrets = + YAML.respond_to?(:unsafe_load) ? YAML.unsafe_load(erb_processed_yaml) : YAML.safe_load(erb_processed_yaml) + @application_secrets.merge!(yaml_secrets["shared"].deep_symbolize_keys) if yaml_secrets["shared"] + @application_secrets.merge!(yaml_secrets[rails_env].deep_symbolize_keys) if yaml_secrets[rails_env] + end + + def default_encrypted_secret_filename(config_key) + DEFAULT_PATHS[config_key][:encrypted_secret_filename] + end + + def encrypted_secret_file(config_key) + config = merged_configs(config_key) + return config[:encrypted_secret_file] if config[:encrypted_secret_file] + + config_yaml = load_yaml + # Path handling for shared.path / encrypted_settings.path is a duplicate + # of the logic in config/initializers/1_settings.rb + shared_path = File.expand_path(config_yaml.dig(:shared, :path) || + DEFAULT_PATHS[:shared_path], RAILS_ROOT_DIR) + encrypted_settings_path = + File.expand_path(config_yaml.dig(:encrypted_settings, :path) || + File.join(shared_path, DEFAULT_PATHS[:encrypted_settings_path]), + RAILS_ROOT_DIR) + File.join(encrypted_settings_path, default_encrypted_secret_filename(config_key)) + end + + def encrypted_configuration_settings(config_key) + { + content_path: encrypted_secret_file(config_key), + base_key: application_secrets[:encrypted_settings_key_base], + previous_keys: application_secrets[:rotated_encrypted_settings_key_base] || [] + } + end + + def decrypted_secrets(config_key) + settings = encrypted_configuration_settings(config_key) + return if settings[:base_key].nil? + + ec = Gitlab::EncryptedConfiguration.new(**settings) + ec.active? ? ec.config : nil + end end end end diff --git a/lib/tasks/gitlab/incoming_email.rake b/lib/tasks/gitlab/incoming_email.rake new file mode 100644 index 00000000000000..eaceeb91ad00b3 --- /dev/null +++ b/lib/tasks/gitlab/incoming_email.rake @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +namespace :gitlab do + namespace :incoming_email do + namespace :secret do + desc 'GitLab | Incoming Email | Secret | Write Incoming Email secrets' + task write: [:environment] do + content = $stdin.tty? ? $stdin.gets : $stdin.read + Gitlab::EncryptedIncomingEmailCommand.write(content) + end + + desc 'GitLab | Incoming Email | Secret | Edit Incoming Email secrets' + task edit: [:environment] do + Gitlab::EncryptedIncomingEmailCommand.edit + end + + desc 'GitLab | Incoming Email | Secret | Show Incoming Email secrets' + task show: [:environment] do + Gitlab::EncryptedIncomingEmailCommand.show + end + end + end +end diff --git a/lib/tasks/gitlab/service_desk_email.rake b/lib/tasks/gitlab/service_desk_email.rake new file mode 100644 index 00000000000000..39c9d40bf5cf0d --- /dev/null +++ b/lib/tasks/gitlab/service_desk_email.rake @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +namespace :gitlab do + namespace :service_desk_email do + namespace :secret do + desc 'GitLab | Service Desk Email | Secret | Write Service Desk Email secrets' + task write: [:environment] do + content = $stdin.tty? ? $stdin.gets : $stdin.read + Gitlab::EncryptedServiceDeskEmailCommand.write(content) + end + + desc 'GitLab | Service Desk Email | Secret | Edit Service Desk Email secrets' + task edit: [:environment] do + Gitlab::EncryptedServiceDeskEmailCommand.edit + end + + desc 'GitLab | Service Desk Email | Secret | Show Service Desk Email secrets' + task show: [:environment] do + Gitlab::EncryptedServiceDeskEmailCommand.show + end + end + end +end -- GitLab From f77439310db1333ca40435cf14971eacb4669c04 Mon Sep 17 00:00:00 2001 From: Jason Young Date: Thu, 26 Jan 2023 20:40:58 -0500 Subject: [PATCH 02/14] Specs for incoming and service desk email encrypted secrets support Both encrypted fixtures are encrypted with a base key of `'0123456789abcdef' * 8` service_desk_email.yaml.enc contents: ``` password: '123abc' user: 'service-desk-test-account@gitlab.example.com' ``` incoming_email.yaml.enc contents: ``` password: 'abc123' user: 'incoming-test-account@gitlab.com' ``` Signed-off-by: Jason Young --- .../encrypted_secrets/incoming_email.yaml.enc | 1 + .../service_desk_email.yaml.enc | 1 + spec/fixtures/mail_room/secrets.yml.erb | 11 ++ spec/lib/gitlab/mail_room/mail_room_spec.rb | 63 ++++++++- spec/tasks/gitlab/incoming_email_rake_spec.rb | 122 +++++++++++++++++ .../gitlab/service_desk_email_rake_spec.rb | 127 ++++++++++++++++++ 6 files changed, 323 insertions(+), 2 deletions(-) create mode 100644 spec/fixtures/mail_room/encrypted_secrets/incoming_email.yaml.enc create mode 100644 spec/fixtures/mail_room/encrypted_secrets/service_desk_email.yaml.enc create mode 100644 spec/fixtures/mail_room/secrets.yml.erb create mode 100644 spec/tasks/gitlab/incoming_email_rake_spec.rb create mode 100644 spec/tasks/gitlab/service_desk_email_rake_spec.rb diff --git a/spec/fixtures/mail_room/encrypted_secrets/incoming_email.yaml.enc b/spec/fixtures/mail_room/encrypted_secrets/incoming_email.yaml.enc new file mode 100644 index 00000000000000..c11722e68478e4 --- /dev/null +++ b/spec/fixtures/mail_room/encrypted_secrets/incoming_email.yaml.enc @@ -0,0 +1 @@ +v7dkZ/3zpOBsA6XhOq99ai5S4czZlkdLUmNcH8AYOw56b7PgEMmtLHu39Fcyd4ZvERJNMIqyLuCwooqvJKfUeFRi9HpY0Q==--GldddWssSV3R/Ood--1XlQ63E4XCVqcfZVAd+NGQ== \ No newline at end of file diff --git a/spec/fixtures/mail_room/encrypted_secrets/service_desk_email.yaml.enc b/spec/fixtures/mail_room/encrypted_secrets/service_desk_email.yaml.enc new file mode 100644 index 00000000000000..bad1f2bbce11da --- /dev/null +++ b/spec/fixtures/mail_room/encrypted_secrets/service_desk_email.yaml.enc @@ -0,0 +1 @@ +nWE1RNp/i+RzboK4SqbQBI52cFP14G3hduqIOdus2Ffgul8n0vL/bKHMHaiCttq2hzGnzw5zcMGUWxJu3RkAhR0jnLAgbpBrYsxKTH72cqkJfw==--5FtWCIPwB8DldWkY--FLjDkVAsCzDM9VY1x7yifg== \ No newline at end of file diff --git a/spec/fixtures/mail_room/secrets.yml.erb b/spec/fixtures/mail_room/secrets.yml.erb new file mode 100644 index 00000000000000..fce7ff3180e1b9 --- /dev/null +++ b/spec/fixtures/mail_room/secrets.yml.erb @@ -0,0 +1,11 @@ +--- +production: + an_unread_key: 'this key will not be in the secrets' +shared: + a_shared_key: 'this key is shared' + an_overriden_shared_key: 'this key is overwritten by merge' +test: + an_environment_specific_key: 'test environment value' + an_overriden_shared_key: 'the merge overwrote this key' + erb_env_key: <%= ENV['KEY'] %> + encrypted_settings_key_base: <%= '0123456789abcdef' * 8 %> diff --git a/spec/lib/gitlab/mail_room/mail_room_spec.rb b/spec/lib/gitlab/mail_room/mail_room_spec.rb index 0c2c9b8900560e..a93d29197e8748 100644 --- a/spec/lib/gitlab/mail_room/mail_room_spec.rb +++ b/spec/lib/gitlab/mail_room/mail_room_spec.rb @@ -36,11 +36,12 @@ let(:incoming_email_config) { yml_config.merge(custom_config) } let(:service_desk_email_config) { yml_config.merge(custom_config) } + let(:global_config) { {} } let(:configs) do - { + global_config.merge({ incoming_email: incoming_email_config, service_desk_email: service_desk_email_config - } + }) end before do @@ -328,4 +329,62 @@ end end end + + describe 'mailroom encrypted configuration' do + let(:mail_room_template) { ERB.new(File.read(Rails.root.join("./config/mail_room.yml"))).result } + let(:mail_room_yml) { YAML.safe_load(mail_room_template, permitted_classes: [Symbol]) } + let(:application_secrets_file) { Rails.root.join('spec/fixtures/mail_room/secrets.yml.erb').to_s } + + before do + allow(described_class).to receive(:application_secrets_file).and_return(application_secrets_file) + stub_env('KEY', 'an environment variable value') + described_class.instance_variable_set(:@application_secrets, nil) + end + + after do + described_class.instance_variable_set(:@application_secrets, nil) + end + + context 'when using encrypted secrets' do + let(:encrypted_settings_key_base) { '0123456789abcdef' * 8 } + let(:global_config) do + { + encrypted_settings: { path: 'spec/fixtures/mail_room/encrypted_secrets' } + } + end + + it 'reads in the secrets.yml file as erb and merges shared and test environments' do + application_secrets = described_class.send(:application_secrets) + + expect(application_secrets).to match(a_hash_including( + a_shared_key: 'this key is shared', + an_overriden_shared_key: 'the merge overwrote this key', + an_environment_specific_key: 'test environment value', + erb_env_key: 'an environment variable value', + encrypted_settings_key_base: encrypted_settings_key_base + )) + + expect(application_secrets[:an_unread_key]).to be_nil + end + + it 'renders the encrypted secrets into the configuration correctly' do + expect(mail_room_yml[:mailboxes]).to be_an(Array) + expect(mail_room_yml[:mailboxes].length).to eq(2) + + expect(mail_room_yml[:mailboxes][0]).to match( + a_hash_including( + password: 'abc123', + email: 'incoming-test-account@gitlab.com' + ) + ) + + expect(mail_room_yml[:mailboxes][1]).to match( + a_hash_including( + password: '123abc', + email: 'service-desk-test-account@gitlab.example.com' + ) + ) + end + end + end end diff --git a/spec/tasks/gitlab/incoming_email_rake_spec.rb b/spec/tasks/gitlab/incoming_email_rake_spec.rb new file mode 100644 index 00000000000000..3e1cc663ddbd02 --- /dev/null +++ b/spec/tasks/gitlab/incoming_email_rake_spec.rb @@ -0,0 +1,122 @@ +# frozen_string_literal: true + +require 'rake_helper' + +RSpec.describe 'gitlab:incoming_email:secret rake tasks', :silence_stdout, feature_category: :build do + let(:encrypted_secret_file_dir) { Pathname.new(Dir.mktmpdir) } + let(:encrypted_secret_file) { encrypted_secret_file_dir.join('incoming_email.yaml.enc') } + + before do + Rake.application.rake_require 'tasks/gitlab/incoming_email' + stub_env('EDITOR', 'cat') + stub_warn_user_is_not_gitlab + allow(Gitlab.config.incoming_email).to receive(:encrypted_secret_file).and_return(encrypted_secret_file) + allow(Gitlab::Application.secrets).to receive(:encrypted_settings_key_base).and_return(SecureRandom.hex(64)) + end + + after do + FileUtils.rm_rf(Rails.root.join('tmp/tests/incoming_email_enc')) + end + + describe ':show' do + it 'displays error when file does not exist' do + expect { run_rake_task('gitlab:incoming_email:secret:show') }.to \ + output(/File .* does not exist. Use `gitlab-rake gitlab:incoming_email:secret:edit` to change that./).to_stdout + end + + it 'displays error when key does not exist' do + Settings.encrypted(encrypted_secret_file).write('somevalue') + allow(Gitlab::Application.secrets).to receive(:encrypted_settings_key_base).and_return(nil) + expect { run_rake_task('gitlab:incoming_email:secret:show') }.to \ + output(/Missing encryption key encrypted_settings_key_base./).to_stderr + end + + it 'displays error when key is changed' do + Settings.encrypted(encrypted_secret_file).write('somevalue') + allow(Gitlab::Application.secrets).to receive(:encrypted_settings_key_base).and_return(SecureRandom.hex(64)) + expect { run_rake_task('gitlab:incoming_email:secret:show') }.to \ + output(/Couldn't decrypt .* Perhaps you passed the wrong key?/).to_stderr + end + + it 'outputs the unencrypted content when present' do + encrypted = Settings.encrypted(encrypted_secret_file) + encrypted.write('somevalue') + expect { run_rake_task('gitlab:incoming_email:secret:show') }.to output(/somevalue/).to_stdout + end + end + + describe 'edit' do + it 'creates encrypted file' do + expect { run_rake_task('gitlab:incoming_email:secret:edit') }.to output(/File encrypted and saved./).to_stdout + expect(File.exist?(encrypted_secret_file)).to be true + value = Settings.encrypted(encrypted_secret_file) + expect(value.read).to match(/password: '123'/) + end + + it 'displays error when key does not exist' do + allow(Gitlab::Application.secrets).to receive(:encrypted_settings_key_base).and_return(nil) + expect { run_rake_task('gitlab:incoming_email:secret:edit') }.to \ + output(/Missing encryption key encrypted_settings_key_base./).to_stderr + end + + it 'displays error when key is changed' do + Settings.encrypted(encrypted_secret_file).write('somevalue') + allow(Gitlab::Application.secrets).to receive(:encrypted_settings_key_base).and_return(SecureRandom.hex(64)) + expect { run_rake_task('gitlab:incoming_email:secret:edit') }.to \ + output(/Couldn't decrypt .* Perhaps you passed the wrong key?/).to_stderr + end + + it 'displays error when write directory does not exist' do + FileUtils.rm_rf(encrypted_secret_file_dir) + expect { run_rake_task('gitlab:incoming_email:secret:edit') }.to \ + output(/Directory .* does not exist./).to_stderr + end + + it 'shows a warning when content is invalid' do + Settings.encrypted(encrypted_secret_file).write('somevalue') + expect { run_rake_task('gitlab:incoming_email:secret:edit') }.to \ + output(/WARNING: Content was not a valid INCOMING_EMAIL secret yml file/).to_stdout + value = Settings.encrypted(encrypted_secret_file) + expect(value.read).to match(/somevalue/) + end + + it 'displays error when $EDITOR is not set' do + stub_env('EDITOR', nil) + expect { run_rake_task('gitlab:incoming_email:secret:edit') }.to \ + output(/No \$EDITOR specified to open file. Please provide one when running the command/).to_stderr + end + end + + describe 'write' do + before do + allow($stdin).to receive(:tty?).and_return(false) + allow($stdin).to receive(:read).and_return('username: foo') + end + + it 'creates encrypted file from stdin' do + expect { run_rake_task('gitlab:incoming_email:secret:write') }.to output(/File encrypted and saved./).to_stdout + expect(File.exist?(encrypted_secret_file)).to be true + value = Settings.encrypted(encrypted_secret_file) + expect(value.read).to match(/username: foo/) + end + + it 'displays error when key does not exist' do + allow(Gitlab::Application.secrets).to receive(:encrypted_settings_key_base).and_return(nil) + expect { run_rake_task('gitlab:incoming_email:secret:write') }.to \ + output(/Missing encryption key encrypted_settings_key_base./).to_stderr + end + + it 'displays error when write directory does not exist' do + FileUtils.rm_rf(encrypted_secret_file_dir) + expect { run_rake_task('gitlab:incoming_email:secret:write') }.to output(/Directory .* does not exist./).to_stderr + end + + it 'shows a warning when content is invalid' do + Settings.encrypted(encrypted_secret_file).write('somevalue') + expect { run_rake_task('gitlab:incoming_email:secret:edit') }.to \ + output(/WARNING: Content was not a valid INCOMING_EMAIL secret yml file/).to_stdout + value = Settings.encrypted(encrypted_secret_file) + expect(value.read).to match(/somevalue/) + end + end +end diff --git a/spec/tasks/gitlab/service_desk_email_rake_spec.rb b/spec/tasks/gitlab/service_desk_email_rake_spec.rb new file mode 100644 index 00000000000000..6a1a7473f4a272 --- /dev/null +++ b/spec/tasks/gitlab/service_desk_email_rake_spec.rb @@ -0,0 +1,127 @@ +# frozen_string_literal: true + +require 'rake_helper' + +RSpec.describe 'gitlab:service_desk_email:secret rake tasks', :silence_stdout, feature_category: :build do + let(:encrypted_secret_file_dir) { Pathname.new(Dir.mktmpdir) } + let(:encrypted_secret_file) { encrypted_secret_file_dir.join('service_desk_email.yaml.enc') } + + before do + Rake.application.rake_require 'tasks/gitlab/service_desk_email' + stub_env('EDITOR', 'cat') + stub_warn_user_is_not_gitlab + FileUtils.mkdir_p('tmp/tests/service_desk_email_enc/') + allow(Gitlab.config.service_desk_email).to receive(:encrypted_secret_file).and_return(encrypted_secret_file) + allow(Gitlab::Application.secrets).to receive(:encrypted_settings_key_base).and_return(SecureRandom.hex(64)) + end + + after do + FileUtils.rm_rf(Rails.root.join('tmp/tests/service_desk_email_enc')) + end + + describe ':show' do + it 'displays error when file does not exist' do + expect { run_rake_task('gitlab:service_desk_email:secret:show') }.to \ + output(/File .* does not exist. Use `gitlab-rake gitlab:service_desk_email:secret:edit` to change that./) \ + .to_stdout + end + + it 'displays error when key does not exist' do + Settings.encrypted(encrypted_secret_file).write('somevalue') + allow(Gitlab::Application.secrets).to receive(:encrypted_settings_key_base).and_return(nil) + expect { run_rake_task('gitlab:service_desk_email:secret:show') }.to \ + output(/Missing encryption key encrypted_settings_key_base./).to_stderr + end + + it 'displays error when key is changed' do + Settings.encrypted(encrypted_secret_file).write('somevalue') + allow(Gitlab::Application.secrets).to receive(:encrypted_settings_key_base).and_return(SecureRandom.hex(64)) + expect { run_rake_task('gitlab:service_desk_email:secret:show') }.to \ + output(/Couldn't decrypt .* Perhaps you passed the wrong key?/).to_stderr + end + + it 'outputs the unencrypted content when present' do + encrypted = Settings.encrypted(encrypted_secret_file) + encrypted.write('somevalue') + expect { run_rake_task('gitlab:service_desk_email:secret:show') }.to output(/somevalue/).to_stdout + end + end + + describe 'edit' do + it 'creates encrypted file' do + expect { run_rake_task('gitlab:service_desk_email:secret:edit') }.to \ + output(/File encrypted and saved./).to_stdout + expect(File.exist?(encrypted_secret_file)).to be true + value = Settings.encrypted(encrypted_secret_file) + expect(value.read).to match(/password: '123'/) + end + + it 'displays error when key does not exist' do + allow(Gitlab::Application.secrets).to receive(:encrypted_settings_key_base).and_return(nil) + expect { run_rake_task('gitlab:service_desk_email:secret:edit') }.to \ + output(/Missing encryption key encrypted_settings_key_base./).to_stderr + end + + it 'displays error when key is changed' do + Settings.encrypted(encrypted_secret_file).write('somevalue') + allow(Gitlab::Application.secrets).to receive(:encrypted_settings_key_base).and_return(SecureRandom.hex(64)) + expect { run_rake_task('gitlab:service_desk_email:secret:edit') }.to \ + output(/Couldn't decrypt .* Perhaps you passed the wrong key?/).to_stderr + end + + it 'displays error when write directory does not exist' do + FileUtils.rm_rf(encrypted_secret_file_dir) + expect { run_rake_task('gitlab:service_desk_email:secret:edit') }.to \ + output(/Directory .* does not exist./).to_stderr + end + + it 'shows a warning when content is invalid' do + Settings.encrypted(encrypted_secret_file).write('somevalue') + expect { run_rake_task('gitlab:service_desk_email:secret:edit') }.to \ + output(/WARNING: Content was not a valid SERVICE_DESK_EMAIL secret yml file/).to_stdout + value = Settings.encrypted(encrypted_secret_file) + expect(value.read).to match(/somevalue/) + end + + it 'displays error when $EDITOR is not set' do + stub_env('EDITOR', nil) + expect { run_rake_task('gitlab:service_desk_email:secret:edit') }.to \ + output(/No \$EDITOR specified to open file. Please provide one when running the command/).to_stderr + end + end + + describe 'write' do + before do + allow($stdin).to receive(:tty?).and_return(false) + allow($stdin).to receive(:read).and_return('username: foo') + end + + it 'creates encrypted file from stdin' do + expect { run_rake_task('gitlab:service_desk_email:secret:write') }.to \ + output(/File encrypted and saved./).to_stdout + expect(File.exist?(encrypted_secret_file)).to be true + value = Settings.encrypted(encrypted_secret_file) + expect(value.read).to match(/username: foo/) + end + + it 'displays error when key does not exist' do + allow(Gitlab::Application.secrets).to receive(:encrypted_settings_key_base).and_return(nil) + expect { run_rake_task('gitlab:service_desk_email:secret:write') }.to \ + output(/Missing encryption key encrypted_settings_key_base./).to_stderr + end + + it 'displays error when write directory does not exist' do + FileUtils.rm_rf(encrypted_secret_file_dir) + expect { run_rake_task('gitlab:service_desk_email:secret:write') }.to \ + output(/Directory .* does not exist./).to_stderr + end + + it 'shows a warning when content is invalid' do + Settings.encrypted(encrypted_secret_file).write('somevalue') + expect { run_rake_task('gitlab:service_desk_email:secret:edit') }.to \ + output(/WARNING: Content was not a valid SERVICE_DESK_EMAIL secret yml file/).to_stdout + value = Settings.encrypted(encrypted_secret_file) + expect(value.read).to match(/somevalue/) + end + end +end -- GitLab From e7f20cf124b77f1ce5f5117fc628a630b7d34e0f Mon Sep 17 00:00:00 2001 From: Jason Young Date: Thu, 26 Jan 2023 20:41:31 -0500 Subject: [PATCH 03/14] Instrumentation classes and configuration for service ping Signed-off-by: Jason Young --- ...coming_email_encrypted_secrets_enabled.yml | 23 +++++++++++++++++++ ...e_desk_email_encrypted_secrets_enabled.yml | 23 +++++++++++++++++++ ..._email_encrypted_secrets_enabled_metric.rb | 15 ++++++++++++ ..._email_encrypted_secrets_enabled_metric.rb | 15 ++++++++++++ ...l_encrypted_secrets_enabled_metric_spec.rb | 10 ++++++++ ...l_encrypted_secrets_enabled_metric_spec.rb | 10 ++++++++ 6 files changed, 96 insertions(+) create mode 100644 config/metrics/settings/20230125220526_incoming_email_encrypted_secrets_enabled.yml create mode 100644 config/metrics/settings/20230125221700_service_desk_email_encrypted_secrets_enabled.yml create mode 100644 lib/gitlab/usage/metrics/instrumentations/incoming_email_encrypted_secrets_enabled_metric.rb create mode 100644 lib/gitlab/usage/metrics/instrumentations/service_desk_email_encrypted_secrets_enabled_metric.rb create mode 100644 spec/lib/gitlab/usage/metrics/instrumentations/incoming_email_encrypted_secrets_enabled_metric_spec.rb create mode 100644 spec/lib/gitlab/usage/metrics/instrumentations/service_desk_email_encrypted_secrets_enabled_metric_spec.rb diff --git a/config/metrics/settings/20230125220526_incoming_email_encrypted_secrets_enabled.yml b/config/metrics/settings/20230125220526_incoming_email_encrypted_secrets_enabled.yml new file mode 100644 index 00000000000000..ae73bcbafea5d8 --- /dev/null +++ b/config/metrics/settings/20230125220526_incoming_email_encrypted_secrets_enabled.yml @@ -0,0 +1,23 @@ +--- +key_path: settings.incoming_email_encrypted_secrets_enabled +description: Are encrypted incoming email secrets configured? +product_section: enablement +product_stage: enablement +product_group: distribution +product_category: build +value_type: boolean +status: active +milestone: "15.9" +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/108279 +time_frame: none +data_source: system +data_category: optional +instrumentation_class: IncomingEmailEncryptedSecretsEnabledMetric +performance_indicator_type: [] +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate diff --git a/config/metrics/settings/20230125221700_service_desk_email_encrypted_secrets_enabled.yml b/config/metrics/settings/20230125221700_service_desk_email_encrypted_secrets_enabled.yml new file mode 100644 index 00000000000000..227bc86adfa2f9 --- /dev/null +++ b/config/metrics/settings/20230125221700_service_desk_email_encrypted_secrets_enabled.yml @@ -0,0 +1,23 @@ +--- +key_path: settings.service_desk_email_encrypted_secrets_enabled +description: Are service desk email secrets configured? +product_section: enablement +product_stage: enablement +product_group: distribution +product_category: build +value_type: boolean +status: active +milestone: "15.9" +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/108279 +time_frame: none +data_source: system +data_category: optional +instrumentation_class: ServiceDeskEmailEncryptedSecretsEnabledMetric +performance_indicator_type: [] +distribution: +- ce +- ee +tier: +- free +- premium +- ultimate diff --git a/lib/gitlab/usage/metrics/instrumentations/incoming_email_encrypted_secrets_enabled_metric.rb b/lib/gitlab/usage/metrics/instrumentations/incoming_email_encrypted_secrets_enabled_metric.rb new file mode 100644 index 00000000000000..ab9c6f87023c02 --- /dev/null +++ b/lib/gitlab/usage/metrics/instrumentations/incoming_email_encrypted_secrets_enabled_metric.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module Gitlab + module Usage + module Metrics + module Instrumentations + class IncomingEmailEncryptedSecretsEnabledMetric < GenericMetric + value do + Gitlab::IncomingEmail.encrypted_secrets.active? + end + end + end + end + end +end diff --git a/lib/gitlab/usage/metrics/instrumentations/service_desk_email_encrypted_secrets_enabled_metric.rb b/lib/gitlab/usage/metrics/instrumentations/service_desk_email_encrypted_secrets_enabled_metric.rb new file mode 100644 index 00000000000000..4332043de8a0c5 --- /dev/null +++ b/lib/gitlab/usage/metrics/instrumentations/service_desk_email_encrypted_secrets_enabled_metric.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module Gitlab + module Usage + module Metrics + module Instrumentations + class ServiceDeskEmailEncryptedSecretsEnabledMetric < GenericMetric + value do + Gitlab::ServiceDeskEmail.encrypted_secrets.active? + end + end + end + end + end +end diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/incoming_email_encrypted_secrets_enabled_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/incoming_email_encrypted_secrets_enabled_metric_spec.rb new file mode 100644 index 00000000000000..ed35b2c8cdea05 --- /dev/null +++ b/spec/lib/gitlab/usage/metrics/instrumentations/incoming_email_encrypted_secrets_enabled_metric_spec.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Usage::Metrics::Instrumentations::IncomingEmailEncryptedSecretsEnabledMetric, +feature_category: :service_ping do + it_behaves_like 'a correct instrumented metric value', { time_frame: 'none', data_source: 'ruby' } do + let(:expected_value) { ::Gitlab::IncomingEmail.encrypted_secrets.active? } + end +end diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/service_desk_email_encrypted_secrets_enabled_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/service_desk_email_encrypted_secrets_enabled_metric_spec.rb new file mode 100644 index 00000000000000..d602eae3159de3 --- /dev/null +++ b/spec/lib/gitlab/usage/metrics/instrumentations/service_desk_email_encrypted_secrets_enabled_metric_spec.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Usage::Metrics::Instrumentations::ServiceDeskEmailEncryptedSecretsEnabledMetric, +feature_category: :service_ping do + it_behaves_like 'a correct instrumented metric value', { time_frame: 'none', data_source: 'ruby' } do + let(:expected_value) { ::Gitlab::ServiceDeskEmail.encrypted_secrets.active? } + end +end -- GitLab From 41a71ebe46dfa80fa738154ac465041b4835e1ca Mon Sep 17 00:00:00 2001 From: Jason Young Date: Thu, 26 Jan 2023 20:41:50 -0500 Subject: [PATCH 04/14] Docs additions and updates Signed-off-by: Jason Young --- doc/administration/encrypted_configuration.md | 2 + doc/administration/incoming_email.md | 128 +++++++++++++++ .../raketasks/incoming_email.md | 149 ++++++++++++++++++ .../raketasks/service_desk_email.md | 149 ++++++++++++++++++ doc/raketasks/index.md | 2 + doc/user/project/service_desk.md | 128 +++++++++++++++ 6 files changed, 558 insertions(+) create mode 100644 doc/administration/raketasks/incoming_email.md create mode 100644 doc/administration/raketasks/service_desk_email.md diff --git a/doc/administration/encrypted_configuration.md b/doc/administration/encrypted_configuration.md index 648f6d7018ef30..1ddf2951f70b34 100644 --- a/doc/administration/encrypted_configuration.md +++ b/doc/administration/encrypted_configuration.md @@ -11,7 +11,9 @@ type: reference GitLab can read settings for certain features from encrypted settings files. The supported features are: +- [Incoming email `user` and `password`](incoming_email.md#use-encrypted-credentials). - [LDAP `bind_dn` and `password`](auth/ldap/index.md#use-encrypted-credentials). +- [Service Desk email `user` and `password`](../user/project/service_desk.md#use-encrypted-credentials). - [SMTP `user_name` and `password`](raketasks/smtp.md#secrets). To enable the encrypted configuration settings, a new base key must be generated for diff --git a/doc/administration/incoming_email.md b/doc/administration/incoming_email.md index 86c80c06f16731..d77bd1cdd6e8d1 100644 --- a/doc/administration/incoming_email.md +++ b/doc/administration/incoming_email.md @@ -867,3 +867,131 @@ gitlab_rails['incoming_email_inbox_options'] = { ``` The Microsoft Graph API is not yet supported in source installations. See [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/326169) for more details. + +### Use encrypted credentials + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/108279) in GitLab 15.9. + +Instead of having the incoming email credentials stored in plaintext in the configuration files, you can optionally +use an encrypted file for the incoming email credentials. + +Prerequisites: + +- To use encrypted credentials, you must first enable the + [encrypted configuration](encrypted_configuration.md). + +The supported configuration items for the encrypted file are: + +- `user` +- `password` + +::Tabs + +:::TabTitle Linux package (Omnibus) + +1. If initially your incoming email configuration in `/etc/gitlab/gitlab.rb` looked like: + + ```ruby + gitlab_rails['incoming_email_email'] = "incoming-email@mail.example.com" + gitlab_rails['incoming_email_password'] = "examplepassword" + ``` + +1. Edit the encrypted secret: + + ```shell + sudo gitlab-rake gitlab:incoming_email:secret:edit EDITOR=vim + ``` + +1. Enter the unencrypted contents of the incoming email secret: + + ```yaml + user: 'incoming-email@mail.example.com' + password: 'examplepassword' + ``` + +1. Edit `/etc/gitlab/gitlab.rb` and remove the `incoming_email` settings for `email` and `password`. +1. Save the file and reconfigure GitLab: + + ```shell + sudo gitlab-ctl reconfigure + ``` + +:::TabTitle Helm chart (Kubernetes) + +Use a Kubernetes secret to store the incoming email password. For more information, +read about [Helm IMAP secrets](https://docs.gitlab.com/charts/installation/secrets.html#imap-password-for-incoming-emails). + +:::TabTitle Docker + +1. If initially your incoming email configuration in `docker-compose.yml` looked like: + + ```yaml + version: "3.6" + services: + gitlab: + image: 'gitlab/gitlab-ee:latest' + restart: always + hostname: 'gitlab.example.com' + environment: + GITLAB_OMNIBUS_CONFIG: | + gitlab_rails['incoming_email_email'] = "incoming-email@mail.example.com" + gitlab_rails['incoming_email_password'] = "examplepassword" + ``` + +1. Get inside the container, and edit the encrypted secret: + + ```shell + sudo docker exec -t bash + gitlab-rake gitlab:incoming_email:secret:edit EDITOR=vim + ``` + +1. Enter the unencrypted contents of the incoming email secret: + + ```yaml + user: 'incoming-email@mail.example.com' + password: 'examplepassword' + ``` + +1. Edit `docker-compose.yml` and remove the `incoming_email` settings for `email` and `password`. +1. Save the file and restart GitLab: + + ```shell + docker compose up -d + ``` + +:::TabTitle Self-compiled (source) + +1. If initially your incoming email configuration in `/home/git/gitlab/config/gitlab.yml` looked like: + + ```yaml + production: + incoming_email: + user: 'incoming-email@mail.example.com' + password: 'examplepassword' + ``` + +1. Edit the encrypted secret: + + ```shell + bundle exec rake gitlab:incoming_email:secret:edit EDITOR=vim RAILS_ENVIRONMENT=production + ``` + +1. Enter the unencrypted contents of the incoming email secret: + + ```yaml + user: 'incoming-email@mail.example.com' + password: 'examplepassword' + ``` + +1. Edit `/home/git/gitlab/config/gitlab.yml` and remove the `incoming_email:` settings for `user` and `password`. +1. Save the file and restart GitLab and Mailroom + + ```shell + # For systems running systemd + sudo systemctl restart gitlab.target + + # For systems running SysV init + sudo service gitlab restart + ``` + +::EndTabs diff --git a/doc/administration/raketasks/incoming_email.md b/doc/administration/raketasks/incoming_email.md new file mode 100644 index 00000000000000..622b0d0118af59 --- /dev/null +++ b/doc/administration/raketasks/incoming_email.md @@ -0,0 +1,149 @@ +--- +stage: Systems +group: Distribution +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments +--- + +# Incoming email Rake tasks **(FREE SELF)** + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/108279) in GitLab 15.9. + +The following are Incoming email-related Rake tasks. + +## Secrets + +GitLab can use [Incoming email](../incoming_email.md) secrets read from an encrypted file instead of storing them in plaintext in the file system. The following Rake tasks are provided for updating the contents of the encrypted file. + +### Show secret + +Show the contents of the current Incoming email secrets. + +::Tabs + +:::TabTitle Linux package (Omnibus) + +```shell +sudo gitlab-rake gitlab:incoming_email:secret:show +``` + +:::TabTitle Helm chart (Kubernetes) + +Use a Kubernetes secret to store the incoming email password. For more information, +read about [Helm IMAP secrets](https://docs.gitlab.com/charts/installation/secrets.html#imap-password-for-incoming-emails). + +:::TabTitle Docker + +```shell +sudo docker exec -t gitlab:incoming_email:secret:show +``` + +:::TabTitle Self-compiled (source) + +```shell +bundle exec rake gitlab:incoming_email:secret:show RAILS_ENV=production +``` + +::EndTabs + +#### Example output + +```plaintext +password: 'examplepassword' +user: 'incoming-email@mail.example.com' +``` + +### Edit secret + +Opens the secret contents in your editor, and writes the resulting content to the encrypted secret file when you exit. + +::Tabs + +:::TabTitle Linux package (Omnibus) + +```shell +sudo gitlab-rake gitlab:incoming_email:secret:edit EDITOR=vim +``` + +:::TabTitle Helm chart (Kubernetes) + +Use a Kubernetes secret to store the incoming email password. For more information, +read about [Helm IMAP secrets](https://docs.gitlab.com/charts/installation/secrets.html#imap-password-for-incoming-emails). + +:::TabTitle Docker + +```shell +sudo docker exec -t gitlab:incoming_email:secret:edit EDITOR=vim +``` + +:::TabTitle Self-compiled (source) + +```shell +bundle exec rake gitlab:incoming_email:secret:edit RAILS_ENV=production EDITOR=vim +``` + +::EndTabs + +### Write raw secret + +Write new secret content by providing it on `STDIN`. + +::Tabs + +:::TabTitle Linux package (Omnibus) + +```shell +echo -e "password: 'examplepassword'" | sudo gitlab-rake gitlab:incoming_email:secret:write +``` + +:::TabTitle Helm chart (Kubernetes) + +Use a Kubernetes secret to store the incoming email password. For more information, +read about [Helm IMAP secrets](https://docs.gitlab.com/charts/installation/secrets.html#imap-password-for-incoming-emails). + +:::TabTitle Docker + +```shell +sudo docker exec -t /bin/bash +echo -e "password: 'examplepassword'" | gitlab-rake gitlab:incoming_email:secret:write +``` + +:::TabTitle Self-compiled (source) + +```shell +echo -e "password: 'examplepassword'" | bundle exec rake gitlab:incoming_email:secret:write RAILS_ENV=production +``` + +::EndTabs + +### Secrets examples + +**Editor example** + +The write task can be used in cases where the edit command does not work with your editor: + +```shell +# Write the existing secret to a plaintext file +sudo gitlab-rake gitlab:incoming_email:secret:show > incoming_email.yaml +# Edit the incoming_email file in your editor +... +# Re-encrypt the file +cat incoming_email.yaml | sudo gitlab-rake gitlab:incoming_email:secret:write +# Remove the plaintext file +rm incoming_email.yaml +``` + +**KMS integration example** + +It can also be used as a receiving application for content encrypted with a KMS: + +```shell +gcloud kms decrypt --key my-key --keyring my-test-kms --plaintext-file=- --ciphertext-file=my-file --location=us-west1 | sudo gitlab-rake gitlab:incoming_email:secret:write +``` + +**Google Cloud secret integration example** + +It can also be used as a receiving application for secrets out of Google Cloud: + +```shell +gcloud secrets versions access latest --secret="my-test-secret" > $1 | sudo gitlab-rake gitlab:incoming_email:secret:write +``` diff --git a/doc/administration/raketasks/service_desk_email.md b/doc/administration/raketasks/service_desk_email.md new file mode 100644 index 00000000000000..a263db2cbd128a --- /dev/null +++ b/doc/administration/raketasks/service_desk_email.md @@ -0,0 +1,149 @@ +--- +stage: Systems +group: Distribution +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments +--- + +# Service Desk email Rake tasks **(FREE SELF)** + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/108279) in GitLab 15.9. + +The following are Service Desk email-related Rake tasks. + +## Secrets + +GitLab can use [Service Desk email](../../user/project/service_desk.md#configuring-a-custom-mailbox) secrets read from an encrypted file instead of storing them in plaintext in the file system. The following Rake tasks are provided for updating the contents of the encrypted file. + +### Show secret + +Show the contents of the current Service Desk email secrets. + +::Tabs + +:::TabTitle Linux package (Omnibus) + +```shell +sudo gitlab-rake gitlab:service_desk_email:secret:show +``` + +:::TabTitle Helm chart (Kubernetes) + +Use a Kubernetes secret to store the Service Desk email password. For more information, +read about [Helm IMAP secrets](https://docs.gitlab.com/charts/installation/secrets.html#imap-password-for-service-desk-emails). + +:::TabTitle Docker + +```shell +sudo docker exec -t gitlab:service_desk_email:secret:show +``` + +:::TabTitle Self-compiled (source) + +```shell +bundle exec rake gitlab:service_desk_email:secret:show RAILS_ENV=production +``` + +::EndTabs + +#### Example output + +```plaintext +password: 'examplepassword' +user: 'service-desk-email@mail.example.com' +``` + +### Edit secret + +Opens the secret contents in your editor, and writes the resulting content to the encrypted secret file when you exit. + +::Tabs + +:::TabTitle Linux package (Omnibus) + +```shell +sudo gitlab-rake gitlab:service_desk_email:secret:edit EDITOR=vim +``` + +:::TabTitle Helm chart (Kubernetes) + +Use a Kubernetes secret to store the Service Desk email password. For more information, +read about [Helm IMAP secrets](https://docs.gitlab.com/charts/installation/secrets.html#imap-password-for-service-desk-emails). + +:::TabTitle Docker + +```shell +sudo docker exec -t gitlab:service_desk_email:secret:edit EDITOR=vim +``` + +:::TabTitle Self-compiled (source) + +```shell +bundle exec rake gitlab:service_desk_email:secret:edit RAILS_ENV=production EDITOR=vim +``` + +::EndTabs + +### Write raw secret + +Write new secret content by providing it on `STDIN`. + +::Tabs + +:::TabTitle Linux package (Omnibus) + +```shell +echo -e "password: 'examplepassword'" | sudo gitlab-rake gitlab:service_desk_email:secret:write +``` + +:::TabTitle Helm chart (Kubernetes) + +Use a Kubernetes secret to store the Service Desk email password. For more information, +read about [Helm IMAP secrets](https://docs.gitlab.com/charts/installation/secrets.html#imap-password-for-service-desk-emails). + +:::TabTitle Docker + +```shell +sudo docker exec -t /bin/bash +echo -e "password: 'examplepassword'" | gitlab-rake gitlab:service_desk_email:secret:write +``` + +:::TabTitle Self-compiled (source) + +```shell +echo -e "password: 'examplepassword'" | bundle exec rake gitlab:service_desk_email:secret:write RAILS_ENV=production +``` + +::EndTabs + +### Secrets examples + +**Editor example** + +The write task can be used in cases where the edit command does not work with your editor: + +```shell +# Write the existing secret to a plaintext file +sudo gitlab-rake gitlab:service_desk_email:secret:show > service_desk_email.yaml +# Edit the service_desk_email file in your editor +... +# Re-encrypt the file +cat service_desk_email.yaml | sudo gitlab-rake gitlab:service_desk_email:secret:write +# Remove the plaintext file +rm service_desk_email.yaml +``` + +**KMS integration example** + +It can also be used as a receiving application for content encrypted with a KMS: + +```shell +gcloud kms decrypt --key my-key --keyring my-test-kms --plaintext-file=- --ciphertext-file=my-file --location=us-west1 | sudo gitlab-rake gitlab:service_desk_email:secret:write +``` + +**Google Cloud secret integration example** + +It can also be used as a receiving application for secrets out of Google Cloud: + +```shell +gcloud secrets versions access latest --secret="my-test-secret" > $1 | sudo gitlab-rake gitlab:service_desk_email:secret:write +``` diff --git a/doc/raketasks/index.md b/doc/raketasks/index.md index 1b8eccc7ae4203..b5a778d6b7417d 100644 --- a/doc/raketasks/index.md +++ b/doc/raketasks/index.md @@ -29,6 +29,7 @@ The following Rake tasks are available for use with GitLab: | [Geo maintenance](../administration/raketasks/geo.md) | [Geo](../administration/geo/index.md)-related maintenance. | | [GitHub import](../administration/raketasks/github_import.md) | Retrieve and import repositories from GitHub. | | [Import large project exports](../development/import_project.md#importing-via-a-rake-task) | Import large GitLab [project exports](../user/project/settings/import_export.md). | +| [Incoming email](../administration/raketasks/incoming_email.md) | Incoming email-related tasks. | | [Integrity checks](../administration/raketasks/check.md) | Check the integrity of repositories, files, LDAP, and more. | | [LDAP maintenance](../administration/raketasks/ldap.md) | [LDAP](../administration/auth/ldap/index.md)-related tasks. | | [List repositories](list_repos.md) | List all GitLab-managed Git repositories on disk. | @@ -37,6 +38,7 @@ The following Rake tasks are available for use with GitLab: | [Project import/export](../administration/raketasks/project_import_export.md) | Prepare for [project exports and imports](../user/project/settings/import_export.md). | | [Sample Prometheus data](generate_sample_prometheus_data.md) | Generate sample Prometheus data. | | [Sidekiq job migration](../administration/sidekiq/sidekiq_job_migration.md) | Migrate Sidekiq jobs scheduled for future dates to a new queue. | +| [Service Desk email](../administration/raketasks/service_desk_email.md) | Service Desk email-related tasks. | | [SMTP maintenance](../administration/raketasks/smtp.md) | SMTP-related tasks. | | [SPDX license list import](spdx.md) | Import a local copy of the [SPDX license list](https://spdx.org/licenses/) for matching [License Compliance policies](../user/compliance/license_compliance/index.md). | | [Repository storage](../administration/raketasks/storage.md) | List and migrate existing projects and attachments from legacy storage to hashed storage. | diff --git a/doc/user/project/service_desk.md b/doc/user/project/service_desk.md index cbc64fe2368b25..3455ba0da35a16 100644 --- a/doc/user/project/service_desk.md +++ b/doc/user/project/service_desk.md @@ -260,6 +260,134 @@ service_desk_email: The configuration options are the same as for configuring [incoming email](../../administration/incoming_email.md#set-it-up). +#### Use encrypted credentials + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/108279) in GitLab 15.9. + +Instead of having the Service Desk email credentials stored in plaintext in the configuration files, you can optionally +use an encrypted file for the Incoming email credentials. + +Prerequisites: + +- To use encrypted credentials, you must first enable the + [encrypted configuration](../../administration/encrypted_configuration.md). + +The supported configuration items for the encrypted file are: + +- `user` +- `password` + +::Tabs + +:::TabTitle Linux package (Omnibus) + +1. If initially your LDAP configuration in `/etc/gitlab/gitlab.rb` looked like: + + ```ruby + gitlab_rails['service_desk_email_email'] = "service-desk-email@mail.example.com" + gitlab_rails['service_desk_email_password'] = "examplepassword" + ``` + +1. Edit the encrypted secret: + + ```shell + sudo gitlab-rake gitlab:service_desk_email:secret:edit EDITOR=vim + ``` + +1. Enter the unencrypted contents of the Service Desk email secret: + + ```yaml + user: 'service-desk-email@mail.example.com' + password: 'examplepassword' + ``` + +1. Edit `/etc/gitlab/gitlab.rb` and remove the `service_desk` settings for `email` and `password`. +1. Save the file and reconfigure GitLab: + + ```shell + sudo gitlab-ctl reconfigure + ``` + +:::TabTitle Helm chart (Kubernetes) + +Use a Kubernetes secret to store the Service Desk email password. For more information, +read about [Helm LDAP secrets](https://docs.gitlab.com/charts/installation/secrets.html#imap-password-for-service-desk-emails). + +:::TabTitle Docker + +1. If initially your LDAP configuration in `docker-compose.yml` looked like: + + ```yaml + version: "3.6" + services: + gitlab: + image: 'gitlab/gitlab-ee:latest' + restart: always + hostname: 'gitlab.example.com' + environment: + GITLAB_OMNIBUS_CONFIG: | + gitlab_rails['service_desk_email_email'] = "service-desk-email@mail.example.com" + gitlab_rails['service_desk_email_password'] = "examplepassword" + ``` + +1. Get inside the container, and edit the encrypted secret: + + ```shell + sudo docker exec -t bash + gitlab-rake gitlab:service_desk_email:secret:edit EDITOR=vim + ``` + +1. Enter the unencrypted contents of the LDAP secret: + + ```yaml + user: 'service-desk-email@mail.example.com' + password: 'examplepassword' + ``` + +1. Edit `docker-compose.yml` and remove the `service_desk` settings for `email` and `password`. +1. Save the file and restart GitLab: + + ```shell + docker compose up -d + ``` + +:::TabTitle Self-compiled (source) + +1. If initially your LDAP configuration in `/home/git/gitlab/config/gitlab.yml` looked like: + + ```yaml + production: + service_desk_email: + user: 'service-desk-email@mail.example.com' + password: 'examplepassword' + ``` + +1. Edit the encrypted secret: + + ```shell + bundle exec rake gitlab:service_desk_email:secret:edit EDITOR=vim RAILS_ENVIRONMENT=production + ``` + +1. Enter the unencrypted contents of the LDAP secret: + + ```yaml + user: 'service-desk-email@mail.example.com' + password: 'examplepassword' + ``` + +1. Edit `/home/git/gitlab/config/gitlab.yml` and remove the `service_desk_email:` settings for `user` and `password`. +1. Save the file and restart GitLab and Mailroom + + ```shell + # For systems running systemd + sudo systemctl restart gitlab.target + + # For systems running SysV init + sudo service gitlab restart + ``` + +::EndTabs + ##### Microsoft Graph > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214900) in GitLab 13.11. -- GitLab From daaf0807b2d455ee78c1c2070ef5d01ac71d79b2 Mon Sep 17 00:00:00 2001 From: Jason Young Date: Fri, 27 Jan 2023 10:15:20 -0500 Subject: [PATCH 05/14] Better isolate specs and test config parsing --- spec/lib/gitlab/mail_room/mail_room_spec.rb | 104 +++++++++++++++----- 1 file changed, 82 insertions(+), 22 deletions(-) diff --git a/spec/lib/gitlab/mail_room/mail_room_spec.rb b/spec/lib/gitlab/mail_room/mail_room_spec.rb index a93d29197e8748..7259b5e2484cc7 100644 --- a/spec/lib/gitlab/mail_room/mail_room_spec.rb +++ b/spec/lib/gitlab/mail_room/mail_room_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Gitlab::MailRoom do +RSpec.describe Gitlab::MailRoom, feature_category: :build do let(:default_port) { 143 } let(:log_path) { Rails.root.join('log', 'mail_room_json.log').to_s } @@ -36,12 +36,11 @@ let(:incoming_email_config) { yml_config.merge(custom_config) } let(:service_desk_email_config) { yml_config.merge(custom_config) } - let(:global_config) { {} } let(:configs) do - global_config.merge({ + { incoming_email: incoming_email_config, service_desk_email: service_desk_email_config - }) + } end before do @@ -331,26 +330,18 @@ end describe 'mailroom encrypted configuration' do - let(:mail_room_template) { ERB.new(File.read(Rails.root.join("./config/mail_room.yml"))).result } - let(:mail_room_yml) { YAML.safe_load(mail_room_template, permitted_classes: [Symbol]) } - let(:application_secrets_file) { Rails.root.join('spec/fixtures/mail_room/secrets.yml.erb').to_s } - - before do - allow(described_class).to receive(:application_secrets_file).and_return(application_secrets_file) - stub_env('KEY', 'an environment variable value') - described_class.instance_variable_set(:@application_secrets, nil) - end + context "when parsing secrets.yml" do + let(:application_secrets_file) { Rails.root.join('spec/fixtures/mail_room/secrets.yml.erb').to_s } + let(:encrypted_settings_key_base) { '0123456789abcdef' * 8 } - after do - described_class.instance_variable_set(:@application_secrets, nil) - end + before do + allow(described_class).to receive(:application_secrets_file).and_return(application_secrets_file) + stub_env('KEY', 'an environment variable value') + described_class.instance_variable_set(:@application_secrets, nil) + end - context 'when using encrypted secrets' do - let(:encrypted_settings_key_base) { '0123456789abcdef' * 8 } - let(:global_config) do - { - encrypted_settings: { path: 'spec/fixtures/mail_room/encrypted_secrets' } - } + after do + described_class.instance_variable_set(:@application_secrets, nil) end it 'reads in the secrets.yml file as erb and merges shared and test environments' do @@ -366,6 +357,75 @@ expect(application_secrets[:an_unread_key]).to be_nil end + end + + context "when parsing gitlab.yml" do + let(:plain_configs) { configs } + let(:shared_path_config) do + { shared: { path: '/this/is/my/shared_path' } }.merge(configs) + end + + let(:encrypted_settings_config) do + { + shared: { path: '/this/is/my/shared_path' }, + encrypted_settings: { path: '/this/is/my_custom_encrypted_path' } + }.merge(configs) + end + + let(:encrypted_file_config) do + configs.deep_merge({ + incoming_email: { encrypted_secret_file: '/custom_incoming_secret.yaml.enc' }, + service_desk_email: { encrypted_secret_file: '/custom_service_desk_secret.yaml.enc' } + }) + end + + it 'returns default encrypted_secret_file path' do + allow(described_class).to receive(:load_yaml).and_return(plain_configs) + + expect(described_class.send(:encrypted_secret_file, :incoming_email)) + .to end_with('shared/encrypted_settings/incoming_email.yaml.enc') + + expect(described_class.send(:encrypted_secret_file, :service_desk_email)) + .to end_with('shared/encrypted_settings/service_desk_email.yaml.enc') + end + + it 'returns encrypted_secret_file relative to custom shared path' do + allow(described_class).to receive(:load_yaml).and_return(shared_path_config) + + expect(described_class.send(:encrypted_secret_file, :incoming_email)) + .to eq('/this/is/my/shared_path/encrypted_settings/incoming_email.yaml.enc') + + expect(described_class.send(:encrypted_secret_file, :service_desk_email)) + .to eq('/this/is/my/shared_path/encrypted_settings/service_desk_email.yaml.enc') + end + + it 'returns custom encrypted_secret_file' do + allow(described_class).to receive(:load_yaml).and_return(encrypted_file_config) + + expect(described_class.send(:encrypted_secret_file, :incoming_email)) + .to eq('/custom_incoming_secret.yaml.enc') + + expect(described_class.send(:encrypted_secret_file, :service_desk_email)) + .to eq('/custom_service_desk_secret.yaml.enc') + end + end + + context 'when using encrypted secrets' do + let(:mail_room_template) { ERB.new(File.read(Rails.root.join("./config/mail_room.yml"))).result } + let(:mail_room_yml) { YAML.safe_load(mail_room_template, permitted_classes: [Symbol]) } + let(:application_secrets) { { encrypted_settings_key_base: '0123456789abcdef' * 8 } } # gitleaks:allow + let(:configs) do + { + encrypted_settings: { path: 'spec/fixtures/mail_room/encrypted_secrets' } + }.merge({ + incoming_email: incoming_email_config, + service_desk_email: service_desk_email_config + }) + end + + before do + allow(described_class).to receive(:application_secrets).and_return(application_secrets) + end it 'renders the encrypted secrets into the configuration correctly' do expect(mail_room_yml[:mailboxes]).to be_an(Array) -- GitLab From f6ac222f62794d93cbcbdd0a0a0d36a7054e04bb Mon Sep 17 00:00:00 2001 From: Jason Young Date: Fri, 27 Jan 2023 11:31:54 -0500 Subject: [PATCH 06/14] Allow env override of secrets path and avoid abbeviations Signed-off-by: Jason Young --- lib/gitlab/mail_room.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/gitlab/mail_room.rb b/lib/gitlab/mail_room.rb index 9ebcdf5610c704..5cf334c97363c5 100644 --- a/lib/gitlab/mail_room.rb +++ b/lib/gitlab/mail_room.rb @@ -133,7 +133,7 @@ def load_yaml end def application_secrets_file - File.expand_path('../../config/secrets.yml', __dir__) + ENV['MAIL_ROOM_GITLAB_SECRETS_FILE'] || File.expand_path('../../config/secrets.yml', __dir__) end def application_secrets @@ -181,8 +181,8 @@ def decrypted_secrets(config_key) settings = encrypted_configuration_settings(config_key) return if settings[:base_key].nil? - ec = Gitlab::EncryptedConfiguration.new(**settings) - ec.active? ? ec.config : nil + encrypted = Gitlab::EncryptedConfiguration.new(**settings) + encrypted.active? ? encrypted.config : nil end end end -- GitLab From be61a853ded42ed3c7f5e5c5026d1da6f6b10fc0 Mon Sep 17 00:00:00 2001 From: Jason Young Date: Fri, 27 Jan 2023 12:06:56 -0500 Subject: [PATCH 07/14] Add the EncryptedSecretsEnabledMetrics to usage_data.rb Signed-off-by: Jason Young --- lib/gitlab/usage_data.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/gitlab/usage_data.rb b/lib/gitlab/usage_data.rb index a163cf37d10343..858a42d77956a6 100644 --- a/lib/gitlab/usage_data.rb +++ b/lib/gitlab/usage_data.rb @@ -214,7 +214,9 @@ def system_usage_data_settings service_ping_features_enabled: add_metric('ServicePingFeaturesMetric', time_frame: 'none'), snowplow_enabled: add_metric('SnowplowEnabledMetric', time_frame: 'none'), snowplow_configured_to_gitlab_collector: add_metric('SnowplowConfiguredToGitlabCollectorMetric', time_frame: 'none'), - certificate_based_clusters_ff: add_metric('CertBasedClustersFfMetric') + certificate_based_clusters_ff: add_metric('CertBasedClustersFfMetric'), + incoming_email_encrypted_secrets_enabled: add_metric('IncomingEmailEncryptedSecretsEnabledMetric', time_frame: 'none'), + service_desk_email_encrypted_secrets_enabled: add_metric('ServiceDeskEmailEncryptedSecretsEnabledMetric', time_frame: 'none') } } end -- GitLab From f05d4558475506a0570e5a2bdd70ef8ff48e603a Mon Sep 17 00:00:00 2001 From: Jason Young Date: Fri, 27 Jan 2023 12:38:49 -0500 Subject: [PATCH 08/14] Fix documentation copy-paste errors Signed-off-by: Jason Young --- doc/user/project/service_desk.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/user/project/service_desk.md b/doc/user/project/service_desk.md index 3455ba0da35a16..fb63f0ca44bfda 100644 --- a/doc/user/project/service_desk.md +++ b/doc/user/project/service_desk.md @@ -311,11 +311,11 @@ The supported configuration items for the encrypted file are: :::TabTitle Helm chart (Kubernetes) Use a Kubernetes secret to store the Service Desk email password. For more information, -read about [Helm LDAP secrets](https://docs.gitlab.com/charts/installation/secrets.html#imap-password-for-service-desk-emails). +read about [Helm IMAP secrets](https://docs.gitlab.com/charts/installation/secrets.html#imap-password-for-service-desk-emails). :::TabTitle Docker -1. If initially your LDAP configuration in `docker-compose.yml` looked like: +1. If initially your Service Desk configuration in `docker-compose.yml` looked like: ```yaml version: "3.6" @@ -337,7 +337,7 @@ read about [Helm LDAP secrets](https://docs.gitlab.com/charts/installation/secre gitlab-rake gitlab:service_desk_email:secret:edit EDITOR=vim ``` -1. Enter the unencrypted contents of the LDAP secret: +1. Enter the unencrypted contents of the Service Desk secret: ```yaml user: 'service-desk-email@mail.example.com' @@ -353,7 +353,7 @@ read about [Helm LDAP secrets](https://docs.gitlab.com/charts/installation/secre :::TabTitle Self-compiled (source) -1. If initially your LDAP configuration in `/home/git/gitlab/config/gitlab.yml` looked like: +1. If initially your Service Desk configuration in `/home/git/gitlab/config/gitlab.yml` looked like: ```yaml production: @@ -368,7 +368,7 @@ read about [Helm LDAP secrets](https://docs.gitlab.com/charts/installation/secre bundle exec rake gitlab:service_desk_email:secret:edit EDITOR=vim RAILS_ENVIRONMENT=production ``` -1. Enter the unencrypted contents of the LDAP secret: +1. Enter the unencrypted contents of the Service Desk secret: ```yaml user: 'service-desk-email@mail.example.com' -- GitLab From 703d5b36b590a9aa6af3fa0ec480b86bc9bcc132 Mon Sep 17 00:00:00 2001 From: Jason Young Date: Fri, 27 Jan 2023 12:43:18 -0500 Subject: [PATCH 09/14] Missed another copy paste sentence Signed-off-by: Jason Young --- doc/user/project/service_desk.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/user/project/service_desk.md b/doc/user/project/service_desk.md index fb63f0ca44bfda..e2850a2bd1de48 100644 --- a/doc/user/project/service_desk.md +++ b/doc/user/project/service_desk.md @@ -281,7 +281,7 @@ The supported configuration items for the encrypted file are: :::TabTitle Linux package (Omnibus) -1. If initially your LDAP configuration in `/etc/gitlab/gitlab.rb` looked like: +1. If initially your Service Desk configuration in `/etc/gitlab/gitlab.rb` looked like: ```ruby gitlab_rails['service_desk_email_email'] = "service-desk-email@mail.example.com" -- GitLab From e40207c720d7d29d335fd2faf8747b1b66d9dfa5 Mon Sep 17 00:00:00 2001 From: DJ Mountney Date: Fri, 27 Jan 2023 19:09:36 +0000 Subject: [PATCH 10/14] Replace vim with editor in docker instructions --- doc/administration/incoming_email.md | 2 +- doc/administration/raketasks/incoming_email.md | 2 +- doc/administration/raketasks/service_desk_email.md | 2 +- doc/user/project/service_desk.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/administration/incoming_email.md b/doc/administration/incoming_email.md index d77bd1cdd6e8d1..ea051e2067df80 100644 --- a/doc/administration/incoming_email.md +++ b/doc/administration/incoming_email.md @@ -942,7 +942,7 @@ read about [Helm IMAP secrets](https://docs.gitlab.com/charts/installation/secre ```shell sudo docker exec -t bash - gitlab-rake gitlab:incoming_email:secret:edit EDITOR=vim + gitlab-rake gitlab:incoming_email:secret:edit EDITOR=editor ``` 1. Enter the unencrypted contents of the incoming email secret: diff --git a/doc/administration/raketasks/incoming_email.md b/doc/administration/raketasks/incoming_email.md index 622b0d0118af59..6b9c27ed144023 100644 --- a/doc/administration/raketasks/incoming_email.md +++ b/doc/administration/raketasks/incoming_email.md @@ -72,7 +72,7 @@ read about [Helm IMAP secrets](https://docs.gitlab.com/charts/installation/secre :::TabTitle Docker ```shell -sudo docker exec -t gitlab:incoming_email:secret:edit EDITOR=vim +sudo docker exec -t gitlab:incoming_email:secret:edit EDITOR=editor ``` :::TabTitle Self-compiled (source) diff --git a/doc/administration/raketasks/service_desk_email.md b/doc/administration/raketasks/service_desk_email.md index a263db2cbd128a..10de379b1cddb7 100644 --- a/doc/administration/raketasks/service_desk_email.md +++ b/doc/administration/raketasks/service_desk_email.md @@ -72,7 +72,7 @@ read about [Helm IMAP secrets](https://docs.gitlab.com/charts/installation/secre :::TabTitle Docker ```shell -sudo docker exec -t gitlab:service_desk_email:secret:edit EDITOR=vim +sudo docker exec -t gitlab:service_desk_email:secret:edit EDITOR=editor ``` :::TabTitle Self-compiled (source) diff --git a/doc/user/project/service_desk.md b/doc/user/project/service_desk.md index e2850a2bd1de48..b0dcc26dfb3291 100644 --- a/doc/user/project/service_desk.md +++ b/doc/user/project/service_desk.md @@ -334,7 +334,7 @@ read about [Helm IMAP secrets](https://docs.gitlab.com/charts/installation/secre ```shell sudo docker exec -t bash - gitlab-rake gitlab:service_desk_email:secret:edit EDITOR=vim + gitlab-rake gitlab:service_desk_email:secret:edit EDITOR=editor ``` 1. Enter the unencrypted contents of the Service Desk secret: -- GitLab From 07898274a5b84f172baf238591cedfc2a9bf6654 Mon Sep 17 00:00:00 2001 From: Jason Young Date: Fri, 27 Jan 2023 14:41:05 -0500 Subject: [PATCH 11/14] Fix header level for Service Desk encrypted settings Signed-off-by: Jason Young --- doc/user/project/service_desk.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/user/project/service_desk.md b/doc/user/project/service_desk.md index b0dcc26dfb3291..732450f54433d8 100644 --- a/doc/user/project/service_desk.md +++ b/doc/user/project/service_desk.md @@ -260,7 +260,7 @@ service_desk_email: The configuration options are the same as for configuring [incoming email](../../administration/incoming_email.md#set-it-up). -#### Use encrypted credentials +##### Use encrypted credentials > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/108279) in GitLab 15.9. -- GitLab From c18092b6c7613f8f25256049a74ff05e7bc566f3 Mon Sep 17 00:00:00 2001 From: Jason Young Date: Mon, 30 Jan 2023 15:19:36 -0500 Subject: [PATCH 12/14] Remove metrics from usage_data Signed-off-by: Jason Young --- lib/gitlab/usage_data.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/gitlab/usage_data.rb b/lib/gitlab/usage_data.rb index 858a42d77956a6..a163cf37d10343 100644 --- a/lib/gitlab/usage_data.rb +++ b/lib/gitlab/usage_data.rb @@ -214,9 +214,7 @@ def system_usage_data_settings service_ping_features_enabled: add_metric('ServicePingFeaturesMetric', time_frame: 'none'), snowplow_enabled: add_metric('SnowplowEnabledMetric', time_frame: 'none'), snowplow_configured_to_gitlab_collector: add_metric('SnowplowConfiguredToGitlabCollectorMetric', time_frame: 'none'), - certificate_based_clusters_ff: add_metric('CertBasedClustersFfMetric'), - incoming_email_encrypted_secrets_enabled: add_metric('IncomingEmailEncryptedSecretsEnabledMetric', time_frame: 'none'), - service_desk_email_encrypted_secrets_enabled: add_metric('ServiceDeskEmailEncryptedSecretsEnabledMetric', time_frame: 'none') + certificate_based_clusters_ff: add_metric('CertBasedClustersFfMetric') } } end -- GitLab From be54845ed28e905e28ff760ec5c6036dcc4b18c2 Mon Sep 17 00:00:00 2001 From: Quang-Minh Nguyen Date: Tue, 31 Jan 2023 15:10:34 +0000 Subject: [PATCH 13/14] Fix comment and add explicit return to application_secrets --- lib/gitlab/mail_room.rb | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/lib/gitlab/mail_room.rb b/lib/gitlab/mail_room.rb index 5cf334c97363c5..9ba9170982c9a3 100644 --- a/lib/gitlab/mail_room.rb +++ b/lib/gitlab/mail_room.rb @@ -45,7 +45,7 @@ module MailRoom } }.freeze - # default path strings ( this is a data duplication + # Default path strings (this is a data duplication # with Settings which is not pulled in - see the service # comment at the top of this file) DEFAULT_PATHS = { @@ -137,16 +137,15 @@ def application_secrets_file end def application_secrets - return @application_secrets if @application_secrets - - @application_secrets = {} - # Uses Rails::Secret.parse - # from: https://github.com/rails/rails/blob/v6.1.6.1/railties/lib/rails/secrets.rb#L24 - erb_processed_yaml = ERB.new(File.read(application_secrets_file)).result - yaml_secrets = - YAML.respond_to?(:unsafe_load) ? YAML.unsafe_load(erb_processed_yaml) : YAML.safe_load(erb_processed_yaml) - @application_secrets.merge!(yaml_secrets["shared"].deep_symbolize_keys) if yaml_secrets["shared"] - @application_secrets.merge!(yaml_secrets[rails_env].deep_symbolize_keys) if yaml_secrets[rails_env] + @application_secrets ||= {}.tap do |application_secrets| + # Uses Rails::Secret.parse + # from: https://github.com/rails/rails/blob/v6.1.6.1/railties/lib/rails/secrets.rb#L24 + erb_processed_yaml = ERB.new(File.read(application_secrets_file)).result + yaml_secrets = + YAML.respond_to?(:unsafe_load) ? YAML.unsafe_load(erb_processed_yaml) : YAML.safe_load(erb_processed_yaml) + application_secrets.merge!(yaml_secrets["shared"].deep_symbolize_keys) if yaml_secrets["shared"] + application_secrets.merge!(yaml_secrets[rails_env].deep_symbolize_keys) if yaml_secrets[rails_env] + end end def default_encrypted_secret_filename(config_key) -- GitLab From 7052d9bbdf0a4440365dfd02fe8f26622dfb3304 Mon Sep 17 00:00:00 2001 From: Jason Young Date: Tue, 31 Jan 2023 12:03:13 -0500 Subject: [PATCH 14/14] Fix identation Signed-off-by: Jason Young --- lib/gitlab/mail_room.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/gitlab/mail_room.rb b/lib/gitlab/mail_room.rb index 9ba9170982c9a3..bad2e265f73a49 100644 --- a/lib/gitlab/mail_room.rb +++ b/lib/gitlab/mail_room.rb @@ -145,7 +145,7 @@ def application_secrets YAML.respond_to?(:unsafe_load) ? YAML.unsafe_load(erb_processed_yaml) : YAML.safe_load(erb_processed_yaml) application_secrets.merge!(yaml_secrets["shared"].deep_symbolize_keys) if yaml_secrets["shared"] application_secrets.merge!(yaml_secrets[rails_env].deep_symbolize_keys) if yaml_secrets[rails_env] - end + end end def default_encrypted_secret_filename(config_key) -- GitLab