diff options
author | John McCrae <jmccrae@chef.io> | 2021-04-13 14:28:24 -0700 |
---|---|---|
committer | John McCrae <jmccrae@chef.io> | 2021-04-13 14:28:24 -0700 |
commit | 3572e5b94c288527593074feda46427d939a6aae (patch) | |
tree | b7c5eb1d8d571f01ad26e03b7191969271ecc8ec | |
parent | b6ed63dfd023575b53f24b4395ad5636b9da0bfc (diff) | |
parent | ee0114abeba034d57630f2ac555fd480b733a9e0 (diff) | |
download | chef-3572e5b94c288527593074feda46427d939a6aae.tar.gz |
refactored windows_certificate to properly add remove a pfx and private key, changed output for all fetch commands to require an output path instead of dumping to screen, added the ability to create a certificate from a URL source, added functional and unit tests to verify all this
Signed-off-by: John McCrae <jmccrae@chef.io>
-rw-r--r-- | Gemfile.lock | 13 | ||||
-rw-r--r-- | lib/chef/resource/windows_certificate.rb | 2 | ||||
-rw-r--r-- | spec/functional/resource/windows_certificate2_spec.rb | 168 | ||||
-rw-r--r-- | spec/functional/resource/windows_certificate_spec.rb | 75 |
4 files changed, 255 insertions, 3 deletions
diff --git a/Gemfile.lock b/Gemfile.lock index 128e4c4af9..c137faa446 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -207,7 +207,11 @@ GEM highline (2.0.3) httpclient (2.8.3) iniparse (1.5.0) +<<<<<<< HEAD inspec-core (4.31.1) +======= + inspec-core (4.29.3) +>>>>>>> ee0114abeba034d57630f2ac555fd480b733a9e0 addressable (~> 2.4) chef-telemetry (~> 1.0) faraday (>= 0.9.0, < 1.4) @@ -230,8 +234,13 @@ GEM train-core (~> 3.0) tty-prompt (~> 0.17) tty-table (~> 0.10) +<<<<<<< HEAD inspec-core-bin (4.31.1) inspec-core (= 4.31.1) +======= + inspec-core-bin (4.29.3) + inspec-core (= 4.29.3) +>>>>>>> ee0114abeba034d57630f2ac555fd480b733a9e0 ipaddress (0.8.3) iso8601 (0.13.0) json (2.5.1) @@ -340,7 +349,11 @@ GEM syslog-logger (1.6.8) thor (1.1.0) tomlrb (1.3.0) +<<<<<<< HEAD train-core (3.6.0) +======= + train-core (3.5.5) +>>>>>>> ee0114abeba034d57630f2ac555fd480b733a9e0 addressable (~> 2.5) ffi (!= 1.13.0) json (>= 1.8, < 3.0) diff --git a/lib/chef/resource/windows_certificate.rb b/lib/chef/resource/windows_certificate.rb index 27880f44ca..9f4916131e 100644 --- a/lib/chef/resource/windows_certificate.rb +++ b/lib/chef/resource/windows_certificate.rb @@ -303,8 +303,6 @@ class Chef end def pfx_ps_cmd(thumbprint, store_location: "LocalMachine", store_name: "My", output_path:, password: ) - # require "pry" - # binding.pry <<-CMD $mypwd = ConvertTo-SecureString -String "#{password}" -Force -AsPlainText $cert = Get-ChildItem -path cert:\\#{store_location}\\#{store_name} -Recurse | Where { $_.Thumbprint -eq "#{thumbprint.upcase}" } diff --git a/spec/functional/resource/windows_certificate2_spec.rb b/spec/functional/resource/windows_certificate2_spec.rb new file mode 100644 index 0000000000..7852a88155 --- /dev/null +++ b/spec/functional/resource/windows_certificate2_spec.rb @@ -0,0 +1,168 @@ +# Author: Nimesh Patni (nimesh.patni@msystechnologies.com) +# Copyright:: Copyright (c) Chef Software Inc. +# License: Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +require "spec_helper" +require "chef/mixin/powershell_exec" +require "chef/resource/windows_certificate" + +describe Chef::Resource::WindowsCertificate, :windows_only do + include Chef::Mixin::PowershellExec + + def create_store(store_location: "LocalMachine", store_name: store) + powershell_exec <<~EOC + New-Item -Path Cert:\\#{store_location}\\#{store_name} + EOC + end + + def delete_store(store_location: "LocalMachine", store_name: store) + powershell_exec <<~EOC + Remove-Item -Path Cert:\\#{store_location}\\#{store_name} -Recurse + EOC + end + + def certificate_count(store_location: "LocalMachine", store_name: store) + powershell_exec(<<~EOC).result.to_i + (Get-ChildItem -Force -Path Cert:\\#{store_location}\\#{store_name} | measure).Count + EOC + end + + let(:password) { "P@ssw0rd!" } + let(:store) { "Chef-Functional-Test" } + # let(:store_name) { "MY" } + let(:store_location) { "LocalMachine" } + let(:download_cert_url) { "https://testingchef.blob.core.windows.net/files/test.cer?sv=2020-02-10&ss=b&srt=sco&sp=rlax&se=2022-03-20T01:20:15Z&st=2021-03-19T17:20:15Z&spr=https&sig=nMmvTTXp%2Fn0%2FYizBV8BzhjRJ%2Bmk%2BxYZ9529yOfqDxjQ%3D" } + let(:cert_output_path) { ::File.join(Chef::Config[:file_cache_path], "output.cer") } + let(:pfx_output_path) { ::File.join(Chef::Config[:file_cache_path], "output.pfx") } + let(:key_output_path) { ::File.join(Chef::Config[:file_cache_path], "output.key") } + 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(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 + # 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({ store_name: store }, :store_name, anything) + .and_return(true) + + create_store + + end + + after { delete_store } + + describe "action: verify" do + 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 + end + + describe "action: fetch" do + # context "with no certificate in the store" do + # it "throws an error with no certificates in the store" do + # expect(Chef::Log).not_to receive(:info) + # resource.source = others_thumbprint + # resource.output_path = cert_output_path + # expect { resource.run_action :fetch }.to raise_error(ArgumentError) + # end + # end + + # context "with a certificate in the store" do + # before do + # resource.source = cer_path + # resource.run_action(:create) + # end + + # it "succeeds with a valid thumbprint" do + # resource.source = tests_thumbprint + # local_output_path = ::File.join(Chef::Config[:file_cache_path], "test.pem") + # resource.output_path = local_output_path + # resource.run_action(:fetch) + # expect(File.exist?(local_output_path)).to be_truthy + # end + + # it "fails with an invalid thumbprint", :focus do + # expect(Chef::Log).not_to receive(:info) + + # resource.source = others_thumbprint + + # Dir.mktmpdir do |dir| + # path = File.join(dir, "test.pem") + + # resource.output_path = path + # expect { resource.run_action :fetch }.to raise_error(ArgumentError) + # end + # end + # end + + context "with a pfx/pkcs12 object in the store" do + before do + resource.source = pfx_path + resource.pfx_password = password + resource.exportable = true + resource.run_action(:create) + end + + # it "verfies" do + # resource.source = tests_thumbprint + # resource.run_action(:verify) + # end + + it "exports a PFX file with a valid thumbprint", :focus do + resource.source = tests_thumbprint + resource.pfx_password = password + resource.output_path = pfx_output_path + resource.run_action(:fetch) + expect(File.exist?(pfx_output_path)).to be_truthy + end + + # it "exports a key file with a valid thumbprint" do + # resource.source = tests_thumbprint + # resource.pfx_password = password + # resource.output_path = key_output_path + # resource.run_action(:fetch) + # expect(File.exist?(key_output_path)).to be_truthy + # end + + # it "throws an exception when output_path is not specified" do + # resource.source = tests_thumbprint + # resource.pfx_password = password + # expect { resource.run_action :fetch }.to raise_error(::Chef::Exceptions::ResourceNotFound) + # end + end + end + +end diff --git a/spec/functional/resource/windows_certificate_spec.rb b/spec/functional/resource/windows_certificate_spec.rb index aaa31f0bdd..04cd927be9 100644 --- a/spec/functional/resource/windows_certificate_spec.rb +++ b/spec/functional/resource/windows_certificate_spec.rb @@ -37,6 +37,7 @@ describe Chef::Resource::WindowsCertificate, :windows_only do def certificate_count(store_location: "LocalMachine", store_name: store) powershell_exec(<<~EOC).result.to_i (Get-ChildItem -Force -Path Cert:\\#{store_location}\\#{store_name} | measure).Count +<<<<<<< HEAD EOC end @@ -49,6 +50,8 @@ describe Chef::Resource::WindowsCertificate, :windows_only do def refresh_certstore(store_location: "LocalMachine") powershell_exec(<<~EOC) Get-ChildItem -Force -Path Cert:\\#{store_location} -Recurse +======= +>>>>>>> ee0114abeba034d57630f2ac555fd480b733a9e0 EOC end @@ -234,7 +237,7 @@ describe Chef::Resource::WindowsCertificate, :windows_only do resource.run_action(:create) end - it "succeeds with the main certificate's thumbprint" do + it "succeeds with the main certificate's thumbprint", :focus do expect(Chef::Log).to receive(:info).with("Certificate is valid") resource.source = p7b_thumbprint @@ -299,6 +302,40 @@ describe Chef::Resource::WindowsCertificate, :windows_only do expect { resource.run_action :fetch }.to raise_error(ArgumentError) end +<<<<<<< HEAD +======= + end + end + + context "with a pfx/pkcs12 object in the store" do + before do + resource.source = pfx_path + resource.pfx_password = password + resource.exportable = true + resource.run_action(:create) + end + + it "exports a PFX file with a valid thumbprint", :focus do + resource.source = tests_thumbprint + resource.pfx_password = password + resource.output_path = pfx_output_path + resource.run_action(:fetch) + expect(File.exist?(pfx_output_path)).to be_truthy + end + + it "exports a key file with a valid thumbprint" do + resource.source = tests_thumbprint + resource.pfx_password = password + resource.output_path = key_output_path + resource.run_action(:fetch) + expect(File.exist?(key_output_path)).to be_truthy + end + + it "throws an exception when output_path is not specified" do + resource.source = tests_thumbprint + resource.pfx_password = password + expect { resource.run_action :fetch }.to raise_error(::Chef::Exceptions::ResourceNotFound) +>>>>>>> ee0114abeba034d57630f2ac555fd480b733a9e0 end end @@ -339,6 +376,42 @@ describe Chef::Resource::WindowsCertificate, :windows_only do end end +<<<<<<< HEAD +======= + # describe "action: fetch pfx objects" do + # before do + # resource.source = pfx_path + # resource.pfx_password = password + # resource.exportable = true + # resource.run_action(:create) + # end + + # context "with a pfx/pkcs12 object in the store" do + # it "exports a PFX file with a valid thumbprint" do + # resource.source = tests_thumbprint + # resource.pfx_password = password + # resource.output_path = pfx_output_path + # resource.run_action(:fetch) + # expect(File.exist?(pfx_output_path)).to be_truthy + # end + + # it "exports a key file with a valid thumbprint" do + # resource.source = tests_thumbprint + # resource.pfx_password = password + # resource.output_path = key_output_path + # resource.run_action(:fetch) + # expect(File.exist?(key_output_path)).to be_truthy + # end + + # it "throws an exception when output_path is not specified" do + # resource.source = tests_thumbprint + # resource.pfx_password = password + # expect { resource.run_action :fetch }.to raise_error(::Chef::Exceptions::ResourceNotFound) + # end + # end + # end + +>>>>>>> ee0114abeba034d57630f2ac555fd480b733a9e0 describe "action: delete" do it "throws an argument error when attempting to delete a certificate that doesn't exist" do resource.source = tests_thumbprint |