Skip to content

Commit

Permalink
Added client launcher
Browse files Browse the repository at this point in the history
  • Loading branch information
techiemac committed Sep 17, 2021
1 parent d42fa05 commit f556e0c
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 42 deletions.
98 changes: 59 additions & 39 deletions internal/cmd/connect.go
Expand Up @@ -3,8 +3,11 @@ package cmd
import (
"context"
"fmt"
"getswizzle.io/swiz/internal/config"
"getswizzle.io/swiz/pkg/client"
"getswizzle.io/swiz/pkg/clihelper"
"getswizzle.io/swiz/pkg/infra"
"getswizzle.io/swiz/pkg/infra/model"
"getswizzle.io/swiz/pkg/network/ssh"
"github.com/urfave/cli/v2"
"log"
Expand All @@ -21,20 +24,13 @@ func init() {
Action: connectCmd,
Flags: []cli.Flag{
&cli.StringFlag{
Name: "bastion",
Aliases: []string{"b"},
Usage: "bastion host address",
Required: true,
Name: "cfg",
Aliases: []string{"c"},
Usage: "config file location",
},
&cli.StringFlag{
Name: "key",
Aliases: []string{"k"},
Usage: "ssh key file",
Required: true,
},
&cli.StringFlag{
Name: "connect",
Aliases: []string{"c"},
Name: "remote",
Aliases: []string{"r"},
Usage: "remote endpoint to tunnel to",
Required: false,
},
Expand All @@ -48,7 +44,7 @@ func init() {
})
}

func launchTunnel(tun *ssh.Tunnel) {
func launchTunnel(tun *ssh.Tunnel) chan struct{} {
cCtx, cancel := context.WithCancel(context.Background())
exitCh := make(chan struct{})
go func(ctx context.Context) {
Expand Down Expand Up @@ -79,56 +75,80 @@ func launchTunnel(tun *ssh.Tunnel) {

time.Sleep(500 * time.Millisecond) // TODO: Poll for channel

<-exitCh
return exitCh
}

// connectCmd runs the connect command
func connectCmd(ctx *cli.Context) error {
fmt.Printf("Connecting to host\n")
bastion := ctx.String("bastion")
key := ctx.String("key")
host := ctx.String("connect")
host := ctx.String("remote")
filename := ctx.String("cfg")

// Load the config
cfgStore := config.NewConfigMustLoad(filename)

// Create the infra services and determine which service to use
svc, err := infra.NewInfraService()
if err != nil {
log.Fatalf("creating infrastructure service. %v", err)
}

services := svc.ListServices()
var hostObj *model.TargetInstance
if host == "" {
services := svc.ListServices()

service := clihelper.GetOrPromptOptions(ctx, "service", "Select the service that you would like to connect to",
services, "Quit")
if service == "" {
// Quit
return nil
}
log.Printf("Fetching instances from %v", service)

hosts, err := svc.GetInstances(service)
if err != nil {
log.Fatalf("error fetching instances: %v", err)
}
hostMap := map[string]string{}
hostObjMap := map[string]*model.TargetInstance{}
for k, v := range hosts {
hostMap[v.String()] = k
h := hosts[k]
hostObjMap[k] = &h
}
host = clihelper.GetOrPromptOptions(ctx, "remote", "Select the host that you want to connect to", hostMap, "Quit")
if host == "" {
// Quit
return nil
}

service := clihelper.GetOrPromptOptions(ctx, "service", "Select the service that you would like to connect to",
services, "Quit")
if service == "" {
// Quit
return nil
hostObj = hostObjMap[host]
}
log.Printf("Fetching instances from %v", service)

hosts, err := svc.GetInstances(service)
launchInfo, err := cfgStore.GetHostLaunchInfo(*hostObj)
if err != nil {
log.Fatalf("error fetching instances: %v", err)
}
hostMap := map[string]string{}
for k, v := range hosts {
hostMap[v.String()] = k
}
host = clihelper.GetOrPromptOptions(ctx, "connect", "Select the host that you want to connect to", hostMap, "Quit")
if host == "" {
// Quit
return nil
log.Fatalf("fetching host launch info %v", err)
}
log.Printf("%v", host)

// Connect
keyAuth := ssh.NewPrivateKeyAuth()
err = keyAuth.InitFromFile(key)
err = keyAuth.InitFromFile(launchInfo.BastionAuth.KeyFilename) // TODO: BastionAuth should come from a keyauth factory
if err != nil {
log.Fatalf("loading key %v", err)
}
tun := ssh.NewSshTunnel(bastion, keyAuth.GetAuthMethod(), host, 0)
tun := ssh.NewSshTunnel(launchInfo.BastionAddr, keyAuth.GetAuthMethod(), launchInfo.HostString, 0)

launchTunnel(tun)
exitCh := launchTunnel(tun)

// Launch app.
clientSvc := client.NewService()
err = clientSvc.Launch(launchInfo.Os, launchInfo.ClientConfig)
if err != nil {
log.Fatalf("launching client app %v", err)
}

// Wait for exit. TODO: Clean up these channels once end to end is working
<-exitCh

return nil
}
4 changes: 4 additions & 0 deletions pkg/client/model/model.go
Expand Up @@ -8,3 +8,7 @@ type RemoteLaunchProfile struct {
Width int
Height int
}

type ClientLauncher interface {
Launch(profile RemoteLaunchProfile) error
}
11 changes: 8 additions & 3 deletions pkg/client/osx/launcher.go
Expand Up @@ -15,12 +15,17 @@ import (
type OsxClient struct {
}

// NewOsxClient returns a new OSX client
func NewOsxClient() model.ClientLauncher {
return &OsxClient{}
}

// Launch launches a client based on the specified launch profile
func (c OsxClient) Launch(profile model.RemoteLaunchProfile) error {
switch strings.ToLower(profile.Appname) {
case "rdp":
return c.launchOsx(profile, "/Applications/Microsoft Remote Desktop Beta.app", "rdp://full%20address=s:127.0.0.1:{{.Port}}&audiomode=i:0&disable%20themes=i:1&desktopwidth:i:{{.Width}}&desktopheight:i:{{.Height}}&screen%20mode%20id=i:1&username=s:{{.Username}}&prompt%20for%20credentials%20on%20client:i:0")
case "ssh":
case common.RemoteAccessRdp:
return c.launchOsx(profile, "/Applications/Microsoft Remote Desktop.app", "rdp://full%20address=s:127.0.0.1:{{.Port}}&audiomode=i:0&disable%20themes=i:1&desktopwidth:i:{{.Width}}&desktopheight:i:{{.Height}}&screen%20mode%20id=i:1&username=s:{{.Username}}&prompt%20for%20credentials%20on%20client:i:0")
case common.RemoteAccessSsh:
return c.launchOsx(profile, "ssh", "-i {{.Keyfile}} {{.Username}}@127.0.0.1:{{.Port}}")
}

Expand Down
34 changes: 34 additions & 0 deletions pkg/client/service.go
@@ -1 +1,35 @@
package client

import (
"getswizzle.io/swiz/pkg/client/model"
"getswizzle.io/swiz/pkg/client/osx"
"getswizzle.io/swiz/pkg/common"
"strings"
)

type Servicer interface {
Launch(os string, profile model.RemoteLaunchProfile) error
}

type Service struct {
clients map[string]model.ClientLauncher
}

func NewService() Servicer {
svc := &Service{
clients: map[string]model.ClientLauncher{},
}

svc.clients[common.OsOsx] = osx.NewOsxClient()

return svc
}

func (s Service) Launch(os string, profile model.RemoteLaunchProfile) error {
client := s.clients[strings.ToLower(os)]
if client == nil {
return common.NotSupportedError{Subject: os}
}

return client.Launch(profile)
}

0 comments on commit f556e0c

Please sign in to comment.