feat: Add TURN proxying to enable offline deployments (#1000)

* Add turnconn

* Add option for passing ICE servers

* Log TURN remote address

* Add TURN server to coder start
This commit is contained in:
Kyle Carberry
2022-04-18 22:40:25 +00:00
committed by GitHub
parent e5a1c305d3
commit d202f20fdb
25 changed files with 603 additions and 112 deletions
+1 -4
View File
@@ -16,7 +16,6 @@ import (
"github.com/coder/coder/agent"
"github.com/coder/coder/cli/cliflag"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/peer"
"github.com/coder/retry"
)
@@ -110,9 +109,7 @@ func workspaceAgent() *cobra.Command {
return xerrors.Errorf("writing agent session token to config: %w", err)
}
closer := agent.New(client.ListenWorkspaceAgent, &peer.ConnOptions{
Logger: logger,
})
closer := agent.New(client.ListenWorkspaceAgent, logger)
<-cmd.Context().Done()
return closer.Close()
},
+2 -2
View File
@@ -61,7 +61,7 @@ func TestWorkspaceAgent(t *testing.T) {
coderdtest.AwaitWorkspaceAgents(t, client, workspace.LatestBuild.ID)
resources, err := client.WorkspaceResourcesByBuild(ctx, workspace.LatestBuild.ID)
require.NoError(t, err)
dialer, err := client.DialWorkspaceAgent(ctx, resources[0].Agents[0].ID, nil, nil)
dialer, err := client.DialWorkspaceAgent(ctx, resources[0].Agents[0].ID, nil)
require.NoError(t, err)
defer dialer.Close()
_, err = dialer.Ping()
@@ -115,7 +115,7 @@ func TestWorkspaceAgent(t *testing.T) {
coderdtest.AwaitWorkspaceAgents(t, client, workspace.LatestBuild.ID)
resources, err := client.WorkspaceResourcesByBuild(ctx, workspace.LatestBuild.ID)
require.NoError(t, err)
dialer, err := client.DialWorkspaceAgent(ctx, resources[0].Agents[0].ID, nil, nil)
dialer, err := client.DialWorkspaceAgent(ctx, resources[0].Agents[0].ID, nil)
require.NoError(t, err)
defer dialer.Close()
_, err = dialer.Ping()
+2 -5
View File
@@ -19,7 +19,6 @@ import (
"github.com/coder/coder/cli/clitest"
"github.com/coder/coder/coderd/coderdtest"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/peer"
"github.com/coder/coder/provisioner/echo"
"github.com/coder/coder/provisionersdk/proto"
"github.com/coder/coder/pty/ptytest"
@@ -72,9 +71,7 @@ func TestConfigSSH(t *testing.T) {
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
agentClient := codersdk.New(client.URL)
agentClient.SessionToken = authToken
agentCloser := agent.New(agentClient.ListenWorkspaceAgent, &peer.ConnOptions{
Logger: slogtest.Make(t, nil),
})
agentCloser := agent.New(agentClient.ListenWorkspaceAgent, slogtest.Make(t, nil))
t.Cleanup(func() {
_ = agentCloser.Close()
})
@@ -82,7 +79,7 @@ func TestConfigSSH(t *testing.T) {
require.NoError(t, err)
_ = tempFile.Close()
resources := coderdtest.AwaitWorkspaceAgents(t, client, workspace.LatestBuild.ID)
agentConn, err := client.DialWorkspaceAgent(context.Background(), resources[0].Agents[0].ID, nil, nil)
agentConn, err := client.DialWorkspaceAgent(context.Background(), resources[0].Agents[0].ID, nil)
require.NoError(t, err)
defer agentConn.Close()
+1 -1
View File
@@ -74,7 +74,7 @@ func TestGitSSH(t *testing.T) {
coderdtest.AwaitWorkspaceAgents(t, client, workspace.LatestBuild.ID)
resources, err := client.WorkspaceResourcesByBuild(context.Background(), workspace.LatestBuild.ID)
require.NoError(t, err)
dialer, err := client.DialWorkspaceAgent(context.Background(), resources[0].Agents[0].ID, nil, nil)
dialer, err := client.DialWorkspaceAgent(context.Background(), resources[0].Agents[0].ID, nil)
require.NoError(t, err)
defer dialer.Close()
_, err = dialer.Ping()
+1 -4
View File
@@ -10,7 +10,6 @@ import (
"github.com/google/uuid"
"github.com/mattn/go-isatty"
"github.com/pion/webrtc/v3"
"github.com/spf13/cobra"
gossh "golang.org/x/crypto/ssh"
"golang.org/x/term"
@@ -99,9 +98,7 @@ func ssh() *cobra.Command {
return xerrors.Errorf("await agent: %w", err)
}
conn, err := client.DialWorkspaceAgent(cmd.Context(), agent.ID, []webrtc.ICEServer{{
URLs: []string{"stun:stun.l.google.com:19302"},
}}, nil)
conn, err := client.DialWorkspaceAgent(cmd.Context(), agent.ID, nil)
if err != nil {
return err
}
+2 -7
View File
@@ -17,7 +17,6 @@ import (
"github.com/coder/coder/cli/clitest"
"github.com/coder/coder/coderd/coderdtest"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/peer"
"github.com/coder/coder/provisioner/echo"
"github.com/coder/coder/provisionersdk/proto"
"github.com/coder/coder/pty/ptytest"
@@ -70,9 +69,7 @@ func TestSSH(t *testing.T) {
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
agentClient := codersdk.New(client.URL)
agentClient.SessionToken = agentToken
agentCloser := agent.New(agentClient.ListenWorkspaceAgent, &peer.ConnOptions{
Logger: slogtest.Make(t, nil).Leveled(slog.LevelDebug),
})
agentCloser := agent.New(agentClient.ListenWorkspaceAgent, slogtest.Make(t, nil).Leveled(slog.LevelDebug))
t.Cleanup(func() {
_ = agentCloser.Close()
})
@@ -115,9 +112,7 @@ func TestSSH(t *testing.T) {
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
agentClient := codersdk.New(client.URL)
agentClient.SessionToken = agentToken
agentCloser := agent.New(agentClient.ListenWorkspaceAgent, &peer.ConnOptions{
Logger: slogtest.Make(t, nil).Leveled(slog.LevelDebug),
})
agentCloser := agent.New(agentClient.ListenWorkspaceAgent, slogtest.Make(t, nil).Leveled(slog.LevelDebug))
t.Cleanup(func() {
_ = agentCloser.Close()
})
+15
View File
@@ -18,6 +18,7 @@ import (
"github.com/briandowns/spinner"
"github.com/coreos/go-systemd/daemon"
"github.com/pion/turn/v2"
"github.com/spf13/cobra"
"golang.org/x/xerrors"
"google.golang.org/api/idtoken"
@@ -34,6 +35,7 @@ import (
"github.com/coder/coder/coderd/database/databasefake"
"github.com/coder/coder/coderd/devtunnel"
"github.com/coder/coder/coderd/gitsshkey"
"github.com/coder/coder/coderd/turnconn"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/provisioner/terraform"
"github.com/coder/coder/provisionerd"
@@ -56,11 +58,13 @@ func start() *cobra.Command {
tlsEnable bool
tlsKeyFile string
tlsMinVersion string
turnRelayAddress string
skipTunnel bool
traceDatadog bool
secureAuthCookie bool
sshKeygenAlgorithmRaw string
)
root := &cobra.Command{
Use: "start",
RunE: func(cmd *cobra.Command, args []string) error {
@@ -156,6 +160,14 @@ func start() *cobra.Command {
return xerrors.Errorf("parse ssh keygen algorithm %s: %w", sshKeygenAlgorithmRaw, err)
}
turnServer, err := turnconn.New(&turn.RelayAddressGeneratorStatic{
RelayAddress: net.ParseIP(turnRelayAddress),
Address: turnRelayAddress,
})
if err != nil {
return xerrors.Errorf("create turn server: %w", err)
}
options := &coderd.Options{
AccessURL: accessURLParsed,
Logger: logger.Named("coderd"),
@@ -164,6 +176,7 @@ func start() *cobra.Command {
GoogleTokenValidator: validator,
SecureAuthCookie: secureAuthCookie,
SSHKeygenAlgorithm: sshKeygenAlgorithm,
TURNServer: turnServer,
}
_, _ = fmt.Fprintf(cmd.ErrOrStderr(), "access-url: %s\n", accessURL)
@@ -376,6 +389,8 @@ func start() *cobra.Command {
cliflag.BoolVarP(root.Flags(), &skipTunnel, "skip-tunnel", "", "CODER_DEV_SKIP_TUNNEL", false, "Skip serving dev mode through an exposed tunnel for simple setup.")
_ = root.Flags().MarkHidden("skip-tunnel")
cliflag.BoolVarP(root.Flags(), &traceDatadog, "trace-datadog", "", "CODER_TRACE_DATADOG", false, "Send tracing data to a datadog agent")
cliflag.StringVarP(root.Flags(), &turnRelayAddress, "turn-relay-address", "", "CODER_TURN_RELAY_ADDRESS", "127.0.0.1",
"Specifies the address to bind TURN connections.")
cliflag.BoolVarP(root.Flags(), &secureAuthCookie, "secure-auth-cookie", "", "CODER_SECURE_AUTH_COOKIE", false, "Specifies if the 'Secure' property is set on browser session cookies")
cliflag.StringVarP(root.Flags(), &sshKeygenAlgorithmRaw, "ssh-keygen-algorithm", "", "CODER_SSH_KEYGEN_ALGORITHM", "ed25519", "Specifies the algorithm to use for generating ssh keys. "+
`Accepted values are "ed25519", "ecdsa", or "rsa4096"`)