Skip to content

Commit

Permalink
feat: Support to send important log/errors to security engine (#142)
Browse files Browse the repository at this point in the history
  • Loading branch information
sumitsuthar committed Jan 3, 2024
1 parent c2d0ff8 commit b9c2d6b
Show file tree
Hide file tree
Showing 9 changed files with 126 additions and 36 deletions.
3 changes: 3 additions & 0 deletions lib/nr-security-agent/lib/core/Auth-headers.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const logs = require('./logging');
const logger = logs.getLogger();
const initLogger = logs.getInitLogger();
const LinkingMetaData = require('./LinkingMetadata');
const LogMessage = require('./LogMessage');


/* eslint-disable camelcase */
Expand Down Expand Up @@ -38,6 +39,8 @@ function AuthHeaders() {
authHeaders['NR-CSEC-ENTITY-GUID'] = metadata['entity.guid'] ? metadata['entity.guid'] : '';
} catch (error) {
logger.error("Exception in preparing auth headers:", error);
const logMessage = new LogMessage.logMessage("SEVERE", 'Exception in preparing auth headers', __filename, error);
commonUtils.addLogEventtoBuffer(logMessage);
}

return authHeaders;
Expand Down
53 changes: 39 additions & 14 deletions lib/nr-security-agent/lib/core/LogMessage.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,31 @@
const LinkingMetaData = require('./LinkingMetadata');
const API = require('../../../nr-security-api');
const NRAgent = API.getNRAgent();
const { BasicInfo } = require('./event');
const applicationInfo = require('./applicationinfo').getInstance();

/**
* constructor function to create LogMessageException object
* @param {*} message
* @param {*} cause
* @param {*} stacktrace
*/
function logMessageException (exception) {
this.message = exception.message;
this.cause = exception.cause ? exception.cause : '';
this.stacktrace = exception.stack;
function logMessageException(exception) {
let exceptionObject = {};
try {
exceptionObject.message = exception.message ? exception.message : '';
exceptionObject.cause = exception.cause ? exception.cause : '';
if (exception.stack) {
let stacktraceInList = exception.stack.split('\n');
stacktraceInList = stacktraceInList.slice(1);
exceptionObject.stacktrace = stacktraceInList;
}

} catch (error) {

}

return exceptionObject;
}

/**
Expand All @@ -28,17 +42,28 @@ function logMessageException (exception) {
* @param {*} exception
* @param {*} linkingMetadata
*/
function logMessage (level, message, caller, exception) {
this.timestamp = Date.now();
this.level = level;
this.message = message;
this.caller = caller;
if (exception) {
this.exception = logMessageException(exception);
}
if (NRAgent) {
this.linkingMetadata = LinkingMetaData.getLinkingMetadata();
function logMessage(level, message, caller, exception) {
try {
BasicInfo.call(this);
this.jsonVersion = applicationInfo.jsonVersion;
this.jsonName = 'log-message';
this.applicationUUID = applicationInfo.applicationUUID;
this.groupName = applicationInfo.groupName;
this.policyVersion = applicationInfo.policyVersion;
this.timestamp = Date.now();
this.level = level ? level : 'SEVERE';
this.message = message;
this.caller = caller;
if (exception) {
this.exception = logMessageException(exception);
}
if (NRAgent) {
this.linkingMetadata = LinkingMetaData.getLinkingMetadata();
}
} catch (error) {

}

}

module.exports = {
Expand Down
32 changes: 28 additions & 4 deletions lib/nr-security-agent/lib/core/commonUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,18 @@ const OS = require('os');
const path = require('path');
const checkDiskSpace = require('check-disk-space').default;
const AgentStatus = require('../core/agent-status');
const { LOG_MESSAGES, CSEC_HOME, SLASH } = require('./sec-agent-constants');
const { CSEC_HOME, SLASH } = require('./sec-agent-constants');

const prettyBytes = require('pretty-bytes');
const njsAgentConstants = require('./sec-agent-constants');
const LinkingMetaData = require('./LinkingMetadata');
const API = require('../../../nr-security-api');
const NRAgent = API.getNRAgent();
const lodash = require('lodash')
const backupLogFileRegex = /.log.\d/gm;
let websocketHealth;

const ringBuffer = require('ringbufferjs');
const bufferedLogEvents = new ringBuffer(10);

/**
* Utility to generate UUID
* @returns UUID
Expand Down Expand Up @@ -417,6 +419,26 @@ function getWSHealthStatus() {
}
}

/**
* return buffered Log Event instance.
*/
function getLogEvents() {
return bufferedLogEvents;
}


/**
* Utility to add error object in error buffer
* @param {*} error
*/
function addLogEventtoBuffer(logMessage) {
try {
bufferedLogEvents.enq(logMessage);
} catch (error) {
logger.debug(error);
}
}

module.exports = {
getUUID,
getKindIdPair,
Expand All @@ -438,5 +460,7 @@ module.exports = {
getCSECmode,
getPathOfCACert,
getWSHealthStatus,
setWSHealthStatus
setWSHealthStatus,
addLogEventtoBuffer,
getLogEvents
};
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ const stringify = require('fast-safe-stringify');
const restClient = require('../../restclient');
const { Agent } = require('../../../agent');
const { FuzzFailEvent } = require('../../../FuzzFailEvent');
const { CSEC_HOME_TMP, COLON, NR_CSEC_FUZZ_REQUEST_ID, SLASH, CSEC_SEP } = require('../../../sec-agent-constants');
const { CSEC_HOME_TMP, COLON, NR_CSEC_FUZZ_REQUEST_ID, SLASH, CSEC_SEP, SEVERE } = require('../../../sec-agent-constants');
const LOCALHOST = 'localhost';
const COLON_SLASH_SLASH = '://';
const http = require('http');
const https = require('https');
const IASTUtil = require('./IASTUtils');
const LogMessage = require('../../../LogMessage');

require('dns').setDefaultResultOrder('ipv4first')
const PolicyManager = require('../../../Policy');
Expand Down Expand Up @@ -98,6 +99,9 @@ function handler(json) {
IASTUtil.addPendingRequestId(json.id);
} catch (error) {
logger.error('Parsing exeception in fuzz request: ', error);

const logMessage = new LogMessage.logMessage(SEVERE, 'Parsing exeception in fuzz request', __filename, error);
commonUtils.addLogEventtoBuffer(logMessage);
}
if (!fuzzRequest) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

const _ = require('lodash');

const { SERVER_COMMAND } = require('../../../sec-agent-constants');
const { SERVER_COMMAND, SEVERE } = require('../../../sec-agent-constants');
const UnsupportedAgentHandler = require('./unsupported-agent-handler');
const StartupHandshakeHandler = require('./startup-handshake-handler');
const FuzzRequestHandler = require('./fuzz-request-handler');
Expand All @@ -17,6 +17,7 @@ const coolDown = require('./iast-cool-down');
const recordDeletion = require('./iast-record-deletion');
const logs = require('../../../logging');
let logger = logs.getLogger();
const LogMessage = require('../../../LogMessage');

const commandHandlerMap = {
[SERVER_COMMAND.STARTUP_WELCOME_MSG]: StartupHandshakeHandler,
Expand All @@ -38,7 +39,9 @@ const handle = function handle (json) {
NoOpHandler.handler.call(this, json);
}
} catch (error) {
logger.error("Error in handling Control Commnad",error);
logger.error("Error in handling Control Command",error);
const logMessage = new LogMessage.logMessage(SEVERE, 'Error in handling Control Command', __filename, error);
commonUtils.addLogEventtoBuffer(logMessage);
}

};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@ const hc = require('../../health-check');
const fs = require('fs');
const { promisify } = require('../../sec-util');
const ResponseHandler = require('./response');
const { EMPTY_APPLICATION_UUID, LOG_MESSAGES, CSEC_SEP, NR_CSEC_FUZZ_REQUEST_ID, EXITEVENT, JSON_NAME, RASP } = require('../../sec-agent-constants');
const { EMPTY_APPLICATION_UUID, LOG_MESSAGES, CSEC_SEP, NR_CSEC_FUZZ_REQUEST_ID, EXITEVENT, JSON_NAME, RASP, SEVERE } = require('../../sec-agent-constants');
const statusUtils = require('../../statusUtils');
const commonUtils = require('../../commonUtils');
const IASTUtil = require('../websocket/response/IASTUtils');
const LogMessage = require('../../LogMessage');

const BUSY = 'busy';
const IDLE = 'idle';
Expand Down Expand Up @@ -109,6 +110,9 @@ SecWebSocket.prototype.init = function init() {
cert = fs.readFileSync(certPath, 'utf8');
} catch (error) {
logger.error("Error in reading certificate:", error);
const logMessage = new LogMessage.logMessage(SEVERE, 'Error in reading certificate for websocket', __filename, error);
commonUtils.addLogEventtoBuffer(logMessage);

}

webSocket = new WebSocket(validatorService, { headers: authHeaders, cert: cert, handshakeTimeout: 10000 });
Expand All @@ -120,6 +124,17 @@ SecWebSocket.prototype.init = function init() {
lastPongtime = Date.now();
commonUtils.setWSHealthStatus('OK');
logger.debug("Pong received from Validator");

try {
let logBuffer = commonUtils.getLogEvents();
while (logBuffer.size() > 0) {
let logEvent = logBuffer.deq();
this.dispatch(logEvent);
}
} catch (error) {
logger.error("Error while sending log events", error);
}

})
webSocket.on('close', () => {
logger.warn("WS connection closed");
Expand Down Expand Up @@ -172,6 +187,7 @@ SecWebSocket.prototype.obeyReconnect = function obeyReconnect() {
SecWebSocket.prototype.pingWS = async function pingWS() {
const self = this;
let currentTime = Date.now();

let timeDiffInPing = (currentTime - lastPongtime) / 1000;
if (timeDiffInPing > 40 && lastPongtime != 0) {
self.obeyReconnect();
Expand All @@ -193,6 +209,7 @@ SecWebSocket.prototype.pingWS = async function pingWS() {
commonUtils.setWSHealthStatus('Error');
return;
}

}

/**
Expand Down Expand Up @@ -412,6 +429,8 @@ const defaultOnErrCB = () => function onClose(error) {
statusUtils.addErrortoBuffer(error);
const self = this;
logger.error("Error while connecting to validator:", error.message)
const logMessage = new LogMessage.logMessage(SEVERE, 'Error while connecting to validator', __filename, error);
commonUtils.addLogEventtoBuffer(logMessage);
logger.warn("Security Agent INACTIVE!!!")
if (error && error.code && (error.code === 'ECONNREFUSED' || error.code === 'EPIPE' || error.code === 'ECONNRESET')) {
logger.debug("WS Client Error callback called:", error);
Expand Down
3 changes: 3 additions & 0 deletions lib/nr-security-agent/lib/core/sec-agent-constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ module.exports = {
CSEC_SEP: ':IAST:',
RASP: 'RASP',
IAST: 'IAST',
SEVERE: 'SEVERE',
HIGH: 'HIGH',
CRITICAL: 'CRITICAL',

LOG_MESSAGES: {
LOADED_CSEC_ENVS_MSG: '[STEP-1][COMPLETE][env] Environment Information Gathering Done.',
Expand Down
20 changes: 14 additions & 6 deletions lib/nr-security-agent/lib/core/sec-util.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ const { SecEvent } = require('./event');
const logs = require('./logging');
const { Agent } = require('./agent');
const shaUtil = require('./sha-size-util');
const { LOG_MESSAGES, NR_CSEC_FUZZ_REQUEST_ID, COLON, VULNERABLE, EXITEVENT, EMPTY_STR, RASP } = require('./sec-agent-constants');
const { LOG_MESSAGES, NR_CSEC_FUZZ_REQUEST_ID, COLON, VULNERABLE, EXITEVENT, EMPTY_STR, RASP, SEVERE } = require('./sec-agent-constants');
const API = require('../../../nr-security-api');
const NRAgent = API.getNRAgent();
const HC = require('./health-check');
const LogMessage = require('./LogMessage');
const commonUtils = require('./commonUtils');

const statusUtils = require('./statusUtils');

Expand Down Expand Up @@ -67,10 +69,10 @@ function generateSecEvent(securityMetadata) {
const traceObject = securityMetadata.traceObject;
const request = securityMetadata.request;

if(request && request.headers[NR_CSEC_FUZZ_REQUEST_ID]){
if (request && request.headers[NR_CSEC_FUZZ_REQUEST_ID]) {
HC.getInstance().iastEventStats.processed++;
}
else{
else {
HC.getInstance().raspEventStats.processed++;
}
try {
Expand Down Expand Up @@ -102,11 +104,14 @@ function generateSecEvent(securityMetadata) {
} catch (e) {
statusUtils.addErrortoBuffer(e);
logger.error("Error in generating event:", e);

if(request && request.headers[NR_CSEC_FUZZ_REQUEST_ID]){

const logMessage = new LogMessage.logMessage(SEVERE, 'Error while generating event', __filename, e);
commonUtils.addLogEventtoBuffer(logMessage);

if (request && request.headers[NR_CSEC_FUZZ_REQUEST_ID]) {
HC.getInstance().iastEventStats.errorCount++;
}
else{
else {
HC.getInstance().raspEventStats.errorCount++;
}
}
Expand Down Expand Up @@ -141,6 +146,9 @@ function generateExitEvent(secEvent) {
}
} catch (error) {
logger.error('Error in generating exit event', error);

const logMessage = new LogMessage.logMessage(SEVERE, 'Error in generating exit event', __filename, error);
commonUtils.addLogEventtoBuffer(logMessage);
HC.getInstance().exitEventStats.errorCount++;
}
}
Expand Down
17 changes: 9 additions & 8 deletions lib/nr-security-agent/lib/core/websocket-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,17 +140,18 @@ const sendHC = async function () {
* @param {JSON} eventJson
*/
function getDispatcherAndSendEvent(eventJson) {
const eventType = eventJson.jsonName;
if (eventType === JSON_NAME.EVENT || eventType === EXITEVENT) {
hc.getInstance().registerEventProcessed();
}
if (eventJson) {
const eventType = eventJson.jsonName;
if (eventType === JSON_NAME.EVENT || eventType === EXITEVENT) {
hc.getInstance().registerEventProcessed();
}

dispatcher(eventJson);
dispatcher(eventJson);

if (eventType === JSON_NAME.EVENT || eventType === EXITEVENT) {
hc.getInstance().registerEventSent();
if (eventType === JSON_NAME.EVENT || eventType === EXITEVENT) {
hc.getInstance().registerEventSent();
}
}

}

/**
Expand Down

0 comments on commit b9c2d6b

Please sign in to comment.