This tutorial is about assigning Microsoft Office 365 Licenses through a Powershell Scipt in a Runbook in Azure Automation.
If you are managing an Office 365 tenant with Microsoft Office 365 E5, E5 or Azure AD Premium (P1) you are in the lucky situation licenses can be based on groups. But if you are using another product (eg. the Micrsoft Office 365 Business Suites) you only can assign license directly to users. https://docs.microsoft.com/en-us/azure/active-directory/users-groups-roles/licensing-group-advanced
See here the difference between a tenant with Office 365 E3 licenses and one with Office 365 Business Premium:
The solution is Azure Automation
The solution is to run a Powershell script through Azure Automation. This also can be run as a scheduled task on a Windows Server. But if you don’t have a server suitable for the task you can create a runbook through Azure Automation. That’s much cooler anyway!
Step 1. Create a License group for the users
First we need to create a group we want to assign licenses to:
– Go to https://admin.microsoft.com and logon with your admin credentials
– Click “Groups” -> “Add a group”
– Choose “Security Group” and click Next
– Enter a groupname and description, click Next
– Review your input and click “Create group”
If you have Azure ADConnect in place which synchronises your on-premises Active Directory to Office365 / Azure Active Directory it is also possible to make an Active Directory group for this purpose.
After you have created the group you might want to add some users to the group….
Step 2. Create an Azure subscription
If you already have an Azure subscription you can use that one. But if you don’t, you need to create one. Azure Automation is free to a certain point and number. But since there is a posibility you consume Azure credit you have to have a subscrition. Under normal circumstances you don’t have to worry this solutions costs money.
There is an option to create a free 12 month subscription and $200 free credit.
Go to https://portal.azure.com and start with a free trial.
Now you have to fill in your personal information and creditcard information. No worries, you won’t be charged unless you upgrade.
Your local Microsoft Partner can also provide you with an CSP subcription for which you will receive an invoice instead of credit card payment.
Step 3. Create a Resource group
Go to your subscription and create a resource group:
– Choose a suitable name
– Select the right region
– Click “Review + Create” and “Create”
Step 4. Create an Automation Account
Go back to the Azure portal and go to Automation Accounts
Click “Add”
1. Choose a suitable name
2. Select subscription
3. Select the previously created Resource Group
4. Hit “Create”
Step 5. Setup the credentials
Since the Automation needs credentials we need to add them to the automation account.
Upfront I created an license admin account throught the Office 365 Admin portal. The user needs the “User Admin” role. The “License Admin” role does not suffice.
Now go back to your Automation Account and and the create account as New Credential
Step 6. Add the MSOnline module to your automation account
Go to the Modules gallery in the automation account, search for “msonline” and select the module.
Click “Import” and “OK”
Now after a couple of minutes the module appears in the module list
Step 7. Create a Powershell Runbook
Now we are going to create a powershell runbook to execute the script from. Again in your Automation Account follow the instructions below.
Step 8. Determine the license you want to distribute
First we need the exact technical description of your license. Fire up a powershell prompt make sure you have the MSonline Modules installed. Connect by executing Connect-MsolService
and enter Get-MsolAccountSku
In this case we need <yourtenantname>:O365_BUSINESS_PREMIUM
PS C:\Users\edwin> Connect-MsolService
PS C:\Users\edwin> Get-MsolAccountSku
AccountSkuId ActiveUnits WarningUnits ConsumedUnits
------------ ----------- ------------ -------------
<yourtenantname>:O365_BUSINESS_PREMIUM 25 0 0
PS C:\Users\edwin>
In this case we see a license sku of Office 365 Business Premium which consists of several license plan options. If you do not want to give users all the options you can disable certain plans. First let’s tak a look at the plan options with Get-MsolAccountSku | select -ExpandProperty ServiceStatus
PS C:\Users\edwin> Get-MsolAccountSku | select -ExpandProperty ServiceStatus
ServicePlan ProvisioningStatus
----------- ------------------
MICROSOFT_SEARCH Success
WHITEBOARD_PLAN1 Success
MYANALYTICS_P2 Success
DYN365BC_MS_INVOICING Success
KAIZALA_O365_P2 Success
STREAM_O365_SMB Success
Deskless Success
BPOS_S_TODO_1 Success
MICROSOFTBOOKINGS Success
FORMS_PLAN_E1 Success
FLOW_O365_P1 Success
POWERAPPS_O365_P1 Success
O365_SB_Relationship_Management Success
TEAMS1 Success
PROJECTWORKMANAGEMENT Success
SWAY Success
INTUNE_O365 PendingActivation
SHAREPOINTWAC PendingInput
OFFICE_BUSINESS Success
YAMMER_ENTERPRISE Success
EXCHANGE_S_STANDARD Success
MCOSTANDARD Success
SHAREPOINTSTANDARD PendingInput
In the left column you see the different service plans. You can see the reference at https://docs.microsoft.com/en-gb/azure/active-directory/users-groups-roles/licensing-service-plan-reference
In this example we are going to prevent the use of Microsoft Sway (SWAY) and Microsoft Kaizala Pro (KAIZALA_0365_P2)
Step 9. Create the powershell script in the Runbook
Now we have all the parts it’s time to create the script.
Copy and Past the script below in your favorite editor and change the following lines:
9) Change the license admin user to the one you created in your Automation Account (Step 5). Use the name and not the username (if different)
14) Change the AccountSku and Plans you optionally want to disable. If you do not want to disable any plans simply remove the -DisabledPlans
parameter and its options.
18) Change the name. This is a just a label
19) Change the LicenseSKU to match line 14
20) Change the group to the one you created or selected in Step 1
24) Change the location where the users reside. NL for the Netherlands in my case.
<#
.SYNOPSIS
Script that assigns Office 365 licenses based on Group membership..
.NOTES
The script are provided “AS IS” with no guarantees, no warranties, and they confer no rights.
#>
#Office 365 Admin Credentials
$Credential = Get-AutomationPSCredential -Name "licenseadmin@xxxxxxx.onmicrosoft.com"
#Connect to Office 365
Connect-MsolService -Credential $Credential
$LicenseOptions = New-MsolLicenseOptions -AccountSkuId "xxxxxxxxxx:O365_BUSINESS_PREMIUM" -DisabledPlans "SWAY","KAIZALA_O365_P2"
$Licenses = @{
'Office365BusinessPremium' = @{
LicenseSKU = 'xxxxxxxxxx:O365_BUSINESS_PREMIUM'
Group = 'LIC_UsersOffice365BusinessPremium'
}
}
$UsageLocation = 'NL'
#Get all currently licensed users and put them in a custom object
$LicensedUserDetails = Get-MsolUser -All | Where-Object {$_.IsLicensed -eq 'True'} | ForEach-Object {
[pscustomobject]@{
UserPrincipalName = $_.UserPrincipalName
License = $_.Licenses.AccountSkuId
}
}
#Create array for users to change or delete
$UsersToChangeOrDelete = @()
foreach ($license in $Licenses.Keys) {
#Get current group name and ObjectID from Hashtable
$GroupName = $Licenses[$license].Group
$GroupID = (Get-MsolGroup -All | Where-Object {$_.DisplayName -eq $GroupName}).ObjectId
$AccountSKU = Get-MsolAccountSku | Where-Object {$_.AccountSKUID -eq $Licenses[$license].LicenseSKU}
Write-Output "Checking for unlicensed $license users in group $GroupName with ObjectGuid $GroupID..."
#Get all members of the group in current scope
$GroupMembers = (Get-MsolGroupMember -GroupObjectId $GroupID -All).EmailAddress
#Get all already licensed users in current scope
$ActiveUsers = ($LicensedUserDetails | Where-Object {$_.License -eq $licenses[$license].LicenseSKU}).UserPrincipalName
$UsersToHandle = ''
if ($GroupMembers) {
if ($ActiveUsers) {
#Compare $Groupmembers and $Activeusers
#Users which are in the group but not licensed, will be added
#Users licensed, but not, will be evaluated for deletion or change of license
$UsersToHandle = Compare-Object -ReferenceObject $GroupMembers -DifferenceObject $ActiveUsers -ErrorAction SilentlyContinue -WarningAction SilentlyContinue
$UsersToAdd = ($UsersToHandle | Where-Object {$_.SideIndicator -eq '<='}).InputObject
$UsersToChangeOrDelete += ($UsersToHandle | Where-Object {$_.SideIndicator -eq '=>'}).InputObject
} else {
#No licenses currently assigned for the license in scope, assign licenses to all group members.
$UsersToAdd = $GroupMembers
}
} else {
Write-Warning "Group $GroupName is empty - will process removal or move of all users with license $($AccountSKU.AccountSkuId)"
#If no users are a member in the group, add them for deletion or change of license.
$UsersToChangeOrDelete += $ActiveUsers
}
#Check the amount of licenses left...
if ($AccountSKU.ActiveUnits - $AccountSKU.consumedunits -lt $UsersToAdd.Count) {
Write-Warning 'Not enough licenses for all users, please remove user licenses or buy more licenses'
}
foreach ($User in $UsersToAdd){
#Process all users for license assignment, if not already licensed with the SKU in order.
if ((Get-MsolUser -UserPrincipalName $User).Licenses.AccountSkuId -notcontains $AccountSku.AccountSkuId) {
try {
#Assign UsageLocation and License.
Set-MsolUser -UserPrincipalName $User -UsageLocation $UsageLocation -ErrorAction Stop -WarningAction Stop
Set-MsolUserLicense -UserPrincipalName $User -AddLicenses $AccountSKU.AccountSkuId -LicenseOptions $LicenseOptions -ErrorAction Stop -WarningAction Stop
Write-Output "SUCCESS: Licensed $User with $license"
} catch {
Write-Warning "Error when licensing $User"
}
}
}
}
#Process users for change or deletion
if ($UsersToChangeOrDelete -ne $null) {
foreach ($User in $UsersToChangeOrDelete) {
if ($user -ne $null) {
#Fetch users old license for later usage
$OldLicense = ($LicensedUserDetails | Where-Object {$_.UserPrincipalName -eq $User}).License
#Loop through to check if the user group assignment has been changed, and put the old and the new license in a custom object.
#Only one license group per user is currently supported.
$ChangeLicense = $Licenses.Keys | ForEach-Object {
$GroupName = $Licenses[$_].Group
if (Get-MsolGroupMember -All -GroupObjectId (Get-MsolGroup -All | Where-Object {$_.DisplayName -eq $GroupName}).ObjectId | Where-Object {$_.EmailAddress -eq $User}) {
[pscustomobject]@{
OldLicense = $OldLicense
NewLicense = $Licenses[$_].LicenseSKU
}
}
}
if ($ChangeLicense) {
#The user were assigned to another group, switch license to the new one.
try {
Set-MsolUserLicense -UserPrincipalName $User -RemoveLicenses $ChangeLicense.OldLicense -AddLicenses $ChangeLicense.NewLicense -LicenseOptions $LicenseOptions -ErrorAction Stop -WarningAction Stop
Write-Output "SUCCESS: Changed license for user $User from $($ChangeLicense.OldLicense) to $($ChangeLicense.NewLicense)"
} catch {
Write-Warning "Error when changing license on $User`r`n$_"
}
} else {
#The user is no longer a member of any license group, remove license
Write-Warning "$User is not a member of any group, license will be removed... "
try {
Set-MsolUserLicense -UserPrincipalName $User -RemoveLicenses $OldLicense -ErrorAction Stop -WarningAction Stop
Write-Output "SUCCESS: Removed $OldLicense for $User"
} catch {
Write-Warning "Error when removing license on user`r`n$_"
}
}
}
}
}
After you edited the script you simply past it in your runbook and Click “Save”” and “Publish”.
Step 10. Test and Schedule the runbook
First we are going to test the correct working of our runbook/Script by hitting “Start”
- Hit “Refresh” a few times
- Wait for the script to be completed
- Click “All logs”
- See the licenses assigned to the users in the group.
Now go back to your Office 365 Portal and verify the users have the license assigned.
Once everything works go to Automation Account and let’s create a Schedule
After creating a schedule we have to link it to your Runbook. Go to the Runbook and click “Link to schedule”
Click Schedule, Select the schedule you created and click OK
Finished
Now you’ve done it. Users are getting a license assigned through Azure Automation. You’ve basically fixed Group Based licensing without having the licenses normally required for this task.
I hope you enjoyed reading and deploying…..
One Reply to “Assign Microsoft Office 365 Licenses through Azure Automation”