Skip to content

Commit

Permalink
Add domain node click action
Browse files Browse the repository at this point in the history
  • Loading branch information
rvazarkar committed Sep 9, 2016
1 parent 118e16f commit 5f8fb85
Show file tree
Hide file tree
Showing 6 changed files with 277 additions and 8 deletions.
1 change: 1 addition & 0 deletions deploy.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env bash
# DO NOT RUN THIS SCRIPT, THIS IS A SCRIPT FOR TRAVIS TO DO STUFF
response="$(curl -s --user "${GH_USER}" https://api.github.com/repos/adaptivethreat/BloodHound/releases/4033842/assets)"

win32id="$(echo "$response" | grep -B 1 \"BloodHound-linux-ia32 | head -n1 | cut -d ":" -f 2 | cut -c 2- | sed 's/.$//')"
Expand Down
2 changes: 2 additions & 0 deletions src/components/Graph.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,8 @@ export default class GraphContainer extends Component {
emitter.emit('groupNodeClicked', n.data.node.label)
}else if (n.data.node.type_computer){
emitter.emit('computerNodeClicked', n.data.node.label)
}else if (n.data.node.type_domain){
emitter.emit('domainNodeClicked', n.data.node.label)
}
}else{
this.setState({dragged: false})
Expand Down
26 changes: 22 additions & 4 deletions src/components/SearchContainer/TabContainer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import NoNodeData from './Tabs/NoNodeData'
import UserNodeData from './Tabs/UserNodeData'
import GroupNodeData from './Tabs/GroupNodeData';
import ComputerNodeData from './Tabs/ComputerNodeData';
import DomainNodeData from './Tabs/DomainNodeData';
import { Tabs, Tab } from 'react-bootstrap';

export default class TabContainer extends Component {
Expand All @@ -15,6 +16,7 @@ export default class TabContainer extends Component {
userVisible: false,
computerVisible: false,
groupVisible: false,
domainVisible: false,
selected: 1
}
}
Expand All @@ -23,7 +25,8 @@ export default class TabContainer extends Component {
this.setState({
userVisible: true,
computerVisible: false,
groupVisible: false
groupVisible: false,
domainVisible: false
})
this.setState({selected: 2})
}
Expand All @@ -32,7 +35,8 @@ export default class TabContainer extends Component {
this.setState({
userVisible: false,
computerVisible: false,
groupVisible: true
groupVisible: true,
domainVisible: false
})
this.setState({selected: 2})
}
Expand All @@ -41,15 +45,28 @@ export default class TabContainer extends Component {
this.setState({
userVisible: false,
computerVisible: true,
groupVisible: false
groupVisible: false,
domainVisible: false
})
this.setState({selected: 2})
}

_domainNodeClicked(){
this.setState({
userVisible: false,
computerVisible: false,
groupVisible: false,
domainVisible: true
})
this.setState({selected: 2})
}


componentDidMount() {
emitter.on('userNodeClicked', this._userNodeClicked.bind(this))
emitter.on('groupNodeClicked', this._groupNodeClicked.bind(this))
emitter.on('computerNodeClicked', this._computerNodeClicked.bind(this))
emitter.on('domainNodeClicked', this._domainNodeClicked.bind(this))
}

_handleSelect(index, last){
Expand All @@ -65,10 +82,11 @@ export default class TabContainer extends Component {
</Tab>

<Tab eventKey={2} title="Node Info">
<NoNodeData visible={!this.state.userVisible && !this.state.computerVisible && !this.state.groupVisible}/>
<NoNodeData visible={!this.state.userVisible && !this.state.computerVisible && !this.state.groupVisible && !this.state.domainVisible}/>
<UserNodeData visible={this.state.userVisible}/>
<GroupNodeData visible={this.state.groupVisible}/>
<ComputerNodeData visible={this.state.computerVisible}/>
<DomainNodeData visible={this.state.domainVisible}/>
</Tab>

<Tab eventKey={3} title="Queries">
Expand Down
226 changes: 226 additions & 0 deletions src/components/SearchContainer/Tabs/DomainNodeData.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
import React, { Component } from 'react';
import NodeALink from './NodeALink.jsx'
import LoadLabel from './LoadLabel.jsx'
import { fullAjax } from 'utils'

export default class DomainNodeData extends Component {
propTypes: {
visible : React.PropTypes.bool.isRequired
}

constructor(){
super();

this.state = {
label: "",
users: -1,
groups: -1,
computers: -1,
foreignGroups: -1,
foreignUsers: -1,
firstDegreeOutboundTrusts: -1,
effectiveOutboundTrusts: -1,
firstDegreeInboundTrusts: -1,
effectiveInboundTrusts: -1
}

emitter.on('domainNodeClicked', this.getNodeData.bind(this));
}

getNodeData(payload){
this.state = {
label: payload,
users: -1,
groups: -1,
computers: -1,
foreignGroups: -1,
foreignUsers: -1,
firstDegreeOutboundTrusts: -1,
effectiveOutboundTrusts: -1,
firstDegreeInboundTrusts: -1,
effectiveInboundTrusts: -1
}

var users,
groups,
computers,
foreignGroups,
foreignUsers,
firstDegreeInboundTrusts,
firstDegreeOutboundTrusts,
effectiveInboundTrusts,
effectiveOutboundTrusts;

users = fullAjax(
"MATCH (a:User) WHERE a.name ENDS WITH ('@' + '{}') RETURN COUNT(a)".format(payload),
function(json){
this.setState({users: json.results[0].data[0].row[0]})
}.bind(this))

groups = fullAjax(
"MATCH (a:Group) WHERE a.name ENDS WITH ('@' + '{}') RETURN COUNT(a)".format(payload),
function(json){
this.setState({groups: json.results[0].data[0].row[0]})
}.bind(this))

computers = fullAjax(
"MATCH (n:Computer) WHERE n.name ENDS WITH '{}' WITH n WHERE size(split(n.name,'.')) - size(split('{}}','.')) = 1 RETURN count(n)".formatAll(payload),
function(json){
this.setState({computers: json.results[0].data[0].row[0]})
}.bind(this))

foreignGroups = fullAjax(
"MATCH (a:Group) WHERE NOT a.name ENDS WITH ('@' + '{}') WITH a MATCH (b:Group) WHERE b.name ENDS WITH ('@' + '{}') WITH a,b MATCH (a)-[r:MemberOf]->(b) RETURN count(a)".formatAll(payload),
function(json){
this.setState({foreignGroups: json.results[0].data[0].row[0]})
}.bind(this))

foreignUsers = fullAjax(
"MATCH (a:User) WHERE NOT a.name ENDS WITH ('@' + '{}') WITH a MATCH (b:Group) WHERE b.name ENDS WITH ('@' + '{}') WITH a,b MATCH (a)-[r:MemberOf]->(b) RETURN count(a)".formatAll(payload),
function(json){
this.setState({foreignUsers: json.results[0].data[0].row[0]})
}.bind(this))

firstDegreeInboundTrusts = fullAjax(
"MATCH (a:Domain {name:'{}'})<-[r:TrustedBy]-(b:Domain) RETURN count(b)".format(payload),
function(json){
this.setState({firstDegreeInboundTrusts: json.results[0].data[0].row[0]})
}.bind(this))

firstDegreeOutboundTrusts = fullAjax(
"MATCH (a:Domain {name:'{}'})-[r:TrustedBy]->(b:Domain) RETURN count(b)".format(payload),
function(json){
this.setState({firstDegreeOutboundTrusts: json.results[0].data[0].row[0]})
}.bind(this))

effectiveInboundTrusts = fullAjax(
"MATCH (a:Domain {name:'{}'})<-[r:TrustedBy*1..]-(b:Domain) RETURN count(b)".format(payload),
function(json){
this.setState({effectiveInboundTrusts: json.results[0].data[0].row[0]})
}.bind(this))

effectiveOutboundTrusts = fullAjax(
"MATCH (a:Domain {name:'{}'})-[r:TrustedBy*1..]->(b:Domain) RETURN count(b)".format(payload),
function(json){
this.setState({effectiveOutboundTrusts: json.results[0].data[0].row[0]})
}.bind(this))

$.ajax(users)
$.ajax(groups)
$.ajax(computers)
$.ajax(foreignGroups)
$.ajax(foreignUsers)
$.ajax(firstDegreeInboundTrusts)
$.ajax(firstDegreeOutboundTrusts)
$.ajax(effectiveInboundTrusts)
$.ajax(effectiveOutboundTrusts)
}

render() {
return (
<div className={this.props.visible ? "" : "displaynone"}>
<dl className='dl-horizontal'>
<dt>
Node
</dt>
<dd>
{this.state.label}
</dd>
<br />
<dt>
Users
</dt>
<dd>
<LoadLabel
ready={this.state.users !== -1}
value={this.state.users} />
</dd>
<dt>
Groups
</dt>
<dd>
<LoadLabel
ready={this.state.groups !== -1}
value={this.state.groups} />
</dd>
<dt>
Computers
</dt>
<dd>
<LoadLabel
ready={this.state.computers !== -1}
value={this.state.computers} />
</dd>
<br />
<dt>
Foreign Users
</dt>
<dd>
<NodeALink
ready={this.state.foreignUsers !== -1}
value={this.state.foreignUsers}
click={function(){
emitter.emit('query', "MATCH (a:User) WHERE NOT a.name ENDS WITH ('@' + '{}') WITH a MATCH (b:Group) WHERE b.name ENDS WITH ('@' + '{}') WITH a,b MATCH (a)-[r:MemberOf]-(b) RETURN a,r,b".formatAll(this.state.label))
}.bind(this)} />
</dd>
<dt>
Foreign Groups
</dt>
<dd>
<NodeALink
ready={this.state.foreignGroups !== -1}
value={this.state.foreignGroups}
click={function(){
emitter.emit('query', "MATCH (a:Group) WHERE NOT a.name ENDS WITH ('@' + '{}') WITH a MATCH (b:Group) WHERE b.name ENDS WITH ('@' + '{}') WITH a,b MATCH (a)-[r:MemberOf]-(b) RETURN a,r,b".formatAll(this.state.label))
}.bind(this)} />
</dd>
<br />
<dt>
Inbound Trusts
</dt>
<dd>
<NodeALink
ready={this.state.firstDegreeInboundTrusts !== -1}
value={this.state.firstDegreeInboundTrusts}
click={function(){
emitter.emit('query', "MATCH (a:Domain {name:'{}'})<-[r:TrustedBy]-(b:Domain) RETURN a,r,b".formatAll(this.state.label))
}.bind(this)} />
</dd>
<dt>
Effective Inbound Trusts
</dt>
<dd>
<NodeALink
ready={this.state.effectiveInboundTrusts !== -1}
value={this.state.effectiveInboundTrusts}
click={function(){
emitter.emit('query', "MATCH (a:Domain {name:'{}'})<-[r:TrustedBy*1..]-(b:Domain) RETURN a,r,b".formatAll(this.state.label))
}.bind(this)} />
</dd>
<dt>
Outbound Trusts
</dt>
<dd>
<NodeALink
ready={this.state.firstDegreeOutboundTrusts !== -1}
value={this.state.firstDegreeOutboundTrusts}
click={function(){
emitter.emit('query', "MATCH (a:Domain {name:'{}'})-[r:TrustedBy]->(b:Domain) RETURN a,r,b".formatAll(this.state.label))
}.bind(this)} />
</dd>
<dt>
Effective Outbound Trusts
</dt>
<dd>
<NodeALink
ready={this.state.effectiveOutboundTrusts !== -1}
value={this.state.effectiveOutboundTrusts}
click={function(){
emitter.emit('query', "MATCH (a:Domain {name:'{}'})-[r:TrustedBy*1..]->(b:Domain) RETURN a,r,b".formatAll(this.state.label))
}.bind(this)} />
</dd>
</dl>
</div>
);
}
}
4 changes: 0 additions & 4 deletions src/components/SearchContainer/Tabs/GroupNodeData.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,6 @@ export default class GroupNodeData extends Component {
emitter.on('groupNodeClicked', this.getNodeData.bind(this));
}

placeholder(){

}

getNodeData(payload){
this.setState({
label: payload,
Expand Down
26 changes: 26 additions & 0 deletions src/components/SearchContainer/Tabs/LoadLabel.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React, { Component } from 'react';
import { If, Then, Else } from 'react-if';

export default class LoadLabel extends Component {
propTypes: {
ready : React.PropTypes.bool.isRequired,
value : React.PropTypes.number
}
constructor(props){
super(props);
}
render() {
return (
<If condition={this.props.ready}>
<Then><div>{this.props.value}</div></Then>
<Else>{() =>
<div className="spinner">
<div className="bounce1"></div>
<div className="bounce2"></div>
<div className="bounce3"></div>
</div>
}</Else>
</If>
);
}
}

0 comments on commit 5f8fb85

Please sign in to comment.