summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn McCrae <jmccrae@chef.io>2021-04-13 14:28:24 -0700
committerJohn McCrae <jmccrae@chef.io>2021-04-13 14:28:24 -0700
commit3572e5b94c288527593074feda46427d939a6aae (patch)
treeb7c5eb1d8d571f01ad26e03b7191969271ecc8ec
parentb6ed63dfd023575b53f24b4395ad5636b9da0bfc (diff)
parentee0114abeba034d57630f2ac555fd480b733a9e0 (diff)
downloadchef-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.lock13
-rw-r--r--lib/chef/resource/windows_certificate.rb2
-rw-r--r--spec/functional/resource/windows_certificate2_spec.rb168
-rw-r--r--spec/functional/resource/windows_certificate_spec.rb75
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