From 068ef9bc0dc62f1623a0ed85f736494edbe84731 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 19 Nov 2024 20:04:20 +0100 Subject: [PATCH] chore: improve logging around local HTTP server listening MONGOSH-1917 --- src/log-hook.ts | 12 ++++++++++++ src/rfc-8252-http-server.ts | 38 ++++++++++++++++++++++++++----------- src/types.ts | 18 +++++++++++++++--- 3 files changed, 54 insertions(+), 14 deletions(-) diff --git a/src/log-hook.ts b/src/log-hook.ts index 19999f3..1d000c7 100644 --- a/src/log-hook.ts +++ b/src/log-hook.ts @@ -92,6 +92,18 @@ export function hookLoggerToMongoLogWriter( ); }); + emitter.on('mongodb-oidc-plugin:local-listen-resolved-hostname', (ev) => { + log.info( + 'OIDC-PLUGIN', + mongoLogId(1_002_000_028), + `${contextPrefix}-oidc`, + 'Resolved hostnames for local server', + { + ...ev, + } + ); + }); + emitter.on('mongodb-oidc-plugin:local-listen-failed', (ev) => { log.error( 'OIDC-PLUGIN', diff --git a/src/rfc-8252-http-server.ts b/src/rfc-8252-http-server.ts index d6b04f4..d937367 100644 --- a/src/rfc-8252-http-server.ts +++ b/src/rfc-8252-http-server.ts @@ -300,14 +300,18 @@ export class RFC8252HTTPServer { */ public get listeningPort(): number | undefined { if (this.servers.length === 0) return undefined; - const ports = new Set( - this.servers.map((srv) => (srv.address() as AddressInfo)?.port) + const addresses: AddressInfo[] = this.servers.map( + (srv) => srv.address() as AddressInfo ); + const ports = new Set(addresses.map((addr) => addr.port)); const port = ports.size === 1 && [...ports][0]; if (typeof port !== 'number') { + const addressesDebugInfo = addresses + .map((addr) => JSON.stringify(addr)) + .join(','); // Should never happen throw new MongoDBOIDCError( - `Server is listening in inconsistent state: ${[...ports].join(',')}` + `Server is listening in inconsistent state: ${addressesDebugInfo}` ); } return port; @@ -343,8 +347,11 @@ export class RFC8252HTTPServer { ); } + const urlPort = this.redirectUrl.port === '' ? 80 : +this.redirectUrl.port; + this.logger.emit('mongodb-oidc-plugin:local-listen-started', { url: this.redirectUrl.toString(), + urlPort, }); // https://www.rfc-editor.org/rfc/rfc8252#section-7.3 states: @@ -363,9 +370,18 @@ export class RFC8252HTTPServer { let hostname = this.redirectUrl.hostname; if (hostname.startsWith('[') && hostname.endsWith(']')) hostname = hostname.slice(1, -1); - const dnsResults = await dns.lookup(hostname, { - all: true, - hints: ADDRCONFIG, + const dnsResults = ( + await dns.lookup(hostname, { + all: true, + hints: ADDRCONFIG, + }) + ).map(({ address, family }) => ({ address, family })); + + this.logger.emit('mongodb-oidc-plugin:local-listen-resolved-hostname', { + url: this.redirectUrl.toString(), + urlPort, + hostname, + interfaces: dnsResults, }); if (dnsResults.length === 0) { @@ -375,9 +391,6 @@ export class RFC8252HTTPServer { } try { - const urlPort = - this.redirectUrl.port === '' ? 80 : +this.redirectUrl.port; - // Two scenarios: Either we are listening on an arbitrary port here, // or listening on a specific port. Using an arbitrary port has the // advantage that the OS will allocate a free one for us, while a @@ -406,7 +419,7 @@ export class RFC8252HTTPServer { if (typeof port !== 'number') { // Should never happen throw new MongoDBOIDCError( - `Listening on ${dnsResults[0].address} did not return a port` + `Listening on ${dnsResults[0].address} (family = ${dnsResults[0].family}) did not return a port` ); } } @@ -429,13 +442,16 @@ export class RFC8252HTTPServer { await this.close(); this.logger.emit('mongodb-oidc-plugin:local-listen-failed', { url: this.redirectUrl.toString(), + error: String( + err && typeof err === 'object' && 'message' in err ? err.message : err + ), }); throw err; } this.logger.emit('mongodb-oidc-plugin:local-listen-succeeded', { url: this.listeningRedirectUrl || '', - interfaces: dnsResults.map((dnsResult) => dnsResult.address), + interfaces: dnsResults, }); } diff --git a/src/types.ts b/src/types.ts index f130b72..af20bd7 100644 --- a/src/types.ts +++ b/src/types.ts @@ -25,11 +25,23 @@ export interface MongoDBOIDCLogEventsMap { method: string; path: string; }) => void; - 'mongodb-oidc-plugin:local-listen-started': (event: { url: string }) => void; - 'mongodb-oidc-plugin:local-listen-failed': (event: { url: string }) => void; + 'mongodb-oidc-plugin:local-listen-started': (event: { + url: string; + urlPort: number; + }) => void; + 'mongodb-oidc-plugin:local-listen-resolved-hostname': (event: { + url: string; + urlPort: number; + hostname: string; + interfaces: { family: number; address: string }[]; + }) => void; + 'mongodb-oidc-plugin:local-listen-failed': (event: { + url: string; + error: string; + }) => void; 'mongodb-oidc-plugin:local-listen-succeeded': (event: { url: string; - interfaces: string[]; + interfaces: { family: number; address: string }[]; }) => void; 'mongodb-oidc-plugin:local-server-close': (event: { url: string }) => void; 'mongodb-oidc-plugin:open-browser': (event: {