Microsoft releases new services all around the year, recent example is Kaizala. it pushes the license automatically to all users.
Many of our customers do not like the automatic push and want to know the exact date when Microsoft enables the new service to their tenants and want to take necessary actions to disable it as soon as they can.(reason is that they want to evaluate it first with their pilot groups before releasing it to general user population)
This is the reason we have written this script that runs 4 times daily, detects any new service addition to E3 or any other plan and sends the alert with CSV report of service that is added or removed(We do not think removal will happen but just in case)
Download the code zip from below link, code is paramterized so you can just create a batch file as show in in below example contents and schedule it to run as per requirements.
https://github.com/VikasSukhija/Downloads/blob/master/o365NewServiceMonitor.zip
powershell .\o365NewServiceMonitor.ps1 -LicenseSKU “Company:ENTERPRISEPACK” -smtpserver “smtp.labtest.com” -from “DoNotReply@labtest.com” -erroremail “ReportLogs@labtest.com” -email “VSukhija@labtest.com,c83975758@amer.teams.ms” -userid “MSOLSVC@labtest.com”
powershell .\o365NewServiceMonitor.ps1 -LicenseSKU “Company:DESKLESSPACK” -smtpserver “smtp.labtest.com” -from “DoNotReply@labtest.com” -erroremail “ReportLogs@labtest.com” -email “VSukhija@labtest.com,c83975758@amer.teams.ms” -userid “MSOLSVC@labtest.com”
Run the encrypt.bat file to generate the encrypted password for MSOL service account as that will be used by the script everytime it runs.
Below parameters are self explanatory that are required by the script:
[string]$LicenseSKU = $(Read-Host “Enter License SKU”),
[string]$smtpserver = $(Read-Host “Enter SMTP Server”),
[string]$from = $(Read-Host “Enter From Address”),
[string]$erroremail = $(Read-Host “Enter Address for Report and Errors”),
[string]$userId = $(Read-Host “Enter UserID of the account that has access to MSOL”),
[array]$email= $(Read-Host “Enter Address for Email Report”)
Note:
- MSOL Module is required for this script to function.
- script will recycle the logs and reports after 60 days.
Here is the report output that will be sent on email.(it will be only sent when new service is added)
PowerShell Code:
<# .NOTES =========================================================================== Created with: ISE Created on: 7/22/2018 1:46 PM Created by: Vikas Sukhija Organization: Filename: o365NewServiceMonitor.ps1 =========================================================================== .DESCRIPTION This Script will generate Alert if any new servioce in o365 is added #> param ( [string]$LicenseSKU = $(Read-Host "Enter License SKU"), [string]$smtpserver = $(Read-Host "Enter SMTP Server"), [string]$from = $(Read-Host "Enter From Address"), [string]$erroremail = $(Read-Host "Enter Address for Report and Errors"), [string]$userId = $(Read-Host "Enter UserID of the account that has access to MSOL"), [array]$email= $(Read-Host "Enter Address for Email Report") ) function Write-Log { [CmdletBinding()] param ( [Parameter(Mandatory = $true,ParameterSetName = 'Create')] [array]$Name, [Parameter(Mandatory = $true,ParameterSetName = 'Create')] [string]$Ext, [Parameter(Mandatory = $true,ParameterSetName = 'Create')] [string]$folder, [Parameter(ParameterSetName = 'Create',Position = 0)][switch]$Create, [Parameter(Mandatory = $true,ParameterSetName = 'Message')] [String]$Message, [Parameter(Mandatory = $true,ParameterSetName = 'Message')] [String]$path, [Parameter(Mandatory = $false,ParameterSetName = 'Message')] [ValidateSet('Information','Warning','Error')] [string]$Severity = 'Information', [Parameter(ParameterSetName = 'Message',Position = 0)][Switch]$MSG ) switch ($PsCmdlet.ParameterSetName) { "Create" { $log = @() $date1 = Get-Date -Format d $date1 = $date1.ToString().Replace("/", "-") $time = Get-Date -Format t $time = $time.ToString().Replace(":", "-") $time = $time.ToString().Replace(" ", "") foreach ($n in $Name) {$log += (Get-Location).Path + "\" + $folder + "\" + $n + "_" + $date1 + "_" + $time + "_.$Ext"} return $log } "Message" { $date = Get-Date $concatmessage = "|$date" + "| |" + $Message +"| |" + "$Severity|" switch($Severity){ "Information"{Write-Host -Object $concatmessage -ForegroundColor Green} "Warning"{Write-Host -Object $concatmessage -ForegroundColor Yellow} "Error"{Write-Host -Object $concatmessage -ForegroundColor Red} } Add-Content -Path $path -Value $concatmessage } } } #Function Write-Log function ProgressBar { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] $Title, [Parameter(Mandatory = $true)] [int]$Timer ) For ($i = 1; $i -le $Timer; $i++) { Start-Sleep -Seconds 1; Write-Progress -Activity $Title -Status "$i" -PercentComplete ($i /10 * 100) } } function LaunchMSOL { param ( $UserCredential ) Import-Module msonline Write-Host "Enter MS Online Credentials" -ForegroundColor Green Connect-MsolService -Credential $UserCredential } Function RemoveMSOL {Write-Host "Close Powershell Window - No disconnect available" -ForegroundColor yellow} #################Check if logs folder is created#### $logpath = (Get-Location).path + "\logs" $testlogpath = Test-Path -Path $logpath if($testlogpath -eq $false) { ProgressBar -Title "Creating logs folder" -Timer 10 New-Item -Path (Get-Location).path -Name Logs -Type directory } $Reportpath = (Get-Location).path + "\Report" $testlogpath = Test-Path -Path $Reportpath if($testlogpath -eq $false) { ProgressBar -Title "Creating Report folder" -Timer 10 New-Item -Path (Get-Location).path -Name Report -Type directory } ####################Load variables and log########## $log = Write-Log -Name "o365ServiceChange-Log" -folder "logs" -Ext "log" $licenseskupsplit = $LicenseSKU -split ":" $chgreport = "ChangeReport" + $licenseskupsplit[1] $ChangeReport = Write-Log -Name $chgreport -folder Report -Ext csv $staticReport = (Get-Location).Path + "\Report\" + $licenseskupsplit[1] + "staticreport.csv" ##################Userid & password################# $encrypted1 = Get-Content -Path .\password1.txt $pwd = ConvertTo-SecureString -String $encrypted1 $Credential = New-Object System.Management.Automation.PSCredential -ArgumentList $userId, $pwd #################Start Script####################### Write-Log -Message "Start script" -path $log try { LaunchMSOL -UserCredential $Credential Write-Log -Message "loaded.... MSOL" -path $log } catch { $exception = $_.Exception Write-Log -Message "Error loading MSOL" -path $log -Severity Error Write-Log -Message $exception -path $log -Severity error Send-MailMessage -SmtpServer $smtpserver -From $from -To $erroremail -Subject "Error has occured in connecting to o365NewServiceMonitor" -Body $($_.Exception.Message) exit; } $testpath = Test-Path -Path $staticReport if($testpath -eq $false){ try{ Write-Log -Message "Extarct Services from $LicenseSKU - First time" -path $log $colllicsku=Get-MsolAccountSku | where{$_.AccountSKUID -eq $LicenseSKU} | select ServiceStatus $colllicsku.ServiceStatus.serviceplan | select servicename | export-csv $staticReport -NoTypeInformation } catch{ $exception = $_.Exception Write-Log -Message "Error Extarct Services from $LicenseSKU" -path $log -Severity Error Write-Log -Message $exception -path $log -Severity error Send-MailMessage -SmtpServer $smtpserver -From $from -To $erroremail -Subject "Error has occured Extarct Services from $LicenseSKU o365NewServiceMonitor" -Body $($_.Exception.Message) exit; } } else { try{ Write-Log -Message "Extarct Services from $LicenseSKU - For Comparison" -path $log $colllicsku=Get-MsolAccountSku | where{$_.AccountSKUID -eq $LicenseSKU} | select ServiceStatus $collicreport = $colllicsku.ServiceStatus.serviceplan | select servicename $Changes = Compare-Object -ReferenceObject $collicreport -DifferenceObject $(Import-Csv $staticReport) -Property servicename | Select-Object -Property servicename, @{ n = 'State' e = {If ($_.SideIndicator -eq "=>"){"Removal" } Else { "Addition" }} } if($Changes){ $Changes | Export-Csv $ChangeReport -NoTypeInformation Write-Log -Message "Sending changes $LicenseSKU - For Comparison" -path $log Send-MailMessage -SmtpServer $SmtpServer -From $From -To $email -bcc $erroremail -Subject "o365 Services Change Monitor" -Body "o365 Services Change Monitor" -Attachments $ChangeReport $collicreport | select servicename | export-csv $staticReport -NoTypeInformation } } catch{ $exception = $_.Exception Write-Log -Message "Error Compare Services from $LicenseSKU" -path $log -Severity Error Write-Log -Message $exception -path $log -Severity error Send-MailMessage -SmtpServer $smtpserver -From $from -To $erroremail -Subject "Error has occured Compare Services from $LicenseSKU o365NewServiceMonitor" -Body $($_.Exception.Message) } } ########################Recycle reports & logs############## Write-Log -Message "Recycle Logs and reports" -path $log $path1 = (Get-Location).path + "\report\" $path2 = (Get-Location).path + "\Logs\" $limit = (Get-Date).AddDays(-60) #for report recycling Get-ChildItem -Path $path1 | Where-Object -FilterScript {$_.CreationTime -lt $limit} | Remove-Item -Recurse -Force Get-ChildItem -Path $path2 | Where-Object -FilterScript {$_.CreationTime -lt $limit} | Remove-Item -Recurse -Force Write-Log -Message "Script Finished" -path $log Send-MailMessage -SmtpServer $smtpserver -From $from -To $erroremail -Subject "Transcript Log - $LicenseSKU o365NewServiceMonitor" -Body "Transcript Log - $LicenseSKU o365NewServiceMonitor" -Attachments $log ########################################################################