Files
coder/cli/gitaskpass_test.go
Spike Curtis 1354d84eb4 chore: refactor instance identity to be a SessionTokenProvider (#19566)
Refactors Agent instance identity to be a SessionTokenProvider.

Refactors the CLI to create Agent clients via a centralized function, rather than add-hoc via individual command handlers and their flags.

This allows commands besides `coder agent`, but which still use the agent identity, to support instance identity authentication.

Fixes #19111 by unifying all API requests to go thru the SessionTokenProvider for auth credentials.
2025-09-03 10:38:42 +04:00

112 lines
3.3 KiB
Go

package cli_test
import (
"context"
"net/http"
"net/http/httptest"
"sync/atomic"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/coder/coder/v2/cli/clitest"
"github.com/coder/coder/v2/cli/cliui"
"github.com/coder/coder/v2/coderd/httpapi"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/codersdk/agentsdk"
"github.com/coder/coder/v2/pty/ptytest"
"github.com/coder/coder/v2/testutil"
)
func TestGitAskpass(t *testing.T) {
t.Parallel()
t.Run("UsernameAndPassword", func(t *testing.T) {
t.Parallel()
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
httpapi.Write(context.Background(), w, http.StatusOK, agentsdk.ExternalAuthResponse{
Username: "something",
Password: "bananas",
})
}))
t.Cleanup(srv.Close)
url := srv.URL
inv, _ := clitest.New(t, "--agent-url", url, "Username for 'https://github.com':")
inv.Environ.Set("GIT_PREFIX", "/")
inv.Environ.Set("CODER_AGENT_TOKEN", "fake-token")
pty := ptytest.New(t)
inv.Stdout = pty.Output()
clitest.Start(t, inv)
pty.ExpectMatch("something")
inv, _ = clitest.New(t, "--agent-url", url, "Password for 'https://potato@github.com':")
inv.Environ.Set("GIT_PREFIX", "/")
inv.Environ.Set("CODER_AGENT_TOKEN", "fake-token")
pty = ptytest.New(t)
inv.Stdout = pty.Output()
clitest.Start(t, inv)
pty.ExpectMatch("bananas")
})
t.Run("NoHost", func(t *testing.T) {
t.Parallel()
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
httpapi.Write(context.Background(), w, http.StatusNotFound, codersdk.Response{
Message: "Nope!",
})
}))
t.Cleanup(srv.Close)
url := srv.URL
inv, _ := clitest.New(t, "--agent-url", url, "--no-open", "Username for 'https://github.com':")
inv.Environ.Set("GIT_PREFIX", "/")
inv.Environ.Set("CODER_AGENT_TOKEN", "fake-token")
pty := ptytest.New(t)
inv.Stderr = pty.Output()
err := inv.Run()
require.ErrorIs(t, err, cliui.ErrCanceled)
pty.ExpectMatch("Nope!")
})
t.Run("Poll", func(t *testing.T) {
t.Parallel()
ctx := testutil.Context(t, testutil.WaitShort)
resp := atomic.Pointer[agentsdk.ExternalAuthResponse]{}
resp.Store(&agentsdk.ExternalAuthResponse{
URL: "https://something.org",
})
poll := make(chan struct{}, 10)
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
val := resp.Load()
if r.URL.Query().Has("listen") {
poll <- struct{}{}
if val.URL != "" {
httpapi.Write(context.Background(), w, http.StatusInternalServerError, val)
return
}
}
httpapi.Write(context.Background(), w, http.StatusOK, val)
}))
t.Cleanup(srv.Close)
url := srv.URL
inv, _ := clitest.New(t, "--agent-url", url, "--no-open", "Username for 'https://github.com':")
inv.Environ.Set("GIT_PREFIX", "/")
inv.Environ.Set("CODER_AGENT_TOKEN", "fake-token")
stdout := ptytest.New(t)
inv.Stdout = stdout.Output()
stderr := ptytest.New(t)
inv.Stderr = stderr.Output()
go func() {
err := inv.Run()
assert.NoError(t, err)
}()
testutil.RequireReceive(ctx, t, poll)
stderr.ExpectMatch("Open the following URL to authenticate")
resp.Store(&agentsdk.ExternalAuthResponse{
Username: "username",
Password: "password",
})
stdout.ExpectMatch("username")
})
}