title: Golang SSH to Cisco Wireless Controller and Run Commands
body: <p>I am trying to SSH to a Cisco wireless controller through Go, using Go's <code>golang.org/x/crypto/ssh</code> library, to programmatically configure access points. The problem I'm running into is correctly parsing the controller CLI in Go. For example, this is the typical SSH login to the controller:</p>
  
  <pre><code>$ ssh &lt;controller_ip&gt;
  
  
  (Cisco Controller)
  User: username
  Password:****************
  (Cisco Controller) &gt;
  </code></pre>
  
  <p>I am trying to figure out how to send the username and then the password after the SSH session is established in Go. So far, I am able to successfully SSH to the controller, but the program exits at the username prompt, like this:</p>
  
  <pre><code>$ go run main.go 
  
  
  (Cisco Controller) 
  User: 
  </code></pre>
  
  <p><strong>How would I go about sending the username when prompted, then repeating that for the password prompt?</strong> </p>
  
  <p>No errors are being thrown or exit codes are being given, so I'm not sure why the program is exiting immediately at the username prompt. But Even if it wasn't exiting that way, I'm still unsure of how to send the username and password when the controller's CLI is expecting it.</p>
  
  <p>Here is my code:</p>
  
  <pre><code>package main
  
  import (
      "golang.org/x/crypto/ssh"
      "log"
      "io/ioutil"
      "os"
      "strings"
      "path/filepath"
      "bufio"
      "fmt"
      "errors"
      "time"
  )
  
  const (
      HOST = "host"
  )
  
  func main() {
      hostKey, err := checkHostKey(HOST)
      if err != nil {
          log.Fatal(err)
      }
  
      key, err := ioutil.ReadFile("/Users/user/.ssh/id_rsa")
      if err != nil {
          log.Fatalf("unable to read private key: %v", err)
      }
  
      // Create the Signer for this private key.
      signer, err := ssh.ParsePrivateKey(key)
      if err != nil {
          log.Fatalf("unable to parse private key: %v", err)
      }
  
      // Create client config
      config := &amp;ssh.ClientConfig{
          User: "username",
          Auth: []ssh.AuthMethod{
              ssh.Password("password"),
              // Use the PublicKeys method for remote authentication.
              ssh.PublicKeys(signer),
          },
          HostKeyCallback: ssh.FixedHostKey(hostKey),
          Timeout: time.Second * 5,
      }
  
      // Connect to the remote server and perform the SSH handshake.
      client, err := ssh.Dial("tcp", HOST+":22", config)
      if err != nil {
          log.Fatalf("unable to connect: %v", err)
      }
      defer client.Close()
      // Create a session
      session, err := client.NewSession()
      if err != nil {
          log.Fatal("Failed to create session: ", err)
      }
      defer session.Close()
  
      stdin, err := session.StdinPipe()
      if err != nil {
          log.Fatal(err)
      }
      stdout, err := session.StdoutPipe()
      if err != nil {
          log.Fatal(err)
      }
  
      modes := ssh.TerminalModes{
          ssh.ECHO:          0,
          ssh.TTY_OP_ISPEED: 9600,
          ssh.TTY_OP_OSPEED: 9600,
      }
  
      if err := session.RequestPty("xterm", 0, 200, modes); err != nil {
          log.Fatal(err)
      }
      if err := session.Shell(); err != nil {
          log.Fatal(err)
      }
  
      buf := make([]byte, 1000)
      n, err := stdout.Read(buf) //this reads the ssh terminal welcome message
      loadStr := ""
      if err == nil {
          loadStr = string(buf[:n])
      }
      for (err == nil) &amp;&amp; (!strings.Contains(loadStr, "(Cisco Controller)")) {
          n, err = stdout.Read(buf)
          loadStr += string(buf[:n])
      }
      fmt.Println(loadStr)
  
      if _, err := stdin.Write([]byte("show ap summary\r")); err != nil {
          panic("Failed to run: " + err.Error())
      }
  }
  
  func checkHostKey(host string) (ssh.PublicKey, error) {
      file, err := os.Open(filepath.Join(os.Getenv("HOME"), ".ssh", "known_hosts"))
      if err != nil {
          return nil, err
      }
      defer file.Close()
  
      scanner := bufio.NewScanner(file)
      var hostKey ssh.PublicKey
      for scanner.Scan() {
          fields := strings.Split(scanner.Text(), " ")
          if len(fields) != 3 {
              continue
          }
          if strings.Contains(fields[0], host) {
              hostKey, _, _, _, err = ssh.ParseAuthorizedKey(scanner.Bytes())
              if err != nil {
                  return nil, errors.New(fmt.Sprintf("error parsing %q: %v", fields[2], err))
              }
              break
          }
      }
  
      if hostKey == nil {
          return nil, errors.New(fmt.Sprintf("no hostkey for %s", host))
      }
  
      return hostKey, nil
  }
  </code></pre>