Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita1b87a6

Browse files
authored
fix: use client preferred URL for the default DERP (#18911)
The agentsdk currently does a remap of the DERP map to change theEmbeddedRelay node's URL to match the agent's access URL.This PR makes changes to the `workspacesdk` (used by clients like theCLI) and `vpn` (used by Coder Desktop) to match this behavior.This enables us the ability to try Coder clients in dogfood over a VPNwithout changing the global access URL.
1 parentfb00cd2 commita1b87a6

File tree

11 files changed

+248
-56
lines changed

11 files changed

+248
-56
lines changed

‎agent/agent.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ type Client interface {
9898
ConnectRPC26(ctx context.Context) (
9999
proto.DRPCAgentClient26, tailnetproto.DRPCTailnetClient26,error,
100100
)
101-
RewriteDERPMap(derpMap*tailcfg.DERPMap)
101+
tailnet.DERPMapRewriter
102102
}
103103

104104
typeAgentinterface {

‎coderd/tailnet.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ func NewServerTailnet(
9898
controller:=tailnet.NewController(logger,dialer)
9999
// it's important to set the DERPRegionDialer above _before_ we set the DERP map so that if
100100
// there is an embedded relay, we use the local in-memory dialer.
101-
controller.DERPCtrl=tailnet.NewBasicDERPController(logger,conn)
101+
controller.DERPCtrl=tailnet.NewBasicDERPController(logger,nil,conn)
102102
coordCtrl:=NewMultiAgentController(serverCtx,logger,tracer,conn)
103103
controller.CoordCtrl=coordCtrl
104104
// TODO: support controller.TelemetryCtrl

‎codersdk/agentsdk/agentsdk.go

Lines changed: 6 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import (
88
"net/http"
99
"net/http/cookiejar"
1010
"net/url"
11-
"strconv"
1211
"time"
1312

1413
"cloud.google.com/go/compute/metadata"
@@ -27,6 +26,7 @@ import (
2726
"github.com/coder/coder/v2/coderd/httpapi"
2827
"github.com/coder/coder/v2/codersdk"
2928
"github.com/coder/coder/v2/codersdk/drpcsdk"
29+
"github.com/coder/coder/v2/tailnet"
3030
tailnetproto"github.com/coder/coder/v2/tailnet/proto"
3131
)
3232

@@ -126,40 +126,13 @@ type Script struct {
126126
Scriptstring`json:"script"`
127127
}
128128

129-
// RewriteDERPMap rewrites the DERP map to use the access URL of the SDK as the
130-
// "embedded relay" access URL. The passed derp map is modified in place.
129+
// RewriteDERPMap rewrites the DERP map to use theconfiguredaccess URL of the
130+
//agent as the"embedded relay" access URL.
131131
//
132-
// Agents can provide an arbitrary access URL that may be different that the
133-
// globally configured one. This breaks the built-in DERP, which would continue
134-
// to reference the global access URL.
132+
// See tailnet.RewriteDERPMapDefaultRelay for more details on why this is
133+
// necessary.
135134
func (c*Client)RewriteDERPMap(derpMap*tailcfg.DERPMap) {
136-
accessingPort:=c.SDK.URL.Port()
137-
ifaccessingPort=="" {
138-
accessingPort="80"
139-
ifc.SDK.URL.Scheme=="https" {
140-
accessingPort="443"
141-
}
142-
}
143-
accessPort,err:=strconv.Atoi(accessingPort)
144-
iferr!=nil {
145-
// this should never happen because URL.Port() returns the empty string if the port is not
146-
// valid.
147-
c.SDK.Logger().Critical(context.Background(),"failed to parse URL port",slog.F("port",accessingPort))
148-
}
149-
for_,region:=rangederpMap.Regions {
150-
if!region.EmbeddedRelay {
151-
continue
152-
}
153-
154-
for_,node:=rangeregion.Nodes {
155-
ifnode.STUNOnly {
156-
continue
157-
}
158-
node.HostName=c.SDK.URL.Hostname()
159-
node.DERPPort=accessPort
160-
node.ForceHTTP=c.SDK.URL.Scheme=="http"
161-
}
162-
}
135+
tailnet.RewriteDERPMapDefaultRelay(context.Background(),c.SDK.Logger(),derpMap,c.SDK.URL)
163136
}
164137

165138
// ConnectRPC20 returns a dRPC client to the Agent API v2.0. Notably, it is missing

‎codersdk/agentsdk/agentsdk_test.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@ import (
55
"io"
66
"net/http"
77
"net/http/httptest"
8+
"net/url"
89
"testing"
910

1011
"github.com/google/uuid"
1112
"github.com/stretchr/testify/require"
13+
"tailscale.com/tailcfg"
1214

1315
"cdr.dev/slog/sloggers/slogtest"
1416
"github.com/coder/coder/v2/codersdk/agentsdk"
@@ -120,3 +122,31 @@ func TestStreamAgentReinitEvents(t *testing.T) {
120122
require.ErrorIs(t,receiveErr,context.Canceled)
121123
})
122124
}
125+
126+
funcTestRewriteDERPMap(t*testing.T) {
127+
t.Parallel()
128+
// This test ensures that RewriteDERPMap mutates built-in DERPs with the
129+
// client access URL.
130+
dm:=&tailcfg.DERPMap{
131+
Regions:map[int]*tailcfg.DERPRegion{
132+
1: {
133+
EmbeddedRelay:true,
134+
RegionID:1,
135+
Nodes: []*tailcfg.DERPNode{{
136+
HostName:"bananas.org",
137+
DERPPort:1,
138+
}},
139+
},
140+
},
141+
}
142+
parsed,err:=url.Parse("https://coconuts.org:44558")
143+
require.NoError(t,err)
144+
client:=agentsdk.New(parsed)
145+
client.RewriteDERPMap(dm)
146+
region:=dm.Regions[1]
147+
require.True(t,region.EmbeddedRelay)
148+
require.Len(t,region.Nodes,1)
149+
node:=region.Nodes[0]
150+
require.Equal(t,"coconuts.org",node.HostName)
151+
require.Equal(t,44558,node.DERPPort)
152+
}

‎codersdk/workspacesdk/workspacesdk.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,15 @@ type DialAgentOptions struct {
193193
EnableTelemetrybool
194194
}
195195

196+
// RewriteDERPMap rewrites the DERP map to use the configured access URL of the
197+
// client as the "embedded relay" access URL.
198+
//
199+
// See tailnet.RewriteDERPMapDefaultRelay for more details on why this is
200+
// necessary.
201+
func (c*Client)RewriteDERPMap(derpMap*tailcfg.DERPMap) {
202+
tailnet.RewriteDERPMapDefaultRelay(context.Background(),c.client.Logger(),derpMap,c.client.URL)
203+
}
204+
196205
func (c*Client)DialAgent(dialCtx context.Context,agentID uuid.UUID,options*DialAgentOptions) (agentConn*AgentConn,errerror) {
197206
ifoptions==nil {
198207
options=&DialAgentOptions{}
@@ -248,6 +257,8 @@ func (c *Client) DialAgent(dialCtx context.Context, agentID uuid.UUID, options *
248257
telemetrySink=basicTel
249258
controller.TelemetryCtrl=basicTel
250259
}
260+
261+
c.RewriteDERPMap(connInfo.DERPMap)
251262
conn,err:=tailnet.NewConn(&tailnet.Options{
252263
Addresses: []netip.Prefix{netip.PrefixFrom(ip,128)},
253264
DERPMap:connInfo.DERPMap,
@@ -270,7 +281,7 @@ func (c *Client) DialAgent(dialCtx context.Context, agentID uuid.UUID, options *
270281
coordCtrl:=tailnet.NewTunnelSrcCoordController(options.Logger,conn)
271282
coordCtrl.AddDestination(agentID)
272283
controller.CoordCtrl=coordCtrl
273-
controller.DERPCtrl=tailnet.NewBasicDERPController(options.Logger,conn)
284+
controller.DERPCtrl=tailnet.NewBasicDERPController(options.Logger,c,conn)
274285
controller.Run(ctx)
275286

276287
options.Logger.Debug(ctx,"running tailnet API v2+ connector")

‎codersdk/workspacesdk/workspacesdk_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import (
1919

2020
"github.com/coder/coder/v2/coderd/httpapi"
2121
"github.com/coder/coder/v2/codersdk"
22-
"github.com/coder/coder/v2/codersdk/agentsdk"
2322
"github.com/coder/coder/v2/codersdk/workspacesdk"
2423
"github.com/coder/coder/v2/tailnet"
2524
"github.com/coder/coder/v2/testutil"
@@ -43,7 +42,7 @@ func TestWorkspaceRewriteDERPMap(t *testing.T) {
4342
}
4443
parsed,err:=url.Parse("https://coconuts.org:44558")
4544
require.NoError(t,err)
46-
client:=agentsdk.New(parsed)
45+
client:=workspacesdk.New(codersdk.New(parsed))
4746
client.RewriteDERPMap(dm)
4847
region:=dm.Regions[1]
4948
require.True(t,region.EmbeddedRelay)

‎tailnet/controllers.go

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -568,13 +568,15 @@ type DERPMapSetter interface {
568568
}
569569

570570
typebasicDERPControllerstruct {
571-
logger slog.Logger
572-
setterDERPMapSetter
571+
logger slog.Logger
572+
rewriterDERPMapRewriter// optional
573+
setterDERPMapSetter
573574
}
574575

575576
func (b*basicDERPController)New(clientDERPClient)CloserWaiter {
576577
l:=&derpSetLoop{
577578
logger:b.logger,
579+
rewriter:b.rewriter,
578580
setter:b.setter,
579581
client:client,
580582
errChan:make(chanerror,1),
@@ -584,17 +586,23 @@ func (b *basicDERPController) New(client DERPClient) CloserWaiter {
584586
returnl
585587
}
586588

587-
funcNewBasicDERPController(logger slog.Logger,setterDERPMapSetter)DERPController {
589+
// NewBasicDERPController creates a DERP controller that rewrites the DERP map
590+
// with the provided rewriter before setting it on the provided setter.
591+
//
592+
// The rewriter is optional and can be nil.
593+
funcNewBasicDERPController(logger slog.Logger,rewriterDERPMapRewriter,setterDERPMapSetter)DERPController {
588594
return&basicDERPController{
589-
logger:logger,
590-
setter:setter,
595+
logger:logger,
596+
rewriter:rewriter,
597+
setter:setter,
591598
}
592599
}
593600

594601
typederpSetLoopstruct {
595-
logger slog.Logger
596-
setterDERPMapSetter
597-
clientDERPClient
602+
logger slog.Logger
603+
rewriterDERPMapRewriter// optional
604+
setterDERPMapSetter
605+
clientDERPClient
598606

599607
sync.Mutex
600608
closedbool
@@ -640,6 +648,9 @@ func (l *derpSetLoop) recvLoop() {
640648
return
641649
}
642650
l.logger.Debug(context.Background(),"got new DERP Map",slog.F("derp_map",dm))
651+
ifl.rewriter!=nil {
652+
l.rewriter.RewriteDERPMap(dm)
653+
}
643654
l.setter.SetDERPMap(dm)
644655
}
645656
}

‎tailnet/controllers_test.go

Lines changed: 91 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -586,7 +586,7 @@ func TestNewBasicDERPController_Mainline(t *testing.T) {
586586
t.Parallel()
587587
fs:=make(chan*tailcfg.DERPMap)
588588
logger:=testutil.Logger(t)
589-
uut:=tailnet.NewBasicDERPController(logger,fakeSetter(fs))
589+
uut:=tailnet.NewBasicDERPController(logger,nil,fakeSetter(fs))
590590
fc:=fakeDERPClient{
591591
ch:make(chan*tailcfg.DERPMap),
592592
}
@@ -609,7 +609,7 @@ func TestNewBasicDERPController_RecvErr(t *testing.T) {
609609
t.Parallel()
610610
fs:=make(chan*tailcfg.DERPMap)
611611
logger:=testutil.Logger(t)
612-
uut:=tailnet.NewBasicDERPController(logger,fakeSetter(fs))
612+
uut:=tailnet.NewBasicDERPController(logger,nil,fakeSetter(fs))
613613
expectedErr:=xerrors.New("a bad thing happened")
614614
fc:=fakeDERPClient{
615615
ch:make(chan*tailcfg.DERPMap),
@@ -1041,7 +1041,7 @@ func TestController_Disconnects(t *testing.T) {
10411041
// darwin can be slow sometimes.
10421042
tailnet.WithGracefulTimeout(5*time.Second))
10431043
uut.CoordCtrl=tailnet.NewAgentCoordinationController(logger.Named("coord_ctrl"),fConn)
1044-
uut.DERPCtrl=tailnet.NewBasicDERPController(logger.Named("derp_ctrl"),fConn)
1044+
uut.DERPCtrl=tailnet.NewBasicDERPController(logger.Named("derp_ctrl"),nil,fConn)
10451045
uut.Run(ctx)
10461046

10471047
call:=testutil.TryReceive(testCtx,t,fCoord.CoordinateCalls)
@@ -1945,6 +1945,52 @@ func TestTunnelAllWorkspaceUpdatesController_HandleErrors(t *testing.T) {
19451945
}
19461946
}
19471947

1948+
funcTestBasicDERPController_RewriteDERPMap(t*testing.T) {
1949+
t.Parallel()
1950+
ctx:=testutil.Context(t,testutil.WaitShort)
1951+
logger:=slogtest.Make(t,&slogtest.Options{IgnoreErrors:true}).Leveled(slog.LevelDebug)
1952+
1953+
testDERPMap:=&tailcfg.DERPMap{
1954+
Regions:map[int]*tailcfg.DERPRegion{
1955+
1: {
1956+
RegionID:1,
1957+
},
1958+
},
1959+
}
1960+
1961+
// Ensure the fake rewriter works as expected.
1962+
rewriter:=&fakeDERPMapRewriter{
1963+
ctx:ctx,
1964+
calls:make(chanrewriteDERPMapCall,16),
1965+
}
1966+
rewriter.RewriteDERPMap(testDERPMap)
1967+
rewriteCall:=testutil.TryReceive(ctx,t,rewriter.calls)
1968+
require.Same(t,testDERPMap,rewriteCall.derpMap)
1969+
1970+
derpClient:=&fakeDERPClient{
1971+
ch:make(chan*tailcfg.DERPMap),
1972+
err:nil,
1973+
}
1974+
deferderpClient.Close()
1975+
1976+
derpSetter:=&fakeDERPMapSetter{
1977+
ctx:ctx,
1978+
calls:make(chan*setDERPMapCall,16),
1979+
}
1980+
1981+
derpCtrl:=tailnet.NewBasicDERPController(logger,rewriter,derpSetter)
1982+
derpCtrl.New(derpClient)
1983+
1984+
// Simulate receiving a new DERP map from the server, which should be passed
1985+
// to the rewriter and setter.
1986+
testDERPMap=testDERPMap.Clone()// make a new pointer
1987+
derpClient.ch<-testDERPMap
1988+
rewriteCall=testutil.TryReceive(ctx,t,rewriter.calls)
1989+
require.Same(t,testDERPMap,rewriteCall.derpMap)
1990+
setterCall:=testutil.TryReceive(ctx,t,derpSetter.calls)
1991+
require.Same(t,testDERPMap,setterCall.derpMap)
1992+
}
1993+
19481994
typefakeWorkspaceUpdatesControllerstruct {
19491995
ctx context.Context
19501996
t testing.TB
@@ -2040,3 +2086,45 @@ type fakeCloser struct{}
20402086
func (fakeCloser)Close()error {
20412087
returnnil
20422088
}
2089+
2090+
typefakeDERPMapRewriterstruct {
2091+
ctx context.Context
2092+
callschanrewriteDERPMapCall
2093+
}
2094+
2095+
var_ tailnet.DERPMapRewriter=&fakeDERPMapRewriter{}
2096+
2097+
typerewriteDERPMapCallstruct {
2098+
derpMap*tailcfg.DERPMap
2099+
}
2100+
2101+
func (f*fakeDERPMapRewriter)RewriteDERPMap(derpMap*tailcfg.DERPMap) {
2102+
call:=rewriteDERPMapCall{
2103+
derpMap:derpMap,
2104+
}
2105+
select {
2106+
casef.calls<-call:
2107+
case<-f.ctx.Done():
2108+
}
2109+
}
2110+
2111+
typefakeDERPMapSetterstruct {
2112+
ctx context.Context
2113+
callschan*setDERPMapCall
2114+
}
2115+
2116+
var_ tailnet.DERPMapSetter=&fakeDERPMapSetter{}
2117+
2118+
typesetDERPMapCallstruct {
2119+
derpMap*tailcfg.DERPMap
2120+
}
2121+
2122+
func (f*fakeDERPMapSetter)SetDERPMap(derpMap*tailcfg.DERPMap) {
2123+
call:=&setDERPMapCall{
2124+
derpMap:derpMap,
2125+
}
2126+
select {
2127+
case<-f.ctx.Done():
2128+
casef.calls<-call:
2129+
}
2130+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp