Python, Neo4j and Yworks
The Pain Point: While Neo4J is incredible with network graphs DB, it has limited visualization. Here comes Yworks and Python to give us better visualization. My thanks to Sebastian Muller whos shared his code here:
https://gist.github.com/yGuy/9e0f35c2f5c9ef1473c9f39264640f02#file-yfiles_graphs_for_jupyter_nodes_2022-ipynb
For example:
To This:
Or To this:
To start, we need to install the required plugins (neo4j and yfiles_jupyter_graphs) using PIP install:
Open Jupyter notebook (/JupyterProjects/SecurityLogFiles/YWorksSampleCode.ipynb)
with driver.session(database=”neo4j”) as session:
graph= session.run(“match(a:ASNUM)<-[v:belongsTo]-(j:ISPName)<-[l:OwnedBy]-(n:Attacker)-[i:Incident]->(m:Target) where n.pagerank>400 return n,i,m,j,a limit 100”).graph()from yfiles_jupyter_graphs import GraphWidget
GraphWidget(graph = graph)
Next: Adding colors, and changing the shapes of nodes
# Customization / adding styles
with driver.session(database=”neo4j”) as session:
graph= session.run(“match(a:ASNUM)<-[v:belongsTo]-(j:ISPName)<-[l:OwnedBy]-(n:Attacker)-[i:Incident]->(m:Target)
where n.pagerank>400 return a,j,n,i,m limit 100”).graph()from yfiles_jupyter_graphs import GraphWidget
w = GraphWidget(graph = graph)
w.directed = False
w.set_graph_layout(“radial”)
w.set_neighborhood(2)
w.set_sidebar(enabled = False, start_with = “Neighborhood”)
w.set_overview(False)w.set_node_color_mapping(lambda index, node : “red” if node[“properties”][“label”] == “Attacker:Node” else “blue”)
w.set_edge_color_mapping(lambda index, edge : “orange” if edge[“properties”][“protocol”] == “tcp” else “black”)
w.set_node_label_mapping(lambda index, node : node[“properties”][“IPv4”] + “\n” + str(node[“properties”][“pagerank”])
if node[“properties”][“label”] == “Attacker:Node” else node[“properties”][“label”])
w.set_node_scale_factor_mapping(lambda index, node : 1 + node[“properties”][“pagerank”] / 80
if node[“properties”][“label”] == “Attacker:Node” else 1)w.show()
Using the Helper Method:
node_styles = {
“ASNUM”: {“color”:”orange”, “shape”:”ellipse”, “label”:”OrgName”},
“Attacker:Node”: {“color”:”red”, “shape”:”rectangle”, “label”:”IPv4"},
“ISPName”: {“color”:”#386664", “shape”:”rectangle”, “label”:”Name”},
“Node”: {“color”:”#498381", “shape”:”octagon”, “label”:”IPv4"},
“Node:Target”: {“color”:”blue”, “shape”:”ellipse”, “label”:”IPv4"},
“DEFAULT”: { “label”: “label”, “color”: “green” }
}relationship_styles = {
“Incident”: {“color”:”orange”, “directed”: True},
“OwnedBy”: {“color”:”black”, “directed”: True },
“belongsTo”: {“color”:”red”, “directed”: True},
“DEFAULT”: { “label”: “label”, “directed”: True, “color”: “black” }
}def createSecurityGraph(neo4jGraph):
def get_style(styles_dict, item):
return styles_dict.get(item[“properties”][“label”], styles_dict[“DEFAULT”])def get_style_value(styles_dict, item, key):
style = get_style(styles_dict, item)
return style.get(key, styles_dict[“DEFAULT”][key])def get_relationship_style(relationship):
return get_style(relationship_styles, relationship);def get_label (styles_dict, item):
return item[“properties”][get_style_value(styles_dict, item, “label”)]w = GraphWidget(graph = graph)
w.set_graph_layout(“radial”)
w.set_edge_color_mapping(lambda index, edge : get_relationship_style(edge)[“color”])
w.set_node_styles_mapping(lambda index, node : node_styles.get(node[“properties”][“label”], {}))
w.set_node_label_mapping(lambda index, node : get_label(node_styles, node))
w.set_edge_label_mapping(lambda index, edge : get_label(relationship_styles, edge))
w.set_directed_mapping(lambda index, edge : get_style_value(relationship_styles, edge, “directed”))return w.show()
Now we look at communities :
from neo4j import GraphDatabase
driver = GraphDatabase.driver(db, auth=basic_auth(user=”neo4j”, password=pwd))with driver.session(database=”neo4j”) as session:
graph = session.run(“match (j:ISPName)<-[l:OwnedBy]-(n:Attacker)-[i:Incident]->(m:Target) where n.louvain=27206 return j,n,i,m,l limit 500”).graph()createSecurityGraph(graph)