From 46645ee014faa11469bf87d9634e4ba0c13a8595 Mon Sep 17 00:00:00 2001 From: imranalisyed506 <105209301+imranalisyed506@users.noreply.github.com> Date: Fri, 24 May 2024 09:39:11 +0530 Subject: [PATCH] Cisco Meraki Collector --- collectors/ciscomeraki/.jshintrc | 15 + collectors/ciscomeraki/.npmrc | 1 + collectors/ciscomeraki/LICENSE | 8 + collectors/ciscomeraki/Makefile | 6 + collectors/ciscomeraki/README.md | 149 ++++ .../ciscomeraki/al-ciscomeraki-collector.json | 6 + .../cfn/ciscomeraki-collector.template | 115 +++ collectors/ciscomeraki/collector.js | 238 +++++ .../ciscomeraki/docs/Ciscomeraki_img1.png | Bin 0 -> 69341 bytes .../ciscomeraki/docs/Ciscomeraki_img2.png | Bin 0 -> 71049 bytes .../ciscomeraki/docs/Ciscomerakiorg.png | Bin 0 -> 81651 bytes collectors/ciscomeraki/index.js | 23 + collectors/ciscomeraki/local/env.json.tmpl | 17 + .../ciscomeraki/local/events/event.json | 16 + .../ciscomeraki/local/events/event_poll.json | 20 + .../local/events/event_register.json | 16 + .../local/events/event_selfupdate.json | 4 + collectors/ciscomeraki/local/run-sam.sh | 51 ++ .../ciscomeraki/local/sam-template.yaml | 48 + collectors/ciscomeraki/package.json | 36 + .../ciscomeraki/test/ciscomeraki_mock.js | 104 +++ .../ciscomeraki/test/ciscomeraki_test.js | 829 ++++++++++++++++++ collectors/ciscomeraki/test/utils_test.js | 452 ++++++++++ collectors/ciscomeraki/utils.js | 223 +++++ 24 files changed, 2377 insertions(+) create mode 100644 collectors/ciscomeraki/.jshintrc create mode 100644 collectors/ciscomeraki/.npmrc create mode 100644 collectors/ciscomeraki/LICENSE create mode 100644 collectors/ciscomeraki/Makefile create mode 100644 collectors/ciscomeraki/README.md create mode 100644 collectors/ciscomeraki/al-ciscomeraki-collector.json create mode 100644 collectors/ciscomeraki/cfn/ciscomeraki-collector.template create mode 100644 collectors/ciscomeraki/collector.js create mode 100644 collectors/ciscomeraki/docs/Ciscomeraki_img1.png create mode 100644 collectors/ciscomeraki/docs/Ciscomeraki_img2.png create mode 100644 collectors/ciscomeraki/docs/Ciscomerakiorg.png create mode 100644 collectors/ciscomeraki/index.js create mode 100644 collectors/ciscomeraki/local/env.json.tmpl create mode 100644 collectors/ciscomeraki/local/events/event.json create mode 100644 collectors/ciscomeraki/local/events/event_poll.json create mode 100644 collectors/ciscomeraki/local/events/event_register.json create mode 100644 collectors/ciscomeraki/local/events/event_selfupdate.json create mode 100755 collectors/ciscomeraki/local/run-sam.sh create mode 100644 collectors/ciscomeraki/local/sam-template.yaml create mode 100644 collectors/ciscomeraki/package.json create mode 100644 collectors/ciscomeraki/test/ciscomeraki_mock.js create mode 100644 collectors/ciscomeraki/test/ciscomeraki_test.js create mode 100644 collectors/ciscomeraki/test/utils_test.js create mode 100644 collectors/ciscomeraki/utils.js diff --git a/collectors/ciscomeraki/.jshintrc b/collectors/ciscomeraki/.jshintrc new file mode 100644 index 00000000..d847dead --- /dev/null +++ b/collectors/ciscomeraki/.jshintrc @@ -0,0 +1,15 @@ +{ + "esversion": 8, + "shadow": "outer", + "undef": true, + "unused": "vars", + "node": true, + "predef": [ + "it", + "describe", + "before", + "after", + "beforeEach", + "afterEach" + ] +} diff --git a/collectors/ciscomeraki/.npmrc b/collectors/ciscomeraki/.npmrc new file mode 100644 index 00000000..43c97e71 --- /dev/null +++ b/collectors/ciscomeraki/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/collectors/ciscomeraki/LICENSE b/collectors/ciscomeraki/LICENSE new file mode 100644 index 00000000..6eac43de --- /dev/null +++ b/collectors/ciscomeraki/LICENSE @@ -0,0 +1,8 @@ +Copyright 2019 ALERT LOGIC + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + diff --git a/collectors/ciscomeraki/Makefile b/collectors/ciscomeraki/Makefile new file mode 100644 index 00000000..2bc6a0c3 --- /dev/null +++ b/collectors/ciscomeraki/Makefile @@ -0,0 +1,6 @@ +AWS_LAMBDA_FUNCTION_NAME ?= alertlogic-ciscomeraki-collector +AWS_LAMBDA_PACKAGE_NAME ?= al-ciscomeraki-collector.zip +AWS_LAMBDA_CONFIG_PATH ?= ./al-ciscomeraki-collector.json +AWS_CFN_TEMPLATE_PATH ?= ./cfn/ciscomeraki-collector.template + +-include ../collector.mk diff --git a/collectors/ciscomeraki/README.md b/collectors/ciscomeraki/README.md new file mode 100644 index 00000000..96d120e7 --- /dev/null +++ b/collectors/ciscomeraki/README.md @@ -0,0 +1,149 @@ +# Ciscomeraki collector +Alert Logic Ciscomeraki AWS Based API Poll (PAWS) Log Collector Library. + +# Overview +This repository contains the AWS JavaScript Lambda function and CloudFormation +Template (CFT) for deploying a log collector in AWS which will poll Ciscomeraki (Network Events) service API to collect and +forward logs to the Alert Logic CloudInsight backend services. + +# Installation + +# Cisco Meraki Dashboard Log Collection Setup + +Instructions for setting up log collection from Cisco Meraki Dashboard using its API. + +## Prerequisites + +1. **Cisco Meraki Dashboard Account**: You need to have access to a Cisco Meraki Dashboard account with administrative privileges. +2. **API Key**: Generate an API key from the Cisco Meraki Dashboard. Follow [this guide](https://developer.cisco.com/meraki/api-v1/authorization/) to obtain your API key. + +## Setup Steps + +1. **Enable API Access**: + - Log in to your [Cisco Meraki Dashboard](https://dashboard.meraki.com) account. + - You need to have access to organizational level administrative privileges. + - Get the Organization ID at the bottom of the page ![ScreenShot](./docs/Ciscomerakiorg.png). + - Navigate to *Organization > Settings*. + - Under *Dashboard API access*, enable API access ![ScreenShot](./docs/Ciscomeraki_img1.png). + +2. **Generate API Key**: + - Go to *My Profile*. + - Under *API access*, generate a new API key ![ScreenShot](./docs/Ciscomeraki_img2.png). + +3. **Collect Network Events**: + - Refer to the [Cisco Meraki Dashboard API documentation](https://developer.cisco.com/meraki/api/) for details on how to use the API to retrieve [network events](https://developer.cisco.com/meraki/api-v1/get-network-events/). + - Example API endpoint: `GET /organizations/{organizationId}/networks/{networkId}/events` + +4. **Handle Authentication**: + - Include your API key in the request headers for authentication. + - Example: `X-Cisco-Meraki-API-Key: YOUR_API_KEY` + +### Rate Limits +- Cisco Meraki Dashboard imposes rate limits on API requests to ensure fair usage and prevent abuse. Refer to the [Rate Limits documentation](https://developer.cisco.com/meraki/api-v1/rate-limit/) for details on the specific limits for different endpoints. +- Ensure that your application adheres to these rate limits to avoid throttling errors. + +### Organization Call Budget +- Each Meraki organization has a call budget of **10 requests per second**, regardless of the number of API applications interacting with that organization. + +### Throttling Errors +- Throttling errors occur when your API requests exceed the allowed rate limit. When a throttling error occurs, the API will return an HTTP 429 status code along with an error message. +- Refer to the [Throttling Errors documentation](https://developer.cisco.com/meraki/api/#/rest/guides/throttling-errors) for information on how to handle throttling errors and retry mechanisms. + +### 2. API Docs + +1. [Network Events](https://developer.cisco.com/meraki/api-v1/get-network-events/) + + This endpoint allows you to retrieve network events from **all networks** within an organization, filtered by specific product types such as "appliance", "switch", and more. These events provide insights into network changes, device status updates, and other relevant activities. + + +API URLs required for Ciscomeraki collector for Example + +| URL | +|--------------------------------------| +| https://n219.meraki.com/organizations/{organizationId}/networks/{networkId}/events | + +## Support + +If you encounter any issues or have questions, please reach out to Cisco Meraki support or refer to their documentation. + +Refer to [CF template readme](./cfn/README.md) for installation instructions. + +# How it works + +## Update Trigger + +The `Updater` is a timer triggered function that runs a deployment sync operation +every 12 hours in order to keep the collector lambda function up to date. +The `Updater` syncs from the Alert Logic S3 bucket where you originally deployed from. + +## Collection Trigger + +The `Collector` function is an AWS lambda function which is triggered by SQS which contains collection state message. +During each invocation the function polls 3rd party service log API and sends retrieved data to +AlertLogic `Ingest` service for further processing. + +## Checkin Trigger + +The `Checkin` Scheduled Event trigger is used to report the health and status of +the Alert Logic AWS lambda collector to the `Azcollect` back-end service based on +an AWS Scheduled Event that occurs every 15 minutes. + + +# Development + +## Creating New Collector Types +run `npm run create-collector <> <>` to create a skeleton collector in the `collectors` folder. + +## Build collector +Clone this repository and build a lambda package by executing: +``` +$ git clone https://github.com/alertlogic/paws-collector.git +$ cd paws-collector/collectors/ciscomeraki +$ make deps test package +``` + +The package name is *al-ciscomeraki-collector.zip* + +## Debugging + +To get a debug trace, set an Node.js environment variable called DEBUG and +specify the JavaScript module/s to debug. + +E.g. + +``` +export DEBUG=* +export DEBUG=index +``` + +Or set an environment variable called "DEBUG" in your AWS stack (using the AWS +console) for a collector AWS Lambda function, with value "index" or "\*". + +See [debug](https://www.npmjs.com/package/debug) for further details. + +## Invoking locally + +In order to invoke lambda locally please follow the [instructions](https://docs.aws.amazon.com/lambda/latest/dg/sam-cli-requirements.html) to install AWS SAM. +AWS SAM uses `default` credentials profile from `~/.aws/credentials`. + + 1. Encrypt the key using aws cli: +``` +aws kms encrypt --key-id KMS_KEY_ID --plaintext AIMS_SECRET_KEY +``` + 2. Include the encrypted token, and `KmsKeyArn` that you used in Step 1 inside my SAM yaml: +``` + KmsKeyArn: arn:aws:kms:us-east-1:xxx:key/yyy + Environment: + Variables: +``` + 3. Fill in environment variables in `env.json` (including encrypted AIMS secret key) and invoke locally: + +``` +cp ./local/env.json.tmpl ./local/env.json +vi ./local/env.json +make test +make sam-local +``` + 4. Please see `local/event.json` for the event payload used for local invocation. +Please write your readme here + diff --git a/collectors/ciscomeraki/al-ciscomeraki-collector.json b/collectors/ciscomeraki/al-ciscomeraki-collector.json new file mode 100644 index 00000000..650b2fcb --- /dev/null +++ b/collectors/ciscomeraki/al-ciscomeraki-collector.json @@ -0,0 +1,6 @@ +{ + "Runtime": { + "path": "Runtime", + "value": "nodejs18.x" + } +} diff --git a/collectors/ciscomeraki/cfn/ciscomeraki-collector.template b/collectors/ciscomeraki/cfn/ciscomeraki-collector.template new file mode 100644 index 00000000..8a7d287d --- /dev/null +++ b/collectors/ciscomeraki/cfn/ciscomeraki-collector.template @@ -0,0 +1,115 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Description": "Alert Logic template for creating a CiscoMeraki log collector", + "Parameters": { + "AlertlogicAccessKeyId": { + "Description": "Alert Logic Access Key Id obtained from AIMS", + "Type": "String" + }, + "AlertlogicSecretKey": { + "Description": "Alert Logic Secret Key returned from AIMS for the Access Key Id", + "Type": "String", + "NoEcho": true + }, + "AlApplicationId": { + "Description": "Alert Logic Application Id for collector logs", + "Type": "String", + "Default": "ciscomeraki" + }, + "AlApiEndpoint": { + "Description": "Alert Logic API endpoint", + "Type": "String", + "Default": "api.global-services.global.alertlogic.com", + "AllowedValues": [ + "api.global-services.global.alertlogic.com", + "api.global-integration.product.dev.alertlogic.com" + ] + }, + "AlDataResidency": { + "Description": "Alert Logic Data Residency", + "Type": "String", + "Default": "default", + "AllowedValues": ["default"] + }, + "PackagesBucketPrefix": { + "Description": "S3 bucket name prefix where collector packages are located.", + "Type": "String", + "Default": "alertlogic-collectors" + }, + "PawsCollectorTypeName": { + "Description": "A collector type name. For example, okta, auth0", + "Type": "String", + "Default": "ciscomeraki" + }, + "AlertlogicCustomerId": { + "Description": "Optional. Alert Logic customer ID which collected data should be reported for. If not set customer ID is derived from AIMs tokens", + "Type": "String", + "Default": "" + }, + "CollectorId": { + "Description": "Optional. A collector UUID if known.", + "Type": "String", + "Default": "none" + }, + "CiscoMerakiEndpoint": { + "Description": "Cisco Meraki API URL to poll. For Example https://n149.meraki.com/api/v1", + "Type": "String" + }, + "CiscoMerakiClientId": { + "Description": "Cisco Meraki Client ID for oauth2 authentication type", + "Type": "String" + }, + "CiscoMerakiSecret": { + "Description": "Cisco Meraki Client Secret API Key for authentication.", + "Type": "String", + "NoEcho": true + }, + "CiscoMerakiOrgKey": { + "Description": "Cisco Meraki Organisation Key, used for collection of network events", + "Type": "String", + "Default": "" + }, + "CiscoMerakiProductTypes": { + "Description": "Define Product Types. Please pass JSON formatted list of product types. Possible values are [\"appliances\",\"switch\",\"systemsManager\"]", + "Type": "String", + "Default": "" + }, + "CollectionStartTs": { + "Description": "Timestamp when log collection starts. For example, 2019-11-21T16:00:00Z", + "Type": "String", + "Default" : "", + "AllowedPattern" : "(?:^\\d{4}(-\\d{2}){2}T(\\d{2}:){2}\\d{2}Z$)?" + } + }, + "Resources":{ + "CiscoMerakiCollectorStack" : { + "Type" : "AWS::CloudFormation::Stack", + "Properties" : { + "TemplateURL" : {"Fn::Join" : ["", [ + "https://s3.amazonaws.com/", + {"Ref":"PackagesBucketPrefix"}, "-us-east-1", + "/cfn/paws-collector.template" + ]]}, + "Parameters" : { + "AlertlogicAccessKeyId" : { "Ref":"AlertlogicAccessKeyId" }, + "AlertlogicSecretKey" : { "Ref":"AlertlogicSecretKey" }, + "AlApplicationId" : { "Ref":"AlApplicationId" }, + "AlApiEndpoint" : { "Ref":"AlApiEndpoint" }, + "AlDataResidency" : { "Ref":"AlDataResidency" }, + "PackagesBucketPrefix" : { "Ref":"PackagesBucketPrefix" }, + "PawsCollectorTypeName" : "ciscomeraki", + "AlertlogicCustomerId" : { "Ref":"AlertlogicCustomerId" }, + "CollectorId" : { "Ref":"CollectorId" }, + "PollingInterval" : 60, + "PawsEndpoint" : { "Ref":"CiscoMerakiEndpoint" }, + "PawsAuthType" : "oauth2", + "PawsClientId" : "", + "CollectorParamString1" : { "Ref":"CiscoMerakiProductTypes" }, + "CollectorParamString2" : { "Ref":"CiscoMerakiOrgKey" }, + "PawsSecret" : { "Ref":"CiscoMerakiSecret" }, + "CollectionStartTs" : { "Ref":"CollectionStartTs" } + } + } + } + } +} diff --git a/collectors/ciscomeraki/collector.js b/collectors/ciscomeraki/collector.js new file mode 100644 index 00000000..688cf061 --- /dev/null +++ b/collectors/ciscomeraki/collector.js @@ -0,0 +1,238 @@ +/* ----------------------------------------------------------------------------- + * @copyright (C) 2024, Alert Logic, Inc + * @doc + * + * ciscomeraki class. + * + * @end + * ----------------------------------------------------------------------------- + */ +'use strict'; + +const moment = require('moment'); +const PawsCollector = require('@alertlogic/paws-collector').PawsCollector; +const parse = require('@alertlogic/al-collector-js').Parse; +const packageJson = require('./package.json'); +const calcNextCollectionInterval = require('@alertlogic/paws-collector').calcNextCollectionInterval; +const utils = require("./utils"); +const AlLogger = require('@alertlogic/al-aws-collector-js').Logger; +const MAX_POLL_INTERVAL = 900; +const API_THROTTLING_ERROR = 429; +const API_NOT_FOUND_ERROR = 404; + +let typeIdPaths = [{ path: ["type"] }]; +let tsPaths = [{ path: ["occurredAt"] }]; + +class CiscomerakiCollector extends PawsCollector { + constructor(context, creds) { + super(context, creds, packageJson.version); + } + + async pawsInitCollectionState(event, callback) { + const resourceNames = process.env.collector_streams ? JSON.parse(process.env.collector_streams) : []; + try { + if (resourceNames.length > 0) { + const initialStates = this.generateInitialStates(resourceNames); + return callback(null, initialStates, 1); + } + else { + let networks = await utils.getAllNetworks(callback); + if (networks.length > 0) { + const initialStates = this.generateInitialStates(networks); + return callback(null, initialStates, 1); + } else { + return callback("Error: No networks found"); + } + } + + } catch (error) { + return callback(error); + } + } + + generateInitialStates(networkIds) { + const startTs = process.env.paws_collection_start_ts ? + process.env.paws_collection_start_ts : + moment().toISOString(); + const endTs = moment(startTs).add(this.pollInterval, 'seconds').toISOString(); + const initialStates = networkIds.map(networkId => ({ + networkId: networkId, + since: startTs, + until: endTs, + nextPage: null, + poll_interval_sec: parseInt(Math.floor(Math.random() * 30) + 1) + })); + return initialStates; + } + + async handleEvent(event) { + let collector = this; + let context = this._invokeContext; + let parsedEvent = collector._parseEvent(event); + + switch (parsedEvent.RequestType) { + case 'ScheduledEvent': + switch (parsedEvent.Type) { + case 'SelfUpdate': + collector.handleUpdateStreamsFromNetworks(); + return collector.handleUpdate(); + break; + default: + super.handleEvent(event); + } + default: + super.handleEvent(event); + } + } + + async handleUpdateStreamsFromNetworks() { + let collector = this; + //get networks from api + let networks = await utils.getAllNetworks(); + const keyValue = `${process.env.customer_id}/${collector._pawsCollectorType}/${collector.collector_id}/networks_${collector.collector_id}.json`; + + let params = await utils.getS3ObjectParams(keyValue, undefined); + //get networks json from s3 bucket + let networksFromS3 = await utils.fetchJsonFromS3Bucket(params.bucketName, params.key); + if (networks.length > 0 && Array.isArray(networksFromS3) && networksFromS3.length > 0) { + let differenceNetworks = utils.differenceOfNetworksArray(networks, networksFromS3); + AlLogger.debug(`CMRI0000024 Networks updated ${JSON.stringify(differenceNetworks)}`); + + if (differenceNetworks.length > 0) { + const initialStates = this.generateInitialStates(differenceNetworks); + AlLogger.debug(`CMRI0000020: SQS message added ${JSON.stringify(initialStates)}`); + collector._storeCollectionState({}, initialStates, this.pollInterval, () => { + utils.uploadNetworksListInS3Bucket(keyValue, networks); + }); + } else { + utils.uploadNetworksListInS3Bucket(keyValue, networks); + } + } else if (networksFromS3 && (networksFromS3.Code === 'NoSuchKey' || networksFromS3.Code === 'AccessDenied')) { + await utils.uploadNetworksListInS3Bucket(keyValue, networks); + } + } + + pawsGetLogs(state, callback) { + const collector = this; + + const productTypes = process.env.paws_collector_param_string_1 ? JSON.parse(process.env.paws_collector_param_string_1) : []; + if (!productTypes) { + return callback("The Product Types was not found!"); + } + const { clientSecret, apiEndpoint, orgKey } = utils.getOrgKeySecretEndPoint(collector.secret, callback); + const apiDetails = utils.getAPIDetails(orgKey, productTypes); + if (!apiDetails.url) { + return callback("The API name was not found!"); + } + AlLogger.info(`CMRI000001 Collecting data for NetworkId-${state.networkId} from ${state.since}`); + utils.getAPILogs(apiDetails, [], apiEndpoint, state, clientSecret, process.env.paws_max_pages_per_invocation) + .then(({ accumulator, nextPage }) => { + let newState; + if (nextPage === undefined) { + newState = this._getNextCollectionState(state); + } else { + newState = this._getNextCollectionStateWithNextPage(state, nextPage); + } + AlLogger.info(`CMRI000002 Next collection in ${newState.poll_interval_sec} seconds`); + return callback(null, accumulator, newState, newState.poll_interval_sec); + }) + .catch((error) => { + if (error && error.response && error.response.status == API_THROTTLING_ERROR) { + collector.handleThrottlingError(error, state, callback); + } else { + collector.handleOtherErrors(error, state, callback); + } + }); + } + + handleThrottlingError(error, state, callback) { + const maxRandom = 5; + let retry = parseInt(error.response.headers['retry-after']) || 1; + retry += Math.floor(Math.random() * (maxRandom + 1)); + state.poll_interval_sec = state.poll_interval_sec < MAX_POLL_INTERVAL ? + parseInt(state.poll_interval_sec) + retry : MAX_POLL_INTERVAL; + AlLogger.info(`CMRI000007 Throttling error, retrying after ${state.poll_interval_sec} sec`); + this.reportApiThrottling(function () { + return callback(null, [], state, state.poll_interval_sec); + }); + } + + handleOtherErrors(error, state, callback) { + if (error && error.response && error.response.status == API_NOT_FOUND_ERROR) { + console.error('error.response.status>>>', error.response.status, JSON.stringify(state)); + state.retry = state.retry ? state.retry + 1 : 1; + if (state.retry > 3) { + AlLogger.debug(`CMRI0000021 Deleted SQS message from Queue${JSON.stringify(state)}`); + this._invokeContext.succeed(); + } else { + return callback(error); + } + } else if (error && error.response && error.response.data) { + AlLogger.debug(`CMRI0000022 error ${error.response.data.errors} - status: ${error.response.status}`); + error.response.data.errorCode = error.response.status; + return callback(error.response.data); + } else { + return callback(error); + } + } + + _getNextCollectionState(curState) { + const untilMoment = moment(curState.until); + const { nextUntilMoment, nextSinceMoment, nextPollInterval } = calcNextCollectionInterval('no-cap', untilMoment, this.pollInterval); + return { + networkId: curState.networkId, + since: nextSinceMoment.toISOString(), + until: nextUntilMoment.toISOString(), + nextPage: null, + poll_interval_sec: nextPollInterval + }; + } + + _getNextCollectionStateWithNextPage({ networkId, since, until }, nextPage) { + const obj = { + networkId, + since: nextPage, + until, + nextPage: null, + poll_interval_sec: 1 + }; + return obj; + } + + pawsGetRegisterParameters(event, callback) { + const regValues = { + ciscoMerakiObjectNames: process.env.collector_streams + }; + callback(null, regValues); + } + + pawsFormatLog(msg) { + // TODO: double check that this message parsing fits your use case + let collector = this; + + let ts = parse.getMsgTs(msg, tsPaths); + let typeId = parse.getMsgTypeId(msg, typeIdPaths); + + let formattedMsg = { + hostname: collector.collector_id, + messageTs: ts.sec, + priority: 11, + progName: 'CiscomerakiCollector', + message: JSON.stringify(msg), + messageType: 'json/ciscomeraki', + application_id: collector.application_id + }; + + if (typeId !== null && typeId !== undefined) { + formattedMsg.messageTypeId = `${typeId}`; + } + if (ts.usec) { + formattedMsg.messageTsUs = ts.usec; + } + return formattedMsg; + } +} + +module.exports = { + CiscomerakiCollector: CiscomerakiCollector +} \ No newline at end of file diff --git a/collectors/ciscomeraki/docs/Ciscomeraki_img1.png b/collectors/ciscomeraki/docs/Ciscomeraki_img1.png new file mode 100644 index 0000000000000000000000000000000000000000..c7ff2b9f1596e1f0e3095927f7deb66369a62070 GIT binary patch literal 69341 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 z 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 TvBPNx_`7&s=iIZiR=58H)N>gq literal 0 HcmV?d00001 diff --git a/collectors/ciscomeraki/docs/Ciscomeraki_img2.png b/collectors/ciscomeraki/docs/Ciscomeraki_img2.png new file mode 100644 index 0000000000000000000000000000000000000000..955046fe96b862045707b64b46181fd64ebccba9 GIT binary patch literal 71049 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

