github.com/mook-as/cf-cli@v7.0.0-beta.28.0.20200120190804-b91c115fae48+incompatible/command/v7/ssh_command.go (about) 1 package v7 2 3 import ( 4 "code.cloudfoundry.org/cli/actor/sharedaction" 5 "code.cloudfoundry.org/cli/actor/v7action" 6 "code.cloudfoundry.org/cli/command" 7 "code.cloudfoundry.org/cli/command/flag" 8 "code.cloudfoundry.org/cli/command/translatableerror" 9 "code.cloudfoundry.org/cli/command/v7/shared" 10 "code.cloudfoundry.org/cli/util/clissh" 11 "code.cloudfoundry.org/clock" 12 ) 13 14 //go:generate counterfeiter . SharedSSHActor 15 16 type SharedSSHActor interface { 17 ExecuteSecureShell(sshClient sharedaction.SecureShellClient, sshOptions sharedaction.SSHOptions) error 18 } 19 20 //go:generate counterfeiter . SSHActor 21 22 type SSHActor interface { 23 GetSecureShellConfigurationByApplicationNameSpaceProcessTypeAndIndex(appName string, spaceGUID string, processType string, processIndex uint) (v7action.SSHAuthentication, v7action.Warnings, error) 24 } 25 26 type SSHCommand struct { 27 RequiredArgs flag.AppName `positional-args:"yes"` 28 ProcessIndex uint `long:"app-instance-index" short:"i" default:"0" description:"App process instance index"` 29 Commands []string `long:"command" short:"c" description:"Command to run"` 30 DisablePseudoTTY bool `long:"disable-pseudo-tty" short:"T" description:"Disable pseudo-tty allocation"` 31 ForcePseudoTTY bool `long:"force-pseudo-tty" description:"Force pseudo-tty allocation"` 32 LocalPortForwardSpecs []flag.SSHPortForwarding `short:"L" description:"Local port forward specification"` 33 ProcessType string `long:"process" default:"web" description:"App process name"` 34 RequestPseudoTTY bool `long:"request-pseudo-tty" short:"t" description:"Request pseudo-tty allocation"` 35 SkipHostValidation bool `long:"skip-host-validation" short:"k" description:"Skip host key validation. Not recommended!"` 36 SkipRemoteExecution bool `long:"skip-remote-execution" short:"N" description:"Do not execute a remote command"` 37 38 usage interface{} `usage:"CF_NAME ssh APP_NAME [--process PROCESS] [-i INDEX] [-c COMMAND]...\n [-L [BIND_ADDRESS:]LOCAL_PORT:REMOTE_HOST:REMOTE_PORT]... [--skip-remote-execution]\n [--disable-pseudo-tty | --force-pseudo-tty | --request-pseudo-tty] [--skip-host-validation]"` 39 relatedCommands interface{} `related_commands:"allow-space-ssh, enable-ssh, space-ssh-allowed, ssh-code, ssh-enabled"` 40 allproxy interface{} `environmentName:"all_proxy" environmentDescription:"Specify a proxy server to enable proxying for all requests"` 41 42 UI command.UI 43 Config command.Config 44 SharedActor command.SharedActor 45 Actor SSHActor 46 SSHActor SharedSSHActor 47 SSHClient *clissh.SecureShell 48 } 49 50 func (cmd *SSHCommand) Setup(config command.Config, ui command.UI) error { 51 cmd.UI = ui 52 cmd.Config = config 53 sharedActor := sharedaction.NewActor(config) 54 cmd.SharedActor = sharedActor 55 cmd.SSHActor = sharedActor 56 57 ccClient, uaaClient, err := shared.GetNewClientsAndConnectToCF(config, ui, "") 58 if err != nil { 59 return err 60 } 61 62 cmd.Actor = v7action.NewActor(ccClient, config, sharedActor, uaaClient, clock.NewClock()) 63 64 cmd.SSHClient = clissh.NewDefaultSecureShell() 65 66 return nil 67 } 68 69 func (cmd SSHCommand) Execute(args []string) error { 70 71 err := cmd.SharedActor.CheckTarget(true, true) 72 if err != nil { 73 return err 74 } 75 76 ttyOption, err := cmd.EvaluateTTYOption() 77 if err != nil { 78 return err 79 } 80 81 var forwardSpecs []sharedaction.LocalPortForward 82 for _, spec := range cmd.LocalPortForwardSpecs { 83 forwardSpecs = append(forwardSpecs, sharedaction.LocalPortForward(spec)) 84 } 85 86 sshAuth, warnings, err := cmd.Actor.GetSecureShellConfigurationByApplicationNameSpaceProcessTypeAndIndex( 87 cmd.RequiredArgs.AppName, 88 cmd.Config.TargetedSpace().GUID, 89 cmd.ProcessType, 90 cmd.ProcessIndex, 91 ) 92 cmd.UI.DisplayWarnings(warnings) 93 if err != nil { 94 return err 95 } 96 97 err = cmd.SSHActor.ExecuteSecureShell( 98 cmd.SSHClient, 99 sharedaction.SSHOptions{ 100 Commands: cmd.Commands, 101 Endpoint: sshAuth.Endpoint, 102 HostKeyFingerprint: sshAuth.HostKeyFingerprint, 103 LocalPortForwardSpecs: forwardSpecs, 104 Passcode: sshAuth.Passcode, 105 SkipHostValidation: cmd.SkipHostValidation, 106 SkipRemoteExecution: cmd.SkipRemoteExecution, 107 TTYOption: ttyOption, 108 Username: sshAuth.Username, 109 }) 110 if err != nil { 111 return err 112 } 113 114 return nil 115 } 116 117 // EvaluateTTYOption determines which TTY options are mutually exclusive and 118 // returns an error accordingly. 119 func (cmd SSHCommand) EvaluateTTYOption() (sharedaction.TTYOption, error) { 120 var count int 121 122 option := sharedaction.RequestTTYAuto 123 if cmd.DisablePseudoTTY { 124 option = sharedaction.RequestTTYNo 125 count++ 126 } 127 if cmd.ForcePseudoTTY { 128 option = sharedaction.RequestTTYForce 129 count++ 130 } 131 if cmd.RequestPseudoTTY { 132 option = sharedaction.RequestTTYYes 133 count++ 134 } 135 136 if count > 1 { 137 return option, translatableerror.ArgumentCombinationError{Args: []string{ 138 "--disable-pseudo-tty", "-T", "--force-pseudo-tty", "--request-pseudo-tty", "-t", 139 }} 140 } 141 142 return option, nil 143 }