From bda6bd5dc06e901f9ee1bdc4dde383f7153f54eb Mon Sep 17 00:00:00 2001 From: Curt Tudor Date: Sun, 20 Oct 2024 08:24:29 -0600 Subject: [PATCH] introduce to 'target host transformer' to gzip inflator --- src/context/context.js | 8 +++++++- .../readable-stream/_stream_passthrough.js | 20 +++++++++++++++++-- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/context/context.js b/src/context/context.js index 7c9fe84..706487d 100644 --- a/src/context/context.js +++ b/src/context/context.js @@ -216,6 +216,12 @@ class ZitiContext extends EventEmitter { } + this.targetService = options.target; + this.targetServiceAppData = await this.getConnectAppDataByServiceName (this.targetService.service, this.targetService.scheme); + this.targetServiceHost = await this.getConfigHostByServiceName (this.targetService.service); + this.targetServiceHostAndPort = `${this.targetServiceAppData.dst_hostname}:${this.targetServiceAppData.dst_port}`; + this.bootstrapperHost = options.bootstrapperHost; + this._initialized = true; this._zitiEnroller = new ZitiEnroller ({ @@ -2341,7 +2347,7 @@ class ZitiContext extends EventEmitter { if (isEqual(res.statusCode, 204)) { response = new HttpResponse(null, response_options); } else { - let body = res.pipe(new PassThrough( response_options )); + let body = res.pipe(new PassThrough( response_options, { zitiContext: res.socket.zitiContext } )); response = new HttpResponse(body, response_options); } diff --git a/src/http/readable-stream/_stream_passthrough.js b/src/http/readable-stream/_stream_passthrough.js index 93ddbc6..d439830 100644 --- a/src/http/readable-stream/_stream_passthrough.js +++ b/src/http/readable-stream/_stream_passthrough.js @@ -5,11 +5,11 @@ import { Transform } from './_stream_transform'; import EventEmitter from 'events'; import pako from 'pako'; -import { isEqual } from 'lodash-es'; +import { isEqual, isUndefined } from 'lodash-es'; class PassThrough extends Transform { - constructor (options) { + constructor (options, zitiOptions) { super(options); this.ee = new EventEmitter(); if (options.headers) { @@ -23,12 +23,28 @@ class PassThrough extends Transform { } } } + this.zitiContext = zitiOptions.zitiContext; } _transform(chunk, encoding, cb) { if (this.isGzip) { this.inflator.push(chunk); chunk = this.inflator.result; + + /** + * This logic was added on behalf of Solarwinds Orion, which embeds the host:port of the protected web server in some + * HTML/inline-JS (which is also gzip'ed). We must swap the hostname from the "protected web server" to the boot-strapper, + * or some downstream Orion logic will mismatch when doing some hostname comparisons, which leads it to NOT include + * an XSRF Token header on HTTP requests, which leads to 400's being returned fro teh web server, + * which leads to errors in Orion web UI. + */ + if (!isUndefined(chunk)) { + let decodedChunk = new TextDecoder().decode(chunk); + if (decodedChunk.indexOf(this.zitiContext.targetServiceHostAndPort) != -1) { + decodedChunk = decodedChunk.replaceAll(this.zitiContext.targetServiceHostAndPort, this.zitiContext.bootstrapperHost); + chunk = new TextEncoder().encode(decodedChunk); + } + } } cb(null, chunk, this); };