Skip to content

Commit c767580

Browse files
committed
Fixes #31049 - Introduce server CA file setting
1 parent b5169f0 commit c767580

File tree

5 files changed

+93
-24
lines changed

5 files changed

+93
-24
lines changed

app/models/setting.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ class Setting < ApplicationRecord
1515
FROZEN_ATTRS = %w{name category}
1616
NONZERO_ATTRS = %w{puppet_interval idle_timeout entries_per_page outofsync_interval}
1717
BLANK_ATTRS = %w{ host_owner trusted_hosts login_delegation_logout_url root_pass default_location default_organization websockets_ssl_key websockets_ssl_cert oauth_consumer_key oauth_consumer_secret login_text oidc_audience oidc_issuer oidc_algorithm
18-
smtp_address smtp_domain smtp_user_name smtp_password smtp_openssl_verify_mode smtp_authentication sendmail_arguments sendmail_location http_proxy http_proxy_except_list default_locale default_timezone ssl_certificate ssl_ca_file ssl_priv_key default_pxe_item_global default_pxe_item_local oidc_jwks_url instance_title }
18+
smtp_address smtp_domain smtp_user_name smtp_password smtp_openssl_verify_mode smtp_authentication sendmail_arguments sendmail_location http_proxy http_proxy_except_list default_locale default_timezone ssl_certificate ssl_ca_file server_ca_file ssl_priv_key default_pxe_item_global default_pxe_item_local oidc_jwks_url instance_title }
1919
ARRAY_HOSTNAMES = %w{trusted_hosts}
2020
URI_ATTRS = %w{foreman_url unattended_url}
2121
URI_BLANK_ATTRS = %w{login_delegation_logout_url}

app/models/setting/auth.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ def self.default_settings
1515
set('ssl_client_dn_env', N_('Environment variable containing the subject DN from a client SSL certificate'), 'SSL_CLIENT_S_DN', N_('SSL client DN env')),
1616
set('ssl_client_verify_env', N_('Environment variable containing the verification status of a client SSL certificate'), 'SSL_CLIENT_VERIFY', N_('SSL client verify env')),
1717
set('ssl_client_cert_env', N_("Environment variable containing a client's SSL certificate"), 'SSL_CLIENT_CERT', N_('SSL client cert env')),
18+
set('server_ca_file', N_("SSL CA file that will be used in templates (to verify the connection to Foreman)"), nil, N_('Server CA file')),
1819
set('websockets_ssl_key', N_("Private key file that Foreman will use to encrypt websockets "), nil, N_('Websockets SSL key')),
1920
set('websockets_ssl_cert', N_("Certificate that Foreman will use to encrypt websockets "), nil, N_('Websockets SSL certificate')),
2021
# websockets_encrypt depends on key/cert when true, so initialize it last

lib/foreman/renderer/scope/macros/base.rb

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -334,20 +334,33 @@ def gem_version_compare(first, second)
334334
Gem::Version.new(first.to_s) <=> Gem::Version.new(second.to_s)
335335
end
336336

337-
apipie :method, "Returns content of 'SSL CA file' configured in Settings > Authentication" do
337+
apipie :method, "Returns a combination of 'Server CA file' and 'SSL CA file' configured in Settings > Authentication" do
338338
example "SSL_CA_CERT=$(mktemp)
339339
cat > $SSL_CA_CERT <<CA_CONTENT
340340
<%= foreman_server_ca_cert %>
341341
CA_CONTENT
342-
curl --cacert $SSL_CA_CERT https://smart-proxy.example.com:8443"
343-
end
344-
def foreman_server_ca_cert
345-
if File.exist?(Setting[:ssl_ca_file])
346-
File.read(Setting[:ssl_ca_file])
347-
else
348-
msg = N_("SSL CA file not found, check the 'SSL CA file' in Settings > Authentication")
349-
raise Foreman::Exception.new(msg)
342+
curl --cacert $SSL_CA_CERT https://foreman.example.com:8443"
343+
end
344+
def foreman_server_ca_cert(server_ca_file_enabled: true, ssl_ca_file_enabled: true)
345+
setting_names = [].tap do |array|
346+
array << :server_ca_file if server_ca_file_enabled
347+
array << :ssl_ca_file if ssl_ca_file_enabled
348+
end
349+
350+
setting_values = setting_names.map { |setting_name| Setting[setting_name] }.compact
351+
352+
files_content = setting_values.map do |setting_value|
353+
File.read(setting_value)
354+
rescue Errno::ENOENT, Errno::EACCES
355+
nil
350356
end
357+
358+
result = files_content.compact.join("\n")
359+
360+
return result if result.present?
361+
362+
msg = N_("SSL CA file not found, check the 'Server CA file' and 'SSL CA file' in Settings > Authentication")
363+
raise Foreman::Exception.new(msg)
351364
end
352365

