-
Notifications
You must be signed in to change notification settings - Fork 101
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
Add support for Windows hosts through WinRM #216
Conversation
@Temikus, Here is the Pull request I mentioned. This is my first Vagrant plugin so I would appreciate any feedback. The plugin does require the setting of the GOOGLE_APPLICATION_CREDENTIALS environment variable to use the same JSON file that is used by the rest of the vagrant-google plugin. I could not figure out how to pass the file directly to the googl-api-ruby-client. |
@dvanbrug Sorry for the response delay - this is really cool! I think we can pull through the functionality to reset windows passwords into Can you give me an example Vagrantfile that I can use to debug/repro? |
Oh cool! Here is an example Vagrantfile: https://gist.github.com/dvanbrug/f24572ac7eb340cda096273a640c9e99 One note, I've found a couple of bugs in this implementation but have not had time to chase them down yet. They both have to do with how the Ansible hosts file, likely due to some race conditions or incorrect error handling on my part. |
+1 for me, really need to build some windows machines with WinRM access. I would have thought the winrm connection stuff would have been separate to the provider however. The provider builds a box and exposes its public/private IP and then the config.vm.communicator and config.winrm settings should define how vagrant connects to that box after it has been provisioned which should be the same regardless of whether its gce, azure, aws or any other provider. |
@GodKratos, are you still interested in this? I thought I'd try and dust it off and give things another go. The current version was really setup just to make WinRM communicator work with GCE defaults. Part of this was dealing with the dance of GCE that requires setting a temporary password and then setting your desired password. The rest was using the default ports that GCE had in place. For your "non-standard" settings, is this based on the standard windows images provided by GCE or custom windows images that you are using? If the latter, is it correct to assume you don't have to go through Google APIs to set a temporary password before being able to setup WinRM settings? |
@Temikus I am brushing this off and reworking the pull request. I wanted to get your opinion on my approach. In order to get a Google-based Windows instance up and running, we need to perform the following steps:
For the rework, first, I've pulled out the "Password Reset" functionality into fog-google. This allows vagrant-google to just call the reset functionality. I'll submit that pull request shortly. Second, I am trying to figure out the best place to add the needed functionality within vagrant-google. I am thinking I'd create a new action called setup_windows_password but am not sure where I should call it from. My first thought was in run-instance, around line 289 This is because after this point, while the next block of code is a little specific to SSH, if we succeed in setting up the correct WinRM password, the next block should work as written. If this is a good location, what would be a good way to call the reset code only if we are using a Google provided image? Some sort of flag within the config to indicate that we should reset the password? Are there any examples of these sort of flags being used elsewhere? Thank you any ideas you may have! |
Awesome, thanks! Apologies this didn't move much last year. I've changed roles and then had some medical issues which took me out of commission for a while m(_ _)m
Great! I'm prepping a new release so I think we should be able to push it through quickly.
Generally new actions should be called in the action.rb only, e.g. somewhere after
Hm, if it's only google images that need to be reset, I think it's reasonable to hardcode a list of windows image projects (e.g. And if I'm missing something - just let me know. I'm happy to help! |
( Forgot to @ you :) ) |
@Temikus, No worries. I too was pulled away and the current global situation provided a great time to dig back into this.
If I understand how action.rb works correctly, I think this may be a problem. Since RunInstance creates and boots the instance and then waits for That is why I was thinking it belonged on line 289.
I'll dig into those and see if I can find a suitable indicator. |
@dvanbrug Thanks for the explanation!
Got ya. Let's proceed with that then and I'll later refactor this out. Probably going to make communication with the VM a separate action. |
@dvanbrug Just to clarify - I didn't forget about this - just figuring out the fog release. Will ping you here as soon as it's released. Planning to work on it sometime this week. |
@Temikus No worries, I figured that was the case. It makes sense to get the fog-google change released first. |
@dvanbrug released: https://github.com/fog/fog-google/releases/tag/v1.10.0 Can you update the deps in the PR and let me know if this vagrantfile is still valid? https://gist.github.com/dvanbrug/f24572ac7eb340cda096273a640c9e99 Thank you for your patience and hard work ❤️ |
@Temikus I just updated the dependency and confirmed it worked with the published v1.10 of fog-google. I updated the original Vagrantfile within the Gist so it corresponds to the latest version. Please let me know if you run into any trouble. |
Alright, acceptance tests are green:
Only left to check one other scenario and we should be good to go :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dvanbrug Ok, so - I admit I spent 3-4 solid hours on this and didn't manage to get WinRM to connect 😞 After debugging for a while I think it's purely my problem (some org policy I suspect), but during the debugging I did uncover some issues that we ideally want to fix.
I'm sorry to lay even more changes on you m(_ _)m PTAL
In the meantime I'll take another stab at this on Monday.
# https://github.com/GoogleCloudPlatform/compute-image-windows/blob/master/examples/windows_auth_python_sample.py | ||
# to enable WinRM with vagrant. | ||
|
||
require "fog/google" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Those requires should not be needed, can you take a look?
require "fog/google"
require "googleauth"
require "google/apis/compute_v1"
require "vagrant/../../plugins/communicators/winrm/communicator"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I missed the first 3 when I refactored to use fog-google directly. For the others, things seem to work if I remove all of the requires. I would have thought I'd need at least the following 2 because I make use of those Classes directly.
require "log4r"
require "vagrant/../../plugins/communicators/winrm/communicator"
At this point I've removed them all.
env[:ui].info("Setting up WinRM Password") | ||
env[:action_runner].run(Action.action_setup_winrm_password, env) | ||
end | ||
|
||
unless env[:terminated] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So while debugging I noticed that winrm options are not really set:
ls @machine.winrm_info
NoMethodError: undefined method `winrm_info' for #<Vagrant::Machine: winserver (VagrantPlugins::Google::Provider)>
from /Users/temikus/.rbenv/versions/2.4.3/lib/ruby/gems/2.4.0/gems/pry-0.12.2/lib/pry/core_extensions.rb:17:in `__pry__'
I suspect it may be because we never set up the winrm capability in the provider, like Azure did:
https://github.com/Azure/vagrant-azure/blob/97f4d125aebcb5669e9d1278b702e13554bef640/lib/vagrant-azure/capabilities/winrm.rb
I'm raising this since this may cause issues in the future as Vagrant has some autodetect logic which this may break.
Can you take a look?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had originally had all the features from the Azure plugin included, like this capability file but refactored it out when it didn't seem to do anything. I am confused as to what the difference is between including the details in the config (e.g. config.winrm.*) and the need for setting up env[:machine_winrm_info]
via this capability.
The WinRM communicator does not appear to need this winrm_info, using the details from the Vagrantfile config instead. However, I do see that there is a machine_ssh_info
, so it would make sense to mimic that with WinRM.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After some more digging, I've found that if I add in a read_winrm_info
functionality, I am actually breaking things. I've found that in the following file, it has a default way of computing winrm_info if it is not explicitly defined. That must be why it works without adding in this functionality.
Would this be sufficient? Else I can explicitly add in this functionality, though I am still troubleshooting it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I should've been more clear here, sorry m(_ _)m
So, ideally we would want the provider to explicitly set that guest capability to make sure we don't rely on heuristics. However, if it's too difficult I'm also open leaving that as an explicit TODO in the code and creating an issue for the future.
WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll take another shot at implementing this and see if I can get it working correctly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's go ahead and use the default heuristics.
@Temikus I started digging into this and noticed that things are responding much slower and setting up the password does not even complete. I'll spend some time this weekend debugging to see if I can figure out what is going on. If I had to guess, I'm thinking there are some timing issues with Windows being set up and restarting a few times during setup. |
@Temikus So I think I've narrowed down the issues I was having to the latest If you use Windows Server 2019 Also, if you are still having trouble, I made a note in the Vagrantfile that you'll need to create a new firewall rule that allows both TCP and UDP connections to 5985 and 5986 ports and associate it with the target tag From there, I found this site useful for WinRM troubleshooting (http://www.hurryupandwait.io/blog/understanding-and-troubleshooting-winrm-connection-and-authentication-a-thrill-seekers-guide-to-adventure). Notably, the following command will at least tell you if you have connectivity to the WinRM service as needed. 0 is success, 1 is failure. This is the command that fails on the latest version of
|
@Temikus, I've addressed the two changes above. Let me know if you run into further issues getting WinRM working. I am hoping my previous comment can help a bit. Thanks again for all your help! |
@dvanbrug - those comments help a lot, lemme try with a different image. And no - thank you for your efforts and patience :) |
Ok, so now I am finally getting a connection and the port does open, but it gives me a WinRMAuthorisation Error:
Is there anything specific I should be doing? I've set the account user/pass:
|
@Temikus I have seen this error when the WinRM password is not correct. This can happen if the password reset doesn't succeed and then a WinRM command is issued. I have not seen it during the password reset process though. But from your output, it would look like the "Changing password from temporary ... " part passed successfully. One way to confirm this is what happened is, if the instance did not terminate, edit your Vagrantfile to set the password to the temp one that was printed to stdout. Then try running the test below. My go to test for WinRM is to run the
WinRM does not allow for an interactive shell. The -s command allows you to set what shell will interpret the command that you provide if I understand correctly. I haven't been able to reproduce this during the first boot up but I'll keep trying to see if I can. |
@Temikus Ok, so I still haven't been able to reproduce this on my. Does the image terminate or are you able to run the
|
@dvanbrug - I'm using the vagrant from the dev bundle, i.e. Regarding image - I used the "Windows 2019" family but lemme retry with 2016. |
Ok, I see. The password doesn't get changed, I am able to send winrm functions if I set the password to a temporary one:
Continuing to debug. |
Something's not working when actually changing the password, i.e.:
It does return "true" but maybe doesn't stick properly? I'm not sure 🤔 I'll try debugging a bit more this week. If I don't nail it - let's just merge and leave it as an issue which I will dig into a bit more, since obviously this does work for you and I don't want to block you on this. |
@Temikus So I just started digging back into this and I am concerned about how this doesn't work on a lot of different images. I'll try and iron things out this weekend and see what I can do. The problems I have is that same call just hanging:
I am thinking I should add in some more logic to at least provide more in depth information if WinRM does not respond as expected. |
@Temikus So it turns out my issues were due to a problematic firewall rule. I've tested the code out against the following images and it works on all but two.
Also, in trying to reproduce your error, I spun up a new Ruby environment on a vanilla Centos 7 image on Google Compute. However, I could not reproduce the error there either. The only errors I've had is that the "Changing Temporary Password" hangs because either 1.) The firewall is blocking connections, or 2.) The WinRM service is not running on port 5986 due to problems with certificates not being setup correctly. Since you are able to run WinRM commands through Vagrant, are you able to set the password manually?
The only other thought I have is trying to debug the winrm plugin. All the testing I did was with the changed plugin installed directly instead of using |
@dvanbrug nah, If you cannot repro I'm happy to go with your lead here and merge and then if you run into it we can dig around a bit more. |
@dvanbrug just circling back here - WDYT? :) |
@Temikus Sorry for the delay. Let's go ahead and merge it for now and troubleshoot it as we go. |
@dvanbrug Alright, merging this in. Thanks for your collosal efforts, they're super appreciated ❤️ |
Fixes #173.
Based on WinRM plugin from https://github.com/Azure/vagrant-azure
and existing code here.
Windows instances are already setup to use WinRM, however
setting up a temporary password is required before being
able to connect. This feature uses the Google APIs directly
since the functionality to reset Windows passwords is not
available in fog-google.
Once a temporary password is set, the final password is pulled
from the Vagrantfile and set over the WinRM channel.