Skip to content

Commit e234839

Browse files
authored
[fga] prebuild access (#18560)
1 parent f743245 commit e234839

File tree

2 files changed

+38
-8
lines changed

2 files changed

+38
-8
lines changed

components/server/src/workspace/gitpod-server-impl.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -530,7 +530,23 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
530530

531531
private forwardInstanceUpdateToClient(ctx: TraceContext, instance: WorkspaceInstance) {
532532
// gpl: We decided against tracing updates here, because it create far too much noise (cmp. history)
533-
this.client?.onInstanceUpdate(this.censorInstance(instance));
533+
if (this.userID) {
534+
this.workspaceService
535+
.getWorkspace(this.userID, instance.workspaceId)
536+
.then((ws) => {
537+
this.client?.onInstanceUpdate(this.censorInstance(instance));
538+
})
539+
.catch((err) => {
540+
if (
541+
ApplicationError.hasErrorCode(err) &&
542+
(err.code === ErrorCodes.NOT_FOUND || err.code === ErrorCodes.PERMISSION_DENIED)
543+
) {
544+
// ignore
545+
} else {
546+
log.error("error forwarding instance update to client", err);
547+
}
548+
});
549+
}
534550
}
535551

536552
setClient(ctx: TraceContext, client: GitpodApiClient | undefined): void {
@@ -1197,12 +1213,16 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
11971213
public async isPrebuildDone(ctx: TraceContext, pwsId: string): Promise<boolean> {
11981214
traceAPIParams(ctx, { pwsId });
11991215

1216+
const user = await this.checkUser("isPrebuildDone");
1217+
12001218
const pws = await this.workspaceDb.trace(ctx).findPrebuildByID(pwsId);
1201-
if (!pws) {
1219+
if (!pws || !pws.projectId) {
12021220
// there is no prebuild - that's as good one being done
12031221
return true;
12041222
}
12051223

1224+
await this.auth.checkPermissionOnProject(user.id, "read_prebuild", pws.projectId);
1225+
12061226
return PrebuiltWorkspace.isDone(pws);
12071227
}
12081228

@@ -1486,6 +1506,7 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
14861506

14871507
const project = await this.projectsService.getProject(user.id, projectId);
14881508
await this.guardProjectOperation(user, projectId, "get");
1509+
await this.auth.checkPermissionOnProject(user.id, "read_prebuild", projectId);
14891510

14901511
const events = await this.projectsService.getPrebuildEvents(user.id, project.cloneUrl);
14911512
return events;

components/server/src/workspace/workspace-service.ts

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -134,9 +134,14 @@ export class WorkspaceService {
134134

135135
// Internal method for allowing for additional DBs to be passed in
136136
private async doGetWorkspace(userId: string, workspaceId: string, db: WorkspaceDB = this.db): Promise<Workspace> {
137-
await this.auth.checkPermissionOnWorkspace(userId, "access", workspaceId);
138-
139137
const workspace = await db.findById(workspaceId);
138+
139+
if (workspace?.type === "prebuild" && workspace.projectId) {
140+
await this.auth.checkPermissionOnProject(userId, "read_prebuild", workspace.projectId);
141+
} else {
142+
await this.auth.checkPermissionOnWorkspace(userId, "access", workspaceId);
143+
}
144+
140145
// TODO(gpl) We might want to add || !!workspace.softDeleted here in the future, but we were unsure how that would affect existing clients
141146
// In order to reduce risk, we leave it for a future changeset.
142147
if (!workspace || workspace.deleted) {
@@ -678,9 +683,13 @@ export class WorkspaceService {
678683
): Promise<HeadlessLogUrls> {
679684
const workspace = await this.db.findByInstanceId(instanceId);
680685
if (!workspace) {
681-
throw new ApplicationError(ErrorCodes.NOT_FOUND, `Workspace for instanceId ${instanceId} not found`);
686+
throw new ApplicationError(ErrorCodes.NOT_FOUND, `Prebuild for instanceId ${instanceId} not found`);
682687
}
683-
await this.auth.checkPermissionOnWorkspace(userId, "access", workspace.id);
688+
if (workspace.type !== "prebuild" || !workspace.projectId) {
689+
throw new ApplicationError(ErrorCodes.CONFLICT, `Workspace is not a prebuild`);
690+
}
691+
692+
await this.auth.checkPermissionOnProject(userId, "read_prebuild", workspace.projectId);
684693

685694
const wsiPromise = this.db.findInstanceById(instanceId);
686695
await check(workspace);
@@ -703,8 +712,8 @@ export class WorkspaceService {
703712
workspaceId: string,
704713
client: Pick<GitpodClient, "onWorkspaceImageBuildLogs">,
705714
): Promise<void> {
706-
await this.auth.checkPermissionOnWorkspace(userId, "access", workspaceId);
707-
715+
// check access
716+
await this.getWorkspace(userId, workspaceId);
708717
const logCtx: LogContext = { userId, workspaceId };
709718
let instance = await this.db.findCurrentInstance(workspaceId);
710719
if (!instance || instance.status.phase === "stopped") {

0 commit comments

Comments
 (0)