-
Notifications
You must be signed in to change notification settings - Fork 1.3k
[fga] Workspace: create, get, stop and delete #18403
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
Conversation
499141f
to
edc7282
Compare
@@ -77,21 +77,18 @@ export class PrebuildManager { | |||
const results: Promise<any>[] = []; | |||
for (const prebuild of prebuilds) { | |||
try { | |||
for (const instance of prebuild.instances) { |
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.
No clue why we would cycle over instances here before. I could imagine this was to mitigate some weird behavior we had in the past. 🤔
We only every have one WorkspaceInstance for every Workspace of type = 'prebuilt'. And even if we'd change that in the future: There is always ever one WorkspaceInstance "running" for each given Workspace. 🤷
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.
Also, I just noticed that same code paths did not emit ApplicationError
but just Error
instead. But I don't expect big issues there.
await this.auth.checkPermissionOnWorkspace(userId, "access", workspaceId); | ||
|
||
const workspace = await this.db.findById(workspaceId); | ||
if (!workspace || !!workspace.softDeleted || workspace.deleted) { |
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.
THIS is the only thing that should have changed in comparison to the old code: Before, we would ignore softDeleted
and workspace.deleted
, and simply return the workspace.
Of course I reviewed all (transient) call sites and they should be fine, but I might have missed sth.
I'm torn here: If anybody raises there hand, I'm happy to add a feature flag here, just to reduce the risk of rolling this change out. 👍
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.
I would have been more concerned about the contract to throw NOT_FOUND instead of undefined
but since you only replaced usages of GitpodServerImpl#internalGetWorkspace
which has the same contract I believe this is good.
That said, we will want to call this for adminGetWorkspace(s)
as well, which should return deleted workspaces.
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.
Yes, I thought I can postpone that problem, but that might not mamke sense. Let me check if we can remove softDeleted here.
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.
wrong thread, removed
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.
I checked again, and before, only startWorkspace checked for softDeleted. To keep the change in this PR as low as possible, I removed that check here.
I would leave it and monitor if I was there on Monday, but as I'm not, I really don't want to add extra noise to the point of these changes (FGA). 👍
relation owner: user | ||
|
||
// Whether a user can access a workspace (with an IDE) | ||
//+ (hasAccessToRepository && isPrebuild) + everyoneIfIsShared |
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.
This is missing, and will be added with a follow-up PR.
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.
We just discussed with Sven and Anton: This will break "prebuild access" (for everybody except owners) and "workspace sharing" everywhere we have the FGA feature flag enabled, namely preview environments.
edc7282
to
8da43bb
Compare
Going to rebase this now to resolve the conflicts, and align with the authorizer changes. |
8da43bb
to
72ab824
Compare
- createWorkspace - getWorkspace - stopWorkspace - deleteWorkspace - hardDeleteWorkspace
72ab824
to
a1e5387
Compare
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.
Looks all very good! Just a few comments.
@@ -70,7 +72,7 @@ export class WorkspaceGarbageCollector implements Job { | |||
); | |||
const afterSelect = new Date(); | |||
const deletes = await Promise.all( | |||
workspaces.map((ws) => this.deletionService.softDeleteWorkspace({ span }, ws, "gc")), | |||
workspaces.map((ws) => this.workspaceService.deleteWorkspace(ws.ownerId, ws.id, "gc")), // TODO(gpl) This should be a system user/service account instead of ws owner |
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.
This would work, but is not correct as this is not triggered by the owner but by the system.
In another place (UserService#findById
) I have used undefined
as the userId to indicate the request is coming from the system.
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.
Ok, I was not aware that we have a way (undefined
) to express "the system does it".
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.
Yeah, I'm not particularly satisfied with that choice for the protocol. But I liked it better than introducing a system ID or anything else I could think of. 🤷
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.
@svenefftinge Could you shoot me a link to an example? I can't find one on main atm, and wonder if you meant setting all userId types to string | undefined
? 🤔
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.
await this.orgService.addOrUpdateMember(undefined, organizationId, user.id, "member", ctx); |
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.
After looking at the change, I really thing we should make this a separate argument, instead of overriding userId for the security reasons. Let's discuss in sync. 👍
await this.auth.checkPermissionOnWorkspace(userId, "access", workspaceId); | ||
|
||
const workspace = await this.db.findById(workspaceId); | ||
if (!workspace || !!workspace.softDeleted || workspace.deleted) { |
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.
I would have been more concerned about the contract to throw NOT_FOUND instead of undefined
but since you only replaced usages of GitpodServerImpl#internalGetWorkspace
which has the same contract I believe this is good.
That said, we will want to call this for adminGetWorkspace(s)
as well, which should return deleted workspaces.
/unhold |
Description
This PR introduces a first version of a
WorkspaceService
to encapsulate the CRUD operations on Workspaces, and do authorization with FGA/SpiceDB. It currently has the following methods:There is a lot of code-movement happening, so here some highlights interesting for reviewers:
WorkspaceService
(specifically the places where we check and add/remove relations)internalGetWorkspace
Future work:
RelationshipUpdate
for addinguser -> workspace.owner
andorg -> workspace.org
WorkspaceDeletionService
intoWorkspaceGC
(follow up PR)WorkspaceFactory
by extracting all external calls (ConfigProvider
)GitpodServerImpl.createWorkspace
API. I did not include this here because:Summary generated by Copilot
🤖 Generated by Copilot at 75c3415
This pull request introduces a centralized permissions feature for workspaces and organizations, using Spicedb as the backend. It adds a new WorkspaceService class to handle workspace operations, and updates the Authorizer, PrebuildManager, and GitpodServerImpl classes to use it. It also updates the schema, code generation, and tests to support the new feature, and fixes some bugs related to tracing and testing.
Related Issue(s)
Fixes EXP-317, EXP-320, EXP-323, EXP-322
How to test
Documentation
Preview status
Gitpod was successfully deployed to your preview environment.
Build Options
Build
Run the build with werft instead of GHA
Run Leeway with
--dont-test
Publish
Installer
Add desired feature flags to the end of the line above, space separated
Preview Environment / Integration Tests
If enabled this will build
install/preview
If enabled this will create the environment on GCE infra
Valid options are
all
,workspace
,webapp
,ide
,jetbrains
,vscode
,ssh
. If enabled,with-preview
andwith-large-vm
will be enabled./hold