Skip to content

Commit bbcc4a9

Browse files
committed
feat: allow DERP headers to be set
1 parent 7fa6483 commit bbcc4a9

File tree

6 files changed

+75
-20
lines changed

6 files changed

+75
-20
lines changed

cli/root.go

+61-15
Original file line numberDiff line numberDiff line change
@@ -46,17 +46,19 @@ var (
4646
)
4747

4848
const (
49-
varURL = "url"
50-
varToken = "token"
51-
varAgentToken = "agent-token"
52-
varAgentURL = "agent-url"
53-
varHeader = "header"
54-
varNoOpen = "no-open"
55-
varNoVersionCheck = "no-version-warning"
56-
varNoFeatureWarning = "no-feature-warning"
57-
varForceTty = "force-tty"
58-
varVerbose = "verbose"
59-
notLoggedInMessage = "You are not logged in. Try logging in using 'coder login <url>'."
49+
varURL = "url"
50+
varToken = "token"
51+
varAgentToken = "agent-token"
52+
varAgentURL = "agent-url"
53+
varHeader = "header"
54+
varDerpHeader = "derp-header"
55+
varDerpHeaderUseDefault = "derp-header-use-default"
56+
varNoOpen = "no-open"
57+
varNoVersionCheck = "no-version-warning"
58+
varNoFeatureWarning = "no-feature-warning"
59+
varForceTty = "force-tty"
60+
varVerbose = "verbose"
61+
notLoggedInMessage = "You are not logged in. Try logging in using 'coder login <url>'."
6062

6163
envNoVersionCheck = "CODER_NO_VERSION_WARNING"
6264
envNoFeatureWarning = "CODER_NO_FEATURE_WARNING"
@@ -170,6 +172,8 @@ func Root(subcommands []*cobra.Command) *cobra.Command {
170172
_ = cmd.PersistentFlags().MarkHidden(varAgentURL)
171173
cliflag.String(cmd.PersistentFlags(), config.FlagName, "", "CODER_CONFIG_DIR", config.DefaultDir(), "Path to the global `coder` config directory.")
172174
cliflag.StringArray(cmd.PersistentFlags(), varHeader, "", "CODER_HEADER", []string{}, "HTTP headers added to all requests. Provide as \"Key=Value\"")
175+
cliflag.StringArray(cmd.PersistentFlags(), varDerpHeader, "", "CODER_DERP_HEADER", []string{}, "HTTP headers added to all DERP requests. Provide as \"Key=Value\"")
176+
cliflag.Bool(cmd.PersistentFlags(), varDerpHeaderUseDefault, "", "CODER_DERP_HEADER_USE_DEFAULT", false, "Use default HTTP headers for all DERP requests.")
173177
cmd.PersistentFlags().Bool(varForceTty, false, "Force the `coder` command to run as if connected to a TTY.")
174178
_ = cmd.PersistentFlags().MarkHidden(varForceTty)
175179
cmd.PersistentFlags().Bool(varNoOpen, false, "Block automatically opening URLs in the browser.")
@@ -332,19 +336,61 @@ func createUnauthenticatedClient(cmd *cobra.Command, serverURL *url.URL) (*coder
332336
if err != nil {
333337
return nil, err
334338
}
339+
340+
headerMap, err := parseHeaderString(headers)
341+
if err != nil {
342+
return nil, err
343+
}
344+
335345
transport := &headerTransport{
336346
transport: http.DefaultTransport,
337-
headers: map[string]string{},
347+
headers: headerMap,
338348
}
349+
350+
client.HTTPClient.Transport = transport
351+
352+
derpHeaders, err := cmd.Flags().GetStringArray(varDerpHeader)
353+
if err != nil {
354+
return nil, err
355+
}
356+
357+
derpHeaderMap, err := parseHeaderString(derpHeaders)
358+
if err != nil {
359+
return nil, err
360+
}
361+
362+
client.DERPHeader = &http.Header{}
363+
364+
derpHeadersUseDefault, err := cmd.Flags().GetBool(varDerpHeaderUseDefault)
365+
if err != nil {
366+
return nil, err
367+
}
368+
369+
if derpHeadersUseDefault {
370+
for header, value := range headerMap {
371+
client.DERPHeader.Set(header, value)
372+
}
373+
}
374+
375+
for header, value := range derpHeaderMap {
376+
client.DERPHeader.Set(header, value)
377+
}
378+
379+
return client, nil
380+
}
381+
382+
func parseHeaderString(headers []string) (map[string]string, error) {
383+
headerMap := map[string]string{}
384+
339385
for _, header := range headers {
340386
parts := strings.SplitN(header, "=", 2)
341387
if len(parts) < 2 {
342388
return nil, xerrors.Errorf("split header %q had less than two parts", header)
343389
}
344-
transport.headers[parts[0]] = parts[1]
390+
headerMap[parts[0]] = parts[1]
345391
}
346-
client.HTTPClient.Transport = transport
347-
return client, nil
392+
393+
return headerMap, nil
348394
}
349395

350396
// createAgentClient returns a new client from the command context.

codersdk/client.go

+2
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ type Client struct {
7979
HTTPClient *http.Client
8080
URL *url.URL
8181

82+
DERPHeader *http.Header
83+
8284
// Logger is optionally provided to log requests.
8385
// Method, URL, and response code will be logged by default.
8486
Logger slog.Logger

codersdk/workspaceagents.go

+1
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ func (c *Client) DialWorkspaceAgent(ctx context.Context, agentID uuid.UUID, opti
146146
conn, err := tailnet.NewConn(&tailnet.Options{
147147
Addresses: []netip.Prefix{netip.PrefixFrom(ip, 128)},
148148
DERPMap: connInfo.DERPMap,
149+
DERPHeader: c.DERPHeader,
149150
Logger: options.Logger,
150151
BlockEndpoints: options.BlockEndpoints,
151152
})

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ replace github.com/tcnksm/go-httpstat => github.com/kylecarbs/go-httpstat v0.0.0
4040

4141
// There are a few minor changes we make to Tailscale that we're slowly upstreaming. Compare here:
4242
// https://github.com/tailscale/tailscale/compare/main...coder:tailscale:main
43-
replace tailscale.com => github.com/coder/tailscale v1.1.1-0.20230307022319-1e5e724a3949
43+
replace tailscale.com => github.com/JoshVee/tailscale v0.0.0-20230312075737-979756badabf
4444

4545
// Switch to our fork that imports fixes from http://github.com/tailscale/ssh.
4646
// See: https://github.com/coder/coder/issues/3371

go.sum

+2-2
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym
114114
github.com/ClickHouse/clickhouse-go v1.4.3/go.mod h1:EaI/sW7Azgz9UATzd5ZdZHRUhHgv5+JMS9NSr2smCJI=
115115
github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60=
116116
github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs=
117+
github.com/JoshVee/tailscale v0.0.0-20230312075737-979756badabf h1:4r5bosAHmI1IlivX9aHZmWlrgz206xmm+iE3zBmA6l4=
118+
github.com/JoshVee/tailscale v0.0.0-20230312075737-979756badabf/go.mod h1:jpg+77g19FpXL43U1VoIqoSg1K/Vh5CVxycGldQ8KhA=
117119
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
118120
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
119121
github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
@@ -376,8 +378,6 @@ github.com/coder/retry v1.3.1-0.20230210155434-e90a2e1e091d h1:09JG37IgTB6n3ouX9
376378
github.com/coder/retry v1.3.1-0.20230210155434-e90a2e1e091d/go.mod h1:r+1J5i/989wt6CUeNSuvFKKA9hHuKKPMxdzDbTuvwwk=
377379
github.com/coder/ssh v0.0.0-20220811105153-fcea99919338 h1:tN5GKFT68YLVzJoA8AHuiMNJ0qlhoD3pGN3JY9gxSko=
378380
github.com/coder/ssh v0.0.0-20220811105153-fcea99919338/go.mod h1:ZSS+CUoKHDrqVakTfTWUlKSr9MtMFkC4UvtQKD7O914=
379-
github.com/coder/tailscale v1.1.1-0.20230307022319-1e5e724a3949 h1:8WfMfRTDaEpnmhCJWfFQ7JHz19GyP+EgFgLGu5ngdek=
380-
github.com/coder/tailscale v1.1.1-0.20230307022319-1e5e724a3949/go.mod h1:jpg+77g19FpXL43U1VoIqoSg1K/Vh5CVxycGldQ8KhA=
381381
github.com/coder/terraform-provider-coder v0.6.15 h1:Llvh4RwxSQ/goy7ToTOeHf3tdEz+79qbyOh61hNnJs0=
382382
github.com/coder/terraform-provider-coder v0.6.15/go.mod h1:UIfU3bYNeSzJJvHyJ30tEKjD6Z9utloI+HUM/7n94CY=
383383
github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE=

tailnet/conn.go

+8-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"fmt"
77
"io"
88
"net"
9+
"net/http"
910
"net/netip"
1011
"reflect"
1112
"strconv"
@@ -50,8 +51,9 @@ func init() {
5051
}
5152

5253
type Options struct {
53-
Addresses []netip.Prefix
54-
DERPMap *tailcfg.DERPMap
54+
Addresses []netip.Prefix
55+
DERPMap *tailcfg.DERPMap
56+
DERPHeader *http.Header
5557

5658
// BlockEndpoints specifies whether P2P endpoints are blocked.
5759
// If so, only DERPs can establish connections.
@@ -160,6 +162,10 @@ func NewConn(options *Options) (conn *Conn, err error) {
160162
return nil, xerrors.New("get wireguard internals")
161163
}
162164

165+
if options.DERPHeader != nil {
166+
magicConn.SetDERPHeader(options.DERPHeader.Clone())
167+
}
168+
163169
// Update the keys for the magic connection!
164170
err = magicConn.SetPrivateKey(nodePrivateKey)
165171
if err != nil {

0 commit comments

Comments
 (0)