Skip to content

Commit ea3040b

Browse files
authored
Check if target gitpodHost is matching hostSession one in getWorkspaceAuthInfo (#76)
1 parent 9a042b1 commit ea3040b

File tree

2 files changed

+18
-4
lines changed

2 files changed

+18
-4
lines changed

src/local-ssh/ipc/extensionServiceServer.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@ class ExtensionServiceImpl implements ExtensionServiceImplementation {
7575

7676
async getWorkspaceAuthInfo(request: GetWorkspaceAuthInfoRequest, _context: CallContext): Promise<GetWorkspaceAuthInfoResponse> {
7777
try {
78+
if (new URL(this.hostService.gitpodHost).host !== new URL(request.gitpodHost).host) {
79+
this.logService.error(`gitpod host mismatch, actual: ${this.hostService.gitpodHost} target: ${request.gitpodHost}`);
80+
throw new ServerError(Status.FAILED_PRECONDITION, 'gitpod host mismatch');
81+
}
7882
const accessToken = this.sessionService.getGitpodToken();
7983
if (!accessToken) {
8084
throw new ServerError(Status.INTERNAL, 'no access token found');
@@ -113,6 +117,9 @@ class ExtensionServiceImpl implements ExtensionServiceImplementation {
113117
};
114118
} catch (e) {
115119
this.logService.error(e, 'failed to get workspace auth info');
120+
if (e instanceof ServerError) {
121+
throw e;
122+
}
116123
throw new ServerError(Status.UNAVAILABLE, e.toString());
117124
}
118125
}

src/local-ssh/proxy.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { SshClient } from '@microsoft/dev-tunnels-ssh-tcp';
77
import { NodeStream, SshClientCredentials, SshClientSession, SshDisconnectReason, SshServerSession, SshSessionConfiguration, Stream, WebSocketStream } from '@microsoft/dev-tunnels-ssh';
88
import { importKey, importKeyBytes } from '@microsoft/dev-tunnels-ssh-keys';
99
import { ExtensionServiceDefinition, GetWorkspaceAuthInfoResponse } from '../proto/typescript/ipc/v1/ipc';
10-
import { Client, createChannel, createClient } from 'nice-grpc';
10+
import { Client, ClientError, Status, createChannel, createClient } from 'nice-grpc';
1111
import { retry } from '../common/async';
1212
import { WebSocket } from 'ws';
1313
import * as stream from 'stream';
@@ -41,7 +41,7 @@ function getClientOptions(): ClientOptions {
4141
};
4242
}
4343

44-
type FailedToProxyCode = 'SSH.AuthenticationFailed' | 'TUNNEL.AuthenticateSSHKeyFailed' | 'NoRunningInstance' | 'FailedToGetAuthInfo';
44+
type FailedToProxyCode = 'SSH.AuthenticationFailed' | 'TUNNEL.AuthenticateSSHKeyFailed' | 'NoRunningInstance' | 'FailedToGetAuthInfo' | 'GitpodHostMismatch' | 'NoAccessTokenFound';
4545

4646
// IgnoredFailedCodes contains the failreCode that don't need to send error report
4747
const IgnoredFailedCodes: FailedToProxyCode[] = ['NoRunningInstance'];
@@ -139,11 +139,11 @@ class WebSocketSSHProxy {
139139
pipePromise = session.pipe(pipeSession);
140140
return {};
141141
}).catch(async err => {
142-
let sendErrorReport = true
142+
let sendErrorReport = true;
143143
if (err instanceof FailedToProxyError) {
144144
this.flow.failureCode = err.failureCode;
145145
if (IgnoredFailedCodes.includes(err.failureCode)) {
146-
sendErrorReport = false
146+
sendErrorReport = false;
147147
}
148148
}
149149
await Promise.allSettled([
@@ -236,6 +236,13 @@ class WebSocketSSHProxy {
236236
async retryGetWorkspaceInfo(username: string) {
237237
return retry(async () => {
238238
return this.extensionIpc.getWorkspaceAuthInfo({ workspaceId: username, gitpodHost: this.options.host }).catch(e => {
239+
if (e instanceof ClientError) {
240+
if (e.code === Status.FAILED_PRECONDITION && e.message.includes('gitpod host mismatch')) {
241+
throw new FailedToProxyError('GitpodHostMismatch', e);
242+
} else if (e.code === Status.INTERNAL && e.message.includes('no access token found')) {
243+
throw new FailedToProxyError('NoAccessTokenFound', e);
244+
}
245+
}
239246
throw new FailedToProxyError('FailedToGetAuthInfo', e);
240247
});
241248
}, 200, 50);

0 commit comments

Comments
 (0)