-
Notifications
You must be signed in to change notification settings - Fork 943
feat: Add SSH agent forwarding support to coder agent #1548
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 1 commit
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
54b74f7
feat: Add SSH agent forwarding support to coder agent
mafredri 3df1a08
feat: Add forward agent flag to `coder ssh`
mafredri 51c4128
refactor: Share setup between SSH tests, sync goroutines
mafredri 8f0d454
feat: Add test for `coder ssh --forward-agent`
mafredri ce9c05d
fix: Fix TestSSH/ImmediateExit flakyness with sleep
mafredri f1596de
fix: Fix ForwardAgent test on macOS
mafredri 5044d11
fix: Fix test flakes and implement Deans suggestion for helpers
mafredri e754672
fix: Add example to config-ssh
mafredri 8d3df94
fix: Ignore closed errors in test
mafredri ea46d7b
fix: Allow forwarding agent via -A
mafredri 326b942
Update cli/ssh_test.go
mafredri File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
feat: Add test for
coder ssh --forward-agent
- Loading branch information
commit 8f0d4542864c921765f12a87cd4ffda4fd7094cd
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,8 +2,13 @@ package cli_test | |
|
||
import ( | ||
"context" | ||
"crypto/ecdsa" | ||
"crypto/elliptic" | ||
"crypto/rand" | ||
"errors" | ||
"io" | ||
"net" | ||
"path/filepath" | ||
"runtime" | ||
"testing" | ||
"time" | ||
|
@@ -12,6 +17,7 @@ import ( | |
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
"golang.org/x/crypto/ssh" | ||
gosshagent "golang.org/x/crypto/ssh/agent" | ||
|
||
"cdr.dev/slog" | ||
"cdr.dev/slog/sloggers/slogtest" | ||
|
@@ -135,6 +141,84 @@ func TestSSH(t *testing.T) { | |
require.NoError(t, err) | ||
_ = clientOutput.Close() | ||
}) | ||
//nolint:paralleltest // Disabled due to use of t.Setenv. | ||
t.Run("ForwardAgent", func(t *testing.T) { | ||
if runtime.GOOS == "windows" { | ||
t.Skip("Test not supported on windows") | ||
} | ||
|
||
client, workspace, agentToken := setupWorkspaceForSSH(t) | ||
|
||
tGoContext(t, func(ctx context.Context) { | ||
// Run this async so the SSH command has to wait for | ||
// the build and agent to connect! | ||
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID) | ||
agentClient := codersdk.New(client.URL) | ||
agentClient.SessionToken = agentToken | ||
agentCloser := agent.New(agentClient.ListenWorkspaceAgent, &agent.Options{ | ||
Logger: slogtest.Make(t, nil).Leveled(slog.LevelDebug), | ||
}) | ||
<-ctx.Done() | ||
_ = agentCloser.Close() | ||
}) | ||
|
||
// Generate private key. | ||
privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) | ||
require.NoError(t, err) | ||
kr := gosshagent.NewKeyring() | ||
kr.Add(gosshagent.AddedKey{ | ||
PrivateKey: privateKey, | ||
}) | ||
|
||
// Start up ssh agent listening on unix socket. | ||
tmpdir := t.TempDir() | ||
agentSock := filepath.Join(tmpdir, "agent.sock") | ||
l, err := net.Listen("unix", agentSock) | ||
require.NoError(t, err) | ||
defer l.Close() | ||
tGo(t, func() { | ||
for { | ||
fd, err := l.Accept() | ||
if err != nil { | ||
t.Logf("accept error: %v", err) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ignore closed errors |
||
return | ||
} | ||
|
||
err = gosshagent.ServeAgent(kr, fd) | ||
if !errors.Is(err, io.EOF) { | ||
assert.NoError(t, err) | ||
} | ||
} | ||
}) | ||
|
||
t.Setenv("SSH_AUTH_SOCK", agentSock) | ||
cmd, root := clitest.New(t, | ||
"ssh", | ||
workspace.Name, | ||
"--forward-agent", | ||
) | ||
clitest.SetupConfig(t, client, root) | ||
pty := ptytest.New(t) | ||
cmd.SetIn(pty.Input()) | ||
cmd.SetOut(pty.Output()) | ||
cmd.SetErr(io.Discard) | ||
tGo(t, func() { | ||
err := cmd.Execute() | ||
assert.NoError(t, err) | ||
}) | ||
|
||
// Ensure that SSH_AUTH_SOCK is set. | ||
pty.WriteLine("env") | ||
pty.ExpectMatch("SSH_AUTH_SOCK=/tmp") // E.g. /tmp/auth-agent3167016167/listener.sock | ||
// Ensure that ssh-add lists our key. | ||
pty.WriteLine("ssh-add -L") | ||
keys, err := kr.List() | ||
require.NoError(t, err) | ||
pty.ExpectMatch(keys[0].String()) | ||
|
||
// kthxbye | ||
pty.WriteLine("exit") | ||
}) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. praise: This is such a cool test. |
||
} | ||
|
||
// tGoContext runs fn in a goroutine passing a context that will be | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remark, non-blocking: recent versions of Windows do include SSH (source) but it's probably a ghastly can of worms to open! So agreed, let's leave this non-Windows for now. 😅