CIS-M365-Benchmark.psm1

#Requires -Version 5.1

$Script:ComplianceCheckerPath = Join-Path $PSScriptRoot "CIS-M365-Compliance-Checker.ps1"

$Script:PrerequisiteCheckRun = $false

function Script:Install-PrerequisitesAutomatically {
    $requiredModules = @(
        @{ Name = "Microsoft.Graph"; MinVersion = "2.0.0" }
        @{ Name = "ExchangeOnlineManagement"; MinVersion = $null }
        @{ Name = "Microsoft.Online.SharePoint.PowerShell"; MinVersion = $null }
        @{ Name = "MicrosoftTeams"; MinVersion = $null }
        @{ Name = "MSOnline"; MinVersion = $null }
    )

    $missing = @()
    $needsUpdate = @()
    $needsImport = @()
    $psVersion = $PSVersionTable.PSVersion.Major

    foreach ($module in $requiredModules) {
        $moduleName = $module.Name
        $minVersion = $module.MinVersion
        $installed = Get-Module -ListAvailable -Name $moduleName | Sort-Object Version -Descending | Select-Object -First 1

        if (-not $installed) {
            $missing += $module
        }
        elseif ($minVersion -and $installed.Version -lt [Version]$minVersion) {
            $needsUpdate += $module
        }
        else {
            if ($moduleName -ne "Microsoft.Graph") {
                $loaded = Get-Module -Name $moduleName
                if (-not $loaded) {
                    $needsImport += $moduleName
                }
            }
        }
    }

    if ($needsUpdate.Count -gt 0) {
        Write-Host ""
        Write-Host "================================================================" -ForegroundColor Yellow
        Write-Host " CIS M365 Benchmark - Updating Prerequisites" -ForegroundColor Yellow
        Write-Host "================================================================" -ForegroundColor Yellow
        Write-Host ""
        Write-Host "Updating $($needsUpdate.Count) outdated module(s)..." -ForegroundColor Yellow
        Write-Host ""

        foreach ($module in $needsUpdate) {
            Write-Host " Updating $($module.Name)..." -NoNewline -ForegroundColor White

            if ($module.Name -eq "Microsoft.Graph") {
                try {
                    Write-Host ""
                    Write-Host " Removing outdated Microsoft.Graph versions..." -ForegroundColor Gray
                    Get-InstalledModule -Name "Microsoft.Graph" -AllVersions -ErrorAction SilentlyContinue |
                        Where-Object { $_.Version -lt [Version]"2.0.0" } |
                        ForEach-Object {
                            Write-Host " Uninstalling v$($_.Version)..." -NoNewline -ForegroundColor Gray
                            Uninstall-Module -Name "Microsoft.Graph" -RequiredVersion $_.Version -Force -ErrorAction SilentlyContinue
                            Write-Host " [OK]" -ForegroundColor Green
                        }

                    Write-Host " Installing latest Microsoft.Graph..." -NoNewline -ForegroundColor Gray
                    Install-Module -Name "Microsoft.Graph" -Scope CurrentUser -Force -AllowClobber -ErrorAction Stop -WarningAction SilentlyContinue | Out-Null
                    Write-Host " [OK]" -ForegroundColor Green
                    Write-Host " Microsoft.Graph update complete" -ForegroundColor Green
                    $needsImport += $module.Name
                }
                catch {
                    Write-Host " [FAILED]: $_" -ForegroundColor Red
                }
            }
            else {
                try {
                    Update-Module -Name $module.Name -Force -ErrorAction Stop -WarningAction SilentlyContinue | Out-Null
                    Write-Host " [OK]" -ForegroundColor Green
                    $needsImport += $module.Name
                }
                catch {
                    try {
                        Install-Module -Name $module.Name -Scope CurrentUser -Force -AllowClobber -ErrorAction Stop -WarningAction SilentlyContinue | Out-Null
                        Write-Host " [REINSTALLED]" -ForegroundColor Green
                        $needsImport += $module.Name
                    }
                    catch {
                        Write-Host " [FAILED]" -ForegroundColor Yellow
                    }
                }
            }
        }
        Write-Host ""
    }

    if ($missing.Count -gt 0) {
        Write-Host ""
        Write-Host "================================================================" -ForegroundColor Cyan
        Write-Host " CIS M365 Benchmark - Auto-Installing Prerequisites" -ForegroundColor Cyan
        Write-Host "================================================================" -ForegroundColor Cyan
        Write-Host ""
        Write-Host "Installing $($missing.Count) missing module(s)..." -ForegroundColor Yellow
        Write-Host "PowerShell Version: $psVersion" -ForegroundColor Gray
        Write-Host ""

        foreach ($module in $missing) {
            try {
                Write-Host " Installing $($module.Name)..." -NoNewline -ForegroundColor White
                Install-Module -Name $module.Name -Scope CurrentUser -Force -AllowClobber -ErrorAction Stop -WarningAction SilentlyContinue -Repository PSGallery | Out-Null
                Write-Host " [OK]" -ForegroundColor Green
                $needsImport += $module.Name
            }
            catch {
                Write-Host " [FAILED]: $_" -ForegroundColor Red
            }
        }

        Write-Host ""
        Write-Host "================================================================" -ForegroundColor Cyan
        Write-Host " Installation complete!" -ForegroundColor Cyan
        Write-Host "================================================================" -ForegroundColor Cyan
        Write-Host ""
    }

    if ($needsImport.Count -gt 0) {
        Write-Host "Loading prerequisite modules..." -ForegroundColor Cyan

        foreach ($moduleName in $needsImport) {
            try {
                Write-Host " Loading $moduleName..." -NoNewline -ForegroundColor Gray
                if ($psVersion -ge 7) {
                    Import-Module -Name $moduleName -ErrorAction Stop -WarningAction SilentlyContinue -DisableNameChecking -SkipEditionCheck -Force | Out-Null
                }
                else {
                    Import-Module -Name $moduleName -ErrorAction Stop -WarningAction SilentlyContinue -DisableNameChecking -Force | Out-Null
                }
                Write-Host " [OK]" -ForegroundColor Green
            }
            catch {
                Write-Host " [WARNING]" -ForegroundColor Yellow
            }
        }
        Write-Host ""
    }
}

function Script:Fix-MicrosoftGraphVersion {
    try {
        $graphModule = Get-Module -ListAvailable -Name Microsoft.Graph | Sort-Object Version -Descending | Select-Object -First 1

        if ($graphModule -and $graphModule.Version -lt [Version]"2.0.0") {
            Write-Host ""
            Write-Host "================================================================" -ForegroundColor Yellow
            Write-Host " Updating Microsoft.Graph to fix authentication issues" -ForegroundColor Yellow
            Write-Host "================================================================" -ForegroundColor Yellow
            Write-Host ""
            Write-Host "Current version: $($graphModule.Version)" -ForegroundColor Gray
            Write-Host "Required version: 2.0.0 or higher" -ForegroundColor Gray
            Write-Host ""
            Write-Host "Updating Microsoft.Graph module..." -ForegroundColor Yellow

            try {
                Get-InstalledModule -Name Microsoft.Graph -AllVersions -ErrorAction SilentlyContinue |
                    Where-Object { $_.Version -lt [Version]"2.0.0" } |
                    ForEach-Object {
                        Write-Host " Removing old version $($_.Version)..." -NoNewline -ForegroundColor Gray
                        Uninstall-Module -Name Microsoft.Graph -RequiredVersion $_.Version -Force -ErrorAction SilentlyContinue
                        Write-Host " [OK]" -ForegroundColor Green
                    }

                Write-Host " Installing latest Microsoft.Graph..." -NoNewline -ForegroundColor White
                Install-Module -Name Microsoft.Graph -Scope CurrentUser -Force -AllowClobber -ErrorAction Stop -WarningAction SilentlyContinue
                Write-Host " [OK]" -ForegroundColor Green

                Write-Host ""
                Write-Host "================================================================" -ForegroundColor Green
                Write-Host " Microsoft.Graph updated successfully!" -ForegroundColor Green
                Write-Host "================================================================" -ForegroundColor Green
                Write-Host ""
                Write-Host "Please restart PowerShell and run Invoke-CISBenchmark again." -ForegroundColor Yellow
                Write-Host ""
                return $true
            }
            catch {
                Write-Host " [FAILED]" -ForegroundColor Red
                Write-Host ""
                Write-Host "Unable to auto-update Microsoft.Graph. Please update manually:" -ForegroundColor Yellow
                Write-Host " Install-Module -Name Microsoft.Graph -Force -AllowClobber" -ForegroundColor White
                Write-Host ""
                return $false
            }
        }
    }
    catch {
    }
    return $false
}

if (-not $Script:PrerequisiteCheckRun) {
    Script:Install-PrerequisitesAutomatically
    $Script:PrerequisiteCheckRun = $true
}

function Connect-CISBenchmark {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$false)]
        [string[]]$Scopes = @(
            "Organization.Read.All",
            "Directory.Read.All",
            "Policy.Read.All",
            "UserAuthenticationMethod.Read.All",
            "RoleManagement.Read.All",
            "User.Read.All",
            "Group.Read.All",
            "Application.Read.All"
        ),

        [switch]$UseDeviceCode
    )

    Write-Host "`nConnecting to Microsoft Graph" -ForegroundColor Yellow

    try {
        if (-not (Get-Module -Name Microsoft.Graph.Authentication)) {
            Import-Module Microsoft.Graph.Authentication -ErrorAction Stop
        }

        # Check if already connected
        $currentContext = Get-MgContext -ErrorAction SilentlyContinue
        if ($currentContext -and $currentContext.TenantId) {
            Write-Host "Already connected to Microsoft Graph" -ForegroundColor Green
            Write-Host " Tenant ID: $($currentContext.TenantId)" -ForegroundColor White
            Write-Host " Account: $($currentContext.Account)" -ForegroundColor White

            # Check if we have the required scopes
            $missingScopes = $Scopes | Where-Object { $_ -notin $currentContext.Scopes }
            if ($missingScopes) {
                Write-Host "`nMissing required scopes. Reconnecting..." -ForegroundColor Yellow
            } else {
                Write-Host "`nYou can now run: Invoke-CISBenchmark`n" -ForegroundColor Yellow
                return $currentContext
            }
        }

        $params = @{
            Scopes        = $Scopes
            NoWelcome     = $true
            ContextScope  = 'Process'
        }

        # PowerShell 7 specific handling
        if ($PSVersionTable.PSVersion.Major -ge 7) {
            Write-Host "PowerShell 7+ detected" -ForegroundColor Cyan

            # PowerShell 7 has known issues with certain authentication methods
            # We'll use a workaround by setting environment variables
            Write-Host "Configuring authentication for PowerShell 7 compatibility..." -ForegroundColor Yellow

            # Set environment variable to disable problematic authentication methods
            $env:AZURE_IDENTITY_DISABLE_MULTITENANTAUTH = "true"

            # Try different authentication methods in order
            $authMethods = @(
                @{
                    Name = "Interactive Browser"
                    Params = @{
                        Scopes = $Scopes
                        NoWelcome = $true
                    }
                },
                @{
                    Name = "Web Account Manager"
                    Params = @{
                        Scopes = $Scopes
                        NoWelcome = $true
                        ClientId = '14d82eec-204b-4c2f-b7e8-296a70dab67e'
                    }
                },
                @{
                    Name = "Minimal Parameters"
                    Params = @{
                        Scopes = $Scopes
                    }
                }
            )

            $connected = $false
            foreach ($method in $authMethods) {
                if ($connected) { break }

                try {
                    Write-Host "Trying $($method.Name) authentication..." -ForegroundColor Yellow
                    $methodParams = $method.Params
                    Connect-MgGraph @methodParams -ErrorAction Stop
                    $connected = $true
                }
                catch {
                    Write-Verbose "Failed with $($method.Name): $_"
                    # Continue to next method
                }
            }

            if (-not $connected) {
                # If all methods fail, provide specific guidance
                Write-Host "`nâš  PowerShell 7 Authentication Issue Detected" -ForegroundColor Yellow
                Write-Host "This is a known compatibility issue with Microsoft.Graph module in PowerShell 7." -ForegroundColor Yellow
                Write-Host "`nWorkarounds:" -ForegroundColor Cyan
                Write-Host "1. Use PowerShell 5.1 instead (recommended):" -ForegroundColor White
                Write-Host " powershell.exe -Command `"Import-Module CIS-M365-Benchmark; Connect-CISBenchmark`"" -ForegroundColor Gray
                Write-Host "`n2. Or manually authenticate first:" -ForegroundColor White
                Write-Host " Connect-MgGraph -Scopes 'Directory.Read.All','Policy.Read.All','User.Read.All'" -ForegroundColor Gray
                Write-Host " Then run: Invoke-CISBenchmark" -ForegroundColor Gray

                throw "Unable to authenticate with Microsoft Graph in PowerShell 7. See workarounds above."
            }
        }
        else {
            # PowerShell 5.1 - use standard authentication
            if ($UseDeviceCode) {
                $params['UseDeviceCode'] = $true
            }
            Connect-MgGraph @params
        }

        $context = Get-MgContext

        if ($context -and $context.TenantId) {
            Write-Host "`nSuccessfully connected to Microsoft Graph!" -ForegroundColor Green
            Write-Host " Tenant ID: $($context.TenantId)" -ForegroundColor White
            Write-Host " Account: $($context.Account)" -ForegroundColor White
            Write-Host "`nYou can now run: Invoke-CISBenchmark`n" -ForegroundColor Yellow
            return $context
        }
        else {
            throw "Connection established but unable to retrieve context"
        }
    }
    catch [Management.Automation.CommandNotFoundException] {
        Write-Host "`nThe Microsoft Graph PowerShell module is not installed." -ForegroundColor Red
        Write-Host "Please install it using: Install-Module Microsoft.Graph -Scope CurrentUser`n" -ForegroundColor Yellow
        throw
    }
    catch {
        Write-Host "`nFailed to connect to Microsoft Graph" -ForegroundColor Red
        Write-Host "Error: $_`n" -ForegroundColor Red
        throw
    }
}

