@@ -13,6 +13,7 @@ import (
13
13
"net/http"
14
14
"net/url"
15
15
"os"
16
+ "os/exec"
16
17
"os/signal"
17
18
"path/filepath"
18
19
"runtime"
@@ -55,6 +56,7 @@ const (
55
56
varAgentToken = "agent-token"
56
57
varAgentURL = "agent-url"
57
58
varHeader = "header"
59
+ varHeaderProcess = "header-process"
58
60
varNoOpen = "no-open"
59
61
varNoVersionCheck = "no-version-warning"
60
62
varNoFeatureWarning = "no-feature-warning"
@@ -356,6 +358,13 @@ func (r *RootCmd) Command(subcommands []*clibase.Cmd) (*clibase.Cmd, error) {
356
358
Value : clibase .StringArrayOf (& r .header ),
357
359
Group : globalGroup ,
358
360
},
361
+ {
362
+ Flag : varHeaderProcess ,
363
+ Env : "CODER_HEADER_PROCESS" ,
364
+ Description : "An external process that outputs JSON-encoded key-value pairs to be used as additional HTTP headers added to all requests." ,
365
+ Value : clibase .StringOf (& r .headerProcess ),
366
+ Group : globalGroup ,
367
+ },
359
368
{
360
369
Flag : varNoOpen ,
361
370
Env : "CODER_NO_OPEN" ,
@@ -437,6 +446,7 @@ type RootCmd struct {
437
446
token string
438
447
globalConfig string
439
448
header []string
449
+ headerProcess string
440
450
agentToken string
441
451
agentURL * url.URL
442
452
forceTTY bool
@@ -540,9 +550,7 @@ func (r *RootCmd) initClientInternal(client *codersdk.Client, allowTokenMissing
540
550
return err
541
551
}
542
552
}
543
- err = r .setClient (
544
- client , r .clientURL ,
545
- )
553
+ err = r .setClient (inv .Context (), client , r .clientURL )
546
554
if err != nil {
547
555
return err
548
556
}
@@ -592,7 +600,7 @@ func (r *RootCmd) initClientInternal(client *codersdk.Client, allowTokenMissing
592
600
}
593
601
}
594
602
595
- func (r * RootCmd ) setClient (client * codersdk.Client , serverURL * url.URL ) error {
603
+ func (r * RootCmd ) setClient (ctx context. Context , client * codersdk.Client , serverURL * url.URL ) error {
596
604
transport := & headerTransport {
597
605
transport : http .DefaultTransport ,
598
606
header : http.Header {},
@@ -604,16 +612,39 @@ func (r *RootCmd) setClient(client *codersdk.Client, serverURL *url.URL) error {
604
612
}
605
613
transport .header .Add (parts [0 ], parts [1 ])
606
614
}
615
+ if r .headerProcess != "" {
616
+ shell := "sh"
617
+ caller := "-c"
618
+ if runtime .GOOS == "windows" {
619
+ shell = "cmd.exe"
620
+ caller = "/c"
621
+ }
622
+ // #nosec
623
+ cmd := exec .CommandContext (ctx , shell , caller , r .headerProcess )
624
+ cmd .Env = append (os .Environ (), "CODER_URL=" + serverURL .String ())
625
+ out , err := cmd .Output ()
626
+ if err != nil {
627
+ return xerrors .Errorf ("failed to run %v (out: %q): %w" , cmd .Args , out , err )
628
+ }
629
+ var headers map [string ]string
630
+ err = json .Unmarshal (out , & headers )
631
+ if err != nil {
632
+ return xerrors .Errorf ("failed to parse json from %v (out: %q): %w" , cmd .Args , out , err )
633
+ }
634
+ for key , value := range headers {
635
+ transport .header .Add (key , value )
636
+ }
637
+ }
607
638
client .URL = serverURL
608
639
client .HTTPClient = & http.Client {
609
640
Transport : transport ,
610
641
}
611
642
return nil
612
643
}
613
644
614
- func (r * RootCmd ) createUnauthenticatedClient (serverURL * url.URL ) (* codersdk.Client , error ) {
645
+ func (r * RootCmd ) createUnauthenticatedClient (ctx context. Context , serverURL * url.URL ) (* codersdk.Client , error ) {
615
646
var client codersdk.Client
616
- err := r .setClient (& client , serverURL )
647
+ err := r .setClient (ctx , & client , serverURL )
617
648
return & client , err
618
649
}
619
650
0 commit comments