diff options
author | Bryan McLellan <btm@loftninjas.org> | 2018-01-25 12:04:33 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-01-25 12:04:33 -0500 |
commit | dc8adc5901b056d513fd07b736ff50da2ca06563 (patch) | |
tree | 569f671d0a51c242b560822758e69fa56395057a /spec | |
parent | 07486c726bc45f730a1bc91b650d571c3112974d (diff) | |
parent | b07a4f4b8da44bf35d9dbe879e1cf4fd2f040644 (diff) | |
download | chef-dc8adc5901b056d513fd07b736ff50da2ca06563.tar.gz |
Merge pull request #6687 from MsysTechnologiesllc/nim/logonSession_user_permission
[MSYS-724] Chef::Util::Windows::LogonSession should allow having only the prescribed users permissions
Diffstat (limited to 'spec')
-rw-r--r-- | spec/functional/win32/security_spec.rb | 67 | ||||
-rw-r--r-- | spec/unit/util/windows/logon_session_spec.rb | 3 | ||||
-rw-r--r-- | spec/unit/win32/security_spec.rb | 51 |
3 files changed, 113 insertions, 8 deletions
diff --git a/spec/functional/win32/security_spec.rb b/spec/functional/win32/security_spec.rb index 40ae99bfa4..6c24cbec08 100644 --- a/spec/functional/win32/security_spec.rb +++ b/spec/functional/win32/security_spec.rb @@ -17,6 +17,8 @@ # require "spec_helper" +require "mixlib/shellout" +require "chef/mixin/user_context" if Chef::Platform.windows? require "chef/win32/security" end @@ -26,13 +28,37 @@ describe "Chef::Win32::Security", :windows_only do expect(Chef::ReservedNames::Win32::Security.has_admin_privileges?).to eq(true) end - # We've done some investigation adding a negative test and it turned - # out to be a lot of work since mixlib-shellout doesn't have user - # support for windows. - # - # TODO - Add negative tests once mixlib-shellout has user support - it "has_admin_privileges? returns false when running as non-admin" do - skip "requires user support in mixlib-shellout" + describe "running as non admin user" do + include Chef::Mixin::UserContext + let(:user) { "security_user" } + let(:password) { "Security@123" } + + let(:domain) do + whoami = Mixlib::ShellOut.new("whoami") + whoami.run_command + whoami.error! + whoami.stdout.split("\\")[0] + end + + before do + allow_any_instance_of(Chef::Mixin::UserContext).to receive(:node).and_return({ "platform_family" => "windows" }) + allow(Chef::Platform).to receive(:windows_server_2003?).and_return(false) + add_user = Mixlib::ShellOut.new("net user #{user} #{password} /ADD") + add_user.run_command + add_user.error! + end + + after do + delete_user = Mixlib::ShellOut.new("net user #{user} /delete") + delete_user.run_command + delete_user.error! + end + it "has_admin_privileges? returns false" do + has_admin_privileges = with_user_context(user, password, domain, :local) do + Chef::ReservedNames::Win32::Security.has_admin_privileges? + end + expect(has_admin_privileges).to eq(false) + end end describe "get_file_security" do @@ -97,4 +123,31 @@ describe "Chef::Win32::Security", :windows_only do end end end + + describe ".get_token_information_elevation_type" do + let(:token_rights) { Chef::ReservedNames::Win32::Security::TOKEN_READ } + + let(:token) do + Chef::ReservedNames::Win32::Security.open_process_token( + Chef::ReservedNames::Win32::Process.get_current_process, + token_rights) + end + + context "when the token is valid" do + let(:token_elevation_type) { [:TokenElevationTypeDefault, :TokenElevationTypeFull, :TokenElevationTypeLimited] } + + it "returns the token elevation type" do + elevation_type = Chef::ReservedNames::Win32::Security.get_token_information_elevation_type(token) + expect(token_elevation_type).to include(elevation_type) + end + end + + context "when the token is invalid" do + it "raises `handle invalid` error" do + # If `OpenProcessToken` is stubbed, `open_process_token` returns an invalid token + allow(Chef::ReservedNames::Win32::Security).to receive(:OpenProcessToken).and_return(true) + expect { Chef::ReservedNames::Win32::Security.get_token_information_elevation_type(token) }.to raise_error(Chef::Exceptions::Win32APIError) + end + end + end end diff --git a/spec/unit/util/windows/logon_session_spec.rb b/spec/unit/util/windows/logon_session_spec.rb index b9b6c458b6..8a94802bf6 100644 --- a/spec/unit/util/windows/logon_session_spec.rb +++ b/spec/unit/util/windows/logon_session_spec.rb @@ -27,7 +27,8 @@ describe ::Chef::Util::Windows::LogonSession do stub_const("Chef::ReservedNames::Win32::API::System", Class.new ) end - let(:session) { ::Chef::Util::Windows::LogonSession.new(session_user, password, session_domain) } + let(:session) { ::Chef::Util::Windows::LogonSession.new(session_user, password, session_domain, authentication) } + let(:authentication) { :remote } shared_examples_for "it received syntactically invalid credentials" do it "does not raisees an exception when it is initialized" do diff --git a/spec/unit/win32/security_spec.rb b/spec/unit/win32/security_spec.rb index 1c755061ce..6e4441a482 100644 --- a/spec/unit/win32/security_spec.rb +++ b/spec/unit/win32/security_spec.rb @@ -63,4 +63,55 @@ describe "Chef::Win32::Security", :windows_only do end end end + + describe "self.has_admin_privileges?" do + it "returns true for windows server 2003" do + allow(Chef::Platform).to receive(:windows_server_2003?).and_return(true) + expect(Chef::ReservedNames::Win32::Security.has_admin_privileges?).to be true + end + + context "when the user doesn't have admin privileges" do + it "returns false" do + allow(Chef::Platform).to receive(:windows_server_2003?).and_return(false) + allow(Chef::ReservedNames::Win32::Security).to receive(:open_current_process_token).and_raise("Access is denied.") + expect(Chef::ReservedNames::Win32::Security.has_admin_privileges?).to be false + end + end + + context "when open_current_process_token fails with some other error than `Access is Denied`" do + it "raises error" do + allow(Chef::Platform).to receive(:windows_server_2003?).and_return(false) + allow(Chef::ReservedNames::Win32::Security).to receive(:open_current_process_token).and_raise("boom") + expect { Chef::ReservedNames::Win32::Security.has_admin_privileges? }.to raise_error(Chef::Exceptions::Win32APIError) + end + end + + context "when the user has admin privileges" do + it "returns true" do + allow(Chef::Platform).to receive(:windows_server_2003?).and_return(false) + allow(Chef::ReservedNames::Win32::Security).to receive(:open_current_process_token) + token = Chef::ReservedNames::Win32::Security.open_current_process_token + allow(token).to receive_message_chain(:handle, :handle) + allow(Chef::ReservedNames::Win32::Security).to receive(:get_token_information_elevation_type) + allow(Chef::ReservedNames::Win32::Security).to receive(:GetTokenInformation).and_return(true) + allow_any_instance_of(FFI::Buffer).to receive(:read_ulong).and_return(1) + expect(Chef::ReservedNames::Win32::Security.has_admin_privileges?).to be true + end + end + end + + describe "self.get_token_information_elevation_type" do + let(:token_rights) { Chef::ReservedNames::Win32::Security::TOKEN_READ } + + let(:token) do + Chef::ReservedNames::Win32::Security.open_process_token( + Chef::ReservedNames::Win32::Process.get_current_process, + token_rights) + end + + it "raises error if GetTokenInformation fails" do + allow(Chef::ReservedNames::Win32::Security).to receive(:GetTokenInformation).and_return(false) + expect { Chef::ReservedNames::Win32::Security.get_token_information_elevation_type(token) }.to raise_error(Chef::Exceptions::Win32APIError) + end + end end |