summaryrefslogtreecommitdiff
path: root/code/environments/production/modules/certregen/spec/acceptance
diff options
context:
space:
mode:
Diffstat (limited to 'code/environments/production/modules/certregen/spec/acceptance')
-rw-r--r--code/environments/production/modules/certregen/spec/acceptance/ca_spec.rb60
-rw-r--r--code/environments/production/modules/certregen/spec/acceptance/healthcheck_spec.rb135
-rw-r--r--code/environments/production/modules/certregen/spec/acceptance/help_spec.rb39
-rw-r--r--code/environments/production/modules/certregen/spec/acceptance/helpers.rb83
-rw-r--r--code/environments/production/modules/certregen/spec/acceptance/nodesets/centos-7-x64.yml10
-rw-r--r--code/environments/production/modules/certregen/spec/acceptance/nodesets/debian-8-x64.yml10
-rw-r--r--code/environments/production/modules/certregen/spec/acceptance/nodesets/default.yml10
-rw-r--r--code/environments/production/modules/certregen/spec/acceptance/nodesets/docker/centos-7.yml12
-rw-r--r--code/environments/production/modules/certregen/spec/acceptance/nodesets/docker/debian-8.yml11
-rw-r--r--code/environments/production/modules/certregen/spec/acceptance/nodesets/docker/ubuntu-14.04.yml12
-rw-r--r--code/environments/production/modules/certregen/spec/acceptance/workflow_regen_after_expire_spec.rb105
-rw-r--r--code/environments/production/modules/certregen/spec/acceptance/workflow_regen_before_expire_spec.rb77
12 files changed, 564 insertions, 0 deletions
diff --git a/code/environments/production/modules/certregen/spec/acceptance/ca_spec.rb b/code/environments/production/modules/certregen/spec/acceptance/ca_spec.rb
new file mode 100644
index 0000000..c9df863
--- /dev/null
+++ b/code/environments/production/modules/certregen/spec/acceptance/ca_spec.rb
@@ -0,0 +1,60 @@
+require 'spec_helper_acceptance'
+
+describe "puppet certregen ca" do
+ if hosts_with_role(hosts, 'master').length>0 then
+ context 'regen ca on master' do
+
+ context 'C99811 - without --ca_serial' do
+ it 'should provide ca serial id via stderr' do
+ on(master, puppet("certregen ca"), :acceptable_exit_codes => 1) do |result|
+ expect(result.stderr).to match(/rerun this command with --ca_serial ([0-9a-fA-F]+)/)
+ end
+ end
+ end
+
+ context "C99815 - 'puppet certregen ca --ca_serial'" do
+ before(:all) do
+ serial = get_ca_serial_id_on(master)
+ today = get_time_on(master)
+ @future = today + 5*YEAR
+ @regen_result = on(master, "puppet certregen ca --ca_serial #{serial}")
+ end
+ it 'should output the updated CA expiration date' do
+ expect(@regen_result.stdout).to match( /CA expiration is now #{@future.utc.strftime('%Y-%m-%d')}/ )
+ end
+ it 'should update CA cert enddate' do
+ enddate = get_ca_enddate_time_on(master)
+ expect(enddate - @future).to be < 10.0
+ end
+ end
+
+ context 'C99816 - invalid ca_serial id' do
+ it 'should yield an error' do
+ on(master, puppet("certregen ca --ca_serial FD"), :acceptable_exit_codes => 1) do |result|
+ expect(result.stderr).to match(/The serial number of the current CA certificate .* does not match the serial number given on the command line \(FD\)/)
+ expect(result.stderr).to match(/rerun this command with --ca_serial ([0-9a-fA-F]+)/)
+ end
+ end
+ end
+
+ context "C99817 - 'puppet certregen ca --ca_serial --ca_ttl 1d'" do
+ before(:all) do
+ today = get_time_on(master)
+ @tomorrow = today + 1*DAY
+
+ serial = get_ca_serial_id_on(master)
+ @regen_result = on(master, "puppet certregen ca --ca_serial #{serial} --ca_ttl 1d")
+ end
+
+ it 'should output the updated CA expiration date' do
+ expect(@regen_result.stdout).to match( /CA expiration is now #{@tomorrow.utc.strftime('%Y-%m-%d')}/ )
+ end
+ it 'should update CA cert enddate' do
+ enddate = get_ca_enddate_time_on(master)
+ expect(enddate - @tomorrow).to be < 10.0
+ end
+ end
+
+ end
+ end
+end
diff --git a/code/environments/production/modules/certregen/spec/acceptance/healthcheck_spec.rb b/code/environments/production/modules/certregen/spec/acceptance/healthcheck_spec.rb
new file mode 100644
index 0000000..387810d
--- /dev/null
+++ b/code/environments/production/modules/certregen/spec/acceptance/healthcheck_spec.rb
@@ -0,0 +1,135 @@
+require 'spec_helper_acceptance'
+require 'yaml'
+require 'json'
+
+describe "puppet certregen healthcheck" do
+ if hosts_with_role(hosts, 'master').length>0 then
+
+ context 'C99803 - cert with more than 10 percent of life' do
+ before(:all) do
+ serial = get_ca_serial_id_on(master)
+ on(master, "puppet certregen ca --ca_serial #{serial}")
+ end
+ it 'should not produce a health warning' do
+ on(master, "puppet certregen healthcheck") do |result|
+ expect(result.stderr).to be_empty
+ expect(result.stdout).to match(/No certificates are approaching expiration/)
+ end
+ end
+ end
+
+ context 'C99804 - cert with less than 10 percent of life' do
+ before(:all) do
+ serial = get_ca_serial_id_on(master)
+ # patch puppet to defeat copywrite date check when generating historical CA
+ patch_puppet_date_check_on(master)
+ @today = get_time_on(master)
+ # set back the clock in order to create a CA that will be approaching its EOL
+ past = @today - (5*YEAR - 20*DAY)
+ on(master, "date #{past.strftime('%m%d%H%M%Y')}")
+ # create old CA
+ on(master, "puppet certregen ca --ca_serial #{serial}")
+ # update to current time
+ on(master, "date #{@today.strftime('%m%d%H%M%Y')}")
+ # revert patch to defeat copywrite date check
+ patch_puppet_date_check_on(master, 'reverse')
+ end
+
+ it 'system should have current date' do
+ today = get_time_on(master)
+ expect(today.utc.strftime('%Y-%m-%d')).to eq @today.utc.strftime('%Y-%m-%d')
+ end
+
+ it 'should warn about pending expiration' do
+ enddate = get_ca_enddate_time_on(master)
+ on(master, "puppet certregen healthcheck") do |result|
+ expect(result.stdout).to match(/Status:\s+expiring/)
+ expect(result.stdout).to match(/Expiration date:\s+#{enddate.utc.strftime('%Y-%m-%d')}/)
+ end
+ end
+
+ end
+
+ context 'C99805 - expired cert' do
+ before(:all) do
+ serial = get_ca_serial_id_on(master)
+ on(master, "puppet certregen ca --ca_serial #{serial} --ca_ttl 1s")
+ sleep 2
+ end
+ it 'should produce a health warning' do
+ on(master, "puppet certregen healthcheck") do |result|
+ expect(result.stdout.gsub("\n", " ")).to match(/ca.*Status: expired/)
+ end
+ end
+ end
+
+ context '--all flag' do
+
+ context 'C99806 --all' do
+ before(:all) do
+ on(master, puppet("cert list --all")) do |result|
+ @certs = result.stdout.scan(/\) ([A-F0-9:]+) /)
+ end
+ @result = on(master, "puppet certregen healthcheck --all")
+ end
+ it 'should contain expiration data for ca cert' do
+ expect(@result.stdout).to match(/"ca".*\n\s*Status:\s*[Ee]xpir/)
+ end
+ it 'should contain expiration data for all node certs' do
+ @certs.each do |cert|
+ expect(@result.stdout).to include cert[0]
+ end
+ end
+ end
+
+ context '--render-as flag' do
+
+ context 'C99808 - --render-as yaml' do
+ before(:all) do
+ on(master, puppet("cert list --all")) do |result|
+ @certs = result.stdout.scan(/\) ([A-F0-9:]+) /)
+ end
+ @result = on(master, "puppet certregen healthcheck --all --render-as yaml")
+ @yaml = YAML.load(@result.stdout)
+ end
+ it 'should return valid yaml' do
+ expect(YAML.parse(@result.stdout)).to be_instance_of(Psych::Nodes::Document)
+ end
+ it 'should contain expiration data for ca cert' do
+ ca = @yaml.find { |record| record[:name] == 'ca' }
+ expect(ca).not_to be nil
+ expect(ca[:expiry][:status]).to eq(:expired)
+ end
+ it 'should contain expiration data for all node certs' do
+ @certs.each do |cert|
+ expect(@yaml.find { |record| record[:digest] =~ /#{cert[0]}/ }).not_to be nil
+ end
+ end
+ end
+
+ context 'C99809 - --render-as json prints valid json containing expiration data' do
+ before(:all) do
+ on(master, puppet("cert list --all")) do |result|
+ @certs = result.stdout.scan(/\) ([A-F0-9:]+) /)
+ end
+ @json = JSON.parse(on(master, "puppet certregen healthcheck --all --render-as json").stdout)
+ end
+ it 'should return valid json' do
+ expect(@json).not_to be nil
+ end
+ it 'should contain expiration data for ca cert' do
+ ca = @json.find { |record| record['name'] == 'ca' }
+ expect(ca).not_to be nil
+ end
+ it 'should contain expiration data for all node certs' do
+ @certs.each do |cert|
+ expect(@json.find { |record| record['digest'] =~ /#{cert[0]}/ }).not_to be nil
+ end
+ end
+ end
+
+ end
+ end
+
+ end
+end
diff --git a/code/environments/production/modules/certregen/spec/acceptance/help_spec.rb b/code/environments/production/modules/certregen/spec/acceptance/help_spec.rb
new file mode 100644
index 0000000..7d1e83d
--- /dev/null
+++ b/code/environments/production/modules/certregen/spec/acceptance/help_spec.rb
@@ -0,0 +1,39 @@
+require 'spec_helper_acceptance'
+
+describe "pupper help certregen" do
+ # NOTE: MODULES-4733 certregen is not currently compatible with ruby < 1.9
+ ruby_ver = 0
+ on(default, 'ruby --version') do |result|
+ m = /\d+\.\d+\.\d+/.match(result.stdout)
+ ruby_ver = m[0] if m
+ end
+ unless version_is_less(ruby_ver, '1.9') then
+ describe "C98923 - Verify that 'puppet certregen --help' prints help text" do
+ # NOTE: `--help` only works on puppet version 4+
+ if version_is_less( '3.9.9', on(default, puppet('--version')).stdout)
+ describe command("puppet certregen --help") do
+ its(:stdout) { should match( /.*USAGE: puppet certregen <action>.*/ ) }
+ its(:stdout) { should match( /.*See 'puppet man certregen' or 'man puppet-certregen' for full help.*/ ) }
+ end
+ end
+ end
+ describe "C99812 - Verify that 'puppet help certregen' prints help text" do
+ describe command("puppet help certregen") do
+ its(:stdout) { should match( /.*USAGE: puppet certregen <action>.*/ ) }
+ its(:stdout) { should match( /.*See 'puppet man certregen' or 'man puppet-certregen' for full help.*/ ) }
+ end
+ end
+ describe "C99813 - Verify that 'puppet help certregen healthcheck' prints help text for healthcheck subcommand" do
+ describe command("puppet help certregen healthcheck") do
+ its(:stdout) { should match( /.*USAGE: puppet certregen healthcheck .*/ ) }
+ its(:stdout) { should match( /.*See 'puppet man certregen' or 'man puppet-certregen' for full help.*/ ) }
+ end
+ end
+ describe "C99814 - Verify that 'puppet help certregen ca' prints help text for ca subcommand" do
+ describe command("puppet help certregen ca") do
+ its(:stdout) { should match( /.*USAGE: puppet certregen ca .*/ ) }
+ its(:stdout) { should match( /.*See 'puppet man certregen' or 'man puppet-certregen' for full help.*/ ) }
+ end
+ end
+ end
+end
diff --git a/code/environments/production/modules/certregen/spec/acceptance/helpers.rb b/code/environments/production/modules/certregen/spec/acceptance/helpers.rb
new file mode 100644
index 0000000..dba7d81
--- /dev/null
+++ b/code/environments/production/modules/certregen/spec/acceptance/helpers.rb
@@ -0,0 +1,83 @@
+require 'openssl'
+
+# Time constants in seconds
+HOUR = 60 * 60
+DAY = 24 * HOUR
+YEAR = 365 * DAY
+
+# Retrieve CA Certificate from the given host
+#
+# @param [Host] host single Beaker::Host
+#
+# @return [OpenSSL::X509::Certificate] Certificate object
+def get_ca_cert_on(host)
+ if host[:roles].include? 'master' then
+ dir = on(host, puppet('config', 'print', 'cadir')).stdout.chomp
+ ca_path = "#{dir}/ca_crt.pem"
+ else
+ dir = on(host, puppet('config', 'print', 'certdir')).stdout.chomp
+ ca_path = "#{dir}/ca.pem"
+ end
+ on(host, "cat #{ca_path}") do |result|
+ cert = OpenSSL::X509::Certificate.new(result.stdout)
+ return cert
+ end
+end
+
+# Execute `date` command on host with optional arguments
+# and get back a Ruby Time object
+#
+# @param [Host] host single Beaker::Host to run the command on
+# @param [Array<String>] args Array of arguments to be appended to the
+# `date` command
+# @return [Time] Ruby Time object
+def get_time_on(host, args = [])
+ arg_string = args.join(' ')
+ date = on(host, "date #{arg_string}").stdout.chomp
+ return Time.parse(date)
+end
+
+# Retrieve the CA enddate on a given host as a Ruby time object
+#
+# @param [Host] host single Beaker::Host to get CA enddate from
+#
+# @return [Time] Ruby Time object, or nil if error
+def get_ca_enddate_time_on(host)
+ cert = get_ca_cert_on(host)
+ return cert.not_after if cert
+ return nil
+end
+
+# Retrieve the current ca_serial value for `puppet certgen ca` on a given host
+#
+# @param [Host] host single Beaker::Host to get ca_serial from
+#
+# @return [String] ca_serial in hexadecimal, or nil if error
+def get_ca_serial_id_on(host)
+ cert = get_ca_cert_on(host)
+ return cert.serial.to_s(16) if cert
+ return nil
+end
+
+# Patch puppet to get around the date check validation.
+#
+# This method is used to patch puppet in order to prevent it from failing to
+# create a CA if the system clock is turned back in time by years. The same
+# method is used to reverse the patch with the `reverse` parameter.
+#
+# @param [Host] host single Beaker::Host to run the command on
+# @param [String] reverse causes the patch to be reversed
+def patch_puppet_date_check_on(host, reverse=nil)
+ reverse = '--reverse' if reverse
+ apply_manifest_on(host, 'package { "patch": ensure => present}')
+ interface_documentation_file = "/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/interface/documentation.rb"
+ patch =<<EOF
+305c305
+< raise ArgumentError, "copyright with a year \#{fault} is very strange; did you accidentally add or subtract two years?"
+---
+> #raise ArgumentError, "copyright with a year \#{fault} is very strange; did you accidentally add or subtract two years?"
+EOF
+ patch_file = host.tmpfile('iface_doc_patch')
+ create_remote_file(host, patch_file, patch)
+ on(host, "patch #{reverse} #{interface_documentation_file} < #{patch_file}", :acceptable_exit_codes => [0,1])
+end
diff --git a/code/environments/production/modules/certregen/spec/acceptance/nodesets/centos-7-x64.yml b/code/environments/production/modules/certregen/spec/acceptance/nodesets/centos-7-x64.yml
new file mode 100644
index 0000000..5eebdef
--- /dev/null
+++ b/code/environments/production/modules/certregen/spec/acceptance/nodesets/centos-7-x64.yml
@@ -0,0 +1,10 @@
+HOSTS:
+ centos-7-x64:
+ roles:
+ - agent
+ - default
+ platform: el-7-x86_64
+ hypervisor: vagrant
+ box: puppetlabs/centos-7.2-64-nocm
+CONFIG:
+ type: foss
diff --git a/code/environments/production/modules/certregen/spec/acceptance/nodesets/debian-8-x64.yml b/code/environments/production/modules/certregen/spec/acceptance/nodesets/debian-8-x64.yml
new file mode 100644
index 0000000..fef6e63
--- /dev/null
+++ b/code/environments/production/modules/certregen/spec/acceptance/nodesets/debian-8-x64.yml
@@ -0,0 +1,10 @@
+HOSTS:
+ debian-8-x64:
+ roles:
+ - agent
+ - default
+ platform: debian-8-amd64
+ hypervisor: vagrant
+ box: puppetlabs/debian-8.2-64-nocm
+CONFIG:
+ type: foss
diff --git a/code/environments/production/modules/certregen/spec/acceptance/nodesets/default.yml b/code/environments/production/modules/certregen/spec/acceptance/nodesets/default.yml
new file mode 100644
index 0000000..dba339c
--- /dev/null
+++ b/code/environments/production/modules/certregen/spec/acceptance/nodesets/default.yml
@@ -0,0 +1,10 @@
+HOSTS:
+ ubuntu-1404-x64:
+ roles:
+ - agent
+ - default
+ platform: ubuntu-14.04-amd64
+ hypervisor: vagrant
+ box: puppetlabs/ubuntu-14.04-64-nocm
+CONFIG:
+ type: foss
diff --git a/code/environments/production/modules/certregen/spec/acceptance/nodesets/docker/centos-7.yml b/code/environments/production/modules/certregen/spec/acceptance/nodesets/docker/centos-7.yml
new file mode 100644
index 0000000..a3333aa
--- /dev/null
+++ b/code/environments/production/modules/certregen/spec/acceptance/nodesets/docker/centos-7.yml
@@ -0,0 +1,12 @@
+HOSTS:
+ centos-7-x64:
+ platform: el-7-x86_64
+ hypervisor: docker
+ image: centos:7
+ docker_preserve_image: true
+ docker_cmd: '["/usr/sbin/init"]'
+ # install various tools required to get the image up to usable levels
+ docker_image_commands:
+ - 'yum install -y crontabs tar wget openssl sysvinit-tools iproute which initscripts'
+CONFIG:
+ trace_limit: 200
diff --git a/code/environments/production/modules/certregen/spec/acceptance/nodesets/docker/debian-8.yml b/code/environments/production/modules/certregen/spec/acceptance/nodesets/docker/debian-8.yml
new file mode 100644
index 0000000..df5c319
--- /dev/null
+++ b/code/environments/production/modules/certregen/spec/acceptance/nodesets/docker/debian-8.yml
@@ -0,0 +1,11 @@
+HOSTS:
+ debian-8-x64:
+ platform: debian-8-amd64
+ hypervisor: docker
+ image: debian:8
+ docker_preserve_image: true
+ docker_cmd: '["/sbin/init"]'
+ docker_image_commands:
+ - 'apt-get update && apt-get install -y net-tools wget locales strace lsof && echo "en_US.UTF-8 UTF-8" > /etc/locale.gen && locale-gen'
+CONFIG:
+ trace_limit: 200
diff --git a/code/environments/production/modules/certregen/spec/acceptance/nodesets/docker/ubuntu-14.04.yml b/code/environments/production/modules/certregen/spec/acceptance/nodesets/docker/ubuntu-14.04.yml
new file mode 100644
index 0000000..b1efa58
--- /dev/null
+++ b/code/environments/production/modules/certregen/spec/acceptance/nodesets/docker/ubuntu-14.04.yml
@@ -0,0 +1,12 @@
+HOSTS:
+ ubuntu-1404-x64:
+ platform: ubuntu-14.04-amd64
+ hypervisor: docker
+ image: ubuntu:14.04
+ docker_preserve_image: true
+ docker_cmd: '["/sbin/init"]'
+ docker_image_commands:
+ # ensure that upstart is booting correctly in the container
+ - 'rm /usr/sbin/policy-rc.d && rm /sbin/initctl && dpkg-divert --rename --remove /sbin/initctl && apt-get update && apt-get install -y net-tools wget && locale-gen en_US.UTF-8'
+CONFIG:
+ trace_limit: 200
diff --git a/code/environments/production/modules/certregen/spec/acceptance/workflow_regen_after_expire_spec.rb b/code/environments/production/modules/certregen/spec/acceptance/workflow_regen_after_expire_spec.rb
new file mode 100644
index 0000000..3ae0a9e
--- /dev/null
+++ b/code/environments/production/modules/certregen/spec/acceptance/workflow_regen_after_expire_spec.rb
@@ -0,0 +1,105 @@
+require 'spec_helper_acceptance'
+require 'json'
+
+# https://forge.puppet.com/puppetlabs/certregen#revive-a-ca-thats-already-expired
+describe "C99821 - workflow - regen CA after it expires" do
+ if find_install_type == 'pe' then
+ # This workflow only works with a master to manage the CA
+ # This workflow only works with a puppetdb instance to query hostnames from
+ context 'create CA to be expired and update agents' do
+ before(:all) do
+ ttl = 60
+ serial = get_ca_serial_id_on(master)
+ on(master, puppet("certregen ca --ca_serial #{serial} --ca_ttl #{ttl}s"))
+ start = Time.now
+ agents.each do |agent|
+ on(agent, puppet('agent -t'), :acceptable_exit_codes => [0,2])
+ end
+ finish = Time.now
+ elapsed_time = (finish - start).to_i
+ sleep (ttl - elapsed_time) if elapsed_time < ttl
+ sleep 1
+ end
+
+ it 'should warn that ca is expired' do
+ on(master, puppet("certregen healthcheck")) do |result|
+ expect(result.stdout).to match(/Status:\s+expired/)
+ end
+ end
+
+ context 'regenerate CA' do
+ before(:all) do
+ serial = get_ca_serial_id_on(master)
+ on(master, puppet("certregen ca --ca_serial #{serial}"))
+ end
+
+ it 'should update CA cert enddate' do
+ enddate = get_ca_enddate_time_on(master)
+ future = get_time_on(master, ['-d', "'5 years'"])
+ expect(future - enddate).to be <= (48*HOUR)
+ end
+
+ context 'automatically distribute new ca to linux hosts' do
+ before(:all) do
+ # distribute ssh key for root to agents
+ on(master, "ssh-keygen -t rsa -f $HOME/.ssh/id_rsa -P ''")
+ on(master, "cat $HOME/.ssh/id_rsa.pub") do |result|
+ key_array = result.stdout.split(' ')
+ fail_test('could not get ssh key from master') unless key_array.size > 1
+ @public_key = key_array[1]
+ end
+ agents.each do |agent|
+ unless agent['platform'] =~ /windows/
+ args = ['ensure=present',
+ "user='root'",
+ "type='rsa'",
+ "key='#{@public_key}'",
+ ]
+ on(agent, puppet_resource('ssh_authorized_key', master.hostname, args))
+ on(master, "ssh -o StrictHostKeyChecking=no #{agent.hostname} ls")
+ end
+ end
+ on(master, "/opt/puppetlabs/puppet/bin/gem install chloride")
+ result = on(master, puppet("certregen redistribute"))
+ @report = JSON.parse(result.stdout)
+ end
+
+ after(:all) do
+ on(master, "rm -f $HOME/.ssh/id_rsa $HOME/.ssh/id_rsa.pub", :acceptable_exit_codes => [0,1])
+ agents.each do |agent|
+ on(agent, puppet_resource('ssh_authorized_key', master.hostname, ['ensure=absent', "user='root'"]), :acceptable_exit_codes => [0,1])
+ end
+ end
+
+ it 'should emit a report in valid json' do
+ expect(@report).not_to be nil
+ end
+ it 'should emit a report with a succeeded key' do
+ expect(@report['succeeded']).not_to be nil
+ end
+ it 'should emit a report with a failed key' do
+ expect(@report['failed']).not_to be nil
+ end
+ it 'should report success on all linux agents' do
+ agents.each do |agent|
+ if agent['platform'] =~ /debian|ubuntu|cumulus|huaweios|el-|centos|fedora|redhat|oracle|scientific|eos|archlinux|sles/
+ expect(@report['succeeded']).to include agent.hostname
+ end
+ end
+ end
+ it 'should update CA cert on all linux agents' do
+ master_enddate = get_ca_enddate_time_on(master)
+ agents.each do |agent|
+ if agent['platform'] =~ /debian|ubuntu|cumulus|huaweios|el-|centos|fedora|redhat|oracle|scientific|eos|archlinux|sles/
+ on(agent, puppet('agent -t'), :acceptable_exit_codes => [0,2])
+ enddate = get_ca_enddate_time_on(agent)
+ expect(enddate).to eq master_enddate
+ end
+ end
+ end
+ end
+
+ end
+ end
+ end
+end
diff --git a/code/environments/production/modules/certregen/spec/acceptance/workflow_regen_before_expire_spec.rb b/code/environments/production/modules/certregen/spec/acceptance/workflow_regen_before_expire_spec.rb
new file mode 100644
index 0000000..bad7a84
--- /dev/null
+++ b/code/environments/production/modules/certregen/spec/acceptance/workflow_regen_before_expire_spec.rb
@@ -0,0 +1,77 @@
+require 'spec_helper_acceptance'
+
+# https://forge.puppet.com/puppetlabs/certregen#refresh-a-ca-thats-expiring-soon
+describe "C99818 - workflow - regen CA before it expires" do
+ if hosts_with_role(hosts, 'master').length>0 then
+ # This workflow only works with a master to manage the CA
+ context 'setting CA to expire soon' do
+ before(:all) do
+ serial = get_ca_serial_id_on(master)
+
+ # patch puppet to defeat copywrite date check when generating historical CA
+ patch_puppet_date_check_on(master)
+
+ # determine current time on master
+ @today = get_time_on(master)
+
+ # set back the clock in order to create a CA that will be approaching its EOL
+ past = @today - (5*YEAR - 20*DAY)
+ on(master, "date #{past.strftime('%m%d%H%M%Y')}")
+ # create old CA
+ on(master, puppet(" certregen ca --ca_serial #{serial}"))
+ # update to current time
+ on(master, "date #{@today.strftime('%m%d%H%M%Y')}")
+ end
+
+ it 'should have current date' do
+ today = get_time_on(master)
+ expect(today.utc.strftime('%Y-%m-%d')).to eq @today.utc.strftime('%Y-%m-%d')
+ end
+
+ it 'should warn about pending expiration' do
+ enddate = get_ca_enddate_time_on(master)
+ on(master, puppet("certregen healthcheck")) do |result|
+ expect(result.stdout).to match(/Status:\s+expiring/)
+ expect(result.stdout).to match(/Expiration date:\s+#{enddate.utc.strftime('%Y-%m-%d')}/)
+ end
+ end
+
+ context 'restoring previously patched puppet' do
+ before(:all) do
+ # revert patch to defeat copywrite date check
+ patch_puppet_date_check_on(master, 'reverse')
+ end
+
+ context 'regenerating CA prior to expiration' do
+ before(:all) do
+ serial = get_ca_serial_id_on(master)
+ on(master, puppet("certregen ca --ca_serial #{serial}"))
+ end
+ # validate time stamp
+ it 'should update CA cert enddate' do
+ enddate = get_ca_enddate_time_on(master)
+ future = get_time_on(master, ['-d', "'5 years'"])
+ expect(future - enddate).to be <= (48*HOUR)
+ end
+
+ context 'distribute new ca to linux hosts that have been classified with `certregen::client`' do
+ before(:all) do
+ create_remote_file(master, '/etc/puppetlabs/code/environments/production/manifests/ca.pp', 'include certregen::client')
+ on(master, 'chmod 755 /etc/puppetlabs/code/environments/production/manifests/ca.pp')
+ on(master, puppet('agent -t'), :acceptable_exit_codes => [0,2])
+ end
+ it 'should update CA cert on all linux agents' do
+ master_enddate = get_ca_enddate_time_on(master)
+ agents.each do |agent|
+ on(agent, puppet('agent -t'), :acceptable_exit_codes => [0,2])
+ enddate = get_ca_enddate_time_on(agent)
+ expect(enddate).to eq master_enddate
+ end
+ end
+ end
+
+ end
+ end
+ end
+ end
+end