WinRM SSL support

This commit is contained in:
Max Lincoln 2014-12-11 13:55:49 -05:00
parent 61a792ac9f
commit 234adaae63
8 changed files with 114 additions and 53 deletions

View File

@ -106,11 +106,8 @@ module VagrantPlugins
WinRMShell.new(
winrm_info[:host],
@machine.config.winrm.username,
@machine.config.winrm.password,
port: winrm_info[:port],
timeout_in_seconds: @machine.config.winrm.timeout,
max_tries: @machine.config.winrm.max_tries,
winrm_info[:port],
@machine.config.winrm
)
end

View File

@ -8,6 +8,8 @@ module VagrantPlugins
attr_accessor :guest_port
attr_accessor :max_tries
attr_accessor :timeout
attr_accessor :transport
attr_accessor :ssl_peer_verification
def initialize
@username = UNSET_VALUE
@ -17,16 +19,21 @@ module VagrantPlugins
@guest_port = UNSET_VALUE
@max_tries = UNSET_VALUE
@timeout = UNSET_VALUE
@transport = UNSET_VALUE
@ssl_peer_verification = UNSET_VALUE
end
def finalize!
@username = "vagrant" if @username == UNSET_VALUE
@password = "vagrant" if @password == UNSET_VALUE
@transport = :plaintext if @transport == UNSET_VALUE
@host = nil if @host == UNSET_VALUE
@port = 5985 if @port == UNSET_VALUE
@guest_port = 5985 if @guest_port == UNSET_VALUE
is_ssl = @transport == :ssl
@port = (is_ssl ? 5986 : 5985) if @port == UNSET_VALUE
@guest_port = (is_ssl ? 5986 : 5985) if @guest_port == UNSET_VALUE
@max_tries = 20 if @max_tries == UNSET_VALUE
@timeout = 1800 if @timeout == UNSET_VALUE
@ssl_peer_verification = true if @ssl_peer_verification == UNSET_VALUE
end
def validate(machine)
@ -38,6 +45,9 @@ module VagrantPlugins
errors << "winrm.guest_port cannot be nil." if @guest_port.nil?
errors << "winrm.max_tries cannot be nil." if @max_tries.nil?
errors << "winrm.timeout cannot be nil." if @timeout.nil?
unless @ssl_peer_verification == true || @ssl_peer_verification == false
errors << "winrm.ssl_peer_verification must be a boolean."
end
{ "WinRM" => errors }
end

View File

@ -32,23 +32,21 @@ module VagrantPlugins
]
attr_reader :logger
attr_reader :username
attr_reader :password
attr_reader :host
attr_reader :port
attr_reader :timeout_in_seconds
attr_reader :max_tries
attr_reader :username
attr_reader :password
attr_reader :config
def initialize(host, username, password, options = {})
def initialize(host, port, config)
@logger = Log4r::Logger.new("vagrant::communication::winrmshell")
@logger.debug("initializing WinRMShell")
@host = host
@port = options[:port] || 5985
@username = username
@password = password
@timeout_in_seconds = options[:timeout_in_seconds] || 60
@max_tries = options[:max_tries] || 20
@port = port
@username = config.username
@password = config.password
@config = config
end
def powershell(command, &block)
@ -87,7 +85,7 @@ module VagrantPlugins
end
def execute_shell_with_retry(command, shell, &block)
retryable(tries: @max_tries, on: @@exceptions_to_retry_on, sleep: 10) do
retryable(tries: @config.max_tries, on: @@exceptions_to_retry_on, sleep: 10) do
@logger.debug("#{shell} executing:\n#{command}")
output = session.send(shell, command) do |out, err|
block.call(:stdout, out) if block_given? && out
@ -118,10 +116,11 @@ module VagrantPlugins
@logger.info("Attempting to connect to WinRM...")
@logger.info(" - Host: #{@host}")
@logger.info(" - Port: #{@port}")
@logger.info(" - Username: #{@username}")
@logger.info(" - Username: #{@config.username}")
@logger.info(" - Transport: #{@config.transport}")
client = ::WinRM::WinRMWebService.new(endpoint, :plaintext, endpoint_options)
client.set_timeout(@timeout_in_seconds)
client = ::WinRM::WinRMWebService.new(endpoint, @config.transport.to_sym, endpoint_options)
client.set_timeout(@config.timeout)
client.toggle_nori_type_casting(:off) #we don't want coersion of types
client
end
@ -131,7 +130,14 @@ module VagrantPlugins
end
def endpoint
case @config.transport.to_sym
when :ssl
"https://#{@host}:#{@port}/wsman"
when :plaintext
"http://#{@host}:#{@port}/wsman"
else
raise Errors::WinRMInvalidTransport, transport: @config.transport
end
end
def endpoint_options
@ -139,8 +145,8 @@ module VagrantPlugins
pass: @password,
host: @host,
port: @port,
operation_timeout: @timeout_in_seconds,
basic_auth_only: true }
basic_auth_only: true,
no_ssl_peer_verification: !@config.ssl_peer_verification }
end
end #WinShell class
end

View File

@ -399,10 +399,15 @@ module VagrantPlugins
host_ip: "127.0.0.1",
id: "winrm",
auto_correct: true
end
end
if !@__networks["forwarded_port-ssh"]
network :forwarded_port,
guest: 5986,
host: 55986,
host_ip: "127.0.0.1",
id: "winrm-ssl",
auto_correct: true
end
elsif !@__networks["forwarded_port-ssh"]
network :forwarded_port,
guest: 22,
host: 2222,

