summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn McCrae <john.mccrae@progress.com>2022-02-01 11:09:06 -0800
committerGitHub <noreply@github.com>2022-02-01 11:09:06 -0800
commitcdfc851fa0a5ca2c2ce598a403d41e17d13189b0 (patch)
tree6e25bc62810d6b4936635f9edde7c998de07beaa
parent6fb40bcfbe2be4b23581493e697756a52be84e70 (diff)
parent0baa4e8bfbae9d17465fd4fa1d23652e58bcef2f (diff)
downloadchef-cdfc851fa0a5ca2c2ce598a403d41e17d13189b0.tar.gz
Merge pull request #12426 from chef/jfm/win_certs_take2
-rw-r--r--Gemfile.lock7
-rw-r--r--Rakefile19
-rw-r--r--chef-universal-mingw32.gemspec1
-rw-r--r--lib/chef/client.rb11
-rw-r--r--lib/chef/http/authenticator.rb120
-rw-r--r--lib/chef/mixin/powershell_exec.rb33
-rw-r--r--lib/chef/win32/registry.rb6
-rw-r--r--spec/functional/resource/dsc_script_spec.rb2
-rw-r--r--spec/integration/client/client_spec.rb73
-rw-r--r--spec/unit/client_spec.rb4
-rw-r--r--spec/unit/mixin/powershell_exec_spec.rb10
-rw-r--r--spec/unit/platform/query_helpers_spec.rb23
-rw-r--r--spec/unit/util/dsc/local_configuration_manager_spec.rb2
13 files changed, 231 insertions, 80 deletions
diff --git a/Gemfile.lock b/Gemfile.lock
index a7b2cc37ee..752d7a9ebb 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -71,6 +71,7 @@ PATH
aws-sdk-s3 (~> 1.91)
aws-sdk-secretsmanager (~> 1.46)
chef-config (= 18.0.25)
+ chef-powershell (~> 1.0.12)
chef-utils (= 18.0.25)
chef-vault
chef-zero (>= 14.0.11)
@@ -164,6 +165,9 @@ GEM
debug_inspector (>= 0.0.1)
builder (3.2.4)
byebug (11.1.3)
+ chef-powershell (1.0.13)
+ ffi (~> 1.15)
+ ffi-yajl (~> 2.4)
chef-telemetry (1.1.1)
chef-config
concurrent-ruby (~> 1.0)
@@ -438,7 +442,6 @@ GEM
wmi-lite (1.0.5)
PLATFORMS
- arm64-darwin-20
ruby
x64-mingw32
x86-mingw32
@@ -466,4 +469,4 @@ DEPENDENCIES
webmock
BUNDLED WITH
- 2.2.32
+ 2.3.5
diff --git a/Rakefile b/Rakefile
index b0dfb63b26..17c6a62ca8 100644
--- a/Rakefile
+++ b/Rakefile
@@ -99,25 +99,6 @@ task :register_eventlog do
end
end
-desc "Copies powershell_exec related binaries from the latest built Habitat Packages"
-task :update_chef_exec_dll do
- raise "This task must be run on Windows since we are installing a Windows targeted package!" unless Gem.win_platform?
-
- require "mkmf"
- raise "Unable to locate Habitat cli. Please install Habitat cli before invoking this task!" unless find_executable "hab"
-
- sh("hab pkg install chef/chef-powershell-shim")
- sh("hab pkg install chef/chef-powershell-shim-x86")
- x64 = `hab pkg path chef/chef-powershell-shim`.chomp.tr("\\", "/")
- x86 = `hab pkg path chef/chef-powershell-shim-x86`.chomp.tr("\\", "/")
- FileUtils.rm_rf(Dir["distro/ruby_bin_folder/AMD64/*"])
- FileUtils.rm_rf(Dir["distro/ruby_bin_folder/x86/*"])
- puts "Copying #{x64}/bin/* to distro/ruby_bin_folder/AMD64"
- FileUtils.cp_r(Dir["#{x64}/bin/*"], "distro/ruby_bin_folder/AMD64")
- puts "Copying #{x86}/bin/* to distro/ruby_bin_folder/x86"
- FileUtils.cp_r(Dir["#{x86}/bin/*"], "distro/ruby_bin_folder/x86")
-end
-
begin
require "chefstyle"
require "rubocop/rake_task"
diff --git a/chef-universal-mingw32.gemspec b/chef-universal-mingw32.gemspec
index 329b4f9d6b..bf7446ed02 100644
--- a/chef-universal-mingw32.gemspec
+++ b/chef-universal-mingw32.gemspec
@@ -15,6 +15,7 @@ gemspec.add_dependency "wmi-lite", "~> 1.0"
gemspec.add_dependency "win32-taskscheduler", "~> 2.0"
gemspec.add_dependency "iso8601", ">= 0.12.1", "< 0.14" # validate 0.14 when it comes out
gemspec.add_dependency "win32-certstore", "~> 0.6.2" # 0.5+ required for specifying user vs. system store
+gemspec.add_dependency "chef-powershell", "~> 1.0.12" # The guts of the powershell_exec code have been moved to its own gem, chef-powershell. It's part of the chef-powershell-shim repo.
gemspec.extensions << "ext/win32-eventlog/Rakefile"
gemspec.files += Dir.glob("{distro,ext}/**/*")
diff --git a/lib/chef/client.rb b/lib/chef/client.rb
index 7f184d7db4..5ec15fb582 100644
--- a/lib/chef/client.rb
+++ b/lib/chef/client.rb
@@ -229,7 +229,7 @@ class Chef
start_profiling
runlock = RunLock.new(Chef::Config.lockfile)
- # TODO feels like acquire should have its own block arg for this
+ # TODO: feels like acquire should have its own block arg for this
runlock.acquire
# don't add code that may fail before entering this section to be sure to release lock
begin
@@ -637,7 +637,14 @@ class Chef
# @api private
#
def register(client_name = node_name, config = Chef::Config)
- if !config[:client_key]
+ if Chef::HTTP::Authenticator.detect_certificate_key(client_name)
+ if File.exists?(config[:client_key])
+ logger.warn("WARNING - Client key #{client_name} is present on disk, ignoring that in favor of key stored in CertStore")
+ end
+ events.skipping_registration(client_name, config)
+ logger.trace("Client key #{client_name} is present in certificate repository - skipping registration")
+ config[:client_key] = "Cert:\\LocalMachine\\My\\chef-#{client_name}"
+ elsif !config[:client_key]
events.skipping_registration(client_name, config)
logger.trace("Client key is unspecified - skipping registration")
elsif File.exists?(config[:client_key])
diff --git a/lib/chef/http/authenticator.rb b/lib/chef/http/authenticator.rb
index 80b32be750..26413c283b 100644
--- a/lib/chef/http/authenticator.rb
+++ b/lib/chef/http/authenticator.rb
@@ -16,15 +16,20 @@
# limitations under the License.
#
+require "chef/mixin/powershell_exec"
require_relative "auth_credentials"
require_relative "../exceptions"
+require_relative "../win32/registry"
autoload :OpenSSL, "openssl"
class Chef
class HTTP
class Authenticator
-
DEFAULT_SERVER_API_VERSION = "2".freeze
+ # cspell:disable-next-line
+ SOME_CHARS = "~!@#%^&*_-+=`|\\(){}[<]:;'>,.?/0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz".each_char.to_a
+
+ extend Chef::Mixin::PowershellExec
attr_reader :signing_key_filename
attr_reader :raw_key
@@ -83,8 +88,53 @@ class Chef
@auth_credentials.client_name
end
+ def detect_certificate_key(client_name)
+ self.class.detect_certificate_key(client_name)
+ end
+
+ def check_certstore_for_key(client_name)
+ self.class.check_certstore_for_key(client_name)
+ end
+
+ def retrieve_certificate_key(client_name)
+ self.class.retrieve_certificate_key(client_name)
+ end
+
+ # Detects if a private key exists in a certificate repository like Keychain (macOS) or Certificate Store (Windows)
+ #
+ # @param client_name - we're using the node name to store and retrieve any keys
+ # Returns true if a key is found, false if not. False will trigger a registration event which will lead to a certificate based key being created
+ #
+ def self.detect_certificate_key(client_name)
+ if ChefUtils.windows?
+ check_certstore_for_key(client_name)
+ else # generic return for Mac and LInux clients
+ false
+ end
+ end
+
+ def self.check_certstore_for_key(client_name)
+ powershell_code = <<~CODE
+ $cert = Get-ChildItem -path cert:\\LocalMachine\\My -Recurse -Force | Where-Object { $_.Subject -Match "#{client_name}" } -ErrorAction Stop
+ if (($cert.HasPrivateKey -eq $true) -and ($cert.PrivateKey.Key.ExportPolicy -ne "NonExportable")) {
+ return $true
+ }
+ else{
+ return $false
+ }
+ CODE
+ powershell_exec!(powershell_code).result
+ end
+
def load_signing_key(key_file, raw_key = nil)
- if !!key_file
+ results = retrieve_certificate_key(Chef::Config[:node_name])
+
+ if key_file == nil? && raw_key == nil?
+ puts "\nNo key detected\n"
+ elsif !!results
+ # results variable can be 1 of 2 values - "False" or the contents of a key.
+ @raw_key = results
+ elsif !!key_file
@raw_key = IO.read(key_file).strip
elsif !!raw_key
@raw_key = raw_key.strip
@@ -104,6 +154,72 @@ class Chef
raise Chef::Exceptions::InvalidPrivateKey, msg
end
+ # takes no parameters. Checks for the password in the registry and returns it if there, otherwise returns false
+ def self.get_cert_password
+ @win32registry = Chef::Win32::Registry.new
+ path = "HKEY_LOCAL_MACHINE\\Software\\Progress\\Authentication"
+ # does the registry key even exist?
+ present = @win32registry.get_values(path)
+ if present.nil? || present.empty?
+ raise Chef::Exceptions::Win32RegKeyMissing
+ end
+
+ present.each do |secret|
+ if secret[:name] == "PfxPass"
+ return secret[:data]
+ end
+ end
+
+ # if we make it this far, that means there is no valid password in the Registry. Fail out to correct that.
+ raise Chef::Exceptions::Win32RegKeyMissing
+
+ rescue Chef::Exceptions::Win32RegKeyMissing
+ # if we don't have a password, log that and generate one
+ Chef::Log.warn "Authentication Hive and value not present in registry, creating it now"
+ new_path = "HKEY_LOCAL_MACHINE\\Software\\Progress\\Authentication"
+ unless @win32registry.key_exists?(new_path)
+ @win32registry.create_key(new_path, true)
+ end
+ password = SOME_CHARS.sample(1 + rand(SOME_CHARS.count)).join[0...14]
+ values = { name: "PfxPass", type: :string, data: password }
+ @win32registry.set_value(new_path, values)
+ password
+ end
+
+ def self.retrieve_certificate_key(client_name)
+ require "openssl" unless defined?(OpenSSL)
+
+ if ChefUtils.windows?
+
+ password = get_cert_password
+
+ return false unless password
+
+ if check_certstore_for_key(client_name)
+ powershell_code = <<~CODE
+ Try {
+ $my_pwd = ConvertTo-SecureString -String "#{password}" -Force -AsPlainText;
+ $cert = Get-ChildItem -path cert:\\LocalMachine\\My -Recurse | Where-Object { $_.Subject -match "#{client_name}" } -ErrorAction Stop;
+ $tempfile = [System.IO.Path]::GetTempPath() + "export_pfx.pfx";
+ Export-PfxCertificate -Cert $cert -Password $my_pwd -FilePath $tempfile;
+ }
+ Catch {
+ return $false
+ }
+ CODE
+ my_result = powershell_exec!(powershell_code).result
+
+ if !!my_result
+ pkcs = OpenSSL::PKCS12.new(File.binread(my_result["PSPath"].split("::")[1]), password)
+ ::File.delete(my_result["PSPath"].split("::")[1])
+ return OpenSSL::PKey::RSA.new(pkcs.key.to_pem)
+ end
+ end
+ end
+
+ false
+ end
+
def authentication_headers(method, url, json_body = nil, headers = nil)
request_params = {
http_method: method,
diff --git a/lib/chef/mixin/powershell_exec.rb b/lib/chef/mixin/powershell_exec.rb
index 75114220cb..8b11529957 100644
--- a/lib/chef/mixin/powershell_exec.rb
+++ b/lib/chef/mixin/powershell_exec.rb
@@ -15,9 +15,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-require_relative "../powershell"
-require_relative "../pwsh"
-
# The powershell_exec mixin provides in-process access to the PowerShell engine.
#
# powershell_exec is initialized with a string that should be set to the script
@@ -94,35 +91,15 @@ require_relative "../pwsh"
# - It is not possible to impersonate another user running powershell, the
# credentials of the user running Chef Client are used.
#
+if ChefUtils.windows?
+ require "chef-powershell"
+end
class Chef
module Mixin
module PowershellExec
- # Run a command under PowerShell via a managed (.NET) API.
- #
- # Requires: .NET Framework 4.0 or higher on the target machine.
- #
- # @param script [String] script to run
- # @param interpreter [Symbol] the interpreter type, `:powershell` or `:pwsh`
- # @param timeout [Integer, nil] timeout in seconds.
- # @return [Chef::PowerShell] output
- def powershell_exec(script, interpreter = :powershell, timeout: -1)
- case interpreter
- when :powershell
- Chef::PowerShell.new(script, timeout: timeout)
- when :pwsh
- Chef::Pwsh.new(script, timeout: timeout)
- else
- raise ArgumentError, "Expected interpreter of :powershell or :pwsh"
- end
- end
-
- # The same as the #powershell_exec method except this will raise
- # Chef::PowerShell::CommandFailed if the command fails
- def powershell_exec!(script, interpreter = :powershell, **options)
- cmd = powershell_exec(script, interpreter, **options)
- cmd.error!
- cmd
+ if ChefUtils.windows?
+ include ChefPowerShell::ChefPowerShellModule::PowerShellExec
end
end
end
diff --git a/lib/chef/win32/registry.rb b/lib/chef/win32/registry.rb
index 4f7f2b2d52..ec7783815d 100644
--- a/lib/chef/win32/registry.rb
+++ b/lib/chef/win32/registry.rb
@@ -293,7 +293,11 @@ class Chef
end
def machine_architecture
- node[:kernel][:machine].to_sym
+ if node.nil?
+ ::RbConfig::CONFIG["target_cpu"] == "x64" ? :x86_64 : :i386
+ else
+ node[:kernel][:machine].to_sym
+ end
end
def assert_architecture!
diff --git a/spec/functional/resource/dsc_script_spec.rb b/spec/functional/resource/dsc_script_spec.rb
index 6aee29133f..3831486547 100644
--- a/spec/functional/resource/dsc_script_spec.rb
+++ b/spec/functional/resource/dsc_script_spec.rb
@@ -263,7 +263,7 @@ describe Chef::Resource::DscScript, :windows_powershell_dsc_only, :ruby64_only d
dsc_test_resource.cwd(dsc_environment_fail_etc_directory)
expect {
dsc_test_resource.run_action(:run)
- }.to raise_error(Chef::PowerShell::CommandFailed, /#{exception_message_signature}/)
+ }.to raise_error(ChefPowerShell::PowerShellExceptions::PowerShellCommandFailed, /#{exception_message_signature}/)
end
end
end
diff --git a/spec/integration/client/client_spec.rb b/spec/integration/client/client_spec.rb
index af35eadb74..bec58eb682 100644
--- a/spec/integration/client/client_spec.rb
+++ b/spec/integration/client/client_spec.rb
@@ -4,6 +4,10 @@ require "chef/mixin/shell_out"
require "tiny_server"
require "tmpdir"
require "chef-utils/dist"
+require "chef/mixin/powershell_exec"
+
+# cspell:disable-next-line
+SOME_CHARS = "~!@#%^&*_-+=`|\\(){}[<]:;'>,.?/0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz".each_char.to_a.freeze
describe "chef-client" do
@@ -31,8 +35,48 @@ describe "chef-client" do
@server = @api = nil
end
+ def install_certificate_in_store
+ if ChefUtils.windows?
+ powershell_exec!("New-SelfSignedCertificate -certstorelocation cert:\\localmachine\\my -Subject #{client_name} -FriendlyName #{client_name} -KeyExportPolicy Exportable")
+ end
+ end
+
+ def create_registry_key
+ @win32registry = Chef::Win32::Registry.new
+ path = "HKEY_LOCAL_MACHINE\\Software\\Progress\\Authentication"
+ unless @win32registry.key_exists?(path)
+ @win32registry.create_key(path, true)
+ end
+ password = SOME_CHARS.sample(1 + rand(SOME_CHARS.count)).join[0...14]
+ values = { name: "PfxPass", type: :string, data: password }
+ @win32registry.set_value(path, values)
+ end
+
+ def remove_certificate_from_store
+ powershell_exec! <<~EOH
+ Get-ChildItem -path cert:\\LocalMachine\\My -Recurse -Force | Where-Object { $_.Subject -Match "#{client_name}" } -ErrorAction Stop | Remove-Item
+ EOH
+ end
+
+ def remove_registry_key
+ powershell_exec!("Remove-Item -Path HKLM:\\SOFTWARE\\Progress -Recurse")
+ end
+
+ def verify_export_password_exists
+ powershell_exec! <<~EOH
+ Try {
+ $response = Get-ItemPropertyValue -Path "HKLM:\\Software\\Progress\\Authentication" -Name "PfxPass" -ErrorAction Stop
+ if ($response) {return $true}
+ }
+ Catch {
+ return $false
+ }
+ EOH
+ end
+
include IntegrationSupport
include Chef::Mixin::ShellOut
+ include Chef::Mixin::PowershellExec
let(:chef_dir) { File.join(__dir__, "..", "..", "..") }
@@ -47,6 +91,7 @@ describe "chef-client" do
# cf. CHEF-4914
let(:chef_client) { "bundle exec #{ChefUtils::Dist::Infra::CLIENT} --minimal-ohai" }
let(:chef_solo) { "bundle exec #{ChefUtils::Dist::Solo::EXEC} --legacy-mode --minimal-ohai" }
+ let(:client_name) { "chef-973334" }
context "when validation.pem in current Directory" do
let(:validation_path) { "" }
@@ -146,6 +191,34 @@ describe "chef-client" do
result.error!
end
+ if ChefUtils.windows?
+ context "and the private key is in the Windows CertStore" do
+ before do
+ # install the p12/pfx and make sure the key and password are stored in the registry
+ install_certificate_in_store
+ create_registry_key
+ end
+
+ after do
+ # remove the p12/pfx and remove the registry key
+ remove_certificate_from_store
+ remove_registry_key
+ end
+
+ it "should verify that the cert is loaded in the LocalMachine\\My" do
+ expect(Chef::HTTP::Authenticator.check_certstore_for_key(client_name)).to eq(true)
+ end
+
+ it "should verify that the export password for the pfx is loaded in the Registry" do
+ expect(verify_export_password_exists.result).to eq(true)
+ end
+
+ it "should verify that a private key is returned to me" do
+ expect(Chef::HTTP::Authenticator.retrieve_certificate_key(client_name)).not_to be_falsey
+ end
+ end
+ end
+
context "and a private key" do
before do
file "mykey.pem", <<~EOM
diff --git a/spec/unit/client_spec.rb b/spec/unit/client_spec.rb
index b6a321c8e8..1e835ae398 100644
--- a/spec/unit/client_spec.rb
+++ b/spec/unit/client_spec.rb
@@ -113,6 +113,7 @@ shared_context "a client run" do
# --Client.register
# Make sure Client#register thinks the client key doesn't
# exist, so it tries to register and create one.
+ allow(Chef::HTTP::Authenticator).to receive(:detect_certificate_key).with(fqdn).and_return(false)
allow(File).to receive(:exists?).and_call_original
expect(File).to receive(:exists?)
.with(Chef::Config[:client_key])
@@ -201,7 +202,6 @@ shared_context "a client run" do
# Post conditions: check that node has been filled in correctly
expect(client).to receive(:run_started)
-
stub_for_run
end
end
@@ -262,7 +262,7 @@ end
# requires platform and platform_version be defined
shared_examples "a completed run" do
- include_context "run completed"
+ include_context "run completed" # should receive run_completed_successfully
it "runs ohai, sets up authentication, loads node state, synchronizes policy, converges" do
# This is what we're testing.
diff --git a/spec/unit/mixin/powershell_exec_spec.rb b/spec/unit/mixin/powershell_exec_spec.rb
index 92e92dc2a1..b7e7f2a160 100644
--- a/spec/unit/mixin/powershell_exec_spec.rb
+++ b/spec/unit/mixin/powershell_exec_spec.rb
@@ -26,7 +26,7 @@ describe Chef::Mixin::PowershellExec, :windows_only do
describe "#powershell_exec" do
context "not specifying an interpreter" do
it "runs a basic command and returns a Chef::PowerShell object" do
- expect(object.powershell_exec("$PSVersionTable")).to be_kind_of(Chef::PowerShell)
+ expect(object.powershell_exec("$PSVersionTable")).to be_kind_of(ChefPowerShell::PowerShell)
end
it "uses less than version 6" do
@@ -37,7 +37,7 @@ describe Chef::Mixin::PowershellExec, :windows_only do
context "using pwsh interpreter" do
it "runs a basic command and returns a Chef::PowerShell object" do
- expect(object.powershell_exec("$PSVersionTable", :pwsh)).to be_kind_of(Chef::Pwsh)
+ expect(object.powershell_exec("$PSVersionTable", :pwsh)).to be_kind_of(ChefPowerShell::Pwsh)
end
it "uses greater than version 6" do
@@ -48,7 +48,7 @@ describe Chef::Mixin::PowershellExec, :windows_only do
context "using powershell interpreter" do
it "runs a basic command and returns a Chef::PowerShell object" do
- expect(object.powershell_exec("$PSVersionTable", :powershell)).to be_kind_of(Chef::PowerShell)
+ expect(object.powershell_exec("$PSVersionTable", :powershell)).to be_kind_of(ChefPowerShell::PowerShell)
end
it "uses less than version 6" do
@@ -76,11 +76,11 @@ describe Chef::Mixin::PowershellExec, :windows_only do
describe "#powershell_exec!" do
it "runs a basic command and returns a Chef::PowerShell object" do
- expect(object.powershell_exec!("$PSVersionTable")).to be_kind_of(Chef::PowerShell)
+ expect(object.powershell_exec!("$PSVersionTable")).to be_kind_of(ChefPowerShell::PowerShell)
end
it "raises an error if the command fails" do
- expect { object.powershell_exec!("this-should-error") }.to raise_error(Chef::PowerShell::CommandFailed)
+ expect { object.powershell_exec!("this-should-error") }.to raise_error(ChefPowerShell::PowerShellExceptions::PowerShellCommandFailed)
end
it "raises an error if the interpreter is invalid" do
diff --git a/spec/unit/platform/query_helpers_spec.rb b/spec/unit/platform/query_helpers_spec.rb
index 0b4169810e..424bd6348b 100644
--- a/spec/unit/platform/query_helpers_spec.rb
+++ b/spec/unit/platform/query_helpers_spec.rb
@@ -18,7 +18,7 @@
require "spec_helper"
-describe "Chef::Platform#supports_dsc_invoke_resource?" do
+describe "Chef::Platform#supports_dsc_invoke_resource?", :windows_only do
it "returns false if powershell is not present" do
node = Chef::Node.new
expect(Chef::Platform.supports_dsc_invoke_resource?(node)).to be_falsey
@@ -39,25 +39,14 @@ describe "Chef::Platform#supports_dsc_invoke_resource?" do
end
end
-describe "Chef::Platform#dsc_refresh_mode_disabled?" do
+describe "Chef::Platform#dsc_refresh_mode_disabled?", :windows_only do
let(:node) { instance_double("Chef::Node") }
- let(:powershell) { instance_double("Chef::PowerShell") }
+ let(:powershell) { Class.new { include ChefPowerShell::ChefPowerShellModule::PowerShellExec } }
+ subject(:object) { powershell.new }
it "returns true when RefreshMode is Disabled" do
- expect(Chef::PowerShell).to receive(:new)
- .with("Get-DscLocalConfigurationManager")
- .and_return(powershell)
- expect(powershell).to receive(:error!)
- expect(powershell).to receive(:result).and_return({ "RefreshMode" => "Disabled" })
- expect(Chef::Platform.dsc_refresh_mode_disabled?(node)).to be true
- end
-
- it "returns false when RefreshMode is not Disabled" do
- expect(Chef::PowerShell).to receive(:new)
- .with("Get-DscLocalConfigurationManager")
- .and_return(powershell)
- expect(powershell).to receive(:error!)
- expect(powershell).to receive(:result).and_return({ "RefreshMode" => "LaLaLa" })
+ execution = object.powershell_exec("Get-DscLocalConfigurationManager", :powershell, timeout: -1)
+ expect(execution.result["RefreshMode"]).to eq "PUSH"
expect(Chef::Platform.dsc_refresh_mode_disabled?(node)).to be false
end
end
diff --git a/spec/unit/util/dsc/local_configuration_manager_spec.rb b/spec/unit/util/dsc/local_configuration_manager_spec.rb
index 8adf778949..510038db73 100644
--- a/spec/unit/util/dsc/local_configuration_manager_spec.rb
+++ b/spec/unit/util/dsc/local_configuration_manager_spec.rb
@@ -185,7 +185,7 @@ describe Chef::Util::DSC::LocalConfigurationManager do
context "when invalid dsc script is given" do
it "raises exception" do
configuration_document = "invalid-config"
- expect { lcm.send(:run_configuration_cmdlet, configuration_document, true) }.to raise_error(Chef::PowerShell::CommandFailed)
+ expect { lcm.send(:run_configuration_cmdlet, configuration_document, true) }.to raise_error(ChefPowerShell::PowerShellExceptions::PowerShellCommandFailed)
end
end
end