Skip to content

Commit

Permalink
[server] Use RequestContext.subjectId for authorization (#19091)
Browse files Browse the repository at this point in the history
  • Loading branch information
geropl authored Nov 24, 2023
1 parent d5c978a commit b6fa451
Show file tree
Hide file tree
Showing 17 changed files with 296 additions and 167 deletions.
2 changes: 1 addition & 1 deletion components/server/src/api/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ export class API {
}

private async ensureFgaMigration(subjectId: SubjectId): Promise<void> {
const fgaChecksEnabled = await isFgaChecksEnabled(subjectId.userId());
const fgaChecksEnabled = await isFgaChecksEnabled(subjectId);
if (!fgaChecksEnabled) {
throw new ConnectError("unauthorized", Code.PermissionDenied);
}
Expand Down
50 changes: 31 additions & 19 deletions components/server/src/api/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,11 @@ import {
} from "@gitpod/public-api/lib/gitpod/experimental/v1/user_pb";
import { UserAuthentication } from "../user/user-authentication";
import { WorkspaceService } from "../workspace/workspace-service";
import { SYSTEM_USER } from "../authorization/authorizer";
import { validate } from "uuid";
import { log } from "@gitpod/gitpod-protocol/lib/util/logging";
import { StopWorkspacePolicy } from "@gitpod/ws-manager/lib";
import { SYSTEM_USER, SYSTEM_USER_ID } from "../authorization/authorizer";
import { runWithRequestContext } from "../util/request-context";

@injectable()
export class APIUserService implements ServiceImpl<typeof UserServiceInterface> {
Expand Down Expand Up @@ -59,6 +60,7 @@ export class APIUserService implements ServiceImpl<typeof UserServiceInterface>
throw new ConnectError("unimplemented", Code.Unimplemented);
}

// INTERNAL ONLY
public async blockUser(req: BlockUserRequest): Promise<BlockUserResponse> {
const { userId, reason } = req;

Expand All @@ -74,27 +76,37 @@ export class APIUserService implements ServiceImpl<typeof UserServiceInterface>

// TODO: Once connect-node supports middlewares, lift the tracing into the middleware.
const trace = {};
// TODO for now we use SYSTEM_USER, since it is only called by internal componenets like usage
// TODO(gpl) for now we use SYSTEM_USER, since it is only called by internal componenets like usage
// and not exposed publically, but there should be better way to get an authenticated user
await this.userService.blockUser(SYSTEM_USER, userId, true);
log.info(`Blocked user ${userId}.`, {
userId,
reason,
});
await runWithRequestContext(
{
requestKind: "user-service",
requestMethod: "blockUser",
signal: new AbortController().signal,
subjectId: SYSTEM_USER,
},
async () => {
await this.userService.blockUser(SYSTEM_USER_ID, userId, true);
log.info(`Blocked user ${userId}.`, {
userId,
reason,
});

const stoppedWorkspaces = await this.workspaceService.stopRunningWorkspacesForUser(
trace,
SYSTEM_USER,
userId,
reason,
StopWorkspacePolicy.IMMEDIATELY,
);
const stoppedWorkspaces = await this.workspaceService.stopRunningWorkspacesForUser(
trace,
SYSTEM_USER_ID,
userId,
reason,
StopWorkspacePolicy.IMMEDIATELY,
);

log.info(`Stopped ${stoppedWorkspaces.length} workspaces in response to BlockUser.`, {
userId,
reason,
workspaceIds: stoppedWorkspaces.map((w) => w.id),
});
log.info(`Stopped ${stoppedWorkspaces.length} workspaces in response to BlockUser.`, {
userId,
reason,
workspaceIds: stoppedWorkspaces.map((w) => w.id),
});
},
);

return new BlockUserResponse();
}
Expand Down
13 changes: 13 additions & 0 deletions components/server/src/auth/subject-id.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,16 @@ export class SubjectId {
* Interface type meant for backwards compatibility
*/
export type Subject = string | SubjectId;
export namespace Subject {
export function toId(subject: Subject): SubjectId {
if (SubjectId.is(subject)) {
return subject;
}
if (typeof subject === "string") {
// either a subjectId string or a userId string
const parsed = SubjectId.parse(subject);
return parsed || SubjectId.fromUserId(subject);
}
throw new Error("Invalid Subject");
}
}
Loading

0 comments on commit b6fa451

Please sign in to comment.