View File

@ -1,14 +1,23 @@
require File.expand_path("../../../../base", __FILE__)
require Vagrant.source_root.join("plugins/communicators/winrm/shell")
require Vagrant.source_root.join("plugins/communicators/winrm/config")
describe VagrantPlugins::CommunicatorWinRM::WinRMShell do
include_context "unit"
let(:session) { double("winrm_session") }
let(:port) { config.transport == :ssl ? 5986 : 5985 }
let(:config) {
VagrantPlugins::CommunicatorWinRM::Config.new.tap do |c|
c.username = 'username'
c.password = 'password'
c.finalize!
end
}
subject do
described_class.new('localhost', 'username', 'password').tap do |comm|
described_class.new('localhost', port, config).tap do |comm|
allow(comm).to receive(:new_session).and_return(session)
end
end
@ -20,7 +29,8 @@ describe VagrantPlugins::CommunicatorWinRM::WinRMShell do
end
it "should raise auth error when exception message contains 401" do
expect(session).to receive(:powershell).with(/^dir.+/).and_raise(
config.winrm.max_tries = 2
expect(session).to receive(:powershell).with(/^dir.+/).twice.and_raise(
StandardError.new("Oh no! a 401 SOAP error!"))
expect { subject.powershell("dir") }.to raise_error(
VagrantPlugins::CommunicatorWinRM::Errors::AuthError)
@ -42,16 +52,30 @@ describe VagrantPlugins::CommunicatorWinRM::WinRMShell do
end
describe ".endpoint" do
it "should create winrm endpoint address" do
context 'when transport is :ssl' do
let(:config) {
VagrantPlugins::CommunicatorWinRM::Config.new.tap do |c|
c.transport = :ssl
c.finalize!
end
}
it "should create winrm endpoint address using https" do
expect(subject.send(:endpoint)).to eq("https://localhost:5986/wsman")
end
end
context "when transport is :plaintext" do
it "should create winrm endpoint address using http" do
expect(subject.send(:endpoint)).to eq("http://localhost:5985/wsman")
end
end
end
describe ".endpoint_options" do
it "should create endpoint options" do
expect(subject.send(:endpoint_options)).to eq(
{ user: "username", pass: "password", host: "localhost", port: 5985,
operation_timeout: 60, basic_auth_only: true })
basic_auth_only: true, no_ssl_peer_verification: false })
end
end

View File

@ -23,6 +23,13 @@ describe VagrantPlugins::Kernel_V2::VMConfig do
end
end
def find_network(name)
network_definitions = subject.networks.map do |n|
n[1]
end
network_definitions.find {|n| n[:id] == name}
end
before do
env = double("env")
env.stub(root_path: nil)
@ -183,6 +190,7 @@ describe VagrantPlugins::Kernel_V2::VMConfig do
subject.finalize!
n = subject.networks
expect(n.length).to eq(2)
expect(n[0][0]).to eq(:forwarded_port)
expect(n[0][1][:guest]).to eq(5985)
expect(n[0][1][:host]).to eq(55985)
@ -190,9 +198,10 @@ describe VagrantPlugins::Kernel_V2::VMConfig do
expect(n[0][1][:id]).to eq("winrm")
expect(n[1][0]).to eq(:forwarded_port)
expect(n[1][1][:guest]).to eq(22)
expect(n[1][1][:host]).to eq(2222)
expect(n[1][1][:id]).to eq("ssh")
expect(n[1][1][:guest]).to eq(5986)
expect(n[1][1][:host]).to eq(55986)
expect(n[1][1][:host_ip]).to eq("127.0.0.1")
expect(n[1][1][:id]).to eq("winrm-ssl")
end
it "allows overriding SSH" do
@ -214,12 +223,22 @@ describe VagrantPlugins::Kernel_V2::VMConfig do
guest: 22, host: 14100, id: "winrm"
subject.finalize!
n = subject.networks
expect(n.length).to eq(2)
expect(n[0][0]).to eq(:forwarded_port)
expect(n[0][1][:guest]).to eq(22)
expect(n[0][1][:host]).to eq(14100)
expect(n[0][1][:id]).to eq("winrm")
winrm_network = find_network 'winrm'
expect(winrm_network[:guest]).to eq(22)
expect(winrm_network[:host]).to eq(14100)
expect(winrm_network[:id]).to eq("winrm")
end
it "allows overriding WinRM SSL" do
subject.communicator = :winrmssl
subject.network "forwarded_port",
guest: 22, host: 14100, id: "winrmssl"
subject.finalize!
winrmssl_network = find_network 'winrmssl'
expect(winrmssl_network[:guest]).to eq(22)
expect(winrmssl_network[:host]).to eq(14100)
expect(winrmssl_network[:id]).to eq("winrmssl")
end
it "turns all forwarded port ports to ints" do

View File

@ -28,7 +28,7 @@ Gem::Specification.new do |s|
s.add_dependency "rb-kqueue", "~> 0.2.0"
s.add_dependency "rest-client", ">= 1.6.0", "< 2.0"
s.add_dependency "wdm", "~> 0.1.0"
s.add_dependency "winrm", "~> 1.1.3"
s.add_dependency "winrm", "= 1.3.0.dev.2"
# We lock this down to avoid compilation issues.
s.add_dependency "nokogiri", "= 1.6.3.1"