diff --git a/files/gitlab-config-template/gitlab.rb.template b/files/gitlab-config-template/gitlab.rb.template index 4e24f6c3e3d3fb0f399fc2e02fabfafce031a7b0_ZmlsZXMvZ2l0bGFiLWNvbmZpZy10ZW1wbGF0ZS9naXRsYWIucmIudGVtcGxhdGU=..a7ded2feeef93afeed156110e822f9cbf45293e6_ZmlsZXMvZ2l0bGFiLWNvbmZpZy10ZW1wbGF0ZS9naXRsYWIucmIudGVtcGxhdGU= 100644 --- a/files/gitlab-config-template/gitlab.rb.template +++ b/files/gitlab-config-template/gitlab.rb.template @@ -1803,5 +1803,7 @@ # gitlab_kas['listen_address'] = 'localhost:8150' # gitlab_kas['listen_network'] = 'tcp' # gitlab_kas['listen_websocket'] = true +# gitlab_kas['certificate_file'] = "/path/to/certificate.pem" +# gitlab_kas['key_file'] = "/path/to/key.pem" # gitlab_kas['internal_api_listen_network'] = 'tcp' # gitlab_kas['internal_api_listen_address'] = 'localhost:8153' @@ -1806,3 +1808,5 @@ # gitlab_kas['internal_api_listen_network'] = 'tcp' # gitlab_kas['internal_api_listen_address'] = 'localhost:8153' +# gitlab_kas['internal_api_certificate_file'] = "/path/to/certificate.pem" +# gitlab_kas['internal_api_key_file'] = "/path/to/key.pem" # gitlab_kas['kubernetes_api_listen_address'] = 'localhost:8154' @@ -1808,3 +1812,5 @@ # gitlab_kas['kubernetes_api_listen_address'] = 'localhost:8154' +# gitlab_kas['kubernetes_api_certificate_file'] = "/path/to/certificate.pem" +# gitlab_kas['kubernetes_api_key_file'] = "/path/to/key.pem" # gitlab_kas['private_api_listen_network'] = 'tcp' # gitlab_kas['private_api_listen_address'] = 'localhost:8155' @@ -1809,5 +1815,7 @@ # gitlab_kas['private_api_listen_network'] = 'tcp' # gitlab_kas['private_api_listen_address'] = 'localhost:8155' +# gitlab_kas['private_api_certificate_file'] = "/path/to/certificate.pem" +# gitlab_kas['private_api_key_file'] = "/path/to/key.pem" ##! Metrics configuration for GitLab KAS # gitlab_kas['metrics_usage_reporting_period'] = 60 diff --git a/files/gitlab-cookbooks/gitlab-kas/attributes/default.rb b/files/gitlab-cookbooks/gitlab-kas/attributes/default.rb index 4e24f6c3e3d3fb0f399fc2e02fabfafce031a7b0_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRsYWIta2FzL2F0dHJpYnV0ZXMvZGVmYXVsdC5yYg==..a7ded2feeef93afeed156110e822f9cbf45293e6_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRsYWIta2FzL2F0dHJpYnV0ZXMvZGVmYXVsdC5yYg== 100644 --- a/files/gitlab-cookbooks/gitlab-kas/attributes/default.rb +++ b/files/gitlab-cookbooks/gitlab-kas/attributes/default.rb @@ -13,5 +13,7 @@ default['gitlab-kas']['listen_address'] = 'localhost:8150' default['gitlab-kas']['listen_network'] = 'tcp' default['gitlab-kas']['listen_websocket'] = true +default['gitlab-kas']['certificate_file'] = nil +default['gitlab-kas']['key_file'] = nil default['gitlab-kas']['internal_api_listen_address'] = 'localhost:8153' default['gitlab-kas']['internal_api_listen_network'] = 'tcp' @@ -16,3 +18,5 @@ default['gitlab-kas']['internal_api_listen_address'] = 'localhost:8153' default['gitlab-kas']['internal_api_listen_network'] = 'tcp' +default['gitlab-kas']['internal_api_certificate_file'] = nil +default['gitlab-kas']['internal_api_key_file'] = nil default['gitlab-kas']['kubernetes_api_listen_address'] = 'localhost:8154' @@ -18,4 +22,6 @@ default['gitlab-kas']['kubernetes_api_listen_address'] = 'localhost:8154' +default['gitlab-kas']['kubernetes_api_certificate_file'] = nil +default['gitlab-kas']['kubernetes_api_key_file'] = nil default['gitlab-kas']['private_api_secret_key'] = nil default['gitlab-kas']['private_api_listen_address'] = 'localhost:8155' default['gitlab-kas']['private_api_listen_network'] = 'tcp' @@ -19,6 +25,8 @@ default['gitlab-kas']['private_api_secret_key'] = nil default['gitlab-kas']['private_api_listen_address'] = 'localhost:8155' default['gitlab-kas']['private_api_listen_network'] = 'tcp' +default['gitlab-kas']['private_api_certificate_file'] = nil +default['gitlab-kas']['private_api_key_file'] = nil default['gitlab-kas']['metrics_usage_reporting_period'] = 60 default['gitlab-kas']['sentry_dsn'] = nil default['gitlab-kas']['sentry_environment'] = nil diff --git a/files/gitlab-cookbooks/gitlab-kas/recipes/enable.rb b/files/gitlab-cookbooks/gitlab-kas/recipes/enable.rb index 4e24f6c3e3d3fb0f399fc2e02fabfafce031a7b0_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRsYWIta2FzL3JlY2lwZXMvZW5hYmxlLnJi..a7ded2feeef93afeed156110e822f9cbf45293e6_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRsYWIta2FzL3JlY2lwZXMvZW5hYmxlLnJi 100644 --- a/files/gitlab-cookbooks/gitlab-kas/recipes/enable.rb +++ b/files/gitlab-cookbooks/gitlab-kas/recipes/enable.rb @@ -50,6 +50,17 @@ end end +ruby_block 'websocket TLS termination' do + block do + message = [ + "Enabling gitlab-kas API TLS termination and websocket tunnelling at the same time is not supported.", + "See <https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/issues/217>" + ] + LoggingHelper.warning(message.join("\n\n")) + end + only_if { node['gitlab-kas']['listen_websocket'] && node['gitlab-kas']['certificate_file'] && node['gitlab-kas']['key_file'] } +end + version_file 'Create version file for Gitlab KAS' do version_file_path File.join(working_dir, 'VERSION') version_check_cmd '/opt/gitlab/embedded/bin/gitlab-kas --version' diff --git a/files/gitlab-cookbooks/gitlab-kas/templates/default/gitlab-kas-config.yml.erb b/files/gitlab-cookbooks/gitlab-kas/templates/default/gitlab-kas-config.yml.erb index 4e24f6c3e3d3fb0f399fc2e02fabfafce031a7b0_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRsYWIta2FzL3RlbXBsYXRlcy9kZWZhdWx0L2dpdGxhYi1rYXMtY29uZmlnLnltbC5lcmI=..a7ded2feeef93afeed156110e822f9cbf45293e6_ZmlsZXMvZ2l0bGFiLWNvb2tib29rcy9naXRsYWIta2FzL3RlbXBsYXRlcy9kZWZhdWx0L2dpdGxhYi1rYXMtY29uZmlnLnltbC5lcmI= 100644 --- a/files/gitlab-cookbooks/gitlab-kas/templates/default/gitlab-kas-config.yml.erb +++ b/files/gitlab-cookbooks/gitlab-kas/templates/default/gitlab-kas-config.yml.erb @@ -3,6 +3,10 @@ address: <%= @listen_address %> network: <%= @listen_network %> websocket: <%= @listen_websocket %> + <%- if @certificate_file and @key_file %> + certificate_file: <%= @certificate_file %> + key_file: <%= @key_file %> + <%- end %> configuration: poll_period: <%= @agent_configuration_poll_period %>s gitops: @@ -12,6 +16,10 @@ kubernetes_api: listen: address: <%= @kubernetes_api_listen_address %> + <%- if @kubernetes_api_certificate_file and @kubernetes_api_key_file %> + certificate_file: <%= @kubernetes_api_certificate_file %> + key_file: <%= @kubernetes_api_key_file %> + <%- end %> url_path_prefix: / info_cache_ttl: <%= @agent_info_cache_ttl %>s info_cache_error_ttl: <%= @agent_info_cache_error_ttl %>s @@ -50,8 +58,12 @@ network: <%= @internal_api_listen_network %> address: <%= @internal_api_listen_address %> authentication_secret_file: <%= @authentication_secret_file %> + <%- if @internal_api_certificate_file and @internal_api_key_file %> + certificate_file: <%= @internal_api_certificate_file %> + key_file: <%= @internal_api_key_file %> + <%- end %> private_api: listen: network: <%= @private_api_listen_network %> address: <%= @private_api_listen_address %> authentication_secret_file: <%= @private_api_authentication_secret_file %> @@ -53,5 +65,9 @@ private_api: listen: network: <%= @private_api_listen_network %> address: <%= @private_api_listen_address %> authentication_secret_file: <%= @private_api_authentication_secret_file %> + <%- if @private_api_certificate_file and @private_api_key_file %> + certificate_file: <%= @private_api_certificate_file %> + key_file: <%= @private_api_key_file %> + <%- end %> diff --git a/spec/chef/recipes/gitlab-kas_spec.rb b/spec/chef/recipes/gitlab-kas_spec.rb index 4e24f6c3e3d3fb0f399fc2e02fabfafce031a7b0_c3BlYy9jaGVmL3JlY2lwZXMvZ2l0bGFiLWthc19zcGVjLnJi..a7ded2feeef93afeed156110e822f9cbf45293e6_c3BlYy9jaGVmL3JlY2lwZXMvZ2l0bGFiLWthc19zcGVjLnJi 100644 --- a/spec/chef/recipes/gitlab-kas_spec.rb +++ b/spec/chef/recipes/gitlab-kas_spec.rb @@ -403,6 +403,96 @@ end end + describe 'TLS listen config' do + context 'when all certificates and keys are defined' do + before do + stub_gitlab_rb( + external_url: 'https://gitlab.example.com', + gitlab_kas: { + enable: true, + listen_websocket: false, + certificate_file: '/path/to/cert.pem', + key_file: '/path/to/key.pem', + internal_api_certificate_file: '/path/to/internal-api-cert.pem', + internal_api_key_file: '/path/to/internal-api-key.pem', + kubernetes_api_certificate_file: '/path/to/kubernetes-api-cert.pem', + kubernetes_api_key_file: '/path/to/kubernetes-api-key.pem', + private_api_certificate_file: '/path/to/private-api-cert.pem', + private_api_key_file: '/path/to/private-api-key.pem' + } + ) + end + + it 'correctly renders the KAS config file' do + expect(gitlab_kas_config_yml).to( + include( + agent: hash_including( + listen: hash_including( + certificate_file: '/path/to/cert.pem', + key_file: '/path/to/key.pem' + ), + kubernetes_api: hash_including( + listen: hash_including( + certificate_file: '/path/to/kubernetes-api-cert.pem', + key_file: '/path/to/kubernetes-api-key.pem' + ) + ) + ), + api: { + listen: hash_including( + certificate_file: '/path/to/internal-api-cert.pem', + key_file: '/path/to/internal-api-key.pem' + ), + }, + private_api: { + listen: hash_including( + certificate_file: '/path/to/private-api-cert.pem', + key_file: '/path/to/private-api-key.pem' + ) + } + ) + ) + end + end + + context 'when certificate/key bundles are not correctly defined' do + before do + stub_gitlab_rb( + external_url: 'https://gitlab.example.com', + gitlab_kas: { + enable: true, + certificate_file: '/path/to/file.pem', + internal_api_certificate_file: '/path/to/file.pem', + kubernetes_api_key_file: '/path/to/file.pem', + private_api_key_file: '/path/to/file.pem' + } + ) + end + + it 'renders no certificate or key configuration' do + expect(gitlab_kas_config_yml).not_to(include('/path/to/file.pem')) + end + end + + context 'when the certificate/key bundle is defined and websocket tunneling is enabled' do + before do + stub_gitlab_rb( + external_url: 'https://gitlab.example.com', + gitlab_kas: { + enable: true, + listen_websocket: true, + certificate_file: '/path/to/cert.pem', + key_file: '/path/to/key.pem', + } + ) + end + + it 'logs a warning' do + expect(chef_run).to run_ruby_block('websocket TLS termination') + end + end + end + def chef_run_load_yaml_template(chef_run, path) template = chef_run.template(path) file_content = ChefSpec::Renderer.new(chef_run, template).content