-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathSshEngine.go
More file actions
169 lines (137 loc) · 3.71 KB
/
SshEngine.go
File metadata and controls
169 lines (137 loc) · 3.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
package main
import (
"bufio"
"errors"
"fmt"
"io/ioutil"
"log"
"os"
"github.com/spf13/viper"
"golang.org/x/crypto/ssh"
)
func main() {
// log.Println("Running on " + runtime.GOOS)
// Read configuration
configuration := readConfiguration()
debugLogging := false
// Setup logging if a log file name was passed in
if configuration.LogFileName != "" {
file, err := os.OpenFile("engine.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0666)
if err != nil {
log.Fatal(err)
}
defer file.Close()
log.SetOutput(file)
debugLogging = true
}
server := fmt.Sprintf("%s:%s", configuration.Host, configuration.Port)
// Setup the client configuration
sshConfig := getSshConfig(configuration)
// Start the connection
client, err := ssh.Dial("tcp", server, sshConfig)
if err != nil {
fmt.Printf("Could not connect to ssh (failed to dial). Error is: %s\n", err)
os.Exit(1)
}
// Start a session
session, err := client.NewSession()
if err != nil {
fmt.Printf("Failed to create ssh session. Error is: %s\n", err)
os.Exit(1)
}
defer session.Close()
session.Stdout = os.Stdout
session.Stderr = os.Stderr
// StdinPipe for commands
stdin, _ := session.StdinPipe()
// Start remote shell
if err := session.Shell(); err != nil {
fmt.Printf("Failed to start shell. Error is: %s\n", err)
os.Exit(1)
}
// Run the supplied command first
fmt.Fprintf(stdin, "%s\n", configuration.RemoteCommand)
// Accepting commands
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
if debugLogging {
log.Println("Input: " + scanner.Text())
}
fmt.Fprintf(stdin, "%s\n", scanner.Text())
if scanner.Text() == "quit" {
if debugLogging {
log.Println("Quit sent")
}
break
}
}
}
func getSshConfig(configuration Configurations) *ssh.ClientConfig {
key, err := getKeyFile(configuration.PrivateKeyFile)
if err != nil {
fmt.Printf("Could not read privateKeyFile at %s\n", configuration.PrivateKeyFile)
os.Exit(1)
}
sshConfig := &ssh.ClientConfig{
User: configuration.User,
Auth: []ssh.AuthMethod{
ssh.PublicKeys(key),
},
}
sshConfig.HostKeyCallback = ssh.InsecureIgnoreHostKey()
return sshConfig
}
func getKeyFile(file string) (key ssh.Signer, err error) {
buf, err := ioutil.ReadFile(file)
if err != nil {
fmt.Printf("Error reading the key file. Error is: %s\n", err)
return
}
key, err = ssh.ParsePrivateKey(buf)
if err != nil {
fmt.Printf("Error parsing the private key file. Is this a valid private key? Error is: %s\n", err)
return
}
return
}
func readConfiguration() Configurations {
if _, err := os.Stat("engine.yml"); errors.Is(err, os.ErrNotExist) {
// path/to/whatever does not exist
fmt.Println("The file 'engine.yml' could not be found in the current directory")
os.Exit(1)
}
// Set the file name of the configurations file
viper.SetConfigName("engine")
viper.SetConfigType("yml")
// Set the path to look for the configurations file
viper.AddConfigPath(".")
// Read the Configuration
var configuration Configurations
if err := viper.ReadInConfig(); err != nil {
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
// Config file not found; ignore error if desired
fmt.Println("No such config file")
os.Exit(1)
} else {
// Config file was found but another error was produced
fmt.Printf("Error reading the engine.yml file, %s", err)
os.Exit(1)
}
}
// Set undefined variables
viper.SetDefault("logFileName", "")
err := viper.Unmarshal(&configuration)
if err != nil {
fmt.Printf("Unable to decode the engine.yml file, %v", err)
os.Exit(1)
}
return configuration
}
type Configurations struct {
User string
PrivateKeyFile string
Host string
Port string
RemoteCommand string
LogFileName string
}