-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 90d881b
Showing
9 changed files
with
489 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
The MIT License | ||
|
||
Copyright (c) 2017 Breach Intelligence, Inc. | ||
|
||
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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# Polarity TrapX DeceptionGrid Integration | ||
|
||
The Polarity TrapX integration allows Polarity to search the TrapX DeceptionGrid API to return event information on IP addresses. | ||
|
||
## Installation Instructions | ||
|
||
Installation instructions for integrations are provided on the [PolarityIO GitHub Page](https://polarityio.github.io/). | ||
|
||
## Polarity | ||
|
||
Polarity is a memory-augmentation platform that improves and accelerates analyst decision making. For more information about the Polarity platform please see: | ||
|
||
https://polarity.io/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
polarity.export = PolarityComponent.extend({ | ||
details: Ember.computed.alias('block.data.details') | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
polarity.export = PolarityComponent.extend({ | ||
details: Ember.computed.alias('block.data.details') | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
module.exports = { | ||
/** | ||
* Name of the integration which is displayed in the Polarity integrations user interface | ||
* | ||
* @type String | ||
* @required | ||
*/ | ||
name: 'TrapX DeceptionGrid', | ||
/** | ||
* The acronym that appears in the notification window when information from this integration | ||
* is displayed. Note that the acronym is included as part of each "tag" in the summary information | ||
* for the integration. As a result, it is best to keep it to 4 or less characters. The casing used | ||
* here will be carried forward into the notification window. | ||
* | ||
* @type String | ||
* @required | ||
*/ | ||
acronym: 'TRPX', | ||
/** | ||
* Description for this integration which is displayed in the Polarity integrations user interface | ||
* | ||
* @type String | ||
* @optional | ||
*/ | ||
description: | ||
'TrapX DeceptionGrid protects your valuable assets against a multitude of attacks including malicious insiders and sophisticated cybercriminals', | ||
entityTypes: ['IPv4'], | ||
/** | ||
* Provide custom component logic and template for rendering the integration details block. If you do not | ||
* provide a custom template and/or component then the integration will display data as a table of key value | ||
* pairs. | ||
* | ||
* @type Object | ||
* @optional | ||
*/ | ||
block: { | ||
component: { | ||
file: './components/tx-block.js' | ||
}, | ||
template: { | ||
file: './templates/tx-block.hbs' | ||
} | ||
}, | ||
summary: { | ||
component: { | ||
file: './components/tx-summary.js' | ||
}, | ||
template: { | ||
file: './templates/tx-summary.hbs' | ||
} | ||
}, | ||
request: { | ||
// Provide the path to your certFile. Leave an empty string to ignore this option. | ||
// Relative paths are relative to the Urlhaus integration's root directory | ||
cert: '', | ||
// Provide the path to your private key. Leave an empty string to ignore this option. | ||
// Relative paths are relative to the Urlhaus integration's root directory | ||
key: '', | ||
// Provide the key passphrase if required. Leave an empty string to ignore this option. | ||
// Relative paths are relative to the Urlhaus integration's root directory | ||
passphrase: '', | ||
// Provide the Certificate Authority. Leave an empty string to ignore this option. | ||
// Relative paths are relative to the Urlhaus integration's root directory | ||
ca: '', | ||
// An HTTP proxy to be used. Supports proxy Auth with Basic Auth, identical to support for | ||
// the url parameter (by embedding the auth info in the uri) | ||
proxy: '', | ||
|
||
rejectUnauthorized: false | ||
}, | ||
logging: { | ||
level: 'info' //trace, debug, info, warn, error, fatal | ||
}, | ||
/** | ||
* Options that are displayed to the user/admin in the Polarity integration user-interface. Should be structured | ||
* as an array of option objects. | ||
* | ||
* @type Array | ||
* @optional | ||
*/ | ||
options: [ | ||
{ | ||
key: 'url', | ||
name: 'TrapX DeceptionGrid URL', | ||
description: 'The base URL for the DeceptionGrid TSOC API including the schema (i.e., https://)', | ||
type: 'text', | ||
default: '', | ||
userCanEdit: false, | ||
adminOnly: true | ||
}, | ||
{ | ||
key: 'apiKey', | ||
name: 'API Key', | ||
description: 'Valid TrapX API Key.', | ||
default: '', | ||
type: 'password', | ||
userCanEdit: true, | ||
adminOnly: false | ||
}, | ||
{ | ||
key: 'trapType', | ||
name: 'Trap Type to search', | ||
description: | ||
'Search Events with the specified Trap Type (Full OS or Emulation)', | ||
default: { | ||
value: 'fullOS', | ||
display: 'Full OS' | ||
}, | ||
type: 'select', | ||
options: [ | ||
{ | ||
value: 'Full OS', | ||
display: 'Full OS' | ||
}, | ||
{ | ||
value: 'Emulation', | ||
display: 'Emulation' | ||
} | ||
], | ||
multiple: false, | ||
userCanEdit: true, | ||
adminOnly: false | ||
} | ||
] | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,198 @@ | ||
"use strict"; | ||
|
||
const request = require("request"); | ||
const config = require("./config/config"); | ||
const async = require("async"); | ||
const fs = require("fs"); | ||
|
||
let Logger; | ||
let requestWithDefaults; | ||
|
||
const MAX_PARALLEL_LOOKUPS = 10; | ||
|
||
/** | ||
* | ||
* @param entities | ||
* @param options | ||
* @param cb | ||
*/ | ||
function startup(logger) { | ||
let defaults = {}; | ||
Logger = logger; | ||
|
||
const { cert, key, passphrase, ca, proxy, rejectUnauthorized } = config.request; | ||
|
||
if (typeof cert === "string" && cert.length > 0) { | ||
defaults.cert = fs.readFileSync(cert); | ||
} | ||
|
||
if (typeof key === "string" && key.length > 0) { | ||
defaults.key = fs.readFileSync(key); | ||
} | ||
|
||
if (typeof passphrase === "string" && passphrase.length > 0) { | ||
defaults.passphrase = passphrase; | ||
} | ||
|
||
if (typeof ca === "string" && ca.length > 0) { | ||
defaults.ca = fs.readFileSync(ca); | ||
} | ||
|
||
if (typeof proxy === "string" && proxy.length > 0) { | ||
defaults.proxy = proxy; | ||
} | ||
|
||
if (typeof rejectUnauthorized === "boolean") { | ||
defaults.rejectUnauthorized = rejectUnauthorized; | ||
} | ||
|
||
requestWithDefaults = request.defaults(defaults); | ||
} | ||
|
||
function doLookup(entities, options, cb) { | ||
let lookupResults = []; | ||
let tasks = []; | ||
|
||
Logger.debug(entities); | ||
|
||
entities.forEach(entity => { | ||
let postData = {"api_key": options.apiKey,"filter":{"trap_type":options.trapType.value,"attacker_address":entity.value}}; | ||
let requestOptions = { | ||
method: 'POST', | ||
uri: `${options.url}/api/v1.2/events/search`, | ||
body: postData, | ||
json: true | ||
}; | ||
|
||
Logger.trace({ uri: requestOptions }, "Request URI"); | ||
|
||
tasks.push(function (done) { | ||
requestWithDefaults(requestOptions, function (error, res, body) { | ||
if (error) { | ||
return done(error); | ||
} | ||
|
||
Logger.trace(requestOptions); | ||
Logger.trace( | ||
{ body, statusCode: res ? res.statusCode : "N/A" }, | ||
"Result of Lookup" | ||
); | ||
|
||
let result = {}; | ||
|
||
if (res.statusCode === 200) { | ||
result = { | ||
entity, | ||
body | ||
}; | ||
} else if (res.statusCode === 404 || res.statusCode === 202) { | ||
result = { | ||
entity, | ||
body: null | ||
}; | ||
} else { | ||
let error = { | ||
err: body, | ||
detail: `${body.error}: ${body.message}` | ||
}; | ||
if (res.statusCode === 401) { | ||
error = { | ||
err: 'Unauthorized', | ||
detail: 'Request had Authorization header but token was missing or invalid. Please ensure your API key is valid.' | ||
}; | ||
} else if (res.statusCode === 403) { | ||
error = { | ||
err: 'Access Denied', | ||
detail: 'Not enough access permissions.' | ||
}; | ||
} else if (res.statusCode === 404) { | ||
error = { | ||
err: 'Not Found', | ||
detail: 'Requested item doesn’t exist or not enough access permissions.' | ||
}; | ||
} else if (res.statusCode === 429) { | ||
error = { | ||
err: 'Too Many Requests', | ||
detail: 'Daily number of requests exceeds limit. Check Retry-After header to get information about request delay.' | ||
}; | ||
} else if (Math.round(res.statusCode / 10) * 10 === 500) { | ||
error = { | ||
err: 'Server Error', | ||
detail: 'Unexpected Server Error' | ||
}; | ||
} | ||
|
||
return done(error); | ||
} | ||
|
||
done(null, result); | ||
}); | ||
}); | ||
}); | ||
|
||
async.parallelLimit(tasks, MAX_PARALLEL_LOOKUPS, (err, results) => { | ||
if (err) { | ||
Logger.error({ err: err }, "Error"); | ||
cb(err); | ||
return; | ||
} | ||
|
||
results.forEach(result => { | ||
if (result.body === null || result.body.number_of_events === 0) { | ||
lookupResults.push({ | ||
entity: result.entity, | ||
data: null | ||
}); | ||
} else { | ||
lookupResults.push({ | ||
entity: result.entity, | ||
data: { | ||
summary: [], | ||
details: result.body | ||
} | ||
}); | ||
} | ||
}); | ||
|
||
Logger.debug({ lookupResults }, "Results"); | ||
cb(null, lookupResults); | ||
}); | ||
} | ||
|
||
function validateStringOption(errors, options, optionName, errMessage) { | ||
if ( | ||
typeof options[optionName].value !== "string" || | ||
(typeof options[optionName].value === "string" && | ||
options[optionName].value.length === 0) | ||
) { | ||
errors.push({ | ||
key: optionName, | ||
message: errMessage | ||
}); | ||
} | ||
} | ||
|
||
function validateOptions(options, callback) { | ||
let errors = []; | ||
|
||
validateStringOption( | ||
errors, | ||
options, | ||
"url", | ||
"You must provide a valid URL" | ||
); | ||
validateStringOption( | ||
errors, | ||
options, | ||
"apiKey", | ||
"You must provide a valid API Key" | ||
); | ||
|
||
callback(null, errors); | ||
} | ||
|
||
module.exports = { | ||
doLookup, | ||
startup, | ||
validateOptions | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{ | ||
"main": "./integration.js", | ||
"name": "TrapX", | ||
"version": "3.0.0-beta", | ||
"private": true, | ||
"dependencies": { | ||
"request": "^2.88", | ||
"lodash": "^4.17.11", | ||
"async": "^2.6" | ||
} | ||
} |
Oops, something went wrong.