Skip to content

Commit 6182399

Browse files
committed
always verify authorized keys in parallel with other work, and at most once
1 parent 0af268d commit 6182399

File tree

1 file changed

+27
-19
lines changed

1 file changed

+27
-19
lines changed

pkg/cmd/codespace/ssh.go

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,18 @@ func (a *App) SSH(ctx context.Context, sshArgs []string, opts sshOptions) (err e
9595
return fmt.Errorf("get or choose codespace: %w", err)
9696
}
9797

98-
session, err := openSSHSession(ctx, a, codespace, liveshareLogger)
98+
// While connecting, ensure in the background that the user has keys installed.
99+
// That lets us report a more useful error message if they don't.
100+
authkeys := make(chan error, 1)
101+
go func() {
102+
authkeys <- a.ensureAuthorizedKeys(ctx)
103+
}()
104+
105+
session, err := a.openSSHSession(ctx, codespace, liveshareLogger)
99106
if err != nil {
107+
if authErr := <-authkeys; authErr != nil {
108+
return authErr
109+
}
100110
return fmt.Errorf("error connecting to codespace: %w", err)
101111
}
102112
defer safeClose(session, &err)
@@ -201,7 +211,7 @@ func (a *App) printOpenSSHConfig(ctx context.Context, opts configOptions) error
201211
}
202212
}()
203213

204-
session, err := openSSHSession(ctx, a, cs, nil)
214+
session, err := a.openSSHSession(ctx, cs, nil)
205215
if err != nil {
206216
result.err = fmt.Errorf("error connecting to codespace: %w", err)
207217
return
@@ -220,6 +230,12 @@ func (a *App) printOpenSSHConfig(ctx context.Context, opts configOptions) error
220230
}()
221231
}
222232

233+
// While the above fetches are running, ensure that the user has keys installed.
234+
// That lets us report a more useful error message if they don't.
235+
if err = a.ensureAuthorizedKeys(ctx); err != nil {
236+
return err
237+
}
238+
223239
ghexec, err := os.Executable()
224240
if err != nil {
225241
return err
@@ -284,19 +300,7 @@ type codespaceSSHConfig struct {
284300
GHExec string // path used for invoking the current `gh` binary
285301
}
286302

287-
func openSSHSession(ctx context.Context, a *App, codespace *api.Codespace, liveshareLogger *log.Logger) (*liveshare.Session, error) {
288-
// TODO(josebalius): We can fetch the user in parallel to everything else
289-
// we should convert this call and others to happen async
290-
user, err := a.apiClient.GetUser(ctx)
291-
if err != nil {
292-
return nil, fmt.Errorf("error getting user: %w", err)
293-
}
294-
295-
authkeys := make(chan error, 1)
296-
go func() {
297-
authkeys <- checkAuthorizedKeys(ctx, a.apiClient, user.Login)
298-
}()
299-
303+
func (a *App) openSSHSession(ctx context.Context, codespace *api.Codespace, liveshareLogger *log.Logger) (*liveshare.Session, error) {
300304
if liveshareLogger == nil {
301305
liveshareLogger = noopLogger()
302306
}
@@ -306,12 +310,16 @@ func openSSHSession(ctx context.Context, a *App, codespace *api.Codespace, lives
306310
return nil, fmt.Errorf("error connecting to codespace: %w", err)
307311
}
308312

309-
if err := <-authkeys; err != nil {
310-
session.Close()
311-
return nil, err
313+
return session, nil
314+
}
315+
316+
func (a *App) ensureAuthorizedKeys(ctx context.Context) error {
317+
user, err := a.apiClient.GetUser(ctx)
318+
if err != nil {
319+
return fmt.Errorf("error getting user: %w", err)
312320
}
313321

314-
return session, nil
322+
return checkAuthorizedKeys(ctx, a.apiClient, user.Login)
315323
}
316324

317325
type cpOptions struct {

0 commit comments

Comments
 (0)