diff --git a/files/gitlab-config-template/gitlab.rb.template b/files/gitlab-config-template/gitlab.rb.template index db8b43c93038a5c7fd29aac666c9e50a50e57fbc_ZmlsZXMvZ2l0bGFiLWNvbmZpZy10ZW1wbGF0ZS9naXRsYWIucmIudGVtcGxhdGU=..f67e6a508af155548a72d71a27f3820c6092150f_ZmlsZXMvZ2l0bGFiLWNvbmZpZy10ZW1wbGF0ZS9naXRsYWIucmIudGVtcGxhdGU= 100644 --- a/files/gitlab-config-template/gitlab.rb.template +++ b/files/gitlab-config-template/gitlab.rb.template @@ -1138,6 +1138,36 @@ ##! **We do not recommend changing this directory.** # gitlab_shell['dir'] = "/var/opt/gitlab/gitlab-shell" +################################################################################ +## gitlab-sshd +################################################################################ + +# gitlab_sshd['enable'] = false +# gitlab_sshd['generate_host_keys'] = true +# gitlab_sshd['dir'] = "/var/opt/gitlab/gitlab-sshd" + +# gitlab-sshd outputs most logs to /var/log/gitlab/gitlab-shell/gitlab-shell.log. +# This directory only stores stdout/stderr output from the daemon. +# gitlab_sshd['log_directory'] = "/var/log/gitlab/gitlab-sshd/" + +# gitlab_sshd['env_directory'] = '/opt/gitlab/etc/gitlab-sshd/env' +# gitlab_sshd['listen_address'] = 'localhost:2222' +# gitlab_sshd['metrics_address'] = 'localhost:9122' +# gitlab_sshd['concurrent_sessions_limit'] = 100 +# gitlab_sshd['proxy_protocol'] = false +# gitlab_sshd['proxy_policy'] = 'use' +# gitlab_sshd['proxy_header_timeout'] = '500ms' +# gitlab_sshd['grace_period'] = 55 +# gitlab_sshd['client_alive_interval'] = nil +# gitlab_sshd['ciphers'] = nil +# gitlab_sshd['kex_algorithms'] = nil +# gitlab_sshd['macs'] = nil +# gitlab_sshd['login_grace_time'] = 60 +# gitlab_sshd['host_keys_dir'] = '/var/opt/gitlab/gitlab-sshd' +# gitlab_sshd['host_keys_glob'] = 'ssh_host_*_key' +# gitlab_sshd['host_certs_dir'] = '/var/opt/gitlab/gitlab-sshd' +# gitlab_sshd['host_certs_glob'] = 'ssh_host_*-cert.pub' + ################################################################ ## GitLab PostgreSQL ################################################################ diff --git a/files/gitlab-cookbooks/gitlab/attributes/default.rb b/files/gitlab-cookbooks/gitlab/attributes/default.rb index db8b43c93038a5c7fd29aac666c9e50a50e57fbc_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRsYWIvYXR0cmlidXRlcy9kZWZhdWx0LnJi..f67e6a508af155548a72d71a27f3820c6092150f_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRsYWIvYXR0cmlidXRlcy9kZWZhdWx0LnJi 100644 --- a/files/gitlab-cookbooks/gitlab/attributes/default.rb +++ b/files/gitlab-cookbooks/gitlab/attributes/default.rb @@ -614,6 +614,33 @@ "default" => { "path" => "/var/opt/gitlab/git-data" } } +### +# gitlab-sshd +### +default['gitlab']['gitlab_sshd']['enable'] = false +default['gitlab']['gitlab_sshd']['generate_host_keys'] = true +default['gitlab']['gitlab_sshd']['dir'] = "/var/opt/gitlab/gitlab-sshd" +# gitlab-sshd outputs most logs to /var/log/gitlab/gitlab-shell/gitlab-shell.log. +# This directory only stores any stdout/stderr output from the daemon. +default['gitlab']['gitlab_sshd']['log_directory'] = "/var/log/gitlab/gitlab-sshd/" +default['gitlab']['gitlab_sshd']['env_directory'] = '/opt/gitlab/etc/gitlab-sshd/env' +default['gitlab']['gitlab_sshd']['listen_address'] = 'localhost:2222' +default['gitlab']['gitlab_sshd']['metrics_address'] = 'localhost:9122' +default['gitlab']['gitlab_sshd']['concurrent_sessions_limit'] = 100 +default['gitlab']['gitlab_sshd']['proxy_protocol'] = false +default['gitlab']['gitlab_sshd']['proxy_policy'] = 'use' +default['gitlab']['gitlab_sshd']['proxy_header_timeout'] = '500ms' +default['gitlab']['gitlab_sshd']['grace_period'] = 55 +default['gitlab']['gitlab_sshd']['client_alive_interval'] = nil +default['gitlab']['gitlab_sshd']['ciphers'] = nil +default['gitlab']['gitlab_sshd']['kex_algorithms'] = nil +default['gitlab']['gitlab_sshd']['macs'] = nil +default['gitlab']['gitlab_sshd']['login_grace_time'] = 60 +default['gitlab']['gitlab_sshd']['host_keys_dir'] = '/var/opt/gitlab/gitlab-sshd' +default['gitlab']['gitlab_sshd']['host_keys_glob'] = 'ssh_host_*_key' +default['gitlab']['gitlab_sshd']['host_certs_dir'] = '/var/opt/gitlab/gitlab-sshd' +default['gitlab']['gitlab_sshd']['host_certs_glob'] = 'ssh_host_*-cert.pub' + #### # Web server #### diff --git a/files/gitlab-cookbooks/gitlab/libraries/gitlab_sshd_helper.rb b/files/gitlab-cookbooks/gitlab/libraries/gitlab_sshd_helper.rb new file mode 100644 index 0000000000000000000000000000000000000000..f67e6a508af155548a72d71a27f3820c6092150f_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRsYWIvbGlicmFyaWVzL2dpdGxhYl9zc2hkX2hlbHBlci5yYg== --- /dev/null +++ b/files/gitlab-cookbooks/gitlab/libraries/gitlab_sshd_helper.rb @@ -0,0 +1,55 @@ +class GitlabSshdHelper + OMNIBUS_KEYS = %w[enable dir generate_host_keys log_directory env_directory host_keys_dir host_keys_glob host_certs_dir host_certs_glob].freeze + + def initialize(node) + @node = node + end + + # This returns the configuration needed to start gitlab-sshd inside the gitlab-shell + # configuration file. + # + # We purposely don't memoize this call since find_host_keys! and find_host_certs! + # may change if new host keys are created. + def json_config + config = @node['gitlab']['gitlab_sshd'].dup + + find_host_keys!(config) + find_host_certs!(config) + + config['listen'] = config.delete('listen_address') + config['web_listen'] = config.delete('metrics_address') + OMNIBUS_KEYS.each { |key| config.delete(key) } + + config + end + + def no_host_keys? + json_config['host_key_files'].empty? + end + + private + + def find_host_keys!(config) + host_keys_dir = config['host_keys_dir'] + host_keys_glob = config['host_keys_glob'] + + return unless host_keys_glob && host_keys_dir + + path = File.join(host_keys_dir, host_keys_glob) + + host_keys = Dir[path] + config['host_key_files'] = host_keys + end + + def find_host_certs!(config) + host_certs_dir = config['host_certs_dir'] + host_certs_glob = config['host_certs_glob'] + + return unless host_certs_glob && host_certs_dir + + path = File.join(host_certs_dir, host_certs_glob) + + host_certs = Dir[path] + config['host_key_certs'] = host_certs + end +end diff --git a/files/gitlab-cookbooks/gitlab/recipes/gitlab-shell.rb b/files/gitlab-cookbooks/gitlab/recipes/gitlab-shell.rb index db8b43c93038a5c7fd29aac666c9e50a50e57fbc_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRsYWIvcmVjaXBlcy9naXRsYWItc2hlbGwucmI=..f67e6a508af155548a72d71a27f3820c6092150f_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRsYWIvcmVjaXBlcy9naXRsYWItc2hlbGwucmI= 100644 --- a/files/gitlab-cookbooks/gitlab/recipes/gitlab-shell.rb +++ b/files/gitlab-cookbooks/gitlab/recipes/gitlab-shell.rb @@ -16,6 +16,8 @@ ## # account_helper = AccountHelper.new(node) +omnibus_helper = OmnibusHelper.new(node) +sshd_helper = GitlabSshdHelper.new(node) git_user = account_helper.gitlab_user git_group = account_helper.gitlab_group @@ -26,6 +28,14 @@ log_directory = node['gitlab']['gitlab-shell']['log_directory'] gitlab_shell_config_file = File.join(gitlab_shell_var_dir, "config.yml") +gitlab_sshd_enabled = Services.enabled?('gitlab_sshd') +gitlab_sshd_generate_host_keys = node['gitlab']['gitlab_sshd']['generate_host_keys'] +gitlab_sshd_bin_path = File.join(gitlab_shell_dir, 'bin', 'gitlab-sshd') +gitlab_sshd_working_dir = node['gitlab']['gitlab_sshd']['dir'] +gitlab_sshd_log_dir = node['gitlab']['gitlab_sshd']['log_directory'] +gitlab_sshd_env_dir = node['gitlab']['gitlab_sshd']['env_directory'] +gitlab_sshd_host_key_dir = node['gitlab']['gitlab_sshd']['host_keys_dir'] + # Creates `.ssh` directory to hold authorized_keys [ ssh_dir, @@ -38,5 +48,5 @@ end end -[ +directories = [ log_directory, @@ -42,6 +52,10 @@ log_directory, - gitlab_shell_var_dir -].each do |dir| + gitlab_shell_var_dir, +] + +directories += [gitlab_sshd_working_dir, gitlab_sshd_log_dir] if gitlab_sshd_enabled + +directories.each do |dir| directory dir do owner git_user mode "0700" @@ -50,6 +64,25 @@ end gitlab_url, gitlab_relative_path = WebServerHelper.internal_api_url(node) +ssh_key_path = File.join(gitlab_sshd_host_key_dir, '/etc/ssh') +ssh_key_glob = File.join(ssh_key_path, 'ssh_host_*_key') + +bash 'generate gitlab-sshd host keys' do + action + only_if { gitlab_sshd_enabled && gitlab_sshd_generate_host_keys && Dir.exist?(gitlab_sshd_host_key_dir) && sshd_helper.no_host_keys? } + code <<~EOS + set -e + mkdir -p #{ssh_key_path} + ssh-keygen -A -f #{gitlab_sshd_host_key_dir} + chmod 0600 #{ssh_key_glob} + chown #{git_user}:#{git_group} #{ssh_key_glob} + mv #{ssh_key_glob} #{gitlab_sshd_host_key_dir} + EOS +end + +gitlab_rails_dir = node['gitlab']['gitlab-rails']['dir'] +gitlab_rails_etc_dir = File.join(gitlab_rails_dir, "etc") +gitlab_shell_secret_file = File.join(gitlab_rails_etc_dir, 'gitlab_shell_secret') templatesymlink "Create a config.yml and create a symlink to Rails root" do link_from File.join(gitlab_shell_dir, "config.yml") @@ -58,18 +91,24 @@ mode "0640" owner "root" group git_group - variables({ - user: git_user, - gitlab_url: gitlab_url, - gitlab_relative_path: gitlab_relative_path, - authorized_keys: authorized_keys, - log_file: File.join(log_directory, "gitlab-shell.log"), - log_level: node['gitlab']['gitlab-shell']['log_level'], - log_format: node['gitlab']['gitlab-shell']['log_format'], - audit_usernames: node['gitlab']['gitlab-shell']['audit_usernames'], - http_settings: node['gitlab']['gitlab-shell']['http_settings'], - git_trace_log_file: node['gitlab']['gitlab-shell']['git_trace_log_file'], - migration: node['gitlab']['gitlab-shell']['migration'], - ssl_cert_dir: node['gitlab']['gitlab-shell']['ssl_cert_dir'] - }) + variables( + lazy do + { + user: git_user, + gitlab_url: gitlab_url, + gitlab_relative_path: gitlab_relative_path, + authorized_keys: authorized_keys, + secret_file: gitlab_shell_secret_file, + log_file: File.join(log_directory, "gitlab-shell.log"), + log_level: node['gitlab']['gitlab-shell']['log_level'], + log_format: node['gitlab']['gitlab-shell']['log_format'], + audit_usernames: node['gitlab']['gitlab-shell']['audit_usernames'], + http_settings: node['gitlab']['gitlab-shell']['http_settings'], + git_trace_log_file: node['gitlab']['gitlab-shell']['git_trace_log_file'], + migration: node['gitlab']['gitlab-shell']['migration'], + ssl_cert_dir: node['gitlab']['gitlab-shell']['ssl_cert_dir'], + gitlab_sshd: gitlab_sshd_enabled ? sshd_helper.json_config : nil + } + end + ) notifies :run, 'bash[Set proper security context on ssh files for selinux]', :delayed if SELinuxHelper.enabled? @@ -75,4 +114,5 @@ notifies :run, 'bash[Set proper security context on ssh files for selinux]', :delayed if SELinuxHelper.enabled? + notifies :restart, "runit_service[gitlab-sshd]" if gitlab_sshd_enabled sensitive true end @@ -87,3 +127,22 @@ action :create_if_missing notifies :run, 'bash[Set proper security context on ssh files for selinux]', :delayed if SELinuxHelper.enabled? end + +env_dir gitlab_sshd_env_dir do + action gitlab_sshd_enabled ? :create : :nothing + variables node['gitlab']['gitlab_sshd']['env'] + notifies :restart, "runit_service[gitlab-sshd]" if omnibus_helper.should_notify?('gitlab_sshd') +end + +runit_service 'gitlab-sshd' do + action gitlab_sshd_enabled ? :enable : :disable + options({ + user: account_helper.gitlab_user, + groupname: account_helper.gitlab_group, + working_dir: gitlab_sshd_working_dir, + env_dir: gitlab_sshd_env_dir, + bin_path: gitlab_sshd_bin_path, + config_dir: gitlab_shell_var_dir, + log_directory: gitlab_sshd_log_dir, + }.merge(params)) +end diff --git a/files/gitlab-cookbooks/gitlab/templates/default/gitlab-shell-config.yml.erb b/files/gitlab-cookbooks/gitlab/templates/default/gitlab-shell-config.yml.erb index db8b43c93038a5c7fd29aac666c9e50a50e57fbc_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRsYWIvdGVtcGxhdGVzL2RlZmF1bHQvZ2l0bGFiLXNoZWxsLWNvbmZpZy55bWwuZXJi..f67e6a508af155548a72d71a27f3820c6092150f_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRsYWIvdGVtcGxhdGVzL2RlZmF1bHQvZ2l0bGFiLXNoZWxsLWNvbmZpZy55bWwuZXJi 100644 --- a/files/gitlab-cookbooks/gitlab/templates/default/gitlab-shell-config.yml.erb +++ b/files/gitlab-cookbooks/gitlab/templates/default/gitlab-shell-config.yml.erb @@ -12,6 +12,10 @@ gitlab_relative_url_root: <%= @gitlab_relative_path %> <% end %> +# File that contains the secret key for verifying access to GitLab. +# Default is .gitlab_shell_secret in the gitlab-shell directory. +secret_file: "<%= @secret_file %>" + http_settings: <%= @http_settings.to_json if @http_settings %> # user: someone @@ -55,3 +59,7 @@ # It needs to exist so we can check permissions and avoid to throwing warnings to the users. git_trace_log_file: "<%= @git_trace_log_file %>" <% end %> + +<% if @gitlab_sshd %> +sshd: <%= @gitlab_sshd.to_json %> +<% end %> diff --git a/files/gitlab-cookbooks/gitlab/templates/default/sv-gitlab-sshd-log-config.erb b/files/gitlab-cookbooks/gitlab/templates/default/sv-gitlab-sshd-log-config.erb new file mode 100644 index 0000000000000000000000000000000000000000..f67e6a508af155548a72d71a27f3820c6092150f_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRsYWIvdGVtcGxhdGVzL2RlZmF1bHQvc3YtZ2l0bGFiLXNzaGQtbG9nLWNvbmZpZy5lcmI= --- /dev/null +++ b/files/gitlab-cookbooks/gitlab/templates/default/sv-gitlab-sshd-log-config.erb @@ -0,0 +1,6 @@ +<%= "s#@svlogd_size" if @svlogd_size %> +<%= "n#@svlogd_num" if @svlogd_num %> +<%= "t#@svlogd_timeout" if @svlogd_timeout %> +<%= "!#@svlogd_filter" if @svlogd_filter %> +<%= "u#@svlogd_udp" if @svlogd_udp %> +<%= "p#@svlogd_prefix" if @svlogd_prefix %> diff --git a/files/gitlab-cookbooks/gitlab/templates/default/sv-gitlab-sshd-log-run.erb b/files/gitlab-cookbooks/gitlab/templates/default/sv-gitlab-sshd-log-run.erb new file mode 100644 index 0000000000000000000000000000000000000000..f67e6a508af155548a72d71a27f3820c6092150f_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRsYWIvdGVtcGxhdGVzL2RlZmF1bHQvc3YtZ2l0bGFiLXNzaGQtbG9nLXJ1bi5lcmI= --- /dev/null +++ b/files/gitlab-cookbooks/gitlab/templates/default/sv-gitlab-sshd-log-run.erb @@ -0,0 +1,2 @@ +#!/bin/sh +exec svlogd <%= @options[:log_directory] %> diff --git a/files/gitlab-cookbooks/gitlab/templates/default/sv-gitlab-sshd-run.erb b/files/gitlab-cookbooks/gitlab/templates/default/sv-gitlab-sshd-run.erb new file mode 100644 index 0000000000000000000000000000000000000000..f67e6a508af155548a72d71a27f3820c6092150f_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRsYWIvdGVtcGxhdGVzL2RlZmF1bHQvc3YtZ2l0bGFiLXNzaGQtcnVuLmVyYg== --- /dev/null +++ b/files/gitlab-cookbooks/gitlab/templates/default/sv-gitlab-sshd-run.erb @@ -0,0 +1,13 @@ +#!/bin/bash +set -e # fail on errors + +# Redirect stderr -> stdout +exec 2>&1 + +cd <%= @options[:working_dir] %> + +exec chpst -P -e <%= @options[:env_dir] %> \ +-U <%= @options[:user] %>:<%= @options[:groupname] %> \ +-u <%= @options[:user] %>:<%= @options[:groupname] %> \ +<%= @options[:bin_path] %> \ + -config-dir <%= @options[:config_dir] %> \ diff --git a/files/gitlab-cookbooks/package/libraries/config/gitlab.rb b/files/gitlab-cookbooks/package/libraries/config/gitlab.rb index db8b43c93038a5c7fd29aac666c9e50a50e57fbc_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9wYWNrYWdlL2xpYnJhcmllcy9jb25maWcvZ2l0bGFiLnJi..f67e6a508af155548a72d71a27f3820c6092150f_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9wYWNrYWdlL2xpYnJhcmllcy9jb25maWcvZ2l0bGFiLnJi 100644 --- a/files/gitlab-cookbooks/package/libraries/config/gitlab.rb +++ b/files/gitlab-cookbooks/package/libraries/config/gitlab.rb @@ -91,6 +91,7 @@ ee_attribute('suggested_reviewers').use { SuggestedReviewers } # Base GitLab attributes + attribute('gitlab_sshd', priority: 5) attribute('gitlab_shell', priority: 10).use { GitlabShell } # Parse shell before rails for data dir settings attribute('gitlab_rails', priority: 15).use { GitlabRails } # Parse rails first as others may depend on it attribute('gitlab_workhorse', priority: 20).use { GitlabWorkhorse } diff --git a/files/gitlab-cookbooks/package/libraries/config/services.rb b/files/gitlab-cookbooks/package/libraries/config/services.rb index db8b43c93038a5c7fd29aac666c9e50a50e57fbc_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9wYWNrYWdlL2xpYnJhcmllcy9jb25maWcvc2VydmljZXMucmI=..f67e6a508af155548a72d71a27f3820c6092150f_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9wYWNrYWdlL2xpYnJhcmllcy9jb25maWcvc2VydmljZXMucmI= 100644 --- a/files/gitlab-cookbooks/package/libraries/config/services.rb +++ b/files/gitlab-cookbooks/package/libraries/config/services.rb @@ -43,6 +43,7 @@ service 'storage_check' service 'crond' service 'praefect' + service 'gitlab_sshd' end # Define the services included in the EE edition of GitLab diff --git a/files/gitlab-cookbooks/package/libraries/settings_dsl.rb b/files/gitlab-cookbooks/package/libraries/settings_dsl.rb index db8b43c93038a5c7fd29aac666c9e50a50e57fbc_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9wYWNrYWdlL2xpYnJhcmllcy9zZXR0aW5nc19kc2wucmI=..f67e6a508af155548a72d71a27f3820c6092150f_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9wYWNrYWdlL2xpYnJhcmllcy9zZXR0aW5nc19kc2wucmI= 100644 --- a/files/gitlab-cookbooks/package/libraries/settings_dsl.rb +++ b/files/gitlab-cookbooks/package/libraries/settings_dsl.rb @@ -251,7 +251,7 @@ def sanitized_key(key) # Services that have been migrated to use underscored form in Chef code # and no longer needs to be hyphenated. - skip_hyphenation = %w[gitlab_pages] + skip_hyphenation = %w[gitlab_pages gitlab_sshd] return underscored_form(key) if skip_hyphenation.include?(underscored_form(key)) diff --git a/spec/chef/cookbooks/gitlab/recipes/gitlab-shell_spec.rb b/spec/chef/cookbooks/gitlab/recipes/gitlab-shell_spec.rb index db8b43c93038a5c7fd29aac666c9e50a50e57fbc_c3BlYy9jaGVmL2Nvb2tib29rcy9naXRsYWIvcmVjaXBlcy9naXRsYWItc2hlbGxfc3BlYy5yYg==..f67e6a508af155548a72d71a27f3820c6092150f_c3BlYy9jaGVmL2Nvb2tib29rcy9naXRsYWIvcmVjaXBlcy9naXRsYWItc2hlbGxfc3BlYy5yYg== 100644 --- a/spec/chef/cookbooks/gitlab/recipes/gitlab-shell_spec.rb +++ b/spec/chef/cookbooks/gitlab/recipes/gitlab-shell_spec.rb @@ -1,7 +1,7 @@ require 'chef_helper' RSpec.describe 'gitlab::gitlab-shell' do - let(:chef_run) { ChefSpec::SoloRunner.converge('gitlab::default') } + let(:chef_run) { ChefSpec::SoloRunner.new(step_into: %w(templatesymlink runit_service)).converge('gitlab::default') } before do allow(Gitlab).to receive(:[]).and_call_original @@ -45,8 +45,9 @@ it 'create config file in default location with default values' do expect(chef_run).to create_templatesymlink('Create a config.yml and create a symlink to Rails root').with_variables( hash_including( + secret_file: '/var/opt/gitlab/gitlab-rails/etc/gitlab_shell_secret', log_file: '/var/log/gitlab/gitlab-shell/gitlab-shell.log', log_format: "json", migration: { enabled: true, features: [] }, gitlab_url: 'http+unix://%2Fvar%2Fopt%2Fgitlab%2Fgitlab-workhorse%2Fsockets%2Fsocket', gitlab_relative_path: '', @@ -48,9 +49,10 @@ log_file: '/var/log/gitlab/gitlab-shell/gitlab-shell.log', log_format: "json", migration: { enabled: true, features: [] }, gitlab_url: 'http+unix://%2Fvar%2Fopt%2Fgitlab%2Fgitlab-workhorse%2Fsockets%2Fsocket', gitlab_relative_path: '', - ssl_cert_dir: '/opt/gitlab/embedded/ssl/certs/' + ssl_cert_dir: '/opt/gitlab/embedded/ssl/certs/', + gitlab_sshd: nil ) ) end @@ -54,6 +56,21 @@ ) ) end + + it 'renders gitlab-shell config' do + expect(chef_run).to render_file('/var/opt/gitlab/gitlab-shell/config.yml').with_content { |content| + data = YAML.safe_load(content) + + expect(data['secret_file']).to eq('/var/opt/gitlab/gitlab-rails/etc/gitlab_shell_secret') + expect(data['log_file']).to eq('/var/log/gitlab/gitlab-shell/gitlab-shell.log') + expect(data['log_format']).to eq('json') + expect(data['migration']).to eq({ "enabled" => true, "features" => [] }) + expect(data['gitlab_url']).to eq('http+unix://%2Fvar%2Fopt%2Fgitlab%2Fgitlab-workhorse%2Fsockets%2Fsocket') + expect(data['gitlab_relative_path']).to be_nil + expect(data['ssl_cert_dir']).to eq('/opt/gitlab/embedded/ssl/certs/') + expect(data['sshd']).to be_nil + } + end end context 'with a non-default directory' do @@ -226,7 +243,8 @@ expect(chef_run).to create_templatesymlink('Create a config.yml and create a symlink to Rails root').with_variables( hash_including( gitlab_url: 'http://localhost:1234/gitlab', - gitlab_relative_path: nil + gitlab_relative_path: nil, + secret_file: '/var/opt/gitlab/gitlab-rails/etc/gitlab_shell_secret' ) ) end @@ -241,7 +259,8 @@ expect(chef_run).to create_templatesymlink('Create a config.yml and create a symlink to Rails root').with_variables( hash_including( gitlab_url: 'http+unix://%2Fvar%2Fopt%2Fgitlab%2Fgitlab-workhorse%2Fsockets%2Fsocket', - gitlab_relative_path: '/gitlab' + gitlab_relative_path: '/gitlab', + secret_file: '/var/opt/gitlab/gitlab-rails/etc/gitlab_shell_secret' ) ) end @@ -262,4 +281,95 @@ end end end + + context 'with gitlab-sshd enabled' do + let(:templatesymlink) { chef_run.templatesymlink('Create a config.yml and create a symlink to Rails root') } + let(:expected_sshd_keys) do + %w[listen proxy_protocol proxy_policy web_listen concurrent_sessions_limit client_alive_interval + grace_period login_grace_time proxy_header_timeout macs kex_algorithms ciphers host_key_files host_key_certs] + end + + before do + stub_gitlab_rb( + gitlab_sshd: { + enable: true, + log_directory: '/tmp/log' + } + ) + end + + before do + allow(Dir).to receive(:[]).and_call_original + end + + context 'with default host key and cert globs' do + let(:host_key) { %w(/tmp/host_keys/ssh_key) } + let(:default_host_key_glob) { '/var/opt/gitlab/gitlab-sshd/ssh_host_*_key' } + let(:default_host_cert_glob) { '/var/opt/gitlab/gitlab-sshd/ssh_host_*-cert.pub' } + + before do + allow(Dir).to receive(:[]).with(default_host_key_glob).and_return(host_key) + allow(Dir).to receive(:[]).with(default_host_cert_glob).and_return([]) + end + + it 'renders gitlab-sshd config' do + expect(chef_run).to render_file('/var/opt/gitlab/gitlab-shell/config.yml').with_content { |content| + data = YAML.safe_load(content) + + expect(data['sshd'].keys).to match_array(expected_sshd_keys) + expect(data['sshd']['host_key_files']).to eq(host_key) + expect(data['sshd']['host_key_certs']).to be_empty + expect(data['sshd']['listen']).to eq('localhost:2222') + expect(data['sshd']['web_listen']).to eq('localhost:9122') + expect(data['sshd']['proxy_protocol']).to be false + } + end + + it 'template triggers notifications' do + expect(templatesymlink).to notify('runit_service[gitlab-sshd]').to(:restart).delayed + end + + it 'correctly renders out the gitlab_sshd service file' do + expect(chef_run).to render_file("/opt/gitlab/sv/gitlab-sshd/run") + .with_content { |content| + expect(content).to include('cd /var/opt/gitlab/gitlab-sshd') + expect(content).to include('/opt/gitlab/embedded/service/gitlab-shell/bin/gitlab-sshd') + expect(content).to include('-config-dir /var/opt/gitlab/gitlab-shell') + } + end + end + + context 'with custom host key path' do + let(:host_key_glob) { '/tmp/host_keys/ssh_key*' } + let(:host_cert_glob) { '/tmp/host_keys/ssh_cert*' } + let(:host_keys) { %w(/tmp/host_keys/ssh_key1 /tmp/host_keys/ssh_key2) } + let(:host_certs) { %w(/tmp/host_keys/ssh_cert1 /tmp/host_keys/ssh_cert2) } + + before do + stub_gitlab_rb( + gitlab_sshd: { + enable: true, + log_directory: '/tmp/log', + host_keys_dir: '/tmp/host_keys', + host_keys_glob: 'ssh_key*', + host_certs_dir: '/tmp/host_keys', + host_certs_glob: 'ssh_cert*' + } + ) + + allow(Dir).to receive(:[]).with(host_key_glob).and_return(host_keys) + allow(Dir).to receive(:[]).with(host_cert_glob).and_return(host_certs) + end + + it 'renders gitlab-sshd config' do + expect(chef_run).to render_file('/var/opt/gitlab/gitlab-shell/config.yml').with_content { |content| + data = YAML.safe_load(content) + + expect(data['sshd'].keys).to match_array(expected_sshd_keys) + expect(data['sshd']['host_key_files']).to eq(host_keys) + expect(data['sshd']['host_key_certs']).to eq(host_certs) + } + end + end + end end