Awesome
PSNeo4j
PSNeo4j is a simple Neo4j PowerShell module, allowing you to quickly build up graph data from any of the technologies PowerShell can interface with.
IMPORTANT:
- This has had minimal testing, and the default response conversion (
-As Parsed
) currently misses some common cases - Some commands are susceptible to injection. See
Get-Help about_PSNeo4j
and parameter help for more details
Getting Started
Install Neo4j, and configure the neo4j
user's password via http://127.0.0.1:7474
(example)
# One time setup
# Download the repository
# Unblock the zip
# Extract the PSNeo4j folder to a module path (e.g. $env:USERPROFILE\Documents\WindowsPowerShell\Modules\)
# Or, with PowerShell 5 or later or PowerShellGet:
Install-Module PSNeo4j
# Import the module.
Import-Module PSNeo4j #Alternatively, Import-Module \\Path\To\PSNeo4j
# Get commands in the module
Get-Command -Module PSNeo4j
# Get help
Get-Help Invoke-Neo4jQuery -Full
Get-Help about_PSNeo4j
Examples
We'll create a super simple database of systems and services - this could be extended to cover a wide variety of things for a custom CMDB
Set up defaults
# Set a password ahead of time, and maybe use an actual password generator : )
$Password = ConvertTo-SecureString -String "myneo4jpassword!" -AsPlainText -Force
$Cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList neo4j, $password
Set-PSNeo4jConfiguration -Credential $Cred -BaseUri 'http://127.0.0.1:7474'
# Did we connect?
Get-Neo4jUser
Add some nodes
# Add some servers
[pscustomobject]@{
ComputerName = 'dc01'
Domain = 'some.domain'
},
[pscustomobject]@{
ComputerName = 'dc02'
Domain = 'some.domain'
},
[pscustomobject]@{
ComputerName = 'web01'
Domain = 'some.domain'
} |
New-Neo4jNode -Label Server -Passthru
# Add a service
[pscustomobject]@{
Name = 'Active Directory'
Engineer = 'Warren Frame'
} |
New-Neo4jNode -Label Service -Passthru
List everything in the database
# See what we have
Invoke-Neo4jQuery -Query @"
MATCH (n)
RETURN n;
"@ | Format-List -Property * -Force
Add some relationships
# web01 relies on AD for identity and management
New-Neo4jRelationship -LeftLabel Server -LeftHash @{ComputerName = 'web01'} `
-RightLabel Service -RightHash @{Name = 'Active Directory'} `
-Type 'DependsOn' `
-Properties @{
Identity = $True
Management = $True
}
# Active Directory relies on dc01 and dc02
New-Neo4jRelationship -LeftQuery "MATCH (left:Server) WHERE left.ComputerName =~ 'dc.*'" `
-RightQuery "MATCH (right:Service { Name: 'Active Directory'})" `
-Type 'DependsOn' `
-Properties @{
ServiceHost = $True
LoadBalanced = $True
}
# Oops! Wrong direction. Remove the DC relationships
Remove-Neo4jRelationship -LeftQuery "MATCH (left:Server) WHERE left.ComputerName =~ 'dc.*'" `
-Type 'DependsOn' `
-Properties @{
ServiceHost = $True
LoadBalanced = $True
}
# Add the DC relationships back with the right direction (AD depends on DCs)
New-Neo4jRelationship -LeftQuery "MATCH (left:Service { Name: 'Active Directory'})" `
-RightQuery "MATCH (right:Server) WHERE right.ComputerName =~ 'dc.*'" `
-Type 'DependsOn' `
-Properties @{
ServiceHost = $True
LoadBalanced = $True
}
This is just an example. There are better ways to represent the relationship properties
Check things out
- Browse to
http://127.0.0.1:7474
- Select the
Database Information
icon - Pick a query (e.g. Node Label
Server
or*
)
Add some indexes
# Add a composite index, and individual indexes
New-Neo4jIndex -Label Server -Property computername, domain -Composite
New-Neo4jIndex -Label Server -Property computername, domain
# Look at the indexes we created
Get-Neo4jIndex
# Maybe we only need a constraint. Drop some indexes, add a constraint
Remove-Neo4jIndex -Label Server -Property computername, domain -Composite
Remove-Neo4jIndex -Label Server -Property computername, domain
Add a constraint
# Add some constraints on properties
New-Neo4jConstraint -Label Server -Property computername -Unique
Remove a node
# Remove a server
@{ComputerName = 'web01'} | Remove-Neo4jNode -Label Server
# Error! Can't delete if a node if it has a relationship... unless we detach it
@{ComputerName = 'web01'} | Remove-Neo4jNode -Label Server -Detach
Delete everything!
# This removes nodes, relationships, constraints, and indexes
Clear-Neo4j
# Alternatively, just clear nodes and relationships:
Invoke-Neo4jQuery -Query @"
MATCH (n)
DETACH DELETE n;
"@
Notes
- Thanks to @Jaykul for the
Configuration
module that we embed and rely on - Thanks to @GlennSarti for his various articles and presentations on Neo4j, and maintaining the neo4j-community Chocolatey package
- Thanks to the folks behind BloodHound for some in-the-wild examples
- Using the neo4j-community Chocolatey package and want to know what's actually happening? Read the install script (e.g. install for 3.2.3)
- We use the transactional Cypher HTTP endpoint, doing most work with Cypher queries rather than the REST endpoints or Bolt (currently)
- Fun blog post pending!