Important note: The end of an era with licensing scripts is near… and the beginning of a new one with Azure AD Group Based Licensing is here. Group Based Licensing is now in preview and currently requires a paid Azure AD Subscription. Try it out and give Microsoft your feedback on how they can make it even better!
Update 2016-01-07: Updated the script with a new function to support nested groups.
As a follow up to my earlier post about assigning Office 365 licenses based on ad attribute, I’ve now created another script that uses another approach to assign the licenses.
Instead of using ad attributes, we are here using security groups to assign the licenses.
Since you want to automate license assignment, I am assuming that you are using DirSync.
In this script, the groups and group members are enumerated directly in Windows Azure Active Directory. This means that the groups you will use to assign licenses, must be synchronized to WAAD. If you are looking for a more advanced script with change and removal functions, check this one out.
Note: Users that already have a license are not processed by the script, nor are licenses removed from users that are not longer member of the groups.
Getting started
Getting started with the script is very easy. In the $Licenses hash table, you define the licenses to assign, the group to use for assignment and the license SKU.
The license SKU id’s for your tenant are found with the Get-MsolLicenseSKU cmdlet, as below:
Here you will find a good translation table that will help you interpret the License SKU ID to the actual license type. When you have done that, just to put in your O365 credentials and UsageLocation in the script and then you’re all set to schedule the script.
LicenseO365Users.ps1
#2016-01-07 - Updated the script with a new function to support nested groups. #Import Required PowerShell Modules #Note - the Script Requires PowerShell 3.0! Import-Module MSOnline #Office 365 Admin Credentials $CloudUsername = 'admin@tenant.onmicrosoft.com' $CloudPassword = ConvertTo-SecureString 'password' -AsPlainText -Force $CloudCred = New-Object System.Management.Automation.PSCredential $CloudUsername, $CloudPassword #Connect to Office 365 Connect-MsolService -Credential $CloudCred function Get-JDMsolGroupMember { param( [CmdletBinding(SupportsShouldProcess=$true)] [Parameter(Mandatory=$true, ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,Position=0)] [ValidateScript({Get-MsolGroup -ObjectId $_})] $ObjectId, [switch]$Recursive ) begin { $MSOLAccountSku = Get-MsolAccountSku -ErrorAction Ignore -WarningAction Ignore if (-not($MSOLAccountSku)) { throw "Not connected to Azure AD, run Connect-MsolService" } } process { $UserMembers = Get-MsolGroupMember -GroupObjectId $ObjectId -MemberObjectTypes User -All if ($PSBoundParameters['Recursive']) { $GroupsMembers = Get-MsolGroupMember -GroupObjectId $ObjectId -MemberObjectTypes Group -All $GroupsMembers | ForEach-Object -Process { $UserMembers += Get-JDMsolGroupMember -Recursive -ObjectId $_.ObjectId } } Write-Output ($UserMembers | Sort-Object -Property EmailAddress -Unique) } end { } } $Licenses = @{ 'E1' = @{ LicenseSKU = 'mstlabs:STANDARDPACK' Group = 'E1_Users' } 'E3' = @{ LicenseSKU = 'mstlabs:ENTERPRISEPACK' Group = 'Office 365 E5' } } $UsageLocation = 'SE' foreach ($license in $Licenses.Keys) { $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..." $GroupMembers = (Get-JDMsolGroupMember -ObjectId $GroupID -Recursive | Where-Object {$_.IsLicensed -eq $false}).EmailAddress if ($AccountSKU.ActiveUnits - $AccountSKU.consumedunits -lt $GroupMembers.Count) { Write-Warning 'Not enough licenses for all users, please remove user licenses or buy more licenses' } foreach ($User in $GroupMembers) { Try { Set-MsolUser -UserPrincipalName $User -UsageLocation $UsageLocation -ErrorAction Stop -WarningAction Stop Set-MsolUserLicense -UserPrincipalName $User -AddLicenses $AccountSKU.AccountSkuId -ErrorAction Stop -WarningAction Stop Write-Output "Successfully licensed $User with $license" } catch { Write-Warning "Error when licensing $User`r`n$_" } } }
Looking for other script options using groups?
Office 365: Assign licenses based on groups using PowerShell – Advanced version – adds and removes licenses for the users as well.
Office 365: Assign individual parts of licenses based on groups using PowerShell – script with the ability to add and remove serviceparts of a license.
There are lots of things that are not in the script that could also be automated, please help us prioritize with the features you’d like to have the most.
/Johan
Pingback: Office 365: Assign licenses based on groups using PowerShell – Advanced version | Tailspintoys – 365lab.net
How would you add the option to disable options for each plan?
Hi Annie,
Thanks for reading!
To disable specific options for each plan, look into the following site: http://blogs.technet.com/b/treycarlee/archive/2013/11/01/list-of-powershell-licensing-sku-s-for-office-365.aspx.
Basically you would need to add a $disabledplans as in the blogpost above for each SKU, use the -LicenseOptions parameter with the Set-MsolUserLicense cmdlet on row 43.
Hope this helps you, let me know if you need further help!
/Johan
Forgive me as aI am not an expert programer. Would the option be added when you define the license with group or where you actually assign the license? I am not sure what syntax to use….
Hi Johan,
I am trying to do this but unable to accomplish. I can assign E3 license but running into issues disabling specific options. Would you be able to share how to use the $disabledplans in the above script?
Hi,
If you have different options for different licenses, it should be added then the Group is defined and picked up later. I’ll put this on my list with things to do follow up posts on.
/Johan
I was able to modify the scrips to assign different license options, however I have notified during the testing that if a group contains a disabled AD account it won’t assign licenses to anyone in the group. Have you experienced that?
Hi,
Perfect. I’ve tried your scenario with disabled users in the Groups, but have not experienced that particular error.
I can help you troubleshoot further, but would then need to see the Changes in the code you’ve done.
Thanks for Reading!
Hello,
I would be happy to share!
(See attached file: ADGroup.ps1)
Thanks!
Annie.. Can you share the script. I am trying to assign the E3 license with individual options but its failing. I can assign E3 with all options but not selected.
Johah,
I realized I included my personal contact info in my last response. Can this be removed from this site?
Corrected now. I did however not get your attachment.
I am unable to attach files from this site. Did you want to copy and past the code here?
THanks
Annie,
You can send me an email on johan[at]Dahlbom.eu with the code.
/Johan
Hello,
Just wondering if you ever received by code?
Thanks
Hi Annie,
Sorry for the late reply. I have not received any code.
/Johan
Hi Johan,
Thank you for posting this script. I have tried to use it on my system. I have assigned the users to the correct group, adjusted the SKU in the script, edited authentication details.
When I run the script, I simply get the message “Error when licensing”.
Is there anything else I need to do in my environment?
Mark
Hi Mark,
Thanks for Reading!
To be able to troubleshoot further, I have now updated row 47 to include more debugging information. Please replace that row in the script you are running, and hopefully we’ll get more in depth information about the issue.
Control questions:
* Are you running PowerShell 3.0 on the machine which are running the script? I’ve seen problems running this on PowerShell 2.0 Machines.
* Are you running the latest version of the Windows Azure Active Directory module for PowerShell? There are quite a bit of bugs in older versions (one thing with the amount of Group members that could be enumerated. Please update to the latest version if not already running it.
Hope this helps you out!
/Johan
Hi Johan,
Thank you very much for your swift response, it is very much appreciated. I had updated the Windows Azure Active Directory module, but I had not thought to update my version of PowerShell.
I have updated to version 3.0 and the script is running perfectly.
Once again, thank you very much for the script and for your help in getting it working.
Mark
What about users who have changes group (ie. no longer in E1 but now in E3). Can these users be moved?
Hi,
The script will change license if s user gets removed from example the E1 group and added to the E3 group. There are no error handling implemented for conflicting groups (if someone is a member of both groups).
Thanks for reading!
/Johan
I just tested, it doesn’t look like its working as you described. Perhaps line 35 where “$_.IsLicensed -eq $false” is preventing the change. I will fiddle with this to my specific needs, thanks for the initial help!
Removing the ” | Where-Object {$_.IsLicensed -eq $false}” option gives an error for each existing member…
Unable to assign this license because it is invalid. Use the Get-MsolAccountSku cmdlet to retrieve a list of valid licenses.
Then for new members (previously assigned to another group) get the following error…
Unable to update license for this user. The set of licenses includes two or more service plans which cannot be assigned at the same time. Conflicting Service Plans: MCOSTANDARD, MCOSTANDARD.
I have confirmed that users are only in a single group at a time.
Here is my contribution to your work which has corrected the issue for me (replace section starting with line 41 / from the second ‘FroEach’)…
foreach ($User in $GroupMembers) {
# For Users without license
If (!(Get-MsolUser -UserPrincipalName $User).Licenses.AccountSkuId) {
Try {
Set-MsolUser -UserPrincipalName $User -UsageLocation $UsageLocation -ErrorAction Stop -WarningAction Stop
Set-MsolUserLicense -UserPrincipalName $User -AddLicenses $AccountSKU.AccountSkuId -ErrorAction Stop -WarningAction Stop
Write-Output “Successfully licensed $User with $license”
} catch {
Write-Warning “Error when licensing $User`r`n$_”
}
}
# For Users with wrong license
If ((Get-MsolUser -UserPrincipalName $User).Licenses.AccountSkuId -ne $AccountSKU.AccountSkuId) {
Try {
Set-MsolUser -UserPrincipalName $User -UsageLocation $UsageLocation -ErrorAction Stop -WarningAction Stop
Set-MsolUserLicense -UserPrincipalName $User -RemoveLicenses (Get-MsolUser -UserPrincipalName $User).Licenses.AccountSkuId -AddLicenses $AccountSKU.AccountSkuId -ErrorAction Stop -WarningAction Stop
Write-Output “Changed license for user $User to new license $license”
} catch {
Write-Warning “Error when licensing $User`r`n$_”
}
}
}
Hi,
Thanks for the contribution!
/Johan
Pingback: Azure AD, Licensing users in a Security Group - MiguelNunez - Site Home - MSDN Blogs
Thanks works perfect!
This is great for seeding new users… do you have something for removing old users? I’d love to change the error handling to add the lines to a list, and then send an e-mail where the body shows any errors, following by number of new licenses/licenses remaining, and then put it into a scheduled task to run overnight that I can forget about as long as the daily e-mail it sends is okay.
Hi Joel,
Sorry for the late reply.
Have you seen the more advanced version which removes and adds licenses?
Regarding logging, if you look in to the places where I’m using “Write-Output” , it could easily be changed to something else, for example an email.
Send me an email if you’d like additonal help with that offline.
/Johan
I never saw your reply, either, so it’s okay. However, I was eventually able to build on this, and after a few rounds of refactoring I think I have all of those features now. The result of my efforts is available here:
https://github.com/jcoehoorn/O365LicenseSync
Hi,
Nice work – have a look at my approach to the same thing in the “Advanced Version”
Pingback: What are my SKU names for Office 365 Education and how can I automate the licensing? - Microsoft Education in the Cloud - Site Home - TechNet Blogs
Hello Johan and thank you for your useful script.
Is there by any chance a way to make it works when users are in a group, nested in an other group?
Right now, the $GroupMembers is empty in my case because the users are not directly in this group but in several nested groups.
Thank you!
Tom
Hi Tom,
Thanks for reading! Get-MsolGroupMember do not support nested group as it is right now.
I will give it a couple of minutes and see if I can work an alternative out for you 🙂
/Johan
Hi Tom,
I have now updated the script with a new function for enumerating group members to support nested groups. Let me know if you run in to any problems or if you have any questions.
/Johan
I tested this script, but the nested groupmember did not get the licence… it´s checking for unlicensed E3 users,.. but nothing shows after that and the script ends.?!
Can this be modified somehow to assign multiple SKU’s at once?
For instance, in education if I have tenant:stadardwoffpack_student and tenant:officesubscription_student that I want to assign how can I do that?
I tried modifying the $licenses section to where it looks like this:
LicenseSKU = ‘tenant:sku1,tenant:sku2’
or
LicenseSKU = ‘”tenant:sku1″,”tenant:sku2″‘
But it always fails. If I manually modify the set-msoluserlicense line I can get it to work but that just assigns the same sku to every user regardless of the group.
Help?
It is possible, but it needs some rewriting. Do you still need help on this?
Hi Johan,
I could use some help with assigning multiple SKU’s at once.
Pingback: Office 365: Assign licenses based on groups using PowerShell – Advanced version – Nuno Árias Silva Website
Hi,
‘E1’ = @{
LicenseSKU = ‘aspenhospital:SHAREPOINTSTANDARD’
Group = ‘All users’
We are going to assign above license to to group All users, so i have changed following things according my environment, i just want to know what does that ‘E1’ means here??
Has anyone figured out how to assign multiple SKU’s at once? Could use a hand if anyone is willing!
Hi Johan
When I run a version of the script to assisgn licenses, It completes without errors but doesn’t actually assign the licenses. Is there a way I can get some error output back to the server I’m running the script on (redirect error output to a my local server file location) so I can further troubleshoot why the licenses are not being assigned or removed?
Kevin C.
Pingback: Disabling OneDrive for Office365 | LMAmey