Skip to content
This repository was archived by the owner on Jun 11, 2024. It is now read-only.

Commit

Permalink
Implemented bastion support
Browse files Browse the repository at this point in the history
  • Loading branch information
Blake Watters committed Apr 26, 2020
1 parent 572474b commit bf258a7
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 12 deletions.
21 changes: 16 additions & 5 deletions command/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -379,11 +379,12 @@ func (cmd *BaseCommand) RemoveServo(servo Servo) error {

// Servo represents a deployed Servo assembly running somewhere
type Servo struct {
Name string
User string
Host string
Port string
Path string
Name string
User string
Host string
Port string
Path string
Bastion string
}

func (s Servo) HostAndPort() string {
Expand Down Expand Up @@ -420,3 +421,13 @@ func (s Servo) URL() string {
}
return fmt.Sprintf("ssh://%s@%s:%s", s.User, s.DisplayHost(), pathComponent)
}

func (s Servo) BastionComponents() (string, string) {
components := strings.Split(s.Bastion, "@")
user := components[0]
host := components[1]
if !strings.Contains(host, ":") {
host = host + ":22"
}
return user, host
}
47 changes: 40 additions & 7 deletions command/servo.go
Original file line number Diff line number Diff line change
Expand Up @@ -420,23 +420,56 @@ func (servoCmd *servoCommand) runInSSHSession(ctx context.Context, name string,
HostKeyCallback: hostKeyCallback,
}

// Connect to host
client, err := ssh.Dial("tcp", servo.HostAndPort(), config)
if err != nil {
log.Fatal(err)
// Support bastion hosts via redialing
var sshClient *ssh.Client
if servo.Bastion != "" {
user, host := servo.BastionComponents()
bastionConfig := &ssh.ClientConfig{
User: user,
Auth: []ssh.AuthMethod{
servoCmd.sshAgent(),
},
HostKeyCallback: hostKeyCallback,
}

// Dial the bastion host
bastionClient, err := ssh.Dial("tcp", host, bastionConfig)
if err != nil {
log.Fatal(err)
}

// Establish a new connection thrrough the bastion
conn, err := bastionClient.Dial("tcp", servo.HostAndPort())
if err != nil {
log.Fatal(err)
}

// Build a new SSH connection on top of the bastion connection
ncc, chans, reqs, err := ssh.NewClientConn(conn, servo.HostAndPort(), config)
if err != nil {
log.Fatal(err)
}

// Now connection a client on top of it
sshClient = ssh.NewClient(ncc, chans, reqs)
} else {
sshClient, err = ssh.Dial("tcp", servo.HostAndPort(), config)
if err != nil {
log.Fatal(err)
}
}
defer client.Close()
defer sshClient.Close()

// Create sesssion
session, err := client.NewSession()
session, err := sshClient.NewSession()
if err != nil {
log.Fatal("Failed to create session: ", err)
}
defer session.Close()

go func() {
<-ctx.Done()
client.Close()
sshClient.Close()
}()

return runIt(ctx, *servo, session)
Expand Down

0 comments on commit bf258a7

Please sign in to comment.