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
26 changes: 3 additions & 23 deletions acceptance/config/el6/setup/git/pre-suite/04_ValidateSignCert.rb
Original file line number Diff line number Diff line change
@@ -1,26 +1,6 @@
test_name "Validate Sign Cert"

hostname = on(master, 'facter hostname').stdout.strip
fqdn = on(master, 'facter fqdn').stdout.strip
require 'puppet/acceptance/common_utils'
extend Puppet::Acceptance::CAUtils

step "Clear SSL on all hosts"
hosts.each { |host| on host, "rm -rf #{host["puppetpath"]}/ssl" }

step "Master: Start Puppet Master" do
with_puppet_running_on(master, :main => { :dns_alt_names => "puppet,#{hostname},#{fqdn}", :verbose => true, :daemonize => true }) do

hosts.each do |host|
next if host['roles'].include? 'master'

step "Agents: Run agent --test first time to gen CSR"
on host, puppet("agent --test --server #{master}"), :acceptable_exit_codes => [1]
end

# Sign all waiting certs
step "Master: sign all certs"
on master, puppet("cert --sign --all"), :acceptable_exit_codes => [0,24]

step "Agents: Run agent --test second time to obtain signed cert"
on agents, puppet("agent --test --server #{master}"), :acceptable_exit_codes => [0,2]
end
end
initialize_ssl
Original file line number Diff line number Diff line change
@@ -1,29 +1,6 @@
test_name "Validate Sign Cert"

hostname = on(master, 'facter hostname').stdout.strip
fqdn = on(master, 'facter fqdn').stdout.strip
require 'puppet/acceptance/common_utils'
extend Puppet::Acceptance::CAUtils

step "Clear SSL on all hosts"
hosts.each do |host|
ssldir = on(host, puppet('agent --configprint ssldir')).stdout.chomp
on(host, "rm -rf '#{ssldir}'")
end

step "Master: Start Puppet Master" do
with_puppet_running_on(master, :main => { :dns_alt_names => "puppet,#{hostname},#{fqdn}", :verbose => true, :daemonize => true }) do

hosts.each do |host|
next if host['roles'].include? 'master'

step "Agents: Run agent --test first time to gen CSR"
on host, puppet("agent --test --server #{master}"), :acceptable_exit_codes => [1]
end

# Sign all waiting certs
step "Master: sign all certs"
on master, puppet("cert --sign --all"), :acceptable_exit_codes => [0,24]

step "Agents: Run agent --test second time to obtain signed cert"
on agents, puppet("agent --test --server #{master}"), :acceptable_exit_codes => [0,2]
end
end
initialize_ssl
85 changes: 85 additions & 0 deletions acceptance/lib/puppet/acceptance/common_utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,90 @@ def setup(agent, o={})
package {'cron': name=> $cron, ensure=>present, }])
end
end

module CAUtils

def initialize_ssl
hostname = on(master, 'facter hostname').stdout.strip
fqdn = on(master, 'facter fqdn').stdout.strip

step "Clear SSL on all hosts"
hosts.each do |host|
ssldir = on(host, puppet('agent --configprint ssldir')).stdout.chomp
on(host, "rm -rf '#{ssldir}'")
end

step "Master: Start Puppet Master" do
with_puppet_running_on(master, :main => { :dns_alt_names => "puppet,#{hostname},#{fqdn}", :verbose => true, :daemonize => true }) do

hosts.each do |host|
next if host['roles'].include? 'master'

step "Agents: Run agent --test first time to gen CSR"
on host, puppet("agent --test --server #{master}"), :acceptable_exit_codes => [1]
end

# Sign all waiting certs
step "Master: sign all certs"
on master, puppet("cert --sign --all"), :acceptable_exit_codes => [0,24]

step "Agents: Run agent --test second time to obtain signed cert"
on agents, puppet("agent --test --server #{master}"), :acceptable_exit_codes => [0,2]
end
end
end

