mirror of
https://github.com/coder/coder.git
synced 2025-07-03 16:13:58 +00:00
fix: relax csrf to exclude path based apps (#11430)
* fix: relax csrf to exclude path based apps * add unit test to verify path based apps are not CSRF blocked
This commit is contained in:
@ -3,6 +3,7 @@ package coderd_test
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/netip"
|
||||
@ -21,6 +22,9 @@ import (
|
||||
|
||||
"cdr.dev/slog"
|
||||
"cdr.dev/slog/sloggers/slogtest"
|
||||
"github.com/coder/coder/v2/coderd/database"
|
||||
"github.com/coder/coder/v2/coderd/database/dbfake"
|
||||
"github.com/coder/coder/v2/provisionersdk/proto"
|
||||
|
||||
"github.com/coder/coder/v2/agent/agenttest"
|
||||
"github.com/coder/coder/v2/buildinfo"
|
||||
@ -315,3 +319,63 @@ func TestSwagger(t *testing.T) {
|
||||
require.Equal(t, "<pre>\n</pre>\n", string(body))
|
||||
})
|
||||
}
|
||||
|
||||
func TestCSRFExempt(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// This test build a workspace with an agent and an app. The app is not
|
||||
// a real http server, so it will fail to serve requests. We just want
|
||||
// to make sure the failure is not a CSRF failure, as path based
|
||||
// apps should be exempt.
|
||||
t.Run("PathBasedApp", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
client, _, api := coderdtest.NewWithAPI(t, nil)
|
||||
first := coderdtest.CreateFirstUser(t, client)
|
||||
owner, err := client.User(context.Background(), "me")
|
||||
require.NoError(t, err)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitMedium)
|
||||
defer cancel()
|
||||
|
||||
// Create a workspace.
|
||||
const agentSlug = "james"
|
||||
const appSlug = "web"
|
||||
wrk := dbfake.WorkspaceBuild(t, api.Database, database.Workspace{
|
||||
OwnerID: owner.ID,
|
||||
OrganizationID: first.OrganizationID,
|
||||
}).
|
||||
WithAgent(func(agents []*proto.Agent) []*proto.Agent {
|
||||
agents[0].Name = agentSlug
|
||||
agents[0].Apps = []*proto.App{{
|
||||
Slug: appSlug,
|
||||
DisplayName: appSlug,
|
||||
Subdomain: false,
|
||||
Url: "/",
|
||||
}}
|
||||
|
||||
return agents
|
||||
}).
|
||||
Do()
|
||||
|
||||
u := client.URL.JoinPath(fmt.Sprintf("/@%s/%s.%s/apps/%s", owner.Username, wrk.Workspace.Name, agentSlug, appSlug)).String()
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, u, nil)
|
||||
req.AddCookie(&http.Cookie{
|
||||
Name: codersdk.SessionTokenCookie,
|
||||
Value: client.SessionToken(),
|
||||
Path: "/",
|
||||
Domain: client.URL.String(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
resp, err := client.HTTPClient.Do(req)
|
||||
require.NoError(t, err)
|
||||
data, _ := io.ReadAll(resp.Body)
|
||||
_ = resp.Body.Close()
|
||||
|
||||
// A StatusBadGateway means Coderd tried to proxy to the agent and failed because the agent
|
||||
// was not there. This means CSRF did not block the app request, which is what we want.
|
||||
require.Equal(t, http.StatusBadGateway, resp.StatusCode, "status code 500 is CSRF failure")
|
||||
require.NotContains(t, string(data), "CSRF")
|
||||
})
|
||||
}
|
||||
|
Reference in New Issue
Block a user