Skip to content

Commit 842cce9

Browse files
committed
(PUP-11428) Reload ssl state for each agent run
Previously, we only loaded the agent's ssl state once when the agent started, but not between runs. Since the agent may sleep for upwards of `runinterval` seconds and those files may change on disk, reload them each time. The `wait_for_certificates` behavior depends on whether we're running onetime or not and whether `waitforcert` was specified on the `puppet agent` command line. So pass those options through. Enable pending test now that it passes.
1 parent c31730d commit 842cce9

File tree

4 files changed

+26
-17
lines changed

4 files changed

+26
-17
lines changed

lib/puppet/agent.rb

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,19 +45,29 @@ def run(client_options = {})
4545
result = nil
4646
wait_for_lock_deadline = nil
4747
block_run = Puppet::Application.controlled_run do
48-
splay client_options.fetch :splay, Puppet[:splay]
48+
# splay may sleep for awhile!
49+
splay(client_options.fetch(:splay, Puppet[:splay]))
50+
51+
# waiting for certs may sleep for awhile depending on onetime, waitforcert and maxwaitforcert!
52+
# this needs to happen before forking so that if we fail to obtain certs and try to exit, then
53+
# we exit the main process and not the forked child.
54+
ssl_context = wait_for_certificates(client_options)
55+
4956
result = run_in_fork(should_fork) do
5057
with_client(client_options[:transaction_uuid], client_options[:job_id]) do |client|
5158
client_args = client_options.merge(:pluginsync => Puppet::Configurer.should_pluginsync?)
5259
begin
60+
# lock may sleep for awhile depending on waitforlock and maxwaitforlock!
5361
lock do
5462
# NOTE: Timeout is pretty heinous as the location in which it
5563
# throws an error is entirely unpredictable, which means that
5664
# it can interrupt code blocks that perform cleanup or enforce
5765
# sanity. The only thing a Puppet agent should do after this
5866
# error is thrown is die with as much dignity as possible.
5967
Timeout.timeout(Puppet[:runtimeout], RunTimeoutError) do
60-
client.run(client_args)
68+
Puppet.override(ssl_context: ssl_context) do
69+
client.run(client_args)
70+
end
6171
end
6272
end
6373
rescue Puppet::LockError
@@ -137,4 +147,10 @@ def with_client(transaction_uuid, job_id = nil)
137147
ensure
138148
@client = nil
139149
end
150+
151+
def wait_for_certificates(options)
152+
waitforcert = options[:waitforcert] || (Puppet[:onetime] ? 0 : Puppet[:waitforcert])
153+
sm = Puppet::SSL::StateMachine.new(waitforcert: waitforcert, onetime: Puppet[:onetime])
154+
sm.ensure_client_certificate
155+
end
140156
end

lib/puppet/application/agent.rb

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -383,15 +383,11 @@ def run_command
383383

384384
log_config if Puppet[:daemonize]
385385

386-
# run ssl state machine, waiting if needed
387-
ssl_context = wait_for_certificates
388-
389386
# Each application is responsible for pushing loaders onto the context.
390387
# Use the current environment that has already been established, though
391388
# it may change later during the configurer run.
392389
env = Puppet.lookup(:current_environment)
393-
Puppet.override(ssl_context: ssl_context,
394-
current_environment: env,
390+
Puppet.override(current_environment: env,
395391
loaders: Puppet::Pops::Loaders.new(env, true)) do
396392
if Puppet[:onetime]
397393
onetime(daemon)
@@ -434,7 +430,7 @@ def fingerprint
434430

435431
def onetime(daemon)
436432
begin
437-
exitstatus = daemon.agent.run({:job_id => options[:job_id], :start_time => options[:start_time]})
433+
exitstatus = daemon.agent.run({:job_id => options[:job_id], :start_time => options[:start_time], :waitforcert => options[:waitforcert]})
438434
rescue => detail
439435
Puppet.log_exception(detail)
440436
end
@@ -524,10 +520,4 @@ def daemonize_process_when(should_daemonize)
524520

525521
daemon
526522
end
527-
528-
def wait_for_certificates
529-
waitforcert = options[:waitforcert] || (Puppet[:onetime] ? 0 : Puppet[:waitforcert])
530-
sm = Puppet::SSL::StateMachine.new(waitforcert: waitforcert)
531-
sm.ensure_client_certificate
532-
end
533523
end

spec/integration/application/agent_spec.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -836,7 +836,6 @@ def copy_fixtures(sources, dest)
836836
instance.agent.run(splay: false)
837837
end
838838

839-
pending("PUP-11428: the second run should fail due to the revoked client cert")
840839
agent.command_line.args << '--verbose'
841840
expect {
842841
agent.run

spec/unit/agent_spec.rb

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ def controlled_run(&block)
3838
end
3939
end
4040
end
41+
42+
ssl_context = Puppet::SSL::SSLContext.new
43+
machine = instance_double("Puppet::SSL::StateMachine", ensure_client_certificate: ssl_context)
44+
allow(Puppet::SSL::StateMachine).to receive(:new).and_return(machine)
4145
end
4246

4347
after do
@@ -197,7 +201,7 @@ def controlled_run(&block)
197201
@agent.run
198202
end
199203

200-
it "should inform that a run is already in progres and try to run every X seconds if waitforlock is used" do
204+
it "should inform that a run is already in progress and try to run every X seconds if waitforlock is used" do
201205
# so the locked file exists
202206
allow(File).to receive(:file?).and_return(true)
203207
# so we don't have to wait again for the run to exit (default maxwaitforcert is 60)
@@ -226,7 +230,7 @@ def controlled_run(&block)
226230
@agent.run
227231
end
228232
end
229-
233+
230234
describe "when should_fork is true", :if => Puppet.features.posix? && RUBY_PLATFORM != 'java' do
231235
before do
232236
@agent = Puppet::Agent.new(AgentTestClient, true)

0 commit comments

Comments
 (0)