1
1
package main
2
2
3
3
import (
4
+ "bufio"
4
5
"context"
5
6
"fmt"
6
7
"net"
@@ -103,9 +104,20 @@ func findSetting(key string, settings []debug.BuildSetting) string {
103
104
}
104
105
105
106
// setupSSHTunnel creates an SSH tunnel by running the ssh command
106
- func setupSSHTunnel (ctx context.Context , conf sshConfig , out chan <- error ) error {
107
+ func setupSSHTunnel (ctx context.Context , conf sshConfig , out chan error ) error {
108
+ if conf .KeyFile == "" {
109
+ return fmt .Errorf ("ssh: key file is required" )
110
+ }
111
+
107
112
args := []string {
108
- "-N" ,
113
+ "-v" , "-N" ,
114
+ "-F" , "none" , // don't read the default config file
115
+ "-o" , "PasswordAuthentication=no" , // disable password authentication
116
+ "-o" , "PreferredAuthentications=publickey" , // only use public key authentication
117
+ "-o" , "IdentitiesOnly=yes" , // only use explicitly provided keys
118
+ // "-o", "UseKeychain=no", // disable macOS keychain
119
+ // "-o", "IdentityAgent=none", // disable SSH agent
120
+ "-i" , conf .KeyFile , // specify the key file to use
109
121
"-L" , fmt .Sprintf ("%d:localhost:%d" , conf .LocalPort , conf .RemotePort ),
110
122
conf .Host ,
111
123
}
@@ -129,6 +141,17 @@ func setupSSHTunnel(ctx context.Context, conf sshConfig, out chan<- error) error
129
141
// -L: Local port forwarding
130
142
cmd := exec .CommandContext (ctx , "ssh" , args ... )
131
143
144
+ // Capture stdout and stderr
145
+ stdout , err := cmd .StdoutPipe ()
146
+ if err != nil {
147
+ return fmt .Errorf ("create stdout pipe: %w" , err )
148
+ }
149
+
150
+ stderr , err := cmd .StderrPipe ()
151
+ if err != nil {
152
+ return fmt .Errorf ("create stderr pipe: %w" , err )
153
+ }
154
+
132
155
// Start the SSH tunnel
133
156
if err := cmd .Start (); err != nil {
134
157
return fmt .Errorf ("starting SSH tunnel: %w" , err )
@@ -144,6 +167,24 @@ func setupSSHTunnel(ctx context.Context, conf sshConfig, out chan<- error) error
144
167
}
145
168
}()
146
169
170
+ // Log stdout in background
171
+ go func () {
172
+ scanner := bufio .NewScanner (stdout )
173
+ for scanner .Scan () {
174
+ zerolog .Ctx (ctx ).Debug ().
175
+ Msgf ("SSH tunnel stdout: %s" , scanner .Text ())
176
+ }
177
+ }()
178
+
179
+ // Log stderr in background
180
+ go func () {
181
+ scanner := bufio .NewScanner (stderr )
182
+ for scanner .Scan () {
183
+ zerolog .Ctx (ctx ).Debug ().
184
+ Msgf ("SSH tunnel stderr: %s" , scanner .Text ())
185
+ }
186
+ }()
187
+
147
188
// Wait for the tunnel to be established
148
189
for i := 0 ; i < 10 ; i ++ {
149
190
if conn , err := net .Dial ("tcp" , fmt .Sprintf ("localhost:%d" , conf .LocalPort )); err == nil {
@@ -153,6 +194,9 @@ func setupSSHTunnel(ctx context.Context, conf sshConfig, out chan<- error) error
153
194
select {
154
195
case <- ctx .Done ():
155
196
return fmt .Errorf ("wait for SSH tunnel: %w" , ctx .Err ())
197
+ case err := <- out :
198
+ return fmt .Errorf ("setup SSH tunnel: %w" , err )
199
+
156
200
case <- time .After (time .Second ):
157
201
}
158
202
}
0 commit comments