Scripts/ExternalSources/ADGroupMembership.ps1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
<#
.SYNOPSIS
    Read group memberships from Active Directory, add to Neo4j

.DESCRIPTION
    Read group memberships from Active Directory, add to Neo4j

    * Assumes all AD related prefixes are AD (default)
    * Uses SID to assign memberships
    * Only assigns memberships for enabled Users
    * Also creates ManagedBy relationships

    This is invoked by Connect-TheDots

.FUNCTIONALITY
    Dots
#>

[cmdletbinding()]
param(
)

# Dot source so module import is available in this scope
if($Script:TestMode) {
    Write-Verbose "Using mock functions from $ModuleRoot/Mock/Mocks.ps1"
    . "$ModuleRoot/Mock/Mocks.ps1"
}
else {
    . Import-RequiredModule ActiveDirectory -ErrorAction Stop
}

$Groups = Get-ADGroup -Properties ManagedBy, MemberOf -Filter * | Select-Object DistinguishedName, SID, Name, ManagedBy, MemberOf
$Users = Get-ADUser -Properties MemberOf -Filter 'enabled -eq $true' | Select-Object DistinguishedName, SID, MemberOf
$SIDMap = @{}
$TypeMap = @{}
foreach($Group in $Groups){
    $SIDMap.Add($Group.DistinguishedName, $Group.SID.Value)
    $TypeMap.Add($Group.DistinguishedName, 'Group')
}
foreach($User in $Users){
    $SIDMap.Add($User.DistinguishedName, $User.SID.Value)
    $TypeMap.Add($User.DistinguishedName, 'User')
}
$GroupUserMemberMap = @{}
foreach($User in $Users) {
    $UserSID = $User.SID.Value
    foreach($Group in $User.MemberOf) {
        $GroupSID = $SIDMap[$Group]
        if(-not $GroupUserMemberMap.ContainsKey($GroupSID)) {
            $GroupUserMemberMap.Add($GroupSID, $(New-Object System.Collections.ArrayList ))
            [void]$GroupUserMemberMap[$GroupSID].Add($UserSID)
        }
        else {
            [void]$GroupUserMemberMap[$GroupSID].Add($UserSid)
        }
    }
}

$GroupGroupMemberMap = @{}
foreach($Member in $Groups) {
    $MemberSID = $Member.SID.Value
    foreach($Group in $Member.MemberOf) {
        $GroupSID = $SIDMap[$Group]
        if(-not $GroupGroupMemberMap.ContainsKey($GroupSID)) {
            $GroupGroupMemberMap.Add($GroupSID, $(New-Object System.Collections.ArrayList ))
            [void]$GroupGroupMemberMap[$GroupSID].Add($MemberSID)
        }
        else {
            [void]$GroupGroupMemberMap[$GroupSID].Add($MemberSID)
        }
    }
}

Invoke-Neo4jQuery -Query "MATCH ()-[r:MemberOf]->() DELETE r"


$TotalCount = $GroupUserMemberMap.count
$Count = 0
Foreach($Group in $GroupUserMemberMap.Keys) {
    Write-Progress -Activity "Updating Neo4j" -Status  "Relating memberof for group $($Group.SID)" -PercentComplete (($Count / $TotalCount)*100)
    $Count++
    Invoke-Neo4jQuery -Query "
        MATCH (g:Group {ADSID: {group}})
        MATCH (a:User) WHERE a.ADSID IN {members}
        CREATE (a)-[:MemberOf]->(g)
    "
 -Parameters @{
        group = $Group
        members = $GroupUserMemberMap[$Group]
    }
}

$TotalCount = $GroupGroupMemberMap.count
$Count = 0
Foreach($Group in $GroupGroupMemberMap.Keys) {
    Write-Progress -Activity "Updating Neo4j" -Status  "Relating memberof for group $($Group.SID)" -PercentComplete (($Count / $TotalCount)*100)
    $Count++
    Invoke-Neo4jQuery -Query "
        MATCH (g:Group {ADSID: {group}})
        MATCH (a:Group) WHERE a.ADSID IN {members}
        CREATE (a)-[:MemberOf]->(g)
    "
 -Parameters @{
        group = $Group
        members = $GroupGroupMemberMap[$Group]
    }
}

Invoke-Neo4jQuery -Query "MATCH ()-[r:ManagedBy]->() DELETE r"
# Managedby for groups
$TotalCount = $Groups.count
$Count = 0
Foreach($Group in $Groups.where({$_.ManagedBy -and $SIDMap.ContainsKey( $_.managedby ) -and $TypeMap.ContainsKey($_.managedby)})) {
    Write-Progress -Activity "Updating Neo4j" -Status  "Relating managedby for group $($Group.SID.value)" -PercentComplete (($Count / $TotalCount)*100)
    $Count++
    $SID = $null
    $SID = $SIDMap[$Group.ManagedBy]
    if($SID){
        New-Neo4jRelationship -LeftLabel Group -LeftHash @{ADSID = $Group.SID.Value} -RightLabel $TypeMap[$Group.ManagedBy] -RightHash @{ADSID = $SID} -Type ManagedBy
    }
}