Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 20 additions & 10 deletions lib/beaker-pe/install/pe_utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1850,21 +1850,31 @@ def check_puppetdb_status_endpoint(host)
# Prefer the ssl status endpoint. PuppetDB's jetty listener is
# explicitly configured with `client-auth = want`, not `need`
# (see puppet_enterprise::puppetdb::jetty_ini.pp), and
# /pdb/meta/v1/version -- like the rest of /status/v1/* -- is
# allow-unauthenticated in PuppetDB's auth.conf. So `curl -k`
# gets a real, validated response with no client cert needed,
# and it's the only path that still works once the cleartext
# listener is disabled by default (PE-45384/PE-44906,
# SECVULN-1792; PE-45827).
output = on(host, "curl -s -k https://localhost:#{ssl_port}/pdb/meta/v1/version", :accept_all_exit_codes => true)
match = output.stdout =~ /version.*\d+\.\d+\.\d+/
# /status/v1/* is allow-unauthenticated in PuppetDB's auth.conf,
# so `curl -k` gets a real, content-validated response with no
# client cert needed. This is the only path that still works
# once the cleartext listener is disabled by default
# (PE-45384/PE-44906, SECVULN-1792).
#
# NB: /pdb/meta/v1/version is NOT allow-unauthenticated -- it
# requires a cert or token, so a bare `curl -k` against it is
# rejected with "Must supply a certificate or token". PE-45827
# switched this check to ssl but kept /pdb/meta/v1/version, so it
# still hard-failed ("PuppetDB took too long to start") on
# cleartext-disabled upgrade hosts. Query the status endpoint and
# validate the running state instead, matching the working
# sleep_until_puppetdb_started (beaker-puppet, PE-45697). PE-45827.
status_endpoint = "status/v1/services/puppetdb-status"
running = /"state"\s*:\s*"running"/
output = on(host, "curl -s -k https://localhost:#{ssl_port}/#{status_endpoint}", :accept_all_exit_codes => true)
match = output.stdout =~ running

# Fall back to the cleartext port for older or nonstandard
# configurations where the ssl endpoint doesn't behave as
# above.
if !match
output = on(host, "curl -s http://localhost:#{nonssl_port}/pdb/meta/v1/version", :accept_all_exit_codes => true)
match = output.stdout =~ /version.*\d+\.\d+\.\d+/
output = on(host, "curl -s http://localhost:#{nonssl_port}/#{status_endpoint}", :accept_all_exit_codes => true)
match = output.stdout =~ running
end

sleep 1
Expand Down
17 changes: 9 additions & 8 deletions spec/beaker-pe/install/pe_utils_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2671,24 +2671,25 @@ def stub_installer_log_greps(all_but: nil)
subject.check_puppetdb_status_endpoint(unixhost)
end

it 'succeeds via the ssl endpoint alone, without ever falling back to cleartext (PE-45827)' do
it 'queries the allow-unauthenticated ssl status endpoint, not /pdb/meta (PE-45827)' do
allow(subject).to receive(:version_is_less).and_return(false)
allow(subject).to receive(:sleep)
ssl_result = double(Beaker::Result, :stdout => '{"version":"7.12.1"}', :exit_code => 0)
expect(subject).to receive(:on).with(anything, %r{-k https://localhost:8081/}, anything).once.and_return(ssl_result)
ssl_result = double(Beaker::Result, :stdout => '{"puppetdb-status":{"state":"running"}}', :exit_code => 0)
expect(subject).to receive(:on).with(anything, %r{-k https://localhost:8081/status/v1/services/puppetdb-status}, anything).once.and_return(ssl_result)
expect(subject).not_to receive(:on).with(anything, %r{/pdb/meta/}, anything)
expect(subject).not_to receive(:on).with(anything, %r{http://localhost:8080/}, anything)

expect { subject.check_puppetdb_status_endpoint(unixhost) }.not_to raise_error
end

context 'when the ssl endpoint never returns valid content (older or nonstandard config)' do
it 'falls back to the cleartext endpoint' do
context 'when the ssl endpoint never returns a running state (older or nonstandard config)' do
it 'falls back to the cleartext status endpoint' do
allow(subject).to receive(:version_is_less).and_return(false)
allow(subject).to receive(:sleep)
ssl_result = double(Beaker::Result, :stdout => '', :exit_code => 0)
nonssl_result = double(Beaker::Result, :stdout => '{"version":"7.12.1"}', :exit_code => 0)
expect(subject).to receive(:on).with(anything, %r{-k https://localhost:8081/}, anything).once.ordered.and_return(ssl_result)
expect(subject).to receive(:on).with(anything, %r{http://localhost:8080/}, anything).once.ordered.and_return(nonssl_result)
nonssl_result = double(Beaker::Result, :stdout => '{"puppetdb-status":{"state":"running"}}', :exit_code => 0)
expect(subject).to receive(:on).with(anything, %r{-k https://localhost:8081/status/v1/services/puppetdb-status}, anything).once.ordered.and_return(ssl_result)
expect(subject).to receive(:on).with(anything, %r{http://localhost:8080/status/v1/services/puppetdb-status}, anything).once.ordered.and_return(nonssl_result)

expect { subject.check_puppetdb_status_endpoint(unixhost) }.not_to raise_error
end
Expand Down
Loading