def clean_cert(host, cn, check = true)
on(host, puppet('cert', 'clean', cn), :acceptable_exit_codes => check ? [0] : [0, 24])
if check
assert_match(/remov.*Certificate.*#{cn}/i, stdout, "Should see a log message that certificate request was removed.")
on(host, puppet('cert', 'list', '--all'))
assert_no_match(/#{cn}/, stdout, "Should not see certificate in list anymore.")
end
end

def clear_agent_ssl
return if master.is_pe?
step "All: Clear agent only ssl settings (do not clear master)"
hosts.each do |host|
next if host == master
ssldir = on(host, puppet('agent --configprint ssldir')).stdout.chomp
on( host, host_command("rm -rf '#{ssldir}'") )
end
end

def reset_agent_ssl(resign = true)
return if master.is_pe?
clear_agent_ssl

hostname = master.execute('facter hostname')
fqdn = master.execute('facter fqdn')

step "Master: Ensure the master bootstraps CA"
with_puppet_running_on(master,
:master => {
:dns_alt_names => "puppet,#{hostname},#{fqdn}",
:autosign => true,
}
) do

agents.each do |agent|
next if agent == master

step "Clear old agent certificate from master" do
agent_cn = on(agent, puppet('agent --configprint certname')).stdout.chomp
clean_cert(master, agent_cn, false) if agent_cn
end
if resign
step "Agents: Run agent --test once to obtained auto-signed cert" do
on agent, puppet('agent', "--test --server #{master}"), :acceptable_exit_codes => [0,2]
end
end
end

end
end

end
end
end
47 changes: 47 additions & 0 deletions acceptance/tests/ssl/autosign_command.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
require 'puppet/acceptance/common_utils'
extend Puppet::Acceptance::CAUtils

test_name "autosign_command behavior (#7244)" do

def assert_key_generated(name)
assert_match(/Creating a new SSL key for #{name}/, stdout, "Expected agent to create a new SSL key for autosigning")
end

testdir = master.tmpdir('autosign_command')

teardown do
step "Remove autosign configuration"
on(master, host_command("rm -rf '#{testdir}'") )
reset_agent_ssl
end

reset_agent_ssl(false)

step "Step 1: ensure autosign_command can approve CSRs"

master_opts = {'master' => {'autosign' => 'false', 'autosign_command' => '/bin/true'}}
with_puppet_running_on(master, master_opts) do
agents.each do |agent|
next if agent == master

on(agent, puppet("agent --test --server #{master} --waitforcert 0"))
assert_key_generated(agent)
assert_match(/Caching certificate for #{agent}/, stdout, "Expected certificate to be autosigned")
end
end

reset_agent_ssl(false)

step "Step 2: ensure autosign_command can reject CSRs"

master_opts = {'master' => {'autosign' => 'false', 'autosign_command' => '/bin/false'}}
with_puppet_running_on(master, master_opts) do
agents.each do |agent|
next if agent == master

on(agent, puppet("agent --test --server #{master} --waitforcert 0"), :acceptable_exit_codes => [1])
assert_key_generated(agent)
assert_match(/no certificate found/, stdout, "Expected certificate to not be autosigned")
end
end
end
52 changes: 3 additions & 49 deletions acceptance/tests/ssl/puppet_cert_generate_and_autosign.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
require 'puppet/acceptance/common_utils'
extend Puppet::Acceptance::CAUtils

test_name "Puppet cert generate behavior (#6112)" do

# This acceptance test documents the behavior of `puppet cert generate` calls
Expand Down Expand Up @@ -51,15 +54,6 @@
clean_cert(master, test_cn, false)
end

def clean_cert(host, cn, check = true)
on(host, puppet('cert', 'clean', cn), :acceptable_exit_codes => check ? [0] : [0, 24])
if check
assert_match(/remov.*Certificate.*#{cn}/i, stdout, "Should see a log message that certificate request was removed.")
on(host, puppet('cert', 'list', '--all'))
assert_no_match(/#{cn}/, stdout, "Should not see certificate in list anymore.")
end
end

def generate_and_clean_cert(host, cn, autosign)
on(host, puppet('cert', 'generate', cn, '--autosign', autosign))
assert_no_match(/Could not find certificate request for.*cert\.test/i, stderr, "Should not see an error message for a missing certificate request.")
Expand All @@ -85,46 +79,6 @@ def host_is_master?(host)
host['roles'].include?('master')
end

def clear_agent_ssl
return if master.is_pe?
step "All: Clear agent only ssl settings (do not clear master)"
hosts.each do |host|
next if host == master
ssldir = on(host, puppet('agent --configprint ssldir')).stdout.chomp
on( host, host_command("rm -rf '#{ssldir}'") )
end
end

def reset_agent_ssl
return if master.is_pe?
clear_agent_ssl

hostname = master.execute('facter hostname')
fqdn = master.execute('facter fqdn')

step "Master: Ensure the master bootstraps CA"
with_puppet_running_on(master,
:master => {
:dns_alt_names => "puppet,#{hostname},#{fqdn}",
:autosign => true,
}
) do

agents.each do |agent|
next if agent == master

step "Clear old agent certificate from master" do
agent_cn = on(agent, puppet('agent --configprint certname')).stdout.chomp
clean_cert(master, agent_cn, false) if agent_cn
end
step "Agents: Run agent --test once to obtained auto-signed cert" do
on agent, puppet('agent', "--test --server #{master}"), :acceptable_exit_codes => [0,2]
end
end

end
end

################
# Cases 1 and 2:

Expand Down
32 changes: 30 additions & 2 deletions lib/puppet/defaults.rb
Original file line number Diff line number Diff line change
Expand Up @@ -714,8 +714,36 @@ def self.default_diffargs
:mode => 0644,
:desc => "Whether to enable autosign. Valid values are true (which
autosigns any key request, and is a very bad idea), false (which
never autosigns any key request), and the path to a file, which
uses that configuration file to determine which keys to sign."},
disables autosigning certificates based on an autosign file), and the
path to a file, which uses that configuration file to determine which
keys to sign.",
:hook => proc do |value|
unless [false, 'false', true, 'true'].include?(value) or Puppet::Util.absolute_path?(value)
raise ArgumentError, "The autosign parameter must be 'true'/'false' or an absolute path"
end
end
},
:autosign_command => {
:default => nil,
:type => :string,
:desc => "Command to run which determines whether the certificate
request should be automatically signed. The script is called
on each request and is passed the certificate name as an
argument and the contents of the CSR in PEM format on stdin. It should
exit with a status of 0 if the cert should be signed, 1 if the cert
should not be signed, and any other value if an error occured while
running the command.

The 'autosign' parameter has precedence over this one. If 'autosign'
determines a cert should be signed, 'autosign_command' will never be
called. However if 'autosign' does not validate a request, it will
pass through to 'autosign_command'.",
:hook => proc do |value|
if value and !Puppet::Util.absolute_path?(value)
raise ArgumentError, "The autosign_command parameter must be an absolute path"
end
end,
},
:allow_duplicate_certs => {
:default => false,
:type => :boolean,
Expand Down
Loading