diff --git a/source/Private/Assert-ModuleAvailability.ps1 b/source/Private/Assert-ModuleAvailability.ps1 index 807594f..1b6be6c 100644 --- a/source/Private/Assert-ModuleAvailability.ps1 +++ b/source/Private/Assert-ModuleAvailability.ps1 @@ -20,6 +20,16 @@ function Assert-ModuleAvailability { else { Write-Verbose "$ModuleName module is already at required version or newer." } + if ($ModuleName -eq "Microsoft.Graph") { + Write-Verbose "Preloading Microsoft.Graph assembly to prevent type-loading issues..." + try { + # Run a harmless cmdlet to preload the assembly + Get-MgGroup -Top 1 -ErrorAction SilentlyContinue | Out-Null + } + catch { + Write-Verbose "Could not preload Microsoft.Graph assembly. Error: $_" + } + } if ($SubModules.Count -gt 0) { foreach ($subModule in $SubModules) { Write-Verbose "Importing submodule $ModuleName.$subModule..." diff --git a/source/Private/Get-CISMgOutput.ps1 b/source/Private/Get-CISMgOutput.ps1 index d95ee1d..0c03340 100644 --- a/source/Private/Get-CISMgOutput.ps1 +++ b/source/Private/Get-CISMgOutput.ps1 @@ -38,11 +38,25 @@ function Get-CISMgOutput { Write-Verbose "Get-CISMgOutput: Returning data for Rec: $Rec" switch ($rec) { '1.1.1' { - # V4 needs same info - # 1.1.1 - MicrosoftGraphPlaceholder - # Test-AdministrativeAccountCompliance - $AdminRoleAssignmentsAndUsers = Get-AdminRoleUserAndAssignment - return $AdminRoleAssignmentsAndUsers + if ($script:Version400) { + $DirectoryRoles = Get-MgDirectoryRole + # Get privileged role IDs + $PrivilegedRoles = $DirectoryRoles | Where-Object { + $_.DisplayName -like '*Administrator*' -or $_.DisplayName -eq 'Global Reader' + } + # Get the members of these various roles + $RoleMembers = $PrivilegedRoles | ForEach-Object { Get-MgDirectoryRoleMember -DirectoryRoleId $_.Id } | + Select-Object Id -Unique + $PrivilegedUsers = $RoleMembers | ForEach-Object { + Get-MgUser -UserId $_.Id -Property UserPrincipalName, DisplayName, Id, OnPremisesSyncEnabled + } + return $PrivilegedUsers + } + else { + # Test-AdministrativeAccountCompliance + $AdminRoleAssignmentsAndUsers = Get-AdminRoleUserAndAssignment + return $AdminRoleAssignmentsAndUsers + } } '1.1.4' { # 1.1.4 - MicrosoftGraphPlaceholder diff --git a/source/Private/Invoke-TestFunction.ps1 b/source/Private/Invoke-TestFunction.ps1 index 97f12d9..3b514a3 100644 --- a/source/Private/Invoke-TestFunction.ps1 +++ b/source/Private/Invoke-TestFunction.ps1 @@ -26,7 +26,11 @@ function Invoke-TestFunction { $paramList.ApprovedFederatedDomains = $ApprovedFederatedDomains } # Version-aware logging - Write-Verbose "Running $functionName (Version: $($script:Version400 ? '4.0.0' : '3.0.0'))..." + if ($script:Version400) { + Write-Verbose "Running $functionName (Version: 4.0.0)..." + } else { + Write-Verbose "Running $functionName (Version: 3.0.0)..." + } try { $result = & $functionName @paramList # Assuming each function returns an array of CISAuditResult or a single CISAuditResult diff --git a/source/tests/Test-AdministrativeAccountCompliance4.ps1 b/source/tests/Test-AdministrativeAccountCompliance4.ps1 new file mode 100644 index 0000000..3548a57 --- /dev/null +++ b/source/tests/Test-AdministrativeAccountCompliance4.ps1 @@ -0,0 +1,51 @@ +function Test-AdministrativeAccountCompliance4 { + [CmdletBinding()] + param () + begin { + $RecNum = "1.1.1" + Write-Verbose "Starting Test-AdministrativeAccountCompliance4 for Rec: $RecNum" + } + process { + try { + # Retrieve privileged users with OnPremisesSyncEnabled + Write-Verbose "Retrieving data for privileged users" + $PrivilegedUsers = Get-CISMgOutput -Rec $RecNum + # Filter for users with OnPremisesSyncEnabled + $NonCompliantUsers = $PrivilegedUsers | Where-Object { $_.OnPremisesSyncEnabled -eq $true } + if ($NonCompliantUsers.Count -gt 0) { + Write-Verbose "Non-compliant users found: $($NonCompliantUsers.Count)" + # Generate pipe-delimited failure table as plain text + $Header = "DisplayName|UserPrincipalName|OnPremisesSyncEnabled" + $FailureRows = $NonCompliantUsers | ForEach-Object { + "$($_.DisplayName)|$($_.UserPrincipalName)|$($_.OnPremisesSyncEnabled)" + } + $Details = "$Header`n$($FailureRows -join "`n")" + $Status = "Fail" + $FailureReason = "Non-compliant accounts detected: $($NonCompliantUsers.Count)" + } + else { + Write-Verbose "All accounts are compliant." + $Details = "N/A" + $Status = "Pass" + $FailureReason = "All administrative accounts are cloud-only." + } + # Prepare audit result + $Params = @{ + Rec = $RecNum + Result = ($NonCompliantUsers.Count -eq 0) + Status = $Status + Details = $Details + FailureReason = $FailureReason + } + $AuditResult = Initialize-CISAuditResult @Params + } + catch { + Write-Error "Error during compliance check: $_" + $AuditResult = Get-TestError -LastError $_ -RecNum $RecNum + } + } + end { + # Output result + return $AuditResult + } +}