Socket
Socket
Sign inDemoInstall

@jupiterone/graph-cisco-amp

Package Overview
Dependencies
Maintainers
1
Versions
16
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@jupiterone/graph-cisco-amp - npm Package Compare versions

Comparing version 0.7.2 to 1.0.0

dist/getStepStartStates.d.ts

22

CHANGELOG.md

@@ -11,2 +11,24 @@ # Changelog

## 1.0.0 - 2022-04-11
### Added
- Added new findings step creating the following entities and relationships:
- `cisco_amp_finding`
- `cisco_amp_vulnerability`
- `cisco_amp_finding_is_vulnerability`
- `cisco_amp_endpoint_identified_finding`
- Added `getStepStartStates` which disables the `findings` step by default. To
enable this step, the IntegrationConfig must have `disableFindingsStep` =
false.
### Changed
- Client now uses `iterateResources` pattern for all steps.
- Endpoint protects device relationship is now correctly classified as a
`mappedRelationship`
## 0.7.2 - 2022-03-31

@@ -13,0 +35,0 @@

46

dist/collector/ServicesClient.d.ts
import { Request } from 'node-fetch';
import { CiscoAmpComputer, CiscoAmpApiResponse } from './types';
import { CiscoAmpComputer, CiscoAmpApiResponse, CiscoAmpVulnerability, CiscoAmpComputerWithVulnerability } from './types';
export interface ServicesClientInput {

@@ -8,2 +8,3 @@ apiEndpoint: string;

}
export declare type ResourceIteratee<T> = (each: T) => Promise<void>;
/**

@@ -17,5 +18,42 @@ * Services Api

constructor(config: ServicesClientInput);
getVersion(): Promise<CiscoAmpApiResponse>;
iterateComputers(): Promise<CiscoAmpComputer[]>;
iterateAll(url: string): Promise<CiscoAmpComputer[]>;
/**
* Gets Cisco AMP Api version
* @returns Promise<CiscoAmpApiResponse<Record<string, never>>>
*/
getVersion(): Promise<CiscoAmpApiResponse<Record<string, never>>>;
/**
* iterateComputers iterates over all computers
* and calls the provided `ResourceIteratee` for each Computer.
*
* @param fn ResourceIteratee that will be called for each Computer
* @returns Promise<void>
*/
iterateComputers(fn: ResourceIteratee<CiscoAmpComputer>): Promise<void>;
/**
* iterateVulnerabilities iterates over all vulnerabilities
* and calls the provided `ResourceIteratee` for each vulnerability.
*
* @param fn ResourceIteratee function tha will be called for each Vulnerability
* @returns Promise<void>
*/
iterateVulnerabilities(fn: ResourceIteratee<CiscoAmpVulnerability>): Promise<void>;
/**
* iteratesComputersWithVulnerability iterates computers with a vulnerability
* identified by a sha256 hash.
*
* This is useful when a vulnerability is present on more than 1000 computers
* as the `/v1/vulnerabilities` response will only contain the first 1000
*
* @param sha256 The sha256 hash of the vulnerability
* @returns Promise<void>
*/
iterateComputersWithVulnerability(sha256: string, fn: ResourceIteratee<CiscoAmpComputerWithVulnerability>): Promise<void>;
/**
* createResourceIterator creates a function that will paginate the resources
* and call the provided `ResourceIteratee` for each resource.
*
* @param url the url whose resources will be iterated
* @returns a function that will call ResourceIteratee for each resource
*/
createResourceIterator(url: string): <T>(fn: ResourceIteratee<T>) => Promise<void>;
fetch<T = object>(url: string, queryParams?: {

@@ -22,0 +60,0 @@ [param: string]: string | string[];

@@ -21,22 +21,70 @@ "use strict";

}
/**
* Gets Cisco AMP Api version
* @returns Promise<CiscoAmpApiResponse<Record<string, never>>>
*/
getVersion() {
return this.fetch('/v1/version');
}
iterateComputers() {
return this.iterateAll('/v1/computers');
/**
* iterateComputers iterates over all computers
* and calls the provided `ResourceIteratee` for each Computer.
*
* @param fn ResourceIteratee that will be called for each Computer
* @returns Promise<void>
*/
async iterateComputers(fn) {
return await this.createResourceIterator('/v1/computers')(fn);
}
async iterateAll(url) {
const data = [];
/**
* iterateVulnerabilities iterates over all vulnerabilities
* and calls the provided `ResourceIteratee` for each vulnerability.
*
* @param fn ResourceIteratee function tha will be called for each Vulnerability
* @returns Promise<void>
*/
async iterateVulnerabilities(fn) {
return await this.createResourceIterator('/v1/vulnerabilities')(fn);
}
/**
* iteratesComputersWithVulnerability iterates computers with a vulnerability
* identified by a sha256 hash.
*
* This is useful when a vulnerability is present on more than 1000 computers
* as the `/v1/vulnerabilities` response will only contain the first 1000
*
* @param sha256 The sha256 hash of the vulnerability
* @returns Promise<void>
*/
async iterateComputersWithVulnerability(sha256, fn) {
return await this.createResourceIterator(`/v1/vulnerabilities/${sha256}/computers`)(fn);
}
/**
* createResourceIterator creates a function that will paginate the resources
* and call the provided `ResourceIteratee` for each resource.
*
* @param url the url whose resources will be iterated
* @returns a function that will call ResourceIteratee for each resource
*/
createResourceIterator(url) {
const limit = 500;
let offset = 0;
let total = 0;
do {
const response = await this.fetch(url, {
offset: offset.toString(),
});
total = response.metadata.results.total;
offset += limit;
data.push(...response.data);
} while (offset < total);
return data;
return async (fn) => {
do {
const response = await this.fetch(url, {
offset: offset.toString(),
});
total = response.metadata.results.total;
offset += limit;
if (Array.isArray(response.data)) {
for (const data of response.data) {
await fn(data);
}
}
else {
await fn(response.data);
}
} while (offset < total);
};
}

@@ -43,0 +91,0 @@ fetch(url, queryParams = {}, request) {

@@ -1,2 +0,1 @@

import { Opaque } from 'type-fest';
export interface PaginationInput {

@@ -12,3 +11,6 @@ limit: string;

}
export interface CiscoAmpApiResponse {
/**
* CiscoAmpApiResponse structure
*/
export interface CiscoAmpApiResponse<T> {
version: string;

@@ -21,6 +23,92 @@ metadata: {

};
data: T[] | T;
}
export interface ListComputersResponse extends CiscoAmpApiResponse {
data: CiscoAmpComputer[];
/**
* CiscoAmpComputer resource structure
*/
export interface CiscoAmpComputer {
connector_guid: string;
hostname: string;
windows_processor_id: string;
active: boolean;
links: {
computer: string;
trajectory: string;
group: string;
};
connector_version: string;
operating_system: string;
internal_ips: string[];
external_ip: string;
group_guid: string;
install_date: string;
is_compromised: boolean;
demo: boolean;
network_addresses: {
mac: string;
ip: string;
}[];
policy: {
guid: string;
name: string;
};
groups: {
guid: string;
name: string;
}[];
last_seen: string;
faults: any[];
isolation: {
available: boolean;
status: string;
};
orbital: {
status: string;
};
}
export declare type CiscoAmpComputer = Opaque<any, 'CiscoAmpComputer'>;
export interface CiscoAmpComputerWithVulnerability {
connector_guid: string;
hostname: string;
windows_processor_id: string;
active: boolean;
links: {
computer: string;
trajectory: string;
group: string;
};
}
export interface CVE {
id: string;
link: string;
cvss: number;
}
export interface CiscoAmpVulnerability {
application: string;
version: string;
file: {
filename: string;
identity: {
sha256: string;
};
};
cves: CVE[];
latest_timestamp: number;
latest_date: string;
groups: {
name: string;
description: string;
guid: string;
}[];
computers_total_count: number;
computers: {
connector_guid: string;
hostname: string;
windows_processor_id: string;
active: boolean;
links: {
computer: string;
trajectory: string;
group: string;
};
}[];
}
import { CiscoAmpComputer } from '../collector';
import { createIntegrationEntity } from '@jupiterone/integration-sdk-core';
import { createIntegrationEntity, Entity } from '@jupiterone/integration-sdk-core';
export declare const convertComputer: (data: CiscoAmpComputer) => ReturnType<typeof createIntegrationEntity>;
/**
*
* @param id: the instance.id
* @param name: the instance.name
* @param description: the instance.description
* @returns Entity
*/
export declare function createAccountEntity({ id, name, description, }: {
id: string;
name: string;
description: string | undefined;
}): Entity;
interface NetworkAddress {

@@ -5,0 +17,0 @@ mac?: string;

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.convertNetworkAddressesToArray = exports.convertComputer = void 0;
exports.convertNetworkAddressesToArray = exports.createAccountEntity = exports.convertComputer = void 0;
const integration_sdk_core_1 = require("@jupiterone/integration-sdk-core");
const constants_1 = require("../steps/constants");
const convertComputer = (data) => {

@@ -29,4 +30,4 @@ var _a, _b, _c, _d;

_key: `cisco-amp-endpoint:${data.connector_guid}`,
_type: 'cisco_amp_endpoint',
_class: ['HostAgent'],
_type: constants_1.Entities.COMPUTER._type,
_class: constants_1.Entities.COMPUTER._class,
id: data.connector_guid,

@@ -37,5 +38,5 @@ name: data.hostname,

function: ['endpoint-protection', 'anti-malware'],
hardwareId: data.mac_hardware_id || data.windows_processor_id,
installedOn: integration_sdk_core_1.getTime(data.install_date),
lastSeenOn: integration_sdk_core_1.getTime(data.last_seen),
hardwareId: data.windows_processor_id,
installedOn: integration_sdk_core_1.parseTimePropertyValue(data.install_date),
lastSeenOn: integration_sdk_core_1.parseTimePropertyValue(data.last_seen),
installDate: undefined,

@@ -64,2 +65,25 @@ lastSeen: undefined,

exports.convertComputer = convertComputer;
/**
*
* @param id: the instance.id
* @param name: the instance.name
* @param description: the instance.description
* @returns Entity
*/
function createAccountEntity({ id, name, description, }) {
return integration_sdk_core_1.createIntegrationEntity({
entityData: {
source: {},
assign: {
_key: `cisco-amp-account:${id}`,
_type: constants_1.Entities.ACCOUNT._type,
_class: constants_1.Entities.ACCOUNT._class,
name: name,
displayName: name,
description: description,
},
},
});
}
exports.createAccountEntity = createAccountEntity;
function convertNetworkAddressesToArray(networkAddressData, key) {

@@ -66,0 +90,0 @@ if (Array.isArray(networkAddressData)) {

6

dist/index.js

@@ -8,8 +8,10 @@ "use strict";

const config_1 = require("./config");
const synchronize_1 = __importDefault(require("./steps/synchronize"));
const getStepStartStates_1 = require("./getStepStartStates");
const steps_1 = require("./steps");
const validateInvocation_1 = __importDefault(require("./validateInvocation"));
exports.invocationConfig = {
instanceConfigFields: config_1.instanceConfigFields,
getStepStartStates: getStepStartStates_1.getStepStartStates,
validateInvocation: validateInvocation_1.default,
integrationSteps: [synchronize_1.default],
integrationSteps: steps_1.integrationSteps,
};

@@ -1,4 +0,4 @@

import { IntegrationStep } from '@jupiterone/integration-sdk-core';
import { IntegrationStep, IntegrationStepExecutionContext } from '@jupiterone/integration-sdk-core';
import { IntegrationConfig } from '../../config';
declare const step: IntegrationStep<IntegrationConfig>;
export default step;
export declare const synchronizeSteps: IntegrationStep<IntegrationConfig>[];
export declare function synchronize({ instance, jobState, }: IntegrationStepExecutionContext<IntegrationConfig>): Promise<void>;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.synchronize = exports.synchronizeSteps = void 0;
const integration_sdk_core_1 = require("@jupiterone/integration-sdk-core");
const collector_1 = require("../../collector");
const converter_1 = require("../../converter");
const step = {
id: 'synchronize',
name: 'Fetch Cisco AMP entities',
entities: [
{
resourceName: 'Account',
_type: 'cisco_amp_account',
_class: 'Account',
},
{
resourceName: 'Computer',
_type: 'cisco_amp_endpoint',
_class: 'HostAgent',
},
],
relationships: [
{
_type: 'cisco_amp_account_has_endpoint',
sourceType: 'cisco_amp_account',
_class: integration_sdk_core_1.RelationshipClass.HAS,
targetType: 'cisco_amp_endpoint',
},
{
_type: converter_1.ENDPOINT_PROTECTION_RELATIONSHIP,
sourceType: 'cisco_amp_endpoint',
_class: integration_sdk_core_1.RelationshipClass.PROTECTS,
targetType: 'user_endpoint',
},
],
async executionHandler({ instance, jobState }) {
const client = collector_1.createServicesClient(instance);
const accountEntity = {
_key: `cisco_amp_account:${instance.id}`,
_type: 'cisco_amp_account',
_class: ['Account'],
name: instance.name,
displayName: instance.name,
description: instance.description,
};
await jobState.addEntities([accountEntity]);
const computers = await client.iterateComputers();
const computerEntities = computers.map(converter_1.convertComputer);
await jobState.addEntities(computerEntities);
const accountComputerRelationships = computerEntities.map((computerEntity) => integration_sdk_core_1.createDirectRelationship({
const constants_1 = require("../constants");
exports.synchronizeSteps = [
{
id: 'synchronize',
name: 'Fetch Cisco AMP entities',
entities: [constants_1.Entities.ACCOUNT, constants_1.Entities.COMPUTER],
relationships: [constants_1.Relationships.ACCOUNT_HAS_ENDPOINT],
mappedRelationships: [constants_1.MappedRelationships.ENDPOINT_PROTECTS_DEVICE],
executionHandler: synchronize,
},
];
async function synchronize({ instance, jobState, }) {
const client = collector_1.createServicesClient(instance);
const accountEntity = await jobState.addEntity(converter_1.createAccountEntity({
id: instance.id,
name: instance.name,
description: instance.description,
}));
await client.iterateComputers(async (computer) => {
const computerEntity = await jobState.addEntity(converter_1.convertComputer(computer));
await jobState.addRelationship(integration_sdk_core_1.createDirectRelationship({
from: accountEntity,

@@ -54,7 +32,5 @@ to: computerEntity,

}));
await jobState.addRelationships(accountComputerRelationships);
const endpointProtectionRelationships = computerEntities.map(converter_1.mapEndpointProtectionRelationship);
await jobState.addRelationships(endpointProtectionRelationships);
},
};
exports.default = step;
await jobState.addRelationship(converter_1.mapEndpointProtectionRelationship(computerEntity));
});
}
exports.synchronize = synchronize;
{
"name": "@jupiterone/graph-cisco-amp",
"version": "0.7.2",
"version": "1.0.0",
"description": "A graph conversion tool for https://www.cisco.com/c/en/us/products/security/amp-for-endpoints/",

@@ -17,3 +17,3 @@ "license": "MPL-2.0",

"graph": "j1-integration visualize",
"start": "yarn collect; yarn graph",
"start": "yarn collect --disable-schema-validation",
"lint": "eslint . --cache --fix --ext .ts,.tsx",

@@ -23,3 +23,4 @@ "format": "prettier --write '**/*.{ts,js,json,css,md,yml}'",

"type-check": "tsc --noEmit",
"test": "jest --passWithNoTests",
"test": "jest",
"test:env": "LOAD_ENV=1 yarn test",
"test:ci": "yarn lint && yarn type-check && yarn test",

@@ -37,10 +38,10 @@ "prebuild": "yarn test:ci",

"devDependencies": {
"@jupiterone/integration-sdk-core": "^8.8.0",
"@jupiterone/integration-sdk-dev-tools": "^8.8.0",
"@jupiterone/integration-sdk-testing": "^8.8.0",
"@jupiterone/integration-sdk-core": "^8.9.0",
"@jupiterone/integration-sdk-dev-tools": "^8.9.0",
"@jupiterone/integration-sdk-testing": "^8.9.0",
"jest-fetch-mock": "^3.0.3"
},
"peerDependencies": {
"@jupiterone/integration-sdk-core": "^8.8.0"
"@jupiterone/integration-sdk-core": "^8.9.0"
}
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc