-
Notifications
You must be signed in to change notification settings - Fork 4.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
macOS, Vagrant, VirtualBox, shell provider powershell #9138
Comments
Built Windows Server 2016 with packer using this /~https://github.com/StefanScherer/packer-windows
Packer completes without warning or errors. I added a "shell/Noop.ps1", la blank file and the above error still thrown. I changed "shell/Noop.ps1" to
the above error still thrown. Edit 1 Interactive shell on the Windows 2016 Server I find c:\tmp\vagrant-shell.ps1 and it's my Noop.ps1 testing script. Executing this script from a powershell command line works as expected. Edit 2 Does Vagrant use scheduled tasks for powershell provisioners? Vaguely recall having issues with 2003 scheduled tasks when we moved to 2008. Could this be a similar problem going from 2008 to 2016? |
Turned on debug, got the below output $ vagrant up --debug
DEBUG winrmshell: [WinRM] Command created for $username = 'vagrant'
$password = 'vagrant'
$script_file = 'c:/windows/temp/winrm-elevated-shell-7bf83477-461e-42c3-aefa-3ccb548603e9.ps1'
$interactive = 'false'
$pass_to_use = $password
$logon_type = 1
$logon_type_xml = "<LogonType>Password</LogonType>"
if($pass_to_use.length -eq 0) {
$pass_to_use = $null
$logon_type = 5
$logon_type_xml = ""
}
if($interactive -eq 'true') {
$logon_type = 3
$logon_type_xml = "<LogonType>InteractiveTokenOrPassword</LogonType>"
}
$task_name = "WinRM_Elevated_Shell"
$out_file = [System.IO.Path]::GetTempFileName()
$err_file = [System.IO.Path]::GetTempFileName()
$task_xml = @'
<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
<Principals>
<Principal id="Author">
<UserId>{username}</UserId>
{logon_type}
<RunLevel>HighestAvailable</RunLevel>
</Principal>
</Principals>
<Settings>
<MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
<StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
<AllowHardTerminate>true</AllowHardTerminate>
<StartWhenAvailable>false</StartWhenAvailable>
<RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
<IdleSettings>
<StopOnIdleEnd>false</StopOnIdleEnd>
<RestartOnIdle>false</RestartOnIdle>
</IdleSettings>
<AllowStartOnDemand>true</AllowStartOnDemand>
<Enabled>true</Enabled>
<Hidden>false</Hidden>
<RunOnlyIfIdle>false</RunOnlyIfIdle>
<WakeToRun>false</WakeToRun>
<ExecutionTimeLimit>PT24H</ExecutionTimeLimit>
<Priority>4</Priority>
</Settings>
<Actions Context="Author">
<Exec>
<Command>cmd</Command>
<Arguments>{arguments}</Arguments>
</Exec>
</Actions>
</Task>
'@
$arguments = "/c powershell.exe -executionpolicy bypass -NoProfile -File $script_file > $out_file 2>$err_file"
$task_xml = $task_xml.Replace("{arguments}", $arguments)
$task_xml = $task_xml.Replace("{username}", $username)
$task_xml = $task_xml.Replace("{logon_type}", $logon_type_xml)
$schedule = New-Object -ComObject "Schedule.Service"
$schedule.Connect()
$task = $schedule.NewTask($null)
$task.XmlText = $task_xml
$folder = $schedule.GetFolder("\")
$folder.RegisterTaskDefinition($task_name, $task, 6, $username, $pass_to_use, $logon_type, $null) | Out-Null Typed the above into an interactive powershell, all went well until PS C:\Users\vagrant> $folder.RegisterTaskDefinition($task_name, $task, 6, $username, $pass_to_use, $logon_type, $null)
(27,4):Actions:
At line:1 char:1
+ $folder.RegisterTaskDefinition($task_name, $task, 6, $username, $pass ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], ArgumentException
+ FullyQualifiedErrorId : System.ArgumentException Left off the "| Out-Null" |
After a lot of research I found that Windows Server 2016 does not allow schedule tasks to be run as non-Administrator. Even with the vagrant user in the Administrators group it does not allow vagrant user to create schedule tasks. I enabled the local Administrator, set the password changed the VagrantFile as below: config.winrm.username = "Administrator"
config.winrm.password = "Vagrant1234" And provisioned the VM again and things work $ vagrant up --provision
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Running provisioner: shell...
default: Running: shell/Noop.ps1 as c:\tmp\vagrant-shell.ps1
==> default: Testing http://bit.ly/2zqIaNU http://bit.ly/2zqBAqS http://bit.ly/2ztbtjb Edit 1 Might be a macOS issue or how Vagrant implements WinRM on macOS? Looks like using Windows7 as a host things work as expected. https://groups.google.com/d/msg/vagrant-up/lKS1cs9mLpM/L7pnTUMfBAAJ |
I can reproduce on a Windows 7 Enterprise host as well. Vagrant 2.0.0, VirtualBox 5.1.30 and your basebox given in the Vagrantfile above. Well provisioning also works with this box with config.vm.provision :shell, :path => "shell/hello.ps1", privileged: false
config.vm.provision :shell, :path => "shell/PrepareWindows.ps1", privileged: false
config.vm.provision :shell, :path => "shell/InstallNet4.ps1", privileged: false
config.vm.provision :shell, :path => "shell/InstallChocolatey.ps1", privileged: false
config.vm.provision :shell, :path => "shell/NotifyGuiAppsOfEnvironmentChanges.ps1", privileged: false This disables the scheduled task inside the winrm communicator. As the basebox does not have UAC enabled and user vagrant is in the Administrators group it also works, but looks weird. But this is the way I do it in other Vagrantfiles as well. And this does not really notify the GUI apps, so the last provision script "NotifyGuiAppsOfEnvironmentChanges.ps1" has no effect. Open a powershell terminal and type |
Provisioning also works with the Provisioning fails with
|
Vagrant host macOS 10.12.6 Changing the provisioning to look like this: config.vm.provision :shell, :path => "shell/Noop.ps1", privileged: false
config.vm.provision :shell, :path => "shell/PrepareWindows.ps1", privileged: false
config.vm.provision :shell, :path => "shell/InstallNet4.ps1", privileged: false
config.vm.provision :shell, :path => "shell/InstallChocolatey.ps1", privileged: false
config.vm.provision :shell, :path => "shell/NotifyGuiAppsOfEnvironmentChanges.ps1",privileged: false
config.vm.provision :shell, :path => "shell/InstallToolchain.ps1", privileged: false Allows all provisioning to work as expected. |
Closes chocolatey-community#19 Closes chocolatey-community#20 Closes chocolatey-community#21 Closes chocolatey-community#22 See hashicorp/vagrant#9138 for an issues regarding Windows Server 2016 and powershell provisioners. See /~https://github.com/StefanScherer/packer-windows for packer templates
As a vagrant user trying to work with Windows Server 2016, thank you @basictheprogram and @StefanScherer for your work on this. I experienced this issue, as well, and can confirm that this is also a problem when using the VMware Fusion provider. The |
so, the scheduled task is designed to work around issues with PSremoting, for instance, if I try and run 'choco install powershell -y' this will result in the task failing with error 5 (access denied). What I don't understand is why the same code works as Administrator, even though vagrant is also a local administrator. This is what I see from vagrant:
If I change the code to use "Administrator", everything works fine. I've also tried making the vagrant account password suitably 'complex' without any change in behaviour. SYSTEM works fine, and avoids having to pass in credentials at all, by default:
|
Couple things of note - vagrant uses /~https://github.com/WinRb/winrm-elevated as the means to run elevated. This will run as system if no password is passed in, but Vagrant doesn't provide a parameter for this. I can create another user with local admin rights and this works, so it's something specific about the vagrant user. This is the error received from RegisterTaskDefinition:
|
I've just found it'll work with the vagrant account if you specify the username as
This doesn't really work for me, because as part of provisioning I rename the guest to match the name of the VM. The ability to use SYSTEM to register the task would be much cleaner, imo. For the time being, I've worked around it by using 'administrator'. |
Is there any update on this issue? |
+1 here. Everything was working fine until >= 2.2.1. See the following issues for repro: Setting |
@clong Thanks for the report of the issue! For the windows boxes you are using, do they include customized username values for the winrm communicator within the nested Vagrantfile? |
@chrisroberts nope, the Vagrantfile doesn't specify a username for the winrm provider and uses the defaults. |
@chrisroberts On my setup I have the following statements in the box's nested Vagrantfile:
|
Hi there, It looks like this has been resolved within a previously shipped version of Vagrant so I am now closing this issue. If the original issue was not fully resolved, please reopen this issue or create a new one. Cheers! |
I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues. If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further. |
Vagrant version
$ vagrant -v
Vagrant 2.0.0
Host operating system
macOS 10.12.6
Guest operating system
Windows Server 2016
Vagrantfile
Debug output
https://gist.github.com/basictheprogram/9cb025b9c6f3f78a5b10132130c21883
Expected behavior
The shell provisions should execute and not error out.
Actual behavior
$ vagrant up
==> default: Checking if box 'BasicTheProgram/windows_2016' is up to date...
==> default: Running provisioner: shell...
default: Running: shell/PrepareWindows.ps1 as c:\tmp\vagrant-shell.ps1
==> default: (10,8):UserId:
==> default: At line:72 char:1
==> default: + $folder.RegisterTaskDefinition($task_name, $task, 6, $username, $pass ...
==> default: + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
==> default: + CategoryInfo : OperationStopped: (:) [], ArgumentException
==> default: + FullyQualifiedErrorId : System.ArgumentException
==> default: The system cannot find the file specified. (Exception from HRESULT: 0x80070002)
==> default: At line:74 char:1
==> default: + $registered_task = $folder.GetTask("$task_name")
==> default: + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
==> default: + CategoryInfo : OperationStopped: (:) [], FileNotFoundException
==> default: + FullyQualifiedErrorId : System.IO.FileNotFoundException
==> default: You cannot call a method on a null-valued expression.
==> default: At line:75 char:1
==> default: + $registered_task.Run($null) | Out-Null
==> default: + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
==> default: + CategoryInfo : InvalidOperation: (:) [], RuntimeException
==> default: + FullyQualifiedErrorId : InvokeMethodOnNull
The text was updated successfully, but these errors were encountered: