Tests/AD-SecurityAudit.Tests.ps1
|
BeforeAll { $modulePath = Split-Path -Parent $PSScriptRoot Import-Module "$modulePath\AD-SecurityAudit.psd1" -Force } Describe 'AD-SecurityAudit Module' { Context 'Module Loading' { It 'Should import without errors' { { Import-Module "$PSScriptRoot\..\AD-SecurityAudit.psd1" -Force } | Should -Not -Throw } It 'Should export exactly 5 public functions' { $commands = Get-Command -Module AD-SecurityAudit $commands.Count | Should -Be 5 } It 'Should export all expected functions' { $expected = @('Invoke-ADSecurityAudit', 'Get-StaleADObjects', 'Get-LocalAdminAudit', 'Get-OrphanedSIDs', 'Get-PrivilegedGroupReport') foreach ($func in $expected) { Get-Command -Module AD-SecurityAudit -Name $func | Should -Not -BeNullOrEmpty } } It 'Should not export private functions' { { Get-Command -Module AD-SecurityAudit -Name _New-SecurityAuditHtml -ErrorAction Stop } | Should -Throw } } Context 'Get-StaleADObjects Parameter Validation' { It 'Should accept DaysInactive parameter' { (Get-Command Get-StaleADObjects).Parameters.ContainsKey('DaysInactive') | Should -BeTrue } It 'Should validate ObjectType to User, Computer, or Both' { $validateSet = (Get-Command Get-StaleADObjects).Parameters['ObjectType'].Attributes | Where-Object { $_ -is [System.Management.Automation.ValidateSetAttribute] } $validateSet.ValidValues | Should -Contain 'User' $validateSet.ValidValues | Should -Contain 'Computer' $validateSet.ValidValues | Should -Contain 'Both' } It 'Should accept ExcludeOU parameter' { (Get-Command Get-StaleADObjects).Parameters.ContainsKey('ExcludeOU') | Should -BeTrue } } Context 'Get-StaleADObjects Mocked Execution' { BeforeAll { Mock -ModuleName AD-SecurityAudit Import-Module { } Mock -ModuleName AD-SecurityAudit Get-ADUser { @( [PSCustomObject]@{ Name = 'Williams, Mark' SAMAccountName = 'mwilliams' LastLogonDate = (Get-Date).AddDays(-200) PasswordLastSet = (Get-Date).AddDays(-300) WhenCreated = (Get-Date).AddYears(-3) Enabled = $true Department = 'Sales' DistinguishedName = 'CN=Mark Williams,OU=Users,OU=Sales,DC=contoso,DC=com' }, [PSCustomObject]@{ Name = 'Smith, Jane' SAMAccountName = 'jsmith' LastLogonDate = (Get-Date).AddDays(-5) PasswordLastSet = (Get-Date).AddDays(-30) WhenCreated = (Get-Date).AddYears(-2) Enabled = $true Department = 'IT' DistinguishedName = 'CN=Jane Smith,OU=Users,OU=IT,DC=contoso,DC=com' } ) } Mock -ModuleName AD-SecurityAudit Get-ADComputer { @() } } It 'Should only return accounts beyond the inactive threshold' { $results = Get-StaleADObjects -DaysInactive 90 -ObjectType User $results | Where-Object { $_.SAMAccountName -eq 'mwilliams' } | Should -Not -BeNullOrEmpty $results | Where-Object { $_.SAMAccountName -eq 'jsmith' } | Should -BeNullOrEmpty } It 'Should calculate DaysStale correctly' { $results = Get-StaleADObjects -DaysInactive 90 -ObjectType User $stale = $results | Where-Object { $_.SAMAccountName -eq 'mwilliams' } $stale.DaysStale | Should -BeGreaterThan 190 } } Context 'Get-OrphanedSIDs Parameter Validation' { It 'Should have mandatory Path parameter' { (Get-Command Get-OrphanedSIDs).Parameters['Path'].Attributes.Mandatory | Should -Contain $true } It 'Should support -WhatIf' { (Get-Command Get-OrphanedSIDs).Parameters.ContainsKey('WhatIf') | Should -BeTrue } It 'Should accept pipeline input for Path' { (Get-Command Get-OrphanedSIDs).Parameters['Path'].Attributes.ValueFromPipeline | Should -Contain $true } It 'Should have RemoveOrphans switch' { (Get-Command Get-OrphanedSIDs).Parameters['RemoveOrphans'].SwitchParameter | Should -BeTrue } } Context 'Get-LocalAdminAudit Parameter Validation' { It 'Should accept ComputerName parameter' { (Get-Command Get-LocalAdminAudit).Parameters.ContainsKey('ComputerName') | Should -BeTrue } It 'Should accept ExpectedAdmins parameter' { (Get-Command Get-LocalAdminAudit).Parameters.ContainsKey('ExpectedAdmins') | Should -BeTrue } } Context 'Get-PrivilegedGroupReport Parameter Validation' { It 'Should accept AdditionalGroups parameter' { (Get-Command Get-PrivilegedGroupReport).Parameters.ContainsKey('AdditionalGroups') | Should -BeTrue } It 'Should accept DaysInactive parameter' { (Get-Command Get-PrivilegedGroupReport).Parameters.ContainsKey('DaysInactive') | Should -BeTrue } } Context 'Get-PrivilegedGroupReport Mocked Execution' { BeforeAll { Mock -ModuleName AD-SecurityAudit Import-Module { } Mock -ModuleName AD-SecurityAudit Get-ADGroupMember { @( [PSCustomObject]@{ Name = 'admin.lr' SAMAccountName = 'admin.lr' objectClass = 'user' }, [PSCustomObject]@{ Name = 'svc.backup' SAMAccountName = 'svc.backup' objectClass = 'user' } ) } Mock -ModuleName AD-SecurityAudit Get-ADUser { param($Identity) $isServiceAccount = $Identity -like 'svc.*' [PSCustomObject]@{ SAMAccountName = $Identity Enabled = $true LastLogonDate = (Get-Date).AddDays(-5) PasswordNeverExpires = $isServiceAccount WhenCreated = (Get-Date).AddYears(-1) } } Mock -ModuleName AD-SecurityAudit Get-ADGroup { [PSCustomObject]@{ Name = 'Domain Admins' DistinguishedName = 'CN=Domain Admins,CN=Users,DC=contoso,DC=com' } } } It 'Should flag service accounts with PasswordNeverExpires' { $results = Get-PrivilegedGroupReport $results | Should -Not -BeNullOrEmpty } } Context 'HTML Report Generation' { It 'Should generate valid HTML from the private function' { $html = & (Get-Module AD-SecurityAudit) { _New-SecurityAuditHtml -StaleUsers @() -StaleComputers @() -PrivilegedGroups @() -LocalAdmins @() -Domain 'contoso.com' -DaysThreshold 90 } $html | Should -Match '<!DOCTYPE html>' $html | Should -Match 'Active Directory Security Audit' } } } |