Created
August 12, 2020 22:27
-
-
Save cutler-scott-newrelic/987c2365ace54785112d91318aca064c to your computer and use it in GitHub Desktop.
Netflow Nerdlet index
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
import React from 'react' | |
import PropTypes from 'prop-types' | |
import { | |
Grid, | |
GridItem, | |
Stack, | |
StackItem, | |
TextField, | |
Button, | |
LineChart, | |
BarChart, | |
TableChart, | |
HeadingText, | |
Select, | |
SelectItem, | |
PlatformStateContext, | |
UserStorageMutation, | |
Card, | |
CardHeader, | |
CardBody | |
} from 'nr1'; | |
export default class NetflowNerdletV4 extends React.Component { | |
static propTypes = { | |
entity: PropTypes.object, | |
entities: PropTypes.array, | |
entityCount: PropTypes.object, | |
entitiesById: PropTypes.object, | |
entitiesByDomainType: PropTypes.object, | |
relationshipsById: PropTypes.object, | |
summaryDataById: PropTypes.object, | |
isLoadingEntities: PropTypes.bool, | |
headerState: PropTypes.object, | |
nr1: PropTypes.object, | |
width: PropTypes.number, | |
height: PropTypes.number, | |
} | |
constructor(props) { | |
super(props); | |
this.accountId = 1; | |
this.state = { | |
entityGuid: null, | |
appName: null, | |
trafficDirectionFilter: "Combined", | |
ipProtocolNumberAllow: [], | |
ipAddressAllow: [], | |
ipProtocolNumberBlock: [], | |
ipAddressBlock: [], | |
transportPortAllow: [], | |
transportPortBlock: [], | |
customNrqlValue: "", | |
ipInfoJson: {} | |
}; | |
console.debug("Nerdlet constructor", this); //eslint-disable-line | |
this.openEntity = this.openEntity.bind(this); | |
} | |
setApplication(inAppId, inAppName) { | |
this.setState({ | |
entityGuid: inAppId, | |
appName: inAppName, | |
trafficDirectionFilter: this.state.trafficDirectionFilter, | |
ipProtocolNumberAllow: this.state.ipProtocolNumberAllow, | |
ipAddressAllow: this.state.ipAddressAllow, | |
ipProtocolNumberBlock: this.state.ipProtocolNumberBlock, | |
ipAddressBlock: this.state.ipAddressBlock, | |
transportPortAllow: this.state.transportPortAllow, | |
transportPortBlock: this.state.transportPortBlock, | |
customNrqlValue: this.state.customNrqlValue, | |
ipInfoJson: this.state.ipInfoJson | |
}) | |
} | |
setFilters(trafficdir, protocolnumallow, ipaddrallow, protocolnumblock, ipaddrblock, transportportallow, transportportblock) { | |
// console.log("setFilters(%s, %o, %o, %o, %o, %o, %o)", trafficdir, protocolnumallow, ipaddrallow, protocolnumblock, ipaddrblock, transportportallow, transportportblock); | |
this.setState({ | |
entityGuid: this.state.entityGuid, | |
appName: this.state.appName, | |
trafficDirectionFilter: trafficdir, | |
ipProtocolNumberAllow: protocolnumallow, | |
ipAddressAllow: ipaddrallow, | |
ipProtocolNumberBlock: protocolnumblock, | |
ipAddressBlock: ipaddrblock, | |
transportPortAllow: transportportallow, | |
transportPortBlock: transportportblock, | |
customNrqlValue: this.state.customNrqlValue, | |
ipInfoJson: this.state.ipInfoJson | |
}) | |
} | |
setCustomNrql(customNrqlValue) { | |
this.setState({ | |
entityGuid: this.state.entityGuid, | |
appName: this.state.appName, | |
trafficDirectionFilter: this.state.trafficDirectionFilter, | |
ipProtocolNumberAllow: this.state.ipProtocolNumberAllow, | |
ipAddressAllow: this.state.ipAddressAllow, | |
ipProtocolNumberBlock: this.state.ipProtocolNumberBlock, | |
ipAddressBlock: this.state.ipAddressBlock, | |
transportPortAllow: this.state.transportPortAllow, | |
transportPortBlock: this.state.transportPortBlock, | |
customNrqlValue: customNrqlValue, | |
ipInfoJson: this.state.ipInfoJson | |
}) | |
} | |
setIPInfo(ipInfoJson) { | |
this.setState({ | |
entityGuid: this.state.entityGuid, | |
appName: this.state.appName, | |
trafficDirectionFilter: this.state.trafficDirectionFilter, | |
ipProtocolNumberAllow: this.state.ipProtocolNumberAllow, | |
ipAddressAllow: this.state.ipAddressAllow, | |
ipProtocolNumberBlock: this.state.ipProtocolNumberBlock, | |
ipAddressBlock: this.state.ipAddressBlock, | |
transportPortAllow: this.state.transportPortAllow, | |
transportPortBlock: this.state.transportPortBlock, | |
customNrqlValue: this.state.customNrqlValue, | |
ipInfoJson: ipInfoJson | |
}) | |
} | |
autoSetFilters() { | |
this.setFilters( | |
this.state.trafficDirectionFilter, | |
this.state.ipProtocolNumberAllow, | |
this.state.ipAddressAllow, | |
this.state.ipProtocolNumberBlock, | |
this.state.ipAddressBlock, | |
this.state.transportPortAllow, | |
this.state.transportPortBlock | |
); | |
} | |
removeItemOnce(arr, value) { | |
var index = arr.indexOf(value); | |
if (index > -1) { | |
arr.splice(index, 1); | |
} | |
return arr; | |
} | |
createAddButton(array, tempTextBoxValues, valueToPush) { | |
//console.log("Button Add Value: " + tempTexBoxValues[valueToPush]); | |
return <Button | |
onClick={ () => | |
{ | |
array.push(tempTextBoxValues[valueToPush]); | |
this.autoSetFilters(); | |
} | |
} | |
type={Button.TYPE.PRIMARY} | |
iconType={Button.ICON_TYPE.INTERFACE__SIGN__PLUS__V_ALTERNATE}/> | |
} | |
createTextEntryField(labelText, nameOfClass, tempTextBoxKey, tempTextBoxValues) { | |
return <TextField | |
label={labelText} | |
placeholder={labelText} | |
onChange={(evt) => tempTextBoxValues[tempTextBoxKey] = evt.target.value} | |
className={nameOfClass}/> | |
} | |
populateTopToolbarStack(tempTextBoxValues) { | |
// console.log(tempTextBoxValues) | |
let objectsToRender = []; | |
objectsToRender.push(this.createTextEntryField("IP protocol allow", "ipProtocolAllowFilterClass", "tempIpProtocolAllowTextboxValue", tempTextBoxValues)); | |
objectsToRender.push(this.createAddButton(this.state.ipProtocolNumberAllow, tempTextBoxValues, "tempIpProtocolAllowTextboxValue")); | |
objectsToRender.push(this.createTextEntryField("IP protocol block", "ipProtocolBlockFilterClass", "tempIpProtocolBlockTextboxValue", tempTextBoxValues)); | |
objectsToRender.push(this.createAddButton(this.state.ipProtocolNumberBlock, tempTextBoxValues, "tempIpProtocolBlockTextboxValue")); | |
objectsToRender.push(this.createTextEntryField("IP address allow", "ipAddressAllowFilterClass", "tempIpAddressAllowTextboxValue", tempTextBoxValues)); | |
objectsToRender.push(this.createAddButton(this.state.ipAddressAllow, tempTextBoxValues, "tempIpAddressAllowTextboxValue")); | |
objectsToRender.push(this.createTextEntryField("IP address block", "ipAddressBlockFilterClass", "tempIpAddressBlockTextboxValue", tempTextBoxValues)); | |
objectsToRender.push(this.createAddButton(this.state.ipAddressBlock, tempTextBoxValues, "tempIpAddressBlockTextboxValue")); | |
objectsToRender.push(this.createTextEntryField("Transport port allow", "transportPortAllowFilterClass", "tempTransportPortAllowTextboxValue", tempTextBoxValues)); | |
objectsToRender.push(this.createAddButton(this.state.transportPortAllow, tempTextBoxValues, "tempTransportPortAllowTextboxValue")); | |
objectsToRender.push(this.createTextEntryField("Transport port block", "transportPortBlockFilterClass", "tempTransportPortBlockTextboxValue", tempTextBoxValues)); | |
objectsToRender.push(this.createAddButton(this.state.transportPortBlock, tempTextBoxValues, "tempTransportPortBlockTextboxValue")); | |
return objectsToRender.map( | |
object => | |
<StackItem key={Math.random()} className="toolbar-item has-separator"> | |
{object} | |
</StackItem>) | |
} | |
createAllowButton(key, itemToAllow, itemArrayToAllow) { | |
return <Button key={key + itemToAllow} onClick={() => { | |
itemArrayToAllow = this.removeItemOnce(itemArrayToAllow, itemToAllow) | |
this.autoSetFilters(); | |
} | |
} type={Button.TYPE.PRIMARY} iconType={Button.ICON_TYPE.INTERFACE__SIGN__CLOSE}> | |
{key} {itemToAllow} | |
</Button> | |
} | |
createBlockButton(key, itemToBlock, itemArrayToBlock) { | |
return <Button key={key + itemToBlock} onClick={() => { | |
itemArrayToBlock = this.removeItemOnce(itemArrayToBlock, itemToBlock) | |
this.autoSetFilters() | |
} | |
} type={Button.TYPE.DESTRUCTIVE} iconType={Button.ICON_TYPE.INTERFACE__SIGN__CLOSE}> | |
{key} {itemToBlock} | |
</Button> | |
} | |
renderBottomStackButtons() { | |
let bottomButtons = [] | |
bottomButtons.push(this.state.ipProtocolNumberAllow.map( | |
protocol => { return (this.createAllowButton("IP Proto: ", protocol, this.state.ipProtocolNumberAllow)) } | |
)) | |
bottomButtons.push(this.state.ipProtocolNumberBlock.map( | |
protocol => { return (this.createBlockButton("IP Proto: ", protocol, this.state.ipProtocolNumberBlock)) } | |
)) | |
bottomButtons.push(this.state.ipAddressAllow.map( | |
address => { return (this.createAllowButton("IP Addr: ", address, this.state.ipAddressAllow)) } | |
)) | |
bottomButtons.push(this.state.ipAddressBlock.map( | |
address => { return (this.createBlockButton("IP Addr: ", address, this.state.ipAddressBlock)) } | |
)) | |
bottomButtons.push(this.state.transportPortAllow.map( | |
portnum => { return (this.createAllowButton("Port #: ", portnum, this.state.transportPortAllow)) } | |
)) | |
bottomButtons.push(this.state.transportPortBlock.map( | |
portnum => { return (this.createBlockButton("Port #: ", portnum, this.state.transportPortBlock)) } | |
)) | |
return bottomButtons.map( | |
(button) => button | |
) | |
} | |
renderNrqlQueries(input) { | |
let output = ""; | |
for (const property in input) { | |
output += property + ": " + input[property] + "\n\n" | |
} | |
return output | |
} | |
mergeObjects(objectsArray) { | |
let newObject = {} | |
if (objectsArray.length > 0) { | |
objectsArray.forEach((object) => { | |
// console.log(object); | |
if (object !== null && object !== undefined) { | |
Object.keys(object).forEach((key) => { | |
// console.log("Key: " + key); // key | |
// console.log(object[key]); // value | |
newObject[key] = object[key] | |
}); | |
} | |
else { | |
// console.log("null or undefined object fed to mergeObject method!") | |
return null; | |
} | |
}) | |
return newObject; | |
} | |
else { | |
return "objectsArray is empty in mergeObjects method." | |
} | |
} | |
fetchIpAddressInfoFromHost(ipAddress, hostDatabase) { | |
const baseUrl = "https://api.example.com" | |
return fetch(baseUrl + "/" + hostDatabase + "/" + ipAddress, {credentials: 'include'}) | |
.then(response => { | |
// console.log("uncaught response: %o", response) | |
if (!response.ok) { | |
throw new Error('Network response was not ok'); | |
} | |
return response.json(); | |
}) | |
.catch(error => { | |
// console.error('There has been a problem with your fetch operation:', error); | |
return {error_stack: error.stack} | |
}); | |
//console.log("caught response: %o", response) | |
//fetchIpAddress(); | |
} | |
async checkIpForMaliciousActivity(ipAddress) { | |
let accumulatedResponses = []; | |
await this.fetchIpAddressInfoFromHost(ipAddress, "virustotal") | |
.then((response) => { | |
accumulatedResponses.push(response); | |
}); | |
await this.fetchIpAddressInfoFromHost(ipAddress, "alienvault") | |
.then((response) => { | |
accumulatedResponses.push(response); | |
}); | |
await this.fetchIpAddressInfoFromHost(ipAddress, "reverse") | |
.then((response) => { | |
accumulatedResponses.push(response); | |
}); | |
// console.log("Accumulated Responses:" + accumulatedResponses); | |
// console.log(this.mergeObjects(accumulatedResponses)) | |
this.setIPInfo(this.mergeObjects(accumulatedResponses)); | |
} | |
renderIpAddressInfo() { | |
let objectsToRender = []; | |
let ipAddrRenderResult; | |
// console.log(this.state.ipInfoJson); | |
if ((this.state.ipInfoJson !== null && this.state.ipInfoJson !== undefined) && Object.keys(this.state.ipInfoJson).length >= 0) { | |
Object.keys(this.state.ipInfoJson).forEach((key) => { | |
// console.log(key); | |
objectsToRender.push(<p>{key}: {this.state.ipInfoJson[key]}</p>); | |
}) | |
ipAddrRenderResult = <div>{ objectsToRender }</div> | |
if ('error_stack' in this.state.ipInfoJson){ | |
// console.log("Error stack found!"); | |
ipAddrRenderResult = <div>There was an error connecting to the API. Try clicking through <a href="https://netflowapi.service.newrelic.com">this link</a> first then retry here.</div> | |
} | |
} | |
else { | |
ipAddrRenderResult = <div>Click an IP address to get started!</div> | |
} | |
return ipAddrRenderResult; | |
} | |
setAPIKSKey(key) { | |
UserStorageMutation.mutate({ | |
actionType: UserStorageMutation.ACTION_TYPE.WRITE_DOCUMENT, | |
collection: 'netflowapicollection', | |
documentId: 'netflowapiuserapikeys', | |
document: {apiks: key}, | |
}); | |
} | |
openEntity() { | |
const { entityGuid, appName, trafficDirectionFilter, ipProtocolNumberAllow, ipAddressAllow, ipProtocolNumberBlock, ipAddressBlock, transportPortAllow, transportPortBlock } = this.state; | |
nerdlet.setUrlState({ entityGuid, appName, trafficDirectionFilter, ipProtocolNumberAllow, ipAddressAllow, ipProtocolNumberBlock, ipAddressBlock, transportPortAllow, transportPortBlock }); //eslint-disable-line | |
navigation.openEntity(entityGuid); //eslint-disable-line | |
} | |
render() { | |
var { entityGuid, //eslint-disable-line | |
appName, //eslint-disable-line | |
trafficDirectionFilter, | |
ipProtocolNumberAllow, | |
ipAddressAllow, | |
ipProtocolNumberBlock, | |
ipAddressBlock, | |
transportPortAllow, | |
transportPortBlock } = this.state; | |
const nrql_broadtraffic = `SELECT rate(sum(octetDeltaCount * 64000), 1 second) as 'bps' FROM ipfix TIMESERIES`; | |
const nrql_iptraffic_source = `SELECT count(sourceIPv4Address) as 'Number of logs' FROM ipfix FACET sourceIPv4Address`; | |
const nrql_iptraffic_dest = `SELECT count(destinationIPv4Address) as 'Number of logs' FROM ipfix FACET destinationIPv4Address`; | |
const nrql_iptraffic_ipproto = `SELECT count(protocolIdentifier) as 'IP protocol' FROM ipfix LOOKUP ip_protocol_numbers FACET protocolIdentifier`; | |
const nrql_transport_port = `SELECT count(destinationTransportPort) FROM ipfix FACET destinationTransportPort`; | |
var nrql_ipprotonum_filter = " "; | |
if (ipProtocolNumberAllow != []) { | |
for (let i = 0; i < ipProtocolNumberAllow.length; i++) { | |
if (i === 0) { | |
nrql_ipprotonum_filter += " WHERE protocolIdentifier = " + ipProtocolNumberAllow[i]; | |
} | |
else { | |
nrql_ipprotonum_filter += " OR protocolIdentifier = " + ipProtocolNumberAllow[i]; | |
} | |
} | |
} | |
if (ipProtocolNumberBlock != []) { | |
for (let i = 0; i < ipProtocolNumberBlock.length; i++) { | |
if (i === 0 && nrql_ipprotonum_filter === " ") { | |
nrql_ipprotonum_filter += " WHERE protocolIdentifier != " + ipProtocolNumberBlock[i]; | |
} | |
else { | |
nrql_ipprotonum_filter += " AND protocolIdentifier != " + ipProtocolNumberBlock[i]; | |
} | |
} | |
} | |
// console.log("nrql_ipprotonum_filter: %s", nrql_ipprotonum_filter) | |
var nrql_transportnum_filter = " "; | |
if (transportPortAllow != []) { | |
for (let i = 0; i < transportPortAllow.length; i++) { | |
if (i === 0) { | |
nrql_transportnum_filter += " WHERE destinationTransportPort = " + transportPortAllow[i]; | |
} | |
else { | |
nrql_transportnum_filter += " OR destinationTransportPort = " + transportPortAllow[i]; | |
} | |
} | |
} | |
if (transportPortBlock != []) { | |
for (let i = 0; i < transportPortBlock.length; i++) { | |
if (i === 0 && nrql_transportnum_filter === " ") { | |
nrql_transportnum_filter += " WHERE destinationTransportPort != " + transportPortBlock[i]; | |
} | |
else { | |
nrql_transportnum_filter += " AND destinationTransportPort != " + transportPortBlock[i]; | |
} | |
} | |
} | |
// console.log("nrql_transportnum_filter: %s", nrql_transportnum_filter) | |
var nrql_ipaddr_filter = " "; | |
if (ipAddressAllow != []) { | |
for (let i = 0; i < ipAddressAllow.length; i++) { | |
if (i === 0) { | |
nrql_ipaddr_filter += " WHERE (destinationIPv4Address LIKE '" + ipAddressAllow[i] + "' OR sourceIPv4Address LIKE '" + ipAddressAllow[i] + "')" | |
} | |
else { | |
nrql_ipaddr_filter += " AND (destinationIPv4Address LIKE '" + ipAddressAllow[i] + "' OR sourceIPv4Address LIKE '" + ipAddressAllow[i] + "')" | |
} | |
} | |
} | |
if (ipAddressBlock != []) { | |
for (let i = 0; i < ipAddressBlock.length; i++) { | |
let prefix = ""; | |
if (i === 0 && nrql_ipaddr_filter === " ") { | |
prefix = " WHERE " | |
} else { | |
prefix = " AND " | |
} | |
if (trafficDirectionFilter === "Combined") { | |
nrql_ipaddr_filter += prefix + "(destinationIPv4Address NOT LIKE '" + ipAddressBlock[i] + "' AND sourceIPv4Address NOT LIKE '" + ipAddressBlock[i] + "')" | |
} else if (trafficDirectionFilter === "Inbound") { | |
nrql_ipaddr_filter += prefix + "(sourceIPv4Address NOT LIKE '" + ipAddressBlock[i] + "')" | |
} else if (trafficDirectionFilter === "Outbound") { | |
nrql_ipaddr_filter += prefix + "(destinationIPv4Address NOT LIKE '" + ipAddressBlock[i] + "')" | |
} | |
} | |
} | |
// console.log("nrql_ipaddr_filter: %s", nrql_ipaddr_filter) | |
var nrql_trafficdir_filter = " "; | |
if (trafficDirectionFilter != "Combined") { | |
if (trafficDirectionFilter == "Inbound") { | |
nrql_trafficdir_filter = " WHERE bgpSourceAsNumber NOT IN (1, 2, 3, 4)" | |
} else if (trafficDirectionFilter == "Outbound") { | |
nrql_trafficdir_filter = " WHERE bgpSourceAsNumber IN (1, 2, 3, 4)" | |
} | |
} | |
return ( | |
<PlatformStateContext.Consumer> | |
{(platformUrlState) => { | |
//console.debug here for learning purposes | |
console.debug("platformUrlState: %o", platformUrlState); //eslint-disable-line | |
let since = ""; | |
if (platformUrlState.hasOwnProperty('timeRange') && (typeof platformUrlState.timeRange !== 'undefined')) { | |
if (platformUrlState.timeRange.hasOwnProperty('begin_time') && platformUrlState.timeRange.begin_time && platformUrlState.timeRange.hasOwnProperty('end_time') && platformUrlState.timeRange.end_time) { | |
// const { begin_time, end_time, duration } = platformUrlState.timeRange; | |
// console.debug("begin_time, end_time, duration: %o, %o, %o", begin_time, end_time, duration) | |
since = ` SINCE ${platformUrlState.timeRange.begin_time} UNTIL ${platformUrlState.timeRange.end_time}`; | |
// console.debug("since: %o", since); | |
} else if (platformUrlState.timeRange.duration) { | |
// const { begin_time, end_time, duration } = platformUrlState.timeRange; | |
// console.debug("begin_time, end_time, duration: %o, %o, %o", begin_time, end_time, duration) | |
since = ` SINCE ${platformUrlState.timeRange.duration/60/1000} MINUTES AGO`; | |
// console.debug("since: %o", since); | |
} | |
} | |
// console.debug("trafficDirectionFilter: %s", trafficDirectionFilter); | |
let tempCustomNrqlTextBox = ""; //eslint-disable-line | |
// let tempAPIKSTextBox = ""; | |
{/* created a JS object to store these values, | |
objects in JS are passed by reference when passed as a function parameter*/} | |
let tempTextBoxValues = { | |
tempIpProtocolAllowTextboxValue: "", | |
tempIpProtocolBlockTextboxValue: "", | |
tempIpAddressAllowTextboxValue: "", | |
tempIpAddressBlockTextboxValue: "", | |
tempTransportPortAllowTextboxValue: "", | |
tempTransportPortBlockTextboxValue: "" | |
}; | |
let ipAddrRenderResult = null; | |
ipAddrRenderResult = this.renderIpAddressInfo(); | |
let finishedNrqlQueries = { | |
'trafficChart': nrql_broadtraffic+nrql_trafficdir_filter+nrql_ipprotonum_filter+nrql_ipaddr_filter+nrql_transportnum_filter+since, | |
'ipProtocol': nrql_iptraffic_ipproto+nrql_ipprotonum_filter+nrql_trafficdir_filter+nrql_ipaddr_filter+nrql_transportnum_filter+since, | |
'transportLayerPorts': nrql_transport_port+nrql_ipprotonum_filter+nrql_trafficdir_filter+nrql_ipaddr_filter+nrql_transportnum_filter+since, | |
'sourceIPs': nrql_iptraffic_source+nrql_ipprotonum_filter+nrql_trafficdir_filter+nrql_ipaddr_filter+nrql_transportnum_filter+since, | |
'destinationIPs' : nrql_iptraffic_dest+nrql_ipprotonum_filter+nrql_trafficdir_filter+nrql_ipaddr_filter+nrql_transportnum_filter+since | |
} | |
return ( | |
<div className="full-height"> | |
<Stack | |
className="toolbar-container" | |
fullWidth | |
gapType={Stack.GAP_TYPE.NONE} | |
horizontalType={Stack.HORIZONTAL_TYPE.FILL_EVENLY} | |
verticalType={Stack.VERTICAL_TYPE.FILL} | |
> | |
<StackItem className="toolbar-section1"> | |
<Stack | |
gapType={Stack.GAP_TYPE.NONE} | |
fullWidth | |
verticalType={Stack.VERTICAL_TYPE.FILL} | |
> | |
<StackItem className="toolbar-item has-separator"> | |
<Select onChange={(evt, value) => this.setFilters(value, ipProtocolNumberAllow, ipAddressAllow, ipProtocolNumberBlock, ipAddressBlock, transportPortAllow, transportPortBlock)} label="Traffic Direction" className="trafficDirectionFilterclass" value={trafficDirectionFilter}> | |
<SelectItem value="Inbound">Inbound</SelectItem> | |
<SelectItem value="Outbound">Outbound</SelectItem> | |
<SelectItem value="Combined">Combined</SelectItem> | |
</Select> | |
</StackItem> | |
{ this.populateTopToolbarStack(tempTextBoxValues) } | |
</Stack> | |
</StackItem> | |
</Stack> | |
<Stack | |
className="toolbar-container-2" | |
fullWidth | |
gapType={Stack.GAP_TYPE.NONE} | |
horizontalType={Stack.HORIZONTAL_TYPE.FILL_EVENLY} | |
verticalType={Stack.VERTICAL_TYPE.FILL} | |
> | |
<StackItem className="toolbar-section2"> | |
<Stack | |
gapType={Stack.GAP_TYPE.NONE} | |
fullWidth | |
verticalType={Stack.VERTICAL_TYPE.FILL} | |
> | |
<StackItem> | |
{ this.renderBottomStackButtons() } | |
</StackItem> | |
</Stack> | |
</StackItem> | |
</Stack> | |
<Grid | |
className="primary-grid full-height" | |
spacingType={[ | |
Grid.SPACING_TYPE.LARGE, | |
Grid.SPACING_TYPE.LARGE, | |
Grid.SPACING_TYPE.NONE, | |
Grid.SPACING_TYPE.LARGE | |
]} | |
> | |
<GridItem columnSpan={6}> | |
<main className="primary-content full-height"> | |
<HeadingText type={HeadingText.TYPE.HEADING_3}>Traffic Rate (bps)</HeadingText> | |
<LineChart accountId={1} fullHeight={true} fullWidth={true} query={finishedNrqlQueries['trafficChart']} /> | |
</main> | |
</GridItem> | |
<GridItem columnSpan={3}> | |
<main className="primary-content full-height"> | |
<HeadingText type={HeadingText.TYPE.HEADING_3}>IP Protocols</HeadingText> | |
<BarChart accountId={1} fullHeight={true} fullWidth={true} query={finishedNrqlQueries['ipProtocol']} /> | |
</main> | |
</GridItem> | |
<GridItem columnSpan={3}> | |
<main className="primary-content full-height"> | |
<HeadingText type={HeadingText.TYPE.HEADING_3}>Transport Layer Ports</HeadingText> | |
<BarChart accountId={1} fullHeight={true} fullWidth={true} query={finishedNrqlQueries['transportLayerPorts']} /> | |
</main> | |
</GridItem> | |
<GridItem columnSpan={5}> | |
<main className="primary-content"> | |
<TableChart accountId={1} fullWidth={true} onClickTable={(i, j) => {this.checkIpForMaliciousActivity(j.sourceIPv4Address)}} query={finishedNrqlQueries['sourceIPs']} /> | |
</main> | |
</GridItem> | |
<GridItem columnSpan={5}> | |
<main className="primary-content"> | |
<TableChart accountId={1} fullWidth={true} onClickTable={(i, j) => {this.checkIpForMaliciousActivity(j.destinationIPv4Address)}} query={finishedNrqlQueries['destinationIPs']} /> | |
</main> | |
</GridItem> | |
<GridItem columnSpan={2}> | |
<main className="primary-content"> | |
<Card> | |
<CardHeader title="IP address information" /> | |
<CardBody> | |
{ipAddrRenderResult} | |
</CardBody> | |
</Card> | |
</main> | |
</GridItem> | |
<GridItem columnSpan={6}> | |
<main className="primary-content"> | |
<TextField | |
multiline | |
label="NRQL queries" | |
value={this.renderNrqlQueries(finishedNrqlQueries)} | |
/> | |
</main> | |
</GridItem> | |
<GridItem columnSpan={6}> | |
<main className="primary-content"> | |
<h3>Before using this nerdlet, please click through <a href="https://api.example.com">this link</a> to authenticate to the backend API</h3> | |
</main> | |
</GridItem> | |
</Grid> | |
</div> | |
); | |
}} | |
</PlatformStateContext.Consumer> | |
) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment