MantraBlockSenders.psm1

#
# MantraBlockSenders PowerShell Module
# Simplified onboarding for Mantra Threats Block multi-tenant deployment
#
# Copyright (c) 2026 Mantra. All rights reserved.
#

function Connect-MantraBlockSenders {
    <#
    .SYNOPSIS
        Configure Mantra Threats Block on your Microsoft 365 tenant

    .DESCRIPTION
        Automatically configures the Exchange Online permissions required
        for Mantra Threats Block (sender/domain blocking).

        This function:
        1. Installs ExchangeOnlineManagement module if needed
        2. Connects to Exchange Online (interactive login)
        3. Creates a Service Principal for Mantra application
        4. Creates a limited RBAC role group (blocking only)
        5. Assigns the Service Principal to the role group

    .PARAMETER AppId
        Mantra application (client) ID
        This is the same for all clients and is provided on the authorization page

    .PARAMETER ObjectId
        Service Principal Object ID from your tenant
        Retrieved automatically during the authorization process

    .PARAMETER Organization
        Your tenant identifier. Accepts either:
        - Domain name: "client.onmicrosoft.com" (primary verified domain)
        - Tenant ID: "12345678-1234-1234-1234-123456789012" (tenant GUID)

    .EXAMPLE
        Connect-MantraBlockSenders `
            -AppId "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" `
            -ObjectId "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb" `
            -Organization "client.onmicrosoft.com"

        Configures Mantra Threats Block using domain name.

    .EXAMPLE
        Connect-MantraBlockSenders `
            -AppId "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" `
            -ObjectId "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb" `
            -Organization "12345678-1234-1234-1234-123456789012"

        Configures Mantra Threats Block using tenant ID (GUID).

    .NOTES
        Requirements:
        - Global Administrator or Exchange Administrator role
        - Internet connection for initial setup
        - PowerShell 5.1 or later

        Estimated execution time: 30-60 seconds

    .LINK
        https://app.mantra.ms/docs
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true, Position = 0)]
        [ValidatePattern('^[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}$')]
        [string]$AppId,

        [Parameter(Mandatory = $true, Position = 1)]
        [ValidatePattern('^[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}$')]
        [string]$ObjectId,

        [Parameter(Mandatory = $true, Position = 2)]
        [ValidatePattern('^([0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}|.*\.onmicrosoft\.com)$')]
        [string]$Organization
    )

    $ErrorActionPreference = "Stop"

    Write-Host ""
    Write-Host "============================================" -ForegroundColor Cyan
    Write-Host " Mantra Threats Block - Configuration " -ForegroundColor Cyan
    Write-Host "============================================" -ForegroundColor Cyan
    Write-Host ""
    Write-Host "Organization : $Organization" -ForegroundColor Gray
    Write-Host "App ID : $AppId" -ForegroundColor Gray
    Write-Host "Object ID : $ObjectId" -ForegroundColor Gray
    Write-Host ""

    $AppName = "MantraBlockSendersBlock"
    $RoleName = "Mantra Blocage"

    try {
        # [1/5] Check/Install Exchange module
        Write-Host "[1/5] Checking Exchange module..." -ForegroundColor Yellow
        $module = Get-Module -ListAvailable -Name ExchangeOnlineManagement
        if (-not $module) {
            Write-Host " Installing ExchangeOnlineManagement..." -ForegroundColor Gray
            Install-Module -Name ExchangeOnlineManagement -Force -AllowClobber -Scope CurrentUser -ErrorAction Stop
            Write-Host " Installed ✅" -ForegroundColor Green
        } else {
            Write-Host " OK (v$($module.Version)) ✅" -ForegroundColor Green
        }

        Import-Module ExchangeOnlineManagement -ErrorAction Stop

        # [2/5] Connect to Exchange Online
        Write-Host "[2/5] Connecting to Exchange Online..." -ForegroundColor Yellow
        Write-Host " (Login window will open)" -ForegroundColor Gray
        Write-Host ""
        Connect-ExchangeOnline -ShowBanner:$false -ErrorAction Stop
        Write-Host " Connected ✅" -ForegroundColor Green

        # [3/5] Create Service Principal
        Write-Host "[3/5] Configuring Service Principal..." -ForegroundColor Yellow
        $existingSP = Get-ServicePrincipal -Identity $ObjectId -ErrorAction SilentlyContinue
        if ($existingSP) {
            Write-Host " Already exists ✅" -ForegroundColor Green
        } else {
            New-ServicePrincipal -AppId $AppId -ServiceId $ObjectId -DisplayName $AppName -ErrorAction Stop | Out-Null
            Write-Host " Created ✅" -ForegroundColor Green
        }

        # [4/5] Create Role Group
        Write-Host "[4/5] Configuring role group..." -ForegroundColor Yellow
        $existingRole = Get-RoleGroup -Identity $RoleName -ErrorAction SilentlyContinue
        if ($existingRole) {
            Write-Host " Already exists ✅" -ForegroundColor Green
        } else {
            New-RoleGroup -Name $RoleName `
                -Roles @("Tenant AllowBlockList Manager") `
                -Description "Mantra Threats Block - Sender/domain blocking only" `
                -ErrorAction Stop | Out-Null
            Write-Host " Created ✅" -ForegroundColor Green
        }

        # [5/5] Assign role
        Write-Host "[5/5] Assigning permissions..." -ForegroundColor Yellow
        try {
            Add-RoleGroupMember -Identity $RoleName -Member $ObjectId -ErrorAction Stop
            Write-Host " Assigned ✅" -ForegroundColor Green
        } catch {
            if ($_.Exception.Message -like "*already a member*") {
                Write-Host " Already member ✅" -ForegroundColor Green
            } else {
                throw
            }
        }

        # Disconnect
        Disconnect-ExchangeOnline -Confirm:$false -ErrorAction SilentlyContinue

        # Success message
        Write-Host ""
        Write-Host "============================================" -ForegroundColor Green
        Write-Host " CONFIGURATION COMPLETED! " -ForegroundColor Green
        Write-Host "============================================" -ForegroundColor Green
        Write-Host ""
        Write-Host "Mantra Threats Block can now block malicious" -ForegroundColor Cyan
        Write-Host "senders and domains on your tenant." -ForegroundColor Cyan
        Write-Host ""
        Write-Host "You can close this window." -ForegroundColor Gray
        Write-Host ""

    } catch {
        Write-Host ""
        Write-Host "❌ Configuration failed" -ForegroundColor Red
        Write-Host " Error: $($_.Exception.Message)" -ForegroundColor Red
        Write-Host ""
        Write-Host "Troubleshooting:" -ForegroundColor Yellow
        Write-Host " • Verify you have Global Admin or Exchange Admin role" -ForegroundColor Gray
        Write-Host " • Check that all parameters are correct" -ForegroundColor Gray
        Write-Host " • Ensure ExchangeOnlineManagement module can be installed" -ForegroundColor Gray
        Write-Host ""
        Write-Host "Contact support: support@mantra.ms" -ForegroundColor Cyan
        Write-Host ""

        Disconnect-ExchangeOnline -Confirm:$false -ErrorAction SilentlyContinue

        throw
    }
}

function Test-MantraBlockSendersConnection {
    <#
    .SYNOPSIS
        Test Mantra Threats Block configuration

    .DESCRIPTION
        Verifies that Mantra Threats Block is correctly configured on your tenant
        by attempting to connect to Exchange Online and checking RBAC permissions.

    .EXAMPLE
        Test-MantraBlockSendersConnection

    .OUTPUTS
        System.Boolean
        Returns $true if configuration is valid, $false otherwise.
    #>

    [CmdletBinding()]
    param()

    Write-Host ""
    Write-Host "Testing Mantra Threats Block configuration..." -ForegroundColor Cyan
    Write-Host ""

    try {
        Connect-ExchangeOnline -ShowBanner:$false -ErrorAction Stop
        Write-Host " ✓ Exchange Online connection: OK" -ForegroundColor Green

        $testList = Get-TenantAllowBlockListItems -ListType Sender -ErrorAction Stop | Select-Object -First 1
        Write-Host " ✓ Blocking permissions: OK" -ForegroundColor Green

        Disconnect-ExchangeOnline -Confirm:$false -ErrorAction SilentlyContinue

        Write-Host ""
        Write-Host "✅ Configuration is valid!" -ForegroundColor Green
        Write-Host ""

        return $true

    } catch {
        Write-Host " ✗ Configuration check failed" -ForegroundColor Red
        Write-Host ""
        Write-Host "❌ Configuration incomplete" -ForegroundColor Red
        Write-Host " Error: $($_.Exception.Message)" -ForegroundColor Red
        Write-Host ""

        Disconnect-ExchangeOnline -Confirm:$false -ErrorAction SilentlyContinue

        return $false
    }
}

function Get-MantraBlockSendersHelp {
    <#
    .SYNOPSIS
        Display help information

    .DESCRIPTION
        Shows available commands and support links
    #>


    Write-Host ""
    Write-Host "╔═══════════════════════════════════════════════════════════════╗" -ForegroundColor Cyan
    Write-Host "║ Mantra Threats Block - Help ║" -ForegroundColor Cyan
    Write-Host "╚═══════════════════════════════════════════════════════════════╝" -ForegroundColor Cyan
    Write-Host ""
    Write-Host "Available commands:" -ForegroundColor White
    Write-Host ""
    Write-Host " Connect-MantraBlockSenders" -ForegroundColor Yellow
    Write-Host " -AppId <guid> -ObjectId <guid> -Organization <domain>" -ForegroundColor Gray
    Write-Host ""
    Write-Host " Test-MantraBlockSendersConnection" -ForegroundColor Yellow
    Write-Host " Verify configuration" -ForegroundColor Gray
    Write-Host ""
    Write-Host "Documentation: https://app.mantra.ms/docs" -ForegroundColor Cyan
    Write-Host "Support: support@mantra.ms" -ForegroundColor Cyan
    Write-Host ""
}

# Aliases
New-Alias -Name "Setup-MantraBlockSenders" -Value "Connect-MantraBlockSenders" -ErrorAction SilentlyContinue
New-Alias -Name "Test-MantraBlockSenders" -Value "Test-MantraBlockSendersConnection" -ErrorAction SilentlyContinue

# Exports
Export-ModuleMember -Function Connect-MantraBlockSenders, Test-MantraBlockSendersConnection, Get-MantraBlockSendersHelp
Export-ModuleMember -Alias Setup-MantraBlockSenders, Test-MantraBlockSenders