Wednesday, November 11, 2015

Modifying License Assignments in Office 365

Automating the assigning of licenses in Office 365 isn't terribly hard - unless you have multiple subscription packages... and multiple Active Directory domains... and you're in hybrid mode with Exchange on-premises... and you only want to assign certain features of those subscriptions, and then only to certain users. This is one of those stories. Our company originally purchased an E3 subscription for our corporate "knowledge workers", and a K2 subscription for our store associates. Last year we added a K1 subscription for our seasonal associates, and I recently learned that the K2 subscription had been discontinued, so we had to increase our K1 subscription to cover all store associates. Due to this, I recently had to convert a large group of users from the discontinued K2 subscription to the K1 subscription, and only enable them for the sharepoint online feature.

After connecting to our tenant...

connect-msolservice

... I configured the K1 license options to exclude the Exchange Online feature...

$StoreK1License = New-MsolLicenseOptions -AccountSkuId "tenantname:DESKLESSPACK" -DisabledPlans EXCHANGE_S_DESKLESS

Next, I ran a query against our on-premises Active Directory, to build a list of user accounts that needed to be changed...

$k2users = get-aduser -filter {(extensionattribute11 -notlike "Regular") -and ((company -eq "Company1") -or (company -eq "Company2"))} -Server mydomain.local -SearchBase "ou=store employees,ou=stores,dc=mydomain,dc=local"

Now that we have our array of user accounts, we'll use the UserPrincipalname property to locate those users in Office 365. First, we check to see if they do indeed have the K2 license assigned...

foreach ($k2user in $k2users) {
if ((Get-MsolUser -UserPrincipalName $k2user.userprincipalname).licenses[0].accountsku.skupartnumber -eq "DESKLESSWOFFPACK") {

If the call to Get-MsolUser returns true, we proceed to (1) make sure the Usage Location is set to "US", then (2) we remove the K2 license and assign the new K1 license, with our previously defined options, all in one fell swoop...

write-host "Converting $($k2user.userprincipalname) from K2 to K1..." -foreground yellow
set-msoluser -userprincipalname $k2user.userprincipalname -usagelocation "US"
Set-MsolUserLicense -UserPrincipalName $k2user.userprincipalname -RemoveLicenses "tenantname:DESKLESSWOFFPACK" -AddLicenses "tenantname:DESKLESSPACK" -LicenseOptions $StoreK1License

And if the call to Get-MsolUser returned false, the user did not have a K2 license, so we just send a message to the screen and move on to the next user in the list.

} else {
write-host "K2 not found for $($k2user.userprincipalname)..." -foreground darkgray
}
}

I try not to use write-host commands in my regular scripting, but this was a quick and dirty task, and if I had left them out, since the Set-MsolUser and Set-MsolUserLicense commands produce no output (unless they encounter an error), write-host is in there just to provide evidence of progress. My AD query returned over 25000 user accounts, and it takes quite a while to process all those license changes, so the write-host output was good enough for the task at hand.

Here's the whole script:

connect-msolservice

$StoreK1License = New-MsolLicenseOptions -AccountSkuId "tenantname:DESKLESSPACK" -DisabledPlans EXCHANGE_S_DESKLESS

$k2users = get-aduser -filter {(extensionattribute11 -notlike "Regular") -and ((company -eq "Company1") -or (company -eq "Company2"))} -Server mydomain.local -SearchBase "ou=store employees,dc=mydomain,dc=local"


foreach ($k2user in $k2users) {
if ((Get-MsolUser -UserPrincipalName $k2user.userprincipalname).licenses[0].accountsku.skupartnumber -eq "DESKLESSWOFFPACK") {
write-host "Converting $($k2user.userprincipalname) from K2 to K1..." -foreground yellow
set-msoluser -userprincipalname $k2user.userprincipalname -usagelocation "US"
Set-MsolUserLicense -UserPrincipalName $k2user.userprincipalname -RemoveLicenses "tenantname:DESKLESSWOFFPACK" -AddLicenses "tenantname:DESKLESSPACK" -LicenseOptions $StoreK1License
} else {
write-host "K2 not found for $($k2user.userprincipalname)..." -foreground darkgray
}
}