diff --git a/src/components/SearchContainer/TabContainer.jsx b/src/components/SearchContainer/TabContainer.jsx index 3fa5b51d3..c746db5a9 100644 --- a/src/components/SearchContainer/TabContainer.jsx +++ b/src/components/SearchContainer/TabContainer.jsx @@ -34,6 +34,8 @@ import BaseNodeData from "./Tabs/BaseNodeData"; import ContainerNodeData from "./Tabs/ContainerNodeData"; import AZManagementGroupNodeData from "./Tabs/AZManagementGroupNodeData"; import AZRoleNodeData from "./Tabs/AZRoleNodeData"; +import AZStorageAccountNodeData from './Tabs/AZStorageAccountNodeData'; +import AZStorageContainerNodeData from './Tabs/AZStorageContainerNodeData'; class TabContainer extends Component { @@ -64,6 +66,11 @@ class TabContainer extends Component { azTenantVisible: false, azVMVisible: false, azServicePrincipalVisible: false, + azStorageAccountVisible: false, + azStorageContainerVisible: false, + azAutomationAccountVisible: false, + azLogicAppVisible: false, + azWebAppVisible: false, azAppVisible: false, azManagementGroupVisible: false, azRoleVisible: false, @@ -136,7 +143,18 @@ class TabContainer extends Component { this._azManagementGroupNodeClicked() } else if (type === 'AZRole') { this._azRoleNodeClicked() + } else if (type === 'AZStorageAccount') { + this._azStorageAccountNodeClicked(); + } else if (type === 'AZStorageContainer') { + this._azStorageContainerNodeClicked(); + } else if (type === 'AZAutomationAccount') { + this._azAutomationAccountNodeClicked(); + } else if (type === 'AZLogicApp') { + this._azLogicAppNodeClicked(); + } else if (type === 'AZWebApp') { + this._azWebAppNodeClicked(); } + } componentDidMount() { @@ -369,6 +387,46 @@ class TabContainer extends Component { }); } + _azStorageAccountNodeClicked() { + this.clearVisible() + this.setState({ + azStorageAccountVisible: true, + selected: 2 + }); + } + + _azStorageContainerNodeClicked() { + this.clearVisible() + this.setState({ + azStorageContainerVisible: true, + selected: 2 + }); + } + + _azAutomationAccountNodeClicked() { + this.clearVisible() + this.setState({ + azAutomationAccountVisible: true, + selected: 2 + }); + } + + _azLogicAppNodeClicked() { + this.clearVisible() + this.setState({ + azLogicAppVisible: true, + selected: 2 + }); + } + + _azWebAppNodeClicked() { + this.clearVisible() + this.setState({ + azWebAppVisible: true, + selected: 2 + }); + } + _azAppNodeClicked() { this.clearVisible() this.setState({ @@ -421,6 +479,11 @@ class TabContainer extends Component { !this.state.azTenantVisible && !this.state.azVMVisible && !this.state.azServicePrincipalVisible && + !this.state.azStorageAccountVisble && + !this.state.azStorageContainerVisble && + !this.state.azAutomationAccountVisible && + !this.state.azLogicAppVisible && + !this.state.azWebAppVisible && !this.state.azAppVisible && !this.state.baseVisible && !this.state.azManagementGroupVisible && @@ -465,6 +528,11 @@ class TabContainer extends Component { + + + + + diff --git a/src/components/SearchContainer/Tabs/AZAutomationAccountNodeData.jsx b/src/components/SearchContainer/Tabs/AZAutomationAccountNodeData.jsx index c13f82028..2ae7fd8f7 100644 --- a/src/components/SearchContainer/Tabs/AZAutomationAccountNodeData.jsx +++ b/src/components/SearchContainer/Tabs/AZAutomationAccountNodeData.jsx @@ -75,18 +75,28 @@ const AZAutomationAccountNodeData = () => { property='See Automation Account within Tenant' query='MATCH p = (d:AZTenant)-[r:AZContains*1..]->(u:AZAutomationAccount {objectid: $objectid}) RETURN p' /> - (n)' + + (n) RETURN COUNT(p)' + } + graphQuery={ + 'MATCH p=(:AZAutomationAccount {objectid:$objectid})-[:AZManagedIdentity]->(n) RETURN p' } + start={label} property={'Managed Identities'} target={objectid} + distinct /> - +
{ properties={nodeProps} label={label} /> - +
{ properties={nodeProps} label={label} /> - +
+ + +
+ (u:AZAutomationAccount {objectid: $objectid}) RETURN COUNT(p)' + } + graphQuery={ + 'MATCH p = (d)-[r:Owner*1..]->(u:AZAutomationAccount {objectid: $objectid}) RETURN p' + } + property={'Automation Account Owners'} + target={objectid} + /> + (u:AZAutomationAccount {objectid: $objectid}) RETURN COUNT(p)' + } + graphQuery={ + 'MATCH p = (d)-[r:Contributor*1..]->(u:AZAutomationAccount {objectid: $objectid}) RETURN p' + } + property={'Automation Account Contributors'} + target={objectid} + /> + (u:AZAutomationAccount {objectid: $objectid}) RETURN COUNT(p)' + } + graphQuery={ + 'MATCH p = (d)-[r:UserAccessAdministrator*1..]->(u:AZAutomationAccount {objectid: $objectid}) RETURN p' + } + property={'User Access Administrators'} + target={objectid} + /> + (u:AZAutomationAccount {objectid: $objectid}) RETURN COUNT(p)' + } + graphQuery={ + 'MATCH p = (d)-[r]->(u:AZAutomationAccount {objectid: $objectid}) RETURN p' + } + property={'All Relations'} + target={objectid} + /> +
@@ -141,7 +195,6 @@ const AZAutomationAccountNodeData = () => {
- ); diff --git a/src/components/SearchContainer/Tabs/AZLogicAppNodeData.jsx b/src/components/SearchContainer/Tabs/AZLogicAppNodeData.jsx index 037f4d00b..e61bee72b 100644 --- a/src/components/SearchContainer/Tabs/AZLogicAppNodeData.jsx +++ b/src/components/SearchContainer/Tabs/AZLogicAppNodeData.jsx @@ -75,18 +75,27 @@ const AZLogicAppNodeData = () => { property='See Logic App within Tenant' query='MATCH p = (d:AZTenant)-[r:AZContains*1..]->(u:AZLogicApp {objectid: $objectid}) RETURN p' /> - (n)' + + (n) RETURN COUNT(p)' } + graphQuery={ + 'MATCH p=(:AZLogicApp {objectid:$objectid})-[:AZManagedIdentity]->(n) RETURN p' + } + start={label} property={'Managed Identities'} target={objectid} + distinct /> -
{ properties={nodeProps} label={label} /> -
{ properties={nodeProps} label={label} /> - +
- +
+ (u:AZLogicApp {objectid: $objectid}) RETURN COUNT(p)' + } + graphQuery={ + 'MATCH p = (d)-[r:Owner*1..]->(u:AZLogicApp {objectid: $objectid}) RETURN p' + } + property={'Logic App Owners'} + target={objectid} + /> + (u:AZLogicApp {objectid: $objectid}) RETURN COUNT(p)' + } + graphQuery={ + 'MATCH p = (d)-[r:Contributor*1..]->(u:AZLogicApp {objectid: $objectid}) RETURN p' + } + property={'Logic App Contributors'} + target={objectid} + /> + (u:AZLogicApp {objectid: $objectid}) RETURN COUNT(p)' + } + graphQuery={ + 'MATCH p = (d)-[r:UserAccessAdministrator*1..]->(u:AZLogicApp {objectid: $objectid}) RETURN p' + } + property={'User Access Administrators'} + target={objectid} + /> + (u:AZLogicApp {objectid: $objectid}) RETURN COUNT(p)' + } + graphQuery={ + 'MATCH p = (d)-[r]->(u:AZLogicApp {objectid: $objectid}) RETURN p' + } + property={'All Relations'} + target={objectid} + /> + +
+
+
+
+ { end={label} distinct /> - - - - + ); diff --git a/src/components/SearchContainer/Tabs/AZStorageAccountNodeData.jsx b/src/components/SearchContainer/Tabs/AZStorageAccountNodeData.jsx new file mode 100644 index 000000000..bb7b116c7 --- /dev/null +++ b/src/components/SearchContainer/Tabs/AZStorageAccountNodeData.jsx @@ -0,0 +1,204 @@ +import React, { useContext, useEffect, useState } from 'react'; +import clsx from 'clsx'; +import CollapsibleSection from './Components/CollapsibleSection'; +import NodeCypherLinkComplex from './Components/NodeCypherLinkComplex'; +import NodeCypherLink from './Components/NodeCypherLink'; +import NodeCypherNoNumberLink from './Components/NodeCypherNoNumberLink'; +import MappedNodeProps from './Components/MappedNodeProps'; +import ExtraNodeProps from './Components/ExtraNodeProps'; +import NodePlayCypherLink from './Components/NodePlayCypherLink'; +import { Table } from 'react-bootstrap'; +import styles from './NodeData.module.css'; +import { AppContext } from '../../../AppContext'; + +const AZStorageAccountNodeData = () => { + const [visible, setVisible] = useState(false); + const [objectid, setObjectid] = useState(null); + const [label, setLabel] = useState(null); + const [domain, setDomain] = useState(null); + const [nodeProps, setNodeProps] = useState({}); + const context = useContext(AppContext); + + useEffect(() => { + emitter.on('nodeClicked', nodeClickEvent); + + return () => { + emitter.removeListener('nodeClicked', nodeClickEvent); + }; + }, []); + + const nodeClickEvent = (type, id, blocksinheritance, domain) => { + if (type === 'AZStorageAccount') { + setVisible(true); + setObjectid(id); + setDomain(domain); + let session = driver.session(); + session + .run(`MATCH (n:AZStorageAccount {objectid: $objectid}) RETURN n AS node`, { + objectid: id, + }) + .then((r) => { + let props = r.records[0].get('node').properties; + setNodeProps(props); + setLabel(props.name || props.azname || objectid); + session.close(); + }); + } else { + setObjectid(null); + setVisible(false); + } + }; + + const displayMap = { + objectid: 'Object ID', + }; + + return objectid === null ? ( +
+ ) : ( +
+
+
{label || objectid}
+ + +
+ + + + + + (n) RETURN COUNT(p)' + } + graphQuery={ + 'MATCH p=(:AZStorageAccount {objectid:$objectid})-[:AZManagedIdentity]->(n) RETURN p' + } + start={label} + property={'Managed Identities'} + target={objectid} + distinct + /> + (d) RETURN COUNT(p)' + } + graphQuery={ + 'MATCH p = (u:AZStorageAccount {objectid: $objectid})-[r:AZContains*1..]->(d) RETURN p' + } + property={'Storage Containers'} + target={objectid} + /> + +
+
+
+ +
+ + + +
+ + + +
+ + +
+ + + + (u:AZStorageAccount {objectid: $objectid}) RETURN COUNT(p)' + } + graphQuery={ + 'MATCH p = (d)-[r:Owner*1..]->(u:AZStorageAccount {objectid: $objectid}) RETURN p' + } + property={'Storage Account Owners'} + target={objectid} + /> + (u:AZStorageAccount {objectid: $objectid}) RETURN COUNT(p)' + } + graphQuery={ + 'MATCH p = (d)-[r:Contributor*1..]->(u:AZStorageAccount {objectid: $objectid}) RETURN p' + } + property={'Storage Account Contributors'} + target={objectid} + /> + (u:AZStorageAccount {objectid: $objectid}) RETURN COUNT(p)' + } + graphQuery={ + 'MATCH p = (d)-[r:ReaderAndDataAccess*1..]->(u:AZStorageAccount {objectid: $objectid}) RETURN p' + } + property={'Storage Account Data Readers'} + target={objectid} + /> + (u:AZStorageAccount {objectid: $objectid}) RETURN COUNT(p)' + } + graphQuery={ + 'MATCH p = (d)-[r:StorageAccountKeyOperator*1..]->(u:AZStorageAccount {objectid: $objectid}) RETURN p' + } + property={'Storage Account Key Operator'} + target={objectid} + /> + (u:AZStorageAccount {objectid: $objectid}) RETURN COUNT(p)' + } + graphQuery={ + 'MATCH p = (d)-[r:UserAccessAdministrator*1..]->(u:AZStorageAccount {objectid: $objectid}) RETURN p' + } + property={'User Access Administrators'} + target={objectid} + /> + (u:AZStorageAccount {objectid: $objectid}) RETURN COUNT(p)' + } + graphQuery={ + 'MATCH p = (d)-[r]->(u:AZStorageAccount {objectid: $objectid}) RETURN p' + } + property={'All Relations'} + target={objectid} + /> + +
+
+
+ +
+
+ ); +}; + +AZStorageAccountNodeData.propTypes = {}; +export default AZStorageAccountNodeData; \ No newline at end of file diff --git a/src/components/SearchContainer/Tabs/AZStorageContainerNodeData.jsx b/src/components/SearchContainer/Tabs/AZStorageContainerNodeData.jsx new file mode 100644 index 000000000..78037e9c4 --- /dev/null +++ b/src/components/SearchContainer/Tabs/AZStorageContainerNodeData.jsx @@ -0,0 +1,177 @@ +import React, { useContext, useEffect, useState } from 'react'; +import clsx from 'clsx'; +import CollapsibleSection from './Components/CollapsibleSection'; +import NodeCypherLinkComplex from './Components/NodeCypherLinkComplex'; +import NodeCypherLink from './Components/NodeCypherLink'; +import NodeCypherNoNumberLink from './Components/NodeCypherNoNumberLink'; +import MappedNodeProps from './Components/MappedNodeProps'; +import ExtraNodeProps from './Components/ExtraNodeProps'; +import NodePlayCypherLink from './Components/NodePlayCypherLink'; +import { Table } from 'react-bootstrap'; +import styles from './NodeData.module.css'; +import { AppContext } from '../../../AppContext'; + +const AZStorageContainerNodeData = () => { + const [visible, setVisible] = useState(false); + const [objectid, setObjectid] = useState(null); + const [label, setLabel] = useState(null); + const [domain, setDomain] = useState(null); + const [nodeProps, setNodeProps] = useState({}); + const context = useContext(AppContext); + + useEffect(() => { + emitter.on('nodeClicked', nodeClickEvent); + + return () => { + emitter.removeListener('nodeClicked', nodeClickEvent); + }; + }, []); + + const nodeClickEvent = (type, id, blocksinheritance, domain) => { + if (type === 'AZStorageContainer') { + setVisible(true); + setObjectid(id); + setDomain(domain); + let session = driver.session(); + session + .run(`MATCH (n:AZStorageContainer {objectid: $objectid}) RETURN n AS node`, { + objectid: id, + }) + .then((r) => { + let props = r.records[0].get('node').properties; + setNodeProps(props); + setLabel(props.name || props.azname || objectid); + session.close(); + }); + } else { + setObjectid(null); + setVisible(false); + } + }; + + const displayMap = { + objectid: 'Object ID', + }; + + return objectid === null ? ( +
+ ) : ( +
+
+
{label || objectid}
+ + +
+ + + + + + + +
+
+
+ +
+ + + +
+ + + +
+ + +
+ + + + (u:AZStorageContainer {objectid: $objectid}) RETURN COUNT(p)' + } + graphQuery={ + 'MATCH p = (d)-[r:Owner*1..]->(u:AZStorageContainer {objectid: $objectid}) RETURN p' + } + property={'Storage Container Owners'} + target={objectid} + /> + (u:AZStorageContainer {objectid: $objectid}) RETURN COUNT(p)' + } + graphQuery={ + 'MATCH p = (d)-[r:Contributor*1..]->(u:AZStorageContainer {objectid: $objectid}) RETURN p' + } + property={'Storage Container Contributors'} + target={objectid} + /> + (u:AZStorageContainer {objectid: $objectid}) RETURN COUNT(p)' + } + graphQuery={ + 'MATCH p = (d)-[r:ReaderAndDataAccess*1..]->(u:AZStorageContainer {objectid: $objectid}) RETURN p' + } + property={'Storage Container Data Readers'} + target={objectid} + /> + (u:AZStorageContainer {objectid: $objectid}) RETURN COUNT(p)' + } + graphQuery={ + 'MATCH p = (d)-[r:UserAccessAdministrator*1..]->(u:AZStorageContainer {objectid: $objectid}) RETURN p' + } + property={'User Access Administrators'} + target={objectid} + /> + (u:AZStorageContainer {objectid: $objectid}) RETURN COUNT(p)' + } + graphQuery={ + 'MATCH p = (d)-[r]->(u:AZStorageContainer {objectid: $objectid}) RETURN p' + } + property={'All Relations'} + target={objectid} + /> + +
+
+
+ +
+
+ ); +}; + +AZStorageContainerNodeData.propTypes = {}; +export default AZStorageContainerNodeData; diff --git a/src/components/SearchContainer/Tabs/AZWebAppNodeData.jsx b/src/components/SearchContainer/Tabs/AZWebAppNodeData.jsx index d9e6dbe3b..fe1ba7e1f 100644 --- a/src/components/SearchContainer/Tabs/AZWebAppNodeData.jsx +++ b/src/components/SearchContainer/Tabs/AZWebAppNodeData.jsx @@ -75,18 +75,27 @@ const AZWebAppNodeData = () => { property='See Web App within Tenant' query='MATCH p = (d:AZTenant)-[r:AZContains*1..]->(u:AZWebApp {objectid: $objectid}) RETURN p' /> - (n)' + + (n) RETURN COUNT(p)' } + graphQuery={ + 'MATCH p=(:AZWebApp {objectid:$objectid})-[:AZManagedIdentity]->(n) RETURN p' + } + start={label} property={'Managed Identities'} target={objectid} + distinct />
-
{ properties={nodeProps} label={label} /> -
{ properties={nodeProps} label={label} /> - +
- +
+ (u:AZWebApp {objectid: $objectid}) RETURN COUNT(p)' + } + graphQuery={ + 'MATCH p = (d)-[r:Owner*1..]->(u:AZWebApp {objectid: $objectid}) RETURN p' + } + property={'Web App Owners'} + target={objectid} + /> + (u:AZWebApp {objectid: $objectid}) RETURN COUNT(p)' + } + graphQuery={ + 'MATCH p = (d)-[r:Contributor*1..]->(u:AZWebApp {objectid: $objectid}) RETURN p' + } + property={'Web App Contributors'} + target={objectid} + /> + (u:AZWebApp {objectid: $objectid}) RETURN COUNT(p)' + } + graphQuery={ + 'MATCH p = (d)-[r:UserAccessAdministrator*1..]->(u:AZWebApp {objectid: $objectid}) RETURN p' + } + property={'User Access Administrators'} + target={objectid} + /> + (u:AZWebApp {objectid: $objectid}) RETURN COUNT(p)' + } + graphQuery={ + 'MATCH p = (d)-[r]->(u:AZWebApp {objectid: $objectid}) RETURN p' + } + property={'All Relations'} + target={objectid} + /> + +
+
+
+
+ + { end={label} distinct /> - - - + - ); diff --git a/src/components/SearchContainer/Tabs/DatabaseDataDisplay.jsx b/src/components/SearchContainer/Tabs/DatabaseDataDisplay.jsx index a411c2829..c215e8d6d 100644 --- a/src/components/SearchContainer/Tabs/DatabaseDataDisplay.jsx +++ b/src/components/SearchContainer/Tabs/DatabaseDataDisplay.jsx @@ -236,9 +236,24 @@ const DatabaseDataDisplay = () => { label={'AZVM'} /> + + +