Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Neo4j >= 4 compatibility (shortestonly and dijkstra-cypher algorithms only) #9

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Neo4j >= 4 compatibility (shortestpath algorithm only)
aas-n committed Apr 10, 2021
commit ae9c252524f8470535d26d7b08666a3a03844f91
2 changes: 1 addition & 1 deletion aclpwn/__init__.py
Original file line number Diff line number Diff line change
@@ -103,7 +103,7 @@ def main():
paths = pathfinding.dijkstra_find_cypher(from_object, to_object, args.from_type.capitalize(), args.to_type.capitalize())
else:
# First we need to obtain the node IDs for use with the REST api
q = "MATCH (n:%s {name: {name}}) RETURN n"
q = "MATCH (n:%s {name: $name}) RETURN n"
with database.driver.session() as session:
fromres = session.run(q % args.from_type.capitalize(), name=from_object)
try:
2 changes: 1 addition & 1 deletion aclpwn/database.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from __future__ import unicode_literals, print_function
from neo4j.v1 import GraphDatabase
from neo4j import GraphDatabase
import platform
import requests
import json
17 changes: 9 additions & 8 deletions aclpwn/pathfinding.py
Original file line number Diff line number Diff line change
@@ -39,7 +39,7 @@ def dijkstra_find(fromid, toid, dbhost):
return paths

def dijkstra_find_cypher(startnode, endnode, starttype='User', endtype='User'):
query = "MATCH (n:%s {name: {startnode}}), (m:%s {name: {endnode}}) " \
query = "MATCH (n:%s {name: $startnode}), (m:%s {name: $endnode}) " \
"CALL algo.shortestPath.stream(n, m, 'aclpwncost', " \
"{nodeQuery:null, relationshipQuery:null, defaultValue:200.0, direction:'OUTGOING'}) " \
"YIELD nodeId, cost " \
@@ -60,15 +60,15 @@ def dijkstra_find_cypher(startnode, endnode, starttype='User', endtype='User'):

queries = {
# Query all shortest paths
'shortestonly': "MATCH (n:%s {name: {startnode}}),"
"(m:%s {name: {endnode}}),"
'shortestonly': "MATCH (n:%s {name: $startnode}),"
"(m:%s {name: $endnode}),"
" p=allShortestPaths((n)-[:MemberOf|AddMember|GenericAll|"
"GenericWrite|WriteOwner|WriteDacl|Owns|DCSync|GetChangesAll|AllExtendedRights*1..]->(m))"
" RETURN p",
# Query all simple paths (more expensive query than above)
# credits to https://stackoverflow.com/a/40062243
'allsimple': "MATCH (n:%s {name: {startnode}}),"
"(m:%s {name: {endnode}}),"
'allsimple': "MATCH (n:%s {name: $startnode}),"
"(m:%s {name: $endnode}),"
" p=(n)-[:MemberOf|AddMember|GenericAll|"
"GenericWrite|WriteOwner|WriteDacl|Owns|DCSync|GetChangesAll|AllExtendedRights*1..]->(m)"
"WHERE ALL(x IN NODES(p) WHERE SINGLE(y IN NODES(p) WHERE y = x))"
@@ -77,11 +77,12 @@ def dijkstra_find_cypher(startnode, endnode, starttype='User', endtype='User'):


def get_path(startnode, endnode, starttype='User', endtype='User', querytype='allsimple'):
records = []
with database.driver.session() as session:
with session.begin_transaction() as tx:
return tx.run(queries[querytype] % (starttype, endtype),
startnode=startnode,
endnode=endnode)
for record in tx.run(queries[querytype] % (starttype, endtype), startnode=startnode, endnode=endnode):
records.append(record)
return records

def get_path_cost(record):
nmap = utils.getnodemap(record['p'].nodes)
4 changes: 2 additions & 2 deletions aclpwn/utils.py
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@ def print_path(record):
# Iterate the path
pathtext = '(%s)-' % record['p'].nodes[0].get('name')
for el in record['p']:
pathtext += '[%s]->(%s)-' % (el.type, nmap[el.end].get('name'))
pathtext += '[%s]->(%s)-' % (el.type, nmap[el.end_node.id].get('name'))
pathtext = pathtext[:-1]
return pathtext

@@ -20,7 +20,7 @@ def build_path(record):
nmap = getnodemap(record['p'].nodes)
# Iterate the path
for el in record['p']:
path.append((el, nmap[el.end]))
path.append((el, nmap[el.end_node.id]))
return path

def build_rest_path(nodes, rels):
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
neo4j-driver
impacket
ldap3
requests