diff --git a/lib/beaker-pe/install/pe_utils.rb b/lib/beaker-pe/install/pe_utils.rb index 7cce23c..25ac96f 100644 --- a/lib/beaker-pe/install/pe_utils.rb +++ b/lib/beaker-pe/install/pe_utils.rb @@ -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 diff --git a/spec/beaker-pe/install/pe_utils_spec.rb b/spec/beaker-pe/install/pe_utils_spec.rb index f745d14..70dba5b 100644 --- a/spec/beaker-pe/install/pe_utils_spec.rb +++ b/spec/beaker-pe/install/pe_utils_spec.rb @@ -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