Skip to content

Commit 0810836

Browse files
mustard-mhroboquat
authored andcommitted
[server,dashboard] add endpoints to get ide credentials
1 parent ad3b05c commit 0810836

File tree

7 files changed

+89
-16
lines changed

7 files changed

+89
-16
lines changed

components/dashboard/src/service/service.tsx

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,9 @@ export function getIDEFrontendService(workspaceID: string, sessionId: string, se
6767
export class IDEFrontendService implements IDEFrontendDashboardService.IServer {
6868
private instanceID: string | undefined;
6969
private user: User | undefined;
70+
private ideCredentials!: string;
7071

71-
private latestStatus?: IDEFrontendDashboardService.Status;
72+
private latestInfo?: IDEFrontendDashboardService.Status;
7273

7374
private readonly onDidChangeEmitter = new Emitter<IDEFrontendDashboardService.SetStateData>();
7475
readonly onSetState = this.onDidChangeEmitter.event;
@@ -108,24 +109,32 @@ export class IDEFrontendService implements IDEFrontendDashboardService.IServer {
108109
}
109110

110111
private async processServerInfo() {
111-
this.user = await this.service.server.getLoggedInUser();
112-
113-
const listener = await this.service.listenToInstance(this.workspaceID);
112+
const [user, listener, ideCredentials] = await Promise.all([
113+
this.service.server.getLoggedInUser(),
114+
this.service.listenToInstance(this.workspaceID),
115+
this.service.server.getIDECredentials(this.workspaceID),
116+
]);
117+
this.user = user;
118+
this.ideCredentials = ideCredentials;
114119
const reconcile = () => {
115-
const status = this.getWorkspaceStatus(listener.info);
116-
this.latestStatus = status;
120+
const info = this.parseInfo(listener.info);
121+
this.latestInfo = info;
117122
const oldInstanceID = this.instanceID;
118-
this.instanceID = status.instanceId;
119-
if (status.instanceId && oldInstanceID !== status.instanceId) {
123+
this.instanceID = info.instanceId;
124+
if (info.instanceId && oldInstanceID !== info.instanceId) {
120125
this.auth();
121126
}
122-
this.sendStatusUpdate(this.latestStatus);
127+
128+
// TODO(hw): to be removed after IDE deployed
129+
this.sendStatusUpdate(this.latestInfo);
130+
// TODO(hw): end of todo
131+
this.sendInfoUpdate(this.latestInfo);
123132
};
124133
reconcile();
125134
listener.onDidChange(reconcile);
126135
}
127136

128-
private getWorkspaceStatus(workspace: WorkspaceInfo): IDEFrontendDashboardService.Status {
137+
private parseInfo(workspace: WorkspaceInfo): IDEFrontendDashboardService.Info {
129138
return {
130139
loggedUserId: this.user!.id,
131140
workspaceID: this.workspaceID,
@@ -134,6 +143,7 @@ export class IDEFrontendService implements IDEFrontendDashboardService.IServer {
134143
statusPhase: workspace.latestInstance?.status.phase,
135144
workspaceDescription: workspace.workspace.description,
136145
workspaceType: workspace.workspace.type,
146+
credentialsToken: this.ideCredentials,
137147
};
138148
}
139149

@@ -153,9 +163,9 @@ export class IDEFrontendService implements IDEFrontendDashboardService.IServer {
153163
msg.properties = {
154164
...msg.properties,
155165
sessionId: this.sessionId,
156-
instanceId: this.latestStatus?.instanceId,
166+
instanceId: this.latestInfo?.instanceId,
157167
workspaceId: this.workspaceID,
158-
type: this.latestStatus?.workspaceType,
168+
type: this.latestInfo?.workspaceType,
159169
};
160170
this.service.server.trackEvent(msg);
161171
}
@@ -183,6 +193,7 @@ export class IDEFrontendService implements IDEFrontendDashboardService.IServer {
183193
}
184194
}
185195

196+
// TODO(hw): to be removed after IDE deployed
186197
sendStatusUpdate(status: IDEFrontendDashboardService.Status): void {
187198
this.clientWindow.postMessage(
188199
{
@@ -193,6 +204,18 @@ export class IDEFrontendService implements IDEFrontendDashboardService.IServer {
193204
"*",
194205
);
195206
}
207+
// TODO(hw): end of todo
208+
209+
sendInfoUpdate(info: IDEFrontendDashboardService.Info): void {
210+
this.clientWindow.postMessage(
211+
{
212+
version: 1,
213+
type: "ide-info-update",
214+
info,
215+
} as IDEFrontendDashboardService.InfoUpdateEventData,
216+
"*",
217+
);
218+
}
196219

197220
relocate(url: string): void {
198221
this.clientWindow.postMessage(

components/gitpod-protocol/src/frontend-dashboard-service.ts

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,18 @@ export namespace IDEFrontendDashboardService {
3131
* IServer is the server side which is using in dashboard loading screen
3232
*/
3333
export interface IServer {
34+
// TODO(hw): to be removed after IDE deployed
3435
sendStatusUpdate(status: Status): void;
36+
// TODO(hw): end of todo
37+
sendInfoUpdate(info: Info): void;
3538
relocate(url: string): void;
3639
openBrowserIDE(): void;
3740
}
3841

39-
export interface Status {
42+
/**
43+
* Info defined the information that `supervisor/frontend` requires.
44+
*/
45+
export interface Info {
4046
workspaceID: string;
4147
loggedUserId: string;
4248

@@ -46,8 +52,13 @@ export namespace IDEFrontendDashboardService {
4652

4753
workspaceDescription: string;
4854
workspaceType: string;
55+
credentialsToken: string;
4956
}
5057

58+
// TODO(hw): to be removed after IDE deployed
59+
export type Status = Info;
60+
// TODO(hw): end of todo
61+
5162
export interface SetStateData {
5263
ideFrontendFailureCause?: string;
5364
desktopIDE?: {
@@ -57,15 +68,21 @@ export namespace IDEFrontendDashboardService {
5768
};
5869
}
5970

60-
/**
61-
* interface for post message that send status update from dashboard to supervisor
62-
*/
71+
// TODO(hw): to be removed after IDE deployed
6372
export interface StatusUpdateEventData {
6473
// protocol version
6574
version?: number;
6675
type: "ide-status-update";
6776
status: Status;
6877
}
78+
// TODO(hw): end of todo
79+
80+
export interface InfoUpdateEventData {
81+
// protocol version
82+
version?: number;
83+
type: "ide-info-update";
84+
info: Info;
85+
}
6986

7087
export interface HeartbeatEventData {
7188
type: "ide-heartbeat";
@@ -95,9 +112,15 @@ export namespace IDEFrontendDashboardService {
95112
url: string;
96113
}
97114

115+
// TODO(hw): to be removed after IDE deployed
98116
export function isStatusUpdateEventData(obj: any): obj is StatusUpdateEventData {
99117
return obj != null && typeof obj === "object" && obj.type === "ide-status-update";
100118
}
119+
// TODO(hw): end of todo
120+
121+
export function isInfoUpdateEventData(obj: any): obj is InfoUpdateEventData {
122+
return obj != null && typeof obj === "object" && obj.type === "ide-info-update";
123+
}
101124

102125
export function isHeartbeatEventData(obj: any): obj is HeartbeatEventData {
103126
return obj != null && typeof obj === "object" && obj.type === "ide-heartbeat";

components/gitpod-protocol/src/gitpod-service.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ export interface GitpodServer extends JsonRpcServer<GitpodClient>, AdminServer,
117117
getWorkspace(id: string): Promise<WorkspaceInfo>;
118118
isWorkspaceOwner(workspaceId: string): Promise<boolean>;
119119
getOwnerToken(workspaceId: string): Promise<string>;
120+
getIDECredentials(workspaceId: string): Promise<string>;
120121

121122
/**
122123
* Creates and starts a workspace for the given context URL.

components/gitpod-protocol/src/protocol.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -842,6 +842,7 @@ export interface WorkspaceConfig {
842842
vscode?: VSCodeConfig;
843843
jetbrains?: JetBrainsConfig;
844844
coreDump?: CoreDumpConfig;
845+
ideCredentials?: string;
845846

846847
/** deprecated. Enabled by default **/
847848
experimentalNetwork?: boolean;

components/server/src/auth/rate-limiter.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ const defaultFunctions: FunctionsConfig = {
7171
getWorkspace: { group: "default", points: 1 },
7272
isWorkspaceOwner: { group: "default", points: 1 },
7373
getOwnerToken: { group: "default", points: 1 },
74+
getIDECredentials: { group: "default", points: 1 },
7475
createWorkspace: { group: "createWorkspace", points: 1 },
7576
startWorkspace: { group: "startWorkspace", points: 1 },
7677
stopWorkspace: { group: "default", points: 1 },

components/server/src/workspace/config-provider.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import { inject, injectable } from "inversify";
88
import fetch from "node-fetch";
99
import * as path from "path";
10+
import * as crypto from "crypto";
1011

1112
import { log, LogContext } from "@gitpod/gitpod-protocol/lib/util/logging";
1213
import {
@@ -243,6 +244,7 @@ export class ConfigProvider {
243244
ports: [],
244245
tasks: [],
245246
image: this.config.workspaceDefaults.workspaceImage,
247+
ideCredentials: crypto.randomBytes(32).toString("base64"),
246248
};
247249
}
248250

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,28 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
692692
return ownerToken;
693693
}
694694

695+
public async getIDECredentials(ctx: TraceContext, workspaceId: string): Promise<string> {
696+
traceAPIParams(ctx, { workspaceId });
697+
traceWI(ctx, { workspaceId });
698+
699+
this.checkAndBlockUser("getIDECredentials");
700+
701+
const workspace = await this.workspaceDb.trace(ctx).findById(workspaceId);
702+
if (!workspace) {
703+
throw new Error("workspace not found");
704+
}
705+
await this.guardAccess({ kind: "workspace", subject: workspace }, "get");
706+
if (workspace.config.ideCredentials) {
707+
return workspace.config.ideCredentials;
708+
}
709+
return this.workspaceDb.trace(ctx).transaction(async (db) => {
710+
const ws = await this.internalGetWorkspace(workspaceId, db);
711+
ws.config.ideCredentials = crypto.randomBytes(32).toString("base64");
712+
await db.store(ws);
713+
return ws.config.ideCredentials;
714+
});
715+
}
716+
695717
public async startWorkspace(
696718
ctx: TraceContext,
697719
workspaceId: string,

0 commit comments

Comments
 (0)