Skip to content

In this episode, we discuss Microsoft Teams 5th anniversary, how we got here, and Microsoft Teams' most impactful things.

In this episode, the team discusses upcoming changes in M365 that will break your configuration if you don't act upon them.

  • Microsoft Teams Powershell Cmdlets for number management
  • Microsoft Teams SBC Direct Routing - Changes
  • Microsoft Teams Meeting recording expiration policy
  • IE 11 Expiration
  • Microsoft Exchange - Plus Addressing
  • Microsoft Exchange - API Retirements
  • Microsoft Exchange - Anti-Malware policy - Quarantine notifications for recipient

**Update**

If you have a Direct Routing as a Service (DRaaS) user with a DID for which you need to remove that DID, you must run the Remove-CsPhoneNumberAssignment cmdlet for that user and then renenable them for EnterpriseVoice using Set-CsPhoneNumberAssignment -EnterpriseVoiceEnabled $True

This enables EV without assigning a DID which would be useful for users that don't require a DID or need to be an Agent in a Call Queue for example.

Happy New Year!!

In this episode, the team recaps 2021 and what we are looking forward to in 2022 both personally and in Microsoft 365.

In this episode, we talk to Enable UC Partners Kevin Keiller and our very own O365Eh co-host Dino Caputo about the approach and process to develop and publish a Microsoft Teams app. They have developed a Trivia application called Trivia Engine that allows participants to compete during challenges to answer the most questions correctly, as quickly as possible, for the best score. As they compete, they learn, and Trivia Engine allows you to track that learning progress.

Trivia Engine Website - https://www.triviaengine.com

Download link in Teams App Store - https://teams.microsoft.com/l/app/3bd813fa-a19a-4c06-b130-450b24b8ee08

Microsoft AppSource Listing - https://appsource.microsoft.com/en-US/product/office/wa200003412

In this episode, we talk about the November Ignite 2021 Announcements to Microsoft 365.

In our 100th episode, the team wanted to reflect on customer activities, what sessions we are excited about at Ignite Nov 2021 and what it feels like to return to in-person conferences.

In this episode, we talk about all things you need to know about the move from classic Microsoft Stream to new Stream.

New Stream

https://docs.microsoft.com/en-us/stream/streamnew/new-stream

Listing all the content you have in Classic Stream

https://techcommunity.microsoft.com/t5/microsoft-stream-forum/powershell-script-to-list-all-videos-in-your-365-stream/m-p/1752149

Permissions related challenges to sharing out content in the new stream

https://docs.microsoft.com/en-us/MicrosoftTeams/tmr-meeting-recording-change#permissions-or-role-based-access

Migration Phases

https://docs.microsoft.com/en-us/stream/streamnew/classic-migration

Office video migration

https://docs.microsoft.com/en-us/stream/migrate-from-office-365#newstreamimp

Stream roadmap

https://www.microsoft.com/en-gb/microsoft-365/roadmap?filters=Microsoft%20Stream

WOW 3 years have flown by, this latest episode the team recaps:

  • Our 2020 Episodes
  • How 2019 rolled into 2020
  • Key features from 2020
  • Looking forward into 2021

New intro music provided by Habib's son Mo.

In this episode, the team goes deeper into the discussion about Microsoft Teams templates.

  • Types of templates
  • Managing templates
  • Governance
  • Development

In this Episode, a follow up to Episode 71. The teams walks through the process of running Microsoft 365 DSC in Azure Automation.

What is MicrosoftDSC?

Microsoft365DSC is an Open-Source initiative hosted on GitHub, lead by Microsoft engineers and maintained by the community. It allows you to write a definition for how your Microsoft 365 tenant should be configured, automate the deployment of that configuration, and ensures the monitoring of the defined configuration, notifying and acting on detected configuration drifts. It also allows you to extract a full-fidelity configuration out of any existing Microsoft 365 tenant. The tool covers all major Microsoft 365 workloads such as Exchange Online, Teams, Power Platforms, SharePoint and Security and Compliance.

