Move SMB credentials validation into host capability

This commit is contained in:
Chris Roberts 2018-01-12 16:43:19 -08:00
parent 01bc2627be
commit 5444271268
6 changed files with 65 additions and 21 deletions

View File

@ -17,6 +17,16 @@ module VagrantPlugins
true
end
def self.smb_validate_password(env, machine, username, password)
script_path = File.expand_path("../../scripts/check_credentials.ps1", __FILE__)
args = []
args << "-username" << "'#{username.gsub("'", "''")}'"
args << "-password" << "'#{password.gsub("'", "''")}'"
r = Vagrant::Util::PowerShell.execute(script_path, *args)
r.exit_code == 0
end
def self.smb_cleanup(env, machine, opts)
script_path = File.expand_path("../../scripts/unset_share.ps1", __FILE__)

View File

@ -46,6 +46,11 @@ module VagrantPlugins
Cap::SMB
end
host_capability("windows", "smb_cleanup") do
require_relative "cap/smb"
Cap::SMB
end
host_capability("windows", "configured_ip_addresses") do
require_relative "cap/configured_ip_addresses"
Cap::ConfiguredIPAddresses

View File

@ -26,6 +26,10 @@ module VagrantPlugins
error_key(:name_error)
end
class CredentialsRequestError < SMBError
error_key(:credentials_request_error)
end
class DefineShareFailed < SMBError
error_key(:define_share_failed)
end

View File

@ -11,6 +11,10 @@ require_relative "errors"
module VagrantPlugins
module SyncedFolderSMB
class SyncedFolder < Vagrant.plugin("2", :synced_folder)
# Maximum number of times to retry requesting username/password
CREDENTIAL_RETRY_MAX = 5
def initialize(*args)
super
@ -43,28 +47,27 @@ module VagrantPlugins
end
end
script_path = File.expand_path("../scripts/check_credentials.ps1", __FILE__)
if !have_auth
machine.ui.detail(I18n.t("vagrant_sf_smb.warning_password") + "\n ")
auth_success = false
while !auth_success do
@creds[:username] = machine.ui.ask("Username: ")
@creds[:password] = machine.ui.ask("Password (will be hidden): ", echo: false)
retries = 0
while retries < CREDENTIAL_RETRY_MAX do
smb_username = machine.ui.ask("Username: ")
smb_password = machine.ui.ask("Password (will be hidden): ", echo: false)
auth_success = true
args = []
args << "-username" << "'#{@creds[:username].gsub("'", "''")}'"
args << "-password" << "'#{@creds[:password].gsub("'", "''")}'"
r = Vagrant::Util::PowerShell.execute(script_path, *args)
if r.exit_code == 0
auth_success = true
if machine.env.host.capability?(:smb_validate_password)
Vagrant::Util::CredentialScrubber.sensitive(smb_password)
auth_success = machine.env.host.capability(:smb_validate_password,
smb_username, smb_password)
end
if !auth_success
machine.ui.output(I18n.t("vagrant_sf_smb.incorrect_credentials") + "\n ")
end
break if auth_success
machine.ui.output(I18n.t("vagrant_sf_smb.incorrect_credentials") + "\n ")
retries += 1
end
if retries >= CREDENTIAL_RETRY_MAX
raise Errors::CredentialsRequestError
end
end
@ -73,8 +76,6 @@ module VagrantPlugins
machine.env.host.capability(:smb_start)
end
script_path = File.expand_path("../scripts/set_share.ps1", __FILE__)
folders.each do |id, data|
data[:smb_username] ||= smb_username
data[:smb_password] ||= smb_password

View File

@ -39,6 +39,9 @@ en:
Vagrant SMB synced folders require the account password to be stored
in an NT compatible format. Please update your sharing settings to
enable a Windows compatible password and try again.
credentials_request_error: |-
Vagrant failed to receive credential information required for preparing
an SMB share.
define_share_failed: |-
Exporting an SMB share failed! Details about the failure are shown
below. Please inspect the error message and correct any problems.

View File

@ -71,8 +71,8 @@ describe VagrantPlugins::SyncedFolderSMB::SyncedFolder do
context "without credentials provided" do
before do
expect(machine.env.ui).to receive(:ask).and_return('username')
expect(machine.env.ui).to receive(:ask).and_return('password')
expect(machine.env.ui).to receive(:ask).with(/name/, any_args).and_return('username').at_least(1)
expect(machine.env.ui).to receive(:ask).with(/word/, any_args).and_return('password').at_least(1)
end
it "should prompt for credentials" do
@ -91,6 +91,27 @@ describe VagrantPlugins::SyncedFolderSMB::SyncedFolder do
expect(host).to receive(:capability).with(:smb_start, any_args)
subject.prepare(machine, folders, options)
end
context "with host smb_validate_password capability" do
let(:host_caps){ [:smb_start, :smb_prepare, :smb_validate_password] }
it "should validate the password" do
expect(host).to receive(:capability).with(:smb_validate_password, 'username', 'password').and_return(true)
subject.prepare(machine, folders, options)
end
it "should retry when validation fails" do
expect(host).to receive(:capability).with(:smb_validate_password, 'username', 'password').and_return(false)
expect(host).to receive(:capability).with(:smb_validate_password, 'username', 'password').and_return(true)
subject.prepare(machine, folders, options)
end
it "should raise an error if it exceeds the maximum number of retries" do
expect(host).to receive(:capability).with(:smb_validate_password, 'username', 'password').and_return(false).
exactly(VagrantPlugins::SyncedFolderSMB::SyncedFolder::CREDENTIAL_RETRY_MAX).times
expect{ subject.prepare(machine, folders, options) }.to raise_error(VagrantPlugins::SyncedFolderSMB::Errors::CredentialsRequestError)
end
end
end
context "with credentials provided" do