Skip to content

Commit 8e743d2

Browse files
authored
fix: Use instance identity session token for git subcommands (#4884)
This broke using gitssh with instance identity!
1 parent 3f6c448 commit 8e743d2

File tree

3 files changed

+27
-22
lines changed

3 files changed

+27
-22
lines changed

agent/agent.go

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ const (
5656

5757
type Options struct {
5858
Filesystem afero.Fs
59-
ExchangeToken func(ctx context.Context) error
59+
ExchangeToken func(ctx context.Context) (string, error)
6060
Client Client
6161
ReconnectingPTYTimeout time.Duration
6262
EnvironmentVariables map[string]string
@@ -78,6 +78,11 @@ func New(options Options) io.Closer {
7878
if options.Filesystem == nil {
7979
options.Filesystem = afero.NewOsFs()
8080
}
81+
if options.ExchangeToken == nil {
82+
options.ExchangeToken = func(ctx context.Context) (string, error) {
83+
return "", nil
84+
}
85+
}
8186
ctx, cancelFunc := context.WithCancel(context.Background())
8287
server := &agent{
8388
reconnectingPTYTimeout: options.ReconnectingPTYTimeout,
@@ -97,7 +102,7 @@ func New(options Options) io.Closer {
97102
type agent struct {
98103
logger slog.Logger
99104
client Client
100-
exchangeToken func(ctx context.Context) error
105+
exchangeToken func(ctx context.Context) (string, error)
101106
filesystem afero.Fs
102107

103108
reconnectingPTYs sync.Map
@@ -110,8 +115,9 @@ type agent struct {
110115

111116
envVars map[string]string
112117
// metadata is atomic because values can change after reconnection.
113-
metadata atomic.Value
114-
sshServer *ssh.Server
118+
metadata atomic.Value
119+
sessionToken atomic.Pointer[string]
120+
sshServer *ssh.Server
115121

116122
network *tailnet.Conn
117123
stats *Stats
@@ -147,14 +153,13 @@ func (a *agent) run(ctx context.Context) error {
147153
// This allows the agent to refresh it's token if necessary.
148154
// For instance identity this is required, since the instance
149155
// may not have re-provisioned, but a new agent ID was created.
150-
if a.exchangeToken != nil {
151-
err := a.exchangeToken(ctx)
152-
if err != nil {
153-
return xerrors.Errorf("exchange token: %w", err)
154-
}
156+
sessionToken, err := a.exchangeToken(ctx)
157+
if err != nil {
158+
return xerrors.Errorf("exchange token: %w", err)
155159
}
160+
a.sessionToken.Store(&sessionToken)
156161

157-
err := a.client.PostWorkspaceAgentVersion(ctx, buildinfo.Version())
162+
err = a.client.PostWorkspaceAgentVersion(ctx, buildinfo.Version())
158163
if err != nil {
159164
return xerrors.Errorf("update workspace agent version: %w", err)
160165
}
@@ -571,6 +576,9 @@ func (a *agent) createCommand(ctx context.Context, rawCommand string, env []stri
571576
unixExecutablePath := strings.ReplaceAll(executablePath, "\\", "/")
572577
cmd.Env = append(cmd.Env, fmt.Sprintf(`GIT_SSH_COMMAND=%s gitssh --`, unixExecutablePath))
573578

579+
// Specific Coder subcommands require the agent token exposed!
580+
cmd.Env = append(cmd.Env, fmt.Sprintf("CODER_AGENT_TOKEN=%s", *a.sessionToken.Load()))
581+
574582
// Set SSH connection environment variables (these are also set by OpenSSH
575583
// and thus expected to be present by SSH clients). Since the agent does
576584
// networking in-memory, trying to provide accurate values here would be

agent/agent_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -533,9 +533,9 @@ func TestAgent(t *testing.T) {
533533
}
534534
initialized := atomic.Int32{}
535535
closer := agent.New(agent.Options{
536-
ExchangeToken: func(ctx context.Context) error {
536+
ExchangeToken: func(ctx context.Context) (string, error) {
537537
initialized.Add(1)
538-
return nil
538+
return "", nil
539539
},
540540
Client: client,
541541
Logger: slogtest.Make(t, nil).Leveled(slog.LevelInfo),
@@ -567,8 +567,8 @@ func TestAgent(t *testing.T) {
567567
}
568568
filesystem := afero.NewMemMapFs()
569569
closer := agent.New(agent.Options{
570-
ExchangeToken: func(ctx context.Context) error {
571-
return nil
570+
ExchangeToken: func(ctx context.Context) (string, error) {
571+
return "", nil
572572
},
573573
Client: client,
574574
Logger: slogtest.Make(t, nil).Leveled(slog.LevelInfo),

cli/agent.go

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -156,22 +156,19 @@ func workspaceAgent() *cobra.Command {
156156
closer := agent.New(agent.Options{
157157
Client: client,
158158
Logger: logger,
159-
ExchangeToken: func(ctx context.Context) error {
159+
ExchangeToken: func(ctx context.Context) (string, error) {
160160
if exchangeToken == nil {
161-
return nil
161+
return client.SessionToken, nil
162162
}
163163
resp, err := exchangeToken(ctx)
164164
if err != nil {
165-
return err
165+
return "", err
166166
}
167167
client.SessionToken = resp.SessionToken
168-
return nil
168+
return "", nil
169169
},
170170
EnvironmentVariables: map[string]string{
171-
// Override the "CODER_AGENT_TOKEN" variable in all
172-
// shells so "gitssh" and "gitaskpass" works!
173-
"CODER_AGENT_TOKEN": client.SessionToken,
174-
"GIT_ASKPASS": executablePath,
171+
"GIT_ASKPASS": executablePath,
175172
},
176173
})
177174
<-cmd.Context().Done()

0 commit comments

Comments
 (0)