fix: Protect codersdk.Client SessionToken so it can be updated (#4965)

This feature is used by the coder agent to exchange a new token. By
protecting the SessionToken via mutex we ensure there are no data races
when accessing it.
This commit is contained in:
Mathias Fredriksson
2022-11-09 15:31:24 +02:00
committed by GitHub
parent 8cadb33396
commit 26ab0d37c1
25 changed files with 82 additions and 64 deletions

View File

@ -360,7 +360,7 @@ func CreateFirstUser(t *testing.T, client *codersdk.Client) codersdk.CreateFirst
Password: FirstUserParams.Password,
})
require.NoError(t, err)
client.SessionToken = login.SessionToken
client.SetSessionToken(login.SessionToken)
return resp
}
@ -400,7 +400,7 @@ func createAnotherUserRetry(t *testing.T, client *codersdk.Client, organizationI
require.NoError(t, err)
other := codersdk.New(client.URL)
other.SessionToken = login.SessionToken
other.SetSessionToken(login.SessionToken)
if len(roles) > 0 {
// Find the roles for the org vs the site wide roles

View File

@ -134,7 +134,7 @@ func TestAgentGitSSHKey(t *testing.T) {
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
agentClient := codersdk.New(client.URL)
agentClient.SessionToken = authToken
agentClient.SetSessionToken(authToken)
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
defer cancel()

View File

@ -601,7 +601,7 @@ func TestTemplateMetrics(t *testing.T) {
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
agentClient := codersdk.New(client.URL)
agentClient.SessionToken = authToken
agentClient.SetSessionToken(authToken)
agentCloser := agent.New(agent.Options{
Logger: slogtest.Make(t, nil),
Client: agentClient,

View File

@ -275,7 +275,7 @@ func TestUserOAuth2Github(t *testing.T) {
resp := oauth2Callback(t, client)
require.Equal(t, http.StatusTemporaryRedirect, resp.StatusCode)
client.SessionToken = authCookieValue(resp.Cookies())
client.SetSessionToken(authCookieValue(resp.Cookies()))
user, err := client.User(context.Background(), "me")
require.NoError(t, err)
require.Equal(t, "kyle@coder.com", user.Email)
@ -485,14 +485,14 @@ func TestUserOIDC(t *testing.T) {
ctx, _ := testutil.Context(t)
if tc.Username != "" {
client.SessionToken = authCookieValue(resp.Cookies())
client.SetSessionToken(authCookieValue(resp.Cookies()))
user, err := client.User(ctx, "me")
require.NoError(t, err)
require.Equal(t, tc.Username, user.Username)
}
if tc.AvatarURL != "" {
client.SessionToken = authCookieValue(resp.Cookies())
client.SetSessionToken(authCookieValue(resp.Cookies()))
user, err := client.User(ctx, "me")
require.NoError(t, err)
require.Equal(t, tc.AvatarURL, user.AvatarURL)
@ -520,7 +520,7 @@ func TestUserOIDC(t *testing.T) {
ctx, _ := testutil.Context(t)
client.SessionToken = authCookieValue(resp.Cookies())
client.SetSessionToken(authCookieValue(resp.Cookies()))
user, err := client.User(ctx, "me")
require.NoError(t, err)
require.Equal(t, "jon", user.Username)
@ -534,7 +534,7 @@ func TestUserOIDC(t *testing.T) {
resp = oidcCallback(t, client, code)
assert.Equal(t, http.StatusTemporaryRedirect, resp.StatusCode)
client.SessionToken = authCookieValue(resp.Cookies())
client.SetSessionToken(authCookieValue(resp.Cookies()))
user, err = client.User(ctx, "me")
require.NoError(t, err)
require.True(t, strings.HasPrefix(user.Username, "jon-"), "username %q should have prefix %q", user.Username, "jon-")

View File

@ -280,7 +280,7 @@ func TestPostLogin(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
defer cancel()
split := strings.Split(client.SessionToken, "-")
split := strings.Split(client.SessionToken(), "-")
key, err := client.GetAPIKey(ctx, admin.UserID.String(), split[0])
require.NoError(t, err, "fetch login key")
require.Equal(t, int64(86400), key.LifetimeSeconds, "default should be 86400")
@ -356,7 +356,7 @@ func TestPostLogout(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
defer cancel()
keyID := strings.Split(client.SessionToken, "-")[0]
keyID := strings.Split(client.SessionToken(), "-")[0]
apiKey, err := client.GetAPIKey(ctx, admin.UserID.String(), keyID)
require.NoError(t, err)
require.Equal(t, keyID, apiKey.ID, "API key should exist in the database")
@ -676,7 +676,7 @@ func TestUpdateUserPassword(t *testing.T) {
})
require.NoError(t, err)
client.SessionToken = resp.SessionToken
client.SetSessionToken(resp.SessionToken)
// Trying to get an API key should fail since all keys are deleted
// on password change.
@ -1359,7 +1359,7 @@ func TestWorkspacesByUser(t *testing.T) {
require.NoError(t, err)
newUserClient := codersdk.New(client.URL)
newUserClient.SessionToken = auth.SessionToken
newUserClient.SetSessionToken(auth.SessionToken)
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)

View File

@ -113,7 +113,7 @@ func TestWorkspaceAgentListen(t *testing.T) {
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
agentClient := codersdk.New(client.URL)
agentClient.SessionToken = authToken
agentClient.SetSessionToken(authToken)
agentCloser := agent.New(agent.Options{
Client: agentClient,
Logger: slogtest.Make(t, nil).Named("agent").Leveled(slog.LevelDebug),
@ -205,7 +205,7 @@ func TestWorkspaceAgentListen(t *testing.T) {
coderdtest.AwaitWorkspaceBuildJob(t, client, stopBuild.ID)
agentClient := codersdk.New(client.URL)
agentClient.SessionToken = authToken
agentClient.SetSessionToken(authToken)
_, err = agentClient.ListenWorkspaceAgent(ctx)
require.Error(t, err)
@ -245,7 +245,7 @@ func TestWorkspaceAgentTailnet(t *testing.T) {
daemonCloser.Close()
agentClient := codersdk.New(client.URL)
agentClient.SessionToken = authToken
agentClient.SetSessionToken(authToken)
agentCloser := agent.New(agent.Options{
Client: agentClient,
Logger: slogtest.Make(t, nil).Named("agent").Leveled(slog.LevelDebug),
@ -311,7 +311,7 @@ func TestWorkspaceAgentPTY(t *testing.T) {
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
agentClient := codersdk.New(client.URL)
agentClient.SessionToken = authToken
agentClient.SetSessionToken(authToken)
agentCloser := agent.New(agent.Options{
Client: agentClient,
Logger: slogtest.Make(t, nil).Named("agent").Leveled(slog.LevelDebug),
@ -408,7 +408,7 @@ func TestWorkspaceAgentListeningPorts(t *testing.T) {
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
agentClient := codersdk.New(client.URL)
agentClient.SessionToken = authToken
agentClient.SetSessionToken(authToken)
agentCloser := agent.New(agent.Options{
Client: agentClient,
Logger: slogtest.Make(t, nil).Named("agent").Leveled(slog.LevelDebug),
@ -670,7 +670,7 @@ func TestWorkspaceAgentAppHealth(t *testing.T) {
defer cancel()
agentClient := codersdk.New(client.URL)
agentClient.SessionToken = authToken
agentClient.SetSessionToken(authToken)
metadata, err := agentClient.WorkspaceAgentMetadata(ctx)
require.NoError(t, err)
@ -754,7 +754,7 @@ func TestWorkspaceAgentsGitAuth(t *testing.T) {
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
agentClient := codersdk.New(client.URL)
agentClient.SessionToken = authToken
agentClient.SetSessionToken(authToken)
_, err := agentClient.WorkspaceAgentGitAuth(context.Background(), "github.com", false)
var apiError *codersdk.Error
require.ErrorAs(t, err, &apiError)
@ -799,7 +799,7 @@ func TestWorkspaceAgentsGitAuth(t *testing.T) {
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
agentClient := codersdk.New(client.URL)
agentClient.SessionToken = authToken
agentClient.SetSessionToken(authToken)
token, err := agentClient.WorkspaceAgentGitAuth(context.Background(), "github.com/asd/asd", false)
require.NoError(t, err)
require.True(t, strings.HasSuffix(token.URL, fmt.Sprintf("/gitauth/%s", "github")))
@ -879,7 +879,7 @@ func TestWorkspaceAgentsGitAuth(t *testing.T) {
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
agentClient := codersdk.New(client.URL)
agentClient.SessionToken = authToken
agentClient.SetSessionToken(authToken)
token, err := agentClient.WorkspaceAgentGitAuth(context.Background(), "github.com/asd/asd", false)
require.NoError(t, err)
@ -920,7 +920,7 @@ func gitAuthCallback(t *testing.T, id string, client *codersdk.Client) *http.Res
})
req.AddCookie(&http.Cookie{
Name: codersdk.SessionTokenKey,
Value: client.SessionToken,
Value: client.SessionToken(),
})
res, err := client.HTTPClient.Do(req)
require.NoError(t, err)

View File

@ -197,7 +197,7 @@ func createWorkspaceWithApps(t *testing.T, client *codersdk.Client, orgID uuid.U
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
agentClient := codersdk.New(client.URL)
agentClient.SessionToken = authToken
agentClient.SetSessionToken(authToken)
if appHost != "" {
metadata, err := agentClient.WorkspaceAgentMetadata(context.Background())
require.NoError(t, err)
@ -350,7 +350,7 @@ func TestWorkspaceApplicationAuth(t *testing.T) {
// Get the current user and API key.
user, err := client.User(ctx, codersdk.Me)
require.NoError(t, err)
currentAPIKey, err := client.GetAPIKey(ctx, firstUser.UserID.String(), strings.Split(client.SessionToken, "-")[0])
currentAPIKey, err := client.GetAPIKey(ctx, firstUser.UserID.String(), strings.Split(client.SessionToken(), "-")[0])
require.NoError(t, err)
// Try to load the application without authentication.
@ -418,7 +418,7 @@ func TestWorkspaceApplicationAuth(t *testing.T) {
// Verify the API key permissions
appClient := codersdk.New(client.URL)
appClient.SessionToken = apiKey
appClient.SetSessionToken(apiKey)
appClient.HTTPClient.CheckRedirect = client.HTTPClient.CheckRedirect
appClient.HTTPClient.Transport = client.HTTPClient.Transport
@ -893,7 +893,7 @@ func TestAppSharing(t *testing.T) {
Password: password,
})
require.NoError(t, err)
clientInOtherOrg.SessionToken = loginRes.SessionToken
clientInOtherOrg.SetSessionToken(loginRes.SessionToken)
clientInOtherOrg.HTTPClient.CheckRedirect = func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
}
@ -916,14 +916,14 @@ func TestAppSharing(t *testing.T) {
// If the client has a session token, we also want to check that a
// scoped key works.
clients := []*codersdk.Client{client}
if client.SessionToken != "" {
if client.SessionToken() != "" {
token, err := client.CreateToken(ctx, codersdk.Me, codersdk.CreateTokenRequest{
Scope: codersdk.APIKeyScopeApplicationConnect,
})
require.NoError(t, err)
scopedClient := codersdk.New(client.URL)
scopedClient.SessionToken = token.Key
scopedClient.SetSessionToken(token.Key)
scopedClient.HTTPClient.CheckRedirect = client.HTTPClient.CheckRedirect
clients = append(clients, scopedClient)

View File

@ -1400,7 +1400,7 @@ func TestWorkspaceWatcher(t *testing.T) {
wait()
agentClient := codersdk.New(client.URL)
agentClient.SessionToken = authToken
agentClient.SetSessionToken(authToken)
agentCloser := agent.New(agent.Options{
Client: agentClient,
Logger: slogtest.Make(t, nil).Named("agent").Leveled(slog.LevelDebug),