Merge pull request #7797 from lukebakken/features/lrb/better-windows-admin-detection

Improve user permission detection on Windows
This commit is contained in:
Chris Roberts 2017-04-17 14:37:43 -07:00 committed by GitHub
commit 4d0ecc14f7
2 changed files with 37 additions and 23 deletions

View File

@ -3,6 +3,7 @@ require "shellwords"
require "tmpdir" require "tmpdir"
require "vagrant/util/subprocess" require "vagrant/util/subprocess"
require "vagrant/util/powershell"
module Vagrant module Vagrant
module Util module Util
@ -42,27 +43,17 @@ module Vagrant
# Checks if the user running Vagrant on Windows has administrative # Checks if the user running Vagrant on Windows has administrative
# privileges. # privileges.
# #
# From: https://support.microsoft.com/en-us/kb/243330
# SID: S-1-5-19
#
# @return [Boolean] # @return [Boolean]
def windows_admin? def windows_admin?
return @_windows_admin if defined?(@_windows_admin) return @_windows_admin if defined?(@_windows_admin)
# We lazily-load this because it is only available on Windows
require "win32/registry"
# Verify that we have administrative privileges. The odd method of
# detecting this is based on this StackOverflow question:
#
# https://stackoverflow.com/questions/560366/
# detect-if-running-with-administrator-privileges-under-windows-xp
@_windows_admin = -> { @_windows_admin = -> {
begin ps_cmd = "[System.Security.Principal.WindowsIdentity]::GetCurrent().Groups | ForEach-Object { if ($_.Value -eq 'S-1-5-19'){ Write-Host 'true'; break }}"
Win32::Registry::HKEY_USERS.open("S-1-5-19") {} output = Vagrant::Util::PowerShell.execute_cmd(ps_cmd)
return output == 'true'
# The above doesn't seem to be 100% bullet proof. See GH-5616.
return (`reg query HKU\\S-1-5-19 2>&1` =~ /ERROR/).nil?
rescue Win32::Registry::Error
return false
end
}.call }.call
return @_windows_admin return @_windows_admin
@ -78,15 +69,13 @@ module Vagrant
# @return [Boolean] # @return [Boolean]
def windows_hyperv_admin? def windows_hyperv_admin?
return @_windows_hyperv_admin if defined?(@_windows_hyperv_admin) return @_windows_hyperv_admin if defined?(@_windows_hyperv_admin)
@_windows_hyperv_admin = -> { @_windows_hyperv_admin = -> {
begin ps_cmd = "[System.Security.Principal.WindowsIdentity]::GetCurrent().Groups | ForEach-Object { if ($_.Value -eq 'S-1-5-32-578'){ Write-Host 'true'; break }}"
username = ENV["USERNAME"] output = Vagrant::Util::PowerShell.execute_cmd(ps_cmd)
process = Subprocess.execute("net", "localgroup", "Hyper-V Administrators") return output == 'true'
return process.stdout.include?(username)
rescue Errors::CommandUnavailableWindows
return false
end
}.call }.call
return @_windows_hyperv_admin return @_windows_hyperv_admin
end end

View File

@ -19,7 +19,9 @@ module Vagrant
def self.execute(path, *args, **opts, &block) def self.execute(path, *args, **opts, &block)
command = [ command = [
"powershell", "powershell",
"-NoLogo",
"-NoProfile", "-NoProfile",
"-NonInteractive",
"-ExecutionPolicy", "Bypass", "-ExecutionPolicy", "Bypass",
"&('#{path}')", "&('#{path}')",
args args
@ -32,14 +34,37 @@ module Vagrant
Subprocess.execute(*command, &block) Subprocess.execute(*command, &block)
end end
# Execute a powershell command.
#
# @param [String] command PowerShell command to execute.
# @return [Subprocess::Result]
def self.execute_cmd(command)
c = [
"powershell",
"-NoLogo",
"-NoProfile",
"-NonInteractive",
"-ExecutionPolicy", "Bypass",
"-Command",
command
].flatten
r = Subprocess.execute(*c)
return nil if r.exit_code != 0
return r.stdout.chomp
end
# Returns the version of PowerShell that is installed. # Returns the version of PowerShell that is installed.
# #
# @return [String] # @return [String]
def self.version def self.version
command = [ command = [
"powershell", "powershell",
"-NoLogo",
"-NoProfile", "-NoProfile",
"-NonInteractive",
"-ExecutionPolicy", "Bypass", "-ExecutionPolicy", "Bypass",
"-Command",
"$PSVersionTable.PSVersion.Major" "$PSVersionTable.PSVersion.Major"
].flatten ].flatten