# HG changeset patch # User Balasankar 'Balu' C <balasankar@gitlab.com> # Date 1701294444 0 # Wed Nov 29 21:47:24 2023 +0000 # Node ID a978e3430da0cf17ca889776cee3c3b306c087c7 # Parent f15c34848a31670455a8f82e7814f374ee8cebeb Support specifying encrypted secrets path for Redis Closes https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/6275 Changelog: added Signed-off-by: Balasankar "Balu" C <balasankar@gitlab.com> diff --git a/files/gitlab-cookbooks/gitlab/attributes/default.rb b/files/gitlab-cookbooks/gitlab/attributes/default.rb --- a/files/gitlab-cookbooks/gitlab/attributes/default.rb +++ b/files/gitlab-cookbooks/gitlab/attributes/default.rb @@ -446,6 +446,7 @@ default['gitlab']['gitlab_rails']['redis_tls_client_cert_file'] = nil default['gitlab']['gitlab_rails']['redis_tls_client_key_file'] = nil default['gitlab']['gitlab_rails']['redis_password'] = nil +default['gitlab']['gitlab_rails']['redis_encrypted_settings_file'] = nil default['gitlab']['gitlab_rails']['redis_socket'] = "/var/opt/gitlab/redis/redis.socket" default['gitlab']['gitlab_rails']['redis_enable_client'] = true default['gitlab']['gitlab_rails']['redis_sentinels'] = [] @@ -455,6 +456,7 @@ default['gitlab']['gitlab_rails']['redis_cache_sentinels_password'] = nil default['gitlab']['gitlab_rails']['redis_cache_username'] = nil default['gitlab']['gitlab_rails']['redis_cache_password'] = nil +default['gitlab']['gitlab_rails']['redis_cache_encrypted_settings_file'] = nil default['gitlab']['gitlab_rails']['redis_cache_cluster_nodes'] = [] default['gitlab']['gitlab_rails']['redis_cache_ssl'] = false default['gitlab']['gitlab_rails']['redis_cache_tls_ca_cert_dir'] = default['gitlab']['gitlab_rails']['redis_tls_ca_cert_dir'].dup @@ -464,6 +466,7 @@ default['gitlab']['gitlab_rails']['redis_queues_instance'] = nil default['gitlab']['gitlab_rails']['redis_queues_username'] = nil default['gitlab']['gitlab_rails']['redis_queues_password'] = nil +default['gitlab']['gitlab_rails']['redis_queues_encrypted_settings_file'] = nil default['gitlab']['gitlab_rails']['redis_queues_sentinels'] = [] default['gitlab']['gitlab_rails']['redis_queues_sentinels_password'] = nil default['gitlab']['gitlab_rails']['redis_queues_cluster_nodes'] = [] @@ -477,6 +480,7 @@ default['gitlab']['gitlab_rails']['redis_shared_state_sentinels_password'] = nil default['gitlab']['gitlab_rails']['redis_shared_state_username'] = nil default['gitlab']['gitlab_rails']['redis_shared_state_password'] = nil +default['gitlab']['gitlab_rails']['redis_shared_state_encrypted_settings_file'] = nil default['gitlab']['gitlab_rails']['redis_shared_state_cluster_nodes'] = [] default['gitlab']['gitlab_rails']['redis_shared_state_ssl'] = false default['gitlab']['gitlab_rails']['redis_shared_state_tls_ca_cert_dir'] = default['gitlab']['gitlab_rails']['redis_tls_ca_cert_dir'].dup @@ -488,6 +492,7 @@ default['gitlab']['gitlab_rails']['redis_trace_chunks_sentinels_password'] = nil default['gitlab']['gitlab_rails']['redis_trace_chunks_username'] = nil default['gitlab']['gitlab_rails']['redis_trace_chunks_password'] = nil +default['gitlab']['gitlab_rails']['redis_trace_chunks_encrypted_settings_file'] = nil default['gitlab']['gitlab_rails']['redis_trace_chunks_cluster_nodes'] = [] default['gitlab']['gitlab_rails']['redis_trace_chunks_ssl'] = false default['gitlab']['gitlab_rails']['redis_trace_chunks_tls_ca_cert_dir'] = default['gitlab']['gitlab_rails']['redis_tls_ca_cert_dir'].dup @@ -499,6 +504,7 @@ default['gitlab']['gitlab_rails']['redis_actioncable_sentinels_password'] = nil default['gitlab']['gitlab_rails']['redis_actioncable_username'] = nil default['gitlab']['gitlab_rails']['redis_actioncable_password'] = nil +default['gitlab']['gitlab_rails']['redis_actioncable_encrypted_settings_file'] = nil default['gitlab']['gitlab_rails']['redis_actioncable_cluster_nodes'] = [] default['gitlab']['gitlab_rails']['redis_actioncable_ssl'] = false default['gitlab']['gitlab_rails']['redis_actioncable_tls_ca_cert_dir'] = default['gitlab']['gitlab_rails']['redis_tls_ca_cert_dir'].dup @@ -510,6 +516,7 @@ default['gitlab']['gitlab_rails']['redis_rate_limiting_sentinels_password'] = nil default['gitlab']['gitlab_rails']['redis_rate_limiting_username'] = nil default['gitlab']['gitlab_rails']['redis_rate_limiting_password'] = nil +default['gitlab']['gitlab_rails']['redis_rate_limiting_encrypted_settings_file'] = nil default['gitlab']['gitlab_rails']['redis_rate_limiting_cluster_nodes'] = [] default['gitlab']['gitlab_rails']['redis_rate_limiting_ssl'] = false default['gitlab']['gitlab_rails']['redis_rate_limiting_tls_ca_cert_dir'] = default['gitlab']['gitlab_rails']['redis_tls_ca_cert_dir'].dup @@ -521,6 +528,7 @@ default['gitlab']['gitlab_rails']['redis_sessions_sentinels_password'] = nil default['gitlab']['gitlab_rails']['redis_sessions_username'] = nil default['gitlab']['gitlab_rails']['redis_sessions_password'] = nil +default['gitlab']['gitlab_rails']['redis_sessions_encrypted_settings_file'] = nil default['gitlab']['gitlab_rails']['redis_sessions_cluster_nodes'] = [] default['gitlab']['gitlab_rails']['redis_sessions_ssl'] = false default['gitlab']['gitlab_rails']['redis_sessions_tls_ca_cert_dir'] = default['gitlab']['gitlab_rails']['redis_tls_ca_cert_dir'].dup @@ -532,6 +540,7 @@ default['gitlab']['gitlab_rails']['redis_repository_cache_sentinels_password'] = nil default['gitlab']['gitlab_rails']['redis_repository_cache_username'] = nil default['gitlab']['gitlab_rails']['redis_repository_cache_password'] = nil +default['gitlab']['gitlab_rails']['redis_repository_cache_encrypted_settings_file'] = nil default['gitlab']['gitlab_rails']['redis_repository_cache_cluster_nodes'] = [] default['gitlab']['gitlab_rails']['redis_repository_cache_ssl'] = false default['gitlab']['gitlab_rails']['redis_repository_cache_tls_ca_cert_dir'] = default['gitlab']['gitlab_rails']['redis_tls_ca_cert_dir'].dup @@ -543,6 +552,7 @@ default['gitlab']['gitlab_rails']['redis_cluster_rate_limiting_sentinels_password'] = nil default['gitlab']['gitlab_rails']['redis_cluster_rate_limiting_username'] = nil default['gitlab']['gitlab_rails']['redis_cluster_rate_limiting_password'] = nil +default['gitlab']['gitlab_rails']['redis_cluster_rate_limiting_encrypted_settings_file'] = nil default['gitlab']['gitlab_rails']['redis_cluster_rate_limiting_cluster_nodes'] = [] default['gitlab']['gitlab_rails']['redis_cluster_rate_limiting_ssl'] = false default['gitlab']['gitlab_rails']['redis_cluster_rate_limiting_tls_ca_cert_dir'] = default['gitlab']['gitlab_rails']['redis_tls_ca_cert_dir'].dup diff --git a/files/gitlab-cookbooks/gitlab/libraries/gitlab_rails.rb b/files/gitlab-cookbooks/gitlab/libraries/gitlab_rails.rb --- a/files/gitlab-cookbooks/gitlab/libraries/gitlab_rails.rb +++ b/files/gitlab-cookbooks/gitlab/libraries/gitlab_rails.rb @@ -17,6 +17,7 @@ require_relative 'nginx.rb' require_relative '../../gitaly/libraries/gitaly.rb' require_relative '../../package/libraries/settings_dsl.rb' +require_relative 'redis_helper' module GitlabRails ALLOWED_DATABASES = %w[main ci geo embedding].freeze @@ -323,7 +324,16 @@ def parse_encrypted_settings_path # This requires the parse_shared_dir to be executed before - Gitlab['gitlab_rails']['encrypted_settings_path'] ||= File.join(Gitlab['gitlab_rails']['shared_path'], 'encrypted_settings') + encrypted_settings_path = Gitlab['gitlab_rails']['encrypted_settings_path'] ||= File.join(Gitlab['gitlab_rails']['shared_path'], 'encrypted_settings') + + RedisHelper::REDIS_INSTANCES.each do |instance| + Gitlab['gitlab_rails']["redis_#{instance}_encrypted_settings_file"] ||= Gitlab['gitlab_rails']['redis_encrypted_settings_file'] || File.join(encrypted_settings_path, "redis.#{instance}.yml.enc") + end + + # NOTE: The default value of `redis_encrypted_settings_file` should be + # set only after the instance-specific ones are handled, or this default + # value will get used for the instance-specific settings. + Gitlab['gitlab_rails']['redis_encrypted_settings_file'] ||= File.join(encrypted_settings_path, 'redis.yml.enc') end def parse_pages_dir diff --git a/files/gitlab-cookbooks/gitlab/recipes/gitlab-rails.rb b/files/gitlab-cookbooks/gitlab/recipes/gitlab-rails.rb --- a/files/gitlab-cookbooks/gitlab/recipes/gitlab-rails.rb +++ b/files/gitlab-cookbooks/gitlab/recipes/gitlab-rails.rb @@ -217,6 +217,7 @@ redis_tls_ca_cert_file = node['gitlab']['gitlab_rails']['redis_tls_ca_cert_file'] redis_tls_client_cert_file = node['gitlab']['gitlab_rails']['redis_tls_client_cert_file'] redis_tls_client_key_file = node['gitlab']['gitlab_rails']['redis_tls_client_key_file'] +redis_encrypted_settings_file = node['gitlab']['gitlab_rails']['redis_encrypted_settings_file'] templatesymlink "Create a secrets.yml and create a symlink to Rails root" do link_from File.join(gitlab_rails_source_dir, "config/secrets.yml") @@ -253,7 +254,8 @@ redis_tls_ca_cert_dir: redis_tls_ca_cert_dir, redis_tls_ca_cert_file: redis_tls_ca_cert_file, redis_tls_client_cert_file: redis_tls_client_cert_file, - redis_tls_client_key_file: redis_tls_client_key_file + redis_tls_client_key_file: redis_tls_client_key_file, + redis_encrypted_settings_file: redis_encrypted_settings_file ) dependent_services.each { |svc| notifies :restart, svc } sensitive true @@ -305,6 +307,7 @@ ca_cert_file = node['gitlab']['gitlab_rails']["redis_#{instance}_tls_ca_cert_file"] certificate_file = node['gitlab']['gitlab_rails']["redis_#{instance}_tls_client_cert_file"] key_file = node['gitlab']['gitlab_rails']["redis_#{instance}_tls_client_key_file"] + instance_encrypted_settings_file = node['gitlab']['gitlab_rails']["redis_#{instance}_encrypted_settings_file"] from_filename = File.join(gitlab_rails_source_dir, "config/#{filename}") to_filename = File.join(gitlab_rails_etc_dir, filename) @@ -329,7 +332,8 @@ redis_tls_ca_cert_dir: ca_cert_dir, redis_tls_ca_cert_file: ca_cert_file, redis_tls_client_cert_file: certificate_file, - redis_tls_client_key_file: key_file + redis_tls_client_key_file: key_file, + redis_encrypted_settings_file: instance_encrypted_settings_file ) dependent_services.each { |svc| notifies :restart, svc } action :delete if url.nil? && clusters.empty? diff --git a/files/gitlab-cookbooks/gitlab/templates/default/resque.yml.erb b/files/gitlab-cookbooks/gitlab/templates/default/resque.yml.erb --- a/files/gitlab-cookbooks/gitlab/templates/default/resque.yml.erb +++ b/files/gitlab-cookbooks/gitlab/templates/default/resque.yml.erb @@ -13,6 +13,7 @@ <% end %> <% else %> url: <%= @redis_url %> + secret_file: <%= @redis_encrypted_settings_file %> <%- if @redis_ssl %> ssl_params: <%- if @redis_tls_ca_cert_dir %>ca_path: "<%= @redis_tls_ca_cert_dir %>"<% end %> diff --git a/spec/chef/cookbooks/gitlab/recipes/gitlab-rails_spec.rb b/spec/chef/cookbooks/gitlab/recipes/gitlab-rails_spec.rb --- a/spec/chef/cookbooks/gitlab/recipes/gitlab-rails_spec.rb +++ b/spec/chef/cookbooks/gitlab/recipes/gitlab-rails_spec.rb @@ -440,7 +440,8 @@ redis_tls_ca_cert_dir: "/opt/gitlab/embedded/ssl/certs/", redis_tls_ca_cert_file: "/opt/gitlab/embedded/ssl/certs/cacert.pem", redis_tls_client_cert_file: nil, - redis_tls_client_key_file: nil + redis_tls_client_key_file: nil, + redis_encrypted_settings_file: "/var/opt/gitlab/gitlab-rails/shared/encrypted_settings/redis.#{instance}.yml.enc" ) expect(chef_run).to render_file("/var/opt/gitlab/gitlab-rails/etc/redis.#{instance}.yml").with_content { |content| @@ -482,7 +483,8 @@ redis_tls_ca_cert_dir: "/opt/gitlab/embedded/ssl/certs/", redis_tls_ca_cert_file: "/opt/gitlab/embedded/ssl/certs/cacert.pem", redis_tls_client_cert_file: nil, - redis_tls_client_key_file: nil + redis_tls_client_key_file: nil, + redis_encrypted_settings_file: "/var/opt/gitlab/gitlab-rails/shared/encrypted_settings/redis.#{instance}.yml.enc" ) expect(chef_run).to render_file("/var/opt/gitlab/gitlab-rails/etc/redis.#{instance}.yml").with_content { |content| @@ -524,7 +526,8 @@ redis_tls_ca_cert_dir: "/opt/gitlab/embedded/ssl/certs/", redis_tls_ca_cert_file: "/opt/gitlab/embedded/ssl/certs/cacert.pem", redis_tls_client_cert_file: nil, - redis_tls_client_key_file: nil + redis_tls_client_key_file: nil, + redis_encrypted_settings_file: "/var/opt/gitlab/gitlab-rails/shared/encrypted_settings/redis.#{instance}.yml.enc" ) expect(chef_run).to render_file("/var/opt/gitlab/gitlab-rails/etc/redis.#{instance}.yml").with_content { |content| @@ -545,6 +548,42 @@ expect(chef_run).to create_templatesymlink('Create a resque.yml and create a symlink to Rails root') end end + + describe 'encrypted_settings_file' do + cached(:chef_run) do + ChefSpec::SoloRunner.new(step_into: %w(templatesymlink)).converge('gitlab::default') + end + + let(:cache_secret_file) { '/etc/gitlab/cache.redis.enc' } + let(:global_secret_file) { '/etc/gitlab/global.redis.enc' } + + context 'with separate file for an instance' do + before do + stub_gitlab_rb( + gitlab_rails: { + redis_encrypted_settings_file: global_secret_file, + redis_cache_instance: 'redis://redis.cache.instance', + redis_cache_encrypted_settings_file: cache_secret_file, + redis_shared_state_instance: 'redis://redis.shared_state.instance' + } + ) + end + + it 'uses specified path for the cache instance' do + expect(chef_run).to render_file("/var/opt/gitlab/gitlab-rails/etc/redis.cache.yml").with_content { |content| + generated_yml = YAML.safe_load(content) + expect(generated_yml.dig('production', 'secret_file')).to eq(cache_secret_file) + } + end + + it 'uses global path for the shared state instance' do + expect(chef_run).to render_file("/var/opt/gitlab/gitlab-rails/etc/redis.shared_state.yml").with_content { |content| + generated_yml = YAML.safe_load(content) + expect(generated_yml.dig('production', 'secret_file')).to eq(global_secret_file) + } + end + end + end end context 'redis.yml override' do