Why automate MicrosoftDSC using a runbook?

Ordinarily, you would need to run MicrosoftDSC manually or setup an “agent” on a server to monitor changes in your tenant (tenant drift) which can be cumbersome and not always practical for some environments.

Azure Automation is a service in Azure that allows you to automate your Azure management tasks and to orchestrate actions across external systems from right within Azure.

The following guide shows you what how to setup Microsoft DSC as an Azure runbook.  The runbook will monitor for changes in your Office 365 tenant an alert you when any changes do occur.

Getting everything setup in your Azure Tenant

Running MicrosoftDSC requires many prerequisite PowerShell Modules and dependencies to be installed into your Azure Tenant.  This quite a cumbersome process so we have created a script to simplify this. **Shout out to fellow MVP Barbara Forbes for the inspiration for this code - https://twitter.com/Ba4bes**

M365DSCRunBookInstall

Before running this you will need to do the following things:

  1. Get your Tenantid.  (use https://www.whatismytenantid.com/)
  2. Find your Azure SubscriptionID from the Azure Portal
  3. Create an Azure Automation Account - QuickStart Ref
  4. Create an Azure Resource Account
  5. Copy the script below into your a PowerShell window (as Administrator)

This will install all the required Microsoft 365 DSC Prerequisites PowerShell Modules to use within your automation RunBook.

install-module az.accounts
install-module az.automation

#Update the values below specific to your tenant!
$tenantID = "YOUR TENANTID HERE"
$subscriptionID = "YOUR SUBSCRIPTION ID HERE"
$automationAccount = "Your M365Automation Account Here"
$resourceGroup = "Your Azure Resource Group Here"

$moduleName = "Microsoft365dsc"
Connect-AzAccount -SubscriptionId $subscriptionID -Tenant $tenantID 

Function Get-Dependency {
#Function modifed from: https://4bes.nl/2019/09/05/script-update-all-powershell-modules-in-your-automation-account/
    param(
        [Parameter(Mandatory = $true)]
        [string] $ModuleName    
    )

    $OrderedModules = [System.Collections.ArrayList]@()
    
    # Getting dependencies from the gallery
    Write-Verbose "Checking dependencies for $ModuleName"
     $ModuleUri = "https://www.powershellgallery.com/api/v2/Search()?`$filter={1}&searchTerm=%27{0}%27&targetFramework=%27%27&includePrerelease=false&`$skip=0&`$top=40"
    $CurrentModuleUrl = $ModuleUri -f $ModuleName, 'IsLatestVersion'
    $SearchResult = Invoke-RestMethod -Method Get -Uri $CurrentModuleUrl -UseBasicParsing | Where-Object { $_.title.InnerText -eq $ModuleName }

    if ($null -eq $SearchResult) {
        Write-Output "Could not find module $ModuleName in PowerShell Gallery."
        Continue
    }
    $ModuleInformation = (Invoke-RestMethod -Method Get -UseBasicParsing -Uri $SearchResult.id)

    #Creating Variables to get an object
    $ModuleVersion = $ModuleInformation.entry.properties.version
    $Dependencies = $ModuleInformation.entry.properties.dependencies
    $DependencyReadable = $Dependencies -split ":\|"

    $ModuleObject = [PSCustomObject]@{
        ModuleName    = $ModuleName
        ModuleVersion = $ModuleVersion
    }
    
    # If no dependencies are found, the module is added to the list
    if (![string]::IsNullOrEmpty($Dependencies) ) {
        foreach ($dependency in $DependencyReadable){
            $DepenencyObject = [PSCustomObject]@{
                ModuleName    = $($dependency.split(':')[0])
                ModuleVersion = $($dependency.split(':')[1].substring(1).split(',')[0])
            }
            $OrderedModules.Add($DepenencyObject) | Out-Null
        }
    }

    $OrderedModules.Add($ModuleObject) | Out-Null

    return $OrderedModules
}

$ModulesAndDependencies = Get-Dependency -moduleName $moduleName
#$ModulesAndDependencies

write-output "Installing $($ModulesAndDependencies | ConvertTo-Json)"

#Install Module and Dependencies into Automation Account
foreach($module in $ModulesAndDependencies){
    $CheckInstalled = get-AzAutomationModule -AutomationAccountName $automationAccount -ResourceGroupName $resourceGroup -Name $($module.modulename) -ErrorAction SilentlyContinue
    if($CheckInstalled.ProvisioningState -eq "Succeeded" -and $CheckInstalled.Version -ge $module.ModuleVersion){
        write-output "$($module.modulename) existing: v$($CheckInstalled.Version), required: v$($module.moduleVersion)"
    }
    else{
        New-AzAutomationModule -AutomationAccountName $automationAccount -ResourceGroupName $resourceGroup -Name $($module.modulename) -ContentLinkUri "https://www.powershellgallery.com/api/v2/package/$($module.modulename)/$($module.moduleVersion)" -Verbose     
        While($(get-AzAutomationModule -AutomationAccountName $automationAccount -ResourceGroupName $resourceGroup -Name $($module.modulename)).ProvisioningState -eq 'Creating'){
            Write-output 'Importing $($module.modulename)...'
            start-sleep -Seconds 10
        }
    }
}

DSC PowerShell RunBook Sample

Here is the sample code as your Azure RunBook.  This can be scheduled to run on regular basis.

  1. Browse to your Azure Automation account.
  2. Under process automation, click Run Books.
  3. Create a new Azure RunBook, give it a name and make sure to select the runbook type asPowerShell.
  4. Edit the RunBook and copy the code below and paste it into your RunBook.
  5. In your Azure Automation Account, browse to shared resources -> credentials to add your credentials which will be used to execute the RunBook.
  6. Set the schedule for how often your Runbook executes
$creds = Get-AutomationPSCredential -Name "AutomationAccount"
$GitHubDSCConfig = 'https://raw.githubusercontent.com/YOURGITHUB/m365dscsample/main/GoldStandardDSCConfig.ps1'

$path = "$env:TEMP" 
$Date = $(Get-Date -f yyyy-MMM-dd-HHMMtt)

write-output "Pulling DSC from Tenant $Date" 
Export-M365DSCConfiguration -Quiet -Workloads @("TEAMS") -GlobalAdminAccount $creds -path $path -filename "runbook_$date.ps1" *>&1 | out-null

write-output "Pulling DSC from GitHub" 
Invoke-RestMethod -Uri $GitHubDSCConfig -OutFile "$path\dscconfig_$date.ps1"

write-output "Generating Delta Report`r`n" 
New-m365dscdeltareport -source "$path\dscconfig_$date.ps1" -destination "$path\runbook_$date.ps1" -OutputPath "$path\DeltaNew_$date.HTML" *>&1 | out-null

$readfile = Get-Content -path "$path\DeltaNew_$date.HTML"
write-output $readfile

write-output "Send Email"

$sendMailParams = @{
    Credential = $Creds
    From = $($Creds.username)
    To = 'habib@mydomain.com', 'michael@mydomain.com','dino@mydomain.com','curtis@mydomain.com'
    Subject = "DSC Delta Report - $Date"
    Body = "This is the delta report between your tenant and the Baseline Configuration $readfile"
    BodyasHtml = $true
    Attachments = "$path\DeltaNew_$date.HTML"
    SMTPServer = 'smtp.office365.com'
    Port = 587
    UseSsl = $true    
    DeliveryNotificationOption = 'OnFailure','OnSuccess'    
    Encoding = 'UTF8'
    Priority = 'High'
    EA = 'Stop'
}

Send-MailMessage @sendMailParams