Skip to content

Commit 9e6ba15

Browse files
committed
implement lw ssh
1 parent 7649607 commit 9e6ba15

File tree

3 files changed

+195
-1
lines changed

3 files changed

+195
-1
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ install: security
44
scripts/build/install
55

66
security:
7-
@gosec ./...
7+
@gosec --exclude=G204 ./...
88

99
clean:
1010
rm -rf _exe/

cmd/ssh.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
Copyright © LiquidWeb
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
package cmd
17+
18+
import (
19+
"github.com/spf13/cobra"
20+
21+
"github.com/liquidweb/liquidweb-cli/instance"
22+
)
23+
24+
var sshCmd = &cobra.Command{
25+
Use: "ssh",
26+
Short: "SSH to a Server",
27+
Long: `SSH to a Server.
28+
29+
Gives you an interactive shell to your Server.`,
30+
Run: func(cmd *cobra.Command, args []string) {
31+
params := &instance.SshParams{}
32+
33+
params.Host, _ = cmd.Flags().GetString("host")
34+
params.PrivateKey, _ = cmd.Flags().GetString("private-ssh-key")
35+
params.User, _ = cmd.Flags().GetString("user")
36+
params.AgentForwarding, _ = cmd.Flags().GetBool("agent-forwarding")
37+
params.Port, _ = cmd.Flags().GetInt("port")
38+
params.Command, _ = cmd.Flags().GetString("command")
39+
40+
if err := lwCliInst.Ssh(params); err != nil {
41+
lwCliInst.Die(err)
42+
}
43+
},
44+
}
45+
46+
func init() {
47+
rootCmd.AddCommand(sshCmd)
48+
49+
sshCmd.Flags().String("host", "", "uniq-id or hostname for the Server")
50+
sshCmd.Flags().Int("port", 22, "ssh port to use")
51+
sshCmd.Flags().String("private-ssh-key", "", "path to a specific/non default ssh private key to use")
52+
sshCmd.Flags().Bool("agent-forwarding", false, "whether or not to enable ssh agent forwarding")
53+
sshCmd.Flags().String("user", "root", "username to use for the ssh connection")
54+
sshCmd.Flags().String("command", "", "run this command and exit rather than start an interactive shell")
55+
56+
if err := sshCmd.MarkFlagRequired("host"); err != nil {
57+
lwCliInst.Die(err)
58+
}
59+
}

instance/ssh.go

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
/*
2+
Copyright © LiquidWeb
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
package instance
17+
18+
import (
19+
"fmt"
20+
"os"
21+
"os/exec"
22+
23+
"github.com/liquidweb/liquidweb-cli/types/api"
24+
"github.com/liquidweb/liquidweb-cli/validate"
25+
)
26+
27+
type SshParams struct {
28+
Host string `yaml:"host"`
29+
Port int `yaml:"port"`
30+
PrivateKey string `yaml:"private-key"`
31+
User string `yaml:"user"`
32+
AgentForwarding bool `yaml:"agent-forwarding"`
33+
Command string `yaml:"command"`
34+
}
35+
36+
func (self *SshParams) UnmarshalYAML(unmarshal func(interface{}) error) error {
37+
type rawType SshParams
38+
raw := rawType{
39+
Port: 22,
40+
User: "root",
41+
}
42+
if err := unmarshal(&raw); err != nil {
43+
return err
44+
}
45+
*self = SshParams(raw)
46+
47+
return nil
48+
}
49+
50+
func (self *SshParams) TranslateHost(ci *Client) (ip string, err error) {
51+
validateFields := map[interface{}]interface{}{
52+
self.Host: "UniqId",
53+
}
54+
55+
if err = validate.Validate(validateFields); err == nil {
56+
var subaccnt apiTypes.Subaccnt
57+
apiArgs := map[string]interface{}{
58+
"uniq_id": self.Host,
59+
}
60+
if aErr := ci.CallLwApiInto("bleed/asset/details", apiArgs, &subaccnt); aErr != nil {
61+
err = aErr
62+
return
63+
}
64+
65+
ip = subaccnt.Ip
66+
} else {
67+
methodArgs := AllPaginatedResultsArgs{
68+
Method: "bleed/asset/list",
69+
ResultsPerPage: 100,
70+
}
71+
results, aErr := ci.AllPaginatedResults(&methodArgs)
72+
if aErr != nil {
73+
err = aErr
74+
return
75+
}
76+
for _, item := range results.Items {
77+
var subaccnt apiTypes.Subaccnt
78+
if err = CastFieldTypes(item, &subaccnt); err != nil {
79+
return
80+
}
81+
82+
if subaccnt.Domain == self.Host {
83+
ip = subaccnt.Ip
84+
break
85+
}
86+
}
87+
}
88+
89+
if ip == "" {
90+
err = fmt.Errorf("unable to determine ip for Host [%s]", self.Host)
91+
return
92+
}
93+
94+
return
95+
}
96+
97+
func (self *Client) Ssh(params *SshParams) (err error) {
98+
validateFields := map[interface{}]interface{}{
99+
params.Port: "PositiveInt",
100+
}
101+
if err = validate.Validate(validateFields); err != nil {
102+
return
103+
}
104+
105+
ip, err := params.TranslateHost(self)
106+
if err != nil {
107+
return
108+
}
109+
110+
sshArgs := []string{}
111+
if params.PrivateKey != "" {
112+
sshArgs = append(sshArgs, "-i", params.PrivateKey)
113+
}
114+
115+
if params.AgentForwarding {
116+
sshArgs = append(sshArgs, "-A")
117+
}
118+
119+
sshArgs = append(sshArgs, fmt.Sprintf("%s@%s", params.User, ip))
120+
sshArgs = append(sshArgs, fmt.Sprintf("-p %d", params.Port))
121+
122+
if params.Command != "" {
123+
sshArgs = append(sshArgs, params.Command)
124+
}
125+
126+
cmd := exec.Command("ssh", sshArgs...)
127+
128+
cmd.Stderr = os.Stderr
129+
cmd.Stdout = os.Stdout
130+
cmd.Stdin = os.Stdin
131+
132+
err = cmd.Run()
133+
134+
return
135+
}

0 commit comments

Comments
 (0)