function Invoke-CISBenchmark {
    [CmdletBinding()]
    [OutputType([PSCustomObject])]
    param(
        [Parameter(Mandatory=$false, Position=0, HelpMessage="Your M365 tenant domain (e.g., contoso.onmicrosoft.com). If not provided, will be auto-detected.")]
        [string]$TenantDomain,

        [Parameter(Mandatory=$false, Position=1, HelpMessage="SharePoint admin URL (e.g., https://contoso-admin.sharepoint.com). If not provided, will be auto-detected.")]
        [ValidatePattern('^https://.*-admin\.sharepoint\.com/?$')]
        [string]$SharePointAdminUrl,

        [Parameter(Mandatory=$false)]
        [ValidateScript({Test-Path -Path $_ -PathType Container -IsValid})]
        [string]$OutputPath = ".",

        [Parameter(Mandatory=$false)]
        [ValidateSet('L1','L2','All')]
        [string]$ProfileLevel = 'All',

        [Parameter(Mandatory=$false)]
        [ValidateSet('Both','HTML','CSV')]
        [string]$Format = 'Both',

        [Parameter(Mandatory=$false)]
        [string[]]$Sections
    )

    begin {
        Write-Verbose "Starting CIS Microsoft 365 Foundations Benchmark v5.0.0 Compliance Check"

        if ([string]::IsNullOrEmpty($TenantDomain) -or [string]::IsNullOrEmpty($SharePointAdminUrl)) {
            Write-Host ""
            Write-Host "================================================================" -ForegroundColor Cyan
            Write-Host " Auto-Detecting Microsoft 365 Tenant Information" -ForegroundColor Cyan
            Write-Host "================================================================" -ForegroundColor Cyan
            Write-Host ""

            try {
                Write-Host "Checking Microsoft Graph connection..." -ForegroundColor Gray
                $graphContext = Get-MgContext -ErrorAction SilentlyContinue

                if (-not $graphContext) {
                    Write-Host ""
                    Write-Host "Not authenticated to Microsoft Graph." -ForegroundColor Yellow
                    Write-Host ""
                    Write-Host "Please run: Connect-CISBenchmark" -ForegroundColor Cyan
                    Write-Host ""
                    Write-Host "Attempting automatic authentication..." -ForegroundColor Yellow

                    try {
                        Connect-MgGraph -Scopes "Organization.Read.All","Directory.Read.All" -ErrorAction Stop | Out-Null
                        $graphContext = Get-MgContext
                        Write-Host "Authentication successful!" -ForegroundColor Green
                    }
                    catch {
                        Write-Host ""
                        Write-Host "================================================================" -ForegroundColor Red
                        Write-Host " Authentication Failed" -ForegroundColor Red
                        Write-Host "================================================================" -ForegroundColor Red
                        Write-Host ""
                        Write-Host "Please authenticate first by running:" -ForegroundColor Yellow
                        Write-Host " Connect-CISBenchmark" -ForegroundColor Cyan
                        Write-Host ""
                        Write-Host "Or provide tenant information manually:" -ForegroundColor Yellow
                        Write-Host " Invoke-CISBenchmark -TenantDomain 'tenant.onmicrosoft.com' -SharePointAdminUrl 'https://tenant-admin.sharepoint.com'" -ForegroundColor Cyan
                        Write-Host ""
                        throw "Authentication required. Run Connect-CISBenchmark first or provide tenant parameters manually."
                    }
                }
                else {
                    Write-Host "Using existing Microsoft Graph connection" -ForegroundColor Green
                    Write-Host " Account: $($graphContext.Account)" -ForegroundColor Gray
                }

                Write-Host "Retrieving tenant information..." -ForegroundColor Gray
                $orgDetails = Get-MgOrganization -ErrorAction Stop | Select-Object -First 1

                if ([string]::IsNullOrEmpty($TenantDomain)) {
                    $verifiedDomains = $orgDetails.VerifiedDomains | Where-Object { $_.Name -like "*.onmicrosoft.com" }
                    if ($verifiedDomains) {
                        $TenantDomain = @($verifiedDomains)[0].Name
                    } else {
                        $TenantDomain = @($orgDetails.VerifiedDomains)[0].Name
                    }
                    Write-Host " Detected Tenant Domain: $TenantDomain" -ForegroundColor Green
                }

                if ([string]::IsNullOrEmpty($SharePointAdminUrl)) {
                    $tenantName = $TenantDomain.Split('.')[0]
                    $SharePointAdminUrl = "https://$tenantName-admin.sharepoint.com"
                    Write-Host " Detected SharePoint Admin URL: $SharePointAdminUrl" -ForegroundColor Green
                }

                Write-Host ""
            }
            catch {
                Write-Host ""
                Write-Host "Failed to auto-detect tenant information: $_" -ForegroundColor Red
                Write-Host ""
                Write-Host "Please authenticate first:" -ForegroundColor Yellow
                Write-Host " Connect-CISBenchmark" -ForegroundColor Cyan
                Write-Host ""
                Write-Host "Or provide the tenant information manually:" -ForegroundColor Yellow
                Write-Host " Invoke-CISBenchmark -TenantDomain 'tenant.onmicrosoft.com' -SharePointAdminUrl 'https://tenant-admin.sharepoint.com'" -ForegroundColor Cyan
                Write-Host ""
                throw "Auto-detection failed. Run Connect-CISBenchmark or provide tenant parameters manually."
            }
        }

        Write-Verbose "Tenant: $TenantDomain"
        Write-Verbose "SharePoint URL: $SharePointAdminUrl"
        Write-Verbose "Profile Level: $ProfileLevel"

        $graphFixed = Script:Fix-MicrosoftGraphVersion
        if ($graphFixed) {
            Write-Host "Microsoft.Graph has been updated. Please restart PowerShell and run this command again." -ForegroundColor Yellow
            return
        }

        if (-not (Test-Path -Path $OutputPath)) {
            Write-Verbose "Creating output directory: $OutputPath"
            New-Item -Path $OutputPath -ItemType Directory -Force | Out-Null
        }
    }

    process {
        try {
            $cleanSharePointUrl = $SharePointAdminUrl.TrimEnd('/')

            $scriptParams = @{
                TenantDomain = $TenantDomain
                SharePointAdminUrl = $cleanSharePointUrl
                OutputPath = $OutputPath
                ProfileLevel = $ProfileLevel
            }

            Write-Verbose "Executing CIS compliance checker script..."

            & $Script:ComplianceCheckerPath @scriptParams

            Write-Verbose "Generating summary report..."

            $htmlReport = Get-ChildItem -Path $OutputPath -Filter "CIS-M365-Compliance-Report_*.html" -ErrorAction SilentlyContinue |
                Sort-Object LastWriteTime -Descending |
                Select-Object -First 1

            $csvReport = Get-ChildItem -Path $OutputPath -Filter "CIS-M365-Compliance-Report_*.csv" -ErrorAction SilentlyContinue |
                Sort-Object LastWriteTime -Descending |
                Select-Object -First 1

            if ($csvReport) {
                $reportData = Import-Csv -Path $csvReport.FullName
                $passed = ($reportData | Where-Object { $_.Result -eq 'Pass' }).Count
                $failed = ($reportData | Where-Object { $_.Result -eq 'Fail' }).Count
                $manual = ($reportData | Where-Object { $_.Result -eq 'Manual' }).Count
                $errors = ($reportData | Where-Object { $_.Result -eq 'Error' }).Count
                $total = $reportData.Count

                $complianceRate = if ($total -gt 0 -and ($total - $manual) -gt 0) {
                    [math]::Round(($passed / ($total - $manual)) * 100, 2)
                } else {
                    0
                }

                $summary = [PSCustomObject]@{
                    TenantDomain = $TenantDomain
                    ProfileLevel = $ProfileLevel
                    TotalControls = $total
                    Passed = $passed
                    Failed = $failed
                    Manual = $manual
                    Errors = $errors
                    ComplianceRate = $complianceRate
                    Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
                    HtmlReport = if ($htmlReport) { $htmlReport.FullName } else { $null }
                    CsvReport = if ($csvReport) { $csvReport.FullName } else { $null }
                }

                return $summary
            }
            else {
                Write-Warning "No CSV report found. Check output path: $OutputPath"
            }

        }
        catch {
            Write-Error "Failed to execute CIS benchmark: $_"
            throw
        }
    }

    end {
        Write-Verbose "CIS benchmark check completed"
    }
}

function Get-CISBenchmarkControl {
    [CmdletBinding(DefaultParameterSetName='All')]
    [OutputType([PSCustomObject[]])]
    param(
        [Parameter(ParameterSetName='ByControl', Position=0)]
        [string[]]$ControlNumber,

        [Parameter(ParameterSetName='BySection')]
        [ValidateSet('1','2','3','4','5','6','7','8','9')]
        [string]$Section,

        [Parameter()]
        [ValidateSet('L1','L2','All')]
        [string]$ProfileLevel = 'All'
    )

    $controls = @(
        [PSCustomObject]@{ControlNumber="1.1.1"; Title="Ensure Administrative accounts are cloud-only"; Section="1"; ProfileLevel="L1"; Automated=$true}
        [PSCustomObject]@{ControlNumber="1.1.2"; Title="Ensure two emergency access accounts have been defined"; Section="1"; ProfileLevel="L1"; Automated=$false}
        [PSCustomObject]@{ControlNumber="1.1.3"; Title="Ensure that between two and four global admins are designated"; Section="1"; ProfileLevel="L1"; Automated=$true}
    )

    $results = $controls

    if ($PSCmdlet.ParameterSetName -eq 'ByControl' -and $ControlNumber) {
        $results = $results | Where-Object { $_.ControlNumber -in $ControlNumber }
    }

    if ($PSCmdlet.ParameterSetName -eq 'BySection' -and $Section) {
        $results = $results | Where-Object { $_.Section -eq $Section }
    }

    if ($ProfileLevel -ne 'All') {
        $results = $results | Where-Object { $_.ProfileLevel -eq $ProfileLevel }
    }

    return $results
}

function Test-CISBenchmarkPrerequisites {
    [CmdletBinding()]
    [OutputType([PSCustomObject[]])]
    param()

    $requiredModules = @(
        @{Name="Microsoft.Graph"; Required=$true}
        @{Name="ExchangeOnlineManagement"; Required=$true}
        @{Name="Microsoft.Online.SharePoint.PowerShell"; Required=$true}
        @{Name="MicrosoftTeams"; Required=$true}
        @{Name="MSOnline"; Required=$false}
    )

    $results = @()

    foreach ($module in $requiredModules) {
        $installed = Get-Module -ListAvailable -Name $module.Name | Select-Object -First 1

        $results += [PSCustomObject]@{
            Module = $module.Name
            Installed = $null -ne $installed
            Version = if ($installed) { $installed.Version.ToString() } else { "Not Installed" }
            Required = $module.Required
            Status = if ($null -ne $installed) { "[OK] Installed" } elseif ($module.Required) { "[!] Required - Not Installed" } else { "[*] Optional - Not Installed" }
        }
    }

    return $results
}

function Get-CISBenchmarkInfo {
    [CmdletBinding()]
    param()

    $module = Get-Module -Name CIS-M365-Benchmark

    Write-Host ""
    Write-Host "================================================================" -ForegroundColor Cyan
    Write-Host " CIS Microsoft 365 Foundations Benchmark v5.0.0" -ForegroundColor Cyan
    Write-Host " PowerShell Module v$($module.Version)" -ForegroundColor Cyan
    Write-Host "================================================================" -ForegroundColor Cyan
    Write-Host ""
    Write-Host "Available Commands:" -ForegroundColor Yellow
    Write-Host " - Connect-CISBenchmark - Authenticate to Microsoft 365" -ForegroundColor White
    Write-Host " - Invoke-CISBenchmark - Run compliance checks" -ForegroundColor White
    Write-Host " - Get-CISBenchmarkControl - Get control information" -ForegroundColor White
    Write-Host " - Test-CISBenchmarkPrerequisites - Check required modules" -ForegroundColor White
    Write-Host " - Get-CISBenchmarkInfo - Display this information" -ForegroundColor White
    Write-Host ""
    Write-Host "Quick Start:" -ForegroundColor Yellow
    Write-Host " 1. Authenticate:" -ForegroundColor Gray
    Write-Host " Connect-CISBenchmark" -ForegroundColor Green
    Write-Host ""
    Write-Host " 2. Run compliance checks:" -ForegroundColor Gray
    Write-Host " Invoke-CISBenchmark" -ForegroundColor Green
    Write-Host ""
    Write-Host " Or manually specify tenant:" -ForegroundColor Gray
    Write-Host " Invoke-CISBenchmark -TenantDomain 'contoso.onmicrosoft.com' \" -ForegroundColor Green
    Write-Host " -SharePointAdminUrl 'https://contoso-admin.sharepoint.com'" -ForegroundColor Green
    Write-Host ""
    Write-Host "Help:" -ForegroundColor Yellow
    Write-Host " Get-Help Invoke-CISBenchmark -Full" -ForegroundColor White
    Write-Host ""
    Write-Host "Links:" -ForegroundColor Yellow
    Write-Host " - Documentation: https://github.com/mohammedsiddiqui6872/CIS-M365-Benchmark" -ForegroundColor White
    Write-Host " - CIS Benchmark: https://www.cisecurity.org/benchmark/microsoft_365" -ForegroundColor White
    Write-Host " - PowerShell Gallery: https://www.powershellgallery.com/packages/CIS-M365-Benchmark" -ForegroundColor White
    Write-Host ""
    Write-Host "================================================================" -ForegroundColor Cyan
    Write-Host ""
}

Export-ModuleMember -Function @(
    'Connect-CISBenchmark',
    'Invoke-CISBenchmark',
    'Get-CISBenchmarkControl',
    'Test-CISBenchmarkPrerequisites',
    'Get-CISBenchmarkInfo'
)