diff --git a/lib/utilities/serverAccessLogger.js b/lib/utilities/serverAccessLogger.js index e6869df940..3ce4464ca6 100644 --- a/lib/utilities/serverAccessLogger.js +++ b/lib/utilities/serverAccessLogger.js @@ -484,10 +484,14 @@ function buildLogEntry(req, params, options) { userAgent: options.userAgent ?? undefined, versionId: options.versionId ?? undefined, signatureVersion: authInfo?.getAuthVersion() ?? undefined, - cipherSuite: req.socket?.encrypted ? req.socket.getCipher()['standardName'] : undefined, + cipherSuite: req.socket?.encrypted + ? req.socket.getCipher()['standardName'] + : req.headers?.['x-ssl-cipher'] ?? undefined, authenticationType: authInfo?.getAuthType() ?? undefined, hostHeader: req.headers?.host ?? undefined, - tlsVersion: req.socket?.encrypted ? req.socket.getCipher()['version'] : undefined, + tlsVersion: req.socket?.encrypted + ? req.socket.getCipher()['version'] + : req.headers?.['x-ssl-protocol'] ?? undefined, aclRequired: options.aclRequired ?? undefined, // TODO: CLDSRV-774 // hostID: undefined, // NOT IMPLEMENTED // accessPointARN: undefined, // NOT IMPLEMENTED diff --git a/package.json b/package.json index 17447ff98b..7e7a3fa717 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@zenko/cloudserver", - "version": "9.2.28", + "version": "9.2.29", "description": "Zenko CloudServer, an open-source Node.js implementation of a server handling the Amazon S3 protocol", "main": "index.js", "engines": { diff --git a/tests/unit/utils/serverAccessLogger.js b/tests/unit/utils/serverAccessLogger.js index a3c3c59d18..fb0d356c73 100644 --- a/tests/unit/utils/serverAccessLogger.js +++ b/tests/unit/utils/serverAccessLogger.js @@ -979,6 +979,57 @@ describe('serverAccessLogger utility functions', () => { assert.strictEqual('tlsVersion' in loggedData, false); }); + it('should read TLS info from proxy headers when socket is not encrypted', () => { + setServerAccessLogger(mockLogger); + const req = { + serverAccessLog: {}, + headers: { + 'x-ssl-cipher': 'ECDHE-RSA-AES256-GCM-SHA384', + 'x-ssl-protocol': 'TLSv1.3', + }, + socket: { + encrypted: false, + }, + }; + const res = { + serverAccessLog: {}, + getHeader: () => null, + }; + + logServerAccess(req, res); + + assert.strictEqual(mockLogger.write.callCount, 1); + const loggedData = JSON.parse(mockLogger.write.firstCall.args[0].trim()); + assert.strictEqual(loggedData.cipherSuite, 'ECDHE-RSA-AES256-GCM-SHA384'); + assert.strictEqual(loggedData.tlsVersion, 'TLSv1.3'); + }); + + it('should prefer socket TLS info over proxy headers when encrypted', () => { + setServerAccessLogger(mockLogger); + const req = { + serverAccessLog: {}, + headers: { + 'x-ssl-cipher': 'PROXY-CIPHER', + 'x-ssl-protocol': 'TLSv1.2', + }, + socket: { + encrypted: true, + getCipher: () => ({ standardName: 'TLS_AES_128_GCM_SHA256', version: 'TLSv1.3' }), + }, + }; + const res = { + serverAccessLog: {}, + getHeader: () => null, + }; + + logServerAccess(req, res); + + assert.strictEqual(mockLogger.write.callCount, 1); + const loggedData = JSON.parse(mockLogger.write.firstCall.args[0].trim()); + assert.strictEqual(loggedData.cipherSuite, 'TLS_AES_128_GCM_SHA256'); + assert.strictEqual(loggedData.tlsVersion, 'TLSv1.3'); + }); + it('should handle missing query parameters', () => { setServerAccessLogger(mockLogger); const req = {