diff --git a/changelogs/unreleased/4478-provide-an-option-to-disable-certain-risky-redis-commands.yml b/changelogs/unreleased/4478-provide-an-option-to-disable-certain-risky-redis-commands.yml new file mode 100644 index 0000000000000000000000000000000000000000..dd97e1dc92a5aa846cc42e032fd636aff2faf049_Y2hhbmdlbG9ncy91bnJlbGVhc2VkLzQ0NzgtcHJvdmlkZS1hbi1vcHRpb24tdG8tZGlzYWJsZS1jZXJ0YWluLXJpc2t5LXJlZGlzLWNvbW1hbmRzLnltbA== --- /dev/null +++ b/changelogs/unreleased/4478-provide-an-option-to-disable-certain-risky-redis-commands.yml @@ -0,0 +1,5 @@ +--- +title: Rename unused redis commands by default +merge_request: 3436 +author: +type: security diff --git a/doc/settings/redis.md b/doc/settings/redis.md index 47c3fd31dc42a84f4dd059f486d424af76c696f3_ZG9jL3NldHRpbmdzL3JlZGlzLm1k..dd97e1dc92a5aa846cc42e032fd636aff2faf049_ZG9jL3NldHRpbmdzL3JlZGlzLm1k 100644 --- a/doc/settings/redis.md +++ b/doc/settings/redis.md @@ -157,6 +157,28 @@ Redis connection using [stunnel](https://redislabs.com/blog/stunnel-secure-redis-ssl/). AWS ElasticCache also supports Redis over SSL. +## Renamed commands + +By default, the `KEYS` command is disabled as a security measure. + +If you'd like to obfuscate or disable this command, or other commands, edit the `redis['rename_commands']` setting in `/etc/gitlab/gitlab.rb` to look like: +```ruby +redis['rename_commands'] = { + 'KEYS': '', + 'OTHER_COMMAND': 'VALUE' +} +``` + +* `OTHER_COMMAND` is the command you want to modify +* `VALUE` should be one of: + 1. A new command name. + 1. '', which completely disables the command + +To disable this functionality: + +1. Set `redis['rename_commands'] = {}` in your `/etc/gitlab/gitlab.rb` file +1. Run `sudo gitlab-ctl reconfigure` + ### Limitations - GitLab does NOT ship with stunnel or other tools to provide encryption diff --git a/files/gitlab-config-template/gitlab.rb.template b/files/gitlab-config-template/gitlab.rb.template index 47c3fd31dc42a84f4dd059f486d424af76c696f3_ZmlsZXMvZ2l0bGFiLWNvbmZpZy10ZW1wbGF0ZS9naXRsYWIucmIudGVtcGxhdGU=..dd97e1dc92a5aa846cc42e032fd636aff2faf049_ZmlsZXMvZ2l0bGFiLWNvbmZpZy10ZW1wbGF0ZS9naXRsYWIucmIudGVtcGxhdGU= 100644 --- a/files/gitlab-config-template/gitlab.rb.template +++ b/files/gitlab-config-template/gitlab.rb.template @@ -929,6 +929,16 @@ # redis['uid'] = nil # redis['gid'] = nil +### Disable or obfuscate unnecessary redis command names +### Uncomment and edit this block to add or remove entries. +### See https://docs.gitlab.com/omnibus/settings/redis.html#renamed-commands +### for detailed usage +### +# redis['rename_commands'] = { +# 'KEYS': '' +#} +# + ###! **To enable only Redis service in this machine, uncomment ###! one of the lines below (choose master or slave instance types).** ###! Docs: https://docs.gitlab.com/omnibus/settings/redis.html diff --git a/files/gitlab-cookbooks/gitlab/libraries/redis.rb b/files/gitlab-cookbooks/gitlab/libraries/redis.rb index 47c3fd31dc42a84f4dd059f486d424af76c696f3_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRsYWIvbGlicmFyaWVzL3JlZGlzLnJi..dd97e1dc92a5aa846cc42e032fd636aff2faf049_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRsYWIvbGlicmFyaWVzL3JlZGlzLnJi 100644 --- a/files/gitlab-cookbooks/gitlab/libraries/redis.rb +++ b/files/gitlab-cookbooks/gitlab/libraries/redis.rb @@ -46,6 +46,10 @@ Gitlab['redis']['master_password'] ||= Gitlab['redis']['password'] end + Gitlab['redis']['rename_commands'] ||= { + 'KEYS' => '' + } + return unless RedisHelper::Checks.sentinel_daemon_enabled? || RedisHelper::Checks.is_redis_slave? raise "redis 'master_ip' is not defined" unless Gitlab['redis']['master_ip'] diff --git a/files/gitlab-cookbooks/redis/attributes/attributes.rb b/files/gitlab-cookbooks/redis/attributes/attributes.rb index 47c3fd31dc42a84f4dd059f486d424af76c696f3_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9yZWRpcy9hdHRyaWJ1dGVzL2F0dHJpYnV0ZXMucmI=..dd97e1dc92a5aa846cc42e032fd636aff2faf049_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9yZWRpcy9hdHRyaWJ1dGVzL2F0dHJpYnV0ZXMucmI= 100644 --- a/files/gitlab-cookbooks/redis/attributes/attributes.rb +++ b/files/gitlab-cookbooks/redis/attributes/attributes.rb @@ -34,6 +34,8 @@ default['redis']['client_output_buffer_limit_pubsub'] = "32mb 8mb 60" default['redis']['save'] = ['900 1', '300 10', '60 10000'] +default['redis']['rename_commands'] = nil + #### # Redis Settings for EE # They are no-op in CE diff --git a/files/gitlab-cookbooks/redis/templates/default/redis.conf.erb b/files/gitlab-cookbooks/redis/templates/default/redis.conf.erb index 47c3fd31dc42a84f4dd059f486d424af76c696f3_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9yZWRpcy90ZW1wbGF0ZXMvZGVmYXVsdC9yZWRpcy5jb25mLmVyYg==..dd97e1dc92a5aa846cc42e032fd636aff2faf049_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9yZWRpcy90ZW1wbGF0ZXMvZGVmYXVsdC9yZWRpcy5jb25mLmVyYg== 100644 --- a/files/gitlab-cookbooks/redis/templates/default/redis.conf.erb +++ b/files/gitlab-cookbooks/redis/templates/default/redis.conf.erb @@ -509,7 +509,11 @@ # # Please note that changing the name of commands that are logged into the # AOF file or transmitted to slaves may cause problems. - +<% if @rename_commands %> + <% @rename_commands.each_pair do |command, newname| %> +rename-command <%= command %> "<%= newname %>" + <% end %> +<% end %> ################################### LIMITS #################################### # Set the max number of connected clients at the same time. By default diff --git a/spec/chef/redis/redis_spec.rb b/spec/chef/redis/redis_spec.rb index 47c3fd31dc42a84f4dd059f486d424af76c696f3_c3BlYy9jaGVmL3JlZGlzL3JlZGlzX3NwZWMucmI=..dd97e1dc92a5aa846cc42e032fd636aff2faf049_c3BlYy9jaGVmL3JlZGlzL3JlZGlzX3NwZWMucmI= 100644 --- a/spec/chef/redis/redis_spec.rb +++ b/spec/chef/redis/redis_spec.rb @@ -10,29 +10,21 @@ context 'by default' do it 'creates redis config with default values' do expect(chef_run).to render_file('/var/opt/gitlab/redis/redis.conf') - .with_content(/client-output-buffer-limit normal 0 0 0/) - expect(chef_run).to render_file('/var/opt/gitlab/redis/redis.conf') - .with_content(/client-output-buffer-limit slave 256mb 64mb 60/) - expect(chef_run).to render_file('/var/opt/gitlab/redis/redis.conf') - .with_content(/client-output-buffer-limit pubsub 32mb 8mb 60/) - expect(chef_run).to render_file('/var/opt/gitlab/redis/redis.conf') - .with_content(/^hz 10/) - expect(chef_run).to render_file('/var/opt/gitlab/redis/redis.conf') - .with_content(/^save 900 1/) - expect(chef_run).to render_file('/var/opt/gitlab/redis/redis.conf') - .with_content(/^save 300 10/) - expect(chef_run).to render_file('/var/opt/gitlab/redis/redis.conf') - .with_content(/^save 60 10000/) - expect(chef_run).to render_file('/var/opt/gitlab/redis/redis.conf') - .with_content(/^maxmemory 0/) - expect(chef_run).to render_file('/var/opt/gitlab/redis/redis.conf') - .with_content(/^maxmemory-policy noeviction/) - expect(chef_run).to render_file('/var/opt/gitlab/redis/redis.conf') - .with_content(/^maxmemory-samples 5/) - expect(chef_run).to render_file('/var/opt/gitlab/redis/redis.conf') - .with_content(/^tcp-backlog 511/) - expect(chef_run).not_to render_file('/var/opt/gitlab/redis/redis.conf') - .with_content(/^slaveof/) + .with_content { |content| + expect(content).to match(/client-output-buffer-limit normal 0 0 0/) + expect(content).to match(/client-output-buffer-limit slave 256mb 64mb 60/) + expect(content).to match(/client-output-buffer-limit pubsub 32mb 8mb 60/) + expect(content).to match(/^hz 10/) + expect(content).to match(/^save 900 1/) + expect(content).to match(/^save 300 10/) + expect(content).to match(/^save 60 10000/) + expect(content).to match(/^maxmemory 0/) + expect(content).to match(/^maxmemory-policy noeviction/) + expect(content).to match(/^maxmemory-samples 5/) + expect(content).to match(/^tcp-backlog 511/) + expect(content).to match(/^rename-command KEYS ""$/) + expect(content).not_to match(/^slaveof/) + } end it 'creates redis user and group' do @@ -56,7 +48,11 @@ tcp_backlog: 1024, hz: 100, username: 'foo', - group: 'bar' + group: 'bar', + rename_commands: { + "FAKE_COMMAND" => "RENAMED_FAKE_COMMAND", + "DISABLED_FAKE_COMMAND" => "" + } } ) end @@ -82,6 +78,15 @@ .with_content(/^hz 100/) end + it 'does not include the default renamed keys in redis.conf' do + expect(chef_run).to render_file('/var/opt/gitlab/redis/redis.conf') + .with_content { |content| + expect(content).not_to match(/^rename-command KEYS ""$/) + expect(content).to match(/^rename-command FAKE_COMMAND "RENAMED_FAKE_COMMAND"$/) + expect(content).to match(/^rename-command DISABLED_FAKE_COMMAND ""$/) + } + end + it 'creates redis user and group' do expect(chef_run).to create_account('user and group for redis').with(username: 'foo', groupname: 'bar') end @@ -169,6 +174,23 @@ end end + context 'with rename_commands disabled' do + before do + stub_gitlab_rb( + redis: { + rename_commands: {} + } + ) + end + + it 'should not rename any commands' do + expect(chef_run).to render_file('/var/opt/gitlab/redis/redis.conf') + .with_content { |content| + expect(content).not_to match(/^rename-command/) + } + end + end + context 'with redis disabled' do before do stub_gitlab_rb(redis: { enable: false })