Friday, June 10, 2016

Office 365 CSP Tenants Subscription Usage summary using DAP access

Scenario:
You are Cloud Solution Provider (CSP) and have a mix of new CSP customers and invited from other Channels like Advisor, EA and etc. Following PowerShell scripts give you an idea what's going on in your CSP world of customer tenants and their subscriptions.

Prerequisites:
Microsoft Online Service Sign-in Assistant for IT Professionals RTW
You need to be connected with Office 365 "Connect-MsolService" cmdlet using Partner account that has delegated access permission (DAP) to Cloud Solution Provider (CSP) customer tenants prior to PowerShell script execution.

Included functions:

Get-MsolSubscriptionUsage
Get-MsolTenantMSSubscription
Get-MsolTenantNoActiveCSP
Get-MsolOffer

Get-MsolDomain -ErrorAction SilentlyContinue | out-null
if(!($?)) {Connect-MsolService}

<#
.Synopsis
   Following function will provide subscription usage summary info for tenant/s
.DESCRIPTION
   Following function  will search for the tenant/s by keyword and provide subscription usage summary for the tenant/s
   Keyword is a search string which is included into tenant displayname or "customer-inc.onmicrosoft.com" tenantname or primary domain name
   Ex. for "Rosemann Technology Inc." you can specify just "Rosemann" or "Rose" or "Rosemann.onmicrosoft.com"
.EXAMPLE
   Get-MsolSubscriptionUsage -Name Rose
   Will search for the subscriptions of the tenant or tenants which contains "Rose" string in their name
   ex. "Rose" matches "Rosemann Inc." or "Rosemann.onmicrosoft.com" or "Rose Inc.", etc.
.EXAMPLE
   Get-MsolSubscriptionUsage -Name Rosemann.onmicrosoft.com
   Will search for the subscriptions of the single customer with "Rosemann.onmicrosoft.com" tenant name
.EXAMPLE
   Get-MsolSubscriptionUsage -Name sill.com
   Will search for the subscriptions of the single customer with "sill.com" primary domain name
.EXAMPLE
   Get-MsolSubscriptionUsage
   Will search for all available tenants
.EXAMPLE
   Get-MsolSubscriptionUsage > Report.txt
   Will search for all available tenants and save results into Report.txt
#>
function Get-MsolSubscriptionUsage
{
    [CmdletBinding()]
    Param
    (
        [Parameter()]
        [string]$Name="*"
    )

Write-Verbose "Searching for the tenant/s that contains string $Name"

$Customer = Get-MsolCustomer -Name $Name

Write-Verbose "Found company: $($Customer.Name) - $($Customer.DefaultDomainName)"

if ($Customer) { $Customer | ForEach-Object {
    [System.Guid]$TenantID = $_.TenantId
    
    $Subscription = Get-MsolSubscription -TenantId $TenantID  -ErrorAction SilentlyContinue

    Show-MsolSubscription -Subscription $Subscription -TenantID $TenantID -Customer $_
    }} else {Write-Warning "Customer not found!"}
}

<#
.Synopsis
   This function will search for customers by primary domain name or by "onmicrosoft.com" name or by DisplayName
.DESCRIPTION
   This function will search for customers by primary domain name or by "onmicrosoft.com" name or by DisplayName
.EXAMPLE
   Get-MsolCustomer -Name domain.net
.EXAMPLE
   Get-MsolCustomer -Name tenantname.onmicrosoft.com
.EXAMPLE
   Get-MsolCustomer -Name CustomerName
#>
function Get-MsolCustomer
{
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory=$true,
                   ValueFromPipelineByPropertyName=$true)]
        [string]$Name
    )
if ($Name -match ".*[.].*") {Get-MsolPartnerContract -SearchKey DefaultDomainName -DomainName $Name}
else {Get-MsolPartnerContract -All | ? {$_.Name -like "*$Name*"}}

}

<#
.Synopsis
   This function will search for MS Subscriptions
.DESCRIPTION
   This function will search for all tenants which contain at least one MS subscription (deployment opportunity of moving to CSP subscription)
