functions/Import-GptIdentity.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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
function Import-GptIdentity
{
<#
    .SYNOPSIS
        Imports identity data exported from the source domain.
     
    .DESCRIPTION
        Imports identity data exported from the source domain.
        This data is used for mapping source identities to destination identities.
     
    .PARAMETER Path
        The path where to pick up the file.
     
    .PARAMETER Name
        Filter identities by name.
     
    .PARAMETER Domain
        The destination domain that later GPOs will be imported to.
     
    .PARAMETER Mapping
        A mapping hashtable allowing you to map identities that have unequal names.
     
    .EXAMPLE
        PS C:\> Import-GptIdentity -Path '.'
     
        Import the identity export file from the current folder.
#>

    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [ValidateScript({ Test-Path -Path $_ })]
        [string]
        $Path,
        
        [string[]]
        $Name = '*',
        
        [string]
        $Domain = $env:USERDNSDOMAIN,
        
        [System.Collections.IDictionary]
        $Mapping = @{ }
    )
    
    begin
    {
        $pathItem = Get-Item -Path $Path
        if ($pathItem.Extension -eq '.csv') { $resolvedPath = $pathItem.FullName }
        else { $resolvedPath = (Get-ChildItem -Path $pathItem.FullName -Filter 'gp_Identities*.csv' | Select-Object -First 1).FullName }
        if (-not $resolvedPath) { throw "Could not find identities file in $($pathItem.FullName)" }
        
        $rootDomain = (Get-ADForest -Server $Domain).RootDomain

        # Declare Module scope index of identities and what they map to
        $script:identityMapping = New-Object 'System.Collections.Generic.List[Object]'
        
        # Helpful Select Hashtables
        $select_TargetMapping = @{
            Name       = 'Target'
            Expression = { $Mapping[$importEntry.Name] }
        }
        $select_TargetName = @{
            Name       = 'Target'
            Expression = { $targetName }
        }
        $select_TargetDomain = @{
            Name = 'TargetDomain'
            Expression = { $domainObject }
        }
    }
    process
    {
        $importData = Import-Csv -Path $resolvedPath
        foreach ($importEntry in $importData)
        {
            # Skip entries filtered out
            if (-not (Test-Overlap -ReferenceObject $importEntry.Name -DifferenceObject $Name -Operator Like))
            {
                continue
            }
            
            #region Case: Mapped Entry
            if ($Mapping[$importEntry.Name])
            {
                $script:identityMapping.Add(($importEntry | Select-Object *, $select_TargetMapping))
            }
            #endregion Case: Mapped Entry
            
            #region Case: Discovery
            else
            {
                #region Case: Native BuiltIn Principal
                if (($importEntry.IsBuiltIn -eq 'True') -and ($importEntry.SID -like "*-32-*"))
                {
                    try { $targetName = ([System.Security.Principal.SecurityIdentifier]$importEntry.SID).Translate([System.Security.Principal.NTAccount]).Value }
                    catch
                    {
                        $adObject = Get-ADObject -Server $rootDomain -LDAPFilter "(objectSID=$($importEntry.SID))" -Properties Name
                        if (-not $adObject) {
                            Write-Warning "Failed to translate identity: $($importEntry.Name) ($($importEntry.SID))"
                            continue
                        }
                        $targetName = $adObject.Name
                    }
                    $script:identityMapping.Add(($importEntry | Select-Object *, $select_TargetName))
                }
                #endregion Case: Native BuiltIn Principal

                #region Case: Domain Specific BuiltIn Principal
                elseif ($importEntry.IsBuiltIn -eq 'True')
                {
                    try { $domainObject = Resolve-DomainMapping -DomainSid ($importEntry.SID -as [System.Security.Principal.SecurityIdentifier]).AccountDomainSid.Value -DomainFqdn $importEntry.DomainFqdn -DomainName $importEntry.DomainName }
                    catch { throw "Cannot resolve domain $($importEntry.DomainFqdn) for $($importEntry.Group) $($importEntry.Name)! $_" }

                    $targetSID = '{0}-{1}' -f $domainObject.DomainSID, $importEntry.RID
                    $adObject = Get-ADObject -Server $domainObject.DNSRoot -LDAPFilter "(&(objectClass=$($importEntry.Type))(objectSID=$($targetSID)))"
                    if (-not $adObject)
                    {
                        Write-Warning "Failed to resolve AD identity: $($importEntry.Name) ($($targetSID))"
                        continue
                    }
                    $targetName = $adObject.Name
                    $script:identityMapping.Add(($importEntry | Select-Object *, $select_TargetName, $select_TargetDomain))
                }
                #endregion Case: Domain Specific BuiltIn Principal
                
                #region Case: Custom Principal
                else
                {
                    try { $domainObject = Resolve-DomainMapping -DomainSid ($importEntry.SID -as [System.Security.Principal.SecurityIdentifier]).AccountDomainSid.Value -DomainFqdn $importEntry.DomainFqdn -DomainName $importEntry.DomainName }
                    catch { throw "Cannot resolve domain $($importEntry.DomainFqdn) for $($importEntry.Group) $($importEntry.Name)! $_" }

                    $adObject = Get-ADObject -Server $domainObject.DNSRoot -LDAPFilter "(&(objectClass=$($importEntry.Type))(name=$($importEntry.Name)))"
                    if (-not $adObject)
                    {
                        Write-Warning "Failed to resolve AD identity: $($importEntry.Name)"
                        continue
                    }
                    $targetName = $adObject.Name
                    $script:identityMapping.Add(($importEntry | Select-Object *, $select_TargetName, $select_TargetDomain))
                }
                #endregion Case: Custom Principal
            }
            #endregion Case: Discovery
        }
    }
}