// Creates a new packer.Communicator implementation over WinRM. // Called when Packer tries to connect to WinRM func New(endpoint *winrm.Endpoint, user string, password string, timeout time.Duration) (*Communicator, error) { // Create the WinRM client we use internally params := winrm.DefaultParameters() params.Timeout = iso8601.FormatDuration(timeout) client, err := winrm.NewClientWithParameters(endpoint, user, password, params) if err != nil { return nil, err } // Attempt to connect to the WinRM service shell, err := client.CreateShell() if err != nil { return nil, err } err = shell.Close() if err != nil { return nil, err } return &Communicator{ endpoint: endpoint, user: user, password: password, }, nil }
// Connect implementation of communicator.Communicator interface func (c *Communicator) Connect(o terraform.UIOutput) error { if c.client != nil { return nil } params := winrm.DefaultParameters() params.Timeout = formatDuration(c.Timeout()) client, err := winrm.NewClientWithParameters( c.endpoint, c.connInfo.User, c.connInfo.Password, params) if err != nil { return err } if o != nil { o.Output(fmt.Sprintf( "Connecting to remote host via WinRM...\n"+ " Host: %s\n"+ " Port: %d\n"+ " User: %s\n"+ " Password: %t\n"+ " HTTPS: %t\n"+ " Insecure: %t\n"+ " CACert: %t", c.connInfo.Host, c.connInfo.Port, c.connInfo.User, c.connInfo.Password != "", c.connInfo.HTTPS, c.connInfo.Insecure, c.connInfo.CACert != nil, )) } log.Printf("connecting to remote shell using WinRM") shell, err := client.CreateShell() if err != nil { log.Printf("connection error: %s", err) return err } err = shell.Close() if err != nil { log.Printf("error closing connection: %s", err) return err } if o != nil { o.Output("Connected!") } c.client = client return nil }
// New creates a new communicator implementation over WinRM. func New(config *Config) (*Communicator, error) { endpoint := &winrm.Endpoint{ Host: config.Host, Port: config.Port, HTTPS: config.Https, Insecure: config.Insecure, /* TODO HTTPS: connInfo.HTTPS, Insecure: connInfo.Insecure, CACert: connInfo.CACert, */ } // 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) if err != nil { return nil, err } // Create the shell to verify the connection log.Printf("[DEBUG] connecting to remote shell using WinRM") shell, err := client.CreateShell() if err != nil { log.Printf("[ERROR] connection error: %s", err) return nil, err } if err := shell.Close(); err != nil { log.Printf("[ERROR] error closing connection: %s", err) return nil, err } return &Communicator{ config: config, client: client, endpoint: endpoint, }, nil }
func New(addr string, config *Config) (*Winrmcp, error) { endpoint, err := parseEndpoint(addr, config.Https, config.Insecure, config.CACertBytes) if err != nil { return nil, err } if config == nil { config = &Config{} } params := winrm.DefaultParameters() if config.OperationTimeout.Seconds() > 0 { params.Timeout = iso8601.FormatDuration(config.OperationTimeout) } client, err := winrm.NewClientWithParameters( endpoint, config.Auth.User, config.Auth.Password, params) return &Winrmcp{client, config}, err }
func StartElevated() (err error) { // The command gets put into an interpolated string in the PS script, // so we need to escape any embedded quotes. cmd = strings.Replace(cmd, "\"", "`\"", -1) elevatedScript, err := createCommandText() if err != nil { return err } // Upload the script which creates and manages the scheduled task winrmcp, err := winrmcp.New(fmt.Sprintf("%s:%d", hostname, port), &winrmcp.Config{ Auth: winrmcp.Auth{user, pass}, OperationTimeout: time.Second * 60, MaxOperationsPerShell: 15, }) tmpFile, err := ioutil.TempFile(os.TempDir(), "packer-elevated-shell.ps1") log.Printf("Temp file: %s", tmpFile.Name()) writer := bufio.NewWriter(tmpFile) if _, err := writer.WriteString(elevatedScript); err != nil { return fmt.Errorf("Error preparing shell script: %s", err) } if err := writer.Flush(); err != nil { return fmt.Errorf("Error preparing shell script: %s", err) } tmpFile.Close() err = winrmcp.Copy(tmpFile.Name(), "${env:TEMP}/packer-elevated-shell.ps1") if err != nil { log.Printf("Error copying shell script: %s", err) return err } // Run the script that was uploaded command := fmt.Sprintf("powershell -executionpolicy bypass -file \"%s\"", "%TEMP%\\packer-elevated-shell.ps1") log.Printf("Running script: %s", command) client, err = winrm.NewClientWithParameters(&winrm.Endpoint{Host: hostname, Port: port, HTTPS: false, Insecure: true, CACert: nil}, user, pass, winrm.NewParameters(timeout, "en-US", 153600)) _, err = client.RunWithInput(command, os.Stdout, os.Stderr, os.Stdin) return err }
func main() { flag.StringVar(&hostname, "hostname", "localhost", "winrm host") flag.StringVar(&user, "username", "vagrant", "winrm admin username") flag.StringVar(&pass, "password", "vagrant", "winrm admin password") flag.StringVar(&timeout, "timeout", "PT36000S", "winrm timeout") flag.IntVar(&port, "port", 5985, "winrm port") flag.BoolVar(&elevated, "elevated", false, "run as elevated user?") flag.BoolVar(&debug, "debug", false, "output debugging info") flag.Parse() cmdB, _ := ioutil.ReadAll(os.Stdin) cmd = string(cmdB) if !debug { log.SetOutput(ioutil.Discard) } log.Printf("Command to run: %s", cmd) log.Printf("user to run: %s", user) log.Printf("pass to run: %s", pass) log.Printf("host to run: %s", hostname) log.Printf("port to run: %s", port) client, err := winrm.NewClientWithParameters(&winrm.Endpoint{Host: hostname, Port: port, HTTPS: false, Insecure: true, CACert: nil}, user, pass, winrm.NewParameters(timeout, "en-US", 153600)) if !elevated { _, err = client.RunWithInput(winrm.Powershell(cmd), os.Stdout, os.Stderr, os.Stdin) } else { err = StartElevated() } if err != nil { fmt.Println(err) os.Exit(1) } os.Exit(0) }
// // WinRMRunCmdWithNTLM runs a command on a Windows Server (specifically // an Azure VM with Windows). Uses WinRM with NTLM support enabled. // WinRM should be enabled on the target server. // // Ref: https://github.com/masterzen/winrm/blob/master/README.md#pluggable-authentication-example-negotiatentlm-authentication // // Parameters: // host: target Windows server host // username: username for the host // password: password for the host // command: command to run // Returns: // string: stdout from command execution // string: stderr from command execution // int: exit status from the command being run // error: errors from establishing connection and running command // func WinRMRunCmdWithNTLM(host string, username string, password string, command string) (string, string, int, error) { var err error params := newwinrm.DefaultParameters() params.TransportDecorator = func(t *http.Transport) http.RoundTripper { return ntlmssp.Negotiator{t} } client, err := newwinrm.NewClientWithParameters(&newwinrm.Endpoint{Host: host, Port: 5986, HTTPS: true, Insecure: true}, username, password, params) if err != nil { log.Error("failed to create shell: ", err) return "", "", -1, err } stdout, stderr, exitcode, err := client.RunWithString(command, "") if err != nil { log.Error("failed to run cmd: ", err) return "", "", -1, err } log.Debug("stdout:", stdout, "stderr:", stderr, "exitcode:", exitcode) return stdout, stderr, exitcode, err }
func (c *Communicator) Start(rc *packer.RemoteCmd) error { log.Printf("starting remote command: %s", rc.Command) // Create a new shell process on the guest params := winrm.DefaultParameters() params.Timeout = iso8601.FormatDuration(time.Hour * 24) client, err := winrm.NewClientWithParameters(c.endpoint, c.user, c.password, params) if err != nil { return err } shell, err := client.CreateShell() if err != nil { return err } cmd, err := shell.Execute(rc.Command) if err != nil { return err } go runCommand(shell, cmd, rc) return nil }