diff --git a/web/packages/teleterm/src/services/tshd/createClient.ts b/web/packages/teleterm/src/services/tshd/createClient.ts index 92d0865a72fdc..68542b2462836 100644 --- a/web/packages/teleterm/src/services/tshd/createClient.ts +++ b/web/packages/teleterm/src/services/tshd/createClient.ts @@ -41,7 +41,7 @@ import { } from 'teleterm/helpers'; import { createFileTransferStream } from './createFileTransferStream'; -import middleware, { withLogging } from './middleware'; +import { loggingInterceptor } from './interceptors'; import * as types from './types'; import { ReportUsageEventRequest, @@ -56,9 +56,9 @@ export function createTshdClient( credentials: grpc.ChannelCredentials ): types.TshdClient { const logger = new Logger('tshd'); - const tshd = middleware(new TerminalServiceClient(addr, credentials), [ - withLogging(logger), - ]); + const tshd = new TerminalServiceClient(addr, credentials, { + interceptors: [loggingInterceptor(logger)], + }); // Create a client instance that could be shared with the renderer (UI) via Electron contextBridge const client = { diff --git a/web/packages/teleterm/src/services/tshd/middleware.test.ts b/web/packages/teleterm/src/services/tshd/interceptors.test.ts similarity index 84% rename from web/packages/teleterm/src/services/tshd/middleware.test.ts rename to web/packages/teleterm/src/services/tshd/interceptors.test.ts index edd7fe3b28e99..2e72ca784d872 100644 --- a/web/packages/teleterm/src/services/tshd/middleware.test.ts +++ b/web/packages/teleterm/src/services/tshd/interceptors.test.ts @@ -20,7 +20,7 @@ import { InterceptingCall, InterceptorOptions } from '@grpc/grpc-js'; import Logger from 'teleterm/logger'; -import { withLogging } from './middleware'; +import { loggingInterceptor } from './interceptors'; it('do not log sensitive info like password', () => { const infoLogger = jest.fn(); @@ -31,7 +31,7 @@ it('do not log sensitive info like password', () => { warn: () => {}, }), }); - const loggingMiddleware = withLogging(new Logger())( + const interceptor = loggingInterceptor(new Logger())( { method_definition: { path: 'LogIn' } } as InterceptorOptions, () => ({ @@ -39,14 +39,12 @@ it('do not log sensitive info like password', () => { } as unknown as InterceptingCall) ); - loggingMiddleware.sendMessage({ - toObject: () => ({ - passw: {}, - userData: { - login: 'admin', - password: 'admin', - }, - }), + interceptor.sendMessage({ + passw: {}, + userData: { + login: 'admin', + password: 'admin', + }, }); expect(infoLogger).toHaveBeenCalledWith( diff --git a/web/packages/teleterm/src/services/tshd/middleware.ts b/web/packages/teleterm/src/services/tshd/interceptors.ts similarity index 56% rename from web/packages/teleterm/src/services/tshd/middleware.ts rename to web/packages/teleterm/src/services/tshd/interceptors.ts index 34ec833bc0a04..fbabf1636dc49 100644 --- a/web/packages/teleterm/src/services/tshd/middleware.ts +++ b/web/packages/teleterm/src/services/tshd/interceptors.ts @@ -28,65 +28,7 @@ export type UnaryInterceptor = ( nextCall: (options: grpc.InterceptorOptions) => grpc.InterceptingCall ) => grpc.InterceptingCall; -// This is custom grpc middleware implementation that uses JS Proxy to intercept method calls -// Curtesy of https://github.com/echo-health/node-grpc-interceptors/blob/master/client-proxy.js -export default function middleware>( - client: T, - interceptors: UnaryInterceptor[] -) { - return new Proxy(client, { - get(target, propKey: any) { - // store the original func being called - const origFunc = target[propKey]; - - // IMPORTANT - we only want to intercept gRPC request functions! - // Validate this is a gRPC request func by checking the object for - // a requestSerialize() function - let grpcMethod = false; - for (const k in origFunc) { - if (k === 'requestSerialize' && typeof origFunc[k] === 'function') { - grpcMethod = true; - break; - } - } - - // if this doesn't look like a gRPC request func, return the original func - if (!grpcMethod) { - return function (...args) { - return origFunc.call(target, ...args); - }; - } - - // setup the original method with provided interceptors - return function (...args) { - let message, options, callback; - - if (args.length >= 3) { - message = args[0]; - options = args[1]; - callback = args[2]; - } else { - message = args[0] || undefined; - callback = args[1] || undefined; - } - - if (!options) { - options = {}; - } - - if (!(options.interceptors && Array.isArray(options.interceptors))) { - options.interceptors = []; - } - - options.interceptors = options.interceptors.concat(interceptors); - - return origFunc.call(target, message, options, callback); - }; - }, - }); -} - -export const withLogging = (logger: Logger): UnaryInterceptor => { +export const loggingInterceptor = (logger: Logger): UnaryInterceptor => { return (options, nextCall) => { const method = options.method_definition.path; const params: grpc.Requester = { @@ -97,9 +39,7 @@ export const withLogging = (logger: Logger): UnaryInterceptor => { }, onReceiveMessage(message, next) { - const json = message - ? filterSensitiveProperties(message.toObject()) - : null; + const json = message ? filterSensitiveProperties(message) : null; logger.info(`receive: ${method} -> (${JSON.stringify(json)})`); next(message); }, @@ -117,7 +57,7 @@ export const withLogging = (logger: Logger): UnaryInterceptor => { sendMessage(message, next) { logger.info( `send: ${method}(${JSON.stringify( - filterSensitiveProperties(message.toObject()) + filterSensitiveProperties(message) )})` ); next(message); diff --git a/web/packages/teleterm/src/services/tshdEvents/index.ts b/web/packages/teleterm/src/services/tshdEvents/index.ts index e52b021053fe8..967a3f05c2e4a 100644 --- a/web/packages/teleterm/src/services/tshdEvents/index.ts +++ b/web/packages/teleterm/src/services/tshdEvents/index.ts @@ -27,7 +27,7 @@ import { ExtractResponseType, TshdEventContextBridgeService, } from 'teleterm/types'; -import { filterSensitiveProperties } from 'teleterm/services/tshd/middleware'; +import { filterSensitiveProperties } from 'teleterm/services/tshd/interceptors'; export interface ReloginRequest extends api.ReloginRequest { rootClusterUri: uri.RootClusterUri;