Skip to content

Commit ad47ef1

Browse files
authored
feat: allow reading the agent token from a file (coder#10080)
Adds `CODER_AGENT_TOKEN_FILE` which will read the agent token from a file if `CODER_AGENT_TOKEN` is not provided. Using a Kubernetes Secret with a volume-mounted file is a more secure way to provide the agent token instead of an environment variable.
1 parent eb4826a commit ad47ef1

File tree

2 files changed

+39
-17
lines changed

2 files changed

+39
-17
lines changed

cli/agent.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -199,9 +199,19 @@ func (r *RootCmd) workspaceAgent() *clibase.Cmd {
199199
var exchangeToken func(context.Context) (agentsdk.AuthenticateResponse, error)
200200
switch auth {
201201
case "token":
202-
token, err := inv.ParsedFlags().GetString(varAgentToken)
203-
if err != nil {
204-
return xerrors.Errorf("CODER_AGENT_TOKEN must be set for token auth: %w", err)
202+
token, _ := inv.ParsedFlags().GetString(varAgentToken)
203+
if token == "" {
204+
tokenFile, _ := inv.ParsedFlags().GetString(varAgentTokenFile)
205+
if tokenFile != "" {
206+
tokenBytes, err := os.ReadFile(tokenFile)
207+
if err != nil {
208+
return xerrors.Errorf("read token file %q: %w", tokenFile, err)
209+
}
210+
token = strings.TrimSpace(string(tokenBytes))
211+
}
212+
}
213+
if token == "" {
214+
return xerrors.Errorf("CODER_AGENT_TOKEN or CODER_AGENT_TOKEN_FILE must be set for token auth")
205215
}
206216
client.SetSessionToken(token)
207217
case "google-instance-identity":

cli/root.go

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ const (
5555
varURL = "url"
5656
varToken = "token"
5757
varAgentToken = "agent-token"
58+
varAgentTokenFile = "agent-token-file"
5859
varAgentURL = "agent-url"
5960
varHeader = "header"
6061
varHeaderCommand = "header-command"
@@ -71,7 +72,9 @@ const (
7172
envSessionToken = "CODER_SESSION_TOKEN"
7273
//nolint:gosec
7374
envAgentToken = "CODER_AGENT_TOKEN"
74-
envURL = "CODER_URL"
75+
//nolint:gosec
76+
envAgentTokenFile = "CODER_AGENT_TOKEN_FILE"
77+
envURL = "CODER_URL"
7578
)
7679

7780
var errUnauthenticated = xerrors.New(notLoggedInMessage)
@@ -328,6 +331,14 @@ func (r *RootCmd) Command(subcommands []*clibase.Cmd) (*clibase.Cmd, error) {
328331
Hidden: true,
329332
Group: globalGroup,
330333
},
334+
{
335+
Flag: varAgentTokenFile,
336+
Env: envAgentTokenFile,
337+
Description: "A file containing an agent authentication token.",
338+
Value: clibase.StringOf(&r.agentTokenFile),
339+
Hidden: true,
340+
Group: globalGroup,
341+
},
331342
{
332343
Flag: varAgentURL,
333344
Env: "CODER_AGENT_URL",
@@ -446,19 +457,20 @@ func LoggerFromContext(ctx context.Context) (slog.Logger, bool) {
446457

447458
// RootCmd contains parameters and helpers useful to all commands.
448459
type RootCmd struct {
449-
clientURL *url.URL
450-
token string
451-
globalConfig string
452-
header []string
453-
headerCommand string
454-
agentToken string
455-
agentURL *url.URL
456-
forceTTY bool
457-
noOpen bool
458-
verbose bool
459-
versionFlag bool
460-
disableDirect bool
461-
debugHTTP bool
460+
clientURL *url.URL
461+
token string
462+
globalConfig string
463+
header []string
464+
headerCommand string
465+
agentToken string
466+
agentTokenFile string
467+
agentURL *url.URL
468+
forceTTY bool
469+
noOpen bool
470+
verbose bool
471+
versionFlag bool
472+
disableDirect bool
473+
debugHTTP bool
462474

463475
noVersionCheck bool
464476
noFeatureWarning bool

0 commit comments

Comments
 (0)