diff --git a/collectors/auth0/package.json b/collectors/auth0/package.json index 44a29e98..8d235f79 100644 --- a/collectors/auth0/package.json +++ b/collectors/auth0/package.json @@ -1,6 +1,6 @@ { "name": "auth0-collector", - "version": "1.1.44", + "version": "1.1.45", "description": "Alert Logic AWS based Auth0 Log Collector extension", "repository": {}, "private": true, diff --git a/collectors/auth0/test/auth0_mock.js b/collectors/auth0/test/auth0_mock.js index 00470c4a..85ea6c8a 100644 --- a/collectors/auth0/test/auth0_mock.js +++ b/collectors/auth0/test/auth0_mock.js @@ -70,7 +70,7 @@ const AUTH0_LOG_EVENT = { "log_id": "90020200113151943625000993024408641221974042823186448498", "_id": "90020200113151943625000993024408641221974042823186448498", "isMobile": false - }; +}; const FUNCTION_ARN = 'arn:aws:lambda:us-east-1:352283894008:function:test-01-CollectLambdaFunction-2CWNLPPW5XO8'; const FUNCTION_NAME = 'test-TestCollectLambdaFunction-1JNNKQIPOTEST'; diff --git a/collectors/auth0/test/auth0_test.js b/collectors/auth0/test/auth0_test.js index 04c93a72..c85f8dec 100644 --- a/collectors/auth0/test/auth0_test.js +++ b/collectors/auth0/test/auth0_test.js @@ -154,6 +154,48 @@ describe('Unit Tests', function () { done(); }); }); + + it('log format when type is null or undefined', function (done) { + let ctx = { + invokedFunctionArn: auth0Mock.FUNCTION_ARN, + fail: function (error) { + assert.fail(error); + done(); + }, + succeed: function () { + done(); + } + }; + + Auth0Collector.load().then(function (creds) { + var collector = new Auth0Collector(ctx, creds); + auth0Mock.AUTH0_LOG_EVENT.type = null; + let fmt = collector.pawsFormatLog(auth0Mock.AUTH0_LOG_EVENT); + assert.equal(fmt.messageTypeId, undefined); + done(); + }); + }); + + it('log format when date is null or undefined', function (done) { + let ctx = { + invokedFunctionArn: auth0Mock.FUNCTION_ARN, + fail: function (error) { + assert.fail(error); + done(); + }, + succeed: function () { + done(); + } + }; + + Auth0Collector.load().then(function (creds) { + var collector = new Auth0Collector(ctx, creds); + auth0Mock.AUTH0_LOG_EVENT.date=null; + let fmt = collector.pawsFormatLog(auth0Mock.AUTH0_LOG_EVENT); + assert.equal(fmt.messageTsUs, undefined); + done(); + }); + }); }); describe('pawsGetLogs', function () { diff --git a/collectors/auth0/test/utils_test.js b/collectors/auth0/test/utils_test.js index 550286e9..a2f8179e 100644 --- a/collectors/auth0/test/utils_test.js +++ b/collectors/auth0/test/utils_test.js @@ -39,6 +39,36 @@ describe('Unit Tests', function () { }); }); + describe('Get API Logs with error', function () { + it('Get API Logs with error', function (done) { + getLogsStub = sinon.stub(auth0Client, 'getLogs').callsFake( + function fakeFn() { + return new Promise(function (resolve, reject) { + return reject({ statusCode: 503, + error: "Service Unavailable", + message: "The API service is temporarily unavailable, please try again later" + }); + }); + }); + + const startDate = moment().subtract(5, 'minutes'); + let state = { + since: startDate.toISOString(), + poll_interval_sec: 1 + }; + let maxPagesPerInvocation = 5; + let accumulator = []; + + utils.getAPILogs(auth0Client, state, accumulator, maxPagesPerInvocation) + .catch(err => { + assert.equal(err.message, "The API service is temporarily unavailable, please try again later", "Error message is not correct"); + getLogsStub.restore(); + done(); + }); + }); + }); + + describe('Get API Logs with last log id', function () { it('Get API Logs with last log id', function (done) { getLogsStub = sinon.stub(auth0Client, 'getLogs').callsFake( diff --git a/collectors/carbonblack/package.json b/collectors/carbonblack/package.json index a6610ad0..abf2e36d 100644 --- a/collectors/carbonblack/package.json +++ b/collectors/carbonblack/package.json @@ -1,6 +1,6 @@ { "name": "carbonblack-collector", - "version": "1.0.40", + "version": "1.0.41", "description": "Alert Logic AWS based Carbonblack Log Collector", "repository": {}, "private": true, diff --git a/collectors/carbonblack/test/Carbonblack_test.js b/collectors/carbonblack/test/Carbonblack_test.js index 9c2945ea..d44a6ff0 100644 --- a/collectors/carbonblack/test/Carbonblack_test.js +++ b/collectors/carbonblack/test/Carbonblack_test.js @@ -202,6 +202,48 @@ describe('Unit Tests', function () { done(); }); }); + it('log format success when id is null', function (done) { + setAlServiceStub(); + let ctx = { + invokedFunctionArn: carbonblackMock.FUNCTION_ARN, + fail: function (error) { + assert.fail(error); + done(); + }, + succeed: function () { + done(); + } + }; + + CarbonblackCollector.load().then(function (creds) { + var collector = new CarbonblackCollector(ctx, creds, 'carbonblack'); + carbonblackMock.LOG_EVENT.eventId = null; + let fmt = collector.pawsFormatLog(carbonblackMock.LOG_EVENT); + assert.equal(fmt.messageTypeId, undefined); + done(); + }); + }); + it('log format success when eventTime is null', function (done) { + setAlServiceStub(); + let ctx = { + invokedFunctionArn: carbonblackMock.FUNCTION_ARN, + fail: function (error) { + assert.fail(error); + done(); + }, + succeed: function () { + done(); + } + }; + + CarbonblackCollector.load().then(function (creds) { + var collector = new CarbonblackCollector(ctx, creds, 'carbonblack'); + carbonblackMock.LOG_EVENT.eventTime = null; + let fmt = collector.pawsFormatLog(carbonblackMock.LOG_EVENT); + assert.equal(fmt.messageTsUs, undefined); + done(); + }); + }); }); describe('NextCollectionStateWithNextPage', function () { @@ -275,7 +317,7 @@ describe('Unit Tests', function () { var collector = new CarbonblackCollector(ctx, creds, 'carbonblack'); const startDate = moment().subtract(3, 'days'); const curState = { - stream: "AuditLogEvents", + stream: null, since: startDate.toISOString(), until: startDate.add(2, 'days').toISOString(), nextPage: null, diff --git a/collectors/carbonblack/test/carbonblack_mock.js b/collectors/carbonblack/test/carbonblack_mock.js index 89932bb8..dd4934cf 100644 --- a/collectors/carbonblack/test/carbonblack_mock.js +++ b/collectors/carbonblack/test/carbonblack_mock.js @@ -19,6 +19,8 @@ process.env.paws_api_secret = "api-secret"; process.env.collector_streams = "[\"AuditLogEvents\", \"SearchAlerts\",\"SearchAlertsCBAnalytics\", \"SearchAlertsWatchlist\"]"; process.env.paws_collector_param_string_2 = "carbonblackOrgKey"; process.env.paws_endpoint = "https://api-url.conferdeploy.net"; +process.env.collector_streams_null = "[\"AuditLogEventsCB\", \"SearchAlertsCB\",\"SearchAlertsCBAnalyticsCB\", \"SearchAlertsWatchlistCB\"]"; + const AIMS_TEST_CREDS = { access_key_id: 'test-access-key-id', @@ -27,7 +29,7 @@ const AIMS_TEST_CREDS = { const LOG_EVENT = { "requestUrl": null, - "eventTime": 1529332687006, + "eventTime": "2020-05-30T13:49:11.789012Z", "eventId": "37075c01730511e89504c9ba022c3fbf", "loginName": "bs@carbonblack.com", "orgName": "example.org", diff --git a/collectors/carbonblack/test/utils_test.js b/collectors/carbonblack/test/utils_test.js index e3c81727..9c0ce61c 100644 --- a/collectors/carbonblack/test/utils_test.js +++ b/collectors/carbonblack/test/utils_test.js @@ -115,5 +115,104 @@ describe('Unit Tests', function () { }); }); }); +describe('Get API Logs (GET) with Error', function () { + it('Get API Logs with Error (GET)', function (done) { + alserviceStub.get = sinon.stub(RestServiceClient.prototype, 'get').callsFake( + function fakeFn(path, extraOptions) { + return new Promise(function (resolve, reject) { + return reject(new Error("Failed to fetch API logs due to an authentication issue")); + }); + }); + let maxPagesPerInvocation = 5; + const startDate = moment().subtract(5, 'minutes'); + let state = { + stream: "AuditLogEvents", + since: startDate.toISOString(), + until: startDate.add(5, 'minutes').toISOString(), + poll_interval_sec: 1 + }; + let apiDetails = { + url: "url", + method: "GET", + requestBody:"", + typeIdPaths: [{ path: ["eventId"] }], + tsPaths: [{ path: ["eventTime"] }] + }; + let accumulator = []; + const apiEndpoint = process.env.paws_endpoint; + const clientSecret = process.env.paws_api_secret; + const clientId = process.env.paws_api_client_id; + + utils.getAPILogs(apiDetails, accumulator, apiEndpoint, state, clientSecret, clientId, maxPagesPerInvocation).catch(err => { + assert.equal(err.message, "Failed to fetch API logs due to an authentication issue", "Error message is not correct"); + alserviceStub.get.restore(); + done(); + }); + }); +}); + + +describe('Get API Logs (POST Request) with Error', function () { + it('Get API Logs with Error (POST)', function (done) { + alserviceStub.post = sinon.stub(RestServiceClient.prototype, 'post').callsFake( + function fakeFn(path, extraOptions) { + return new Promise(function (resolve, reject) { + return reject(new Error("Failed to fetch API logs due to an authentication issue")); + }); + }); + let maxPagesPerInvocation = 5; + const startDate = moment().subtract(5, 'minutes'); + let state = { + stream: "SearchAlerts", + since: startDate.toISOString(), + until: startDate.add(5, 'minutes').toISOString(), + poll_interval_sec: 1 + }; + let apiDetails = { + url: "url", + method: "POST", + requestBody:{ + "criteria": { + "create_time": { + "end": state.until, + "start": state.since + }, + }, + "rows": 0, + "start": 0 + }, + typeIdPaths: [{ path: ["id"] }], + tsPaths: [{ path: ["last_update_time"] }] + }; + let accumulator = []; + const apiEndpoint = process.env.paws_endpoint; + const clientSecret = process.env.paws_api_secret; + const clientId = process.env.paws_api_client_id; + utils.getAPILogs(apiDetails, accumulator, apiEndpoint, state, clientSecret, clientId, maxPagesPerInvocation).catch(err => { + assert.equal(err.message, "Failed to fetch API logs due to an authentication issue", "Error message is not correct"); + alserviceStub.post.restore(); + done(); + }); + }); +}); +describe('Get API Details when state.stream is null', function () { + it('Get API Details when state.stream is null', function (done) { + const startDate = moment().subtract(5, 'minutes'); + const orgKey = "orgKey"; + let apiDetails = []; + const apiNames = JSON.parse(process.env.collector_streams_null); + apiNames.map(stream => { + let state = { + stream: null, + since: startDate.toISOString(), + until: startDate.add(5, 'minutes').toISOString(), + poll_interval_sec: 1 + }; + apiDetails.push(utils.getAPIDetails(state, orgKey)); + }); + assert(apiDetails.length == apiNames.length, "apiDetails length is wrong"); + done(); + }); +}); \ No newline at end of file diff --git a/collectors/ciscoamp/package.json b/collectors/ciscoamp/package.json index 10962a96..3f1c6e44 100644 --- a/collectors/ciscoamp/package.json +++ b/collectors/ciscoamp/package.json @@ -1,6 +1,6 @@ { "name": "ciscoamp-collector", - "version": "1.0.41", + "version": "1.0.42", "description": "Alert Logic AWS based Ciscoamp Log Collector", "repository": {}, "private": true, diff --git a/collectors/ciscoamp/test/ciscoamp_mock.js b/collectors/ciscoamp/test/ciscoamp_mock.js index 70e2d479..68904d18 100644 --- a/collectors/ciscoamp/test/ciscoamp_mock.js +++ b/collectors/ciscoamp/test/ciscoamp_mock.js @@ -31,7 +31,7 @@ const LOG_EVENT = { audit_log_type: 'Computer', audit_log_id: 'b72fd5c0-1ec8-4b7a-b5aa-a500e64635f4', audit_log_user: '16db5cf986eec6f44422', - created_at: '2020-04-20T05:30:18Z', + created_at: '2020-04-20T05:30:18.789012Z', date: "2022-09-27T04:52:54+00:00", old_attributes: { @@ -51,6 +51,30 @@ const LOG_EVENT = { } }; +const LOG_EVENT_WITHOUT_DATE = { + event: 'create', + audit_log_type: 'Computer', + audit_log_id: 'b72fd5c0-1ec8-4b7a-b5aa-a500e64635f4', + audit_log_user: '16db5cf986eec6f44422', + created_at: '2020-04-20T05:30:18Z', + old_attributes: + { + name: null, + desc: null, + hostname: null, + group_id: null, + operating_system_id: null + }, + new_attributes: + { + name: 'Demo_AMP_Intel', + desc: 'Computer populated with demo data', + hostname: 'Demo_AMP_Intel', + group_id: 609190, + operating_system_id: 21810 + } +}; + const FUNCTION_ARN = 'arn:aws:lambda:us-east-1:352283894008:function:test-01-CollectLambdaFunction-2CWNLPPW5XO8'; @@ -60,5 +84,6 @@ module.exports = { AIMS_TEST_CREDS: AIMS_TEST_CREDS, FUNCTION_ARN: FUNCTION_ARN, FUNCTION_NAME: FUNCTION_NAME, - LOG_EVENT: LOG_EVENT + LOG_EVENT: LOG_EVENT, + LOG_EVENT_WITHOUT_DATE: LOG_EVENT_WITHOUT_DATE }; diff --git a/collectors/ciscoamp/test/ciscoamp_test.js b/collectors/ciscoamp/test/ciscoamp_test.js index d3614fb9..9861cbdd 100644 --- a/collectors/ciscoamp/test/ciscoamp_test.js +++ b/collectors/ciscoamp/test/ciscoamp_test.js @@ -177,7 +177,7 @@ describe('Unit Tests', function () { collector.pawsGetLogs(curState, (err, logs, newState, newPollInterval) => { assert.equal(logs.length, 2); assert.equal(newState.poll_interval_sec, 1); - assert.equal(newState.nextPage,'nextPageUrl'); + assert.equal(newState.nextPage, 'nextPageUrl'); assert.equal(newState.apiQuotaResetDate, null); assert.ok(logs[0].audit_log_id); done(); @@ -375,7 +375,7 @@ describe('Unit Tests', function () { }); }); - + it('Paws Get Logs with throttle error and set apiQuotaResetDate', function (done) { let errorObj = { statusCode: 429, @@ -478,7 +478,6 @@ describe('Unit Tests', function () { totalLogsCount: 0, poll_interval_sec: 1 }; - collector.pawsGetLogs(curState, (err, logs, newState, newPollInterval) => { assert.equal(err.errorCode, 401); done(); @@ -540,6 +539,48 @@ describe('Unit Tests', function () { done(); }); }); + + it('log format when state.stream is Audit_Logs and audit_log_id is null', function (done) { + let ctx = { + invokedFunctionArn: ciscoampMock.FUNCTION_ARN, + fail: function (error) { + assert.fail(error); + done(); + }, + succeed: function () { + done(); + } + }; + + CiscoampCollector.load().then(function (creds) { + var collector = new CiscoampCollector(ctx, creds, 'ciscoamp'); + ciscoampMock.LOG_EVENT.audit_log_id = null; + let fmt = collector.pawsFormatLog(ciscoampMock.LOG_EVENT); + assert.equal(fmt.messageTypeId, undefined); + done(); + }); + }); + + it('log format when state.stream is Audit_Logs and created_at is null', function (done) { + let ctx = { + invokedFunctionArn: ciscoampMock.FUNCTION_ARN, + fail: function (error) { + assert.fail(error); + done(); + }, + succeed: function () { + done(); + } + }; + + CiscoampCollector.load().then(function (creds) { + var collector = new CiscoampCollector(ctx, creds, 'ciscoamp'); + ciscoampMock.LOG_EVENT.created_at = null; + let fmt = collector.pawsFormatLog(ciscoampMock.LOG_EVENT); + assert.equal(fmt.messageTsUs, undefined); + done(); + }); + }); }); describe('NextCollectionStateWithNextPage', function () { @@ -577,3 +618,79 @@ describe('Unit Tests', function () { }); }); + +describe('Unit Tests 2', function () { + beforeEach(function () { + AWS.mock('SSM', 'getParameter', function (params, callback) { + const data = new Buffer('test-secret'); + return callback(null, { Parameter: { Value: data.toString('base64') } }); + }); + AWS.mock('KMS', 'decrypt', function (params, callback) { + const data = { + Plaintext: '{}' + }; + return callback(null, data); + }); + }); + + it('Paws Get Logs when currentInterval is less than 120 seconds', function (done) { + getAPILogs = sinon.stub(utils, 'getAPILogs').callsFake( + function fakeFn(baseUrl, authorization, apiUrl, accumulator, maxPagesPerInvocation) { + return new Promise(function (resolve, reject) { + return reject(new Error("Failed to fetch API logs due to an authentication issue")); + }); + }); + CiscoampCollector.load().then(function (creds) { + const state = { + stream: "AuditLogs", + since: "2023-01-31T13:20:00.000Z", + until: "2023-01-31T13:21:00.000Z", + nextPage: null, + apiQuotaResetDate: null, + totalLogsCount: 0, + poll_interval_sec: 1 + }; + const baseUrl = process.env.paws_endpoint; + let maxPagesPerInvocation = 5; + let accumulator = []; + let authorization = "authorization"; + let apiUrl = "apiUrl"; + utils.getAPILogs(baseUrl, authorization, apiUrl, state, accumulator, maxPagesPerInvocation).catch(err => { + assert.equal(err.message, "Failed to fetch API logs due to an authentication issue", "Error message is not correct"); + getAPILogs.restore(); + done(); + }); + + }); + }); + it('Paws Get Logs when state.since is null', function (done) { + getAPILogs = sinon.stub(utils, 'getAPILogs').callsFake( + function fakeFn(baseUrl, authorization, apiUrl, accumulator, maxPagesPerInvocation) { + return new Promise(function (resolve, reject) { + return reject(new Error("Failed to fetch API logs due to an authentication issue")); + }); + }); + CiscoampCollector.load().then(function (creds) { + const state = { + stream: "AuditLogs", + since: null, + until: "2023-01-31T13:21:00.000Z", + nextPage: null, + apiQuotaResetDate: null, + totalLogsCount: 0, + poll_interval_sec: 1 + }; + const baseUrl = process.env.paws_endpoint; + let maxPagesPerInvocation = 5; + let accumulator = []; + let authorization = "authorization"; + let apiUrl = "apiUrl"; + utils.getAPILogs(baseUrl, authorization, apiUrl, state, accumulator, maxPagesPerInvocation).catch(err => { + assert.equal(err.message, "Failed to fetch API logs due to an authentication issue", "Error message is not correct"); + getAPILogs.restore(); + done(); + }); + + }); + }); +}); \ No newline at end of file diff --git a/collectors/ciscoamp/test/utils_test.js b/collectors/ciscoamp/test/utils_test.js index b7dc7f52..c651b65e 100644 --- a/collectors/ciscoamp/test/utils_test.js +++ b/collectors/ciscoamp/test/utils_test.js @@ -68,6 +68,45 @@ describe('Unit Tests', function () { }); }); + describe('Get API Logs with no date property', function () { + it('Get API Logs with no date property', function (done) { + alserviceStub.get = sinon.stub(RestServiceClient.prototype, 'get').callsFake( + function fakeFn() { + return new Promise(function (resolve, reject) { + return resolve({ body: { data: [ciscoampMock.LOG_EVENT_WITHOUT_DATE], metadata: { links: { self: "selfPageUrl" }, results: { total: 100 } } } }); + }); + }); + + const startDate = moment().subtract(5, 'days'); + let state = { + since: startDate.toISOString(), + poll_interval_sec: 1, + stream: 'Events' + }; + let maxPagesPerInvocation = 5; + let accumulator = []; + let authorization = "authorization"; + let apiUrl = "apiUrl"; + + const baseUrl = process.env.paws_endpoint; + utils.getAPILogs(baseUrl, authorization, apiUrl, state, accumulator, maxPagesPerInvocation) + .then(data => { + assert(accumulator.length == 1, "accumulator length is wrong"); + alserviceStub.get.restore(); + done(); + }) + .catch(err => { + if (err === 'CAMP000005 Date is not available in Events api response') { + console.log("Error message matches expected value"); + } else { + console.error("Unexpected error message:", err); + } + alserviceStub.get.restore(); + done(); + }); + + }); + }); describe('Get API Logs with nextPage', function () { it('Page count is more than maxPagesPerInvocation then return tha nextPage url for next invocation', function (done) { alserviceStub.get = sinon.stub(RestServiceClient.prototype, 'get').callsFake( diff --git a/collectors/ciscoduo/package.json b/collectors/ciscoduo/package.json index bb9b77ab..bea5ad16 100644 --- a/collectors/ciscoduo/package.json +++ b/collectors/ciscoduo/package.json @@ -1,6 +1,6 @@ { "name": "ciscoduo-collector", - "version": "1.0.40", + "version": "1.0.41", "description": "Alert Logic AWS based Ciscoduo Log Collector", "repository": {}, "private": true, diff --git a/collectors/ciscoduo/test/ciscoduo_mock.js b/collectors/ciscoduo/test/ciscoduo_mock.js index 476208d4..11cad8bf 100644 --- a/collectors/ciscoduo/test/ciscoduo_mock.js +++ b/collectors/ciscoduo/test/ciscoduo_mock.js @@ -47,7 +47,7 @@ const LOG_EVENT = { isotimestamp: '2020-06-03T14:29:17.668359+00:00', reason: 'bypass_user', result: 'success', - timestamp: 1591194557, + timestamp: "2020-05-30T13:49:11.789012Z", trusted_endpoint_status: 'unknown', txid: 'qwewqewq-23123-adasd-123112d-12323qd', user: { key: 'qweqwewqeqw', name: 'testuser' } diff --git a/collectors/ciscoduo/test/ciscoduo_test.js b/collectors/ciscoduo/test/ciscoduo_test.js index a80e24a7..68517099 100644 --- a/collectors/ciscoduo/test/ciscoduo_test.js +++ b/collectors/ciscoduo/test/ciscoduo_test.js @@ -7,7 +7,6 @@ var CiscoduoCollector = require('../collector').CiscoduoCollector; const moment = require('moment'); const utils = require("../utils"); - var responseStub = {}; let getAPIDetails; let getAPILogs; @@ -101,6 +100,11 @@ describe('Unit Tests', function () { }, succeed: function () { } }; + afterEach(function () { + // responseStub.restore(); + getAPILogs.restore(); + getAPIDetails.restore(); + }); it('Paws Get Logs Success', function (done) { getAPILogs = sinon.stub(utils, 'getAPILogs').callsFake( function fakeFn(client, objectDetails, state, accumulator, maxPagesPerInvocation) { @@ -282,6 +286,60 @@ describe('Unit Tests', function () { }); }); + describe('When object details are null', function() { + let ctx = { + invokedFunctionArn: ciscoduoMock.FUNCTION_ARN, + fail: function (error) { + assert.fail(error); + }, + succeed: function () { } + }; + it('when object details are null(process.env.collector_streams) is null', function (done) { + getAPILogs = sinon.stub(utils, 'getAPILogs').callsFake( + function fakeFn(client, objectDetails, state, accumulator, maxPagesPerInvocation) { + return new Promise(function (resolve, reject) { + return resolve({ accumulator: [ciscoduoMock.LOG_EVENT, ciscoduoMock.LOG_EVENT] }); + }); + }); + getAPIDetails = sinon.stub(utils, 'getAPIDetails').callsFake( + function fakeFn(state) { + const startDate = moment().subtract(3, 'days'); + return { + url: "api_url", + typeIdPaths: [{ path: ["txid"] }], + tsPaths: [{ path: ["timestamp"] }], + query: { + mintime: startDate.valueOf(), + maxtime: startDate.add(2, 'days').valueOf(), + limit: 1000 + }, + method: "GET" + }; + }); + CiscoduoCollector.load().then(function (creds) { + var collector = new CiscoduoCollector(ctx, creds, 'ciscoduo'); + const startDate = moment().subtract(3, 'days'); + const curState = { + stream: "Authentication", + since: startDate.valueOf(), + until: startDate.add(2, 'days').valueOf(), + nextPage: null, + poll_interval_sec: 1 + }; + collector.pawsGetLogs(curState, (err, logs, newState, newPollInterval) => { + assert.equal(logs.length, 2); + assert.equal(newState.poll_interval_sec, 240); + assert.ok(logs[0].txid); + getAPILogs.restore(); + getAPIDetails.restore(); + done(); + }); + + }); + }); + + }); + describe('Next state tests', function () { let ctx = { invokedFunctionArn: ciscoduoMock.FUNCTION_ARN, @@ -366,6 +424,46 @@ describe('Unit Tests', function () { done(); }); }); + it('log format success when txid is null', function (done) { + let ctx = { + invokedFunctionArn: ciscoduoMock.FUNCTION_ARN, + fail: function (error) { + assert.fail(error); + done(); + }, + succeed: function () { + done(); + } + }; + + CiscoduoCollector.load().then(function (creds) { + var collector = new CiscoduoCollector(ctx, creds, 'ciscoduo'); + ciscoduoMock.LOG_EVENT.txid = null; + let fmt = collector.pawsFormatLog(ciscoduoMock.LOG_EVENT); + assert.equal(fmt.messageTypeId, undefined); + done(); + }); + }); + it('log format success when timestamp is null', function (done) { + let ctx = { + invokedFunctionArn: ciscoduoMock.FUNCTION_ARN, + fail: function (error) { + assert.fail(error); + done(); + }, + succeed: function () { + done(); + } + }; + + CiscoduoCollector.load().then(function (creds) { + var collector = new CiscoduoCollector(ctx, creds, 'ciscoduo'); + ciscoduoMock.LOG_EVENT.timestamp = null; + let fmt = collector.pawsFormatLog(ciscoduoMock.LOG_EVENT); + assert.equal(fmt.messageTsUs, undefined); + done(); + }); + }); }); describe('NextCollectionStateWithNextPage', function () { diff --git a/collectors/ciscoduo/test/utils_test.js b/collectors/ciscoduo/test/utils_test.js index d2a7b903..d70fd379 100644 --- a/collectors/ciscoduo/test/utils_test.js +++ b/collectors/ciscoduo/test/utils_test.js @@ -15,6 +15,9 @@ describe('Unit Tests', function () { }); describe('Get API Logs (Authentication)', function () { + afterEach(function () { + getLogsStub.restore(); + }); it('Get API Logs (Authentication) success', function (done) { getLogsStub = sinon.stub(client, 'jsonApiCall').yields({ response: { @@ -52,6 +55,35 @@ describe('Unit Tests', function () { done(); }); }); + it('Get API Logs (Authentication) fail', function (done) { + getLogsStub = sinon.stub(client, 'jsonApiCall').yields(new Error('Request failed'), null); + let maxPagesPerInvocation = 5; + let accumulator = []; + const startDate = moment().subtract(5, 'days'); + let state = { + stream: "Authentication", + since: startDate.valueOf(), + until: startDate.add(2, 'days').valueOf(), + nextPage: null, + poll_interval_sec: 1 + }; + let objectDetails = { + url: "api_url", + typeIdPaths: [{ path: ["txid"] }], + tsPaths: [{ path: ["timestamp"] }], + query: { + mintime: state.since, + maxtime: state.until, + limit: 1000 + }, + method: "GET" + }; + utils.getAPILogs(client, objectDetails, state, accumulator, maxPagesPerInvocation).catch(err => { + assert(err.message === 'Request failed', "error message is wrong"); + getLogsStub.restore(); + done(); + }); + }); }); describe('Get API Logs (Authentication) with nextPage', function () { @@ -92,6 +124,35 @@ describe('Unit Tests', function () { done(); }); }); + it('Get API Logs (Authentication) with nextPage fail', function (done) { + getLogsStub = sinon.stub(client, 'jsonApiCall').yields(new Error('Request failed'), null); + let maxPagesPerInvocation = 5; + let accumulator = []; + const startDate = moment().subtract(5, 'days'); + let state = { + stream: "Authentication", + since: startDate.valueOf(), + until: startDate.add(2, 'days').valueOf(), + nextPage: null, + poll_interval_sec: 1 + }; + let objectDetails = { + url: "api_url", + typeIdPaths: [{ path: ["txid"] }], + tsPaths: [{ path: ["timestamp"] }], + query: { + mintime: state.since, + maxtime: state.until, + limit: 1000 + }, + method: "GET" + }; + utils.getAPILogs(client, objectDetails, state, accumulator, maxPagesPerInvocation).catch(err => { + assert(err.message === 'Request failed', "error message is wrong"); + getLogsStub.restore(); + done(); + }); + }); }); describe('Get API Logs (Administrator)', function () { @@ -123,6 +184,31 @@ describe('Unit Tests', function () { done(); }); }); + it('Get API Logs (Administrator) fail', function (done) { + getLogsStub = sinon.stub(client, 'jsonApiCall').yields(new Error('Request failed'), null); + let maxPagesPerInvocation = 5; + let accumulator = []; + const startDate = moment().subtract(5, 'days'); + let state = { + stream: "Administrator", + since: startDate.unix(), + poll_interval_sec: 1 + }; + let objectDetails = { + url: "api_url", + typeIdPaths: [{ path: ["action"] }], + tsPaths: [{ path: ["timestamp"] }], + query: { + mintime: state.since + }, + method: "GET" + }; + utils.getAPILogs(client, objectDetails, state, accumulator, maxPagesPerInvocation).catch(err => { + assert(err.message === 'Request failed', "error message is wrong"); + getLogsStub.restore(); + done(); + }); + }); }); describe('Get API Logs (Administrator) with nextPage', function () { diff --git a/collectors/crowdstrike/package.json b/collectors/crowdstrike/package.json index f583e7da..da64d2fc 100644 --- a/collectors/crowdstrike/package.json +++ b/collectors/crowdstrike/package.json @@ -1,6 +1,6 @@ { "name": "crowdstrike-collector", - "version": "1.0.22", + "version": "1.0.23", "description": "Alert Logic AWS based Crowdstrike Log Collector", "repository": {}, "private": true, diff --git a/collectors/crowdstrike/test/crowd-strike-test.js b/collectors/crowdstrike/test/crowd-strike-test.js index c06da378..011f45b1 100644 --- a/collectors/crowdstrike/test/crowd-strike-test.js +++ b/collectors/crowdstrike/test/crowd-strike-test.js @@ -169,6 +169,164 @@ describe('Unit Tests', function () { }); }); }); + describe('pawsGetLogs Success when state.stream is Incident', function () { + let ctx = { + invokedFunctionArn: crowdstrikeMock.FUNCTION_ARN, + fail: function (error) { + assert.fail(error); + }, + succeed: function () { } + }; + it('Paws Get Logs Success when state.stream is Incident', function (done) { + setAlServiceStub(); + CrowdstrikeCollector.load().then(function (creds) { + var collector = new CrowdstrikeCollector(ctx, creds, 'crowdstrike'); + const startDate = moment().subtract(3, 'days'); + const curState = { + stream: "Incident", + since: startDate.toISOString(), + until: startDate.add(2, 'days').toISOString(), + offset: 0, + poll_interval_sec: 1 + }; + + collector.pawsGetLogs(curState, (err, logs, newState, newPollInterval) => { + assert.equal(logs.length, 1); + assert.equal(newState.poll_interval_sec, 1); + assert.ok(logs[0].incident_id); + done(); + }); + + }); + }); + }); + + describe('pawsGetLogs (getIncidents) Error', function () { + let ctx = { + invokedFunctionArn: crowdstrikeMock.FUNCTION_ARN, + fail: function (error) { + assert.fail(error); + }, + succeed: function () { } + }; + + it('Paws Get Logs (getIncidents) Error', function (done) { + authenticate = sinon.stub(utils, 'authenticate').callsFake( + function fakeFn(baseUrl, client_id, client_secret) { + return new Promise(function (resolve, reject) { + return resolve(crowdstrikeMock.AUTHENTICATE.access_token); + }); + } + ); + getList = sinon.stub(utils, 'getList').callsFake( + function fakeFn(apiDetails, accumulator, apiEndpoint, token) { + return new Promise(function (resolve, reject) { + return resolve({ accumulator: crowdstrikeMock.LIST.resources, total: 1 }); + }); + }); + getIncidents = sinon.stub(utils, 'getIncidents').callsFake( + function fakeFn(ids, apiEndpoint, token) { + return new Promise(function (resolve, reject) { + return reject(new Error("Failed to fetch API logs due to an authentication issue")); + }); + }); + getDetections = sinon.stub(utils, 'getDetections').callsFake( + function fakeFn(ids, apiEndpoint, token) { + return new Promise(function (resolve, reject) { + return resolve({ resources: crowdstrikeMock.DETECTION_LOG_EVENT.resources}); + }); + }); + getAPIDetails = sinon.stub(utils, 'getAPIDetails').callsFake( + function fakeFn(state) { + return { + url: "url", + method: "GET", + requestBody: "sortFieldName", + typeIdPaths: [{ path: ["incident_id"] }], + tsPaths: [{ path: ["created_timestamp"] }] + }; + }); + CrowdstrikeCollector.load().then(function (creds) { + var collector = new CrowdstrikeCollector(ctx, creds, 'crowdstrike'); + const startDate = moment().subtract(3, 'days'); + const curState = { + stream: "Incident", + since: startDate.toISOString(), + until: startDate.add(2, 'days').toISOString(), + offset: 0, + poll_interval_sec: 1 + }; + collector.pawsGetLogs(curState, (err, logs, newState, newPollInterval) => { + assert.equal(err.message, "Failed to fetch API logs due to an authentication issue", "Error message is not correct"); + done(); + }); + + }); + }); + }); + + describe('pawsGetLogs (getDetections) Error', function () { + let ctx = { + invokedFunctionArn: crowdstrikeMock.FUNCTION_ARN, + fail: function (error) { + assert.fail(error); + }, + succeed: function () { } + }; + it('Paws Get Logs (getDetections) Error', function (done) { + authenticate = sinon.stub(utils, 'authenticate').callsFake( + function fakeFn(baseUrl, client_id, client_secret) { + return new Promise(function (resolve, reject) { + return resolve(crowdstrikeMock.AUTHENTICATE.access_token); + }); + } + ); + getList = sinon.stub(utils, 'getList').callsFake( + function fakeFn(apiDetails, accumulator, apiEndpoint, token) { + return new Promise(function (resolve, reject) { + return resolve({ accumulator: crowdstrikeMock.LIST.resources, total: 1 }); + }); + }); + getIncidents = sinon.stub(utils, 'getIncidents').callsFake( + function fakeFn(ids, apiEndpoint, token) { + return new Promise(function (resolve, reject) { + return resolve({ resources: crowdstrikeMock.INCIDENT_LOG_EVENT.resources}); + }); + }); + getDetections = sinon.stub(utils, 'getDetections').callsFake( + function fakeFn(ids, apiEndpoint, token) { + return new Promise(function (resolve, reject) { + return reject(new Error("Failed to fetch API logs due to an authentication issue")); + }); + }); + getAPIDetails = sinon.stub(utils, 'getAPIDetails').callsFake( + function fakeFn(state) { + return { + url: "url", + method: "GET", + requestBody: "sortFieldName", + typeIdPaths: [{ path: ["detection_id"] }], + tsPaths: [{ path: ["created_timestamp"] }] + }; + }); + CrowdstrikeCollector.load().then(function (creds) { + var collector = new CrowdstrikeCollector(ctx, creds, 'crowdstrike'); + const startDate = moment().subtract(3, 'days'); + const curState = { + stream: "Detection", + since: startDate.toISOString(), + until: startDate.add(2, 'days').toISOString(), + offset: 0, + poll_interval_sec: 1 + }; + collector.pawsGetLogs(curState, (err, logs, newState, newPollInterval) => { + assert.equal(err.message, "Failed to fetch API logs due to an authentication issue", "Error message is not correct"); + done(); + }); + + }); + }); + }); describe('Format Tests', function () { it('log format success', function (done) { @@ -192,6 +350,27 @@ describe('Unit Tests', function () { done(); }); }); + it('log format success when incident_type is null', function (done) { + setAlServiceStub(); + let ctx = { + invokedFunctionArn: crowdstrikeMock.FUNCTION_ARN, + fail: function (error) { + assert.fail(error); + done(); + }, + succeed: function () { + done(); + } + }; + + CrowdstrikeCollector.load().then(function (creds) { + var collector = new CrowdstrikeCollector(ctx, creds, 'crowdstrike'); + crowdstrikeMock.INCIDENT_LOG_EVENT.resources.incident_type = null; + let fmt = collector.pawsFormatLog(crowdstrikeMock.INCIDENT_LOG_EVENT); + assert.equal(fmt.messageTypeId, undefined); + done(); + }); + }); }); describe('NextCollectionStateWithOffset', function () { diff --git a/collectors/crowdstrike/test/utils-test.js b/collectors/crowdstrike/test/utils-test.js index bfc621a1..1372e7a7 100644 --- a/collectors/crowdstrike/test/utils-test.js +++ b/collectors/crowdstrike/test/utils-test.js @@ -168,5 +168,30 @@ describe('Unit Tests', function () { }); }); }); - +describe('Get API Logs (GET) with Error', function () { + it('Get API Logs with Error (GET)', function (done) { + alserviceStub.get = sinon.stub(RestServiceClient.prototype, 'get').callsFake( + function fakeFn(path, extraOptions) { + return new Promise(function (resolve, reject) { + return reject(new Error("Failed to fetch API logs due to an authentication issue")); + }); + }); + let apiDetails = { + url: "url", + method: "GET", + requestBody:"", + typeIdPaths: [{ path: ["eventId"] }], + tsPaths: [{ path: ["eventTime"] }] + }; + let accumulator = []; + const apiEndpoint = process.env.paws_endpoint; + const token = crowdstrikeMock.AUTHENTICATE.access_token; + + utils.getList(apiDetails, accumulator, apiEndpoint, token).catch(err => { + assert.equal(err.message, "Failed to fetch API logs due to an authentication issue", "Error message is not correct"); + alserviceStub.get.restore(); + done(); + }); + }); +}); diff --git a/collectors/googlestackdriver/package.json b/collectors/googlestackdriver/package.json index 42bb0355..384afe3e 100644 --- a/collectors/googlestackdriver/package.json +++ b/collectors/googlestackdriver/package.json @@ -1,6 +1,6 @@ { "name": "googlestackdriver-collector", - "version": "1.1.46", + "version": "1.1.47", "description": "Alert Logic AWS based Googlestackdriver Log Collector", "repository": {}, "private": true, diff --git a/collectors/googlestackdriver/test/test.js b/collectors/googlestackdriver/test/test.js index af33fd59..b2e1b392 100644 --- a/collectors/googlestackdriver/test/test.js +++ b/collectors/googlestackdriver/test/test.js @@ -102,6 +102,20 @@ describe('Unit Tests', function() { }); }); }); + it('when the difference between the current moment and a given startTs timestamp is more than 7 days', function(done) { + GooglestackdriverCollector.load().then(function(creds) { + var collector = new GooglestackdriverCollector(ctx, creds); + const startDate = moment().subtract(8, 'days').toISOString(); + process.env.paws_collection_start_ts = startDate; + + collector.pawsInitCollectionState(googlestackdriverMock.LOG_EVENT, (err, initialStates, nextPoll) => { + initialStates.forEach((state) => { + assert.equal(moment(state.until).diff(state.since, 'days'), 7); + }); + done(); + }); + }); + }); }); describe('pawsGetLogs', function() { @@ -389,6 +403,22 @@ describe('Unit Tests', function() { done(); }); }); + it('get next state when pageSize is given and less than MAX_PAGE_SIZE', function(done) { + GooglestackdriverCollector.load().then(function(creds) { + var collector = new GooglestackdriverCollector(ctx, creds); + const startDate = moment().subtract(collector.pollInterval * 2, 'seconds'); + const curState = { + since: startDate.toISOString(), + until: startDate.add(collector.pollInterval, 'seconds').toISOString(), + poll_interval_sec: 1, + pageSize: 370 + }; + const newState = collector._getNextCollectionState(curState); + assert.equal(moment(newState.until).diff(newState.since, 'seconds'), collector.pollInterval); + assert.equal(newState.poll_interval_sec, 300); + done(); + }); + }); }); describe('Format Tests', function() { it('log format JSON success', function(done) { diff --git a/collectors/gsuite/package.json b/collectors/gsuite/package.json index 90394e0d..6dc7c9a5 100644 --- a/collectors/gsuite/package.json +++ b/collectors/gsuite/package.json @@ -1,6 +1,6 @@ { "name": "gsuite-collector", - "version": "1.2.39", + "version": "1.2.40", "description": "Alert Logic AWS based Gsuite Log Collector", "repository": {}, "private": true, diff --git a/collectors/gsuite/test/gsuite_test.js b/collectors/gsuite/test/gsuite_test.js index e3a40a38..c42db1f0 100644 --- a/collectors/gsuite/test/gsuite_test.js +++ b/collectors/gsuite/test/gsuite_test.js @@ -156,6 +156,35 @@ describe('Unit Tests', function () { }); }); + it('Paws Get Logs Success when nextPage is not undefined', function (done) { + listEvent = sinon.stub(utils, 'listEvents').callsFake( + function fakeFn(path) { + return new Promise(function (resolve, reject) { + return resolve({ accumulator: [gsuiteMock.LOG_EVENT, gsuiteMock.LOG_EVENT], nextPage: null }); + }); + }); + + GsuiteCollector.load().then(function (creds) { + var collector = new GsuiteCollector(ctx, creds, 'gsuite'); + const startDate = moment().subtract(3, 'days'); + const curState = { + application: "login", + since: startDate.toISOString(), + until: startDate.add(2, 'days').toISOString(), + poll_interval_sec: 1 + }; + + collector.pawsGetLogs(curState, (err, logs, newState, newPollInterval) => { + assert.equal(logs.length, 2); + assert.equal(newState.poll_interval_sec, 1); + assert.ok(logs[0].kind); + listEvent.restore(); + done(); + }); + + }); + }); + it('Paws Get Logs with API Quota Reset Date', function (done) { listEvent = sinon.stub(utils, 'listEvents').callsFake( function fakeFn(path) { @@ -272,6 +301,46 @@ describe('Unit Tests', function () { done(); }); }); + it('log format when kind is null or undefined', function (done) { + let ctx = { + invokedFunctionArn: gsuiteMock.FUNCTION_ARN, + fail: function (error) { + assert.fail(error); + done(); + }, + succeed: function () { + done(); + } + }; + + GsuiteCollector.load().then(function (creds) { + var collector = new GsuiteCollector(ctx, creds, 'gsuite'); + gsuiteMock.LOG_EVENT.kind = null; + let fmt = collector.pawsFormatLog(gsuiteMock.LOG_EVENT); + assert.equal(fmt.messageTypeId, undefined); + done(); + }); + }); + it('log format when time is null or undefined', function (done) { + let ctx = { + invokedFunctionArn: gsuiteMock.FUNCTION_ARN, + fail: function (error) { + assert.fail(error); + done(); + }, + succeed: function () { + done(); + } + }; + + GsuiteCollector.load().then(function (creds) { + var collector = new GsuiteCollector(ctx, creds, 'gsuite'); + gsuiteMock.LOG_EVENT.id.time=null; + let fmt = collector.pawsFormatLog(gsuiteMock.LOG_EVENT); + assert.equal(fmt.messageTsUs, undefined); + done(); + }); + }); }); describe('Next State Tests', function () { diff --git a/collectors/o365/package.json b/collectors/o365/package.json index 8dbc3404..5aa040e8 100644 --- a/collectors/o365/package.json +++ b/collectors/o365/package.json @@ -1,6 +1,6 @@ { "name": "o365-collector", - "version": "1.2.51", + "version": "1.2.52", "description": "Alert Logic AWS based O365 Log Collector", "repository": {}, "private": true, diff --git a/collectors/o365/test/o365_test.js b/collectors/o365/test/o365_test.js index f36b95cb..313a10d7 100644 --- a/collectors/o365/test/o365_test.js +++ b/collectors/o365/test/o365_test.js @@ -913,5 +913,44 @@ describe('O365 Collector Tests', function() { done(); }); }); + + it('log format when RecordType is null', function(done) { + let ctx = { + invokedFunctionArn : o365Mock.FUNCTION_ARN, + fail : function(error) { + assert.fail(error); + done(); + }, + succeed : function() { + done(); + } + }; + O365Collector.load().then(function(creds) { + var collector = new O365Collector(ctx, creds, 'o365'); + o365Mock.LOG_EVENT.RecordType = null; + let fmt = collector.pawsFormatLog(o365Mock.LOG_EVENT); + assert.equal(fmt.messageTypeId, undefined); + done(); + }); + }); + it('log format when CreationTime is null', function(done) { + let ctx = { + invokedFunctionArn : o365Mock.FUNCTION_ARN, + fail : function(error) { + assert.fail(error); + done(); + }, + succeed : function() { + done(); + } + }; + O365Collector.load().then(function(creds) { + var collector = new O365Collector(ctx, creds, 'o365'); + o365Mock.LOG_EVENT.CreationTime = null; + let fmt = collector.pawsFormatLog(o365Mock.LOG_EVENT); + assert.equal(fmt.messageTsUs, undefined); + done(); + }); + }); }); }); diff --git a/collectors/o365/test/o365managment_test.js b/collectors/o365/test/o365managment_test.js index 17760ba3..b58f549d 100644 --- a/collectors/o365/test/o365managment_test.js +++ b/collectors/o365/test/o365managment_test.js @@ -17,6 +17,7 @@ function createManagmentInstance(){ return new O365Management(g_appAdCreds, process.env.paws_collector_param_string_1); } + describe('O365 managment tests', function() { describe('request handler tests', function(){ @@ -151,6 +152,93 @@ describe('O365 managment tests', function() { done(); }); }); + + it('in startSubscription when generateClientRequestId is false', (done) => { + sendRequestStub = sinon.stub(O365Management.prototype, 'sendRequest').callsFake( + function fakeFn(request) { + return new Promise(function(resolve, reject) { + const mockRes = { + headers: { + get(key){ + return 'some-header-value'; + } + }, + parsedBody: [{foo: "bar"}], + bodyAsText: '[{"foo": "bar"}]', + status: 200 + }; + + assert.equal(request.method, 'POST'); + assert.notEqual(request.headers.headersArray(), 0); + return resolve(mockRes); + }); + }); + + const managementInstance = createManagmentInstance(); + managementInstance.generateClientRequestId = false; + managementInstance.startSubscription('AFAkeStream', {}).then(() => { + sendRequestStub.restore(); + done(); + }); + }); + + it('in startSubscription when acceptedLanguage is null', (done) => { + sendRequestStub = sinon.stub(O365Management.prototype, 'sendRequest').callsFake( + function fakeFn(request) { + return new Promise(function(resolve, reject) { + const mockRes = { + headers: { + get(key){ + return 'some-header-value'; + } + }, + parsedBody: [{foo: "bar"}], + bodyAsText: '[{"foo": "bar"}]', + status: 200 + }; + + assert.equal(request.method, 'POST'); + assert.notEqual(request.headers.headersArray(), 0); + return resolve(mockRes); + }); + }); + + const managementInstance = createManagmentInstance(); + managementInstance.acceptLanguage = null; + managementInstance.startSubscription('AFAkeStream', {}).then(() => { + sendRequestStub.restore(); + done(); + }); + }); + + it('in startSubscription when option is null', (done) => { + sendRequestStub = sinon.stub(O365Management.prototype, 'sendRequest').callsFake( + function fakeFn(request) { + return new Promise(function(resolve, reject) { + const mockRes = { + headers: { + get(key){ + return 'some-header-value'; + } + }, + parsedBody: [{foo: "bar"}], + bodyAsText: '[{"foo": "bar"}]', + status: 200 + }; + + assert.equal(request.method, 'POST'); + assert.notEqual(request.headers.headersArray(), 0); + return resolve(mockRes); + }); + }); + + const managementInstance = createManagmentInstance(); + managementInstance.startSubscription('AFAkeStream', null).then(() => { + sendRequestStub.restore(); + done(); + }); + }); + }); describe('listSubscriptions', () => { @@ -216,6 +304,65 @@ describe('O365 managment tests', function() { done(); }); }); + + it('in listSubscriptions when generateClientRequestId is false', (done) => { + sendRequestStub = sinon.stub(O365Management.prototype, 'sendRequest').callsFake( + function fakeFn(request) { + return new Promise(function(resolve, reject) { + const mockRes = { + headers: { + get(key){ + return 'some-header-value'; + } + }, + parsedBody: [{foo: "bar"}], + bodyAsText: '[{"foo": "bar"}]', + status: 200 + }; + + assert.equal(request.method, 'GET'); + assert.notEqual(request.headers.headersArray(), 0); + return resolve(mockRes); + }); + }); + + const managementInstance = createManagmentInstance(); + managementInstance.generateClientRequestId = false; + managementInstance.listSubscriptions({}).then(() => { + sendRequestStub.restore(); + done(); + }); + }); + + it('in listSubscriptions when acceptedLanguage is null', (done) => { + sendRequestStub = sinon.stub(O365Management.prototype, 'sendRequest').callsFake( + function fakeFn(request) { + return new Promise(function(resolve, reject) { + const mockRes = { + headers: { + get(key){ + return 'some-header-value'; + } + }, + parsedBody: [{foo: "bar"}], + bodyAsText: '[{"foo": "bar"}]', + status: 200 + }; + + assert.equal(request.method, 'GET'); + assert.notEqual(request.headers.headersArray(), 0); + return resolve(mockRes); + }); + }); + + const managementInstance = createManagmentInstance(); + managementInstance.acceptLanguage = null; + managementInstance.listSubscriptions({}).then(() => { + sendRequestStub.restore(); + done(); + }); + }); + }); describe('subscriptionsContent', () => { @@ -281,6 +428,149 @@ describe('O365 managment tests', function() { done(); }); }); + + it('in subscriptionContent when startDate is null', (done) => { + sendRequestStub = sinon.stub(O365Management.prototype, 'sendRequest').callsFake( + function fakeFn(request) { + return new Promise(function(resolve, reject) { + const mockRes = { + headers: { + get(key){ + return 'some-header-value'; + } + }, + parsedBody: [{foo: "bar"}], + bodyAsText: '[{"foo": "bar"}]', + status: 200 + }; + + assert.equal(request.method, 'GET'); + assert.notEqual(request.headers.headersArray(), 0); + return resolve(mockRes); + }); + }); + + const managementInstance = createManagmentInstance(); + managementInstance.subscriptionsContent('AFakeStream', null, 'endDate', {}).then(() => { + sendRequestStub.restore(); + done(); + }); + }); + + it('in subscriptionContent when endDate is null', (done) => { + sendRequestStub = sinon.stub(O365Management.prototype, 'sendRequest').callsFake( + function fakeFn(request) { + return new Promise(function(resolve, reject) { + const mockRes = { + headers: { + get(key){ + return 'some-header-value'; + } + }, + parsedBody: [{foo: "bar"}], + bodyAsText: '[{"foo": "bar"}]', + status: 200 + }; + + assert.equal(request.method, 'GET'); + assert.notEqual(request.headers.headersArray(), 0); + return resolve(mockRes); + }); + }); + + const managementInstance = createManagmentInstance(); + managementInstance.subscriptionsContent('AFakeStream', 'startDate', null, {}).then(() => { + sendRequestStub.restore(); + done(); + }); + }); + + it('in subscriptionContent when generateClientRequestId is false', (done) => { + sendRequestStub = sinon.stub(O365Management.prototype, 'sendRequest').callsFake( + function fakeFn(request) { + return new Promise(function(resolve, reject) { + const mockRes = { + headers: { + get(key){ + return 'some-header-value'; + } + }, + parsedBody: [{foo: "bar"}], + bodyAsText: '[{"foo": "bar"}]', + status: 200 + }; + + assert.equal(request.method, 'GET'); + assert.notEqual(request.headers.headersArray(), 0); + return resolve(mockRes); + }); + }); + + const managementInstance = createManagmentInstance(); + managementInstance.generateClientRequestId = false; + managementInstance.subscriptionsContent('AFakeStream', 'startDate', 'endDate', {}).then(() => { + sendRequestStub.restore(); + done(); + }); + }); + + it('in subscriptionContent when acceptedLanguage is null', (done) => { + sendRequestStub = sinon.stub(O365Management.prototype, 'sendRequest').callsFake( + function fakeFn(request) { + return new Promise(function(resolve, reject) { + const mockRes = { + headers: { + get(key){ + return 'some-header-value'; + } + }, + parsedBody: [{foo: "bar"}], + bodyAsText: '[{"foo": "bar"}]', + status: 200 + }; + + assert.equal(request.method, 'GET'); + assert.notEqual(request.headers.headersArray(), 0); + return resolve(mockRes); + }); + }); + + const managementInstance = createManagmentInstance(); + managementInstance.acceptLanguage = null; + managementInstance.subscriptionsContent('AFakeStream', 'startDate', 'endDate', {}).then(() => { + sendRequestStub.restore(); + done(); + }); + }); + + it('in subscriptionContent when option is null', (done) => { + sendRequestStub = sinon.stub(O365Management.prototype, 'sendRequest').callsFake( + function fakeFn(request) { + return new Promise(function(resolve, reject) { + const mockRes = { + headers: { + get(key){ + return 'some-header-value'; + } + }, + parsedBody: [{foo: "bar"}], + bodyAsText: '[{"foo": "bar"}]', + status: 200 + }; + + assert.equal(request.method, 'GET'); + assert.notEqual(request.headers.headersArray(), 0); + return resolve(mockRes); + }); + }); + + const managementInstance = createManagmentInstance(); + managementInstance.subscriptionsContent('AFakeStream', 'startDate', 'endDate', null).then(() => { + sendRequestStub.restore(); + done(); + }); + }); + }); describe('getPreFormedUrl', () => { @@ -408,6 +698,99 @@ describe('O365 managment tests', function() { done(); }); }); + + it('in getPreFormedUrl when generateClientRequestId is false', (done) => { + sendRequestStub = sinon.stub(O365Management.prototype, 'sendRequest').callsFake( + function fakeFn(request) { + return new Promise(function(resolve, reject) { + const mockRes = { + headers: { + get(key){ + return 'some-header-value'; + } + }, + parsedBody: [{foo: "bar"}], + bodyAsText: '[{"foo": "bar"}]', + status: 200 + }; + + const query = url.parse(request.url,true).query; + const queryKeys = Object.keys(query); + assert.equal(queryKeys.length, 1); + assert.equal(query.PublisherIdentifier, '79ca7c9d-83ce-498f-952f-4c03b56ab573'); + return resolve(mockRes); + }); + }); + + const managementInstance = createManagmentInstance(); + managementInstance.generateClientRequestId = false; + managementInstance.getPreFormedUrl('https://www.joeiscool.com', {}).then(() => { + sendRequestStub.restore(); + done(); + }); + }); + + it('in getPreFormedUrl when acceptedLanguage is null', (done) => { + sendRequestStub = sinon.stub(O365Management.prototype, 'sendRequest').callsFake( + function fakeFn(request) { + return new Promise(function(resolve, reject) { + const mockRes = { + headers: { + get(key){ + return 'some-header-value'; + } + }, + parsedBody: [{foo: "bar"}], + bodyAsText: '[{"foo": "bar"}]', + status: 200 + }; + + const query = url.parse(request.url,true).query; + const queryKeys = Object.keys(query); + assert.equal(queryKeys.length, 1); + assert.equal(query.PublisherIdentifier, '79ca7c9d-83ce-498f-952f-4c03b56ab573'); + return resolve(mockRes); + }); + }); + + const managementInstance = createManagmentInstance(); + managementInstance.acceptLanguage = null; + managementInstance.getPreFormedUrl('https://www.joeiscool.com', {}).then(() => { + sendRequestStub.restore(); + done(); + }); + }); + + it('in getPreFormedUrl when option is null', (done) => { + sendRequestStub = sinon.stub(O365Management.prototype, 'sendRequest').callsFake( + function fakeFn(request) { + return new Promise(function(resolve, reject) { + const mockRes = { + headers: { + get(key){ + return 'some-header-value'; + } + }, + parsedBody: [{foo: "bar"}], + bodyAsText: '[{"foo": "bar"}]', + status: 200 + }; + + const query = url.parse(request.url,true).query; + const queryKeys = Object.keys(query); + assert.equal(queryKeys.length, 1); + assert.equal(query.PublisherIdentifier, '79ca7c9d-83ce-498f-952f-4c03b56ab573'); + return resolve(mockRes); + }); + }); + + const managementInstance = createManagmentInstance(); + managementInstance.getPreFormedUrl('https://www.joeiscool.com', null).then(() => { + sendRequestStub.restore(); + done(); + }); + }); + }); }); diff --git a/collectors/salesforce/package.json b/collectors/salesforce/package.json index 5c40e42c..f44bf039 100644 --- a/collectors/salesforce/package.json +++ b/collectors/salesforce/package.json @@ -1,6 +1,6 @@ { "name": "salesforce-collector", - "version": "1.1.43", + "version": "1.1.44", "description": "Alert Logic AWS based Salesforce Log Collector", "repository": {}, "private": true, diff --git a/collectors/salesforce/test/salesforce_test.js b/collectors/salesforce/test/salesforce_test.js index 83976e6c..3461a135 100644 --- a/collectors/salesforce/test/salesforce_test.js +++ b/collectors/salesforce/test/salesforce_test.js @@ -186,6 +186,36 @@ describe('Unit Tests', function () { }); }); + it('Paws Get Logs Success when nextPage is not undefined', function (done) { + + getObjectLogs = sinon.stub(utils, 'getObjectLogs').callsFake( + function fakeFn(response, objectQueryDetails, accumulator, state, maxPagesPerInvocation) { + return new Promise(function (resolve, reject) { + return resolve({ accumulator: [salesforceMock.LOG_EVENT, salesforceMock.LOG_EVENT], nextPage: null }); + }); + }); + + SalesforceCollector.load().then(function (creds) { + var collector = new SalesforceCollector(ctx, creds, 'salesforce'); + const startDate = moment().subtract(3, 'days'); + const curState = { + object: "LoginHistory", + since: startDate.toISOString(), + until: startDate.add(2, 'days').toISOString(), + poll_interval_sec: 1 + }; + + collector.pawsGetLogs(curState, (err, logs, newState, newPollInterval) => { + assert.equal(logs.length, 2); + assert.equal(newState.poll_interval_sec, 1); + assert.ok(logs[0].attributes); + getObjectLogs.restore(); + done(); + }); + + }); + }); + it('Paws Get Logs with API Quota Reset Date', function (done) { getObjectLogs = sinon.stub(utils, 'getObjectLogs').callsFake( @@ -250,6 +280,116 @@ describe('Unit Tests', function () { }); }); + + it('Paws Get Logs error when Error code is other than REQUEST_LIMIT_EXCEEDED', function (done) { + + getObjectLogs = sinon.stub(utils, 'getObjectLogs').callsFake( + function fakeFn(response, objectQueryDetails, accumulator, state, maxPagesPerInvocation) { + return new Promise(function (resolve, reject) { + return reject({ errorCode: "Service Unavailable" }); + }); + }); + + SalesforceCollector.load().then(function (creds) { + var collector = new SalesforceCollector(ctx, creds, 'salesforce'); + const startDate = moment().subtract(3, 'days'); + const curState = { + object: "LoginHistory", + since: startDate.toISOString(), + until: startDate.add(2, 'days').toISOString(), + poll_interval_sec: 1 + }; + collector.pawsGetLogs(curState, (err, logs, newState, newPollInterval) => { + assert.strictEqual(err.errorCode, 'Service Unavailable'); + getObjectLogs.restore(); + done(); + }); + + }); + }); + + it('Paws Get Logs error when Error code is INVALID_FIELD', function (done) { + + getObjectLogs = sinon.stub(utils, 'getObjectLogs').callsFake( + function fakeFn(response, objectQueryDetails, accumulator, state, maxPagesPerInvocation) { + return new Promise(function (resolve, reject) { + return reject({ errorCode: "INVALID_FIELD" }); + }); + }); + + SalesforceCollector.load().then(function (creds) { + var collector = new SalesforceCollector(ctx, creds, 'salesforce'); + const startDate = moment().subtract(3, 'days'); + const curState = { + object: "LoginHistory", + since: startDate.toISOString(), + until: startDate.add(2, 'days').toISOString(), + poll_interval_sec: 1 + }; + collector.pawsGetLogs(curState, (err, logs, newState, newPollInterval) => { + assert.strictEqual(err.errorCode, 'INVALID_FIELD'); + getObjectLogs.restore(); + done(); + }); + + }); + }); + + it('Paws Get Logs error when Error code is INVALID_TYPE', function (done) { + + getObjectLogs = sinon.stub(utils, 'getObjectLogs').callsFake( + function fakeFn(response, objectQueryDetails, accumulator, state, maxPagesPerInvocation) { + return new Promise(function (resolve, reject) { + return reject({ errorCode: "INVALID_TYPE" }); + }); + }); + + SalesforceCollector.load().then(function (creds) { + var collector = new SalesforceCollector(ctx, creds, 'salesforce'); + const startDate = moment().subtract(3, 'days'); + const curState = { + object: "LoginHistory", + since: startDate.toISOString(), + until: startDate.add(2, 'days').toISOString(), + poll_interval_sec: 1 + }; + collector.pawsGetLogs(curState, (err, logs, newState, newPollInterval) => { + assert.strictEqual(err.errorCode, 'INVALID_TYPE'); + getObjectLogs.restore(); + done(); + }); + + }); + }); + + it('Paws Get Logs error when Error code is INVALID_SESSION_ID', function (done) { + + getObjectLogs = sinon.stub(utils, 'getObjectLogs').callsFake( + function fakeFn(response, objectQueryDetails, accumulator, state, maxPagesPerInvocation) { + return new Promise(function (resolve, reject) { + return reject({ errorCode: "INVALID_SESSION_ID" }); + }); + }); + + SalesforceCollector.load().then(function (creds) { + var collector = new SalesforceCollector(ctx, creds, 'salesforce'); + const startDate = moment().subtract(3, 'days'); + const curState = { + object: "LoginHistory", + since: startDate.toISOString(), + until: startDate.add(2, 'days').toISOString(), + poll_interval_sec: 1 + }; + collector.pawsGetLogs(curState, (err, logs, newState, newPollInterval) => { + assert.strictEqual(err.errorCode, 'INVALID_SESSION_ID'); + getObjectLogs.restore(); + done(); + }); + + }); + }); + + }); @@ -355,6 +495,28 @@ describe('Unit Tests', function () { done(); }); }); + it('log format when type is null or undefined', function (done) { + setAlServiceStub(); + let ctx = { + invokedFunctionArn: salesforceMock.FUNCTION_ARN, + fail: function (error) { + assert.fail(error); + done(); + }, + succeed: function () { + done(); + } + }; + + SalesforceCollector.load().then(function (creds) { + var collector = new SalesforceCollector(ctx, creds, 'salesforce'); + collector.tsPaths = [{ path: ["LastLoginDate"] }]; + salesforceMock.LOG_EVENT.attributes = null; + let fmt = collector.pawsFormatLog(salesforceMock.LOG_EVENT); + assert.equal(fmt.messageTypeId, undefined); + done(); + }); + }); }); diff --git a/collectors/salesforce/test/utils_test.js b/collectors/salesforce/test/utils_test.js index 879004b6..996fbc30 100644 --- a/collectors/salesforce/test/utils_test.js +++ b/collectors/salesforce/test/utils_test.js @@ -49,6 +49,66 @@ describe('Unit Tests', function () { done(); }); }); + + it('Get Object Logs when state.stream is LoginHistory', function (done) { + mockActivityObject = sinon.stub(conn, 'query').callsFake( + function fakeFn(err, result) { + return result(null, { records: [salesforceMock.LOG_EVENT] }); + }); + let maxPagesPerInvocation = 5; + let response = { + body: `{}` + }; + let objectQueryDetails = { + query: "query", + tsPaths: [{ path: ["LastLoginDate"] }], + sortFieldName: "Id", + sortType: "ASC" + }; + const startDate = moment().subtract(5, 'minutes'); + let state = { + object: "LoginHistory", + stream: "LoginHistory", + since: startDate.toISOString(), + until: startDate.add(5, 'minutes').toISOString(), + poll_interval_sec: 1 + }; + let accumulator = []; + utils.getObjectLogs(response, objectQueryDetails, accumulator, state, maxPagesPerInvocation).then(data => { + assert(accumulator.length == 5, "accumulator length is wrong"); + done(); + }); + }); + + it('Get Object Logs when state.stream is LoginAsEvent', function (done) { + mockActivityObject = sinon.stub(conn, 'query').callsFake( + function fakeFn(err, result) { + return result(null, { records: [salesforceMock.LOG_EVENT] }); + }); + let maxPagesPerInvocation = 5; + let response = { + body: `{}` + }; + let objectQueryDetails = { + query: "query", + tsPaths: [{ path: ["LastLoginDate"] }], + sortFieldName: "Id", + sortType: "ASC" + }; + const startDate = moment().subtract(5, 'minutes'); + let state = { + object: "LoginAsEvent", + stream: "LoginAsEvent", + since: startDate.toISOString(), + until: startDate.add(5, 'minutes').toISOString(), + poll_interval_sec: 1 + }; + let accumulator = []; + utils.getObjectLogs(response, objectQueryDetails, accumulator, state, maxPagesPerInvocation).then(data => { + assert(accumulator.length == 5, "accumulator length is wrong"); + done(); + }); + }); }); describe('Get Object Logs with no records', function () { @@ -99,5 +159,132 @@ describe('Unit Tests', function () { assert(objectQueryDetails.length == objectNames.length, "objectQueryDetails length is wrong"); done(); }); + + it('Get Object Query when state.stream is LoginHistory', function (done) { + const startDate = moment().subtract(5, 'minutes'); + let objectQueryDetails = []; + const objectNames = JSON.parse(process.env.collector_streams); + objectNames.map(object => { + let state = { + object: object, + stream: "LoginHistory", + since: startDate.toISOString(), + until: startDate.add(5, 'minutes').toISOString(), + poll_interval_sec: 1 + }; + objectQueryDetails.push(utils.getObjectQuery(state)); + }); + assert(objectQueryDetails.length == objectNames.length, "objectQueryDetails length is wrong"); + done(); + }); + + it('Get Object Query when state.stream is EventLogFile', function (done) { + const startDate = moment().subtract(5, 'minutes'); + let objectQueryDetails = []; + const objectNames = JSON.parse(process.env.collector_streams); + objectNames.map(object => { + let state = { + object: object, + stream: "EventLogFile", + since: startDate.toISOString(), + until: startDate.add(5, 'minutes').toISOString(), + poll_interval_sec: 1 + }; + objectQueryDetails.push(utils.getObjectQuery(state)); + }); + assert(objectQueryDetails.length == objectNames.length, "objectQueryDetails length is wrong"); + done(); + }); + + it('Get Object Query when state.stream is ApiEvent', function (done) { + const startDate = moment().subtract(5, 'minutes'); + let objectQueryDetails = []; + const objectNames = JSON.parse(process.env.collector_streams); + objectNames.map(object => { + let state = { + object: object, + stream: "ApiEvent", + since: startDate.toISOString(), + until: startDate.add(5, 'minutes').toISOString(), + poll_interval_sec: 1 + }; + objectQueryDetails.push(utils.getObjectQuery(state)); + }); + assert(objectQueryDetails.length == objectNames.length, "objectQueryDetails length is wrong"); + done(); + }); + + it('Get Object Query when state.stream is LoginEvent', function (done) { + const startDate = moment().subtract(5, 'minutes'); + let objectQueryDetails = []; + const objectNames = JSON.parse(process.env.collector_streams); + objectNames.map(object => { + let state = { + object: object, + stream: "LoginEvent", + since: startDate.toISOString(), + until: startDate.add(5, 'minutes').toISOString(), + poll_interval_sec: 1 + }; + objectQueryDetails.push(utils.getObjectQuery(state)); + }); + assert(objectQueryDetails.length == objectNames.length, "objectQueryDetails length is wrong"); + done(); + }); + + it('Get Object Query when state.stream is LogoutEvent', function (done) { + const startDate = moment().subtract(5, 'minutes'); + let objectQueryDetails = []; + const objectNames = JSON.parse(process.env.collector_streams); + objectNames.map(object => { + let state = { + object: object, + stream: "LogoutEvent", + since: startDate.toISOString(), + until: startDate.add(5, 'minutes').toISOString(), + poll_interval_sec: 1 + }; + objectQueryDetails.push(utils.getObjectQuery(state)); + }); + assert(objectQueryDetails.length == objectNames.length, "objectQueryDetails length is wrong"); + done(); + }); + + it('Get Object Query when state.stream is LoginAsEvent', function (done) { + const startDate = moment().subtract(5, 'minutes'); + let objectQueryDetails = []; + const objectNames = JSON.parse(process.env.collector_streams); + objectNames.map(object => { + let state = { + object: object, + stream: "LoginAsEvent", + since: startDate.toISOString(), + until: startDate.add(5, 'minutes').toISOString(), + poll_interval_sec: 1 + }; + objectQueryDetails.push(utils.getObjectQuery(state)); + }); + assert(objectQueryDetails.length == objectNames.length, "objectQueryDetails length is wrong"); + done(); + }); + + it('Get Object Query when state.stream is null', function (done) { + const startDate = moment().subtract(5, 'minutes'); + let objectQueryDetails = []; + const objectNames = JSON.parse(process.env.collector_streams); + objectNames.map(object => { + let state = { + object: object, + stream: null, + since: startDate.toISOString(), + until: startDate.add(5, 'minutes').toISOString(), + poll_interval_sec: 1 + }; + objectQueryDetails.push(utils.getObjectQuery(state)); + }); + assert(objectQueryDetails.length == objectNames.length, "objectQueryDetails length is wrong"); + done(); + }); + }); }); \ No newline at end of file diff --git a/collectors/sentinelone/package.json b/collectors/sentinelone/package.json index f0fe7982..6cba193e 100644 --- a/collectors/sentinelone/package.json +++ b/collectors/sentinelone/package.json @@ -1,6 +1,6 @@ { "name": "sentinelone-collector", - "version": "1.0.40", + "version": "1.0.41", "description": "Alert Logic AWS based Sentinelone Log Collector", "repository": {}, "private": true, diff --git a/collectors/sentinelone/test/sentinelone_test.js b/collectors/sentinelone/test/sentinelone_test.js index 4f4ad76e..a4759f20 100644 --- a/collectors/sentinelone/test/sentinelone_test.js +++ b/collectors/sentinelone/test/sentinelone_test.js @@ -189,6 +189,47 @@ describe('Unit Tests', function () { done(); }); }); + it('log format when id is null or undefined', function (done) { + let ctx = { + invokedFunctionArn: sentineloneMock.FUNCTION_ARN, + fail: function (error) { + assert.fail(error); + done(); + }, + succeed: function () { + done(); + } + }; + + SentineloneCollector.load().then(function (creds) { + var collector = new SentineloneCollector(ctx, creds, 'sentinelone'); + sentineloneMock.LOG_EVENT.id = null; + let fmt = collector.pawsFormatLog(sentineloneMock.LOG_EVENT); + assert.equal(fmt.messageTypeId, undefined); + done(); + }); + }); + + it('log format when createdAt is null or undefined', function (done) { + let ctx = { + invokedFunctionArn: sentineloneMock.FUNCTION_ARN, + fail: function (error) { + assert.fail(error); + done(); + }, + succeed: function () { + done(); + } + }; + + SentineloneCollector.load().then(function (creds) { + var collector = new SentineloneCollector(ctx, creds, 'sentinelone'); + sentineloneMock.LOG_EVENT.createdAt = null; + let fmt = collector.pawsFormatLog(sentineloneMock.LOG_EVENT); + assert.equal(fmt.messageTsUs, undefined); + done(); + }); + }); }); describe('NextCollectionStateWithNextPage', function () { diff --git a/collectors/sophos/package.json b/collectors/sophos/package.json index 044760a9..f1d319b0 100644 --- a/collectors/sophos/package.json +++ b/collectors/sophos/package.json @@ -1,6 +1,6 @@ { "name": "sophos-collector", - "version": "1.0.40", + "version": "1.0.41", "description": "Alert Logic AWS based Sophos Log Collector", "repository": {}, "private": true, diff --git a/collectors/sophos/test/sophos_mock.js b/collectors/sophos/test/sophos_mock.js index 763b472e..8d1501ca 100644 --- a/collectors/sophos/test/sophos_mock.js +++ b/collectors/sophos/test/sophos_mock.js @@ -43,7 +43,7 @@ const LOG_EVENT = { "person": { "id": "4CC323EE-6D93-4CC5-AD3E-7AF5DC3B1AB9" }, - "raisedAt": "2020-05-30T13:49:11.000Z", + "raisedAt": "2020-05-30T13:49:11.789012Z", "allowedActions": [ "acknowledge", "authPua", diff --git a/collectors/sophos/test/sophos_test.js b/collectors/sophos/test/sophos_test.js index 352788be..2e7528cb 100644 --- a/collectors/sophos/test/sophos_test.js +++ b/collectors/sophos/test/sophos_test.js @@ -32,6 +32,7 @@ describe('Unit Tests', function () { afterEach(function () { responseStub.restore(); + }); describe('pawsInitCollectionState', function () { @@ -435,6 +436,47 @@ describe('Unit Tests', function () { done(); }); }); + it('log format success when id is null', function (done) { + let ctx = { + invokedFunctionArn: sophosMock.FUNCTION_ARN, + fail: function (error) { + assert.fail(error); + done(); + }, + succeed: function () { + done(); + } + }; + + SophosCollector.load().then(function (creds) { + var collector = new SophosCollector(ctx, creds, 'sophos'); + sophosMock.LOG_EVENT.id = null; + let fmt = collector.pawsFormatLog(sophosMock.LOG_EVENT); + assert.equal(fmt.messageTypeId, undefined); + done(); + }); + }); + + it('log format success when raisedAt is null', function (done) { + let ctx = { + invokedFunctionArn: sophosMock.FUNCTION_ARN, + fail: function (error) { + assert.fail(error); + done(); + }, + succeed: function () { + done(); + } + }; + + SophosCollector.load().then(function (creds) { + var collector = new SophosCollector(ctx, creds, 'sophos'); + sophosMock.LOG_EVENT.raisedAt = null; + let fmt = collector.pawsFormatLog(sophosMock.LOG_EVENT); + assert.equal(fmt.messageTsUs, undefined); + done(); + }); + }); }); describe('NextCollectionStateWithNextPage', function () { diff --git a/collectors/sophos/test/utils_test.js b/collectors/sophos/test/utils_test.js index ff5e0de9..a10a0142 100644 --- a/collectors/sophos/test/utils_test.js +++ b/collectors/sophos/test/utils_test.js @@ -36,6 +36,37 @@ describe('Unit Tests', function () { }); }); + describe('Get API Logs with Error', function () { + it('Get API Logs with Error', function (done) { + alserviceStub.get = sinon.stub(RestServiceClient.prototype, 'get').callsFake( + function fakeFn() { + return new Promise(function (resolve, reject) { + return reject({ statusCode: 503, + error: "Service Unavailable", + message: "The API service is temporarily unavailable, please try again later" + }); + }); + }); + let maxPagesPerInvocation = 5; + let accumulator = []; + let token = "token"; + let tenant_Id = "57ca9a6b-885f-4e36-95ec-290548c26059"; + const baseUrl = "api-us03.central.sophos.com"; + const startDate = moment().subtract(3, 'days'); + const state = { + since: startDate.toISOString(), + until: startDate.add(2, 'days').toISOString(), + nextPage: null, + poll_interval_sec: 1 + }; + utils.getAPILogs(baseUrl, token, tenant_Id, state, accumulator, maxPagesPerInvocation).catch(err => { + assert.equal(err.message, "The API service is temporarily unavailable, please try again later", "Error message is not correct"); + alserviceStub.get.restore(); + done(); + }); + }); + }); + describe('Get API Logs with nextPage', function () { it('Get API Logs with nextPage success', function (done) { alserviceStub.get = sinon.stub(RestServiceClient.prototype, 'get').callsFake( diff --git a/collectors/sophossiem/package.json b/collectors/sophossiem/package.json index 2592c810..268bbbd4 100644 --- a/collectors/sophossiem/package.json +++ b/collectors/sophossiem/package.json @@ -1,6 +1,6 @@ { "name": "sophossiem-collector", - "version": "1.0.38", + "version": "1.0.39", "description": "Alert Logic AWS based Sophossiem Log Collector", "repository": {}, "private": true, diff --git a/collectors/sophossiem/test/sophossiem_test.js b/collectors/sophossiem/test/sophossiem_test.js index 18735794..26d331a6 100644 --- a/collectors/sophossiem/test/sophossiem_test.js +++ b/collectors/sophossiem/test/sophossiem_test.js @@ -270,6 +270,23 @@ describe('Unit Tests', function () { done(); }); }); + it('Next state tests success when nextPage is null', function (done) { + SophossiemCollector.load().then(function (creds) { + var collector = new SophossiemCollector(ctx, creds, 'sophossiem'); + const startDate = moment(); + const curState = { + stream: "Events", + from_date: startDate.unix(), + poll_interval_sec: 1 + }; + const nextPage = null; + const has_more = true; + let nextState = collector._getNextCollectionState(curState, nextPage, has_more); + assert.equal(nextState.poll_interval_sec, 1); + assert.equal(nextState.nextPage, null); + done(); + }); + }); }); describe('Format Tests', function () { @@ -292,5 +309,43 @@ describe('Unit Tests', function () { done(); }); }); + it('log format success when id is null', function (done) { + let ctx = { + invokedFunctionArn: sophossiemMock.FUNCTION_ARN, + fail: function (error) { + assert.fail(error); + done(); + }, + succeed: function () { + done(); + } + }; + SophossiemCollector.load().then(function (creds) { + var collector = new SophossiemCollector(ctx, creds, 'sophossiem'); + sophossiemMock.LOG_EVENT.id = null; + let fmt = collector.pawsFormatLog(sophossiemMock.LOG_EVENT); + assert.equal(fmt.messageTypeId, undefined); + done(); + }); + }); + it('log format success when created_at is null', function (done) { + let ctx = { + invokedFunctionArn: sophossiemMock.FUNCTION_ARN, + fail: function (error) { + assert.fail(error); + done(); + }, + succeed: function () { + done(); + } + }; + SophossiemCollector.load().then(function (creds) { + var collector = new SophossiemCollector(ctx, creds, 'sophossiem'); + sophossiemMock.LOG_EVENT.created_at = null; + let fmt = collector.pawsFormatLog(sophossiemMock.LOG_EVENT); + assert.equal(fmt.messageTsUs, undefined); + done(); + }); + }); }); });