diff options
author | Derek Groh <derekgroh@gmail.com> | 2018-09-04 13:08:16 -0500 |
---|---|---|
committer | Derek Groh <derekgroh@gmail.com> | 2018-09-04 13:08:16 -0500 |
commit | f923a7b3297a57506adb265d0c2d8d5671596f32 (patch) | |
tree | 00801dc895b91ab308521734a3a216db6247e9a8 /spec | |
parent | eada76335bcf43478b9b3a3d9727c0b127c8bc06 (diff) | |
parent | d06801ff46c0ba2108595bb66da7c638e10eba6c (diff) | |
download | chef-f923a7b3297a57506adb265d0c2d8d5671596f32.tar.gz |
Merge branch 'master' of https://github.com/chef/chef into feature/windows_ad_join
Diffstat (limited to 'spec')
24 files changed, 1226 insertions, 31 deletions
diff --git a/spec/functional/resource/mount_spec.rb b/spec/functional/resource/mount_spec.rb index f4e528c755..f6c7f91bcd 100644 --- a/spec/functional/resource/mount_spec.rb +++ b/spec/functional/resource/mount_spec.rb @@ -1,6 +1,6 @@ # # Author:: Kaustubh Deorukhkar (<kaustubh@clogeny.com>) -# Copyright:: Copyright 2013-2016, Chef Software Inc. +# Copyright:: Copyright 2013-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/spec/functional/resource/windows_task_spec.rb b/spec/functional/resource/windows_task_spec.rb index 02c84d5229..a2cd4b97d7 100644 --- a/spec/functional/resource/windows_task_spec.rb +++ b/spec/functional/resource/windows_task_spec.rb @@ -1096,6 +1096,90 @@ describe Chef::Resource::WindowsTask, :windows_only do end end + context "when battery options are passed" do + subject do + new_resource = Chef::Resource::WindowsTask.new(task_name, run_context) + new_resource.command task_name + new_resource.run_level :highest + new_resource.execution_time_limit = 259200 / 60 # converting "PT72H" into minutes and passing here since win32-taskscheduler accespts this + new_resource + end + + it "sets the default if options are not provided" do + subject.frequency :minute + call_for_create_action + # loading current resource again to check new task is created and it matches task parameters + current_resource = call_for_load_current_resource + expect(current_resource.exists).to eq(true) + expect(current_resource.stop_if_going_on_batteries).to eql(false) + expect(current_resource.disallow_start_if_on_batteries).to eql(false) + end + + it "sets disallow_start_if_on_batteries to true" do + subject.frequency :minute + subject.disallow_start_if_on_batteries true + call_for_create_action + # loading current resource again to check new task is created and it matches task parameters + current_resource = call_for_load_current_resource + expect(current_resource.exists).to eq(true) + expect(current_resource.task.settings[:disallow_start_if_on_batteries]).to eql(true) + end + + it "sets disallow_start_if_on_batteries to false" do + subject.frequency :minute + subject.disallow_start_if_on_batteries false + call_for_create_action + # loading current resource again to check new task is created and it matches task parameters + current_resource = call_for_load_current_resource + expect(current_resource.exists).to eq(true) + expect(current_resource.task.settings[:disallow_start_if_on_batteries]).to eql(false) + end + + it "sets stop_if_going_on_batteries to true" do + subject.frequency :minute + subject.stop_if_going_on_batteries true + call_for_create_action + # loading current resource again to check new task is creted and it matches task parameters + current_resource = call_for_load_current_resource + expect(current_resource.exists).to eq(true) + expect(current_resource.task.settings[:stop_if_going_on_batteries]).to eql(true) + end + + it "sets stop_if_going_on_batteries to false" do + subject.frequency :minute + subject.stop_if_going_on_batteries false + call_for_create_action + # loading current resource again to check new task is created and it matches task parameters + current_resource = call_for_load_current_resource + expect(current_resource.exists).to eq(true) + expect(current_resource.task.settings[:stop_if_going_on_batteries]).to eql(false) + end + + it "sets the default if options are nil" do + subject.frequency :minute + subject.stop_if_going_on_batteries nil + subject.disallow_start_if_on_batteries nil + call_for_create_action + # loading current resource again to check new task is created and it matches task parameters + current_resource = call_for_load_current_resource + expect(current_resource.exists).to eq(true) + expect(current_resource.task.settings[:stop_if_going_on_batteries]).to eql(false) + expect(current_resource.task.settings[:disallow_start_if_on_batteries]).to eql(false) + end + + it "does not converge the resource if it is already converged" do + subject.frequency :minute + subject.stop_if_going_on_batteries true + subject.disallow_start_if_on_batteries false + subject.run_action(:create) + subject.frequency :minute + subject.stop_if_going_on_batteries true + subject.disallow_start_if_on_batteries false + subject.run_action(:create) + expect(subject).not_to be_updated_by_last_action + end + end + context "frequency :none" do subject do new_resource = Chef::Resource::WindowsTask.new(task_name, run_context) diff --git a/spec/functional/resource/yum_package_spec.rb b/spec/functional/resource/yum_package_spec.rb index 17e4669255..3735e67cf2 100644 --- a/spec/functional/resource/yum_package_spec.rb +++ b/spec/functional/resource/yum_package_spec.rb @@ -443,11 +443,13 @@ describe Chef::Resource::YumPackage, :requires_root, external: exclude_test do expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^chef_rpm-1.2-1.#{pkg_arch}$") end - it "downgrade on a local file raises an error" do + it "downgrade on a local file is ignored" do preinstall("chef_rpm-1.10-1.#{pkg_arch}.rpm") yum_package.version "1.2-1" yum_package.package_name("#{CHEF_SPEC_ASSETS}/yumrepo/chef_rpm-1.2-1.#{pkg_arch}.rpm") - expect { yum_package.run_action(:install) }.to raise_error(Mixlib::ShellOut::ShellCommandFailed) + yum_package.run_action(:install) + expect(yum_package.updated_by_last_action?).to be false + expect(shell_out("rpm -q --queryformat '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' chef_rpm").stdout.chomp).to match("^chef_rpm-1.10-1.#{pkg_arch}$") end it "downgrade on a local file with allow_downgrade true works" do diff --git a/spec/support/shared/functional/file_resource.rb b/spec/support/shared/functional/file_resource.rb index d025a0806d..8ae5db6a57 100644 --- a/spec/support/shared/functional/file_resource.rb +++ b/spec/support/shared/functional/file_resource.rb @@ -1,6 +1,6 @@ # # Author:: Seth Chisamore (<schisamo@chef.io>) -# Copyright:: Copyright 2011-2016, Chef Software Inc. +# Copyright:: Copyright 2011-2018, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -385,7 +385,7 @@ shared_examples_for "a configured file resource" do def selinux_security_context_restored?(path) @restorecon_path = which("restorecon") if @restorecon_path.nil? restorecon_test_command = "#{@restorecon_path} -n -v #{path}" - cmdresult = shell_out(restorecon_test_command) + cmdresult = shell_out!(restorecon_test_command) # restorecon will print the required changes to stdout if any is # needed cmdresult.stdout.empty? @@ -725,7 +725,7 @@ shared_examples_for "a configured file resource" do end before(:each) do - result = shell_out("mknod #{path} b 1 2") + result = shell_out!("mknod #{path} b 1 2") result.stderr.empty? end @@ -743,7 +743,7 @@ shared_examples_for "a configured file resource" do end before(:each) do - result = shell_out("mknod #{path} c 1 2") + result = shell_out!("mknod #{path} c 1 2") result.stderr.empty? end @@ -761,7 +761,7 @@ shared_examples_for "a configured file resource" do end before(:each) do - result = shell_out("mkfifo #{path}") + result = shell_out!("mkfifo #{path}") result.stderr.empty? end diff --git a/spec/tiny_server.rb b/spec/tiny_server.rb index 4a6bdfb599..948bde04f2 100644 --- a/spec/tiny_server.rb +++ b/spec/tiny_server.rb @@ -16,7 +16,6 @@ # limitations under the License. # -require "rubygems" require "webrick" require "webrick/https" require "rack" diff --git a/spec/unit/chef_class_spec.rb b/spec/unit/chef_class_spec.rb index 2f370388fa..d862273f52 100644 --- a/spec/unit/chef_class_spec.rb +++ b/spec/unit/chef_class_spec.rb @@ -143,6 +143,16 @@ describe "Chef class" do Chef.deprecated(:generic, "This is my handle.") end + it "allows silencing specific IDs without matching the line number" do + Chef::Config[:silence_deprecation_warnings] = [__LINE__ + 4] + expect(Chef::Log).to receive(:warn).with(/I'm a little teapot/).once + expect(Chef::Log).to receive(:warn).with(/Short and stout/).once + expect(Chef::Log).to receive(:warn).with(/This is my handle/).once + Chef.deprecated(:generic, "I'm a little teapot.") + Chef.deprecated(:internal_api, "Short and stout.") + Chef.deprecated(:generic, "This is my handle.") + end + it "allows silencing specific IDs using the CHEF- syntax" do Chef::Config[:silence_deprecation_warnings] = ["CHEF-0"] expect(Chef::Log).to receive(:warn).with(/I'm a little teapot/).once diff --git a/spec/unit/mixin/openssl_helper_spec.rb b/spec/unit/mixin/openssl_helper_spec.rb index 6873fd8cf2..a6a6fb0e71 100644 --- a/spec/unit/mixin/openssl_helper_spec.rb +++ b/spec/unit/mixin/openssl_helper_spec.rb @@ -126,15 +126,15 @@ describe Chef::Mixin::OpenSSLHelper do end end - context "When the key file does exist, but does not contain a valid rsa private key" do - it "Throws an OpenSSL::PKey::RSAError exception" do + context "When the key file does exist, but does not contain a valid rsa/ec private key" do + it "Throws an OpenSSL::PKey::PKeyError exception" do @keyfile.write("I_am_not_a_key_I_am_a_free_man") @keyfile.close expect(instance.priv_key_file_valid?(@keyfile.path)).to be_falsey end end - context "When the key file does exist, and does contain a vaild rsa private key" do + context "When the rsa key file does exist, and does contain a vaild rsa private key" do it "returns true" do @keyfile.write(::OpenSSL::PKey::RSA.new(1024).to_pem) @keyfile.close @@ -142,17 +142,41 @@ describe Chef::Mixin::OpenSSLHelper do end end - context "When a valid keyfile requires a passphrase, and an invalid passphrase is supplied" do + context "When the ec key file does exist, and does contain a vaild ec private key" do + it "returns true" do + @keyfile.write(OpenSSL::PKey::EC.generate("prime256v1").to_pem) + @keyfile.close + expect(instance.priv_key_file_valid?(@keyfile.path)).to be_truthy + end + end + + context "When a valid rsa keyfile requires a passphrase, and an invalid passphrase is supplied" do + it "returns false" do + @keyfile.write(OpenSSL::PKey::RSA.new(1024).to_pem(cipher, "oink")) + @keyfile.close + expect(instance.priv_key_file_valid?(@keyfile.path, "poml")).to be_falsey + end + end + + context "When a valid ec keyfile requires a passphrase, and an invalid passphrase is supplied" do it "returns false" do - @keyfile.write(::OpenSSL::PKey::RSA.new(1024).to_pem(cipher, "oink")) + @keyfile.write(OpenSSL::PKey::EC.generate("prime256v1").to_pem(cipher, "oink")) @keyfile.close expect(instance.priv_key_file_valid?(@keyfile.path, "poml")).to be_falsey end end - context "When a valid keyfile requires a passphrase, and a valid passphrase is supplied" do + context "When a valid rsa keyfile requires a passphrase, and a valid passphrase is supplied" do it "returns true" do - @keyfile.write(::OpenSSL::PKey::RSA.new(1024).to_pem(cipher, "oink")) + @keyfile.write(OpenSSL::PKey::RSA.new(1024).to_pem(cipher, "oink")) + @keyfile.close + expect(instance.priv_key_file_valid?(@keyfile.path, "oink")).to be_truthy + end + end + + context "When a valid ec keyfile requires a passphrase, and a valid passphrase is supplied" do + it "returns true" do + @keyfile.write(OpenSSL::PKey::EC.generate("prime256v1").to_pem(cipher, "oink")) @keyfile.close expect(instance.priv_key_file_valid?(@keyfile.path, "oink")).to be_truthy end @@ -163,6 +187,40 @@ describe Chef::Mixin::OpenSSLHelper do end end + describe "#crl_file_valid?" do + require "tempfile" + + before(:each) do + @crlfile = Tempfile.new("crlfile") + end + + context "When the crl file doesnt not exist" do + it "returns false" do + expect(instance.crl_file_valid?("/tmp/bad_filename")).to be_falsey + end + end + + context "When the crl file does exist, but does not contain a valid CRL" do + it "returns false" do + @crlfile.write("I_am_not_a_crl_I_am_a_free_man") + @crlfile.close + expect(instance.crl_file_valid?(@crlfile.path)).to be_falsey + end + end + + context "When the crl file does exist, and does contain a vaild CRL" do + it "returns true" do + @crlfile.write("-----BEGIN X509 CRL-----\nMIIBbjCB0QIBATAKBggqhkjOPQQDAjAOMQwwCgYDVQQDDANDQTIXDTE4MDgwMTE3\nMjg1NVoXDTE4MDgwOTE3Mjg1NVowNjA0AhUAx7y2YCouQlHvTignoijLUrwM6i8X\nDTE4MDgwMTE3Mjg1NVowDDAKBgNVHRUEAwoBAKBaMFgwCgYDVR0UBAMCAQQwSgYD\nVR0jBEMwQYAUCqE8XxFIFys0LTVPvsO1UtmrlyOhEqQQMA4xDDAKBgNVBAMMA0NB\nMoIVAPneTuAa1LzrK0wiZrxE8/1lSTp3MAoGCCqGSM49BAMCA4GLADCBhwJBct+Z\nZV3IZkPNevQv2S8lZ6kAMudN8R4QSzIQfM354Uk880RyQStP2S5Mb4gW3aFzwAy2\n/+rbx0bn2WmwoQv17I8CQgDtbvhf9chyPgMwAGCF7al04fve90fU1zRNH0zX1j9H\niDA2q1uBX+3TcTWcN+xgNimeRpvJFJ3uOB6w7jtwqGf1YQ==\n-----END X509 CRL-----\n") + @crlfile.close + expect(instance.crl_file_valid?(@crlfile.path)).to be_truthy + end + end + + after(:each) do + @crlfile.unlink + end + end + # Generators describe "#gen_dhparam" do context "When given an invalid key length" do @@ -183,7 +241,7 @@ describe Chef::Mixin::OpenSSLHelper do context "When a proper key length and generator id are given" do it "Generates a dhparam object" do - expect(instance.gen_dhparam(1024, 2)).to be_kind_of(::OpenSSL::PKey::DH) + expect(instance.gen_dhparam(1024, 2)).to be_kind_of(OpenSSL::PKey::DH) end end end @@ -199,14 +257,14 @@ describe Chef::Mixin::OpenSSLHelper do context "When a proper key length is given" do it "Generates an RSA key object" do - expect(instance.gen_rsa_priv_key(1024)).to be_kind_of(::OpenSSL::PKey::RSA) + expect(instance.gen_rsa_priv_key(1024)).to be_kind_of(OpenSSL::PKey::RSA) end end end describe "#encrypt_rsa_key" do before(:all) do - @rsa_key = ::OpenSSL::PKey::RSA.new(1024) + @rsa_key = OpenSSL::PKey::RSA.new(1024) end context "When given anything other than an RSA key object to encrypt" do @@ -245,7 +303,554 @@ describe Chef::Mixin::OpenSSLHelper do it "Generates a valid encrypted PEM" do @encrypted_key = instance.encrypt_rsa_key(@rsa_key, "oink", "des3") expect(@encrypted_key).to be_kind_of(String) - expect(::OpenSSL::PKey::RSA.new(@encrypted_key, "oink").private?).to be_truthy + expect(OpenSSL::PKey::RSA.new(@encrypted_key, "oink").private?).to be_truthy + end + end + end + + describe "#gen_ec_priv_key" do + context "When given an invalid curve" do + it "Raises a TypeError" do + expect do + instance.gen_ec_priv_key(2048) + end.to raise_error(TypeError) + end + + it "Throws an ArgumentError" do + expect do + instance.gen_ec_priv_key("primeFromTheFuture") + end.to raise_error(ArgumentError) + end + end + + context "When a proper curve is given" do + it "Generates an ec key object" do + expect(instance.gen_ec_priv_key("prime256v1")).to be_kind_of(OpenSSL::PKey::EC) + end + end + end + + describe "#encrypt_ec_key" do + before(:all) do + @ec_key = OpenSSL::PKey::EC.generate("prime256v1") + end + + context "When given anything other than an EC key object to encrypt" do + it "Raises a TypeError" do + expect do + instance.encrypt_ec_key("abcd", "efgh", "des3") + end.to raise_error(TypeError) + end + end + + context "When given anything other than a string as the passphrase" do + it "Raises a TypeError" do + expect do + instance.encrypt_ec_key(@ec_key, 1234, "des3") + end.to raise_error(TypeError) + end + end + + context "When given anything other than a string as the cipher" do + it "Raises a TypeError" do + expect do + instance.encrypt_ec_key(@ec_key, "1234", 1234) + end.to raise_error(TypeError) + end + end + + context "When given an invalid cipher string" do + it "Raises an ArgumentError" do + expect do + instance.encrypt_ec_key(@ec_key, "1234", "des3_bogus") + end.to raise_error(ArgumentError) + end + end + + context "When given a valid ec key and a valid passphrase string" do + it "Generates a valid encrypted PEM" do + @encrypted_key = instance.encrypt_ec_key(@ec_key, "oink", "des3") + expect(@encrypted_key).to be_kind_of(String) + expect(OpenSSL::PKey::EC.new(@encrypted_key, "oink").private?).to be_truthy + end + end + end + + describe "#gen_x509_request" do + before(:all) do + @subject = OpenSSL::X509::Name.new [%w{CN x509request}] + @ec_key = OpenSSL::PKey::EC.generate("prime256v1") + @rsa_key = OpenSSL::PKey::RSA.new(2048) + end + + context "When given anything other than an RSA/EC key object" do + it "Raises a TypeError" do + expect do + instance.gen_x509_request(@subject, "abc") + end.to raise_error(TypeError) + end + end + + context "When given anything other than an X509 Name object" do + it "Raises a TypeError" do + expect do + instance.gen_x509_request("abc", @key) + end.to raise_error(TypeError) + end + end + + context "When given a valid EC key and a valid subject" do + it "Generates a valid x509 request PEM" do + @x509_request = instance.gen_x509_request(@subject, @ec_key) + expect(@x509_request).to be_kind_of(OpenSSL::X509::Request) + expect(OpenSSL::X509::Request.new(@x509_request).verify(@ec_key)).to be_truthy + end + end + + context "When given a valid RSA key and a valid subject" do + it "Generates a valid x509 request PEM" do + @x509_request = instance.gen_x509_request(@subject, @rsa_key) + expect(@x509_request).to be_kind_of(OpenSSL::X509::Request) + expect(OpenSSL::X509::Request.new(@x509_request).verify(@rsa_key)).to be_truthy + end + end + end + + describe "#gen_x509_extensions" do + context "When given anything other than an Ruby Hash object" do + it "Raises a TypeError" do + expect do + instance.gen_x509_extensions("abc") + end.to raise_error(TypeError) + end + end + + context "When a misformatted ruby Hash is given" do + it "Raises a TypeError" do + expect do + instance.gen_x509_extensions("pouet" => "plop") + end.to raise_error(TypeError) + end + + it "Raises a ArgumentError" do + expect do + instance.gen_x509_extensions("pouet" => { "values" => [ "keyCertSign" ], "wrong_key" => true }) + end.to raise_error(ArgumentError) + end + + it "Raises a TypeError" do + expect do + instance.gen_x509_extensions("keyUsage" => { "values" => "keyCertSign", "critical" => true }) + end.to raise_error(TypeError) + end + + it "Raises a TypeError" do + expect do + instance.gen_x509_extensions("keyUsage" => { "values" => [ "keyCertSign" ], "critical" => "yes" }) + end.to raise_error(TypeError) + end + end + + context "When given a well formatted ruby Hash" do + it "Generates a valid Array of X509 Extensions" do + @x509_extension = instance.gen_x509_extensions("keyUsage" => { "values" => [ "keyCertSign" ], "critical" => true }) + expect(@x509_extension).to be_kind_of(Array) + @x509_extension.each { |e| expect(e).to be_kind_of(OpenSSL::X509::Extension) } + end + end + end + + describe "#gen_x509_cert" do + before(:all) do + @instance = Class.new { include Chef::Mixin::OpenSSLHelper }.new + @rsa_key = OpenSSL::PKey::RSA.new(2048) + @ec_key = OpenSSL::PKey::EC.generate("prime256v1") + + @rsa_request = @instance.gen_x509_request(OpenSSL::X509::Name.new([%w{CN RSACert}]), @rsa_key) + @ec_request = @instance.gen_x509_request(OpenSSL::X509::Name.new([%w{CN ECCert}]), @ec_key) + + @x509_extension = @instance.gen_x509_extensions("keyUsage" => { "values" => [ "keyCertSign" ], "critical" => true }) + + # Generating CA + @ca_key = OpenSSL::PKey::RSA.new(2048) + @ca_cert = OpenSSL::X509::Certificate.new + @ca_cert.version = 2 + @ca_cert.serial = 1 + @ca_cert.subject = OpenSSL::X509::Name.new [%w{CN TestCA}] + @ca_cert.issuer = @ca_cert.subject + @ca_cert.public_key = @ca_key.public_key + @ca_cert.not_before = Time.now + @ca_cert.not_after = @ca_cert.not_before + 365 * 24 * 60 * 60 + ef = OpenSSL::X509::ExtensionFactory.new + ef.subject_certificate = @ca_cert + ef.issuer_certificate = @ca_cert + @ca_cert.add_extension(ef.create_extension("basicConstraints", "CA:TRUE", true)) + @ca_cert.add_extension(ef.create_extension("keyUsage", "keyCertSign, cRLSign", true)) + @ca_cert.add_extension(ef.create_extension("subjectKeyIdentifier", "hash", false)) + @ca_cert.add_extension(ef.create_extension("authorityKeyIdentifier", "keyid:always", false)) + @ca_cert.sign(@ca_key, OpenSSL::Digest::SHA256.new) + + @info_with_issuer = { "validity" => 365, "issuer" => @ca_cert } + @info_without_issuer = { "validity" => 365 } + end + + context "When the request given is anything other then a Ruby OpenSSL::X509::Request" do + it "Raises a TypeError" do + expect do + @instance.gen_x509_cert("abc", @x509_extension, @info_without_issuer, @rsa_key) + end.to raise_error(TypeError) + end + end + + context "When the extension given is anything other then a Ruby Array" do + it "Raises a TypeError" do + expect do + @instance.gen_x509_cert(@rsa_request, "abc", @info_without_issuer, @rsa_key) + end.to raise_error(TypeError) + end + end + + context "When the info given is anything other then a Ruby Hash" do + it "Raises a TypeError" do + expect do + @instance.gen_x509_cert(@rsa_request, @x509_extension, "abc", @rsa_key) + end.to raise_error(TypeError) + end + end + + context "When the key given is anything other then a Ruby OpenSSL::Pkey::EC or OpenSSL::Pkey::RSA object" do + it "Raises a TypeError" do + expect do + @instance.gen_x509_cert(@rsa_request, @x509_extension, @info_without_issuer, "abc") + end.to raise_error(TypeError) + end + end + + context "When given valid parameters to generate a self signed certificate" do + it "Generates a valid x509 Certificate" do + @x509_certificate = @instance.gen_x509_cert(@rsa_request, @x509_extension, @info_without_issuer, @rsa_key) + expect(@x509_certificate).to be_kind_of(OpenSSL::X509::Certificate) + expect(OpenSSL::X509::Certificate.new(@x509_certificate).verify(@rsa_key)).to be_truthy + end + end + + context "When given valid parameters to generate a CA signed certificate" do + it "Generates a valid x509 Certificate" do + @x509_certificate = @instance.gen_x509_cert(@ec_request, @x509_extension, @info_with_issuer, @ca_key) + expect(@x509_certificate).to be_kind_of(OpenSSL::X509::Certificate) + expect(OpenSSL::X509::Certificate.new(@x509_certificate).verify(@ca_key)).to be_truthy + end + end + end + + describe "#get_next_crl_number" do + before(:all) do + @crl = OpenSSL::X509::CRL. new "-----BEGIN X509 CRL-----\nMIIBbTCB0QIBATAKBggqhkjOPQQDAjAOMQwwCgYDVQQDDANDQTIXDTE4MDgwMjA5\nMzc0OFoXDTE4MDgxMDA5Mzc0OFowNjA0AhUAx7y2YCouQlHvTignoijLUrwM6i8X\nDTE4MDgwMjA5Mzc0OFowDDAKBgNVHRUEAwoBAKBaMFgwCgYDVR0UBAMCAQQwSgYD\nVR0jBEMwQYAUxRlLNQUIOeWVaYm6HS0qFIbNCs2hEqQQMA4xDDAKBgNVBAMMA0NB\nMoIVAN1nyw8cj7IbhRLBu2CfS9Q8ILmDMAoGCCqGSM49BAMCA4GKADCBhgJBNR3o\njo/PzFwFGJKxIMa09pU+jprLG2CWehpZ4tGDjwiDCfZBztkg3H15eu+hyWmDp0U9\neAP5iJHVb12/3KZP0YUCQSgmaoLF68+Gh7ha+hcDjwFhzqdgmh/UlGPaxFBJ1BiQ\nQq9uBn0IT4o7v1Tv2WRZNDk7oiuRaZG+R9IodiZPsGKv\n-----END X509 CRL-----\n" + end + + context "When the CRL given is anything other then a Ruby OpenSSL::X509::CRL object" do + it "Raises a TypeError" do + expect do + instance.get_next_crl_number("abc") + end.to raise_error(TypeError) + end + end + + context "When given valid parameter to get the next crlNumber" do + it "Get 5" do + @next_crl = instance.get_next_crl_number(@crl) + expect(@next_crl).to be_kind_of(Integer) + expect(@next_crl == 5).to be_truthy + end + end + end + + describe "#serial_revoked?" do + before(:all) do + @crl = OpenSSL::X509::CRL. new "-----BEGIN X509 CRL-----\nMIIBbTCB0QIBATAKBggqhkjOPQQDAjAOMQwwCgYDVQQDDANDQTIXDTE4MDgwMjA5\nMzc0OFoXDTE4MDgxMDA5Mzc0OFowNjA0AhUAx7y2YCouQlHvTignoijLUrwM6i8X\nDTE4MDgwMjA5Mzc0OFowDDAKBgNVHRUEAwoBAKBaMFgwCgYDVR0UBAMCAQQwSgYD\nVR0jBEMwQYAUxRlLNQUIOeWVaYm6HS0qFIbNCs2hEqQQMA4xDDAKBgNVBAMMA0NB\nMoIVAN1nyw8cj7IbhRLBu2CfS9Q8ILmDMAoGCCqGSM49BAMCA4GKADCBhgJBNR3o\njo/PzFwFGJKxIMa09pU+jprLG2CWehpZ4tGDjwiDCfZBztkg3H15eu+hyWmDp0U9\neAP5iJHVb12/3KZP0YUCQSgmaoLF68+Gh7ha+hcDjwFhzqdgmh/UlGPaxFBJ1BiQ\nQq9uBn0IT4o7v1Tv2WRZNDk7oiuRaZG+R9IodiZPsGKv\n-----END X509 CRL-----\n" + end + + context "When the CRL given is anything other then a Ruby OpenSSL::X509::CRL object" do + it "Raises a TypeError" do + expect do + instance.serial_revoked?("abc", "C7BCB6602A2E4251EF4E2827A228CB52BC0CEA2F") + end.to raise_error(TypeError) + end + end + + context "When the serial given is anything other then a Ruby String or Integer object" do + it "Raises a TypeError" do + expect do + instance.serial_revoked?(@crl, []) + end.to raise_error(TypeError) + end + end + + context "When given valid parameters to know if the serial is revoked" do + it "get true" do + @serial_revoked = instance.serial_revoked?(@crl, "C7BCB6602A2E4251EF4E2827A228CB52BC0CEA2F") + expect(@serial_revoked).to be_kind_of(TrueClass) + end + end + end + + describe "#gen_x509_crl" do + before(:all) do + # Generating CA + + @ca_key = OpenSSL::PKey::RSA.new(2048) + @ca_cert = OpenSSL::X509::Certificate.new + @ca_cert.version = 2 + @ca_cert.serial = 1 + @ca_cert.subject = OpenSSL::X509::Name.new [%w{CN TestCA}] + @ca_cert.issuer = @ca_cert.subject + @ca_cert.public_key = @ca_key.public_key + @ca_cert.not_before = Time.now + @ca_cert.not_after = @ca_cert.not_before + 365 * 24 * 60 * 60 + ef = OpenSSL::X509::ExtensionFactory.new + ef.subject_certificate = @ca_cert + ef.issuer_certificate = @ca_cert + @ca_cert.add_extension(ef.create_extension("basicConstraints", "CA:TRUE", true)) + @ca_cert.add_extension(ef.create_extension("keyUsage", "keyCertSign, cRLSign", true)) + @ca_cert.add_extension(ef.create_extension("subjectKeyIdentifier", "hash", false)) + @ca_cert.add_extension(ef.create_extension("authorityKeyIdentifier", "keyid:always", false)) + @ca_cert.sign(@ca_key, OpenSSL::Digest::SHA256.new) + + @info = { "validity" => 8, "issuer" => @ca_cert } + end + + context "When the CA private key given is anything other then a Ruby OpenSSL::PKey::EC object or a OpenSSL::PKey::RSA object" do + it "Raises a TypeError" do + expect do + instance.gen_x509_crl("abc", @info) + end.to raise_error(TypeError) + end + end + + context "When the info given is anything other then a Ruby Hash" do + it "Raises a TypeError" do + expect do + instance.gen_x509_crl(@ca_key, "abc") + end.to raise_error(TypeError) + end + end + + context "When a misformatted info Ruby Hash is given" do + it "Raises a ArgumentError" do + expect do + instance.gen_x509_crl(@ca_key, "abc" => "def", "validity" => 8) + end.to raise_error(ArgumentError) + end + + it "Raises a TypeError" do + expect do + instance.gen_x509_crl(@ca_key, "issuer" => "abc", "validity" => 8) + end.to raise_error(TypeError) + end + + it "Raises a TypeError" do + expect do + instance.gen_x509_crl(@ca_key, "issuer" => @ca_cert, "validity" => "abc") + end.to raise_error(TypeError) + end + end + + context "When given valid parameters to generate a CRL" do + it "Generates a valid x509 CRL" do + @x509_crl = instance.gen_x509_crl(@ca_key, @info) + expect(@x509_crl).to be_kind_of(OpenSSL::X509::CRL) + expect(OpenSSL::X509::CRL.new(@x509_crl).verify(@ca_key)).to be_truthy + end + end + end + + describe "#renew_x509_crl" do + before(:all) do + # Generating CA + @instance = Class.new { include Chef::Mixin::OpenSSLHelper }.new + @ca_key = OpenSSL::PKey::RSA.new(2048) + @ca_cert = OpenSSL::X509::Certificate.new + @ca_cert.version = 2 + @ca_cert.serial = 1 + @ca_cert.subject = OpenSSL::X509::Name.new [%w{CN TestCA}] + @ca_cert.issuer = @ca_cert.subject + @ca_cert.public_key = @ca_key.public_key + @ca_cert.not_before = Time.now + @ca_cert.not_after = @ca_cert.not_before + 365 * 24 * 60 * 60 + ef = OpenSSL::X509::ExtensionFactory.new + ef.subject_certificate = @ca_cert + ef.issuer_certificate = @ca_cert + @ca_cert.add_extension(ef.create_extension("basicConstraints", "CA:TRUE", true)) + @ca_cert.add_extension(ef.create_extension("keyUsage", "keyCertSign, cRLSign", true)) + @ca_cert.add_extension(ef.create_extension("subjectKeyIdentifier", "hash", false)) + @ca_cert.add_extension(ef.create_extension("authorityKeyIdentifier", "keyid:always", false)) + @ca_cert.sign(@ca_key, OpenSSL::Digest::SHA256.new) + + @info = { "validity" => 8, "issuer" => @ca_cert } + + @crl = @instance.gen_x509_crl(@ca_key, @info) + end + + context "When the CRL given is anything other then a Ruby OpenSSL::X509::CRL object" do + it "Raises a TypeError" do + expect do + instance.renew_x509_crl("abc", @ca_key, @info) + end.to raise_error(TypeError) + end + end + + context "When the CA private key given is anything other then a Ruby OpenSSL::PKey::EC object or a OpenSSL::PKey::RSA object" do + it "Raises a TypeError" do + expect do + instance.renew_x509_crl(@crl, "abc", @info) + end.to raise_error(TypeError) + end + end + + context "When the info given is anything other then a Ruby Hash" do + it "Raises a TypeError" do + expect do + instance.renew_x509_crl(@crl, @ca_key, "abc") + end.to raise_error(TypeError) + end + end + + context "When a misformatted info Ruby Hash is given" do + it "Raises a ArgumentError" do + expect do + instance.renew_x509_crl(@crl, @ca_key, "abc" => "def", "validity" => 8) + end.to raise_error(ArgumentError) + end + + it "Raises a TypeError" do + expect do + instance.renew_x509_crl(@crl, @ca_key, "issuer" => "abc", "validity" => 8) + end.to raise_error(TypeError) + end + + it "Raises a TypeError" do + expect do + instance.renew_x509_crl(@crl, @ca_key, "issuer" => @ca_cert, "validity" => "abc") + end.to raise_error(TypeError) + end + end + + context "When given valid parameters to renew a CRL" do + it "Renew a valid x509 CRL" do + @renewed_crl = instance.renew_x509_crl(@crl, @ca_key, @info) + expect(@renewed_crl).to be_kind_of(OpenSSL::X509::CRL) + expect(OpenSSL::X509::CRL.new(@renewed_crl).verify(@ca_key)).to be_truthy + end + end + end + + describe "#revoke_x509_crl" do + before(:all) do + # Generating CA + + @instance = Class.new { include Chef::Mixin::OpenSSLHelper }.new + @ca_key = OpenSSL::PKey::RSA.new(2048) + @ca_cert = OpenSSL::X509::Certificate.new + @ca_cert.version = 2 + @ca_cert.serial = 1 + @ca_cert.subject = OpenSSL::X509::Name.new [%w{CN TestCA}] + @ca_cert.issuer = @ca_cert.subject + @ca_cert.public_key = @ca_key.public_key + @ca_cert.not_before = Time.now + @ca_cert.not_after = @ca_cert.not_before + 365 * 24 * 60 * 60 + ef = OpenSSL::X509::ExtensionFactory.new + ef.subject_certificate = @ca_cert + ef.issuer_certificate = @ca_cert + @ca_cert.add_extension(ef.create_extension("basicConstraints", "CA:TRUE", true)) + @ca_cert.add_extension(ef.create_extension("keyUsage", "keyCertSign, cRLSign", true)) + @ca_cert.add_extension(ef.create_extension("subjectKeyIdentifier", "hash", false)) + @ca_cert.add_extension(ef.create_extension("authorityKeyIdentifier", "keyid:always", false)) + @ca_cert.sign(@ca_key, OpenSSL::Digest::SHA256.new) + + @info = { "validity" => 8, "issuer" => @ca_cert } + + @crl = @instance.gen_x509_crl(@ca_key, @info) + @revoke_info = { "serial" => 1, "reason" => 0 } + end + + context "When the revoke_info given is anything other then a Ruby Hash" do + it "Raises a TypeError" do + expect do + instance.revoke_x509_crl("abc", @crl, @ca_key, @info) + end.to raise_error(TypeError) + end + end + + context "When the CRL given is anything other then a Ruby OpenSSL::X509::CRL object" do + it "Raises a TypeError" do + expect do + instance.revoke_x509_crl(@revoke_info, "abc", @ca_key, @info) + end.to raise_error(TypeError) + end + end + + context "When the CA private key given is anything other then a Ruby OpenSSL::PKey::EC object or a OpenSSL::PKey::RSA object" do + it "Raises a TypeError" do + expect do + instance.revoke_x509_crl(@revoke_info, @crl, "abc", @info) + end.to raise_error(TypeError) + end + end + + context "When the info given is anything other then a Ruby Hash" do + it "Raises a TypeError" do + expect do + instance.revoke_x509_crl(@revoke_info, @crl, @ca_key, "abc") + end.to raise_error(TypeError) + end + end + + context "When a misformatted revoke_info Ruby Hash is given" do + it "Raises a ArgumentError" do + expect do + instance.revoke_x509_crl({ "abc" => "def", "ghi" => "jkl" }, @crl, @ca_key, @info) + end.to raise_error(ArgumentError) + end + + it "Raises a TypeError" do + expect do + instance.revoke_x509_crl({ "serial" => [], "reason" => 0 }, @crl, @ca_key, @info) + end.to raise_error(TypeError) + end + + it "Raises a TypeError" do + expect do + instance.revoke_x509_crl({ "serial" => 1, "reason" => "abc" }, @crl, @ca_key, @info) + end.to raise_error(TypeError) + end + end + + context "When a misformatted info Ruby Hash is given" do + it "Raises a ArgumentError" do + expect do + instance.revoke_x509_crl(@revoke_info, @crl, @ca_key, "abc" => "def", "validity" => 8) + end.to raise_error(ArgumentError) + end + + it "Raises a TypeError" do + expect do + instance.revoke_x509_crl(@revoke_info, @crl, @ca_key, "issuer" => "abc", "validity" => 8) + end.to raise_error(TypeError) + end + + it "Raises a TypeError" do + expect do + instance.revoke_x509_crl(@revoke_info, @crl, @ca_key, "issuer" => @ca_cert, "validity" => "abc") + end.to raise_error(TypeError) + end + end + + context "When given valid parameters to revoke a Serial in a CRL" do + it "Revoke a Serial in a CRL" do + @crl_with_revoked_serial = instance.revoke_x509_crl(@revoke_info, @crl, @ca_key, @info) + expect(@crl_with_revoked_serial).to be_kind_of(OpenSSL::X509::CRL) + expect(OpenSSL::X509::CRL.new(@crl_with_revoked_serial).verify(@ca_key)).to be_truthy + expect(instance.serial_revoked?(@crl_with_revoked_serial, 1)).to be_truthy end end end diff --git a/spec/unit/provider/mount/mount_spec.rb b/spec/unit/provider/mount/mount_spec.rb index 2af3c93fc9..2353d992d0 100644 --- a/spec/unit/provider/mount/mount_spec.rb +++ b/spec/unit/provider/mount/mount_spec.rb @@ -43,6 +43,7 @@ describe Chef::Provider::Mount::Mount do describe "when discovering the current fs state" do before do allow(@provider).to receive(:shell_out_compacted!).and_return(OpenStruct.new(stdout: "")) + allow(::File).to receive(:exist?).with("/etc/fstab").and_return(true) allow(::File).to receive(:foreach).with("/etc/fstab") end diff --git a/spec/unit/provider/osx_profile_spec.rb b/spec/unit/provider/osx_profile_spec.rb index 08d2eebdc4..8f99ad6817 100644 --- a/spec/unit/provider/osx_profile_spec.rb +++ b/spec/unit/provider/osx_profile_spec.rb @@ -116,7 +116,7 @@ describe Chef::Provider::OsxProfile do allow(provider).to receive(:generate_tempfile).and_return(tempfile) allow(provider).to receive(:get_installed_profiles).and_call_original allow(provider).to receive(:read_plist).and_return(all_profiles) - expect(provider).to receive(:shell_out_compacted!).with("profiles", "-P", "-o", "/tmp/allprofiles.plist") + expect(provider).to receive(:shell_out_compacted!).with("/usr/bin/profiles", "-P", "-o", "/tmp/allprofiles.plist") provider.load_current_resource end @@ -166,7 +166,7 @@ describe Chef::Provider::OsxProfile do all_profiles["_computerlevel"][1]["ProfileUUID"] = "1781fbec-3325-565f-9022-9bb39245d4dd" provider.load_current_resource allow(provider).to receive(:write_profile_to_disk).and_return(profile_path) - expect(provider).to receive(:shell_out_compacted).with("profiles", "-I", "-F", profile_path).and_return(shell_out_success) + expect(provider).to receive(:shell_out_compacted).with("/usr/bin/profiles", "-I", "-F", profile_path).and_return(shell_out_success) provider.action_install() end @@ -250,7 +250,7 @@ describe Chef::Provider::OsxProfile do new_resource.identifier "com.testprofile.screensaver" new_resource.action(:remove) provider.load_current_resource - expect(provider).to receive(:shell_out_compacted).with("profiles", "-R", "-p", new_resource.identifier).and_return(shell_out_success) + expect(provider).to receive(:shell_out_compacted).with("/usr/bin/profiles", "-R", "-p", new_resource.identifier).and_return(shell_out_success) provider.action_remove() end end diff --git a/spec/unit/provider/package/rubygems_spec.rb b/spec/unit/provider/package/rubygems_spec.rb index 6b33ab97f9..2e9888fb78 100644 --- a/spec/unit/provider/package/rubygems_spec.rb +++ b/spec/unit/provider/package/rubygems_spec.rb @@ -27,6 +27,19 @@ module GemspecBackcompatCreator end end +# this is a global variable we construct of the highest rspec-core version which is installed, using APIs which +# will break out of the bundle -- and done this way so that we can mock all these internal Gem APIs later... +class RspecVersionString + def self.rspec_version_string + @rspec_version_string ||= begin + stubs = Gem::Specification.send(:installed_stubs, Gem::Specification.dirs, "rspec-core-*.gemspec") + stubs.select! { |stub| stub.name == "rspec-core" && Gem::Dependency.new("rspec-core", ">= 0").requirement.satisfied_by?(stub.version) } + stubs.max_by(&:version).version.to_s + end + end +end +RspecVersionString.rspec_version_string + require "spec_helper" require "ostruct" @@ -57,7 +70,7 @@ describe Chef::Provider::Package::Rubygems::CurrentGemEnvironment do end it "determines the installed versions of gems from the source index (part2: the unmockening)" do - expected = ["rspec-core", Gem::Version.new(RSpec::Core::Version::STRING)] + expected = ["rspec-core", Gem::Version.new( RspecVersionString.rspec_version_string )] actual = @gem_env.installed_versions(Gem::Dependency.new("rspec-core", nil)).map { |spec| [spec.name, spec.version] } expect(actual).to include(expected) end @@ -247,7 +260,7 @@ describe Chef::Provider::Package::Rubygems::AlternateGemEnvironment do end skip("cant find your gem executable") if path_to_gem.empty? gem_env = Chef::Provider::Package::Rubygems::AlternateGemEnvironment.new(path_to_gem) - expected = ["rspec-core", Gem::Version.new(RSpec::Core::Version::STRING)] + expected = ["rspec-core", Gem::Version.new( RspecVersionString.rspec_version_string )] actual = gem_env.installed_versions(Gem::Dependency.new("rspec-core", nil)).map { |s| [s.name, s.version] } expect(actual).to include(expected) end @@ -400,7 +413,7 @@ describe Chef::Provider::Package::Rubygems do end describe "when new_resource version is an rspec version" do - let(:current_version) { RSpec::Core::Version::STRING } + let(:current_version) { RspecVersionString.rspec_version_string } let(:target_version) { current_version } it "triggers a gem configuration load so a later one will not stomp its config values" do diff --git a/spec/unit/provider/package/windows_spec.rb b/spec/unit/provider/package/windows_spec.rb index 3030b7f04a..6b85013f3d 100644 --- a/spec/unit/provider/package/windows_spec.rb +++ b/spec/unit/provider/package/windows_spec.rb @@ -360,6 +360,7 @@ describe Chef::Provider::Package::Windows, :windows_only do before do new_resource.version("5.5.5") allow(provider).to receive(:current_version_array).and_return([ ["5.5.0", "4.3.0", "1.1.1"] ]) + allow(provider).to receive(:version_compare).and_return(false) end it "installs given version" do diff --git a/spec/unit/provider/package_spec.rb b/spec/unit/provider/package_spec.rb index 904e339e47..688d70d677 100644 --- a/spec/unit/provider/package_spec.rb +++ b/spec/unit/provider/package_spec.rb @@ -702,7 +702,7 @@ describe "Chef::Provider::Package - Multi" do it "installs the specified version when some are out of date" do current_resource.version(["1.0", "6.2"]) - new_resource.version(["1.0", "6.1"]) + new_resource.version(["1.0", "6.3"]) provider.run_action(:install) expect(new_resource).to be_updated end @@ -714,6 +714,13 @@ describe "Chef::Provider::Package - Multi" do expect(new_resource).not_to be_updated_by_last_action end + it "does not install older version" do + current_resource.version(["1.1", "6.2"]) + new_resource.version(["1.0", "6.1"]) + provider.run_action(:install) + expect(new_resource).not_to be_updated_by_last_action + end + it "does not install any version if all are installed, and no version was specified" do current_resource.version(["1.0", "6.2"]) provider.run_action(:install) diff --git a/spec/unit/provider/user/windows_spec.rb b/spec/unit/provider/user/windows_spec.rb index dab4814d44..76234def1a 100644 --- a/spec/unit/provider/user/windows_spec.rb +++ b/spec/unit/provider/user/windows_spec.rb @@ -65,7 +65,7 @@ describe Chef::Provider::User::Windows do describe "and the properties match" do it "doesn't set the comment field to be updated" do - expect(@provider.set_options).not_to have_key(:full_name) + expect(@provider.set_options).not_to have_key(:comment) end it "doesn't set the home directory to be updated" do @@ -102,8 +102,8 @@ describe Chef::Provider::User::Windows do @provider.current_resource = @current_resource end - it "marks the full_name field to be updated" do - expect(@provider.set_options[:full_name]).to eq("Adam Jacob") + it "marks the comment field to be updated" do + expect(@provider.set_options[:comment]).to eq("Adam Jacob") end it "marks the home_dir property to be updated" do diff --git a/spec/unit/resource/cron_access_spec.rb b/spec/unit/resource/cron_access_spec.rb new file mode 100644 index 0000000000..8fd65a9c60 --- /dev/null +++ b/spec/unit/resource/cron_access_spec.rb @@ -0,0 +1,36 @@ +# +# Copyright:: Copyright 2018, 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" + +describe Chef::Resource::CronAccess do + let(:resource) { Chef::Resource::CronAccess.new("bob") } + + it "has a default action of [:deny]" do + expect(resource.action).to eql([:allow]) + end + + it "accepts create or delete for action" do + expect { resource.action :allow }.not_to raise_error + expect { resource.action :deny }.not_to raise_error + expect { resource.action :lolcat }.to raise_error(ArgumentError) + end + + it "the user property is the name_property" do + expect(resource.user).to eql("bob") + end +end diff --git a/spec/unit/resource/cron_d_spec.rb b/spec/unit/resource/cron_d_spec.rb new file mode 100644 index 0000000000..6d29a17aaf --- /dev/null +++ b/spec/unit/resource/cron_d_spec.rb @@ -0,0 +1,90 @@ +# +# Copyright:: Copyright 2018, 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" + +describe Chef::Resource::CronD do + let(:resource) { Chef::Resource::CronD.new("cronify") } + + it "has a default action of [:create]" do + expect(resource.action).to eql([:create]) + end + + it "accepts create or delete for action" do + expect { resource.action :create }.not_to raise_error + expect { resource.action :delete }.not_to raise_error + expect { resource.action :lolcat }.to raise_error(ArgumentError) + end + + it "the cron_name property is the name_property" do + expect(resource.cron_name).to eql("cronify") + end + + context "#validate_dow" do + it "it accepts a string day" do + expect(Chef::Resource::CronD.validate_dow("mon")).to be true + end + + it "it accepts an integer day" do + expect(Chef::Resource::CronD.validate_dow(0)).to be true + end + + it "it accepts the string of *" do + expect(Chef::Resource::CronD.validate_dow("*")).to be true + end + + it "returns false for an out of range integer" do + expect(Chef::Resource::CronD.validate_dow(8)).to be false + end + + it "returns false for an invalid string" do + expect(Chef::Resource::CronD.validate_dow("monday")).to be false + end + end + + context "#validate_month" do + it "it accepts a string month" do + expect(Chef::Resource::CronD.validate_month("feb")).to be true + end + + it "it accepts an integer month" do + expect(Chef::Resource::CronD.validate_month(2)).to be true + end + + it "it accepts the string of *" do + expect(Chef::Resource::CronD.validate_month("*")).to be true + end + + it "returns false for an out of range integer" do + expect(Chef::Resource::CronD.validate_month(13)).to be false + end + + it "returns false for an invalid string" do + expect(Chef::Resource::CronD.validate_month("janurary")).to be false + end + end + + context "#validate_numeric" do + it "returns true if the value is in the allowed range" do + expect(Chef::Resource::CronD.validate_numeric(5, 1, 100)).to be true + end + + it "returns false if the value is out of the allowed range" do + expect(Chef::Resource::CronD.validate_numeric(-1, 1, 100)).to be false + end + end +end diff --git a/spec/unit/resource/openssl_ec_private_key_spec.rb b/spec/unit/resource/openssl_ec_private_key_spec.rb new file mode 100644 index 0000000000..c5cac33257 --- /dev/null +++ b/spec/unit/resource/openssl_ec_private_key_spec.rb @@ -0,0 +1,64 @@ +# +# Copyright:: Copyright 2018, 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" + +describe Chef::Resource::OpensslEcPrivateKey do + + let(:resource) { Chef::Resource::OpensslEcPrivateKey.new("fakey_fakerton") } + + it "has a resource name of :openssl_ec_private_key" do + expect(resource.resource_name).to eql(:openssl_ec_private_key) + end + + it "the path property is the name_property" do + expect(resource.path).to eql("fakey_fakerton") + end + + it "sets the default action as :create" do + expect(resource.action).to eql([:create]) + end + + it "supports :create action" do + expect { resource.action :create }.not_to raise_error + end + + it "has a default mode of '0600'" do + expect(resource.mode).to eql("0600") + end + + it "has a default key_cipher of 'des3'" do + expect(resource.key_cipher).to eql("des3") + end + + it "only accepts valid key_cipher values" do + expect { resource.key_cipher "fako" }.to raise_error(ArgumentError) + end + + it "has a default key_curve of 'prime256v1'" do + expect(resource.key_curve).to eql("prime256v1") + end + + it "only accepts valid key_curve values" do + expect { resource.key_curve "fako" }.to raise_error(ArgumentError) + end + + it "has a default force value of of false" do + expect(resource.force).to eql(false) + end + +end diff --git a/spec/unit/resource/openssl_ec_public_key_spec.rb b/spec/unit/resource/openssl_ec_public_key_spec.rb new file mode 100644 index 0000000000..dcc6b20103 --- /dev/null +++ b/spec/unit/resource/openssl_ec_public_key_spec.rb @@ -0,0 +1,43 @@ +# +# Copyright:: Copyright 2018, 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" + +describe Chef::Resource::OpensslEcPublicKey do + + let(:resource) { Chef::Resource::OpensslEcPublicKey.new("key") } + + it "has a resource name of :openssl_ec_public_key" do + expect(resource.resource_name).to eql(:openssl_ec_public_key) + end + + it "the path property is the name_property" do + expect(resource.path).to eql("key") + end + + it "sets the default action as :create" do + expect(resource.action).to eql([:create]) + end + + it "supports :create action" do + expect { resource.action :create }.not_to raise_error + end + + it "has a default mode of '0640'" do + expect(resource.mode).to eql("0640") + end +end diff --git a/spec/unit/resource/openssl_x509_certificate_spec.rb b/spec/unit/resource/openssl_x509_certificate_spec.rb new file mode 100644 index 0000000000..795987f569 --- /dev/null +++ b/spec/unit/resource/openssl_x509_certificate_spec.rb @@ -0,0 +1,72 @@ +# +# Copyright:: Copyright 2018, 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" + +describe Chef::Resource::OpensslX509Certificate do + + let(:resource) { Chef::Resource::OpensslX509Certificate.new("fakey_fakerton") } + + it "has a resource name of :openssl_x509_certificate" do + expect(resource.resource_name).to eql(:openssl_x509_certificate) + end + + it "the path property is the name_property" do + expect(resource.path).to eql("fakey_fakerton") + end + + it "sets the default action as :create" do + expect(resource.action).to eql([:create]) + end + + it "supports :create action" do + expect { resource.action :create }.not_to raise_error + end + + it "has a default expiration of 365" do + expect(resource.expire).to eql(365) + end + + it "has a default key_type of 'rsa'" do + expect(resource.key_type).to eql("rsa") + end + + it "only accepts valid key_type values" do + expect { resource.key_type "fako" }.to raise_error(ArgumentError) + end + + it "has a default key_length of '2048'" do + expect(resource.key_length).to eql(2048) + end + + it "only accepts valid key_length values" do + expect { resource.key_length 1023 }.to raise_error(ArgumentError) + end + + it "has a default key_curve of 'prime256v1'" do + expect(resource.key_curve).to eql("prime256v1") + end + + it "only accepts valid key_curve values" do + expect { resource.key_curve "fako" }.to raise_error(ArgumentError) + end + + it "mode accepts both String and Integer values" do + expect { resource.mode "644" }.not_to raise_error + expect { resource.mode 644 }.not_to raise_error + end +end diff --git a/spec/unit/resource/openssl_x509_crl_spec.rb b/spec/unit/resource/openssl_x509_crl_spec.rb new file mode 100644 index 0000000000..4f852be0c2 --- /dev/null +++ b/spec/unit/resource/openssl_x509_crl_spec.rb @@ -0,0 +1,61 @@ +# +# Copyright:: Copyright 2018, 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" + +describe Chef::Resource::OpensslX509Crl do + + let(:resource) { Chef::Resource::OpensslX509Crl.new("fakey_fakerton") } + + it "has a resource name of :openssl_x509_crl" do + expect(resource.resource_name).to eql(:openssl_x509_crl) + end + + it "the path property is the name_property" do + expect(resource.path).to eql("fakey_fakerton") + end + + it "sets the default action as :create" do + expect(resource.action).to eql([:create]) + end + + it "supports :create action" do + expect { resource.action :create }.not_to raise_error + end + + it "has a default revocation_reason of 0" do + expect(resource.revocation_reason).to eql(0) + end + + it "has a default expiration of 8" do + expect(resource.expire).to eql(8) + end + + it "has a default renewal_threshold of 1" do + expect(resource.renewal_threshold).to eql(1) + end + + it "serial_to_revoke accepts both String and Integer values" do + expect { resource.serial_to_revoke "123" }.not_to raise_error + expect { resource.serial_to_revoke 123 }.not_to raise_error + end + + it "mode accepts both String and Integer values" do + expect { resource.mode "644" }.not_to raise_error + expect { resource.mode 644 }.not_to raise_error + end +end diff --git a/spec/unit/resource/openssl_x509_request.rb b/spec/unit/resource/openssl_x509_request.rb new file mode 100644 index 0000000000..28ca4f7345 --- /dev/null +++ b/spec/unit/resource/openssl_x509_request.rb @@ -0,0 +1,68 @@ +# +# Copyright:: Copyright 2018, 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" + +describe Chef::Resource::OpensslX509Request do + + let(:resource) { Chef::Resource::OpensslX509Request.new("fakey_fakerton") } + + it "has a resource name of :openssl_x509_request" do + expect(resource.resource_name).to eql(:openssl_x509_request) + end + + it "the path property is the name_property" do + expect(resource.path).to eql("fakey_fakerton") + end + + it "sets the default action as :create" do + expect(resource.action).to eql([:create]) + end + + it "supports :create action" do + expect { resource.action :create }.not_to raise_error + end + + it "has a default key_type of 'ec'" do + expect(resource.key_type).to eql("ec") + end + + it "only accepts valid key_type values" do + expect { resource.key_type "fako" }.to raise_error(ArgumentError) + end + + it "has a default key_length of '2048'" do + expect(resource.key_length).to eql(2048) + end + + it "only accepts valid key_length values" do + expect { resource.key_length 1023 }.to raise_error(ArgumentError) + end + + it "has a default key_curve of 'prime256v1'" do + expect(resource.key_curve).to eql("prime256v1") + end + + it "only accepts valid key_curve values" do + expect { resource.key_curve "fako" }.to raise_error(ArgumentError) + end + + it "mode accepts both String and Integer values" do + expect { resource.mode "644" }.not_to raise_error + expect { resource.mode 644 }.not_to raise_error + end +end diff --git a/spec/unit/resource/registry_key_spec.rb b/spec/unit/resource/registry_key_spec.rb index 147bc8492c..47d624a758 100644 --- a/spec/unit/resource/registry_key_spec.rb +++ b/spec/unit/resource/registry_key_spec.rb @@ -133,6 +133,10 @@ describe Chef::Resource::RegistryKey, "values" do expect { resource.values([ { name: "123", type: :string, data: "carmen" } ]) }.to_not raise_error end end + + it "does not raise an exception if keys are in string format" do + expect { resource.values([ { "name" => "123", "type" => :string, "data" => "carmen" } ]) }.to_not raise_error + end end describe Chef::Resource::RegistryKey, "recursive" do diff --git a/spec/unit/resource/systemd_unit_spec.rb b/spec/unit/resource/systemd_unit_spec.rb index fa30255885..f05418eb34 100644 --- a/spec/unit/resource/systemd_unit_spec.rb +++ b/spec/unit/resource/systemd_unit_spec.rb @@ -20,11 +20,12 @@ require "spec_helper" describe Chef::Resource::SystemdUnit do let(:resource) { Chef::Resource::SystemdUnit.new("sysstat-collect.timer") } - let(:unit_content_string) { "[Unit]\nDescription = Run system activity accounting tool every 10 minutes\n\n[Timer]\nOnCalendar = *:00/10\n\n[Install]\nWantedBy = sysstat.service\n" } + let(:unit_content_string) { "[Unit]\nDescription = Run system activity accounting tool every 10 minutes\nDocumentation = foo\nDocumentation = bar\n\n[Timer]\nOnCalendar = *:00/10\n\n[Install]\nWantedBy = sysstat.service\n" } let(:unit_content_hash) do { "Unit" => { "Description" => "Run system activity accounting tool every 10 minutes", + "Documentation" => %w{foo bar}, }, "Timer" => { "OnCalendar" => "*:00/10", diff --git a/spec/unit/resource/windows_task_spec.rb b/spec/unit/resource/windows_task_spec.rb index cbf15092f5..76e2a86ee8 100644 --- a/spec/unit/resource/windows_task_spec.rb +++ b/spec/unit/resource/windows_task_spec.rb @@ -53,6 +53,14 @@ describe Chef::Resource::WindowsTask, :windows_only do expect(resource.frequency_modifier).to eql(1) end + it "sets the default value for disallow_start_if_on_batteries as false" do + expect(resource.disallow_start_if_on_batteries).to eql(false) + end + + it "sets the default value for stop_if_going_on_batteries as false" do + expect(resource.stop_if_going_on_batteries).to eql(false) + end + context "when frequency is not provided" do it "raises ArgumentError to provide frequency" do expect { resource.after_created }.to raise_error(ArgumentError, "Frequency needs to be provided. Valid frequencies are :minute, :hourly, :daily, :weekly, :monthly, :once, :on_logon, :onstart, :on_idle, :none." ) diff --git a/spec/unit/resource_spec.rb b/spec/unit/resource_spec.rb index a4f64e11e1..921ca6d33e 100644 --- a/spec/unit/resource_spec.rb +++ b/spec/unit/resource_spec.rb @@ -966,6 +966,32 @@ describe Chef::Resource do end end + describe "chef_version constraints and the platform map" do + let(:klz3) { Class.new(Chef::Resource) } + + it "doesn't wire up the provides when chef_version is < 1" do + klz3.provides :bulbasaur, chef_version: "< 1.0" # this should be false + expect { Chef::Resource.resource_for_node(:bulbasaur, node) }.to raise_error(Chef::Exceptions::NoSuchResourceType) + end + + it "wires up the provides when chef_version is > 1" do + klz3.provides :bulbasaur, chef_version: "> 1.0" # this should be true + expect(Chef::Resource.resource_for_node(:bulbasaur, node)).to eql(klz3) + end + + it "wires up the default when chef_version is < 1" do + klz3.chef_version_for_provides("< 1.0") # this should be false + klz3.provides :bulbasaur + expect { Chef::Resource.resource_for_node(:bulbasaur, node) }.to raise_error(Chef::Exceptions::NoSuchResourceType) + end + + it "wires up the default when chef_version is > 1" do + klz3.chef_version_for_provides("> 1.0") # this should be true + klz3.provides :bulbasaur + expect(Chef::Resource.resource_for_node(:bulbasaur, node)).to eql(klz3) + end + end + end describe "when creating notifications" do |