Skip to content

Commit 9da787c

Browse files
authored
[server] enable auth for snapshot creation (#3444)
1 parent 10c8dbc commit 9da787c

File tree

5 files changed

+47
-8
lines changed

5 files changed

+47
-8
lines changed

components/ide/code/leeway.Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ RUN sudo apt-get update \
2828
&& sudo apt-get clean -y \
2929
&& rm -rf /var/lib/apt/lists/*
3030

31-
ENV GP_CODE_COMMIT 07fe931b77d75daa0ba73f05e5e282c0f1dc1482
31+
ENV GP_CODE_COMMIT b16a98d1506fc5008773b4694d0553847d441674
3232
RUN mkdir gp-code \
3333
&& cd gp-code \
3434
&& git init \

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ export class GitpodServerEEImpl<C extends GitpodClient, S extends GitpodServer>
242242
}
243243

244244
await this.guardAccess({kind: "workspaceInstance", subject: instance, workspaceOwnerID: workspace.ownerId, workspaceIsShared: workspace.shareable || false}, "get");
245-
await this.guardAccess({kind: "snapshot", subject: undefined, workspaceOwnerID: workspace.ownerId}, "create");
245+
await this.guardAccess({kind: "snapshot", subject: undefined, workspaceOwnerID: workspace.ownerId, workspaceID: workspace.id }, "create");
246246

247247
const client = await this.workspaceManagerClientProvider.get(instance.region);
248248
const request = new TakeSnapshotRequest();

components/server/src/auth/resource-access.spec.ts

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import { suite, test } from "mocha-typescript";
88
import * as chai from 'chai';
99
const expect = chai.expect;
10-
import { TokenResourceGuard, ScopedResourceGuard, GuardedResource } from "./resource-access";
10+
import { TokenResourceGuard, ScopedResourceGuard, GuardedResource, ResourceAccessOp } from "./resource-access";
1111

1212
@suite class TestResourceAccess {
1313

@@ -62,6 +62,8 @@ import { TokenResourceGuard, ScopedResourceGuard, GuardedResource } from "./reso
6262
const tests: {
6363
name: string
6464
guard: TokenResourceGuard
65+
resource?: GuardedResource,
66+
operation?: ResourceAccessOp,
6567
expectation: boolean
6668
}[] = [
6769
{
@@ -100,11 +102,38 @@ import { TokenResourceGuard, ScopedResourceGuard, GuardedResource } from "./reso
100102
"resource:"+ScopedResourceGuard.marshalResourceScope({kind: "workspace", subjectID: "*", operations: ["get"]}),
101103
]),
102104
expectation: true,
103-
}
105+
},
106+
{
107+
name: "snaphshot create",
108+
guard: new TokenResourceGuard(workspaceResource.subject.ownerId, [
109+
"resource:"+ScopedResourceGuard.marshalResourceScope({kind: "snapshot", subjectID: ScopedResourceGuard.SNAPSHOT_WORKSPACE_SUBJECT_ID_PREFIX + workspaceResource.subject.id, operations: ["create"]}),
110+
]),
111+
resource: { kind: "snapshot", subject: undefined, workspaceID: workspaceResource.subject.id, workspaceOwnerID: workspaceResource.subject.ownerId},
112+
operation: "create",
113+
expectation: true,
114+
},
115+
{
116+
name: "snaphshot create missing prefix fails",
117+
guard: new TokenResourceGuard(workspaceResource.subject.ownerId, [
118+
"resource:"+ScopedResourceGuard.marshalResourceScope({kind: "snapshot", subjectID: workspaceResource.subject.id, operations: ["create"]}),
119+
]),
120+
resource: { kind: "snapshot", subject: undefined, workspaceID: workspaceResource.subject.id, workspaceOwnerID: workspaceResource.subject.ownerId},
121+
operation: "create",
122+
expectation: false,
123+
},
124+
{
125+
name: "snaphshot create other user fails",
126+
guard: new TokenResourceGuard(workspaceResource.subject.ownerId, [
127+
"resource:"+ScopedResourceGuard.marshalResourceScope({kind: "snapshot", subjectID: workspaceResource.subject.id, operations: ["create"]}),
128+
]),
129+
resource: { kind: "snapshot", subject: undefined, workspaceID: workspaceResource.subject.id, workspaceOwnerID: "other_owner"},
130+
operation: "create",
131+
expectation: false,
132+
},
104133
]
105134

106135
await Promise.all(tests.map(async t => {
107-
const res = await t.guard.canAccess(workspaceResource, "get")
136+
const res = await t.guard.canAccess(t.resource || workspaceResource, t.operation || "get")
108137
expect(res).to.be.eq(t.expectation, `"${t.name}" expected canAccess(...) === ${t.expectation}, but was ${res}`);
109138
}))
110139
}

components/server/src/auth/resource-access.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export interface GuardedSnapshot {
4141
kind: "snapshot";
4242
subject: Snapshot | undefined;
4343
workspaceOwnerID: string;
44+
workspaceID?: string;
4445
}
4546

4647
export interface GuardedUserStorage {
@@ -172,6 +173,9 @@ export class ScopedResourceGuard implements ResourceAccessGuard {
172173
}
173174

174175
export namespace ScopedResourceGuard {
176+
177+
export const SNAPSHOT_WORKSPACE_SUBJECT_ID_PREFIX = 'ws-'
178+
175179
export interface ResourceScope {
176180
kind: GuardedResourceKind;
177181
subjectID: string;
@@ -229,7 +233,13 @@ export namespace ScopedResourceGuard {
229233
case "gitpodToken":
230234
return resource.subject.tokenHash;
231235
case "snapshot":
232-
return resource.subject ? resource.subject.id : undefined;
236+
if (resource.subject) {
237+
return resource.subject.id;
238+
}
239+
if (resource.workspaceID) {
240+
return SNAPSHOT_WORKSPACE_SUBJECT_ID_PREFIX + resource.workspaceID;
241+
}
242+
return undefined;
233243
case "token":
234244
return resource.subject.value;
235245
case "user":
@@ -308,4 +318,4 @@ export namespace TokenResourceGuard {
308318
return true;
309319
}
310320

311-
}
321+
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -645,7 +645,7 @@ export class WorkspaceStarter {
645645

646646
"resource:"+ScopedResourceGuard.marshalResourceScope({kind: "workspace", subjectID: workspace.id, operations: ["get", "update"]}),
647647
"resource:"+ScopedResourceGuard.marshalResourceScope({kind: "workspaceInstance", subjectID: instance.id, operations: ["get", "update", "delete"]}),
648-
"resource:"+ScopedResourceGuard.marshalResourceScope({kind: "snapshot", subjectID: "*", operations: ["create", "get"]}),
648+
"resource:"+ScopedResourceGuard.marshalResourceScope({kind: "snapshot", subjectID: ScopedResourceGuard.SNAPSHOT_WORKSPACE_SUBJECT_ID_PREFIX + workspace.id, operations: ["create"]}),
649649
"resource:"+ScopedResourceGuard.marshalResourceScope({kind: "gitpodToken", subjectID: "*", operations: ["create"]}),
650650
"resource:"+ScopedResourceGuard.marshalResourceScope({kind: "userStorage", subjectID: "*", operations: ["create", "get", "update"]}),
651651
"resource:"+ScopedResourceGuard.marshalResourceScope({kind: "token", subjectID: "*", operations: ["get"]}),

0 commit comments

Comments
 (0)