353366
private

test/fixtures/settings.yml

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,17 @@ attributes4:
2222
description: Enable safe mode config templates rendinging(recommended)
2323
attributes5:
2424
name: ssl_certificate
25-
category: Setting::Provisioning
25+
category: Setting::Auth
2626
default: /var/lib/puppet/ssl/certs/some.host.fqdn
2727
description: SSL Certificate path that foreman would use to communicate with its proxies
2828
attributes6:
2929
name: ssl_ca_file
30-
category: Setting::Provisioning
30+
category: Setting::Auth
3131
default: /var/lib/puppet/ssl/certs/ca.pem
3232
description: SSL CA file that foreman would use to communicate with its proxies
3333
attributes7:
3434
name: ssl_priv_key
35-
category: Setting::Provisioning
35+
category: Setting::Auth
3636
default: /var/lib/puppet/ssl/private_keys/super.some.host.fqdn.pem
3737
description: SSL Private Key file that foreman would use to communicate with its proxies
3838
attributes8:
@@ -428,3 +428,8 @@ attribute94:
428428
category: Setting::Provisioning
429429
default: 'Global Registration'
430430
description: "Default Global registration template"
431+
attributes95:
432+
name: server_ca_file
433+
category: Setting::Auth
434+
default: /var/lib/puppet/ssl/certs/ca.pem
435+
description: SSL CA file that will be used in templates (to verify the connection to Foreman)

test/unit/foreman/renderer/renderers_shared_tests.rb

Lines changed: 61 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -205,18 +205,68 @@ module RenderersSharedTests
205205
assert_equal(renderer.render(source, @scope), '-1')
206206
end
207207

208-
test "foreman_server_ca_cert - existing file" do
209-
cert_path = Rails.root.join('test/static_fixtures/certificates/example.com.crt')
210-
Setting[:ssl_ca_file] = cert_path
211-
source = OpenStruct.new(content: '<%= foreman_server_ca_cert %>')
212-
assert_equal(renderer.render(source, @scope), File.read(cert_path))
213-
end
208+
describe '#foreman_server_ca_cert' do
209+
subject { renderer.render(source, @scope) }
214210

215-
test "foreman_server_ca_cert - not existing file" do
216-
Setting[:ssl_ca_file] = 'not-existing-file'
217-
source = OpenStruct.new(content: '<%= foreman_server_ca_cert %>')
218-
assert_raise Foreman::Exception do
219-
renderer.render(source, @scope)
211+
let(:source) { OpenStruct.new(content: '<%= foreman_server_ca_cert %>') }
212+
let(:cert_path) { Rails.root.join('test/static_fixtures/certificates/example.com.crt') }
213+
let(:cert_file_content) { File.read(cert_path) }
214+
215+
test "load server_ca_file" do
216+
Setting[:server_ca_file] = cert_path
217+
Setting[:ssl_ca_file] = 'not-existing-file'
218+
219+
assert_equal subject, cert_file_content
220+
end
221+
222+
test "load ssl_ca_file" do
223+
Setting[:server_ca_file] = 'not-existing-file'
224+
Setting[:ssl_ca_file] = cert_path
225+
226+
assert_equal subject, cert_file_content
227+
end
228+
229+
test "load server_ca_file and ssl_ca_file" do
230+
Setting[:server_ca_file] = cert_path
231+
Setting[:ssl_ca_file] = cert_path
232+
233+
expeced = "#{cert_file_content}\n#{cert_file_content}"
234+
assert_equal subject, expeced
235+
end
236+
237+
test "do not load any files and raise exception" do
238+
Setting[:server_ca_file] = 'not-existing-file'
239+
Setting[:ssl_ca_file] = 'not-existing-file'
240+
241+
assert_raise Foreman::Exception do
242+
subject
243+
end
244+
end
245+
246+
context 'when server_ca_file is disabled' do
247+
let(:source) { OpenStruct.new(content: '<%= foreman_server_ca_cert(server_ca_file_enabled: false) %>') }
248+
249+
test "do not load server_ca_file and raise exception" do
250+
Setting[:server_ca_file] = cert_path
251+
Setting[:ssl_ca_file] = 'not-existing-file'
252+
253+
assert_raise Foreman::Exception do
254+
subject
255+
end
256+
end
257+
end
258+
259+
context 'when ssl_ca_file is disabled' do
260+
let(:source) { OpenStruct.new(content: '<%= foreman_server_ca_cert(ssl_ca_file_enabled: false) %>') }
261+
262+
test "do not load ssl_ca_file and raise exception" do
263+
Setting[:server_ca_file] = 'not-existing-file'
264+
Setting[:ssl_ca_file] = cert_path
265+
266+
assert_raise Foreman::Exception do
267+
subject
268+
end
269+
end
220270
end
221271
end
222272

0 commit comments

Comments
 (0)