Wrapper class to ultimately save a salted/hashed password to a file on disk for authenticating against vSphere.
If a credentials file is not found, this will prompt for a password pair and save the salted/hashed to a file.
If a credentials file IS found, it will prompt for a password and attempt to validate it.
This uses bcrypt()
from the OpenBSD guys and the Ruby bcrypt-ruby library.
Disclaimers:
The code probably sucks. I'm not a strong coder, yo. Fortunately, I'm not responsible for the security, as that's done via bcrypt-ruby. You're still storing a file on disk, but it's better than plain text or a bad algorithm.
Some of the design choices here were made to just make the thing usable
in your Vagrantfile with as little work or logic handling on your part
as possible. Assuming you don't want to have to handle that sort of thing,
like prompting, validation, etc. Just stick a couple of lines in your
Vagrantfile
.
This is the class: vsphereauth.rb
Just stick this in a file somewhere. Edit if you want, but you shouldn't need to for basic use.
class Vsphereauth
require 'bcrypt'
def initialize(filename)
@@cred_file = filename
if ! File.exists?(@@cred_file)
puts "=> No vSphere credentials found in #{@@cred_file}"
puts "=> Creating new file..."
Vsphereauth.create_password()
else
if File.readable?(@@cred_file)
Vsphereauth.prompt_password()
else
puts "FATAL: #{@@cred_file} is not readable!"
end
end
end
def self.create_password(max=3,num=1)
begin
print 'Enter vSphere Password'
# We hide the entered characters before to ask for the password
system 'stty -echo'
password1 = $stdin.gets.chomp
print "\nConfirm Enter vSphere Password"
password2 = $stdin.gets.chomp
system 'stty echo'
print "\n"
if password1 != password2
puts
puts "Password mismatch! Attempt #{num}/#{max}"
if num < max
num += 1
self.create_password(max,num)
else
puts "Too many failed attempts."
return false
end
else
File.open(@@cred_file, 'w') do |pw|
enc_password = BCrypt::Password.create(password1)
pw.write enc_password.to_s
puts "=> Credentials saved to #{@@cred_file}"
end
File.chmod(0400, @@cred_file)
@@password = password1
end
rescue NoMethodError, Interrupt
# When the process is exited, we display the characters again
# And we exit
system 'stty echo'
exit
end
end
def self.prompt_password(max=3,num=1)
begin
print 'Enter vSphere Password: '
# We hide the entered characters before to ask for the password
system 'stty -echo'
password = $stdin.gets.chomp
system 'stty echo'
print "\n"
saved_password = BCrypt::Password.new(File.read(@@cred_file))
if saved_password != password
puts
puts "Password mismatch! #{num}/#{max}"
if num < max
num += 1
self.prompt_password(max,num)
else
puts "Too many failed attempts."
return false
end
else
@@password = password
end
rescue NoMethodError, Interrupt
# When the process is exited, we display the characters again
# And we exit
system 'stty echo'
exit
end
end
def self.password()
if defined?(@@password)
return @@password
else
return false
end
end
end
Here's an example of what you might put in your Vagrantfile:
require './path/to/vsphereauth.rb'
Vsphereauth.new('.mycreds')
if Vsphereauth.password
my_password = Vsphereauth.password
else
puts "vSphere credentials not available."
exit 1
end
## Then just use the 'my_password' var wherever you need it....
config.vm.provider :vsphere do |vsphere|
.....
vsphere.password = my_password
.....