Skip to content

Commit 08b7539

Browse files
committed
[server] Cleanup Organization RPCs authorization checks
1 parent 3077ef5 commit 08b7539

File tree

2 files changed

+27
-54
lines changed

2 files changed

+27
-54
lines changed

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

+5-5
Original file line numberDiff line numberDiff line change
@@ -2119,7 +2119,7 @@ export class GitpodServerEEImpl extends GitpodServerImpl {
21192119
}
21202120
let team: Team | undefined;
21212121
if (attrId.kind === "team") {
2122-
team = await this.guardTeamOperation(attrId.teamId, "update");
2122+
team = (await this.guardTeamOperation(attrId.teamId, "update")).team;
21232123
await this.ensureStripeApiIsAllowed({ team });
21242124
} else {
21252125
if (attrId.userId !== user.id) {
@@ -2141,7 +2141,7 @@ export class GitpodServerEEImpl extends GitpodServerImpl {
21412141
}
21422142
let team: Team | undefined;
21432143
if (attrId.kind === "team") {
2144-
team = await this.guardTeamOperation(attrId.teamId, "update");
2144+
team = (await this.guardTeamOperation(attrId.teamId, "update")).team;
21452145
await this.ensureStripeApiIsAllowed({ team });
21462146
} else {
21472147
if (attrId.userId !== user.id) {
@@ -2211,7 +2211,7 @@ export class GitpodServerEEImpl extends GitpodServerImpl {
22112211
let team: Team | undefined;
22122212
try {
22132213
if (attrId.kind === "team") {
2214-
team = await this.guardTeamOperation(attrId.teamId, "update");
2214+
team = (await this.guardTeamOperation(attrId.teamId, "update")).team;
22152215
await this.ensureStripeApiIsAllowed({ team });
22162216
} else {
22172217
await this.ensureStripeApiIsAllowed({ user });
@@ -2257,7 +2257,7 @@ export class GitpodServerEEImpl extends GitpodServerImpl {
22572257
if (attrId.kind === "user") {
22582258
await this.ensureStripeApiIsAllowed({ user });
22592259
} else if (attrId.kind === "team") {
2260-
const team = await this.guardTeamOperation(attrId.teamId, "update");
2260+
const team = (await this.guardTeamOperation(attrId.teamId, "update")).team;
22612261
await this.ensureStripeApiIsAllowed({ team });
22622262
returnUrl = this.config.hostUrl
22632263
.with(() => ({ pathname: `/org-billing`, search: `org=${team.id}` }))
@@ -2493,7 +2493,7 @@ export class GitpodServerEEImpl extends GitpodServerImpl {
24932493
traceAPIParams(ctx, { teamId });
24942494

24952495
this.checkAndBlockUser("getBillingModeForTeam");
2496-
const team = await this.guardTeamOperation(teamId, "get");
2496+
const { team } = await this.guardTeamOperation(teamId, "get");
24972497

24982498
return this.billingModes.getBillingModeForTeam(team, new Date());
24992499
}

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

+22-49
Original file line numberDiff line numberDiff line change
@@ -2030,14 +2030,23 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
20302030
return await this.projectsService.getProjectEnvironmentVariables(projectId);
20312031
}
20322032

2033-
protected async guardTeamOperation(teamId: string | undefined, op: ResourceAccessOp): Promise<Team> {
2034-
const team = await this.teamDB.findTeamById(teamId || "");
2033+
protected async guardTeamOperation(
2034+
teamId: string,
2035+
op: ResourceAccessOp,
2036+
): Promise<{ team: Team; members: TeamMemberInfo[] }> {
2037+
if (!uuidValidate(teamId)) {
2038+
throw new ResponseError(ErrorCodes.BAD_REQUEST, "organization ID must be a valid UUID");
2039+
}
2040+
2041+
const team = await this.teamDB.findTeamById(teamId);
20352042
if (!team) {
2036-
throw new ResponseError(ErrorCodes.NOT_FOUND, "Organization not found");
2043+
// We return Permission Denied because we don't want to leak the existence, or not of the Organization.
2044+
throw new ResponseError(ErrorCodes.PERMISSION_DENIED, `No access to Organization ID: ${teamId}`);
20372045
}
2046+
20382047
const members = await this.teamDB.findMembersByTeam(team.id);
20392048
await this.guardAccess({ kind: "team", subject: team, members }, op);
2040-
return team;
2049+
return { team, members };
20412050
}
20422051

20432052
public async getTeams(ctx: TraceContext): Promise<Team[]> {
@@ -2049,33 +2058,17 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
20492058
public async getTeam(ctx: TraceContext, teamId: string): Promise<Team> {
20502059
traceAPIParams(ctx, { teamId });
20512060

2052-
if (!uuidValidate(teamId)) {
2053-
throw new ResponseError(ErrorCodes.BAD_REQUEST, "organization ID must be a valid UUID");
2054-
}
2055-
20562061
this.checkAndBlockUser("getTeam");
20572062

2058-
const team = await this.guardTeamOperation(teamId, "get");
2059-
if (!team) {
2060-
throw new ResponseError(ErrorCodes.NOT_FOUND, `Team ${teamId} does not exist`);
2061-
}
2062-
2063+
const { team } = await this.guardTeamOperation(teamId, "get");
20632064
return team;
20642065
}
20652066

20662067
public async updateTeam(ctx: TraceContext, teamId: string, team: Pick<Team, "name">): Promise<Team> {
20672068
traceAPIParams(ctx, { teamId });
2068-
2069-
if (!teamId || !uuidValidate(teamId)) {
2070-
throw new ResponseError(ErrorCodes.BAD_REQUEST, "organization ID must be a valid UUID");
2071-
}
20722069
this.checkUser("updateTeam");
2073-
const existingTeam = await this.teamDB.findTeamById(teamId);
2074-
if (!existingTeam) {
2075-
throw new ResponseError(ErrorCodes.NOT_FOUND, `Organization ${teamId} does not exist`);
2076-
}
2077-
const members = await this.teamDB.findMembersByTeam(teamId);
2078-
await this.guardAccess({ kind: "team", subject: existingTeam, members }, "update");
2070+
2071+
await this.guardTeamOperation(teamId, "update");
20792072

20802073
const updatedTeam = await this.teamDB.updateTeam(teamId, team);
20812074
return updatedTeam;
@@ -2084,14 +2077,8 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
20842077
public async getTeamMembers(ctx: TraceContext, teamId: string): Promise<TeamMemberInfo[]> {
20852078
traceAPIParams(ctx, { teamId });
20862079

2087-
if (!uuidValidate(teamId)) {
2088-
throw new ResponseError(ErrorCodes.BAD_REQUEST, "organization ID must be a valid UUID");
2089-
}
2080+
const { members } = await this.guardTeamOperation(teamId, "get");
20902081

2091-
this.checkUser("getTeamMembers");
2092-
const team = await this.getTeam(ctx, teamId);
2093-
const members = await this.teamDB.findMembersByTeam(team.id);
2094-
await this.guardAccess({ kind: "team", subject: team, members }, "get");
20952082
return members;
20962083
}
20972084

@@ -2152,10 +2139,6 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
21522139
): Promise<void> {
21532140
traceAPIParams(ctx, { teamId, userId, role });
21542141

2155-
if (!uuidValidate(teamId)) {
2156-
throw new ResponseError(ErrorCodes.BAD_REQUEST, "organization ID must be a valid UUID");
2157-
}
2158-
21592142
if (!uuidValidate(userId)) {
21602143
throw new ResponseError(ErrorCodes.BAD_REQUEST, "user ID must be a valid UUID");
21612144
}
@@ -2166,16 +2149,13 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
21662149

21672150
this.checkAndBlockUser("setTeamMemberRole");
21682151
await this.guardTeamOperation(teamId, "update");
2152+
21692153
await this.teamDB.setTeamMemberRole(userId, teamId, role);
21702154
}
21712155

21722156
public async removeTeamMember(ctx: TraceContext, teamId: string, userId: string): Promise<void> {
21732157
traceAPIParams(ctx, { teamId, userId });
21742158

2175-
if (!uuidValidate(teamId)) {
2176-
throw new ResponseError(ErrorCodes.BAD_REQUEST, "organization ID must be a valid UUID");
2177-
}
2178-
21792159
if (!uuidValidate(userId)) {
21802160
throw new ResponseError(ErrorCodes.BAD_REQUEST, "user ID must be a valid UUID");
21812161
}
@@ -2202,12 +2182,9 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
22022182
public async getGenericInvite(ctx: TraceContext, teamId: string): Promise<TeamMembershipInvite> {
22032183
traceAPIParams(ctx, { teamId });
22042184

2205-
if (!uuidValidate(teamId)) {
2206-
throw new ResponseError(ErrorCodes.BAD_REQUEST, "organization ID must be a valid UUID");
2207-
}
2208-
22092185
this.checkUser("getGenericInvite");
22102186
await this.guardTeamOperation(teamId, "get");
2187+
22112188
const invite = await this.teamDB.findGenericInviteByTeamId(teamId);
22122189
if (invite) {
22132190
return invite;
@@ -2218,10 +2195,6 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
22182195
public async resetGenericInvite(ctx: TraceContext, teamId: string): Promise<TeamMembershipInvite> {
22192196
traceAPIParams(ctx, { teamId });
22202197

2221-
if (!uuidValidate(teamId)) {
2222-
throw new ResponseError(ErrorCodes.BAD_REQUEST, "organization ID must be a valid UUID");
2223-
}
2224-
22252198
this.checkAndBlockUser("resetGenericInvite");
22262199
await this.guardTeamOperation(teamId, "update");
22272200
return this.teamDB.resetGenericInvite(teamId);
@@ -2240,7 +2213,7 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
22402213
}
22412214
} else {
22422215
// Anyone who can read a team's information (i.e. any team member) can manage team projects
2243-
await this.guardTeamOperation(project.teamId, "get");
2216+
await this.guardTeamOperation(project.teamId || "", "get");
22442217
}
22452218
}
22462219

@@ -2267,7 +2240,7 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
22672240
}
22682241
} else {
22692242
// Anyone who can read a team's information (i.e. any team member) can create a new project.
2270-
await this.guardTeamOperation(params.teamId, "get");
2243+
await this.guardTeamOperation(params.teamId || "", "get");
22712244
}
22722245

22732246
return this.projectsService.createProject(params, user);
@@ -3048,7 +3021,7 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
30483021
throw new ResponseError(ErrorCodes.NOT_FOUND, "Provider resource not found.");
30493022
}
30503023

3051-
await this.guardTeamOperation(authProvider.organizationId, "delete");
3024+
await this.guardTeamOperation(authProvider.organizationId || "", "delete");
30523025

30533026
try {
30543027
await this.authProviderService.deleteAuthProvider(authProvider);

0 commit comments

Comments
 (0)