Tests/cActiveDirectorySecurity.Tests.ps1

# Pester test file for module unit testing

Set-StrictMode -Version Latest

$ModulePath = (Split-Path -Parent (Split-Path -Parent $MyInvocation.MyCommand.Path))
$ModuleName = 'cActiveDirectorySecurity'

Import-Module (Join-Path $ModulePath "$ModuleName.psm1") -Force

## Disable default ADWS drive warning
$Env:ADPS_LoadDefaultDrive = 0
Import-Module -Name ActiveDirectory -Force

try
{
    InModuleScope $ModuleName {
        Describe "Test the Get-ADObjectRightsGUID function which enumerates Active Directory Schema and Extended Rights GUIDs." {
            $mockSchemaObjects = (Get-Content "$PSScriptRoot\schemaObjects.json" -Raw | ConvertFrom-Json)
            $mockAccessRights = (Get-Content -Path "$PSScriptRoot\accessRights.json" -Raw | ConvertFrom-Json)
            Mock -CommandName Get-ADRootDSE -MockWith { New-Object -TypeName PSObject -Property @{"configurationNamingContext" = "CN=Configuration,DC=contoso,DC=com"; "schemaNamingContext" = "CN=Schema,CN=Configuration,DC=contoso,DC=com"; }}
            Context "Retrieve all Schema and Extended Rights GUIDs and their names." {
                Mock -CommandName Get-ADObject -ParameterFilter {$LDAPFilter -eq '(schemaIDGUID=*)'} -MockWith { $mockSchemaObjects }
                Mock -CommandName Get-ADObject -ParameterFilter {$LDAPFilter -eq '(objectClass=controlAccessRight)'} -MockWith { $mockAccessRights }
                It "Test that all the Active Directory Schema Object and Extended Rights GUID retrieved from the (mocked) contoso.com Domain total 1843 in number." {
                    (Get-ADObjectRightsGUID).count | Should Be 1843
                }
            }
            Context "Retrieve a Schema object matching a specific name filter." {
                Mock -CommandName Get-ADObject -ParameterFilter { $LDAPFilter -eq '(&(schemaIDGUID=*)(Name=Computer))' } -MockWith { $mockSchemaObjects | Where-Object {$_.Name -eq 'Computer'} } -Verifiable
                Mock -CommandName Get-ADObject -ParameterFilter { $LDAPFilter -eq '(&(objectClass=controlAccessRight)(Name=Computer))'} -MockWith { $mockAccessRights | Where-Object {$_.Name -eq 'Computer'} } -Verifiable
                It "Test that when a Name filter is provided only the relevant schema object is returned (computer)." {
                    $rtVal = Get-ADObjectRightsGUID -Name 'Computer'
                    $rtVal.Values | Select-Object -First 1 | Should Be 'Computer'
                    Assert-MockCalled -CommandName Get-ADObject -ParameterFilter { $LDAPFilter -eq '(&(schemaIDGUID=*)(Name=Computer))' } -Times 1
                    Assert-MockCalled -CommandName Get-ADObject -ParameterFilter { $LDAPFilter -eq '(&(objectClass=controlAccessRight)(Name=Computer))' } -Times 1
                }
            }
            Context "Retrieve an Extended Right matching a specific name filter." {
                Mock -CommandName Get-ADObject -ParameterFilter { $LDAPFilter -eq '(&(schemaIDGUID=*)(Name=Personal-Information))' } -MockWith { $mockSchemaObjects | Where-Object {$_.Name -eq 'Personal-Information'} } -Verifiable
                Mock -CommandName Get-ADObject -ParameterFilter { $LDAPFilter -eq '(&(objectClass=controlAccessRight)(Name=Personal-Information))'} -MockWith { $mockAccessRights | Where-Object {$_.Name -eq 'Personal-Information'} } -Verifiable
                It "Test that when a Name filter is provided only the relevant extended right object is returned (Personal-Information)." {
                    $rtVal = Get-ADObjectRightsGUID -Name 'Personal-Information'
                    $rtVal.Values | Select-Object -First 1 | Should Be 'Personal-Information'
                    Assert-MockCalled -CommandName Get-ADObject -ParameterFilter { $LDAPFilter -eq '(&(schemaIDGUID=*)(Name=Personal-Information))' } -Times 1
                    Assert-MockCalled -CommandName Get-ADObject -ParameterFilter { $LDAPFilter -eq '(&(objectClass=controlAccessRight)(Name=Personal-Information))' } -Times 1
                }
            }
            Context "Retrieve an Extended Right matching a specific GUID filter." {
                $PersonalInformationGUID = [GUID]"77B5B886-944A-11d1-AEBD-0000F80367C1"
                Mock -CommandName Get-ADObject -ParameterFilter { $Filter -like "*schemaIDGUID*" } -MockWith { $mockSchemaObjects | Where-Object {$_.schemaIDGUID -eq ($PersonalInformationGUID.ToString())} } -Verifiable
                Mock -CommandName Get-ADObject -ParameterFilter { $Filter -like "*rightsGUID*" } -MockWith { $mockAccessRights | Where-Object {$_.rightsGUID -eq ($PersonalInformationGUID.ToString())} } -Verifiable
                It "Test that when a GUID filter is provided only the relevant extended right object is returned (Personal-Information)." {
                    $rtVal = Get-ADObjectRightsGUID -GUID $PersonalInformationGUID
                    $rtVal.Values | Select-Object -First 1 | Should Be 'Personal-Information'
                    Assert-MockCalled -CommandName Get-ADObject { $Filter -like "*schemaIDGUID*" }  -Times 1
                    Assert-MockCalled -CommandName Get-ADObject -ParameterFilter { $Filter -like "*rightsGUID*" } -Times 1
                }
            }
            Context "Retrieve an Schema object matching a specific GUID filter." {
                $ComputerGUID = [GUID]"bf967a86-0de6-11d0-a285-00aa003049e2"
                Mock -CommandName Get-ADObject -ParameterFilter { $Filter -like "*schemaIDGUID*" } -MockWith { $mockSchemaObjects | Where-Object {$_.schemaIDGUID -eq ($ComputerGUID.ToString())} } -Verifiable
                Mock -CommandName Get-ADObject -ParameterFilter { $Filter -like "*rightsGUID*" } -MockWith { $mockAccessRights | Where-Object {$_.rightsGUID -eq ($ComputerGUID.ToString())} } -Verifiable
                It "Test that when a GUID filter is provided only the relevant extended right object is returned (Computer)." {
                    $rtVal = Get-ADObjectRightsGUID -GUID $ComputerGUID
                    $rtVal.Values | Select-Object -First 1 | Should Be 'Computer'
                    Assert-MockCalled -CommandName Get-ADObject { $Filter -like "*schemaIDGUID*" }  -Times 1
                    Assert-MockCalled -CommandName Get-ADObject -ParameterFilter { $Filter -like "*rightsGUID*" } -Times 1
                }
            }
            Context "The Schema Object / Extended Right specified cannot be found." {
                Mock -CommandName Get-ADObject -ParameterFilter { $LDAPFilter -eq '(&(schemaIDGUID=*)(Name=Computers))' } -MockWith { $mockSchemaObjects | Where-Object {$_.Name -eq 'Computers'} } -Verifiable
                Mock -CommandName Get-ADObject -ParameterFilter { $LDAPFilter -eq '(&(objectClass=controlAccessRight)(Name=Computers))'} -MockWith { $mockAccessRights | Where-Object {$_.Name -eq 'Computers'} } -Verifiable
                It "Tests that a null value is returned where the specified Schema Object / Extended Right doesn't exist." {
                    Get-ADObjectRightsGUID -Name 'Computers' | Should Be $null
                    Assert-MockCalled -CommandName Get-ADObject -ParameterFilter { $LDAPFilter -eq '(&(schemaIDGUID=*)(Name=Computers))' } -Times 1
                    Assert-MockCalled -CommandName Get-ADObject -ParameterFilter { $LDAPFilter -eq '(&(objectClass=controlAccessRight)(Name=Computers))' } -Times 1
                }
            }
            Context "Retrieve the 'All' Schema Object / Extended Right by Name, which needs to be handled specifically." {
                It "Test that a value of 'All' is passed to the Name filter only the relevant object is returned (All)." {
                    $rtVal = Get-ADObjectRightsGUID -Name 'All'
                    $rtVal.Values | Select-Object -First 1 | Should Be 'All'
                }
            }
            Context "Retrieve the 'All' Schema Object / Extended Right by GUID, which needs to be handled specifically." {
                $AllGUID = [GUID]'00000000-0000-0000-0000-000000000000'
                It "Test that a GUID of '00000000-0000-0000-0000-000000000000' is passed to the GUID filter only the relevant object is returned (All)." {
                    $rtVal = Get-ADObjectRightsGUID -GUID $AllGUID
                    $rtVal.Values | Select-Object -First 1 | Should Be 'All'
                }
            }
        }
        Describe "Test some basic error handling of the Get-ADObjectAcl function." {
            Mock -CommandName Get-ADDomain -MockWith { New-Object -TypeName PSObject -Property @{"NetBIOSName" = "CONTOSO"} }
            Context "Test Identity parameter passed as string and where object cannot be found." {
                Mock -CommandName Write-Warning -MockWith { } -ParameterFilter {$Message -like "An error occurred locating an object with the identity specified ('CN=JoeB,CN=Users,DC=contoso,DC=com').*"  } -Verifiable
                Mock -CommandName Write-Error -MockWith { } -Verifiable
                Mock -CommandName Set-Location -MockWith { }
                Mock -CommandName  Get-ADObjectRightsGUID -MockWith { }
                Mock Get-ADObject -MockWith { throw "Get-ADObject : Cannot find an object with identity: 'CN=JoeB,CN=Users,DC=contoso,DC=com' under: 'DC=contoso,DC=com'."}
                It "Generates a warning and error message when the specified identity (in string format) cannot be found." {
                    Get-ADObjectAcl -Identity 'CN=JoeB,CN=Users,DC=contoso,DC=com' | Should Be $null
                    Assert-MockCalled -CommandName Write-Warning -Times 1
                    Assert-MockCalled -CommandName Write-Error -Times 1
                }
            }
            Context "Test Identity parameter set to an object that doesn't include either of the mandatory properties of either DistinguishedName or objectGUID." {
                $Identity = New-Object -TypeName PSObject -Property @{sAMAccountName = "Test"}
                Mock -CommandName Write-Warning -MockWith { } -Verifiable
                Mock -CommandName Write-Error -MockWith { } -Verifiable
                Mock -CommandName Set-Location -MockWith { }
                Mock -CommandName  Get-ADObjectRightsGUID -MockWith { }
                It "Generates a warning and error message when the Identity Object passed doesn't include either a DistinguishedName or ObjectGUID property." {
                    Get-ADObjectAcl -Identity $Identity | Should Be $null
                    Assert-MockCalled -CommandName Write-Warning -Times 1
                    Assert-MockCalled -CommandName Write-Error -Times 1
                }
            }
        }
        Describe "Simulate calls to the Get-ADObjectAcl functions with mock data from the root of the default (CONTOSO) Domain." {
            $mockSchemaObjects = (Get-Content "$PSScriptRoot\schemaObjects.json" -Raw | ConvertFrom-Json)
            $mockAccessRights = (Get-Content -Path "$PSScriptRoot\accessRights.json" -Raw | ConvertFrom-Json)
            $mockPermissions = (Get-Content -Path "$PSScriptRoot\MockPermissions.json" -Raw | ConvertFrom-Json)
            Mock -CommandName Get-ADRootDSE -MockWith { New-Object -TypeName PSObject -Property @{"configurationNamingContext" = "CN=Configuration,DC=contoso,DC=com"; "schemaNamingContext" = "CN=Schema,CN=Configuration,DC=contoso,DC=com"; }}
            Mock -CommandName Get-ADDomain -MockWith { New-Object -TypeName PSObject -Property @{"NetBIOSName" = "CONTOSO"} }
            $Identity = New-Object -TypeName PSObject -Property @{"Name" = "CONTOSO"; "DistinguishedName" = "DC=contoso,DC=com" ; "DNSRoot" = "contoso.com"}
            Mock -CommandName Get-ADObject -ParameterFilter {$LDAPFilter -eq '(schemaIDGUID=*)'} -MockWith { $mockSchemaObjects }
            Mock -CommandName Get-ADObject -ParameterFilter {$LDAPFilter -eq '(objectClass=controlAccessRight)'} -MockWith { $mockAccessRights }
            Mock -CommandName Set-Location -MockWith { }
            Mock -CommandName Resolve-ObjectSidToName -MockWith { Return $Sid }
            Context "Gather permissions from the root of the default (CONTOSO) Domain." {
                Mock -CommandName Get-Acl -MockWith {
                    $ContosoAcl = $mockPermissions.ContosoDomainPermissions
                    $permissions = $ContosoAcl | Select-Object -Property @(
                        "ActiveDirectoryRights"
                        "InheritanceType"
                        @{n = "ObjectType"; e = {[System.GUID]$_.ObjectType}}
                        @{n = "InheritedObjectType"; e = {[System.GUID]$_.InheritedObjectType}}
                        "ObjectFlags"
                        "AccessControlType"
                        "IdentityReference"
                        "IsInherited"
                        "InheritanceFlags"
                        "PropagationFlags"
                    )
                    Return New-Object -TypeName PSObject -Property @{"Access" = $permissions}
                }
                It "Tests that all ACEs (53) are returned." {
                    (Get-ADObjectAcl -Identity $Identity).count | Should Be 53
                }
                It "Tests that filtering with the IdentityReference parameter retrieves only pertinent objects (1)." {
                    $rtVal = Get-ADObjectAcl -Identity $Identity -IdentityReference "CONTOSO\Domain Admins"
                    $rtVal | Select-Object -ExpandProperty IdentityReference | Should Be "CONTOSO\Domain Admins"
                }
                It "Tests that filtering with IsInherited flag set to false retrieves only pertinent objects (53). At the root of the domain no permissions are inherited." {
                    $rtVal = Get-ADObjectAcl -Identity $Identity -IsInherited $false
                    $rtVal.count | Should Be 53
                }
                It "Tests that filtering with the IsInherited parameter set to true retrieves only pertinent objects (0). At the root of the domain no permissions are inherited." {
                    $rtVal = Get-ADObjectAcl -Identity $Identity -IsInherited $true
                    $rtVal.count | Should Be 0
                }
                It "Tests that filtering with the ActiveDirectoryRights parameter retrieves only pertinent objects (17)." {
                    $rtVal = Get-ADObjectAcl -Identity $Identity -ActiveDirectoryRights ReadProperty
                    $rtVal.count | Should Be 17
                }
                It "Tests that filtering with multiple ActiveDirectoryRights retrieves only pertinent objects (3)." {
                    $rtVal = Get-ADObjectAcl -Identity $Identity -ActiveDirectoryRights ReadProperty, WriteProperty
                    $rtVal.count | Should Be 3
                    $rtVal | Select-Object -ExpandProperty IdentityReference -First 1 | Should Be "NT Authority\SELF"
                    $rtVal | Select-Object -ExpandProperty IdentityReference -Last 1 | Should Be "CONTOSO\Enterprise Key Admins"
                }
                It "Tests that filtering on InheritanceType retrieves only pertinent objects (4)." {
                    $rtVal = Get-ADObjectAcl -Identity $Identity -InheritanceType Descendents
                    $rtVal.count | Should Be 20
                    $rtVal | Select-Object -ExpandProperty IdentityReference -First 1 | Should Be "CREATOR OWNER"
                    $rtVal | Select-Object -ExpandProperty IdentityReference -Last 1 | Should Be "BUILTIN\Pre-Windows 2000 Compatible Access"
                }
                It "Tests that filtering on InheritedObjectTypeName retrieves only pertinent objects (4)." {
                    $rtVal = Get-ADObjectAcl -Identity $Identity -InheritedObjectTypeName Computer
                    $rtVal.count | Should Be 4
                    $rtVal | ForEach-Object { $_ | Select-Object -ExpandProperty InheritedObjectTypeName | Should Be "Computer" }
                }
                It "Tests that filtering on ObjectTypeName retrieves only pertinent objects (2)." {
                    $rtVal = Get-ADObjectAcl -Identity $Identity -ObjectTypeName DS-Validated-Write-Computer
                    $rtVal.count | Should Be 2
                    $rtVal | ForEach-Object { $_ | Select-Object -ExpandProperty ObjectTypeName | Should Be "DS-Validated-Write-Computer" }
                }
            }
        }
        Describe "Simulate calls to the Get-ADObjectAcl functions with mock data from the Domain Controllers Organizational Unit of the default (CONTOSO) Domain." {
            $mockSchemaObjects = (Get-Content "$PSScriptRoot\schemaObjects.json" -Raw | ConvertFrom-Json)
            $mockAccessRights = (Get-Content -Path "$PSScriptRoot\accessRights.json" -Raw | ConvertFrom-Json)
            $mockPermissions = (Get-Content -Path "$PSScriptRoot\MockPermissions.json" -Raw | ConvertFrom-Json)
            Mock -CommandName Get-ADRootDSE -MockWith { New-Object -TypeName PSObject -Property @{"configurationNamingContext" = "CN=Configuration,DC=contoso,DC=com"; "schemaNamingContext" = "CN=Schema,CN=Configuration,DC=contoso,DC=com"; }}
            Mock -CommandName Get-ADDomain -MockWith { New-Object -TypeName PSObject -Property @{"NetBIOSName" = "CONTOSO"} }
            $Identity = New-Object -TypeName PSObject -Property @{"Name" = "Domain Controllers"; "DistinguishedName" = "OU=Domain Controllers,DC=contoso,DC=com"}
            Mock -CommandName Get-ADObject -ParameterFilter {$LDAPFilter -eq '(schemaIDGUID=*)'} -MockWith { $mockSchemaObjects }
            Mock -CommandName Get-ADObject -ParameterFilter {$LDAPFilter -eq '(objectClass=controlAccessRight)'} -MockWith { $mockAccessRights }
            Mock -CommandName Set-Location -MockWith { }
            Mock -CommandName Resolve-ObjectSidToName -MockWith { Return $Sid }
            Context "Gather all permissions from the Domain Controllers Organizational Units of the default (CONTOSO) Domain." {
                Mock -CommandName Get-Acl -MockWith {
                    $ContosoAcl = $mockPermissions.ContosoDomainControllersPermissions
                    $permissions = $ContosoAcl | Select-Object -Property @(
                        "ActiveDirectoryRights"
                        "InheritanceType"
                        @{n = "ObjectType"; e = {[System.GUID]$_.ObjectType}}
                        @{n = "InheritedObjectType"; e = {[System.GUID]$_.InheritedObjectType}}
                        "ObjectFlags"
                        "AccessControlType"
                        "IdentityReference"
                        "IsInherited"
                        "InheritanceFlags"
                        "PropagationFlags"
                    )
                    Return New-Object -TypeName PSObject -Property @{"Access" = $permissions}
                }
                It "Tests that all ACEs (30) are returned." {
                    (Get-ADObjectAcl -Identity $Identity).count | Should Be 30
                }
                It "Tests that filtering with IsInherited flag set to false retrieves only pertinent objects (4)." {
                    $rtVal = Get-ADObjectAcl -Identity $Identity -IsInherited $false
                    $rtVal.count | Should Be 4
                }
                It "Tests that filtering with the IsInherited parameter set to true retrieves only pertinent objects (26)." {
                    $rtVal = Get-ADObjectAcl -Identity $Identity -IsInherited $true
                    $rtVal.count | Should Be 26
                }
            }
        }
        Describe "Test some basic error handling of the Add-ADObjectAce function." {
            $mockSchemaObjects = (Get-Content "$PSScriptRoot\schemaObjects.json" -Raw | ConvertFrom-Json)
            $mockAccessRights = (Get-Content -Path "$PSScriptRoot\accessRights.json" -Raw | ConvertFrom-Json)
            Mock -CommandName Get-ADRootDSE -MockWith { New-Object -TypeName PSObject -Property @{"configurationNamingContext" = "CN=Configuration,DC=contoso,DC=com"; "schemaNamingContext" = "CN=Schema,CN=Configuration,DC=contoso,DC=com"; }}
            Mock -CommandName Get-ADDomain -MockWith { New-Object -TypeName PSObject -Property @{"NetBIOSName" = "CONTOSO"} }
            Mock -CommandName Set-Location -MockWith { }
            Context "The specified Identity cannot be found." {
                Mock Get-ADObject -MockWith { throw "Get-ADObject : Cannot find an object with identity: 'CN=JoeB,CN=Users,DC=contoso,DC=com' under: 'DC=contoso,DC=com'."}
                Mock -CommandName Get-ADObject -ParameterFilter { $LDAPFilter -eq '(&(schemaIDGUID=*)(Name=Computers))' } -MockWith { $mockSchemaObjects | Where-Object {$_.Name -eq 'Computers'} } -Verifiable
                Mock -CommandName Get-ADObject -ParameterFilter { $LDAPFilter -eq '(&(objectClass=controlAccessRight)(Name=Computers))'} -MockWith { $mockAccessRights | Where-Object {$_.Name -eq 'Computers'} } -Verifiable
                Mock -CommandName Write-Warning -MockWith { } -ParameterFilter {$Message -like "An error occurred locating an object with the identity specified ('CN=JoeB,CN=Users,DC=contoso,DC=com').*"  } -Verifiable
                Mock -CommandName Write-Error -MockWith {} -Verifiable
                It "Generates a warning and error message when the specified Identity cannot be found." {
                    Add-ADObjectAce -Identity 'CN=JoeB,CN=Users,DC=contoso,DC=com' -IdentityReference "CONTOSO\JaneD" -ActiveDirectoryRights ReadProperty, WriteProperty, ExtendedRight -ObjectTypeName 'Private-Information'  | Should Be $null
                    Assert-MockCalled -CommandName Write-Warning -Times 1
                    Assert-MockCalled -CommandName Write-Error -Times 1
                }
            }
            Context "The specified Identity Reference cannot be translated to a Sid." {
                $Identity = New-Object -TypeName PSObject -Property @{"Name" = "Domain Controllers"; "DistinguishedName" = "OU=Domain Controllers,DC=contoso,DC=com"}
                Mock -CommandName Resolve-NameToObjectSid -ParameterFilter {$IdentityReference -eq "CONTOSO\Domain Admins"} -MockWith { Return $null }
                Mock -CommandName Write-Warning -MockWith { } -ParameterFilter {$Message -eq "An error occurred translating the Identity Reference ('CONTOSO\Domain Admins') to a Sid value. Processing cannot continue."} -Verifiable
                It "Generates a warning message when the specified Identity Reference cannot be translated into an object Sid value." {
                    Add-ADObjectAce -Identity $Identity -IdentityReference "CONTOSO\Domain Admins" -ActiveDirectoryRights CreateChild, DeleteChild -ObjectTypeName 'Computers' -InheritedObjectTypeName 'All'  | Should Be $null
                    Assert-MockCalled -CommandName Write-Warning -Times 1
                }
            }
            Context "The specified ObjectTypeName cannot be found." {
                $Identity = New-Object -TypeName PSObject -Property @{"Name" = "Domain Controllers"; "DistinguishedName" = "OU=Domain Controllers,DC=contoso,DC=com"}
                Mock -CommandName Resolve-NameToObjectSid -ParameterFilter {$IdentityReference -eq "CONTOSO\Domain Admins"} -MockWith { Return (New-Object System.Security.Principal.SecurityIdentifier("S-1-5-21-2295585024-2604479722-1786026388-516")) }
                Mock -CommandName Get-ADObject -ParameterFilter { $LDAPFilter -eq '(&(schemaIDGUID=*)(Name=Computers))' } -MockWith { $mockSchemaObjects | Where-Object {$_.Name -eq 'Computers'} } -Verifiable
                Mock -CommandName Get-ADObject -ParameterFilter { $LDAPFilter -eq '(&(objectClass=controlAccessRight)(Name=Computers))'} -MockWith { $mockAccessRights | Where-Object {$_.Name -eq 'Computers'} } -Verifiable
                Mock -CommandName Write-Warning -MockWith { } -ParameterFilter {$Message -eq "An error occurred locating the ObjectTypeName with the name specified ('Computers')."} -Verifiable
                It "Generates a warning and error message when the specified ObjectTypeName cannot be found and returns a null value." {
                    Add-ADObjectAce -Identity $Identity -IdentityReference "CONTOSO\Domain Admins" -ActiveDirectoryRights CreateChild, DeleteChild -ObjectTypeName 'Computers' -InheritedObjectTypeName 'All'  | Should Be $null
                    Assert-MockCalled -CommandName Write-Warning -Times 1
                }
            }
            Context "The specified InheritedObjectTypeName cannot be found." {
                $Identity = New-Object -TypeName PSObject -Property @{"Name" = "Computers"; "DistinguishedName" = "CN=Computers,DC=contoso,DC=com"}
                Mock -CommandName Resolve-NameToObjectSid -ParameterFilter {$IdentityReference -eq "CONTOSO\Domain Admins"} -MockWith { Return (New-Object System.Security.Principal.SecurityIdentifier("S-1-5-21-2295585024-2604479722-1786026388-516")) }
                Mock -CommandName Get-ADObject -ParameterFilter { $LDAPFilter -eq '(&(schemaIDGUID=*)(Name=ms-TPM-Tpm-Information-For-Computer))' } -MockWith { $mockSchemaObjects | Where-Object {$_.Name -eq 'ms-TPM-Tpm-Information-For-Computer'} } -Verifiable
                Mock -CommandName Get-ADObject -ParameterFilter { $LDAPFilter -eq '(&(schemaIDGUID=*)(Name=Computers))' } -MockWith { $mockSchemaObjects | Where-Object {$_.Name -eq 'Computers'} } -Verifiable
                Mock -CommandName Write-Warning -MockWith { } -ParameterFilter {$Message -eq "An error occurred locating the InheritedObjectTypeName with the name specified ('Computers')."} -Verifiable
                It "Generates a warning when the specified ObjectTypeName cannot be found and returns a null value." {
                    Add-ADObjectAce -Identity $Identity -IdentityReference "CONTOSO\Domain Admins" -ActiveDirectoryRights WriteProperty -ObjectTypeName 'ms-TPM-Tpm-Information-For-Computer' -InheritedObjectTypeName 'Computers'  | Should Be $null
                    Assert-MockCalled -CommandName Write-Warning -Times 1
                }
            }
        }
        Describe "Use the Add-ADObjectAce function to generate some Access Control Entries and ensure they compare to their equivalents." {
            # https://msdn.microsoft.com/en-us/library/system.directoryservices.activedirectoryaccessrule(v=vs.110).aspx
            $mockSchemaObjects = (Get-Content "$PSScriptRoot\schemaObjects.json" -Raw | ConvertFrom-Json)
            $mockAccessRights = (Get-Content -Path "$PSScriptRoot\accessRights.json" -Raw | ConvertFrom-Json)
            $mockPermissions = (Get-Content -Path "$PSScriptRoot\MockPermissions.json" -Raw | ConvertFrom-Json)
            Mock -CommandName Get-ADRootDSE -MockWith { New-Object -TypeName PSObject -Property @{"configurationNamingContext" = "CN=Configuration,DC=contoso,DC=com"; "schemaNamingContext" = "CN=Schema,CN=Configuration,DC=contoso,DC=com"; }}
            Mock -CommandName Get-ADDomain -MockWith { New-Object -TypeName PSObject -Property @{"NetBIOSName" = "CONTOSO"} }
            Mock -CommandName Get-ADObject -ParameterFilter {$LDAPFilter -eq '(schemaIDGUID=*)'} -MockWith { $mockSchemaObjects }
            Mock -CommandName Get-ADObject -ParameterFilter {$LDAPFilter -eq '(objectClass=controlAccessRight)'} -MockWith { $mockAccessRights }
            Mock -CommandName Set-Location -MockWith { }
            Mock -CommandName Resolve-ObjectSidToName -MockWith { Return $Sid }
            Mock -CommandName Get-Acl -MockWith {
                $ContosoAcl = $mockPermissions.ContosoDomainPermissions
                $permissions = $ContosoAcl | Select-Object -Property @(
                    "ActiveDirectoryRights"
                    "InheritanceType"
                    @{n = "ObjectType"; e = {[System.GUID]$_.ObjectType}}
                    @{n = "InheritedObjectType"; e = {[System.GUID]$_.InheritedObjectType}}
                    "ObjectFlags"
                    "AccessControlType"
                    "IdentityReference"
                    "IsInherited"
                    "InheritanceFlags"
                    "PropagationFlags"
                )
                Return New-Object -TypeName PSObject -Property @{"Access" = $permissions}
            }
            $props = @("AccessControlType", "ActiveDirectoryRights", "DistinguishedName", "IdentityReference", "InheritanceFlags", "InheritanceType", "InheritedObjectType", "InheritedObjectTypeName", "IsInherited", "ObjectFlags", "ObjectType", "ObjectTypeName", "PropagationFlags", "IdentityReferenceDomain", "IdentityReferenceName")
            $Identity = New-Object -TypeName PSObject -Property @{"Name" = "Domain Controllers"; "DistinguishedName" = "OU=Domain Controllers,DC=contoso,DC=com"}
            Context "Retrieve a specific ACE from the root of the default (CONTOSO) Domain and compare it to an equivalent ACE generated by Add-ADObjectAce (IdentityReference, ActiveDirectoryRights, AccessControlType) (-Whatif)." {
                # https://msdn.microsoft.com/en-us/library/99s25ayd(v=vs.110).aspx
                Mock -CommandName Resolve-NameToObjectSid -ParameterFilter {$IdentityReference -eq "CONTOSO\Domain Admins"} -MockWith { Return (New-Object System.Security.Principal.SecurityIdentifier("S-1-5-21-2295585024-2604479722-1786026388-512")) }
                $Ace1 = Get-ADObjectAcl -Identity $Identity -IdentityReference "CONTOSO\Domain Admins" -ActiveDirectoryRights CreateChild, Self, WriteProperty, ExtendedRight, GenericRead, WriteDacl, WriteOwner -AccessControlType Allow
                $Ace2 = Add-ADObjectAce -Identity $Identity -IdentityReference "CONTOSO\Domain Admins" -ActiveDirectoryRights CreateChild, Self, WriteProperty, ExtendedRight, GenericRead, WriteDacl, WriteOwner -AccessControlType Allow -Whatif
                forEach ($prop in $props)
                {
                    It "Compares the $prop property of the two Access Control Entries." {
                        Compare-Object -ReferenceObject $Ace1 -DifferenceObject $Ace2 -Property $prop | Should Be $null
                    }
                }
            }
            Context "Retrieve a specific ACE from the root of the default (CONTOSO) Domain and compare it to an equivalent ACE generated by Add-ADObjectAce (IdentityReference, ActiveDirectoryRights, AccessControlType, ActiveDirectorySecurityInheritance) (-Whatif)." {
                # https://msdn.microsoft.com/en-us/library/xh02bekw(v=vs.110).aspx
                Mock -CommandName Resolve-NameToObjectSid -ParameterFilter {$IdentityReference -eq "CONTOSO\Enterprise Admins"} -MockWith { Return (New-Object System.Security.Principal.SecurityIdentifier("S-1-5-21-2295585024-2604479722-1786026388-519")) }
                $Ace1 = Get-ADObjectAcl -Identity $Identity -IdentityReference "CONTOSO\Enterprise Admins" -ActiveDirectoryRights GenericAll -AccessControlType Allow -InheritanceType All
                $Ace2 = Add-ADObjectAce -Identity $Identity -IdentityReference "CONTOSO\Enterprise Admins" -ActiveDirectoryRights GenericAll -AccessControlType Allow -InheritanceType All -WhatIf
                forEach ($prop in $props)
                {
                    It "Compares the $prop property of the two Access Control Entries." {
                        Compare-Object -ReferenceObject $Ace1 -DifferenceObject $Ace2 -Property $prop | Should Be $null
                    }
                }
            }
            Context "Retrieve a specific ACE from the root of the default (CONTOSO) Domain and compare it to an equivalent ACE generated by Add-ADObjectAce (IdentityReference, ActiveDirectoryRights, AccessControlType, ActiveDirectorySecurityInheritance, Guid) (-Whatif)." {
                # https://msdn.microsoft.com/en-us/library/4b75624d(v=vs.110).aspx
                Mock -CommandName Resolve-NameToObjectSid -ParameterFilter {$IdentityReference -eq "BUILTIN\Pre-Windows 2000 Compatible Access"} -MockWith { Return (New-Object System.Security.Principal.SecurityIdentifier("S-1-5-32-554")) }
                Mock -CommandName Get-ADObject -ParameterFilter { $LDAPFilter -eq '(&(schemaIDGUID=*)(Name=Group))' } -MockWith { $mockSchemaObjects | Where-Object {$_.Name -eq 'Group'} } -Verifiable
                Mock -CommandName Get-ADObject -ParameterFilter { $LDAPFilter -eq '(&(objectClass=controlAccessRight)(Name=Group))'} -MockWith { $mockAccessRights | Where-Object {$_.Name -eq 'Group'} } -Verifiable
                Mock -CommandName Get-ADObject -ParameterFilter { $Filter -like "*schemaIDGUID*"} -MockWith { $mockSchemaObjects | Where-Object {$_.schemaIDGUID -eq 'bf967a9c-0de6-11d0-a285-00aa003049e2'} } -Verifiable
                Mock -CommandName Get-ADObject -ParameterFilter { $Filter -like "*rightsGUID*"} -MockWith { $mockAccessRights | Where-Object {$_.rightsGUID -eq 'bf967a9c-0de6-11d0-a285-00aa003049e2'} } -Verifiable
                $Ace1 = Get-ADObjectAcl -Identity $Identity -IdentityReference "BUILTIN\Pre-Windows 2000 Compatible Access" -ActiveDirectoryRights GenericRead -AccessControlType Allow -InheritanceType Descendents -InheritedObjectTypeName "Group"
                $Ace2 = Add-ADObjectAce -Identity $Identity -IdentityReference "BUILTIN\Pre-Windows 2000 Compatible Access" -ActiveDirectoryRights GenericRead -AccessControlType Allow -InheritanceType Descendents -InheritedObjectTypeName "Group" -WhatIf
                forEach ($prop in $props)
                {
                    It "Compares the $prop property of the two Access Control Entries." {
                        Compare-Object -ReferenceObject $Ace1 -DifferenceObject $Ace2 -Property $prop | Should Be $null
                    }
                }
            }
            Context "Retrieve a specific ACE from the root of the default (CONTOSO) Domain and compare it to an equivalent ACE generated by Add-ADObjectAce (IdentityReference, ActiveDirectoryRights, AccessControlType, Guid) (-Whatif)." {
                # https://msdn.microsoft.com/en-us/library/sskw937h(v=vs.110).aspx
                Mock -CommandName Resolve-NameToObjectSid -ParameterFilter {$IdentityReference -eq "CONTOSO\Domain Controllers"} -MockWith { Return (New-Object System.Security.Principal.SecurityIdentifier("S-1-5-21-2295585024-2604479722-1786026388-516")) }
                Mock -CommandName Get-ADObject -ParameterFilter { $LDAPFilter -eq '(&(schemaIDGUID=*)(Name=DS-Replication-Get-Changes-All))' } -MockWith { $mockSchemaObjects | Where-Object {$_.Name -eq 'DS-Replication-Get-Changes-All'} } -Verifiable
                Mock -CommandName Get-ADObject -ParameterFilter { $LDAPFilter -eq '(&(objectClass=controlAccessRight)(Name=DS-Replication-Get-Changes-All))'} -MockWith { $mockAccessRights | Where-Object {$_.Name -eq 'DS-Replication-Get-Changes-All'} } -Verifiable
                Mock -CommandName Get-ADObject -ParameterFilter { $Filter -like "*schemaIDGUID*"} -MockWith { $mockSchemaObjects | Where-Object {$_.schemaIDGUID -eq '1131f6ad-9c07-11d1-f79f-00c04fc2dcd2'} } -Verifiable
                Mock -CommandName Get-ADObject -ParameterFilter { $Filter -like "*rightsGUID*"} -MockWith { $mockAccessRights | Where-Object {$_.rightsGUID -eq '1131f6ad-9c07-11d1-f79f-00c04fc2dcd2'} } -Verifiable
                $Ace1 = Get-ADObjectAcl -Identity $Identity -IdentityReference "CONTOSO\Domain Controllers" -ActiveDirectoryRights ExtendedRight -AccessControlType Allow -ObjectTypeName "DS-Replication-Get-Changes-All"
                $Ace2 = Add-ADObjectAce -Identity $Identity -IdentityReference "CONTOSO\Domain Controllers" -ActiveDirectoryRights ExtendedRight -AccessControlType Allow -ObjectTypeName "DS-Replication-Get-Changes-All" -WhatIf
                forEach ($prop in $props)
                {
                    It "Compares the $prop property of the two Access Control Entries." {
                        Compare-Object -ReferenceObject $Ace1 -DifferenceObject $Ace2 -Property $prop | Should Be $null
                    }
                }
            }
            Context "Retrieve a specific ACE from the root of the default (CONTOSO) Domain and compare it to an equivalent ACE generated by Add-ADObjectAce (IdentityReference, ActiveDirectoryRights, AccessControlType, Guid, ActiveDirectorySecurityInheritance) (-Whatif)." {
                # https://msdn.microsoft.com/en-us/library/cawwkf0x(v=vs.110).aspx
                Mock -CommandName Resolve-NameToObjectSid -ParameterFilter {$IdentityReference -eq "CONTOSO\Key Admins"} -MockWith { Return (New-Object System.Security.Principal.SecurityIdentifier("S-1-5-21-2295585024-2604479722-1786026388-526")) }
                Mock -CommandName Get-ADObject -ParameterFilter { $LDAPFilter -eq '(&(schemaIDGUID=*)(Name=ms-DS-Key-Credential-Link))' } -MockWith { $mockSchemaObjects | Where-Object {$_.Name -eq 'ms-DS-Key-Credential-Link'} } -Verifiable
                Mock -CommandName Get-ADObject -ParameterFilter { $LDAPFilter -eq '(&(objectClass=controlAccessRight)(Name=ms-DS-Key-Credential-Link))'} -MockWith { $mockAccessRights | Where-Object {$_.Name -eq 'ms-DS-Key-Credential-Link'} } -Verifiable
                Mock -CommandName Get-ADObject -ParameterFilter { $Filter -like "*schemaIDGUID*"} -MockWith { $mockSchemaObjects | Where-Object {$_.schemaIDGUID -eq '5b47d60f-6090-40b2-9f37-2a4de88f3063'} } -Verifiable
                Mock -CommandName Get-ADObject -ParameterFilter { $Filter -like "*rightsGUID*"} -MockWith { $mockAccessRights | Where-Object {$_.rightsGUID -eq '5b47d60f-6090-40b2-9f37-2a4de88f3063'} } -Verifiable
                $Ace1 = Get-ADObjectAcl -Identity $Identity -IdentityReference "CONTOSO\Key Admins" -ActiveDirectoryRights ReadProperty, WriteProperty -AccessControlType Allow -ObjectTypeName "ms-DS-Key-Credential-Link" -InheritanceType All
                $Ace2 = Add-ADObjectAce -Identity $Identity -IdentityReference "CONTOSO\Key Admins" -ActiveDirectoryRights ReadProperty, WriteProperty -AccessControlType Allow -ObjectTypeName "ms-DS-Key-Credential-Link" -InheritanceType All -WhatIf
                forEach ($prop in $props)
                {
                    It "Compares the $prop property of the two Access Control Entries." {
                        Compare-Object -ReferenceObject $Ace1 -DifferenceObject $Ace2 -Property $prop | Should Be $null
                    }
                }
            }
            Context "Retrieve a specific ACE from the root of the default (CONTOSO) Domain and compare it to an equivalent ACE generated by Add-ADObjectAce (IdentityReference, ActiveDirectoryRights, AccessControlType, Guid, ActiveDirectorySecurityInheritance, Guid) (-Whatif)." {
                # https://msdn.microsoft.com/en-us/library/w72e8e69(v=vs.110).aspx
                Mock -CommandName Resolve-NameToObjectSid -ParameterFilter {$IdentityReference -eq "BUILTIN\Pre-Windows 2000 Compatible Access"} -MockWith { Return (New-Object System.Security.Principal.SecurityIdentifier("S-1-5-32-554")) }
                Mock -CommandName Get-ADObject -ParameterFilter { $LDAPFilter -eq '(&(schemaIDGUID=*)(Name=User))' } -MockWith { $mockSchemaObjects | Where-Object {$_.Name -eq 'User'} } -Verifiable
                Mock -CommandName Get-ADObject -ParameterFilter { $LDAPFilter -eq '(&(objectClass=controlAccessRight)(Name=General-Information))'} -MockWith { $mockAccessRights | Where-Object {$_.Name -eq 'General-Information'} } -Verifiable
                $objectTypeGUID = [GUID]'59ba2f42-79a2-11d0-9020-00c04fc2d3cf' # General-Information
                $inheritedObjectTypeGUID = [GUID]'bf967aba-0de6-11d0-a285-00aa003049e2' # user
                Mock -CommandName Get-ADObjectRightsGUID -ParameterFilter { $GUID -eq $objectTypeGUID } -MockWith { $mockAccessRightsObject = ($mockAccessRights | Where-Object {$_.rightsGUID -eq $objectTypeGUID.ToString()}); Return @{[GUID]$mockAccessRightsObject.rightsGUID = $mockAccessRightsObject.Name} } -Verifiable
                Mock -CommandName Get-ADObjectRightsGUID -ParameterFilter { $GUID -eq $inheritedObjectTypeGUID } -MockWith { $mockSchemaObject = ($mockSchemaObjects | Where-Object {$_.schemaIDGUID -eq $inheritedObjectTypeGUID.ToString()}); Return @{[GUID]$mockSchemaObject.schemaIDGUID = $mockSchemaObject.Name} } -Verifiable
                $Ace1 = Get-ADObjectAcl -Identity $Identity -IdentityReference "BUILTIN\Pre-Windows 2000 Compatible Access" -ActiveDirectoryRights ReadProperty -AccessControlType Allow -ObjectTypeName "General-Information" -InheritanceType Descendents -InheritedObjectTypeName "User"
                $Ace2 = Add-ADObjectAce -Identity $Identity -IdentityReference "BUILTIN\Pre-Windows 2000 Compatible Access" -ActiveDirectoryRights ReadProperty -AccessControlType Allow -ObjectTypeName "General-Information" -InheritanceType Descendents -InheritedObjectTypeName "User" -WhatIf
                forEach ($prop in $props)
                {
                    It "Compares the $prop property of the two Access Control Entries." {
                        Compare-Object -ReferenceObject $Ace1 -DifferenceObject $Ace2 -Property $prop | Should Be $null
                    }
                }
            }
        }
        Describe "Use the Remove-ADObjectAce function to identify some Access Control Entries for removal and ensure they compare to their equivalents." {
            $mockSchemaObjects = (Get-Content "$PSScriptRoot\schemaObjects.json" -Raw | ConvertFrom-Json)
            $mockAccessRights = (Get-Content -Path "$PSScriptRoot\accessRights.json" -Raw | ConvertFrom-Json)
            $mockPermissions = (Get-Content -Path "$PSScriptRoot\MockPermissions.json" -Raw | ConvertFrom-Json)
            Mock -CommandName Get-ADRootDSE -MockWith { New-Object -TypeName PSObject -Property @{"configurationNamingContext" = "CN=Configuration,DC=contoso,DC=com"; "schemaNamingContext" = "CN=Schema,CN=Configuration,DC=contoso,DC=com"; }}
            Mock -CommandName Get-ADDomain -MockWith { New-Object -TypeName PSObject -Property @{"NetBIOSName" = "CONTOSO"} }
            Mock -CommandName Get-ADObject -ParameterFilter {$LDAPFilter -eq '(schemaIDGUID=*)'} -MockWith { $mockSchemaObjects }
            Mock -CommandName Get-ADObject -ParameterFilter {$LDAPFilter -eq '(objectClass=controlAccessRight)'} -MockWith { $mockAccessRights }
            Mock -CommandName Set-Location -MockWith { }
            Mock -CommandName Pop-Location -MockWith { }
            Mock -CommandName Resolve-ObjectSidToName -MockWith { Return $Sid }
            Mock -CommandName Get-Acl -MockWith {
                $ContosoAcl = $mockPermissions.ContosoDomainGBGroupPermissions
                $permissions = $ContosoAcl | Select-Object -Property @(
                    "ActiveDirectoryRights"
                    "InheritanceType"
                    @{n = "ObjectType"; e = {[System.GUID]$_.ObjectType}}
                    @{n = "InheritedObjectType"; e = {[System.GUID]$_.InheritedObjectType}}
                    "ObjectFlags"
                    "AccessControlType"
                    "IdentityReference"
                    "IsInherited"
                    "InheritanceFlags"
                    "PropagationFlags"
                )
                Return New-Object -TypeName PSObject -Property @{"Access" = $permissions}
            }
            $props = @("AccessControlType", "ActiveDirectoryRights", "DistinguishedName", "IdentityReference", "InheritanceFlags", "InheritanceType", "InheritedObjectType", "InheritedObjectTypeName", "IsInherited", "ObjectFlags", "ObjectType", "ObjectTypeName", "PropagationFlags", "IdentityReferenceDomain", "IdentityReferenceName")
            $Identity = New-Object -TypeName PSObject -Property @{"Name" = "Groups"; "DistinguishedName" = "OU=Groups,OU=GB,DC=contoso,DC=com"}
            Context "Retrieve a specific ACE from the 'OU=Groups,OU=GB,DC=contoso,DC=com' OU and compare it to an equivalent ACE identified by Remove-ADObjectAce (-Whatif)." {
                Mock -CommandName Resolve-NameToObjectSid -ParameterFilter {$IdentityReference -eq "CONTOSO\Joe.Bloggs"} -MockWith { Return (New-Object System.Security.Principal.SecurityIdentifier("S-1-5-21-2295585024-2604479722-1786026388-1112")) }
                Mock -CommandName Get-ADObject -ParameterFilter { $LDAPFilter -eq '(&(schemaIDGUID=*)(Name=Group))' } -MockWith { $mockSchemaObjects | Where-Object {$_.Name -eq 'Group'} } -Verifiable
                Mock -CommandName Get-ADObject -ParameterFilter { $LDAPFilter -eq '(&(objectClass=controlAccessRight)(Name=Group))'} -MockWith { $mockAccessRights | Where-Object {$_.Name -eq 'Group'} } -Verifiable
                Mock -CommandName Get-ADObject -ParameterFilter { $Filter -like "*schemaIDGUID*"} -MockWith { $mockSchemaObjects | Where-Object {$_.schemaIDGUID -eq 'bf967a9c-0de6-11d0-a285-00aa003049e2'} } -Verifiable
                Mock -CommandName Get-ADObject -ParameterFilter { $Filter -like "*rightsGUID*"} -MockWith { $mockAccessRights | Where-Object {$_.rightsGUID -eq 'bf967a9c-0de6-11d0-a285-00aa003049e2'} } -Verifiable
                $Ace1 = Get-ADObjectAcl -Identity $Identity -IdentityReference "CONTOSO\Joe.Bloggs" -ActiveDirectoryRights GenericAll -AccessControlType Allow -InheritedObjectTypeName Group -InheritanceType Descendents
                $Ace2 = Remove-ADObjectAce -Identity $Identity -IdentityReference "CONTOSO\Joe.Bloggs" -ActiveDirectoryRights GenericAll -AccessControlType Allow -InheritedObjectTypeName Group -InheritanceType Descendents -Whatif
                forEach ($prop in $props)
                {
                    It "Compares the $prop property of the two Access Control Entries." {
                        Compare-Object -ReferenceObject $Ace1 -DifferenceObject $Ace2 -Property $prop | Should Be $null
                    }
                }
            }
            Context "Combine use of Get-ADObjectAcl and Remove-ADObjectAce to remove all ACEs for a particular security principal." {
                Mock -CommandName Resolve-NameToObjectSid -ParameterFilter {$IdentityReference -eq "CONTOSO\Joe.Bloggs"} -MockWith { Return (New-Object System.Security.Principal.SecurityIdentifier("S-1-5-21-2295585024-2604479722-1786026388-1112")) }
                Mock -CommandName Get-Location -ParameterFilter {$StackName -eq "cActiveDirectorySecurity"} -MockWith { Return (New-Object -TypeName PSObject -Property @{"Path" = "CONTOSO:"}) }
                Mock -CommandName Get-ADObject -ParameterFilter { $LDAPFilter -eq '(&(schemaIDGUID=*)(Name=Group))' } -MockWith { $mockSchemaObjects | Where-Object {$_.Name -eq 'Group'} } -Verifiable
                Mock -CommandName Get-ADObject -ParameterFilter { $LDAPFilter -eq '(&(objectClass=controlAccessRight)(Name=Group))'} -MockWith { $mockAccessRights | Where-Object {$_.Name -eq 'Group'} } -Verifiable
                Mock -CommandName Get-ADObject -ParameterFilter { $Filter -like "*schemaIDGUID*"} -MockWith { $mockSchemaObjects | Where-Object {$_.schemaIDGUID -eq 'bf967a9c-0de6-11d0-a285-00aa003049e2'} } -Verifiable
                Mock -CommandName Get-ADObject -ParameterFilter { $Filter -like "*rightsGUID*"} -MockWith { $mockAccessRights | Where-Object {$_.rightsGUID -eq 'bf967a9c-0de6-11d0-a285-00aa003049e2'} } -Verifiable
                Mock -CommandName Get-ADObject -MockWith { New-Object -TypeName PSObject -Property @{"Name" = "Groups"; "DistinguishedName" = "OU=Groups,OU=GB,DC=contoso,DC=com" } }
                $Ace1 = Get-ADObjectAcl -Identity $Identity -IdentityReference "CONTOSO\Joe.Bloggs"
                $Ace2 = Get-ADObjectAcl -Identity $Identity -IdentityReference "CONTOSO\Joe.Bloggs" | Remove-ADObjectAce -Whatif
                for ($i = 0; $i -lt $Ace1.count; $i++)
                {
                    forEach ($prop in $props)
                    {
                        It "Compares the $prop property of the two Access Control Entries." {
                            Compare-Object -ReferenceObject $Ace1[$i] -DifferenceObject $Ace2[$i] -Property $prop | Should Be $null
                        }
                    }
                }
            }
        }
    }
}
catch
{
    throw $_
}