4j5ls3lhdou-*R|a3(PwTi-;b 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

6puP`4k6jnu0EZ~~C$KdBQ-EEYj~ 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 literal 0 HcmV?d00001 diff --git a/collectors/ciscomeraki/index.js b/collectors/ciscomeraki/index.js new file mode 100644 index 00000000..c36b4f98 --- /dev/null +++ b/collectors/ciscomeraki/index.js @@ -0,0 +1,23 @@ +/* ----------------------------------------------------------------------------- + * @copyright (C) 2019, Alert Logic, Inc + * @doc + * + * Ciscomeraki System logs extension. + * + * @end + * ----------------------------------------------------------------------------- + */ + +const debug = require('debug') ('index'); +const AlLogger = require('@alertlogic/al-aws-collector-js').Logger; +const CiscomerakiCollector = require('./collector').CiscomerakiCollector; + +exports.handler = CiscomerakiCollector.makeHandler(function(event, context) { + debug('input event: ', event); + AlLogger.defaultMeta = { requestId: context.awsRequestId }; + var ciscomerakic; + CiscomerakiCollector.load().then(function(creds) { + ciscomerakic = new CiscomerakiCollector(context, creds); + ciscomerakic.handleEvent(event); + }); +}); diff --git a/collectors/ciscomeraki/local/env.json.tmpl b/collectors/ciscomeraki/local/env.json.tmpl new file mode 100644 index 00000000..b33666f9 --- /dev/null +++ b/collectors/ciscomeraki/local/env.json.tmpl @@ -0,0 +1,17 @@ +{ + "LocalLambda": { + "aims_secret_key": "aims-secret-key-ecnrypted-with-kms-key-from-sam-template", + "aims_access_key_id": "aims-key-id", + "al_api": "api.product.dev.alertlogic.com", + "stack_name": "some-stack", + "azollect_api": "api.product.dev.alertlogic.com", + "ingest_api": "api.global-integration.us-west-2.product.dev.alertlogic.com", + "DEBUG": "*", + "paws_state_queue_arn" :"arn:aws:sqs:us-east-1:352283894008:paws-state-queue", + "paws_state_queue_url" :"https://sqs.us-east-1.amazonaws.com/352283894008/paws-state-queue", + "paws_poll_interval": "900", + "paws_extension": "ciscomeraki", + "sample-custom-var": "https://some-endpoint.com/", + "collector_id": "557D90CB-0BA2-40EC-8A9D-94184612C084" + } +} diff --git a/collectors/ciscomeraki/local/events/event.json b/collectors/ciscomeraki/local/events/event.json new file mode 100644 index 00000000..faafcf55 --- /dev/null +++ b/collectors/ciscomeraki/local/events/event.json @@ -0,0 +1,16 @@ +{ + "RequestType": "Create", + "ServiceToken": "arn:aws:lambda:eu-west-1:352283894008:function:username-test-remov-GetEndpointsLambdaFuncti-RVS9Y1YR1GJR", + "ResponseURL": "https://cloudformation-custom-resource-response-euwest1.s3-eu-west-1.amazonaws.com", + "StackId": "arn:aws:cloudformation:eu-west-1:352283894008:stack/username-test-removed-creds-4/b8d29ba0-c499-11e7-a296-503abe701cd1", + "RequestId": "f0e0cab3-b258-4058-b56a-820c76ff30a5", + "LogicalResourceId": "EndpointAPIs", + "ResourceType": "AWS::CloudFormation::CustomResource", + "ResourceProperties": { + "ServiceToken": "arn:aws:lambda:eu-west-1:352283894008:function:username-test-remov-GetEndpointsLambdaFuncti-RVS9Y1YR1GJR", + "StackName": "username-test-1", + "AwsAccountId": "352283894008", + "VpcId" : "vpc-id", + "LogGroup" : "log-group-name" + } +} diff --git a/collectors/ciscomeraki/local/events/event_poll.json b/collectors/ciscomeraki/local/events/event_poll.json new file mode 100644 index 00000000..3904efce --- /dev/null +++ b/collectors/ciscomeraki/local/events/event_poll.json @@ -0,0 +1,20 @@ +{ + "Records": [ + { + "messageId": "c8bf6989-ccad-4276-8674-62d36403abb5", + "receiptHandle": "AQEB78LmKaaZ+uj8DVnc/O2zQcAe+qKSi3ZGTSBFssIRSmpwwzUEi2vhPTaIBnhOoh0aoRxVjWdoXO3ZloINfMxmcjycP3KC0WXwcWokoOc3iMCdqhYg0NcOhQW1X0ixc79C9/5/XF1xGd79vLhFL7KvRjjiT4sOaSxlAv6v2fJ5eDETnp7CRa5pocCF4EO2su0M4/TnlLreGfsY+C+/tH+r19AM+d3Jt5dbNMrKMWRRZ7/PTjczkIM7U38AHPuusuBz9uzA5yMQGOMI8FPXfqgcafEN17JqKuNSd/l54v1+s9rBQSzL/MH9wZ0XpZditcpe5pTc+dGuRHOXbFK2A0YUQCvRq1Ed8tfr68uELTQK5jWHH/zPnEMWsTyco9VuNCKr", + "body": "{\n \"priv_collector_state\": {\n \n \"since\": \"2024-04-18T16:15:00.000Z\",\n \"until\": \"2024-04-18T16:35:42.740Z\",\n \"nextPage\": null,\n \"networkId\": \"L_686235993220604684\",\n \"poll_interval_sec\": 60,\n \"apiQuotaResetDate\": \"2023-07-07T06:27:42.740Z\" }\n}", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1574159909907", + "SenderId": "some-id", + "ApproximateFirstReceiveTimestamp": "1574159909968" + }, + "messageAttributes": {}, + "md5OfBody": "1845296051d4cfe2e6175358a065cc38", + "eventSource": "aws:sqs", + "eventSourceARN": "arn:aws:sqs:us-east-1:352283894008:paws-state-queue", + "awsRegion": "us-east-1" + } + ] +} diff --git a/collectors/ciscomeraki/local/events/event_register.json b/collectors/ciscomeraki/local/events/event_register.json new file mode 100644 index 00000000..a9410b18 --- /dev/null +++ b/collectors/ciscomeraki/local/events/event_register.json @@ -0,0 +1,16 @@ +{ + "RequestType": "Create", + "ServiceToken": "arn:aws:lambda:eu-west-1:352283894008:function:username-test-remov-GetEndpointsLambdaFuncti-RVS9Y1YR1GJR", + "ResponseURL": "https://cloudformation-custom-resource-response-euwest1.s3-eu-west-1.amazonaws.com/", + "StackId": "arn:aws:cloudformation:eu-west-1:352283894008:stack/username-test-removed-creds-4/b8d29ba0-c499-11e7-a296-503abe701cd1", + "RequestId": "f0e0cab3-b258-4058-b56a-820c76ff30a5", + "LogicalResourceId": "EndpointAPIs", + "ResourceType": "AWS::CloudFormation::CustomResource", + "ResourceProperties": { + "ServiceToken": "arn:aws:lambda:eu-west-1:352283894008:function:username-test-remov-GetEndpointsLambdaFuncti-RVS9Y1YR1GJR", + "StackName": "username-test-1", + "AwsAccountId": "352283894008", + "VpcId" : "vpc-id", + "LogGroup" : "log-group-name" + } +} diff --git a/collectors/ciscomeraki/local/events/event_selfupdate.json b/collectors/ciscomeraki/local/events/event_selfupdate.json new file mode 100644 index 00000000..d83226b2 --- /dev/null +++ b/collectors/ciscomeraki/local/events/event_selfupdate.json @@ -0,0 +1,4 @@ +{ + "RequestType": "ScheduledEvent", + "Type": "SelfUpdate" +} \ No newline at end of file diff --git a/collectors/ciscomeraki/local/run-sam.sh b/collectors/ciscomeraki/local/run-sam.sh new file mode 100755 index 00000000..60f8f082 --- /dev/null +++ b/collectors/ciscomeraki/local/run-sam.sh @@ -0,0 +1,51 @@ +#!/bin/bash +SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) +SAM_TEMPLATE_NAME="sam-template.yaml" +ENV_FILE_NAME="env.json" +EVENT_FILE_NAME="event_poll.json" +SRC_SAM_TEMPLATE="${SCRIPT_DIR}/sam-template.yaml" +SRC_ENV_FILE="${SCRIPT_DIR}/${ENV_FILE_NAME}" +SRC_EVENT_FILE="${SCRIPT_DIR}/events/${EVENT_FILE_NAME}" +RUN_DIR=${SCRIPT_DIR}/../ +PROFILE_NAME="" + +exists(){ + command -v "$1" >/dev/null 2>&1 +} + +if exists jq; then + uid=`uuidgen` + LOWERUUID=$(echo "$uid" | tr '[:upper:]' '[:lower:]') + echo "generating messageId in event.json: ${LOWERUUID}" + jq --arg newRandomvalue $LOWERUUID '(.Records[].messageId) |= $newRandomvalue' ${SRC_EVENT_FILE} > tmp && mv tmp ${SRC_EVENT_FILE} +else + echo "jq does not exist please install jq to run command" +fi + +command -v sam > /dev/null +if [ $? -ne 0 ]; then + echo "sam not found. +Please follow the installation instructions https://docs.aws.amazon.com/lambda/latest/dg/sam-cli-requirements.html" + exit 0 +fi + +if [ ! -f ${SRC_ENV_FILE} ]; then + echo "${SRC_ENV_FILE} doesn't exist. Please copy and fill in ${SRC_ENV_FILE}.tmpl" + exit 0 +fi + +ln -sf ${SRC_SAM_TEMPLATE} ${RUN_DIR}/${SAM_TEMPLATE_NAME} +ln -sf ${SRC_ENV_FILE} ${RUN_DIR}/${ENV_FILE_NAME} +ln -sf ${SRC_EVENT_FILE} ${RUN_DIR}/${EVENT_FILE_NAME} +cd ${RUN_DIR} && \ +sam local invoke \ + --profile ${PROFILE_NAME} \ + --env-vars ${ENV_FILE_NAME} \ + -t ${SAM_TEMPLATE_NAME}\ + -e ${EVENT_FILE_NAME}\ + --region us-east-1\ + "LocalLambda" + +unlink ${RUN_DIR}/${SAM_TEMPLATE_NAME} +unlink ${RUN_DIR}/${ENV_FILE_NAME} +unlink ${RUN_DIR}/${EVENT_FILE_NAME} diff --git a/collectors/ciscomeraki/local/sam-template.yaml b/collectors/ciscomeraki/local/sam-template.yaml new file mode 100644 index 00000000..802e046c --- /dev/null +++ b/collectors/ciscomeraki/local/sam-template.yaml @@ -0,0 +1,48 @@ +AWSTemplateFormatVersion : '2010-09-09' +Transform: AWS::Serverless-2016-10-31 + +Description: Run it locally +Resources: + LocalLambda: + Type: AWS::Serverless::Function + Properties: + KmsKeyArn: arn:aws:kms:us-east-1:352283894008:key/c31cd559-a589-417b-91bb-19bfbcba903f + Environment: + Variables: + AWS_LAMBDA_FUNCTION_NAME: + aims_secret_key: + LOG_LEVEL: + # DEBUG: + aims_access_key_id: + al_api: + stack_name: + azcollect_api: + ingest_api: + collector_status_api: + paws_state_queue_arn: + paws_state_queue_url: + paws_poll_interval: + paws_extension: + paws_collector_param_string_1: + paws_collector_param_string_2: + paws_api_client_id: + collector_streams: + paws_type_name: "ciscomeraki" + paws_max_pages_per_invocation: + paws_secret_param_name: + paws_api_secret: + collector_id: + customer_id: + paws_endpoint: + paws_ddb_table_name: + ssm_direct: + collector_status_api: + paws_poll_interval_delay: + secret: + dl_s3_bucket_name: + CodeUri: + Runtime: nodejs18.x + Handler: index.handler + Timeout: 300 + MemorySize: 1024 + diff --git a/collectors/ciscomeraki/package.json b/collectors/ciscomeraki/package.json new file mode 100644 index 00000000..a87c75d5 --- /dev/null +++ b/collectors/ciscomeraki/package.json @@ -0,0 +1,36 @@ +{ + "name": "ciscomeraki-collector", + "version": "1.0.0", + "description": "Alert Logic AWS based Ciscomeraki Log Collector", + "repository": {}, + "private": true, + "scripts": { + "lint": "jshint --exclude \"./node_modules/*\" **/*.js", + "test": "JUNIT_REPORT_PATH=./test/report.xml nyc --reporter=text mocha --colors" + }, + "devDependencies": { + "@aws-sdk/client-cloudformation": "^3.454.0", + "@aws-sdk/client-cloudwatch": "^3.454.0", + "@aws-sdk/client-dynamodb": "^3.454.0", + "@aws-sdk/client-kms": "^3.454.0", + "@aws-sdk/client-lambda": "^3.454.0", + "@aws-sdk/client-s3": "^3.456.0", + "@aws-sdk/client-sqs": "^3.454.0", + "@aws-sdk/client-ssm": "^3.454.0", + "jshint": "^2.9.5", + "mocha": "^10.2.0", + "mocha-jenkins-reporter": "^0.4.2", + "nyc": "^15.1.0", + "rewire": "^7.0.0", + "sinon": "^17.0.0" + }, + "dependencies": { + "@alertlogic/al-collector-js": "3.0.10", + "@alertlogic/paws-collector": "2.2.1", + "async": "^3.2.4", + "debug": "^4.3.4", + "moment": "2.29.4" + + }, + "author": "Alert Logic Inc." +} \ No newline at end of file diff --git a/collectors/ciscomeraki/test/ciscomeraki_mock.js b/collectors/ciscomeraki/test/ciscomeraki_mock.js new file mode 100644 index 00000000..0a728922 --- /dev/null +++ b/collectors/ciscomeraki/test/ciscomeraki_mock.js @@ -0,0 +1,104 @@ +process.env.AWS_REGION = 'us-east-1'; +process.env.al_api = 'api.global-services.global.alertlogic.com'; +process.env.ingest_api = 'ingest.global-services.global.alertlogic.com'; +process.env.azollect_api = 'azcollect.global-services.global.alertlogic.com'; +process.env.collector_status_api = 'collector_status.global-services.global.alertlogic.com'; + +process.env.aims_access_key_id = 'aims-key-id'; +process.env.aims_secret_key = 'aims-secret-key-encrypted'; +process.env.log_group = 'logGroupName'; +process.env.paws_state_queue_arn = "arn:aws:sqs:us-east-1:352283894008:paws-state-queue"; +process.env.paws_extension = 'ciscomeraki'; +process.env.ciscomeraki_endpoint = 'https://test.alertlogic.com/'; +process.env.ciscomeraki_token = 'ciscomeraki-token'; +process.env.collector_id = 'collector-id'; +process.env.al_application_id = 'application_id'; +process.env.paws_secret_param_name = "ciscomeraki-param-name"; +process.env.paws_poll_interval = 60; +process.env.paws_type_name = "ciscomeraki"; +process.env.paws_collector_param_string_2 = "12345"; +process.env.paws_collector_param_string_1 = "[\"appliance\",\"systemsManager\",\"switch\"]"; +process.env.paws_api_secret = "secret"; +process.env.paws_endpoint = "api.meraki.com"; +process.env.collector_streams = "[\"L_686235993220604684\"]"; +process.env.paws_api_client_id = "client-id"; +process.env.paws_poll_interval_delay = 300; + +const AIMS_TEST_CREDS = { + access_key_id: 'test-access-key-id', + secret_key: 'test-secret-key' +}; + +const LOG_EVENT = { + "occurredAt": "2024-03-19T05:10:47.055027Z", + "networkId": "L_686235993220604684", + "type": "client_vpn", + "description": "Client VPN negotiation", + "clientId": null, + "clientDescription": null, + "clientMac": "", + "category": "wired_only_client_vpn", + "deviceSerial": "Q3FA-KM7T-NYGZ", + "deviceName": "", + "eventData": { + "msg": " deleting IKE_SA l2tp-over-ipsec-1[97] between 209.163.151.90[209.163.151.90]...117.200.14.68[192.168.1.6]" + } + }; + + const NETWORKS = [ + { + id: 'L_686235993220604684', + organizationId: '1547127', + name: 'Alert Logic Test Kit', + productTypes: [ + 'appliance', + 'camera', + 'cellularGateway', + 'sensor', + 'switch', + 'wireless' + ], + timeZone: 'America/Los_Angeles', + tags: [], + enrollmentString: null, + url: 'https://n219.meraki.com/Alert-Logic-Test/n/el2PiaBd/manage/usage/list', + notes: 'Test node', + isBoundToConfigTemplate: false + }, + { + id: 'L_686235993220604720', + organizationId: '1547127', + name: 'Alert Logic Test Kit 1 ', + productTypes: [ + 'appliance', + 'camera', + 'cellularGateway', + 'sensor', + 'switch', + 'wireless' + ], + timeZone: 'America/Los_Angeles', + tags: [], + enrollmentString: null, + url: 'https://n219.meraki.com/Alert-Logic-Test/n/yNvOHaBd/manage/usage/list', + notes: 'Test node', + isBoundToConfigTemplate: false + } + ]; + +const mockInitialStates = [ + { networkId: 'L_686235993220604684', since: '2024-03-20T07:24:34.657Z', until: '2024-03-20T07:25:34.657Z', nextPage: null }, + { networkId: 'L_686235993220604682', since: '2024-03-20T07:24:34.657Z', until: '2024-03-20T07:25:34.657Z', nextPage: null } +]; + +const FUNCTION_ARN = 'arn:aws:lambda:us-east-1:352283894008:function:test-01-CollectLambdaFunction-2CWNLPPW5XO8'; +const FUNCTION_NAME = 'test-TestCollectLambdaFunction-1JNNKQIPOTEST'; + +module.exports = { + AIMS_TEST_CREDS: AIMS_TEST_CREDS, + FUNCTION_ARN: FUNCTION_ARN, + FUNCTION_NAME: FUNCTION_NAME, + LOG_EVENT: LOG_EVENT, + NETWORKS:NETWORKS, + mockInitialStates:mockInitialStates +}; diff --git a/collectors/ciscomeraki/test/ciscomeraki_test.js b/collectors/ciscomeraki/test/ciscomeraki_test.js new file mode 100644 index 00000000..a1819199 --- /dev/null +++ b/collectors/ciscomeraki/test/ciscomeraki_test.js @@ -0,0 +1,829 @@ +const sinon = require('sinon'); +const assert = require('assert'); + +const ciscomerakiMock = require('./ciscomeraki_mock'); +var CiscomerakiCollector = require('../collector').CiscomerakiCollector; +const m_response = require('cfn-response'); +const moment = require('moment'); +const utils = require("../utils"); + +const { CloudWatch } = require("@aws-sdk/client-cloudwatch"), + { KMS } = require("@aws-sdk/client-kms"), + { SSM } = require("@aws-sdk/client-ssm"); + +var responseStub = {}; +let getAPIDetails; +let getAPILogs; +let getAllNetworks; + +describe('Unit Tests', function () { + beforeEach(function () { + sinon.stub(SSM.prototype, 'getParameter').callsFake(function (params, callback) { + const data = Buffer.from('test-secret'); + return callback(null, { Parameter: { Value: data.toString('base64') } }); + }); + sinon.stub(KMS.prototype, 'decrypt').callsFake(function (params, callback) { + const data = { + Plaintext: Buffer.from('{}') + }; + return callback(null, data); + }); + + responseStub = sinon.stub(m_response, 'send').callsFake( + function fakeFn(event, mockContext, responseStatus, responseData, physicalResourceId) { + mockContext.succeed(); + }); + }); + + afterEach(function () { + responseStub.restore(); + KMS.prototype.decrypt.restore(); + SSM.prototype.getParameter.restore(); + }); + + describe('Paws Get Register Parameters', function () { + it('Paws Get Register Parameters Success', function (done) { + let ctx = { + invokedFunctionArn: ciscomerakiMock.FUNCTION_ARN, + fail: function (error) { + assert.fail(error); + done(); + }, + succeed: function () { + done(); + } + }; + + CiscomerakiCollector.load().then(function (creds) { + var collector = new CiscomerakiCollector(ctx, creds, 'ciscomeraki'); + const sampleEvent = { ResourceProperties: { StackName: 'a-stack-name' } }; + collector.pawsGetRegisterParameters(sampleEvent, (err, regValues) => { + const expectedRegValues = { + ciscoMerakiObjectNames: process.env.collector_streams, + }; + assert.deepEqual(regValues, expectedRegValues); + done(); + }); + }); + }); + }); + + describe('Paws Init Collection State', function () { + let ctx = { + invokedFunctionArn: ciscomerakiMock.FUNCTION_ARN, + fail: function (error) { + assert.fail(error); + }, + succeed: function () { } + }; + it('Paws Init Collection State Success', function (done) { + getAllNetworks = sinon.stub(utils, 'getAllNetworks').callsFake( + function fakeFn(client, objectDetails, state, accumulator, maxPagesPerInvocation) { + return new Promise(function (resolve, reject) { + return resolve(ciscomerakiMock.NETWORKS); + }); + }); + CiscomerakiCollector.load().then(function (creds) { + var collector = new CiscomerakiCollector(ctx, creds, 'ciscomeraki'); + const startDate = moment().subtract(1, 'days').toISOString(); + process.env.paws_collection_start_ts = startDate; + + collector.pawsInitCollectionState(null, (err, initialStates, nextPoll) => { + initialStates.forEach((state) => { + if (state.networkId === "L_686235993220604684") { + assert.equal(state.networkId, "L_686235993220604684"); + } else if (state.networkId === "L_686235993220604720") { + assert.equal(state.networkId, "L_686235993220604720"); + } + else { + assert.equal(state.poll_interval_sec, 1); + assert.ok(state.since); + } + }); + }); + }); + done(); + }); + it('Paws Init Collection State with networks', function (done) { + process.env.collector_streams = []; + // Mocking utils.getAllNetworks to return a non-empty array + getAllNetworks = sinon.stub(utils, 'getAllNetworks').callsFake( + function fakeFn(callback) { + return new Promise(function (resolve, reject) { + resolve(ciscomerakiMock.NETWORKS); + }); + }); + + CiscomerakiCollector.load().then(function (creds) { + var collector = new CiscomerakiCollector(ctx, creds, 'ciscomeraki'); + const startDate = moment().subtract(1, 'days').toISOString(); + process.env.paws_collection_start_ts = startDate; + + collector.pawsInitCollectionState(null, (err, initialStates, nextPoll) => { + // Asserting that initialStates are generated correctly + assert.equal(initialStates.length, ciscomerakiMock.NETWORKS.length); + initialStates.forEach((state) => { + assert.ok(state.networkId); // Assuming networkId exists in each state + }); + done(); + }); + }); + }); + + it('Paws Init Collection State without networks', function (done) { + process.env.collector_streams = []; + getAllNetworks = sinon.stub(utils, 'getAllNetworks').callsFake( + function fakeFn(callback) { + return new Promise(function (resolve, reject) { + resolve([]); // Assuming no networks found + }); + }); + + CiscomerakiCollector.load().then(function (creds) { + var collector = new CiscomerakiCollector(ctx, creds, 'ciscomeraki'); + const startDate = moment().subtract(1, 'days').toISOString(); + process.env.paws_collection_start_ts = startDate; + + collector.pawsInitCollectionState(null, (err, initialStates, nextPoll) => { + // Asserting that an error is returned when no networks are found + assert.equal(err, "Error: No networks found"); + done(); + }); + }); + }); + + it('Paws Init Collection State error handling', function (done) { + getAllNetworks = sinon.stub(utils, 'getAllNetworks').rejects(new Error('Network error')); + + CiscomerakiCollector.load().then(function (creds) { + var collector = new CiscomerakiCollector(ctx, creds, 'ciscomeraki'); + const startDate = moment().subtract(1, 'days').toISOString(); + process.env.paws_collection_start_ts = startDate; + + collector.pawsInitCollectionState(null, (err, initialStates, nextPoll) => { + assert.equal(err.message, 'Network error'); + done(); + }); + }); + }); + + afterEach(function () { + getAllNetworks.restore(); + }); + }); + + describe('pawsGetLogs', function () { + let ctx = { + invokedFunctionArn: ciscomerakiMock.FUNCTION_ARN, + fail: function (error) { + assert.fail(error); + }, + succeed: function () { } + }; + it('Paws Get Logs Success', function (done) { + getAPILogs = sinon.stub(utils, 'getAPILogs').callsFake( + function fakeFn(client, objectDetails, state, accumulator, maxPagesPerInvocation) { + return new Promise(function (resolve, reject) { + return resolve({ accumulator: [ciscomerakiMock.LOG_EVENT, ciscomerakiMock.LOG_EVENT] }); + }); + }); + getAPIDetails = sinon.stub(utils, 'getAPIDetails').callsFake( + function fakeFn(state) { + return { + url: "api_url", + method: "GET", + requestBody: "", + orgKey: "1234", + productTypes: ["appliance"] + + }; + }); + getAllNetworks = sinon.stub(utils, 'getAllNetworks').callsFake( + function fakeFn(client, objectDetails, state, accumulator, maxPagesPerInvocation) { + return new Promise(function (resolve, reject) { + return resolve(ciscomerakiMock.NETWORKS); + }); + }); + CiscomerakiCollector.load().then(function (creds) { + var collector = new CiscomerakiCollector(ctx, creds, 'ciscomeraki'); + const curState = { + networkId: "L_686235993220604684", + since: "2024-03-19T05:10:47.055027Z", + until: null, + nextPage: null, + poll_interval_sec: 1 + }; + collector.pawsGetLogs(curState, (err, logs, newState, newPollInterval) => { + assert.equal(logs.length, 2); + assert.equal(newState.poll_interval_sec, 300); + assert.ok(logs[0].type); + getAPILogs.restore(); + getAllNetworks.restore(); + getAPIDetails.restore(); + }); + + done(); + + }); + }); + + it('Paws Get Logs With NextPage Success', function (done) { + getAllNetworks = sinon.stub(utils, 'getAllNetworks').callsFake( + function fakeFn(client, objectDetails, state, accumulator, maxPagesPerInvocation) { + return new Promise(function (resolve, reject) { + return resolve(ciscomerakiMock.NETWORKS); + }); + }); + getAPILogs = sinon.stub(utils, 'getAPILogs').callsFake( + function fakeFn(client, objectDetails, state, accumulator, maxPagesPerInvocation) { + return new Promise(function (resolve, reject) { + return resolve({ accumulator: [ciscomerakiMock.LOG_EVENT, ciscomerakiMock.LOG_EVENT], nextPage: "nextPage" }); + }); + }); + getAPIDetails = sinon.stub(utils, 'getAPIDetails').callsFake( + function fakeFn(state) { + return { + url: "api_url", + method: "GET", + requestBody: "", + orgKey: "1234", + productTypes: ["appliance"] + + }; + }); + CiscomerakiCollector.load().then(function (creds) { + var collector = new CiscomerakiCollector(ctx, creds, 'ciscomeraki'); + const startDate = "2024-03-21T08:00:21.754Z"; + const curState = { + networkId: "L_686235993220604684", + since: startDate.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, 1); + assert.equal(newState.nextPage, null); + assert.equal(newState.since, 'nextPage'); + assert.ok(logs[0].type); + getAPILogs.restore(); + getAPIDetails.restore(); + getAllNetworks.restore(); + + done(); + }); + + }); + }); + + it('Paws Get client error', function (done) { + + getAPILogs = sinon.stub(utils, 'getAPILogs').callsFake( + function fakeFn(client, objectDetails, state, accumulator, maxPagesPerInvocation) { + return new Promise(function (resolve, reject) { + return reject({ + code: 401, + message: 'Invalid API key', + response: { + data: { errors: ['Invalid API key'] }, + status: 401 + } + }); + }); + }); + getAPIDetails = sinon.stub(utils, 'getAPIDetails').callsFake( + function fakeFn(state) { + return { + url: "api_url", + method: "GET", + requestBody: "", + orgKey: "1234", + productTypes: ["appliance"] + + }; + }); + CiscomerakiCollector.load().then(function (creds) { + var collector = new CiscomerakiCollector(ctx, creds, 'ciscomeraki'); + const startDate = moment(); + const curState = { + networkId: "L_686235993220604684", + since: startDate.valueOf(), + nextPage: null, + poll_interval_sec: 1 + }; + collector.pawsGetLogs(curState, (err, logs, newState, newPollInterval) => { + assert.equal(err.errorCode, 401); + getAPILogs.restore(); + getAPIDetails.restore(); + done(); + }); + + }); + }); + + it('Paws Get Logs check throttling error', function (done) { + + getAPILogs = sinon.stub(utils, 'getAPILogs').callsFake( + function fakeFn(client, objectDetails, state, accumulator, maxPagesPerInvocation) { + return new Promise(function (resolve, reject) { + return reject({ + code: 429, + message: 'Too Many Requests', + response: { + data: { errors: ['Too Many Requests'] }, + headers: { 'retry-after': 360 }, + status: 429 + }, + stat: 'FAIL', "errorCode": 429 + }); + }); + }); + getAPIDetails = sinon.stub(utils, 'getAPIDetails').callsFake( + function fakeFn(state) { + return { + url: "api_url", + method: "GET", + requestBody: "", + orgKey: "1234", + productTypes: ["appliance"] + + }; + }); + CiscomerakiCollector.load().then(function (creds) { + var collector = new CiscomerakiCollector(ctx, creds, 'ciscomeraki'); + const startDate = moment(); + const curState = { + networkId: "L_686235993220604684", + since: startDate.valueOf(), + nextPage: null, + poll_interval_sec: 1 + }; + + var reportSpy = sinon.spy(collector, 'reportApiThrottling'); + let putMetricDataStub = sinon.stub(CloudWatch.prototype, 'putMetricData').callsFake((params, callback) => callback()); + collector.pawsGetLogs(curState, (err, logs, newState, newPollInterval) => { + assert.equal(true, reportSpy.calledOnce); + assert.equal(logs.length, 0); + assert.notEqual(newState.poll_interval_sec, 1); + getAPILogs.restore(); + getAPIDetails.restore(); + putMetricDataStub.restore(); + done(); + }); + + }); + }); + // it('Handles successful API log retrieval with logs and next page', function (done) { + // getAPILogs = sinon.stub(utils, 'getAPILogs').callsFake( + // function fakeFn(client, objectDetails, state, accumulator, maxPagesPerInvocation) { + // return new Promise(function (resolve, reject) { + // return resolve({ accumulator: [ciscomerakiMock.LOG_EVENT, ciscomerakiMock.LOG_EVENT], nextPage: "nextPage" }); + // }); + // }); + // getAPIDetails = sinon.stub(utils, 'getAPIDetails').callsFake( + // function fakeFn(state) { + // return { + // url: "api_url", + // method: "GET", + // requestBody:"", + // orgKey:"1234", + // productTypes:["appliance"] + + // }; + // }); + // getAllNetworks = sinon.stub(utils, 'getAllNetworks').callsFake( + // function fakeFn(client, objectDetails, state, accumulator, maxPagesPerInvocation) { + // return new Promise(function (resolve, reject) { + // return resolve(ciscomerakiMock.NETWORKS); + // }); + // }); + // CiscomerakiCollector.load().then(function (creds) { + // var collector = new CiscomerakiCollector(ctx, creds, 'ciscomeraki'); + // const curState = { + // networkId: "L_686235993220604684", + // since: "2024-03-19T05:10:47.055027Z", + // until: null, + // nextPage: null, + // poll_interval_sec: 1 + // }; + // collector.pawsGetLogs(curState, (err, logs, newState, newPollInterval) => { + // assert.equal(logs.length, 2); + // assert.equal(newState.poll_interval_sec, 300); + // assert.ok(logs[0].type); + // assert.equal(newState.nextPage, "nextPage"); + // getAPILogs.restore(); + // getAPIDetails.restore(); + // getAllNetworks.restore(); + // done(); + // }); + // }); + // }); + }); + + describe('Next state tests', function () { + let ctx = { + invokedFunctionArn: ciscomerakiMock.FUNCTION_ARN, + fail: function (error) { + assert.fail(error); + }, + succeed: function () { } + }; + + it('Next state tests success with L_686235993220604684', function (done) { + CiscomerakiCollector.load().then(function (creds) { + var collector = new CiscomerakiCollector(ctx, creds, 'ciscomeraki'); + const startDate = moment(); + const curState = { + networkId: "L_686235993220604684", + since: startDate.valueOf(), + until: startDate.add(collector.pollInterval, 'seconds').valueOf(), + nextPage: null, + poll_interval_sec: 1 + }; + let nextState = collector._getNextCollectionState(curState); + assert.equal(nextState.poll_interval_sec, process.env.paws_poll_interval_delay); + done(); + }); + }); + + }); + + describe('Format Tests', function () { + it('log format success', function (done) { + let ctx = { + invokedFunctionArn: ciscomerakiMock.FUNCTION_ARN, + fail: function (error) { + assert.fail(error); + done(); + }, + succeed: function () { + done(); + } + }; + + CiscomerakiCollector.load().then(function (creds) { + var collector = new CiscomerakiCollector(ctx, creds, 'ciscomeraki'); + let fmt = collector.pawsFormatLog(ciscomerakiMock.LOG_EVENT); + assert.equal(fmt.progName, 'CiscomerakiCollector'); + assert.ok(fmt.message); + done(); + }); + }); + }); + + describe('NextCollectionStateWithNextPage', function () { + let ctx = { + invokedFunctionArn: ciscomerakiMock.FUNCTION_ARN, + fail: function (error) { + assert.fail(error); + }, + succeed: function () { } + }; + it('Get Next Collection State (L_686235993220604684) With NextPage Success', function (done) { + const startDate = moment(); + const curState = { + networkId: "L_686235993220604684", + since: startDate.valueOf(), + poll_interval_sec: 1 + }; + const nextPage = "nextPage"; + CiscomerakiCollector.load().then(function (creds) { + var collector = new CiscomerakiCollector(ctx, creds, 'ciscomeraki'); + let nextState = collector._getNextCollectionStateWithNextPage(curState, nextPage); + assert.ok(nextState.since); + assert.equal(nextState.since, nextPage); + done(); + }); + }); + it('Get Next Collection State (L_686235993220604684) With NextPage Success', function (done) { + const startDate = moment(); + const curState = { + networkId: "L_686235993220604684", + since: startDate.unix(), + poll_interval_sec: 1 + }; + const nextPageTimestamp = "1574157600"; + CiscomerakiCollector.load().then(function (creds) { + var collector = new CiscomerakiCollector(ctx, creds, 'ciscomeraki'); + let nextState = collector._getNextCollectionStateWithNextPage(curState, nextPageTimestamp); + assert.ok(nextState.since); + assert.equal(nextState.since, nextPageTimestamp); + done(); + }); + }); + }); + describe('Next Collection State Calculation', function () { + let ctx = { + invokedFunctionArn: ciscomerakiMock.FUNCTION_ARN, + fail: function (error) { + assert.fail(error); + }, + succeed: function () { } + }; + it('should calculate the next collection state correctly', function (done) { + const curState = { + networkId: "L_686235993220604684", + since: moment().valueOf(), + poll_interval_sec: 1 + }; + + const expectedNextState = { + networkId: 'L_686235993220604684', + since: moment().toISOString(), + until: moment().add(1, 'minutes').toISOString(), + nextPage: null, + poll_interval_sec: '300' + }; + CiscomerakiCollector.load().then(function (creds) { + var collector = new CiscomerakiCollector(ctx, creds, 'ciscomeraki'); + let nextState = collector._getNextCollectionState(curState); + assert.deepEqual(nextState.poll_interval_sec, expectedNextState.poll_interval_sec); + done(); + }); + }); + + it('handles ScheduledEvent with SelfUpdate', function (done) { + let updateNetworksStub; + CiscomerakiCollector.load().then(function (creds) { + var collector = new CiscomerakiCollector(ctx, creds, 'ciscomeraki'); + const event = { RequestType: 'ScheduledEvent', Type: 'SelfUpdate' }; + updateNetworksStub = sinon.stub(collector, 'handleUpdateStreamsFromNetworks'); + collector.handleEvent(event); + assert(updateNetworksStub.calledOnce); + updateNetworksStub.restore(); + done(); + }); + }); + it('handles other event types', () => { + + let updateNetworksStub; + CiscomerakiCollector.load().then(function (creds) { + var collector = new CiscomerakiCollector(ctx, creds, 'ciscomeraki'); + const event = { RequestType: 'OtherEventType' }; + collector.handleEvent(event); + assert(!updateNetworksStub.called); + updateNetworksStub.restore(); + }); + + }); + it('updates networks', () => { + let updateNetworksStub; + CiscomerakiCollector.load().then(function (creds) { + var collector = new CiscomerakiCollector(ctx, creds, 'ciscomeraki'); + updateNetworksStub.returns(Promise.resolve()); + collector.handleScheduledEvent({ Type: 'SelfUpdate' }); + assert(updateNetworksStub.calledOnce); + updateNetworksStub.restore(); + }); + }); + + }); + + describe('Error Handling', function () { + describe('handleThrottlingError', function () { + it('should retry after adding random time to poll_interval_sec', function () { + const error = { + response: { + headers: { + 'retry-after': '10' + } + } + }; + const state = { + poll_interval_sec: 1 + }; + const callback = sinon.stub(); + + let ctx = { + invokedFunctionArn: ciscomerakiMock.FUNCTION_ARN, + fail: function (error1) { + assert.fail(error1); + }, + succeed: function () { } + }; + CiscomerakiCollector.load().then(function (creds) { + var collector = new CiscomerakiCollector(ctx, creds, 'ciscomeraki'); + + collector.handleThrottlingError(error, state, callback); + + assert.strictEqual(callback.calledOnce, true); + assert.strictEqual(typeof callback.args[0][0], 'object'); + assert.strictEqual(callback.args[0][1].length, 0); + assert.strictEqual(callback.args[0][2], state); + assert.strictEqual(typeof callback.args[0][3], 'number'); + }); + }); + }); + + describe('handleOtherErrors', function () { + it('should retry if API_NOT_FOUND_ERROR occurs less than 3 times', function () { + const error = { + response: { + status: CiscomerakiCollector.API_NOT_FOUND_ERROR + } + }; + const state = { + retry: 2 + }; + const callback = sinon.stub(); + + let ctx = { + invokedFunctionArn: ciscomerakiMock.FUNCTION_ARN, + fail: function (error1) { + assert.fail(error1); + }, + succeed: function () { } + }; + CiscomerakiCollector.load().then(function (creds) { + var collector = new CiscomerakiCollector(ctx, creds, 'ciscomeraki'); + + collector.handleOtherErrors(error, state, callback); + + assert.strictEqual(callback.calledOnce, false); + assert.strictEqual(state.retry, 3); + }); + }); + + it('should succeed if API_NOT_FOUND_ERROR occurs 3 times', function () { + const error = { + response: { + status: CiscomerakiCollector.API_NOT_FOUND_ERROR + } + }; + const state = { + retry: 3 + }; + + let ctx = { + invokedFunctionArn: ciscomerakiMock.FUNCTION_ARN, + fail: function (error1) { + assert.fail(error1); + }, + succeed: function () { } + }; + CiscomerakiCollector.load().then(function (creds) { + var collector = new CiscomerakiCollector(ctx, creds, 'ciscomeraki'); + + const succeedStub = sinon.stub(collector._invokeContext, 'succeed'); + + collector.handleOtherErrors(error, state, () => { }); + + assert.strictEqual(succeedStub.calledOnce, true); + }); + }); + + it('should return error if response has data', function () { + const error = { + response: { + data: { + errors: ['Invalid API key'] + }, + status: 401 + } + }; + const state = {}; + + let ctx = { + invokedFunctionArn: ciscomerakiMock.FUNCTION_ARN, + fail: function (error1) { + assert.fail(error1); + }, + succeed: function () { } + }; + CiscomerakiCollector.load().then(function (creds) { + var collector = new CiscomerakiCollector(ctx, creds, 'ciscomeraki'); + + const callbackStub = sinon.stub(); + + collector.handleOtherErrors(error, state, callbackStub); + + assert.strictEqual(callbackStub.calledOnce, true); + assert.deepStrictEqual(callbackStub.args[0][0], { + errors: ['Invalid API key'], + errorCode: 401 + }); + }); + }); + + it('should return original error if response has no data', function () { + const error = { + response: { + status: 500 + } + }; + const state = {}; + + let ctx = { + invokedFunctionArn: ciscomerakiMock.FUNCTION_ARN, + fail: function (error1) { + assert.fail(error1); + }, + succeed: function () { } + }; + CiscomerakiCollector.load().then(function (creds) { + + var collector = new CiscomerakiCollector(ctx, creds, 'ciscomeraki'); + + const callbackStub = sinon.stub(); + + collector.handleOtherErrors(error, state, callbackStub); + + assert.strictEqual(callbackStub.calledOnce, true); + assert.strictEqual(callbackStub.args[0][0], error); + }); + }); + }); + }); + +}); + +describe('handleUpdateStreamsFromNetworks Function', function () { + let uploadStub; + beforeEach(function () { + sinon.stub(utils, 'getAllNetworks').resolves(['network1', 'network2']); + sinon.stub(utils, 'getS3ObjectParams').resolves({ bucketName: 'testBucket', key: 'testKey' }); + sinon.stub(utils, 'fetchJsonFromS3Bucket').resolves(['network1']); + sinon.stub(utils, 'differenceOfNetworksArray').returns(['network2']); + uploadStub = sinon.stub(utils, 'uploadNetworksListInS3Bucket').resolves(); + }); + + afterEach(function () { + sinon.restore(); + }); + + it('should handle network updates correctly', async function () { + + let ctx = { + invokedFunctionArn: ciscomerakiMock.FUNCTION_ARN, + fail: function (error) { + assert.fail(error); + }, + succeed: function () { } + }; + + return CiscomerakiCollector.load().then(async function (creds) { + var collector = new CiscomerakiCollector(ctx, creds, 'ciscomeraki'); + + sinon.stub(collector, '_storeCollectionState').callsFake(function (_, __, ___, callback) { + callback(); + }); + + await collector.handleUpdateStreamsFromNetworks(); + + assert.strictEqual(utils.getAllNetworks.callCount, 1); + assert.strictEqual(utils.getS3ObjectParams.callCount, 1); + assert.strictEqual(utils.fetchJsonFromS3Bucket.callCount, 1); + assert.strictEqual(utils.differenceOfNetworksArray.callCount, 1); + assert.strictEqual(uploadStub.callCount, 1); + sinon.restore(); + }); + }); + + it('should handle network updates when no networks from S3 are found', async function () { + let ctx = { + invokedFunctionArn: ciscomerakiMock.FUNCTION_ARN, + fail: function (error) { + assert.fail(error); + }, + succeed: function () { } + }; + + return CiscomerakiCollector.load().then(async function (creds) { + const collector = new CiscomerakiCollector(ctx, creds, 'ciscomeraki'); + sinon.stub(collector, '_storeCollectionState').callsFake(function (_, __, ___, callback) { + callback(); + }); + + await collector.handleUpdateStreamsFromNetworks(); + + assert.strictEqual(utils.getAllNetworks.callCount, 1); + assert.strictEqual(utils.getS3ObjectParams.callCount, 1); + assert.strictEqual(utils.fetchJsonFromS3Bucket.callCount, 1); + assert.strictEqual(uploadStub.callCount, 1); + }); + }); + + it('should handle network updates when S3 fetch returns an error', async function () { + let ctx = { + invokedFunctionArn: ciscomerakiMock.FUNCTION_ARN, + fail: function (error) { + assert.fail(error); + }, + succeed: function () { } + }; + return CiscomerakiCollector.load().then(async function (creds) { + var collector = new CiscomerakiCollector(ctx, creds, 'ciscomeraki'); + sinon.stub(collector, '_storeCollectionState').callsFake(function (_, __, ___, callback) { + callback(); + }); + + await collector.handleUpdateStreamsFromNetworks(); + assert.strictEqual(utils.getAllNetworks.callCount, 1); + assert.strictEqual(utils.getS3ObjectParams.callCount, 1); + assert.strictEqual(utils.fetchJsonFromS3Bucket.callCount, 1); + assert.strictEqual(uploadStub.callCount, 1); + }); + }); +}); + + diff --git a/collectors/ciscomeraki/test/utils_test.js b/collectors/ciscomeraki/test/utils_test.js new file mode 100644 index 00000000..aea70a89 --- /dev/null +++ b/collectors/ciscomeraki/test/utils_test.js @@ -0,0 +1,452 @@ +const sinon = require('sinon'); +const assert = require('assert'); +const axios = require('axios'); +const ciscomerakiMock = require('./ciscomeraki_mock'); +const AlLogger = require('@alertlogic/al-aws-collector-js').Logger; +const AlAwsUtil = require('@alertlogic/al-aws-collector-js').Util; +const { getAPILogs, makeApiCall, getAllNetworks, fetchAllNetworks, getAPIDetails, + fetchJsonFromS3Bucket, differenceOfNetworksArray, getOrgKeySecretEndPoint, getS3ObjectParams, uploadToS3Bucket } = require('../utils'); +const { S3Client } = require("@aws-sdk/client-s3"); + +describe('API Tests', function () { + let axiosGetStub; + + beforeEach(function () { + axiosGetStub = sinon.stub(axios, 'get'); + }); + + afterEach(function () { + axiosGetStub.restore(); + }); + + describe('getAPILogs', function () { + it('should accumulate data from multiple pages', async function () { + axiosGetStub.onFirstCall().returns(Promise.resolve({ + data: { events: [ciscomerakiMock.LOG_EVENT, ciscomerakiMock.LOG_EVENT], pageEndAt: '2024-04-15T10:00:00Z' }, + headers: { link: '; rel=next' } + })); + axiosGetStub.onSecondCall().returns(Promise.resolve({ + data: { events: [ciscomerakiMock.LOG_EVENT, ciscomerakiMock.LOG_EVENT], pageEndAt: '2024-04-15T11:00:00Z' }, + headers: {} + })); + + const apiDetails = { productTypes: ['appliance', 'switch'] }; + const accumulator = []; + const apiEndpoint = 'api.meraki.com'; + const state = { since: '2024-04-14T00:00:00Z', networkId: 'L_686235993220604684' }; + const clientSecret = 'your-secret'; + const maxPagesPerInvocation = 2; + + const result = await getAPILogs(apiDetails, accumulator, apiEndpoint, state, clientSecret, maxPagesPerInvocation); + + assert.deepStrictEqual(result.accumulator, [ciscomerakiMock.LOG_EVENT, ciscomerakiMock.LOG_EVENT, ciscomerakiMock.LOG_EVENT, ciscomerakiMock.LOG_EVENT]); + assert.strictEqual(result.nextPage, undefined); + }); + }); + + describe('makeApiCall', function () { + it('should return response data', async function () { + let url = 'https://api.meraki.com/network/L_686235993220604684/events'; + const apiKey = 'your-api-key'; + const perPage = 10; + const startingAfter = null; + + axiosGetStub.returns(Promise.resolve({ + data: { events: [ciscomerakiMock.LOG_EVENT, ciscomerakiMock.LOG_EVENT] }, + headers: {} + })); + + const response = await makeApiCall(url, apiKey, perPage, startingAfter); + + assert.deepStrictEqual(response.data.events, [ciscomerakiMock.LOG_EVENT, ciscomerakiMock.LOG_EVENT]); + }); + }); + + describe('fetchAllNetworks', function () { + it('should return network data', async function () { + const url = '/api/v1/networks'; + const apiKey = 'your-api-key'; + const apiEndpoint = 'api.meraki.com'; + + axiosGetStub.returns(Promise.resolve({ + data: { networks: ['L_686235993220604684', 'L_686235993220604685'] }, + headers: {} + })); + + const networks = await fetchAllNetworks(url, apiKey, apiEndpoint); + + assert.deepStrictEqual(networks.networks, ['L_686235993220604684', 'L_686235993220604685']); + }); + }); + + describe('getAPIDetails', function () { + it('should return correct API details', function () { + const orgKey = 'your-org-key'; + const productTypes = ['appliance', 'switch']; + + const apiDetails = getAPIDetails(orgKey, productTypes); + + assert.strictEqual(apiDetails.url, '/api/v1/networks'); + assert.strictEqual(apiDetails.method, 'GET'); + assert.strictEqual(apiDetails.requestBody, ''); + assert.strictEqual(apiDetails.orgKey, orgKey); + assert.deepStrictEqual(apiDetails.productTypes, productTypes); + }); + }); + + describe('Error Handling', function () { + it('should handle network errors gracefully', async function () { + axiosGetStub.rejects(new Error('Network error')); + try { + await makeApiCall('https://api.meraki.com/network/L_686235993220604684/events', 'your-api-key', 10); + } catch (error) { + assert.equal(error.message, 'Network error'); + } + }); + }); + + describe('Pagination Handling', function () { + it('should correctly handle the last page of results', async function () { + const apiDetails = { productTypes: ['appliance', 'switch'] }; + const apiEndpoint = 'api.meraki.com'; + const state = { since: '2024-04-14T00:00:00Z', networkId: 'L_686235993220604684' }; + const clientSecret = 'your-secret'; + const maxPagesPerInvocation = 2; + // Assuming you have a way to track the number of calls to axios.get + let callCount = 0; + axiosGetStub.callsFake(function () { + callCount++; + if (callCount === 1) { + return Promise.resolve({ + data: { events: [ciscomerakiMock.LOG_EVENT, ciscomerakiMock.LOG_EVENT], pageEndAt: '2024-04-16T10:00:00Z' }, + headers: {} + }); + } else if (callCount === 2) { + return Promise.resolve({ + data: { events: [ciscomerakiMock.LOG_EVENT, ciscomerakiMock.LOG_EVENT], pageEndAt: '2024-04-16T10:00:00Z' }, + headers: {} + }); + } else { + return Promise.resolve({ + data: { events: [] }, + headers: {} + }); + } + }); + + const result = await getAPILogs(apiDetails, [], apiEndpoint, state, clientSecret, maxPagesPerInvocation); + const mockResults = { nextPage: undefined, accumulator: [ciscomerakiMock.LOG_EVENT, ciscomerakiMock.LOG_EVENT, ciscomerakiMock.LOG_EVENT, ciscomerakiMock.LOG_EVENT] }; + assert.equal(result.accumulator.length, mockResults.accumulator.length); + assert.equal(result.nextPage, mockResults.nextPage); + }); + }); + + describe('Rate Limiting', function () { + it('should apply exponential backoff on rate limit errors', async function () { + axiosGetStub.rejects({ response: { status: 429 } }); + const attemptApiCall = getAllNetworks('/api/v1/networks', 'your-api-key', 'api.meraki.com'); + attemptApiCall.catch((error) => { + assert.include(error.message, '429'); + }); + }); + }); + + describe('API Details Functionality', function () { + it('should construct correct API details for different orgKey and productTypes', function () { + const orgKey1 = 'another-org-key'; + const productTypes1 = ['switch']; + const apiDetails1 = getAPIDetails(orgKey1, productTypes1); + assert.equal(apiDetails1.url, '/api/v1/networks'); + assert.equal(apiDetails1.method, 'GET'); + assert.equal(apiDetails1.requestBody, ''); + assert.equal(apiDetails1.orgKey, orgKey1); + assert.deepEqual(apiDetails1.productTypes, productTypes1); + + const orgKey2 = 'yet-another-org-key'; + const productTypes2 = ['appliance']; + const apiDetails2 = getAPIDetails(orgKey2, productTypes2); + assert.equal(apiDetails2.url, '/api/v1/networks'); + assert.equal(apiDetails2.method, 'GET'); + assert.equal(apiDetails2.requestBody, ''); + assert.equal(apiDetails2.orgKey, orgKey2); + assert.deepEqual(apiDetails2.productTypes, productTypes2); + }); + }); + + describe('fetchAllNetworks Pagination', function () { + it('should paginate through all networks correctly', async function () { + const url = '/api/v1/networks'; + const apiKey = 'your-api-key'; + const apiEndpoint = 'api.meraki.com'; + + axiosGetStub.resolves({ + data: { networks: ['L_686235993220604684', 'L_686235993220604685'], hasNextPage: true }, + headers: { startingAfter: '2024-01-01T00:00:00' } + }); + + const networks = await fetchAllNetworks(url, apiKey, apiEndpoint); + assert.equal(networks.networks.length, 2); + }); + }); + + + + + describe('getAPIDetails Return Values', function () { + it('should return correct API details', function () { + const orgKey = 'your-org-key'; + const productTypes = ['appliance', 'switch']; + + const apiDetails = getAPIDetails(orgKey, productTypes); + + assert.strictEqual(apiDetails.url, '/api/v1/networks'); + assert.strictEqual(apiDetails.method, 'GET'); + assert.strictEqual(apiDetails.requestBody, ''); + assert.strictEqual(apiDetails.orgKey, orgKey); + assert.deepStrictEqual(apiDetails.productTypes, productTypes); + }); + }); + + describe('fetchJsonFromS3Bucket', function () { + it('should fetch JSON data from S3 bucket', async function () { + const bucketName = 'test-bucket'; + const fileName = 'test.json'; + const mockResponseBody = JSON.stringify([{ id: 1, name: "Test" }]); + + const s3SendStub = sinon.stub(S3Client.prototype, 'send').resolves({ + Body: mockResponseBody + }); + + const result = await fetchJsonFromS3Bucket(bucketName, fileName); + + assert.equal(JSON.stringify(result), mockResponseBody); + + s3SendStub.restore(); + }); + }); + + describe('getAPILogs - Max Pages Per Invocation Reached', function () { + it('should stop accumulating logs after maxPagesPerInvocation and return accumulated data', async function () { + const apiDetails = { productTypes: ['appliance', 'switch'] }; + const apiEndpoint = 'api.meraki.com'; + const state = { since: '2024-04-14T00:00:00Z', networkId: 'L_686235993220604684' }; + const clientSecret = 'your-secret'; + const maxPagesPerInvocation = 2; + + axiosGetStub.onFirstCall().returns(Promise.resolve({ + data: { events: [ciscomerakiMock.LOG_EVENT, ciscomerakiMock.LOG_EVENT], startingAfter: '2024-04-15T10:00:00Z' }, + headers: { link: '; rel=next' } + })); + axiosGetStub.onSecondCall().returns(Promise.resolve({ + data: { events: [ciscomerakiMock.LOG_EVENT, ciscomerakiMock.LOG_EVENT], startingAfter: '2024-04-16T10:00:00Z' }, + headers: {} + })); + + const result = await getAPILogs(apiDetails, [], apiEndpoint, state, clientSecret, maxPagesPerInvocation); + + assert.deepStrictEqual(result.accumulator.length, 4); // Total events from both pages + assert.strictEqual(result.nextPage, undefined); // No more pages to fetch + }); + }); + + describe('Error Handling in fetchAllNetworks', function () { + it('should handle non-rate-limit errors gracefully', async function () { + axiosGetStub.rejects({ response: { status: 500 } }); + try { + await fetchAllNetworks('/api/v1/networks', 'your-api-key', 'api.meraki.com'); + } catch (error) { + assert.equal(error.response.status, 500); + } + }); + }); + + describe('differenceOfNetworksArray', function () { + it('should return the difference between two arrays of network IDs', function () { + // Mock data + const newNetworks = ['L_686235993220604684', 'L_686235993220604685', 'L_686235993220604686']; + const oldNetworks = ['L_686235993220604684', 'L_686235993220604686']; + + const difference = differenceOfNetworksArray(newNetworks, oldNetworks); + + assert.deepStrictEqual(difference, ['L_686235993220604685']); + }); + + it('should return an empty array if oldNetworks contains all network IDs from newNetworks', function () { + const newNetworks = ['L_686235993220604684', 'L_686235993220604685']; + const oldNetworks = ['L_686235993220604684', 'L_686235993220604685', 'L_686235993220604686']; + + const difference = differenceOfNetworksArray(newNetworks, oldNetworks); + + assert.deepStrictEqual(difference, []); + }); + + it('should return newNetworks if oldNetworks is empty', function () { + // Mock data + const newNetworks = ['L_686235993220604684', 'L_686235993220604685']; + + const difference = differenceOfNetworksArray(newNetworks, []); + + assert.deepStrictEqual(difference, newNetworks); + }); + + it('should return an empty array if both newNetworks and oldNetworks are empty', function () { + const difference = differenceOfNetworksArray([], []); + + assert.deepStrictEqual(difference, []); + }); + }); + + describe('Error Handling in getAPILogs', function () { + it('should throw an error when networkId is not provided', async function () { + const apiDetails = { productTypes: ['appliance', 'switch'] }; + const accumulator = []; + const apiEndpoint = 'api.meraki.com'; + const state = { since: '2024-04-14T00:00:00Z' }; + const clientSecret = 'your-secret'; + const maxPagesPerInvocation = 2; + + axiosGetStub.returns(Promise.resolve({ + data: { events: [ciscomerakiMock.LOG_EVENT, ciscomerakiMock.LOG_EVENT], pageEndAt: '2024-04-15T10:00:00Z' }, + headers: { link: '; rel=next' } + })); + + try { + await getAPILogs(apiDetails, accumulator, apiEndpoint, state, clientSecret, maxPagesPerInvocation); + assert.fail('Expected an error to be thrown'); + } catch (error) { + assert.equal(error.message, 'url is not defined'); + } + }); + }); + + describe('getOrgKeySecretEndPoint', function () { + it('should return clientSecret, apiEndpoint, and orgKey when all parameters are provided', function () { + process.env.paws_endpoint = 'https://meraki.com'; + process.env.paws_collector_param_string_2 = 'orgKey123'; + + const callback = sinon.stub(); + const result = getOrgKeySecretEndPoint('mockSecret', callback); + + assert.equal(result.clientSecret, 'mockSecret'); + assert.equal(result.apiEndpoint, 'meraki.com'); + assert.equal(result.orgKey, 'orgKey123'); + sinon.assert.notCalled(callback); + }); + + it('should call callback with error message if clientSecret is missing', function () { + process.env.paws_endpoint = 'https://example.com'; + process.env.paws_collector_param_string_2 = 'orgKey123'; + + const callback = sinon.stub(); + const result = getOrgKeySecretEndPoint(null, callback); + + sinon.assert.calledOnceWithExactly(callback, 'The Client Secret was not found!'); + assert.strictEqual(result, undefined); + }); + + it('should call callback with error message if orgKey is missing', function () { + // Mocking environment variables + process.env.paws_endpoint = 'https://example.com'; + process.env.paws_collector_param_string_2 = ''; + + const callback = sinon.stub(); + const result = getOrgKeySecretEndPoint('mockSecret', callback); + + sinon.assert.calledOnceWithExactly(callback, 'orgKey was not found!'); + assert.strictEqual(result, undefined); + }); + }); + + describe('getS3ObjectParams', function () { + it('should return correct params', async function () { + process.env.dl_s3_bucket_name = 'test-bucket'; + const keyValue = 'test-key'; + const data = { key: 'value' }; + + const params = await getS3ObjectParams(keyValue, data); + + assert.deepStrictEqual(params, { + data: data, + key: keyValue, + bucketName: 'test-bucket' + }); + }); + + it('should handle missing bucket name environment variable', async function () { + delete process.env.dl_s3_bucket_name; + const keyValue = 'test-key'; + const data = { key: 'value' }; + + const params = await getS3ObjectParams(keyValue, data); + + assert.deepStrictEqual(params, { + data: data, + key: keyValue, + bucketName: undefined + }); + }); + }); + + describe('uploadToS3Bucket', function() { + let uploadS3ObjectStub; + let loggerWarnStub; + + beforeEach(function() { + uploadS3ObjectStub = sinon.stub(AlAwsUtil, 'uploadS3Object'); + loggerWarnStub = sinon.stub(AlLogger, 'warn'); + }); + + afterEach(function() { + uploadS3ObjectStub.restore(); + loggerWarnStub.restore(); + }); + + it('should upload data to S3 bucket', function(done) { + const uploadParams = { data: 'test-data', key: 'test-key', bucketName: 'test-bucket' }; + + uploadS3ObjectStub.callsFake((params, callback) => callback(null)); + + uploadToS3Bucket(uploadParams, (err) => { + assert(uploadS3ObjectStub.calledOnce); + assert.strictEqual(err, null); + done(); + }); + }); + + it('should handle upload errors gracefully', function(done) { + const uploadParams = { data: 'test-data', key: 'test-key', bucketName: 'test-bucket' }; + + uploadS3ObjectStub.callsFake((params, callback) => callback(new Error('Upload error'))); + + uploadToS3Bucket(uploadParams, (err) => { + assert(uploadS3ObjectStub.calledOnce); + assert(loggerWarnStub.calledOnce); + assert.strictEqual(err, null); + done(); + }); + }); + + it('should return error if bucket name is missing', function(done) { + const uploadParams = { data: 'test-data', key: 'test-key', bucketName: '' }; + + uploadToS3Bucket(uploadParams, (err) => { + assert.strictEqual(err, 'CMRI0000011 error uploading to undefined bucket'); + done(); + }); + }); + + it('should use default bucket name if not provided', function(done) { + process.env.dl_s3_bucket_name = 'default-bucket'; + const uploadParams = { data: 'test-data', key: 'test-key', bucketName: '' }; + + uploadS3ObjectStub.callsFake((params, callback) => callback(null)); + + uploadToS3Bucket(uploadParams, (err) => { + assert(uploadS3ObjectStub.calledOnce); + assert.strictEqual(err, null); + done(); + }); + }); + }); + +}); diff --git a/collectors/ciscomeraki/utils.js b/collectors/ciscomeraki/utils.js new file mode 100644 index 00000000..615b87d5 --- /dev/null +++ b/collectors/ciscomeraki/utils.js @@ -0,0 +1,223 @@ +const axios = require('axios'); +const AlLogger = require('@alertlogic/al-aws-collector-js').Logger; + +const { S3Client, GetObjectCommand } = require("@aws-sdk/client-s3"); +const AlAwsUtil = require('@alertlogic/al-aws-collector-js').Util; + +const NETWORKS_PER_PAGE = 1000; +const EVENTS_PER_PAGE = 500; +const API_THROTTLING_ERROR = 429; +const DELAY_IN_SECS = 1000; + +async function getAPILogs(apiDetails, accumulator, apiEndpoint, state, clientSecret, maxPagesPerInvocation) { + let nextPage; + let pageCount = 0; + let since; + return new Promise(async (resolve, reject) => { + try { + for (const productType of apiDetails.productTypes) { + pageCount = 0; + since = state.since; + await getData(productType); + } + return resolve({ accumulator, nextPage }); + } catch (error) { + reject(error); + } + }); + + async function getData(productType) { + if (pageCount < maxPagesPerInvocation) { + pageCount++; + try { + if (state.networkId) { + let url = `https://${apiEndpoint}${apiDetails.url}/${state.networkId}/events`; + let response = await makeApiCall(url, clientSecret, EVENTS_PER_PAGE, productType, since); + let data = response && response.data ? response.data.events : []; + AlLogger.debug(`networkId->', ${url}, ' productType->', ${productType}, ' events:', ${data.length}, 'pageCount', ${pageCount}`); + if (data.length) { + accumulator = accumulator.concat(data); + } else { + return accumulator; + } + headers = response.headers; + const linkHeader = response.headers.link; + if (linkHeader && linkHeader.includes('rel=next')) { + const nextLink = linkHeader.match(/<([^>]+)>; rel=next/)[1]; + startingAfter = new URL(nextLink).searchParams.get('startingAfter'); + since = startingAfter; + await getData(productType); + } else { + AlLogger.debug(`CMRI000006 No More Next Page Data Available`); + state.until = response.data.pageEndAt; + } + } + else { + throw new Error(`CMRI000007 Error:NetworkId required in ${url}`); + } + } catch (error) { + throw error; + } + } else { + nextPage = since; + } + } +} + +async function makeApiCall(url, apiKey, perPage, productType, startingAfter = null) { + let fullUrl = `${url}` + + if (perPage) { + fullUrl += `?perPage=${perPage}`; + } + if (productType) { + fullUrl += `&productType=${productType}`; + } + if (startingAfter) { + fullUrl += `&startingAfter=${startingAfter}`; + } + AlLogger.debug(`fullUrl->', ${fullUrl}`); + try { + const response = await axios.get(fullUrl, { + headers: { + 'X-Cisco-Meraki-API-Key': apiKey, + 'Accept': 'application/json', + }, + }); + return response; + } catch (error) { + throw error; + } +} + +async function getAllNetworks(callback) { + const { clientSecret, apiEndpoint, orgKey } = getOrgKeySecretEndPoint(callback); + const url = `/api/v1/organizations/${orgKey}/networks`; + + try { + const networks = await fetchAllNetworks(url, clientSecret, apiEndpoint); + return networks.map(network => network.id); + } catch (error) { + return callback(error); + } +} + +async function fetchAllNetworks(url, apiKey, apiEndpoint) { + let delay = DELAY_IN_SECS; // Initial delay of 1 second + async function attemptApiCall() { + try { + let response = await makeApiCall(`https://${apiEndpoint}/${url}`, apiKey, NETWORKS_PER_PAGE); + return response.data; + } catch (error) { + if (error.response && error.response.status === API_THROTTLING_ERROR) { + // Rate limit exceeded, applying exponential backoff + await new Promise(resolve => setTimeout(resolve, delay)); + delay *= 2; + return attemptApiCall(); + } else { + throw error; + } + } + } + return attemptApiCall(); +} + +function getOrgKeySecretEndPoint(secret,callback) { + const clientSecret = secret; + if (!clientSecret) { + return callback("The Client Secret was not found!"); + } + + const apiEndpoint = process.env.paws_endpoint.replace(/^https:\/\/|\/$/g, ''); + const orgKey = process.env.paws_collector_param_string_2; + if (!orgKey) { + return callback("orgKey was not found!"); + } + + return { clientSecret, apiEndpoint, orgKey }; +} + +function getAPIDetails(orgKey, productTypes) { + let url = "/api/v1/networks"; + let method = "GET"; + let requestBody = ""; + return { + url, + method, + requestBody, + orgKey, + productTypes + }; +} + +function differenceOfNetworksArray(newNetworks, oldNetworks) { + return newNetworks.filter(network => oldNetworks.indexOf(network) === -1); +} + +async function fetchJsonFromS3Bucket(bucketName, fileName, callback) { + try { + const s3Client = new S3Client(); + const getObjectParams = { + Bucket: bucketName, + Key: fileName + }; + const response = await s3Client.send(new GetObjectCommand(getObjectParams)); + + let jsonData = ''; + for await (const chunk of response.Body) { + jsonData += chunk.toString(); + } + const parsedData = JSON.parse(jsonData); + return parsedData; + } catch (error) { + return error; + } +} + +async function getS3ObjectParams(keyValue, data) { + let params = { + data: data, + key: keyValue, + bucketName: process.env.dl_s3_bucket_name + } + return params; +} + +async function uploadNetworksListInS3Bucket(keyValue, networks) { + if (networks.length > 0) { + let params = await getS3ObjectParams(keyValue, networks); + uploadToS3Bucket(params, (err) => { + AlLogger.debug(`CMRI0000010 error while uploading the ${keyValue} : ${JSON.stringify(params)}`); + if (err) { + return err; + } + }); + } +} + +function uploadToS3Bucket({ data, key, bucketName }, callback) { + let bucket = bucketName ? bucketName : process.env.dl_s3_bucket_name; + if (bucket) { + AlAwsUtil.uploadS3Object({ data, key, bucket }, (err) => { + if (err) { + AlLogger.warn(`CMRI0000010 error while uploading the ${key} object in ${bucket} bucket : ${JSON.stringify(err)}`); + } + return callback(null); + }); + } + else return callback(`CMRI0000011 error uploading to ${bucket} bucket`); +} + +module.exports = { + getAPIDetails: getAPIDetails, + makeApiCall: makeApiCall, + getAPILogs: getAPILogs, + getAllNetworks: getAllNetworks, + fetchAllNetworks:fetchAllNetworks, + getOrgKeySecretEndPoint:getOrgKeySecretEndPoint, + uploadNetworksListInS3Bucket: uploadNetworksListInS3Bucket, + getS3ObjectParams: getS3ObjectParams, + uploadToS3Bucket: uploadToS3Bucket, + fetchJsonFromS3Bucket: fetchJsonFromS3Bucket, + differenceOfNetworksArray: differenceOfNetworksArray +}; \ No newline at end of file