From b57ed27352a1312c99d0b51faf44637805db554e Mon Sep 17 00:00:00 2001 From: Christopher Boumenot Date: Thu, 10 Mar 2016 10:47:30 -0800 Subject: [PATCH] Add support for NTLM the WinRM communicator. WinRM exposes an HTTP transport decorator that can be used for different authentication schemes. Windows on Azures requires this if one is to use the out of the box configuration. --- Godeps/Godeps.json | 2 +- communicator/winrm/communicator.go | 6 ++++++ communicator/winrm/config.go | 16 +++++++++------- helper/communicator/config.go | 16 +++++++++------- helper/communicator/step_connect_winrm.go | 15 ++++++++------- 5 files changed, 33 insertions(+), 22 deletions(-) diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index a8d748d84..ff498ed57 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -329,7 +329,7 @@ }, { "ImportPath": "github.com/packer-community/winrmcp/winrmcp", - "Rev": "3d184cea22ee1c41ec1697e0d830ff0c78f7ea97" + "Rev": "f1bcf36a69fa2945e65dd099eee11b560fbd3346" }, { "ImportPath": "github.com/pierrec/lz4", diff --git a/communicator/winrm/communicator.go b/communicator/winrm/communicator.go index f16721aa4..902211bd2 100644 --- a/communicator/winrm/communicator.go +++ b/communicator/winrm/communicator.go @@ -41,6 +41,11 @@ func New(config *Config) (*Communicator, error) { // Create the client params := winrm.DefaultParameters() + + if config.TransportDecorator != nil { + params.TransportDecorator = config.TransportDecorator + } + params.Timeout = formatDuration(config.Timeout) client, err := winrm.NewClientWithParameters( endpoint, config.Username, config.Password, params) @@ -155,5 +160,6 @@ func (c *Communicator) newCopyClient() (*winrmcp.Winrmcp, error) { Insecure: c.config.Insecure, OperationTimeout: c.config.Timeout, MaxOperationsPerShell: 15, // lowest common denominator + TransportDecorator: c.config.TransportDecorator, }) } diff --git a/communicator/winrm/config.go b/communicator/winrm/config.go index a1874bf26..f9c989028 100644 --- a/communicator/winrm/config.go +++ b/communicator/winrm/config.go @@ -1,16 +1,18 @@ package winrm import ( + "net/http" "time" ) // Config is used to configure the WinRM connection type Config struct { - Host string - Port int - Username string - Password string - Timeout time.Duration - Https bool - Insecure bool + Host string + Port int + Username string + Password string + Timeout time.Duration + Https bool + Insecure bool + TransportDecorator func(*http.Transport) http.RoundTripper } diff --git a/helper/communicator/config.go b/helper/communicator/config.go index 81d347e92..ad90d5e9c 100644 --- a/helper/communicator/config.go +++ b/helper/communicator/config.go @@ -3,6 +3,7 @@ package communicator import ( "errors" "fmt" + "net/http" "os" "time" @@ -32,13 +33,14 @@ type Config struct { SSHFileTransferMethod string `mapstructure:"ssh_file_transfer_method"` // WinRM - WinRMUser string `mapstructure:"winrm_username"` - WinRMPassword string `mapstructure:"winrm_password"` - WinRMHost string `mapstructure:"winrm_host"` - WinRMPort int `mapstructure:"winrm_port"` - WinRMTimeout time.Duration `mapstructure:"winrm_timeout"` - WinRMUseSSL bool `mapstructure:"winrm_use_ssl"` - WinRMInsecure bool `mapstructure:"winrm_insecure"` + WinRMUser string `mapstructure:"winrm_username"` + WinRMPassword string `mapstructure:"winrm_password"` + WinRMHost string `mapstructure:"winrm_host"` + WinRMPort int `mapstructure:"winrm_port"` + WinRMTimeout time.Duration `mapstructure:"winrm_timeout"` + WinRMUseSSL bool `mapstructure:"winrm_use_ssl"` + WinRMInsecure bool `mapstructure:"winrm_insecure"` + WinRMTransportDecorator func(*http.Transport) http.RoundTripper } // Port returns the port that will be used for access based on config. diff --git a/helper/communicator/step_connect_winrm.go b/helper/communicator/step_connect_winrm.go index 26f4536ef..49936ad7b 100644 --- a/helper/communicator/step_connect_winrm.go +++ b/helper/communicator/step_connect_winrm.go @@ -124,13 +124,14 @@ func (s *StepConnectWinRM) waitForWinRM(state multistep.StateBag, cancel <-chan log.Println("[INFO] Attempting WinRM connection...") comm, err = winrm.New(&winrm.Config{ - Host: host, - Port: port, - Username: user, - Password: password, - Timeout: s.Config.WinRMTimeout, - Https: s.Config.WinRMUseSSL, - Insecure: s.Config.WinRMInsecure, + Host: host, + Port: port, + Username: user, + Password: password, + Timeout: s.Config.WinRMTimeout, + Https: s.Config.WinRMUseSSL, + Insecure: s.Config.WinRMInsecure, + TransportDecorator: s.Config.WinRMTransportDecorator, }) if err != nil { log.Printf("[ERROR] WinRM connection err: %s", err)