Bulk provisioning Office 365 licenses and services script

By | February 7, 2016

Working with a client to ease the transition of Office 2010 (MSI) using KMS licensing to Office 2013/2016 (Click-to-Run) with subscription licensing to use the new Skype for Business client. It quickly became apparent that enabling thousands of globally dispersed users for a certain feature set via Office 365 Admin Portal wasn’t going to work. PowerShell always to the rescue!

Script Download: BulkO365LicenseServices.ps1 https://gallery.technet.microsoft.com/Bulk-provisioning-Office-f64747d5

First, we have some prerequisites to connect to Microsoft Online and Active Directory(AD) via PowerShell:

The following is a breakdown of the core logic in my script, minus the reporting, error handling and loops…

Load required modules and test connectivity.

Import-Module ActiveDirectory
Import-Module MSOnline
Connect-MsolService #Sign in using account with appropriate licensing permissions
Get-MsolDomain

bls1

Figure out the Account SKUs associated to the Office 365 Tenant, available licenses and the specific services to choose from. The most complete list I’ve found for the breakdown of services for each SKU can be found at: http://blogs.technet.com/b/treycarlee/archive/2013/11/01/list-of-powershell-licensing-sku-s-for-office-365.asp (don’t forget to check the comments).

Get-MsolAccountSku | %{$_.accountskuID;Write "Remaining Licenses:";($x =$_.ActiveUnits - $_.ConsumedUnits);$_.ServiceStatus|ft -hide}

bls2

It’s counterintuitive, but when applying specific Office 365 services from PowerShell you apply a list of services you want disabled vs. the services you want.

The easiest way to figure out which services to disable or enable is to configure a single account using the Office 365 Admin Portal and review via PowerShell.

Get-MsolUser -UserPrincipalName test2@lamontagnesolutions.com |%{ $_.licenses.servicestatus}

bls4
bls3

Make sure your licensing script takes into account when Microsoft changes or adds a new service. You’ll need a way of comparing enable services to available services, giving a disabled list.

#AccountSKU to use
$AccountSKUID = "LaMSol:ENTERPRISEPACK"
#list of Enabled services
$SubLicense = ("RMS_S_ENTERPRISE","OFFICESUBSCRIPTION","MCOSTANDARD","SHAREPOINTWAC","SHAREPOINTENTERPRISE")
get-msolaccountsku | Where {$_.accountSkuID -eq $AccountSKUID } | Select -expand "ServiceStatus" | select -expand "ServicePlan" | select ServiceName | Where {$SubLicense -notcontains $_.ServiceName}

bls5

Grab users and additional attributes based on AD OU.

#User OU's distinguishedName attribute
$OUsearch = "DC=lamontagnesolutions,DC=com" 
get-aduser -Filter * -Searchbase $OUsearch -properties mail,Country| ?{ $_.Enabled -eq 'True'} |Ft name,userprincipalname,mail,country

bls6

Search for Microsoft Online user using either the mail or userprincipalname attribute as the cloud User Principal Name (UPN).

#Using user's Active Directory Mail attribute to find MSOl User. 
$upn = (get-aduser Test2 -Properties mail).mail
#To use UserPrincipalName instead to find MSOl User:
#$upn = (get-aduser Test2).UserPrincipalName
Get-MsolUser -UserPrincipalName $upn

bls7

Is the user licensed for the specific Account SKU?

Get-MsolUser -UserPrincipalName test2@lamontagnesolutions.com | ?{ $_.isLicensed -eq "TRUE" } | ?{ ($_.Licenses | ?{ $_.AccountSkuId -eq $AccountSKUID}).Length -gt 0}

<bls8

If the user is already licensed for the specific Account SKU, confirm/enable required services. Don’t disable additional enabled services as these might be pilot users.

$disabledServices = (Get-MsolUser -UserPrincipalName test2@lamontagnesolutions.com).Licenses.servicestatus | where {$_.ProvisioningStatus -eq "Disabled"} | select -expand serviceplan | Select ServiceName
$disabledServices = $disabledServices | where {$SubLicense -notcontains $_.ServiceName}
$disabled = @()
foreach  ($item in $disabledServices.servicename) {$disabled += $item}
$LicenseOptions = New-MsolLicenseOptions -AccountSkuId $AccountSKUID -DisabledPlans $disabled
set-msoluserlicense  -userprincipalname test2@lamontagnesolutions.com -licenseoptions $LicenseOptions

bls9
bls10
bls11

If the user isn’t licensed, set location based on AD country attribute or manual country code then add Account SKU with required services.

$Location = (get-aduser Test1 -Properties country).country
#$Location = "CA"
$disabledServices = get-msolaccountsku | Where {$_.accountSkuID -eq $AccountSKUID } | Select -expand "ServiceStatus" | select -expand "ServicePlan" | select ServiceName | Where {$SubLicense -notcontains $_.ServiceName}
$disabled = @()
foreach  ($item in $disabledServices.servicename) {$disabled += $item}
$LicenseOptions = New-MsolLicenseOptions -AccountSkuId $AccountSKUID -DisabledPlans $Disabled
Set-MsolUser -UserPrincipalName test1@lamontagnesolutions.com –UsageLocation $Location
Set-MsolUserLicense -User test1@lamontagnesolutions.com -AddLicenses $AccountSKUID -LicenseOptions $LicenseOptions

bls12
bls13
bls14

Download: BulkO365LicenseServices.ps1 https://gallery.technet.microsoft.com/Bulk-provisioning-Office-f64747d5

4 thoughts on “Bulk provisioning Office 365 licenses and services script

  1. Pingback: Bulk provisioning Office 365 licenses and Services script | Real-Time UC | JC's Blog-O-Gibberish

    1. mlamontagne Post author

      I’ll always side with free 🙂 Interesting product though.

      Reply
  2. David

    This script is very helpful. Is there a way to deactivate a particular license without affecting the rest?

    Reply

Leave a Comment