vagrant-hostsupdater
vagrant-hostsupdater copied to clipboard
Windows - not updating hosts
Hi
This doesn't work for me or my colleagues on windows 7 and 10 machines - so I took a look at the code, and I'm a little confused how this is working for Windows users in its current setup (unless they have made their systems open to attack by modifying their 'hosts' attributes)...
addToHosts
The line ```if !File.writable_real?(@@hosts_path)`` is used and passes its bash commands to the sudo function. Since Windows 'hosts' files should be read-only for security reasons our machines pass the bash commands to the 'sudo' windows function, which of course fails (there is no sh command).
The windows '''elsif Vagrant::Util::Platform.windows?''' never triggers because of the first ```if`` test is true, so the hosts never updates. Now if we modify this section to allow the windows actions to happen we also have to add in code to make 'hosts' file temporarily writable e.g.
def addToHosts(entries)
return if entries.length == 0
content = entries.join("\n").strip
@ui.info "[vagrant-hostsupdater] Writing the following entries to (#@@hosts_path)"
@ui.info "[vagrant-hostsupdater] " + entries.join("\n[vagrant-hostsupdater] ")
if !File.writable_real?(@@hosts_path)
@ui.info "[vagrant-hostsupdater] This operation requires administrative access. You may " +
"skip it by manually adding equivalent entries to the hosts file."
if Vagrant::Util::Platform.windows?
@ui.info "[vagrant-hostsupdater] Windows platform create hosts"
require 'tmpdir'
uuid = @machine.id || @machine.config.hostsupdater.id
tmpPath = File.join(Dir.tmpdir, 'hosts-' + uuid + '.cmd')
File.delete(tmpPath) if File.exist?(tmpPath)
File.open(tmpPath, "w") do |tmpFile|
tmpFile.puts "attrib -R \"#{@@hosts_path}\""
entries.each { |line| tmpFile.puts(">>\"#{@@hosts_path}\" echo #{line}") }
tmpFile.puts "attrib +R \"#{@@hosts_path}\""
end
sudo(tmpPath)
#File.delete(tmpPath)
elsif !sudo(%Q(sh -c 'echo "#{content}" >> #{@@hosts_path}'))
@ui.error "[vagrant-hostsupdater] Failed to add hosts, could not use sudo"
adviseOnSudo
end
else
content = "\n" + content + "\n"
hostsFile = File.open(@@hosts_path, "a")
hostsFile.write(content)
hostsFile.close()
end
end
You'll notice I had to comment out File.delete(tmpPath)
. We found that ruby does not wait for win32ole to complete its action - so while you are typing in your admin credentials ruby has continued and already deleted the temporary file!
removeFromHosts
Now this one is stranger as again the test if the 'hosts' file is not writable is true so the bash 'SED' command is again sent to the windows part of the 'sudo' function. SED is not native to windows and all my standalone tests show this command does not work with win32ole. In the cmd windows the '@ui.error' is shown - which is not surprising . But after being asked my admin credentials, my hosts file does get the entries removed! I really cannot work out why that happens!! Inserting @ui.info comments show the alternative 'else' actions are not triggered. The final thing - and it might be a clue about what is happening - is that the removal of the entries converts my 'hosts' file from CRLF to LF. If anyone can explain this to me I would love to hear how removeFromHosts
is working on Windows.
Thanks
You mention great points and I will have to test them out to figure out a better way to manage the Windows prompt. In the meantime try this: https://github.com/cogitatio/vagrant-hostsupdater#windows-uac-prompt
Hi - thanks for taking a look at this when you have time.
I am afraid I can't use your suggestion to add my user write permission to the hosts file - I work in a University and the IT services tend to come down on us like a ton of bricks if they catch us reducing the security of our managed desktops. But thanks for the suggestion all the same.