Skip to content

Commit efe289d

Browse files
committed
Merge branch 'main' into supere2e
2 parents cf0d0bb + 2a492b7 commit efe289d

File tree

71 files changed

+847
-202
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+847
-202
lines changed

.github/workflows/security.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ jobs:
7575
7676
- name: Install sqlc
7777
run: |
78-
curl -sSL https://github.com/kyleconroy/sqlc/releases/download/v1.17.2/sqlc_1.17.2_linux_amd64.tar.gz | sudo tar -C /usr/bin -xz sqlc
78+
curl -sSL https://github.com/kyleconroy/sqlc/releases/download/v1.18.0/sqlc_1.18.0_linux_amd64.tar.gz | sudo tar -C /usr/bin -xz sqlc
7979
- name: Install yq
8080
run: go run github.com/mikefarah/yq/v4@v4.30.6
8181
- name: Install mockgen

agent/agent.go

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -593,7 +593,7 @@ func (a *agent) run(ctx context.Context) error {
593593
network := a.network
594594
a.closeMutex.Unlock()
595595
if network == nil {
596-
network, err = a.createTailnet(ctx, manifest.DERPMap)
596+
network, err = a.createTailnet(ctx, manifest.DERPMap, manifest.DisableDirectConnections)
597597
if err != nil {
598598
return xerrors.Errorf("create tailnet: %w", err)
599599
}
@@ -611,8 +611,9 @@ func (a *agent) run(ctx context.Context) error {
611611

612612
a.startReportingConnectionStats(ctx)
613613
} else {
614-
// Update the DERP map!
614+
// Update the DERP map and allow/disallow direct connections.
615615
network.SetDERPMap(manifest.DERPMap)
616+
network.SetBlockEndpoints(manifest.DisableDirectConnections)
616617
}
617618

618619
a.logger.Debug(ctx, "running tailnet connection coordinator")
@@ -637,12 +638,13 @@ func (a *agent) trackConnGoroutine(fn func()) error {
637638
return nil
638639
}
639640

640-
func (a *agent) createTailnet(ctx context.Context, derpMap *tailcfg.DERPMap) (_ *tailnet.Conn, err error) {
641+
func (a *agent) createTailnet(ctx context.Context, derpMap *tailcfg.DERPMap, disableDirectConnections bool) (_ *tailnet.Conn, err error) {
641642
network, err := tailnet.NewConn(&tailnet.Options{
642-
Addresses: []netip.Prefix{netip.PrefixFrom(codersdk.WorkspaceAgentIP, 128)},
643-
DERPMap: derpMap,
644-
Logger: a.logger.Named("tailnet"),
645-
ListenPort: a.tailnetListenPort,
643+
Addresses: []netip.Prefix{netip.PrefixFrom(codersdk.WorkspaceAgentIP, 128)},
644+
DERPMap: derpMap,
645+
Logger: a.logger.Named("tailnet"),
646+
ListenPort: a.tailnetListenPort,
647+
BlockEndpoints: disableDirectConnections,
646648
})
647649
if err != nil {
648650
return nil, xerrors.Errorf("create tailnet: %w", err)

cli/netcheck.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package cli
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"fmt"
7+
"time"
8+
9+
"golang.org/x/xerrors"
10+
11+
"github.com/coder/coder/cli/clibase"
12+
"github.com/coder/coder/coderd/healthcheck"
13+
"github.com/coder/coder/codersdk"
14+
)
15+
16+
func (r *RootCmd) netcheck() *clibase.Cmd {
17+
client := new(codersdk.Client)
18+
19+
cmd := &clibase.Cmd{
20+
Use: "netcheck",
21+
Short: "Print network debug information for DERP and STUN",
22+
Hidden: true,
23+
Middleware: clibase.Chain(
24+
r.InitClient(client),
25+
),
26+
Handler: func(inv *clibase.Invocation) error {
27+
ctx, cancel := context.WithTimeout(inv.Context(), 30*time.Second)
28+
defer cancel()
29+
30+
connInfo, err := client.WorkspaceAgentConnectionInfo(ctx)
31+
if err != nil {
32+
return err
33+
}
34+
35+
_, _ = fmt.Fprint(inv.Stderr, "Gathering a network report. This may take a few seconds...\n\n")
36+
37+
var report healthcheck.DERPReport
38+
report.Run(ctx, &healthcheck.DERPReportOptions{
39+
DERPMap: connInfo.DERPMap,
40+
})
41+
42+
raw, err := json.MarshalIndent(report, "", " ")
43+
if err != nil {
44+
return err
45+
}
46+
47+
n, err := inv.Stdout.Write(raw)
48+
if err != nil {
49+
return err
50+
}
51+
if n != len(raw) {
52+
return xerrors.Errorf("failed to write all bytes to stdout; wrote %d, len %d", n, len(raw))
53+
}
54+
55+
_, _ = inv.Stdout.Write([]byte("\n"))
56+
return nil
57+
},
58+
}
59+
60+
cmd.Options = clibase.OptionSet{}
61+
return cmd
62+
}

cli/netcheck_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package cli_test
2+
3+
import (
4+
"bytes"
5+
"encoding/json"
6+
"testing"
7+
8+
"github.com/stretchr/testify/assert"
9+
"github.com/stretchr/testify/require"
10+
11+
"github.com/coder/coder/cli/clitest"
12+
"github.com/coder/coder/coderd/healthcheck"
13+
"github.com/coder/coder/pty/ptytest"
14+
)
15+
16+
func TestNetcheck(t *testing.T) {
17+
t.Parallel()
18+
19+
pty := ptytest.New(t)
20+
config := login(t, pty)
21+
22+
var out bytes.Buffer
23+
inv, _ := clitest.New(t, "netcheck", "--global-config", string(config))
24+
inv.Stdout = &out
25+
26+
clitest.StartWithWaiter(t, inv).RequireSuccess()
27+
28+
b := out.Bytes()
29+
t.Log(string(b))
30+
var report healthcheck.DERPReport
31+
require.NoError(t, json.Unmarshal(b, &report))
32+
33+
assert.True(t, report.Healthy)
34+
require.Len(t, report.Regions, 1)
35+
for _, v := range report.Regions {
36+
require.Len(t, v.NodeReports, len(v.Region.Nodes))
37+
}
38+
}

cli/ping.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,13 @@ func (r *RootCmd) ping() *clibase.Cmd {
4949
logger = slog.Make(sloghuman.Sink(inv.Stdout)).Leveled(slog.LevelDebug)
5050
}
5151

52-
conn, err := client.DialWorkspaceAgent(ctx, workspaceAgent.ID, &codersdk.DialWorkspaceAgentOptions{Logger: logger})
52+
if r.disableDirect {
53+
_, _ = fmt.Fprintln(inv.Stderr, "Direct connections disabled.")
54+
}
55+
conn, err := client.DialWorkspaceAgent(ctx, workspaceAgent.ID, &codersdk.DialWorkspaceAgentOptions{
56+
Logger: logger,
57+
BlockEndpoints: r.disableDirect,
58+
})
5359
if err != nil {
5460
return err
5561
}

cli/portforward.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ import (
1515
"github.com/pion/udp"
1616
"golang.org/x/xerrors"
1717

18+
"cdr.dev/slog"
19+
"cdr.dev/slog/sloggers/sloghuman"
20+
1821
"github.com/coder/coder/agent/agentssh"
1922
"github.com/coder/coder/cli/clibase"
2023
"github.com/coder/coder/cli/cliui"
@@ -98,7 +101,18 @@ func (r *RootCmd) portForward() *clibase.Cmd {
98101
return xerrors.Errorf("await agent: %w", err)
99102
}
100103

101-
conn, err := client.DialWorkspaceAgent(ctx, workspaceAgent.ID, nil)
104+
var logger slog.Logger
105+
if r.verbose {
106+
logger = slog.Make(sloghuman.Sink(inv.Stdout)).Leveled(slog.LevelDebug)
107+
}
108+
109+
if r.disableDirect {
110+
_, _ = fmt.Fprintln(inv.Stderr, "Direct connections disabled.")
111+
}
112+
conn, err := client.DialWorkspaceAgent(ctx, workspaceAgent.ID, &codersdk.DialWorkspaceAgentOptions{
113+
Logger: logger,
114+
BlockEndpoints: r.disableDirect,
115+
})
102116
if err != nil {
103117
return err
104118
}

cli/root.go

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ const (
6060
varNoFeatureWarning = "no-feature-warning"
6161
varForceTty = "force-tty"
6262
varVerbose = "verbose"
63+
varDisableDirect = "disable-direct-connections"
6364
notLoggedInMessage = "You are not logged in. Try logging in using 'coder login <url>'."
6465

6566
envNoVersionCheck = "CODER_NO_VERSION_WARNING"
@@ -107,6 +108,7 @@ func (r *RootCmd) Core() []*clibase.Cmd {
107108

108109
// Hidden
109110
r.gitssh(),
111+
r.netcheck(),
110112
r.vscodeSSH(),
111113
r.workspaceAgent(),
112114
}
@@ -366,6 +368,13 @@ func (r *RootCmd) Command(subcommands []*clibase.Cmd) (*clibase.Cmd, error) {
366368
Value: clibase.BoolOf(&r.verbose),
367369
Group: globalGroup,
368370
},
371+
{
372+
Flag: varDisableDirect,
373+
Env: "CODER_DISABLE_DIRECT_CONNECTIONS",
374+
Description: "Disable direct (P2P) connections to workspaces.",
375+
Value: clibase.BoolOf(&r.disableDirect),
376+
Group: globalGroup,
377+
},
369378
{
370379
Flag: "debug-http",
371380
Description: "Debug codersdk HTTP requests.",
@@ -412,16 +421,17 @@ func isTest() bool {
412421

413422
// RootCmd contains parameters and helpers useful to all commands.
414423
type RootCmd struct {
415-
clientURL *url.URL
416-
token string
417-
globalConfig string
418-
header []string
419-
agentToken string
420-
agentURL *url.URL
421-
forceTTY bool
422-
noOpen bool
423-
verbose bool
424-
debugHTTP bool
424+
clientURL *url.URL
425+
token string
426+
globalConfig string
427+
header []string
428+
agentToken string
429+
agentURL *url.URL
430+
forceTTY bool
431+
noOpen bool
432+
verbose bool
433+
disableDirect bool
434+
debugHTTP bool
425435

426436
noVersionCheck bool
427437
noFeatureWarning bool
@@ -523,6 +533,7 @@ func (r *RootCmd) InitClient(client *codersdk.Client) clibase.MiddlewareFunc {
523533
client.PlainLogger = os.Stderr
524534
client.LogBodies = true
525535
}
536+
client.DisableDirectConnections = r.disableDirect
526537

527538
// We send these requests in parallel to minimize latency.
528539
var (

cli/server.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,7 @@ func (r *RootCmd) Server(newAPI func(context.Context, *coderd.Options) (*coderd.
413413
derpMap, err := tailnet.NewDERPMap(
414414
ctx, defaultRegion, cfg.DERP.Server.STUNAddresses,
415415
cfg.DERP.Config.URL.String(), cfg.DERP.Config.Path.String(),
416+
cfg.DERP.Config.BlockDirect.Value(),
416417
)
417418
if err != nil {
418419
return xerrors.Errorf("create derp map: %w", err)

cli/speedtest.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,18 @@ func (r *RootCmd) speedtest() *clibase.Cmd {
5050
if err != nil && !xerrors.Is(err, cliui.AgentStartError) {
5151
return xerrors.Errorf("await agent: %w", err)
5252
}
53+
5354
logger, ok := LoggerFromContext(ctx)
5455
if !ok {
5556
logger = slog.Make(sloghuman.Sink(inv.Stderr))
5657
}
5758
if r.verbose {
5859
logger = logger.Leveled(slog.LevelDebug)
5960
}
61+
62+
if r.disableDirect {
63+
_, _ = fmt.Fprintln(inv.Stderr, "Direct connections disabled.")
64+
}
6065
conn, err := client.DialWorkspaceAgent(ctx, workspaceAgent.ID, &codersdk.DialWorkspaceAgentOptions{
6166
Logger: logger,
6267
})

cli/ssh.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,8 +195,12 @@ func (r *RootCmd) ssh() *clibase.Cmd {
195195
// We don't print the error because cliui.Agent does that for us.
196196
}
197197

198+
if r.disableDirect {
199+
_, _ = fmt.Fprintln(inv.Stderr, "Direct connections disabled.")
200+
}
198201
conn, err := client.DialWorkspaceAgent(ctx, workspaceAgent.ID, &codersdk.DialWorkspaceAgentOptions{
199-
Logger: logger,
202+
Logger: logger,
203+
BlockEndpoints: r.disableDirect,
200204
})
201205
if err != nil {
202206
return xerrors.Errorf("dial agent: %w", err)

0 commit comments

Comments
 (0)