Skip to content

Instantly share code, notes, and snippets.

@joshbeard
Last active August 29, 2015 14:11
Show Gist options
  • Save joshbeard/5a6f05db7effbff92d2d to your computer and use it in GitHub Desktop.
Save joshbeard/5a6f05db7effbff92d2d to your computer and use it in GitHub Desktop.

bcrypt_auth.rb

Overview

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
    .....
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment