private/review/admincenter/users/Invoke-ReviewEntraAdminAccountCloudOnly.ps1

function Invoke-ReviewEntraAdminAccountCloudOnly
{
    <#
    .SYNOPSIS
        Ensure administrative accounts are separate and cloud-only in Entra ID.
    .DESCRIPTION
        Returns review object.
    .EXAMPLE
        Invoke-ReviewEntraAdminAccountCloudOnly;
    #>


    [cmdletbinding()]
    param
    (
    )

    BEGIN
    {
        # Write progress.
        Write-Progress -Activity $MyInvocation.MyCommand -Status 'Running' -CurrentOperation $MyInvocation.MyCommand.Name -PercentComplete -1 -SecondsRemaining -1;

        # Object array to store the admin accounts.
        $adminAccounts = New-Object System.Collections.ArrayList;

        # Object array to store the admin accounts that should be reviewed.
        $reviewAdminAccounts = New-Object System.Collections.ArrayList;

        # Allowed licenses for admin accounts.
        $allowedServicePlanName = @(
            'AAD_PREMIUM',
            'AAD_PREMIUM_P2'
        );

        # Get all users with admin roles.
        $usersWithAdminRole = Get-EntraIdUserAdminRole;
    }
    PROCESS
    {
        # Foreach user with admin role.
        foreach ($userWithAdminRole in $usersWithAdminRole)
        {
            # Get user from admin account.
            $adminAccount = $adminAccounts | Where-Object { $_.UserPrincipalName -eq $userWithAdminRole.UserPrincipalName };

            # If the users is not already in the list.
            if ($null -eq $adminAccount)
            {
                # Add to object array.
                $adminAccounts += [PSCustomObject]@{
                    Id                = $userWithAdminRole.Id;
                    UserPrincipalName = $userWithAdminRole.UserPrincipalName;
                    DisplayName       = $userWithAdminRole.DisplayName;
                    CloudOnly         = $userWithAdminRole.CloudOnly;
                    AccountEnabled    = $userWithAdminRole.AccountEnabled;
                    Roles             = @(
                        [PSCustomObject]@{
                            RoleId          = $userWithAdminRole.RoleId;
                            RoleDisplayName = $userWithAdminRole.RoleDisplayName;
                        }
                    );
                };
            }
            # If the user is already in the list.
            else
            {
                # Add to user roles.
                $adminAccounts[$adminAccounts.IndexOf($userWithAdminRole)].Roles += [PSCustomObject]@{
                    RoleId          = $userWithAdminRole.RoleId;
                    RoleDisplayName = $userWithAdminRole.RoleDisplayName;
                };
            }
        }

        # Get all licenses for the admin accounts.
        $userLicenses = Get-EntraIdUserLicense -UserPrincipalName ($adminAccounts.UserPrincipalName);

        # Foreach admin account.
        foreach ($adminAccount in $adminAccounts)
        {
            # Boolean to determine recommendations.
            [bool]$cloudOnly = $true;
            [bool]$licenseValid = $true;

            # If the admin account is not cloud only.
            if ($false -eq $adminAccount.CloudOnly)
            {
                # Set cloud only to false.
                $cloudOnly = $false;
            }

            # Foreach license.
            foreach ($userLicense in $userLicenses)
            {
                # If the user license is not for the admin account.
                if ($adminAccount.UserPrincipalName -ne $userLicense.UserPrincipalName)
                {
                    # Continue to next license.
                    continue;
                }

                # If license service is not enabled.
                if ($userLicense.ServicePlanProvisioningStatus -ne 'Success')
                {
                    # Continue to next license.
                    continue;
                }

                # If license is not on allowed list.
                if ($allowedServicePlanName -notcontains $userLicense.ServicePlanName)
                {
                    # Set license to be invalid.
                    $licenseValid = $false;
                }
            }

            # If the recommendations is not fulfilled and account is enabled.
            if (($false -eq $cloudOnly -or $false -eq $licenseValid) -and
                $adminAccount.AccountEnabled -eq $true)
            {
                # Get all roles for the admin account.
                $roles = ($adminAccount.Roles | Select-Object -ExpandProperty RoleDisplayName -Unique) -join ', ';

                # Get all licenses.
                $licenses = ($userLicenses | Where-Object { $_.UserPrincipalName -eq $adminAccount.UserPrincipalName } | Select-Object -ExpandProperty LicenseName -Unique) -join ', ';

                # Write to log.
                Write-CustomLog -Category 'Entra' -Subcategory 'User' -Message ("Admin account '{0}' is not cloud-only or has invalid licenses" -f $adminAccount.UserPrincipalName) -Level Verbose;

                # Add to object array.
                $reviewAdminAccounts += [PSCustomObject]@{
                    Id                = $adminAccount.Id;
                    UserPrincipalName = $adminAccount.UserPrincipalName;
                    DisplayName       = $adminAccount.DisplayName;
                    CloudOnly         = $adminAccount.CloudOnly;
                    Roles             = $roles;
                    Licenses          = $licenses;
                    AccountEnabled    = $adminAccount.AccountEnabled;
                };
            }
        }
    }
    END
    {
        # Bool for review flag.
        [bool]$reviewFlag = $false;

        # If review flag should be set.
        if ($reviewAdminAccounts.Count -gt 0)
        {
            # Should be reviewed.
            $reviewFlag = $true;
        }

        # Create new review object to return.
        [Review]$review = [Review]::new();

        # Add to object.
        $review.Id = '289efa41-e17f-43e7-a6b8-9ff8868d3511';
        $review.Category = 'Microsoft 365 Admin Center';
        $review.Subcategory = 'Users';
        $review.Title = 'Ensure Administrative accounts are separate and cloud-only';
        $review.Data = $reviewAdminAccounts;
        $review.Review = $reviewFlag;

        # Print result.
        $review.PrintResult();

        # Return object.
        return $review;
    }
}