janikvonrotz
8/13/2013 - 6:34 AM

PowerShell: Set Office365 Licenses by ActiveDirectory Group Membership #ActiveDirectory #PowerShell #Office365

PowerShell: Set Office365 Licenses by ActiveDirectory Group Membership #ActiveDirectory #PowerShell #Office365

<#
$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
}
<?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>