Public/Install-ByttEmail.ps1

<#
.DESCRIPTION
    Installs ByttEmail in the signed in tenant

.SYNOPSIS
    Installs ByttEmail in the signed in tenant

.EXAMPLE
    Install-ByttEmail
#>

function Install-ByttEmail {
    [CmdletBinding()]

    Param()

    Begin {
        
    }

    Process {
        $fortytwoUniverseAppId = "2808f963-7bba-4e66-9eee-82d0b178f408"
        if (![string]::IsNullOrEmpty($ENV:FORTYTWO_UNIVERSE_APP_ID)) {
            $fortytwoUniverseAppId = $ENV:FORTYTWO_UNIVERSE_APP_ID
        }

        $byttEmailAppId = "34ee8edb-d2ff-4ee9-bac3-73b53303e00f"
        if (![string]::IsNullOrEmpty($ENV:BYTT_EMAIL_APP_ID)) {
            $byttEmailAppId = $ENV:BYTT_EMAIL_APP_ID
        }

        Write-Host "Signing in to Microsoft Graph..."
        Connect-MgGraph -Scope Application.ReadWrite.All, AppRoleAssignment.ReadWrite.All, Group.ReadWrite.All, AdministrativeUnit.ReadWrite.All, DelegatedPermissionGrant.ReadWrite.All -NoWelcome
        
        Write-Host "Checking Enterprise Application for Fortytwo Universe..." -NoNewline
        $fortytwoUniverseApp = Get-MgServicePrincipal -Filter "appId eq '$fortytwoUniverseAppId'" -ErrorAction SilentlyContinue

        if (!$fortytwoUniverseApp) {
            Write-Host -ForegroundColor Green " [Creating...]"
            $fortytwoUniverseApp = New-MgServicePrincipal -AppId $fortytwoUniverseAppId
            Write-Host -ForegroundColor Green "Enterprise Application for Fortytwo Universe created with objectid $($fortytwoUniverseApp.Id)."
        }
        else {
            Write-Host -ForegroundColor Green " [OK]"
        }

        Write-Host "Checking Enterprise Application for Bytt.Email..." -NoNewline
        $byttEmailApp = Get-MgServicePrincipal -Filter "appId eq '$byttEmailAppId'" -ErrorAction SilentlyContinue
        if (!$byttEmailApp) {
            Write-Host -ForegroundColor Green " [Creating...]"
            $byttEmailApp = New-MgServicePrincipal -AppId $byttEmailAppId
            Write-Host -ForegroundColor Green "Enterprise Application for Bytt.Email created with objectid $($byttEmailApp.Id)."
        }
        else {
            Write-Host -ForegroundColor Green " [OK]"
        }

        Write-Host "Adding admin consent for user.read to Fortytwo Universe..." -NoNewline
        $microsoftGraph = Get-MgServicePrincipal -Filter "appId eq '00000003-0000-0000-c000-000000000000'" -ErrorAction SilentlyContinue
        $graphPermissions = Get-MgOauth2PermissionGrant -Filter "consentType eq 'AllPrincipals' and resourceId eq '$($microsoftGraph.Id)'" -All
        $match = $graphPermissions | Where-Object { $_.ClientId -eq $fortytwoUniverseApp.Id -and $_.Scope -eq "user.read" }

        if (!$match) {
            $grant = New-MgOauth2PermissionGrant -ClientId $fortytwoUniverseApp.Id -ConsentType "AllPrincipals" -PrincipalId $null -ResourceId $microsoftGraph.Id -Scope "user.read"
            Write-Host -ForegroundColor Green " [Added]"
        }
        else {
            Write-Host -ForegroundColor Green " [OK]"
        }

        Write-Host "Adding admin consent for user.read to Bytt.Email..." -NoNewline 
        $microsoftGraph = Get-MgServicePrincipal -Filter "appId eq '00000003-0000-0000-c000-000000000000'" -ErrorAction SilentlyContinue
        $graphPermissions = Get-MgOauth2PermissionGrant -Filter "consentType eq 'AllPrincipals' and resourceId eq '$($microsoftGraph.Id)'" -All
        $match = $graphPermissions | Where-Object { $_.ClientId -eq $byttEmailApp.Id -and $_.Scope -eq "user.read" }

        if (!$match) {
            $grant = New-MgOauth2PermissionGrant -ClientId $byttEmailApp.Id -ConsentType "AllPrincipals" -PrincipalId $null -ResourceId $microsoftGraph.Id -Scope "user.read"
            Write-Host -ForegroundColor Green " [Added]"
        }
        else {
            Write-Host -ForegroundColor Green " [OK]"
        }

        Write-Host "Granting user.read.all application permission to Bytt.Email..." -NoNewline
        $appRoleAssignments = Get-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $byttEmailApp.Id -All
        $match = $appRoleAssignments | Where-Object { $_.AppRoleId -eq "df021288-bdef-4463-88db-98f22de89214" -and $_.PrincipalId -eq $byttEmailApp.Id -and $_.ResourceId -eq $microsoftGraph.Id }
        if (!$match) {
            $appRoleAssignment = New-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $byttEmailApp.Id -PrincipalId $byttEmailApp.Id -ResourceId $microsoftGraph.Id -AppRoleId "df021288-bdef-4463-88db-98f22de89214"
            Write-Host -ForegroundColor Green " [Added]"
        }
        else {
            Write-Host -ForegroundColor Green " [OK]"
        }

        Write-Host "Granting groupmember.read.all application permission to Bytt.Email..." -NoNewline
        $appRoleAssignments = Get-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $byttEmailApp.Id -All
        $match = $appRoleAssignments | Where-Object { $_.AppRoleId -eq "df021288-bdef-4463-88db-98f22de89214" -and $_.PrincipalId -eq $byttEmailApp.Id -and $_.ResourceId -eq $microsoftGraph.Id }
        if (!$match) {
            $appRoleAssignment = New-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $byttEmailApp.Id -PrincipalId $byttEmailApp.Id -ResourceId $microsoftGraph.Id -AppRoleId "62a82d76-70ea-41e2-9197-370581804d09"
            Write-Host -ForegroundColor Green " [Added]"
        }
        else {
            Write-Host -ForegroundColor Green " [OK]"
        }

        Write-Host "Creating pattern groups for all domains..."
        $groups = @()
        $domains = Get-MgDomain -All | Where-Object { $_.IsVerified -eq $true } | Where-Object { $_.Id -notlike "*mail.onmicrosoft.com" }

        foreach ($domain in $domains) {
            $groupName = "Bytt.Email pattern - $($domain.Id)"
            Write-Host " - Processing group for domain $($domain.Id)..." -NoNewline
            $group = Get-MgGroup -Filter "displayName eq '$groupName'" -ErrorAction SilentlyContinue
            if (!$group) {
                $group = New-MgGroup -DisplayName $groupName -MailEnabled:$false -SecurityEnabled:$true -MailNickname "$(new-guid)".Substring(0, 8) -AdditionalProperties @{
                    "extension_34ee8edbd2ff4ee9bac373b53303e00f_patterns" = @(
                        "{firstname1}.{lastname-1}@$domain"
                        "{firstname1}.{firstname2}.{lastname-1}@$domain"
                        "{firstname1}.{lastname-2}.{lastname-1}@$domain"
                        "{firstnamewd1}.{lastnamewd-1}@$domain"
                        "{firstnamewd1}.{firstnamewd2}.{lastnamewd-1}@$domain"
                        "{firstnamewd1}.{lastnamewd-2}.{lastnamewd-1}@$domain"
                        "{firstname1}.{firstname2,1}.{lastname-1}@$domain"
                        "{firstname1}.{lastname-1}2@$domain"
                    )
                }
                Write-Host -ForegroundColor Green " [Created]"
            }
            else {
                Write-Host -ForegroundColor Green " [Already exists]"
            }
            $groups += $group
        }

        Write-Host "Creating administrative unit for Bytt.Email..." -NoNewline
        $adminUnitName = "Bytt.Email2"
        $adminUnit = Get-MgDirectoryAdministrativeUnit -Filter "displayName eq '$adminUnitName'" -ErrorAction SilentlyContinue
        $membershipRule = "user.memberof -any (group.objectId -in ['$($groups.Id -join "','")'])"
        if (!$adminUnit) {
            $params = @{
                displayName                   = $adminUnitName
                description                   = "Used for delegating the Bytt.Email application permissions to read users and groups"
                membershipType                = "Dynamic"
                membershipRule                = $membershipRule
                membershipRuleProcessingState = "On"
                visibility                    = "HiddenMembership"
            }

            $AU = New-MgDirectoryAdministrativeUnit -DisplayName $params.displayName -Description $params.description -MembershipType $params.membershipType -MembershipRule $params.membershipRule -MembershipRuleProcessingState $params.membershipRuleProcessingState -Visibility $params.visibility
            Write-Host -ForegroundColor Green " [Created ($($AU.Id))]"
        }
        else {
            Write-Host -ForegroundColor Green " [Already exists]"

            if ($adminUnit.MembershipRule -ne $membershipRule) {
                Write-Warning "The $($adminUnitName) administrative unit exists, but the membership rule is different than expected. However, we will not update it automatically to avoid removing any existing members. Please review and update the membership rule manually if needed. The expected rule is: `n`n$membershipRule`n"
            }
        }

        Write-Host "Granting the Bytt.Email servicePrincipal access to the Bytt.Email administrative unit..." -NoNewline
        $roleTemplateId = "fe930be7-5e62-47db-91af-98c3a49a38b1" # User Administrator
        $role = Get-MgDirectoryRole | Where-Object roleTemplateId -eq $roleTemplateId
        $roleAssignments = Get-MgDirectoryAdministrativeUnitScopedRoleMember -AdministrativeUnitId $adminUnit.Id
        $match = $roleAssignments | Where-Object { $_.RoleId -eq $role.Id -and $_.RoleMemberInfo.Id -eq $byttEmailApp.Id }
        if (!$match) {
            $params = @{
                roleId         = $role.Id
                roleMemberInfo = @{
                    id = $byttEmailApp.Id
                }
            }

            New-MgDirectoryAdministrativeUnitScopedRoleMember -AdministrativeUnitId $adminUnit.Id -BodyParameter $params | Out-Null

            Write-Host -ForegroundColor Green " [Added]"
        }
        else {
            Write-Host -ForegroundColor Green " [OK]"
        }
    }
}