-
Notifications
You must be signed in to change notification settings - Fork 1.5k
fix: remove excess calls to prepareSQLFilter for workspace and template endpoints
#27248
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
Changes from all commits
4f4047a
da3d2f8
d7e9248
c55e672
db30bea
9ea186f
9fb8a13
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -53,6 +53,50 @@ import ( | |
| "github.com/coder/terraform-provider-coder/v2/provider" | ||
| ) | ||
|
|
||
| // TestWorkspacesListSingleAuthorizePrepare guards against reintroducing the | ||
| // redundant OPA partial evaluation the GET /api/v2/workspaces handler used to | ||
| // perform. The handler called AuthorizeSQLFilter to build a prepared | ||
| // ResourceWorkspace authorizer, but the dbauthz GetAuthorizedWorkspaces wrapper | ||
| // ignored it and re-prepared inside GetWorkspaces, so every request ran partial | ||
| // evaluation twice. Partial-evaluation cost scales with the number of | ||
| // organization-scoped roles the subject carries (see #21890), so the duplicate | ||
| // prepare doubled an already expensive operation. A single list request must | ||
| // prepare the ResourceWorkspace authorizer exactly once. | ||
| func TestWorkspacesListSingleAuthorizePrepare(t *testing.T) { | ||
|
cstyan marked this conversation as resolved.
|
||
| t.Parallel() | ||
|
|
||
| authz := &coderdtest.RecordingAuthorizer{Wrapped: rbac.NewStrictCachingAuthorizer(prometheus.NewRegistry())} | ||
| client, db := coderdtest.NewWithDatabase(t, &coderdtest.Options{ | ||
| Authorizer: authz, | ||
| }) | ||
| owner := coderdtest.CreateFirstUser(t, client) | ||
|
|
||
| // Seed one workspace directly in the database. The authorization path the | ||
| // handler takes does not depend on how the workspace was built, so dbfake | ||
| // avoids the cost of a provisioner and real build. | ||
| dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{ | ||
| OwnerID: owner.UserID, | ||
| OrganizationID: owner.OrganizationID, | ||
| }).Do() | ||
|
|
||
| ctx := testutil.Context(t, testutil.WaitLong) | ||
|
|
||
| // Reset immediately before the measured request so setup prepares are | ||
| // excluded. Counts are keyed by subject ID, so background work under system | ||
| // subjects is ignored. | ||
| authz.Reset() | ||
| res, err := client.Workspaces(ctx, codersdk.WorkspaceFilter{}) | ||
| require.NoError(t, err) | ||
| require.Len(t, res.Workspaces, 1) | ||
|
Contributor
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. Note [CRF-10] The exact This is guaranteed today by three facts outside the test: background reconcilers use system subjects, the default
|
||
|
|
||
| // The exact count of 1 relies on this being the only request issued under the | ||
| // owner subject between the reset and this assertion, which holds because the | ||
| // test makes a single serial call. | ||
| count := authz.PrepareCount(owner.UserID.String(), policy.ActionRead, rbac.ResourceWorkspace.Type) | ||
| require.Equal(t, 1, count, | ||
| "GET /workspaces must prepare the ResourceWorkspace authorizer exactly once; a higher count means a redundant partial evaluation was reintroduced") | ||
| } | ||
|
|
||
| func TestWorkspace(t *testing.T) { | ||
| t.Parallel() | ||
|
|
||
|
|
||
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.
👍