Skip to content

Commit 8eb907f

Browse files
Fix transaction ID implementation and verify Event.body is indeed base64 when isBase64 is true. (#31)
* Add transaction ID for lambda responses * Add tests * Add more checks for falsy values * double check if it is base64 even if aws event says it is base64 (#33) * minor fixes * fixed tests for isBase64 * bump version --------- Co-authored-by: Xingheng Wang <[email protected]> Co-authored-by: xinghengwang <[email protected]>
1 parent d433fb1 commit 8eb907f

9 files changed

+867
-24
lines changed

lib/dataUtils.js

+31-1
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,35 @@ function _getEventModelFromRequestandResponse(
229229
return logData;
230230
}
231231

232+
function isStrBase64(str) {
233+
// Check if the string length is divisible by 4
234+
if (!str) {
235+
return false;
236+
}
237+
if (typeof str !== "string") {
238+
return false;
239+
}
240+
241+
if (str.length % 4 !== 0) {
242+
return false;
243+
}
244+
245+
// Check if the string contains only valid Base64 characters
246+
const base64Regex = /^[A-Za-z0-9+/]+={0,2}$/;
247+
if (!base64Regex.test(str)) {
248+
return false;
249+
}
250+
251+
try {
252+
// Use Buffer for Node.js and atob for browsers
253+
const decoded = Buffer.from(str, "base64").toString("utf-8");
254+
console.log("" + decoded);
255+
return true;
256+
} catch (e) {
257+
return false;
258+
}
259+
}
260+
232261
module.exports = {
233262
getUrlFromRequestOptions: _getUrlFromRequestOptions,
234263
getEventModelFromRequestandResponse: _getEventModelFromRequestandResponse,
@@ -237,5 +266,6 @@ module.exports = {
237266
bodyToBase64: _bodyToBase64,
238267
hashSensitive: _hashSensitive,
239268
logMessage: logMessage,
240-
ensureToString: ensureToString
269+
ensureToString: ensureToString,
270+
isStrBase64: isStrBase64
241271
};

lib/extractDataFromEventAndContext.js

+3-12
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
var requestIp = require('request-ip');
22
var dataUtils = require('./dataUtils');
33
var url = require('url');
4-
const { v4: uuid4 } = require('uuid');
54

65
var safeJsonParse = dataUtils.safeJsonParse;
6+
var isStrBase64 = dataUtils.isStrBase64;
77

88
function getIpAddress(event, context, isV1) {
99
if (isV1) {
@@ -152,7 +152,8 @@ function constructBaseLogData(
152152
logData.metadata = options.getMetadata(event, context);
153153

154154
if (options.logBody && event.body) {
155-
if (event.isBase64Encoded) {
155+
if (event.isBase64Encoded && isStrBase64(event.body)) {
156+
// need to verify if body is actually base64.
156157
logData.request.body = event.body;
157158
logData.request.transferEncoding = "base64";
158159
} else {
@@ -176,16 +177,6 @@ function constructBaseLogData(
176177
logData.blockedBy = logData.response.headers['X-Moesif-Blocked-By'];
177178
}
178179

179-
// Add transaction ID to request and response
180-
let disableTransactionId = options.disableTransactionId
181-
? options.disableTransactionId
182-
: false;
183-
if (!disableTransactionId) {
184-
let transactionId = logData.request.headers['X-Moesif-Transaction-Id'] || uuid4();
185-
logData.response.headers['X-Moesif-Transaction-Id'] = transactionId;
186-
logData.request.headers['X-Moesif-Transaction-Id'] = transactionId;
187-
}
188-
189180
if (options.logBody && safeRes.body) {
190181
if (safeRes.isBase64Encoded) {
191182
logData.response.body = safeRes.body;

lib/index.js

+21-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
'use strict'
22
const _ = require('lodash');
3+
const { v4: uuid4 } = require('uuid');
34
const moesifapi = require('moesifapi');
45
const moesifConfigManager = require('./moesifConfigManager');
56
const governanceRulesManager = require('./governanceRulesManager');
@@ -69,7 +70,7 @@ module.exports = function (options, handler) {
6970
// config moesifapi
7071
var config = moesifapi.configuration;
7172
config.ApplicationId = options.applicationId || options.ApplicationId || process.env.MOESIF_APPLICATION_ID;
72-
config.UserAgent = 'moesif-aws-lambda-nodejs/' + '2.0.3';
73+
config.UserAgent = 'moesif-aws-lambda-nodejs/' + '2.0.5';
7374
config.BaseUri = options.baseUri || options.BaseUri || config.BaseUri;
7475
var moesifController = moesifapi.ApiController;
7576

@@ -157,16 +158,30 @@ module.exports = function (options, handler) {
157158
var moesifMiddleware = function (event, context, callback) {
158159
moesifConfigManager.tryGetConfig();
159160

161+
const transactionId = event.headers && event.headers['X-Moesif-Transaction-Id'];
162+
const responseTransactionId = transactionId || uuid4();
163+
164+
let extraHeaders = {
165+
'X-Moesif-Transaction-Id': responseTransactionId,
166+
};
167+
160168
logMessage(options.debug, 'moesifMiddleware', 'start');
169+
161170
var next = function (err, result) {
162-
logEvent(event, context, err, result, options, moesifController);
163-
callback(err, result)
171+
const modifiedResultObject = {
172+
...result,
173+
headers: {
174+
...(result.headers || {}),
175+
...extraHeaders,
176+
}
177+
}
178+
logEvent(event, context, err, modifiedResultObject, options, moesifController);
179+
callback(err, modifiedResultObject)
164180
};
165181

166182
const isV1 = determineIsEventVersionV1(event);
167183

168184
let returnPromise;
169-
let extraHeaders = {};
170185
if (governanceRulesManager.hasRules()) {
171186
var requestDataForGovernance = prepareRequestDataForGovernance(event, context, isV1);
172187

@@ -183,15 +198,15 @@ module.exports = function (options, handler) {
183198
);
184199

185200
if (governedResponseHolder.headers) {
186-
extraHeaders = governedResponseHolder.headers;
201+
extraHeaders = { ...extraHeaders, ...governedResponseHolder.headers };
187202
}
188203

189204
if (governedResponseHolder.blocked_by) {
190205
returnPromise = Promise.resolve({
191206
isBase64Encoded: false,
192207
statusCode: governedResponseHolder.status,
193208
headers: {
194-
...governedResponseHolder.headers,
209+
...extraHeaders,
195210
'X-Moesif-Blocked-By': governedResponseHolder.blocked_by
196211
},
197212
body: JSON.stringify(governedResponseHolder.body)

0 commit comments

Comments
 (0)