Last active
January 26, 2018 21:26
-
-
Save janikvonrotz/6218401 to your computer and use it in GitHub Desktop.
PowerShell: Set Office365 Licenses by ActiveDirectory Group Membership
#ActiveDirectory
#PowerShell
#Office365
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-16"?> | |
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task"> | |
<RegistrationInfo> | |
<Date>2013-03-20T14:18:21.6393172</Date> | |
<Author>Janik von Rotz (www.janikvonrotz.ch)</Author> | |
<Description>Office365 License Management</Description> | |
</RegistrationInfo> | |
<Triggers> | |
<CalendarTrigger> | |
<StartBoundary>2013-01-01T02:30:00</StartBoundary> | |
<Enabled>true</Enabled> | |
<ScheduleByDay> | |
<DaysInterval>1</DaysInterval> | |
</ScheduleByDay> | |
</CalendarTrigger> | |
</Triggers> | |
<Settings> | |
<MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy> | |
<DisallowStartIfOnBatteries>true</DisallowStartIfOnBatteries> | |
<StopIfGoingOnBatteries>true</StopIfGoingOnBatteries> | |
<AllowHardTerminate>true</AllowHardTerminate> | |
<StartWhenAvailable>false</StartWhenAvailable> | |
<RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable> | |
<IdleSettings> | |
<StopOnIdleEnd>true</StopOnIdleEnd> | |
<RestartOnIdle>false</RestartOnIdle> | |
</IdleSettings> | |
<AllowStartOnDemand>true</AllowStartOnDemand> | |
<Enabled>true</Enabled> | |
<Hidden>false</Hidden> | |
<RunOnlyIfIdle>false</RunOnlyIfIdle> | |
<WakeToRun>false</WakeToRun> | |
<ExecutionTimeLimit>P3D</ExecutionTimeLimit> | |
<Priority>7</Priority> | |
</Settings> | |
<Actions Context="Author"> | |
<Exec> | |
<Command>C:\Windows\System32\WindowsPowerShell\v1.0\PowerShell.exe</Command> | |
<Arguments>C:\Powershell-Profile\scripts\Set-O365UserLicensesByADGroup.ps1</Arguments> | |
<WorkingDirectory>C:\Powershell-Profile\scripts</WorkingDirectory> | |
</Exec> | |
</Actions> | |
</Task> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
$Metadata = @{ | |
Title = "Set Office365 Licenses by ActiveDirectory Group Membership" | |
Filename = "Set-O365UserLicensesByADGroup.ps1" | |
Description = @" | |
Adding license to a Office365 user as long the user is in the correct ActiveDirectory group | |
or in the white list, the users is active, the user has a mailbox. | |
The script will remove inactive licenses or if necessary replace them. | |
"@ | |
Tags = "powershell, activedirectory, office365, user, license, activation" | |
Project = "" | |
Author = "Janik von Rotz" | |
AuthorContact = "http://janikvonrotz.ch" | |
CreateDate = "2013-08-13" | |
LastEditDate = "2014-05-02" | |
Url = "https://gist.github.com/janikvonrotz/6218401" | |
Version = "3.5.0" | |
License = @' | |
This work is licensed under the Creative Commons Attribution-ShareAlike 3.0 Switzerland License. | |
To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/3.0/ch/ or | |
send a letter to Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA. | |
'@ | |
} | |
#> | |
try{ | |
#--------------------------------------------------# | |
# settings | |
#--------------------------------------------------# | |
$UsageLocation = "CH" | |
<# | |
Name: name of the license configuration, has to be unique | |
ADGroupSID: Active Directory group containing the users to apply a license | |
Users: for office 365 only users or selected domain users | |
License: Office 365 license type | |
DisabledPlans: Plans to disable | |
Priority: if a user is in both groups the license with the higher priority will be applied | |
SecondaryLicenses: in case the license is not available but another is also pssible to add you can add the name of this license configuration here | |
Count: counting the number of licenses | |
#> | |
$LicenseConfig = $(New-Object PSObject -Property @{ | |
Name = "SharePoint Online Plan 1" | |
License = "vbluzern:SHAREPOINTSTANDARD" | |
ADGroupSID = "S-1-5-21-1744926098-708661255-2033415169-37562" # SPO_SharePointOnlinePlan1License | |
Priority = 3 | |
SecondaryLicense = "Enterprise Plan 1 - SharePoint Only" | |
}), | |
$(New-Object PSObject -Property @{ | |
Name = "Enterprise Plan 1" | |
License = "vbluzern:STANDARDPACK" | |
ADGroupSID = "S-1-5-21-1744926098-708661255-2033415169-36657" # SPO_365E1License | |
Priority = 2 | |
}), | |
$(New-Object PSObject -Property @{ | |
Name = "Enterprise Plan 1 - SharePoint Only" | |
License = "vbluzern:STANDARDPACK" | |
DisabledPlans = "EXCHANGE_S_STANDARD" | |
}), | |
$(New-Object PSObject -Property @{ | |
Name = "Enterprise Plan 1 - O365 users only" | |
Users = "admin@vbluzern.onmicrosoft.com" | |
License = "vbluzern:STANDARDPACK" | |
}), | |
$(New-Object PSObject -Property @{ | |
Name = "SharePoint Online Plan 1 - O365 users only" | |
Users = "urs.egli@vbluzern.onmicrosoft.com","innotix@vbluzern.onmicrosoft.com" | |
License = "vbluzern:SHAREPOINTSTANDARD" | |
}) | |
#--------------------------------------------------# | |
# modules | |
#--------------------------------------------------# | |
Import-Module MSOnline | |
Import-Module MSOnlineExtended | |
Import-Module ActiveDirectory | |
#--------------------------------------------------# | |
# main | |
#--------------------------------------------------# | |
$Credential = Import-PSCredential $(Get-ChildItem -Path $PSconfigs.Path -Filter "Office365.credentials.config.xml" -Recurse).FullName | |
Connect-MsolService -Credential $Credential | |
# normalize license config | |
$LicenseAndUser = $LicenseConfig | select @{L="Name";E={$_.Name}}, | |
@{L="UserPrincipalName"; E={$_.UserPrincipalName}}, | |
@{L="ADGroupSID";E={$_.ADGroupSID}}, | |
@{L="Users";E={$_.Users}}, | |
@{L="License";E={$_.License}}, | |
@{L="DisabledPlans";E={if($_.DisabledPlans){$_.DisabledPlans = New-MsolLicenseOptions -AccountSkuId $_.License -DisabledPlans $_.DisabledPlans}}}, | |
@{L="Priority";E={$_.Priority}}, | |
@{L="SecondaryLicense";E={$_.SecondaryLicense}} | |
# extend the secondary license field with the normalized object | |
$LicenseAndUser = $LicenseAndUser | Foreach-Object{ | |
New-TreeObjectArray -Array $LicenseAndUser -Objects $_ -Attribute "SecondaryLicense" -Filter "Name" | |
} | |
# get userprincipalnames of the ad group members | |
$LicenseAndUser = $LicenseAndUser | Foreach-Object{ | |
if($_.ADGroupSID){ | |
$License = $_ | |
Get-ADGroupMember $_.ADGroupSID -Recursive | Get-ADUser | where{$_.Enabled -eq $true} | Foreach-Object{ | |
$UserLicense = $License.psobject.Copy() | |
$UserLicense.UserPrincipalName = $_.UserPrincipalName | |
$UserLicense | |
} | |
} | |
if($_.Users){ | |
$License = $_ | |
$_.Users | Foreach-Object{ | |
$UserLicense = $License.psobject.Copy() | |
$UserLicense.UserPrincipalName = $_ | |
$UserLicense | |
} | |
} | |
} | |
$Report = @() | |
function New-ReportItem{ | |
param( | |
$User, | |
$License, | |
$Status # NoChanges, NotAllowed, LicenseAssigned, SecondaryLicenseAssigned, UnableToAssignLicense, LicenseRemoved, UnableToRemoveLicense, LicenseReplaced, UnableToReplaceLicense | |
) | |
Return $(New-Object PSObject -Property @{ | |
User = $User | |
License = $License | |
Status = $Status | |
}) | |
} | |
$MsolUsers = Get-MsolUser -All | |
$MsolUsers | Foreach-Object{ | |
$User = $_ | |
# debug a user, set debugger on $true variable | |
if($User.UserPrincipalName -eq ""){ | |
$true} | |
# get license configuration for this user | |
$Config = $LicenseAndUser | where{$_.UserPrincipalName -eq $User.UserPrincipalName} | |
# check the license configuration with the higher priority | |
if($Config.count -gt 1){ | |
$Config = $Config | sort Priority | select -First 1 | |
} | |
# apply the license | |
if($Config){ | |
# licenses are not same | |
if($User.IsLicensed -and ($User.Licenses.AccountSkuId -ne $Config.License)){ | |
# remove license | |
$User.Licenses | Foreach-Object{ | |
$License = $_ | |
try{ | |
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $License.AccountSkuId -ErrorAction Stop | |
}catch{ | |
Write-PPErrorEventLog -Message "Could not remove license: $($License.AccountSkuId) to user: $($User.UserPrincipalName)" -Source "Office365 License Management" -ClearErrorVariable | |
} | |
} | |
# Assign license | |
try{ | |
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $Config.License -LicenseOptions $Config.DisabledPlans -ErrorAction Stop | |
Write-PPEventLog "Replacee Office365 license: $($User.Licenses.AccountSkuId) with: $($Config.License) for user: $($User.UserPrincipalName)" -Source "Office365 License Management" -WriteMessage | |
$Report += New-ReportItem -User $User.UserPrincipalName -License $Config.License -Status "LicenseReplaced" | |
}catch{ | |
Write-PPErrorEventLog -Message "Could not assign license: $($Config.License) to user: $($User.UserPrincipalName)" -Source "Office365 License Management" -ClearErrorVariable | |
$Report += New-ReportItem -User $User.UserPrincipalName -License $Config.License -Status "UnableToReplaceLicense" | |
} | |
# correct license already applied | |
}elseif($User.IsLicensed){ | |
Write-Host "User: $($User.UserPrincipalName) is already licensed with: $($Config.License)" | |
$Report += New-ReportItem -User $User.UserPrincipalName -License $Config.License -Status "NoChanges" | |
# apply a license | |
}else{ | |
# set location in order to apply a license | |
Set-MsolUser -UserPrincipalName $User.UserPrincipalName -UsageLocation $UsageLocation | |
# apply license | |
try{ | |
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -AddLicenses $Config.License -LicenseOptions $Config.DisabledPlans -ErrorAction Stop | |
Write-PPEventLog "Set Office365 license: $($Config.License) for user: $($User.UserPrincipalName)" -Source "Office365 License Management" -WriteMessage | |
$Report += New-ReportItem -User $User.UserPrincipalName -License $Config.License -Status "LicenseAssigned" | |
}catch{ | |
Write-PPErrorEventLog -Message "Could not assign license: $($Config.License) to user: $($User.UserPrincipalName)" -Source "Office365 License Management" -ClearErrorVariable | |
$Report += New-ReportItem -User $User.UserPrincipalName -License $Config.License -Status "UnableToAssignLicense" | |
} | |
} | |
# ignore the user or remove the license | |
}else{ | |
# remove the license | |
if($User.IsLicensed){ | |
$User.Licenses | Foreach-Object{ | |
$License = $_ | |
try{ | |
Set-MsolUserLicense -UserPrincipalName $User.UserPrincipalName -RemoveLicenses $License.AccountSkuId | |
Write-PPEventLog "Removed Office365 license: $($License.AccountSkuId) from user: $($User.UserPrincipalName)" -Source "Office365 License Management" -WriteMessage | |
$Report += New-ReportItem -User $User.UserPrincipalName -License $License.AccountSkuId -Status "LicenseRemoved" | |
}catch{ | |
Write-PPErrorEventLog -Message "Could not remove license: $($License.AccountSkuId) to user: $($User.UserPrincipalName)" -Source "Office365 License Management" -ClearErrorVariable | |
$Report += New-ReportItem -User $User.UserPrincipalName -License $License.AccountSkuId -Status "UnableToRemoveLicense" | |
} | |
} | |
# ignore the user | |
}else{ | |
Write-Host "User: $($User.UserPrincipalName) is not allowed" | |
$Report += New-ReportItem -User $User.UserPrincipalName -Status "NotAllowed" | |
} | |
} | |
} | |
$Report | Group-Object Status | |
}catch{ | |
Write-PPErrorEventLog -Source "Office365 License Management" -ClearErrorVariable -Message | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment