summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPete Higgins <pete@peterhiggins.org>2020-12-29 11:59:35 -0800
committerPete Higgins <pete@peterhiggins.org>2020-12-29 17:19:47 -0800
commitedf10017baeaa0cd27cad76f82e6936efe32fe4c (patch)
treee19ac8fa0ddfdbb06a9e87d639c9c3a7138a33ad
parentc46440d349b2328dab9a868559dcb72ffb0b426d (diff)
downloadchef-edf10017baeaa0cd27cad76f82e6936efe32fe4c.tar.gz
Consolidate tests to reduce runtime on CI.
Signed-off-by: Pete Higgins <pete@peterhiggins.org>
-rw-r--r--spec/functional/resource/windows_certificate_spec.rb588
1 files changed, 204 insertions, 384 deletions
diff --git a/spec/functional/resource/windows_certificate_spec.rb b/spec/functional/resource/windows_certificate_spec.rb
index 20d444dd59..b5d0484e0c 100644
--- a/spec/functional/resource/windows_certificate_spec.rb
+++ b/spec/functional/resource/windows_certificate_spec.rb
@@ -19,478 +19,298 @@ require "spec_helper"
require "chef/mixin/powershell_exec"
require "chef/resource/windows_certificate"
-module WindowsCertificateHelper
+describe Chef::Resource::WindowsCertificate, :windows_only do
include Chef::Mixin::PowershellExec
- def create_store(store)
- path = "Cert:\\LocalMachine\\" + store
- command = <<~EOC
- New-Item -Path #{path}
+ def create_store
+ powershell_exec <<~EOC
+ New-Item -Path Cert:\\LocalMachine\\#{store}
EOC
- powershell_exec(command)
end
- def cleanup(store)
- path = "Cert:\\LocalMachine\\" + store
- command = <<~EOC
- Remove-Item -Path #{path} -Recurse
+ def delete_store
+ powershell_exec <<~EOC
+ Remove-Item -Path Cert:\\LocalMachine\\#{store} -Recurse
EOC
- powershell_exec(command)
end
- def no_of_certificates
- path = "Cert:\\LocalMachine\\" + store
- # Seems weird that we have to call dir twice right?
- # The powershell pki module cache the last dir in module session state
- # Issuing dir with a different arg (-Force) seems to refresh that state.
- command = <<~EOC
- dir #{path} -Force | Out-Null
- (dir #{path} | measure).Count
+ def certificate_count
+ powershell_exec(<<~EOC).result.to_i
+ (Get-ChildItem -Force -Path Cert:\\LocalMachine\\#{store} | measure).Count
EOC
- powershell_exec(command).result.to_i
end
-end
-describe Chef::Resource::WindowsCertificate, :windows_only do
- include WindowsCertificateHelper
-
- let(:stdout) { StringIO.new }
- let(:username) { "ChefFunctionalTest" }
- let(:node) { Chef::Node.new }
- let(:events) { Chef::EventDispatch::Dispatcher.new }
- let(:run_context) { Chef::RunContext.new(node, {}, events) }
- let(:new_resource) { Chef::Resource::WindowsCertificate.new(username, run_context) }
let(:password) { "P@ssw0rd!" }
let(:store) { "Chef-Functional-Test" }
- let(:certificate_path) { File.expand_path(File.join(CHEF_SPEC_DATA, "windows_certificates")) }
- let(:cer_path) { File.join(certificate_path, "test.cer") }
- let(:base64_path) { File.join(certificate_path, "base64_test.cer") }
- let(:pem_path) { File.join(certificate_path, "test.pem") }
- let(:p7b_path) { File.join(certificate_path, "test.p7b") }
- let(:pfx_path) { File.join(certificate_path, "test.pfx") }
- let(:out_path) { File.join(certificate_path, "testout.pem") }
+ let(:cer_path) { File.join(CHEF_SPEC_DATA, "windows_certificates", "test.cer") }
+ let(:base64_path) { File.join(CHEF_SPEC_DATA, "windows_certificates", "base64_test.cer") }
+ let(:pem_path) { File.join(CHEF_SPEC_DATA, "windows_certificates", "test.pem") }
+ let(:p7b_path) { File.join(CHEF_SPEC_DATA, "windows_certificates", "test.p7b") }
+ let(:pfx_path) { File.join(CHEF_SPEC_DATA, "windows_certificates", "test.pfx") }
let(:tests_thumbprint) { "e45a4a7ff731e143cf20b8bfb9c7c4edd5238bb3" }
- let(:other_cer_path) { File.join(certificate_path, "othertest.cer") }
+ let(:other_cer_path) { File.join(CHEF_SPEC_DATA, "windows_certificates", "othertest.cer") }
let(:others_thumbprint) { "6eae1deefaf59daf1a97c9ceeff39c98b3da38cb" }
let(:p7b_thumbprint) { "f867e25b928061318ed2c36ca517681774b06260" }
let(:p7b_nested_thumbprint) { "dc395eae6be5b69951b8b6e1090cfc33df30d2cd" }
+ let(:resource) do
+ run_context = Chef::RunContext.new(Chef::Node.new, {}, Chef::EventDispatch::Dispatcher.new)
+ Chef::Resource::WindowsCertificate.new("ChefFunctionalTest", run_context).tap do |r|
+ r.store_name = store
+ end
+ end
+
before do
- opts = { store_name: store }
- key = :store_name
- to_be = ["TRUSTEDPUBLISHER", "TrustedPublisher", "CLIENTAUTHISSUER",
- "REMOTE DESKTOP", "ROOT", "TRUSTEDDEVICES", "WEBHOSTING",
- "CA", "AUTHROOT", "TRUSTEDPEOPLE", "MY", "SMARTCARDROOT", "TRUST",
- "DISALLOWED"]
-
- # Byepassing the validation so that we may create a custom store
+ # Bypass validation of the store name so we can use a fake test store.
allow_any_instance_of(Chef::Mixin::ParamsValidate)
.to receive(:_pv_equal_to)
- .with(opts, key, to_be)
+ .with({ store_name: store }, :store_name, anything)
.and_return(true)
- # Creating a custom store for the testing
- create_store(store)
+ create_store
+ end
+
+ after { delete_store }
- allow(Chef::Log).to receive(:info) do |msg|
- stdout.puts(msg)
+ describe "action: create" do
+ it "starts with no certificates" do
+ expect(certificate_count).to eq(0)
end
- end
- after { cleanup(store) }
+ it "can add a certificate idempotently" do
+ resource.source = cer_path
+ resource.run_action(:create)
- subject(:win_certificate) do
- new_resource.store_name = store
- new_resource
- end
+ expect(certificate_count).to eq(1)
+ expect(resource).to be_updated_by_last_action
- it "Initially there are no certificates" do
- expect(no_of_certificates).to eq(0)
- end
+ # Adding the cert again should have no effect
+ resource.run_action(:create)
+ expect(certificate_count).to eq(1)
+ expect(resource).not_to be_updated_by_last_action
- describe "action :create" do
- before do
- win_certificate.source = cer_path
- win_certificate.run_action(:create)
- end
+ # Adding the cert again with a different format should have no effect
+ resource.source = pem_path
+ resource.run_action(:create)
+ expect(certificate_count).to eq(1)
+ expect(resource).not_to be_updated_by_last_action
- context "Adding a certificate" do
- it "Imports certificate into store" do
- expect(no_of_certificates).to eq(1)
- end
+ # Adding another cert should work correctly
+ resource.source = other_cer_path
+ resource.run_action(:create)
- it "Converges while addition" do
- expect(win_certificate).to be_updated_by_last_action
- end
+ expect(certificate_count).to eq(2)
+ expect(resource).to be_updated_by_last_action
end
- context "Again adding the same certificate" do
- before do
- win_certificate.run_action(:create)
- end
- it "Does not imports certificate into store" do
- expect(no_of_certificates).to eq(1)
- end
- it "Idempotent: Does not converge while addition" do
- expect(no_of_certificates).to eq(1)
- expect(win_certificate).not_to be_updated_by_last_action
- end
- end
+ it "can add a base64 encoded certificate idempotently" do
+ resource.source = base64_path
+ resource.run_action(:create)
- context "Again adding the same certificate of other format" do
- before do
- win_certificate.source = pem_path
- win_certificate.run_action(:create)
- end
- it "Does not imports certificate into store" do
- expect(no_of_certificates).to eq(1)
- end
- it "Idempotent: Does not converge while addition" do
- expect(no_of_certificates).to eq(1)
- expect(win_certificate).not_to be_updated_by_last_action
- end
- end
+ expect(certificate_count).to eq(1)
- context "Adding another certificate" do
- before do
- win_certificate.source = other_cer_path
- win_certificate.run_action(:create)
- end
- it "Imports certificate into store" do
- expect(no_of_certificates).to eq(2)
- end
- it "Converges while addition" do
- expect(no_of_certificates).to eq(2)
- expect(win_certificate).to be_updated_by_last_action
- end
+ resource.run_action(:create)
+ expect(certificate_count).to eq(1)
+ expect(resource).not_to be_updated_by_last_action
end
- end
- describe "Works for various formats" do
- context "Adds CER" do
- before do
- win_certificate.source = cer_path
- win_certificate.run_action(:create)
- end
- it "Imports certificate into store" do
- expect(no_of_certificates).to eq(1)
- end
- it "Idempotent: Does not converge while adding again" do
- win_certificate.run_action(:create)
- expect(no_of_certificates).to eq(1)
- expect(win_certificate).not_to be_updated_by_last_action
- end
- end
+ it "can add a PEM certificate idempotently" do
+ resource.source = pem_path
+ resource.run_action(:create)
- context "Adds Base64 Encoded CER" do
- before do
- win_certificate.source = base64_path
- win_certificate.run_action(:create)
- end
- it "Imports certificate into store" do
- expect(no_of_certificates).to eq(1)
- end
- it "Idempotent: Does not converge while adding again" do
- win_certificate.run_action(:create)
- expect(no_of_certificates).to eq(1)
- expect(win_certificate).not_to be_updated_by_last_action
- end
+ expect(certificate_count).to eq(1)
+
+ resource.run_action(:create)
+
+ expect(certificate_count).to eq(1)
+ expect(resource).not_to be_updated_by_last_action
end
- context "Adds PEM" do
- before do
- win_certificate.source = pem_path
- win_certificate.run_action(:create)
- end
- it "Imports certificate into store" do
- expect(no_of_certificates).to eq(1)
- end
- it "Idempotent: Does not converge while adding again" do
- win_certificate.run_action(:create)
- expect(no_of_certificates).to eq(1)
- expect(win_certificate).not_to be_updated_by_last_action
- end
+ it "can add a P7B certificate idempotently" do
+ resource.source = p7b_path
+ resource.run_action(:create)
+
+ # A P7B cert includes nested certs
+ expect(certificate_count).to eq(3)
+
+ resource.run_action(:create)
+
+ expect(resource).not_to be_updated_by_last_action
+ expect(certificate_count).to eq(3)
end
- context "Adds P7B" do
- before do
- win_certificate.source = p7b_path
- win_certificate.run_action(:create)
- end
- it "Imports certificate into store" do
- expect(no_of_certificates).not_to eq(0)
- end
- it "Idempotent: Does not converge while adding again" do
- win_certificate.run_action(:create)
- expect(win_certificate).not_to be_updated_by_last_action
- end
- it "Nested certificates are also imported" do
- expect(no_of_certificates).to eq(3)
- end
+ it "can add a PFX certificate idempotently with a valid password" do
+ resource.source = pfx_path
+ resource.pfx_password = password
+ resource.run_action(:create)
+
+ expect(certificate_count).to eq(1)
+
+ resource.run_action(:create)
+ expect(certificate_count).to eq(1)
+ expect(resource).not_to be_updated_by_last_action
end
- context "Adds PFX" do
- context "With valid password" do
- before do
- win_certificate.source = pfx_path
- win_certificate.pfx_password = password
- win_certificate.run_action(:create)
- end
- it "Imports certificate into store" do
- expect(no_of_certificates).to eq(1)
- end
- it "Idempotent: Does not converge while adding again" do
- win_certificate.run_action(:create)
- expect(no_of_certificates).to eq(1)
- expect(win_certificate).not_to be_updated_by_last_action
- end
- end
+ it "raises an error when adding a PFX certificate with an invalid password" do
+ resource.source = pfx_path
+ resource.pfx_password = "Invalid password"
- context "With Invalid password" do
- before do
- win_certificate.source = pfx_path
- win_certificate.pfx_password = "Invalid password"
- end
- it "Raises an error" do
- expect { win_certificate.run_action(:create) }.to raise_error(OpenSSL::PKCS12::PKCS12Error)
- end
- end
+ expect { resource.run_action(:create) }.to raise_error(OpenSSL::PKCS12::PKCS12Error)
end
end
describe "action: verify" do
- context "When a certificate is not present" do
- before do
- win_certificate.source = tests_thumbprint
- win_certificate.run_action(:verify)
- end
- it "Initial check if certificate is not present" do
- expect(no_of_certificates).to eq(0)
- end
- it "Displays correct message" do
- expect(stdout.string.strip).to eq("Certificate not found")
- end
- it "Does not converge while verifying" do
- expect(win_certificate).not_to be_updated_by_last_action
- end
+ it "fails with no certificates in the store" do
+ expect(Chef::Log).to receive(:info).with("Certificate not found")
+
+ resource.source = tests_thumbprint
+ resource.run_action(:verify)
+
+ expect(resource).not_to be_updated_by_last_action
end
- context "When a certificate is present" do
+ context "with a certificate in the store" do
before do
- win_certificate.source = cer_path
- win_certificate.run_action(:create)
+ resource.source = cer_path
+ resource.run_action(:create)
end
- context "For a valid thumbprint" do
- before do
- win_certificate.source = tests_thumbprint
- win_certificate.run_action(:verify)
- end
- it "Initial check if certificate is present" do
- expect(no_of_certificates).to eq(1)
- end
- it "Displays correct message" do
- expect(stdout.string.strip).to eq("Certificate is valid")
- end
- it "Does not converge while verifying" do
- expect(win_certificate).not_to be_updated_by_last_action
- end
+ it "succeeds with a valid thumbprint" do
+ expect(Chef::Log).to receive(:info).with("Certificate is valid")
+
+ resource.source = tests_thumbprint
+ resource.run_action(:verify)
+
+ expect(resource).not_to be_updated_by_last_action
end
- context "For an invalid thumbprint" do
- before do
- win_certificate.source = others_thumbprint
- win_certificate.run_action(:verify)
- end
- it "Initial check if certificate is present" do
- expect(no_of_certificates).to eq(1)
- end
- it "Displays correct message" do
- expect(stdout.string.strip).to eq("Certificate not found")
- end
- it "Does not converge while verifying" do
- expect(win_certificate).not_to be_updated_by_last_action
- end
+ it "fails with an invalid thumbprint" do
+ expect(Chef::Log).to receive(:info).with("Certificate not found")
+
+ resource.source = others_thumbprint
+ resource.run_action(:verify)
+
+ expect(resource).not_to be_updated_by_last_action
end
end
- context "When multiple certificates are present" do
+ context "with a nested certificate in the store" do
before do
- win_certificate.source = p7b_path
- win_certificate.run_action(:create)
+ resource.source = p7b_path
+ resource.run_action(:create)
end
- context "With main certificate's thumbprint" do
- before do
- win_certificate.source = p7b_thumbprint
- win_certificate.run_action(:verify)
- end
- it "Initial check if certificate is present" do
- expect(no_of_certificates).to eq(3)
- end
- it "Displays correct message" do
- expect(stdout.string.strip).to eq("Certificate is valid")
- end
- it "Does not converge while verifying" do
- expect(win_certificate).not_to be_updated_by_last_action
- end
+ it "succeeds with the main certificate's thumbprint" do
+ expect(Chef::Log).to receive(:info).with("Certificate is valid")
+
+ resource.source = p7b_thumbprint
+ resource.run_action(:verify)
+
+ expect(resource).not_to be_updated_by_last_action
end
- context "With nested certificate's thumbprint" do
- before do
- win_certificate.source = p7b_nested_thumbprint
- win_certificate.run_action(:verify)
- end
- it "Initial check if certificate is present" do
- expect(no_of_certificates).to eq(3)
- end
- it "Displays correct message" do
- expect(stdout.string.strip).to eq("Certificate is valid")
- end
- it "Does not converge while verifying" do
- expect(win_certificate).not_to be_updated_by_last_action
- end
+ it "succeeds with the nested certificate's thumbprint" do
+ expect(Chef::Log).to receive(:info).with("Certificate is valid")
+
+ resource.source = p7b_nested_thumbprint
+ resource.run_action(:verify)
+
+ expect(resource).not_to be_updated_by_last_action
end
- context "For an invalid thumbprint" do
- before do
- win_certificate.source = others_thumbprint
- win_certificate.run_action(:verify)
- end
- it "Initial check if certificate is present" do
- expect(no_of_certificates).to eq(3)
- end
- it "Displays correct message" do
- expect(stdout.string.strip).to eq("Certificate not found")
- end
- it "Does not converge while verifying" do
- expect(win_certificate).not_to be_updated_by_last_action
- end
+ it "fails with an invalid thumbprint" do
+ expect(Chef::Log).to receive(:info).with("Certificate not found")
+
+ resource.source = others_thumbprint
+ resource.run_action(:verify)
+
+ expect(resource).not_to be_updated_by_last_action
end
end
end
describe "action: fetch" do
- context "When a certificate is not present" do
- before do
- win_certificate.source = tests_thumbprint
- win_certificate.run_action(:fetch)
- end
- it "Initial check if certificate is not present" do
- expect(no_of_certificates).to eq(0)
- end
- it "Does not show any content" do
- expect(stdout.string.strip).to be_empty
- end
- it "Does not converge while fetching" do
- expect(win_certificate).not_to be_updated_by_last_action
- end
+ it "does nothing with no certificates in the store" do
+ expect(Chef::Log).not_to receive(:info)
+
+ resource.source = tests_thumbprint
+ resource.run_action(:fetch)
+
+ expect(resource).not_to be_updated_by_last_action
end
- context "When a certificate is present" do
+ context "with a certificate in the store" do
before do
- win_certificate.source = cer_path
- win_certificate.run_action(:create)
+ resource.source = cer_path
+ resource.run_action(:create)
end
- after do
- if File.exist?(out_path)
- File.delete(out_path)
- end
- end
+ it "succeeds with a valid thumbprint" do
+ resource.source = tests_thumbprint
- context "For a valid thumbprint" do
- before do
- win_certificate.source = tests_thumbprint
- win_certificate.cert_path = out_path
- win_certificate.run_action(:fetch)
- end
- it "Initial check if certificate is present" do
- expect(no_of_certificates).to eq(1)
- end
- it "Stores Certificate content at given path" do
- expect(File.exist?(out_path)).to be_truthy
- end
- it "Does not converge while fetching" do
- expect(win_certificate).not_to be_updated_by_last_action
+ Dir.mktmpdir do |dir|
+ path = File.join(dir, "test.pem")
+ expect(Chef::Log).to receive(:info).with("Certificate export in #{path}")
+
+ resource.cert_path = path
+ resource.run_action(:fetch)
+
+ expect(File.exist?(path)).to be_truthy
end
+
+ expect(resource).not_to be_updated_by_last_action
end
- context "For an invalid thumbprint" do
- before do
- win_certificate.source = others_thumbprint
- win_certificate.cert_path = out_path
- win_certificate.run_action(:fetch)
- end
- it "Initial check if certificate is present" do
- expect(no_of_certificates).to eq(1)
- end
- it "Does not show any content" do
- expect(stdout.string.strip).to be_empty
- end
- it "Does not store certificate content at given path" do
- expect(File.exist?(out_path)).to be_falsy
- end
- it "Does not converge while fetching" do
- expect(win_certificate).not_to be_updated_by_last_action
+ it "fails with an invalid thumbprint" do
+ expect(Chef::Log).not_to receive(:info)
+
+ resource.source = others_thumbprint
+
+ Dir.mktmpdir do |dir|
+ path = File.join(dir, "test.pem")
+
+ resource.cert_path = path
+ resource.run_action(:fetch)
+
+ expect(File.exist?(path)).to be_falsy
end
+
+ expect(resource).not_to be_updated_by_last_action
end
end
end
describe "action: delete" do
- context "When a certificate is not present" do
- before do
- win_certificate.source = tests_thumbprint
- win_certificate.run_action(:delete)
- end
- it "Initial check if certificate is not present" do
- expect(no_of_certificates).to eq(0)
- end
- it "Does not delete any certificate" do
- expect(stdout.string.strip).to be_empty
- end
+ it "does nothing when attempting to delete a certificate that doesn't exist" do
+ expect(Chef::Log).to receive(:debug).with("Certificate not found")
+
+ resource.source = tests_thumbprint
+ resource.run_action(:delete)
end
- context "When a certificate is present" do
- before do
- win_certificate.source = cer_path
- win_certificate.run_action(:create)
- end
- before { win_certificate.source = tests_thumbprint }
- it "Initial check if certificate is present" do
- expect(no_of_certificates).to eq(1)
- end
- it "Deletes the certificate" do
- win_certificate.run_action(:delete)
- expect(no_of_certificates).to eq(0)
- end
- it "Converges while deleting" do
- win_certificate.run_action(:delete)
- expect(win_certificate).to be_updated_by_last_action
- end
- it "Idempotent: Does not converge while deleting again" do
- win_certificate.run_action(:delete)
- win_certificate.run_action(:delete)
- expect(no_of_certificates).to eq(0)
- expect(win_certificate).not_to be_updated_by_last_action
- end
- it "Deletes the valid certificate" do
- # Add another certificate"
- win_certificate.source = other_cer_path
- win_certificate.run_action(:create)
- expect(no_of_certificates).to eq(2)
-
- # Delete previously added certificate
- win_certificate.source = tests_thumbprint
- win_certificate.run_action(:delete)
- expect(no_of_certificates).to eq(1)
-
- # Verify another certificate still exists
- win_certificate.source = others_thumbprint
- win_certificate.run_action(:verify)
- expect(stdout.string.strip).to eq("Certificate is valid")
- end
+ it "deletes an existing certificate while leaving other certificates alone" do
+ # Add two certs
+ resource.source = cer_path
+ resource.run_action(:create)
+
+ resource.source = other_cer_path
+ resource.run_action(:create)
+
+ # Delete the first cert added
+ resource.source = tests_thumbprint
+ resource.run_action(:delete)
+
+ expect(certificate_count).to eq(1)
+ expect(resource).to be_updated_by_last_action
+
+ resource.run_action(:delete)
+ expect(certificate_count).to eq(1)
+ expect(resource).not_to be_updated_by_last_action
+
+ # Verify second cert still exists
+ expect(Chef::Log).to receive(:info).with("Certificate is valid")
+ resource.source = others_thumbprint
+ resource.run_action(:verify)
end
end
end