.EXAMPLE
   Get-MsolTenantMSSubscription
#>
function Get-MsolTenantMSSubscription
{
    [CmdletBinding()]
    Param()

    $CustomerList=@()

    $Customer = Get-MsolPartnerContract -All

    $Customer | foreach {
    Write-Verbose "Looking into tenant $($_.DefaultDomainName)"

    $Subscription = Get-MsolSubscription -TenantId $_.TenantID  -ErrorAction SilentlyContinue | `
    ? {!($_.OwnerObjectId) -and ($_.Status -eq "Enabled" -or $_.Status -eq "Warning") -and $_.NextLifecycleDate}

    if ($Subscription) {
            Show-MsolSubscription -Subscription $Subscription -TenantID $_.TenantID -Customer $_
            $CustomerList+=$_.Name
            }
        }

    Write-Warning "Subscriptions provisioned by MS are detected in $($CustomerList.Count) customer tenants"
    $CustomerList
}

<#
.Synopsis
   This internal function will print subscription summary information for the particular tenant on screen
#>
function Show-MsolSubscription
{
    [CmdletBinding()]
    Param
    (
        [Parameter()]
        $Subscription,
        [Parameter(Mandatory=$true)]
        $TenantID,
        [Parameter(Mandatory=$true)]
        $Customer
    )
    
    $Customer | ft Name,TenantId,DefaultDomainName

    $Subscription | select `
    @{n="Created";e={$_.Datecreated.ToShortDateString()}}, `
    @{n="Expires";e={$_.NextLifecycleDate.ToShortDateString()}}, `
    @{n="SubscriptionId";e={$_.ObjectId}}, `
    @{n="ProvisionedBy";e={if (!$_.OwnerObjectId) {"Microsoft"} elseif `
    ($_.OwnerObjectId -eq "e63464b7-2b94-4841-8033-5b7f66d196d7") {"CSP"} `
    else {$_.OwnerObjectId}}}, `
    @{n="SKU";e={Get-MsolOffer -SkuPartNumber $_.SkuPartNumber}},TotalLicenses,Status | ft -AutoSize

    Write-Verbose "Resolving $($_.SkuPartNumber)"

    Get-MsolAccountSku -TenantId $TenantID -ErrorAction SilentlyContinue | select `
    @{n="SKU";e={Get-MsolOffer -SkuPartNumber $_.SkuPartNumber}}, `
    ActiveUnits,ConsumedUnits,SubscriptionIds | ft -AutoSize

    Write-Output "============================================================================================================"
}

<#
.Synopsis
   This function will show tenants with no active CSP subscriptions (no CSP benefit usage at all or just invited customers)
.EXAMPLE
   Get-MsolTenantNoActiveCSP
#>
function Get-MsolTenantNoActiveCSP
{
    [CmdletBinding()]
    Param()

    $CustomerList=@()

    $Customer = Get-MsolPartnerContract -All

    $Customer | foreach {

    Write-Verbose "Looking into tenant $($_.DefaultDomainName)"

    $Subscription = Get-MsolSubscription -TenantId $_.TenantID  -ErrorAction SilentlyContinue | `
    ? {$_.OwnerObjectId -and ($_.Status -eq "Enabled" -or $_.Status -eq "Warning")}
    if (!$Subscription) {
            Get-MsolSubscriptionUsage -Name $_.Name
            $CustomerList+=$_.Name
            }
        }

    Write-Warning "$($CustomerList.Count) CSP tenants have no active CSP subscriptions"

    $CustomerList
}

<#
.Synopsis
   This function will convert original Office SKU PartNumber name into friendly name
.EXAMPLE
   Get-MsolOffer -SkuPartNumber MCOIMP
  
   Gives you "SfB Online (Plan 1)"
#>
function Get-MsolOffer
{
    [CmdletBinding()]
    [Alias()]
    Param
    (
        # Param1 help description
        [Parameter(Mandatory=$true,
                   ValueFromPipelineByPropertyName=$true,
                   Position=0)]
        $SkuPartNumber
    )
    switch ($SkuPartNumber) {

    "AAD_BASIC" {"Azure Active Directory Basic"}
    "AAD_PREMIUM" {"Azure Active Directory Premium"}
    "RIGHTSMANAGEMENT" {"Azure Rights Management Premium"}
    "LOCKBOX" {"Customer Lockbox"}
    "EXCHANGE_ANALYTICS" {"Delve Analytics"}
    "EMS" {"Enterprise Mobility Suite"}
    "EXCHANGESTANDARD" {"Exchange Online (Plan 1)"}
    "EXCHANGEENTERPRISE" {"Exchange Online (Plan 2)"}
    "ATP_ENTERPRISE" {"Exchange Online ATP"}
    "EXCHANGEARCHIVE_ADDON" {"EOA for Exchange Online"}
    "EXCHANGEARCHIVE" {"EOA for Exchange Server"}
    "EXCHANGEDESKLESS" {"Exchange Online Kiosk"}
    "EOP_ENTERPRISE" {"Exchange Online Protection"}
    "INTUNE_A" {"Intune"}
    "INTUNE_STORAGE" {"Intune Extra Storage"}
    "ADALLOM_STANDALONE" {"Cloud App Security"}
    "EQUIVIO_ANALYTICS" {"O365 Advanced eDiscovery"}
    "O365_BUSINESS" {"O365 Business"}
    "O365_BUSINESS_ESSENTIALS" {"O365 Business Essentials"}
    "O365_BUSINESS_PREMIUM" {"O365 Business Premium"}
    "STANDARDWOFFPACK" {"O365 Enterprise E2 (Nonprofit E1)"}
    "STANDARDPACK" {"O365 Enterprise E1"}
    "ENTERPRISEPACK" {"O365 Enterprise E3"}
    "ENTERPRISEWITHSCAL" {"O365 Enterprise E4"}
    "ENTERPRISEPREMIUM" {"O365 Enterprise E5"}
    "ENTERPRISEPREMIUM_NOPSTNCONF" {"O365 Enterprise E5 w/o PSTN Conf"}
    "DESKLESSPACK" {"O365 Enterprise K1"}
    "SHAREPOINTSTORAGE" {"O365 Extra File Storage"}
    "WACONEDRIVESTANDARD" {"OneDrive for Business (Plan 1)"}
    "WACONEDRIVEENTERPRISE" {"OneDrive for Business (Plan 2)"}
    "POWER_BI_STANDARD" {"Power BI (free)"}
    "POWER_BI_PRO" {"Power BI (Pro)"}
    "OFFICESUBSCRIPTION" {"O365 ProPlus"}
    "PROJECTESSENTIALS" {"Project Lite"}
    "PROJECTONLINE_PLAN_1" {"Project Online"}
    "PROJECTCLIENT" {"Project Pro for O365"}
    "SHAREPOINTSTANDARD" {"SharePoint Online (Plan 1)"}
    "SHAREPOINTENTERPRISE" {"SharePoint Online (Plan 2)"}
    "MCOEV" {"SfB Cloud PBX"}
    "MCOIMP" {"SfB Online (Plan 1)"}
    "MCOSTANDARD" {"SfB Online (Plan 2)"}
    "MCOMEETADV" {"SfB PSTN Conferencing"}
    "MCOPLUSCAL" {"SfB Plus CAL"}
    "MCOPSTN1" {"SfB PSTN Dom. Calling"}
    "MCOPSTN2" {"SfB PSTN Dom. and Int. Calling"}
    "VISIOCLIENT" {"Visio Pro for O365"}
    "CRMIUR" {"Dynamics CRM Online Pro IUR"}
    "YAMMER_ENTERPRISE_STANDALONE" {"Yammer Enterprise"}
    "LITEPACK" {"O365 Small Business"}
    "LITEPACK_P2" {"O365 Small Business Premium"}
    "CRMPLAN1" {"Dynamics CRM Online Essential"}
    "CRMPLAN2" {"Dynamics CRM Online Basic"}
    "CRMSTANDARD" {"Dynamics CRM Online Pro"}
    }
}

Reference:
Manage Office 365 tenants with Windows PowerShell for Delegated Access Permissions (DAP) partners