(t *testing.T)
| 351 | } |
| 352 | |
| 353 | func TestCSRFExempt(t *testing.T) { |
| 354 | t.Parallel() |
| 355 | |
| 356 | // This test build a workspace with an agent and an app. The app is not |
| 357 | // a real http server, so it will fail to serve requests. We just want |
| 358 | // to make sure the failure is not a CSRF failure, as path based |
| 359 | // apps should be exempt. |
| 360 | t.Run("PathBasedApp", func(t *testing.T) { |
| 361 | t.Parallel() |
| 362 | |
| 363 | client, _, api := coderdtest.NewWithAPI(t, nil) |
| 364 | first := coderdtest.CreateFirstUser(t, client) |
| 365 | owner, err := client.User(context.Background(), "me") |
| 366 | require.NoError(t, err) |
| 367 | |
| 368 | ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitMedium) |
| 369 | defer cancel() |
| 370 | |
| 371 | // Create a workspace. |
| 372 | const agentSlug = "james" |
| 373 | const appSlug = "web" |
| 374 | wrk := dbfake.WorkspaceBuild(t, api.Database, database.WorkspaceTable{ |
| 375 | OwnerID: owner.ID, |
| 376 | OrganizationID: first.OrganizationID, |
| 377 | }). |
| 378 | WithAgent(func(agents []*proto.Agent) []*proto.Agent { |
| 379 | agents[0].Name = agentSlug |
| 380 | agents[0].Apps = []*proto.App{{ |
| 381 | Slug: appSlug, |
| 382 | DisplayName: appSlug, |
| 383 | Subdomain: false, |
| 384 | Url: "/", |
| 385 | }} |
| 386 | |
| 387 | return agents |
| 388 | }). |
| 389 | Do() |
| 390 | |
| 391 | u := client.URL.JoinPath(fmt.Sprintf("/@%s/%s.%s/apps/%s", owner.Username, wrk.Workspace.Name, agentSlug, appSlug)).String() |
| 392 | req, err := http.NewRequestWithContext(ctx, http.MethodPost, u, nil) |
| 393 | req.AddCookie(&http.Cookie{ |
| 394 | Name: codersdk.SessionTokenCookie, |
| 395 | Value: client.SessionToken(), |
| 396 | Path: "/", |
| 397 | Domain: client.URL.String(), |
| 398 | }) |
| 399 | require.NoError(t, err) |
| 400 | |
| 401 | resp, err := client.HTTPClient.Do(req) |
| 402 | require.NoError(t, err) |
| 403 | data, _ := io.ReadAll(resp.Body) |
| 404 | _ = resp.Body.Close() |
| 405 | |
| 406 | // A StatusNotFound means Coderd tried to proxy to the agent and failed because the agent |
| 407 | // was not there. This means CSRF did not block the app request, which is what we want. |
| 408 | require.Equal(t, http.StatusNotFound, resp.StatusCode, "status code 500 is CSRF failure") |
| 409 | require.NotContains(t, string(data), "CSRF") |
| 410 | }) |
nothing calls this directly
no test coverage detected