Skip to the main content.

ScriptRunner Blog

Keine Chance für 'Wildwuchs'! Mit diesen Maßnahmen verhinderst du Teams Sprawl

Inhaltsverzeichnis

Post Featured Image

Möchtest du mehr über die Überwachung von Microsoft Teams mit PowerShell erfahren? Lies, wie du die Einstellungen im Laufe der Zeit auf Änderungen überprüfen kannst. Verhindere (oder korrigiere) Konfigurationsabweichungen.    

 

Wo fange ich an?

Bei Teams kann es zu unterschiedlichen Formen des "Wildwuchs" kommen. Hinter Teams sprawl verbirgt sich ein Ausufern oder Aufblähen von Teams, wenn z.B. für ein Projekt dezentral und unkoordiniert neue Teams angelegt werden, aber am Ende des Projektes nicht wieder gelöscht werden. Mit Creep wird die langsame Ausweitung von Umfang, Funktionalitäten, Rechten oder Konfiguration bezeichnet.  

Scope Creep, Configuration Creep, und Teams Sprawl haben alle ein gemeinsames Grundproblem – das Fehlen von Überwachung oder Kontrolle, um diese Änderungen zu verhindern. In diesem Artikel wird gezeigt, wie mit Hilfe von PowerShell Teams und Teams-Konfigurationen überwacht und Änderungen erkannt werden können. Aufgrund der Größe und Komplexität von Teams werden wir nicht jeden einzelnen Konfigurationsaspekt behandeln, sondern Administratoren einige Beispielen für die Verwendung von PowerShell an die Hand geben. Ein Musterbeispiel dafür findest du im Sicherheitscenter, dem Configuration Analyzer, der über eine Registerkarte "Drift Analysis" und "History" verfügt.   

 

Start

Wie bei jeder Verwendung von PowerShell-Skripten oder -Tools musst du sicherstellen, dass dein Microsoft Teams PowerShell-Modul mit der neuesten Version läuft: 


Update-Module MicrosoftTeams

TSchließe dann deine PowerShell-Sitzung, denn so wird sichergestellt, dass das PowerShell-Modul beim nächsten Mal mit der neuesten Version geladen wird.

Stelle sicher, dass deine Version die neueste ist:


Import-Module MicrosoftTeams
Get-Module MicrosoftTeams

Auch hier vergleichst du die Versionsnummer mit der verfügbaren Version (hier).

 

Welche Cmdlets empfehlenswert sind

Die Erstellung eines benutzerdefinierten Skripts zur Überprüfung einer Microsoft Teams-Konfiguration kann ausschließlich mit Get-*-Cmdlets erfolgen, da es sich hierbei um Discovery PowerShell-Cmdlets handelt, die Einstellungen und Objekte abfragen und die benötigten Details bereitstellen. Eine schnelle Liste dieser Cmdlets findest du mit diesem Einzeiler (sobald du mit dem Microsoft Teams PowerShell Endpunkt verbunden bist):


Get-Command Get-* | 
Where Source -eq MicrosoftTeams |
Sort Name |
ft Name

Wir werden nicht auf jedes einzelne der verfügbaren Cmdlets eingehen, da es über 150 davon gibt, aber wir werden einige ausgewählte Beispiele durchgehen, die dabei helfen, wichtige Elemente in Teams zur Überprüfung, also ein 'Audit' der Einstellungen zu finden.

 

Microsoft Teams und Teams-Kanäle

Liste der Teams

Die Anzahl und die Art der Teams ist ein wichtiger Aspekt bei der Überprüfung einer Teams-Konfiguration, denn Teams können sich über das hinaus ausbreiten, was eine Organisation erstellen oder pflegen wollte. Indem wir die Anzahl der Teams überprüfen, können wir das Wachstum und die Nutzung erkennen, bevor die Zahlen aus dem Ruder laufen. Zuerst wird die Anzahl der Teams abgefragt:


(Get-Team).Count

Das Ergebnis könnte so aussehen: 

01_get-team


Get-Team |
ft DisplayName,Visibility,Archived,GroupId

02_get-team results

 

Liste der Teams-Kanäle

Jedes Team kann einen oder mehrere Kanäle haben, über die es den Überblick behält:


Get-Team |
ForEach-Object {Write-Host $_.DisplayName -ForegroundColor Yellow ;Get-TeamChannel -GroupID $_.GroupID |
ft DisplayName,Membership*,Description}

 

03_list of team channels-1

Mit den obigen PowerShell Cmdlets konnten wir eine Menge Daten und Einstellungen über unsere Teams-Umgebung sammeln. Wie können wir diese Daten nutzen, um eine Umgebung wirklich zu überprüfen? Wir können beispielsweise Teams und Teams Channel Sprawl überwachen. In dem folgenden Beispiel überprüfen wir Teams und Teams-Kanäle jeden Monat, um zu sehen, was sich geändert hat:

 

Beispiel

Wenn die Anzahl der Teams und Channels zum ersten Mal überprüft wird, gibt es vielleicht 35 Teams und 56 Channels. Wenn die Cmdlets dann beispielsweise nach einem Monat erneut ausgeführt werden, existieren bereits 40 Teams und 65 Channels. Wir können die ursprüngliche Anzahl wie folgt abrufen:


# Team count (Anzahl Teams) 
(Get-Team).Count

# Teams channel count (Anzahl Channels)
Get-Team |
Foreach-Object {$Channels = (Get-TeamChannel -GroupID $_.GroupID).Count;$TeamsChannelCount=$TotalChannels+$Channels}

Wir können diese Zahlen zu einem späteren Zeitpunkt planmäßig überprüfen:  


$TeamsCount = (Get-Team).Count
Get-Team |
Foreach-Object {$Channels = (Get-TeamChannel -GroupID $_.GroupID).Count;$TeamsChannelCount=$TotalChannels+$Channels}

 

Bericht Praxisbeispiel

Wenn wir die Anzahl der Teams und Team-Kanäle überprüfen wollen, brauchen wir eine Möglichkeit, die Werte zu speichern und sie mit den aktuellen Zahlen in Teams zu vergleichen.

Erster Durchlauf:


# Date column (Datumsspalte)
$CurrentMonth = Get-Date -Format "MM.yyyy"

# File header (Kopf)
"Date,TeamsCount,TeamsChannelCount" |
Out-File 'TeamsAndChannelCounts.csv'

# First month counts (Anzahl des ersten Monats)
$TeamsCount = (Get-Team).Count
Get-Team |
Foreach-Object {$Channels = (Get-TeamChannel -GroupID $_.GroupID).Count;$TeamsChannelCount=$TotalChannels+$Channels}
$Output = "$CurrentMonth,$TeamsCount,$TeamsChannelCount" |
Out-File 'TeamsAndChannelCounts.csv' -Append

 

Planmäßige Läufe, bei denen wir Datenreihen haben, die wir auf Unterschiede untersucht wollen:


# Import data (Daten importieren)
$TeamsData = Import-Csv .\TeamsAndChannelCounts.csv

# Last line (letzte Zeile)
$CurrentMonth = $TeamsData[-1]

# Next to last line to compare (vorletzte Zeile zum Vergleich)
$LastMonth = $TeamsData[-2]

# Check each Teams data point for change (überprüfe jeden Datensatz aus Teams auf Änderungen)
If ($CurrentMonth.TeamsCount -gt $LastMonth.TeamsCount) {Write-Host 'There are new Teams present.'}
If ($CurrentMonth.TeamsChannelCount -gt $LastMonth.TeamsChannelCount) {Write-Host 'There are new Teams Channels present.'}

 

Wenn wir etwas tiefer in die Trickkiste greifen wollen, können wir auch überprüfen, welche Teams seit dem letzten Mal neu hinzugekommen sind. Dazu können wir dies das erste Mal ausführen:


Get-Team | 
select DisplayName,Visibility,GroupId,Archived,Description |
Export-Csv -Path HistoricalTeams.csv

Wir können jeden Monat nach Änderungen suchen:


Get-Team | 
select DisplayName,Visibility,GroupId,Archived,Description |
Export-Csv -Path CurrentTeams.csv

Dann können wir diese beiden Dateien mit Compare-Object vergleichen:


$Historical = Get-Content .\HistoricalTeams.csv
$Current = Get-Content .\CurrentTeams.csv
Compare-Object -ReferenceObject $Historical -DifferenceObject $Current

 

In diesem Beispiel sehen wir, dass es zwei verschiedene Gruppen gibt, die neu sind, da der SideIndicator-Wert auf die Dateidaten in der Variable $Current verweist.  

04_inputobject

 

Ein weiterer Schritt, den wir mit der PowerShell ausführen können, ist das Ersetzen der Teams-Dateien aus der History durch die aktuellen, damit wir immer die neuesten Zahlen zum Vergleich haben:


Remote-Item HistoricalTeams.csv
Rename-Item CurrentTeams.csv HistoricalTeams.csv

 

Gastzugang

Innerhalb von Teams gibt es Kontrollen dafür, worauf ein Gast Zugriff hat, und wir können diese Einstellungen mit der PowerShell kontrollieren. Die Überwachung der Teams-Konfigurationsaspekte für Nutzer ist ein wichtiger Aspekt der Sicherheit deiner Teams-Konfiguration im Allgemeinen. Wir können dies mit der PowerShell untersuchen, um zu sehen, was wir entdecken und überwachen können.

Zuerst die PowerShell Cmdlets:


Get-Command Get-*team*guest*

Das liefert diese Cmdlets:


Get-CsTeamsGuestCallingConfiguration
Get-CsTeamsGuestMeetingConfiguration
Get-CsTeamsGuestMessagingConfiguration

Jedes dieser Cmdlets gibt Aufschluss über einen anderen Aspekt der Konfiguration. Mit der PowerShell können wir die Einstellungen dokumentieren und dann auf Änderungen hin vergleichen, genau wie wir es bei Teams und Channels gemacht haben.

 

Konfiguration der Gastanrufe

Nehmen wir zunächst die grundlegende Konfiguration zum Anrufen von Gast-Accounts in Angriff:


$CurrentMonth = Get-Date -Format "MM.yyyy"
$GuestCallingCfg = (Get-CsTeamsGuestCallingConfiguration).AllowPrivateCalling
$FileHeader = "Date,AllowPrivateCalling" |
Out-File 'GuestCallingConfiguration.csv'
$Output = "$CurrentMonth,$GuestCallingCfg" |
Out-File 'GuestCallingConfiguration.csv' -append

 

Hier gibt es nur einen wichtigen Wert. Wir können überprüfen, ob sich dieser Wert im Laufe der Zeit geändert hat und können das dann monatlich, vierteljährlich oder so wiederholen:


$CurrentMonth = Get-Date -Format "MM.yyyy"
$GuestCallingCfg = (Get-CsTeamsGuestCallingConfiguration).AllowPrivateCalling
$FileHeader = "Date,AllowPrivateCalling" |
Out-File 'GuestCallingConfiguration.csv'
$Output = "$CurrentMonth,$GuestCallingCfg" |
Out-File 'GuestCallingConfiguration-current.csv' -append

 

Dann können wir die beiden Ausgabedateien wie folgt vergleichen:


$Historical = Import-Csv GuestCallingConfiguration.csv
$Current = Import-Csv GuestCallingConfiguration-current.csv
$Historical.AllowPrivateCalling -eq $Current.AllowPrivateCalling

 

Bei einer Änderung würde das Ergebnis folgendermaßen aussehen:

05_historical

 

Konfiguration von Gastbesprechung

Als Nächstes haben wir die Konfiguration für Gastbesprechungen, die einige weitere Einstellungen enthält, die wir verwalten müssen. Zuerst müssen wir eine Baseline erstellen oder feststellen, was wir heute konfiguriert haben: 

Erster Lauf:


# Discover current configuration (aktuelle Konfiguration ermitteln)
$GuestMeeting = Get-CsTeamsGuestMeetingConfiguration |
Select AllowIPVideo,ScreenSharingMode,AllowMeetNow,LiveCaptionsEnabledType,AllowTranscription

# Create a Hash table output to be exported (Erstelle eine Hash-Tabelle, die exportiert werden soll)
$Hashtable = New-Object System.Collections.Hashtable
$Hashtable['AllowIPVideo'] = $GuestMeeting.AllowIPVideo
$Hashtable['ScreenSharingMode'] = $GuestMeeting.ScreenSharingMode
$Hashtable['AllowMeetNow'] = $GuestMeeting.AllowMeetNow
$Hashtable['LiveCaptionsEnabledType'] = $GuestMeeting.LiveCaptionsEnabledType
$Hashtable['AllowTranscription'] = $GuestMeeting.AllowTranscription

# Export $Hashtable variable to a CSV for comparison (Exportiere die Variable $Hashtable in eine CSV-Datei zum Vergleich)
$HashTable.GetEnumerator() |
Select-Object -Property Key,Value |  
Export-Csv -NoTypeInformation -Path GuestMeeting.csv

 

Dann können wir im Laufe der Zeit weitere Durchläufe [monatlich, vierteljährlich, jährlich] machen, die den gleichen Code wie oben verwenden, aber die Ausgabedatei in "GuestMeeting-Current.csv" ändern:


$HashTable.GetEnumerator() |  
Select-Object -Property Key,Value |  
Export-Csv -NoTypeInformation -Path GuestMeeting-Current.csv

 

Vergleiche die beiden Konfigurationen:


# Compare the original and current CSV files (Vergleiche die ursprüngliche mit der aktuellen CSV-Datei)
$CSV1 = Get-Content .\GuestMeeting.csv
$CSV2 = Get-Content .\GuestMeeting-Current.csv
Compare-Object $CSV1 $CSV2

 

Wenn ein Unterschied festgestellt wird, sollten wir etwas Ähnliches wie das hier sehen:

06_inputobject

 

Gast-Messaging-Konfiguration

Derselbe Prozess kann auch mit der Guest Messaging Configuration durchgeführt werden. Für unseren ersten Durchlauf können wir diesen Code verwenden:


# Discover current configuration (Aktuelle Konfiguration ermitteln)
$GuestMessaging = Get-CsTeamsGuestMessagingConfiguration |
Select AllowUserEditMessage,AllowUserDeleteMessage,AllowUserDeleteChat,AllowUserChat,AllowGiphy,GiphyRatingType,AllowMemes,AllowImmersiveReader,AllowStickers

# Create a Hash table output to be exported (Erstelle eine Hash-Tabelle, die exportiert werden soll)
$Hashtable = New-Object System.Collections.Hashtable
$Hashtable['AllowUserEditMessage'] = $GuestMessaging.AllowUserEditMessage
$Hashtable['AllowUserDeleteMessage'] = $GuestMessaging.AllowUserDeleteMessage
$Hashtable['AllowUserDeleteChat'] = $GuestMessaging.AllowUserDeleteChat
$Hashtable['AllowUserChat'] = $GuestMessaging.AllowUserChat
$Hashtable['AllowGiphy'] = $GuestMessaging.AllowGiphy
$Hashtable['GiphyRatingType'] = $GuestMessaging.GiphyRatingType
$Hashtable['AllowMemes'] = $GuestMessaging.AllowMemes
$Hashtable['AllowImmersiveReader'] = $GuestMessaging.AllowImmersiveReader
$Hashtable['AllowStickers'] = $GuestMessaging.AllowStickers
# Export $Hashtable variable to a CSV for comparison (Exportiere die Variable $Hashtable in eine CSV-Datei zum Vergleich)
$HashTable.GetEnumerator() |
Select-Object -Property Key,Value |  
Export-Csv -NoTypeInformation -Path GuestMessaging.csv

 

Nachfolgende Durchläufe: [Monatlich, Vierteljährlich, Jährlich]

Verwende den gleichen Code wie oben, aber ändere die Ausgabedatei in 'GuestMessaging-Current.csv':


$HashTable.GetEnumerator() |  
Select-Object -Property Key,Value |  
Export-Csv -NoTypeInformation -Path GuestMessaging-Current.csv

Vergleich:


# Compare the original and current CSV files (Vergleiche die ursprüngliche und die aktuelle CSV-Datei)
$CSV1 = Get-Content .\GuestMessaging.csv
$CSV2 = Get-Content .\GuestMessaging-Current.csv
Compare-Object $CSV1 $CSV2

 

Wenn ein Unterschied festgestellt wird, sollten wir etwas wie das hier sehen:

07_inputobject

Beachte, dass sich in dem obigen Vergleich zwei Werte geändert haben: AllowMemes und AllowStickers, und durch die Indikatoren (==>) ist die neue Konfiguration jetzt für beide Einstellungen 'True', während in der ursprünglichen Konfiguration (<==) beide auf 'False' gesetzt waren. 

 

Zwischenfazit

Bei jedem Audit-Prozess müssen Organisationen entscheiden, was sie im Auge behalten wollen, und das gilt auch für Teams-Konfigurationen. Die erforderlichen Tools hast du jetzt kennengelernt und kannst dir analog dazu deinen eigenen Audit-Prozess aufbauen. Jedes Unternehmen ist anders, und eine vollständige Abdeckung aller Einstellungen würde diesen Artikel zu lang machen – und die Wiederholung ist unnötig.

 

Zusätzliche Aufgaben – historische Daten

Wenn es nötig ist, die Konfiguration über einen längeren Zeitraum zu verfolgen, können wir auch historische Diagramme zur Überprüfung erstellen. Dazu exportieren wir die aktuellen Einstellungen und notieren ein Datum/Zeitstempel zu diesem Datensatz. Eine Beispieldatei, wann der jeweilige Datensatz wahr (true) war, könnte etwa so aussehen:


Month,AllowIPVideo,ScreenSharingMode,AllowMeetNow,LiveCaptionsEnabledType,AllowTranscription
07.2023,True,SingleApplication,True,DisabledUserOverride,False
08.2023,True,SingleApplication,False,DisabledUserOverride,False
09.2023,True,SingleApplication,False,DisabledUserOverride,False
10.2023,True,SingleApplication,True,DisabledUserOverride,False
11.2023,True,SingleApplication,True,DisabledUserOverride,False
12.2023,True,SingleApplication,False,DisabledUserOverride,False
01.2024,True,SingleApplication,True,DisabledUserOverride,False

Je nach den internen Abläufen in einer Organisation kann dies auf einer zentralen IT-Freigabe, in SharePoint oder per E-Mail an einen Verteiler geschickt werden, um die Aufmerksamkeit zu erhöhen. 

 

Auditing von Aktivitäten in Teams

Eine häufige Aufgabe von Administratoren ist das Auditing von Aktivitäten oder Aktionen. Dabei werden Protokolle und andere Daten untersucht, um die Ursache für ein Problem zu ermitteln und das Problem zu beheben. Außerdem kann das Auditing auch dazu verwendet werden, eine Aktivität von Microsoft Teams abzufragen. Dies kann dabei helfen, das allgemeine Aktivitätsniveau zu ermitteln oder festzustellen, wann ein bestimmter Dienst genutzt wurde. Im Hintergrund verwendet Microsoft ein Unified Log, das Informationen über die auf der Teams-Plattform durchgeführten Aktionen speichert: PowerShell und die Microsoft Defender Schnittstelle (Link zum PowerShell & Microsoft Defender interface).

Warum in der PowerShell? PowerShell bietet eine Flexibilität, die du in der grafischen Benutzeroberfläche vielleicht nicht findest. Wir können dies entweder in einer Jumpbox planen, die PowerShell-Skripte vor Ort ausführt, oder wir können dies in einem Azure Runbook tun, um die Ressourcen vor Ort zu minimieren. Oder wir können dies innerhalb von ScriptRunner als Teil einer Reihe von Administrationsaufgaben tun.


# First, connect to Exchange Online PowerShell (v3) (Verbinde dich zunächst mit der Exchange Online PowerShell (v3))
Connect-ExchangeOnline

# Retrieve Teams events - stored in the Unified Audit Log (Abrufen von Teams-Events - gespeichert im Unified Audit Log)
# Timeframe: Past 48 hours (Zeitrahmen: Letzte 48 Stunden)
$EndDate = Get-Date
$StartDate = $EndDate.AddDays(-2)

# All Teams events (Alle Teams-Ereignisse)
Search-UnifiedAuditLog -StartDate $StartDate -EndDate $EndDate -RecordType MicrosoftTeams

# Teams channels added (Hinzugefügte Teams-Kanäle)
Search-UnifiedAuditLog -StartDate $StartDate -EndDate $EndDate -RecordType MicrosoftTeams -Operations ChannelAdded

# Sensitivity Label changes (Änderungen an Sensitivity-Labeln)
Search-UnifiedAuditLog -StartDate $StartDate -EndDate $EndDate -RecordType MicrosoftTeams -Operations SensitivityLabelChanged

# Teams are deleted (gelöschte Teams)
Search-UnifiedAuditLog -StartDate $StartDate -EndDate $EndDate -RecordType MicrosoftTeams -Operations TeamDeleted

Als Verweis (Microsoft Learn Seiten): Teams activities

Wenn wir diese Cmdlets ausführen, sollten wir die folgende Ausgabe sehen:

08_teamsessionstarted

Beachte, dass dies nur einer von vielen Einträgen ist und zufällig der protokollierte Beginn einer Teams-Sitzung ist.

Neben diesen Vorgängen gibt es noch weitere Teams-Vorgänge, für die wir Daten abrufen können:


TeamsSessionStarted
MeetingParticipantDetail
MessageReadReceiptReceived
ReactedToMessage
MeetingDetail

 

Fazit

PowerShell bietet Administratoren die Möglichkeit, ihre eigenen Umgebungen zu überwachen, wenn andere Tools nicht vorhanden sind. In diesem Fall konnten wir die PowerShell nutzen, um die Einstellungen im Laufe der Zeit auf Änderungen zu überprüfen und sicherzustellen, dass es keine Konfigurationsabweichungen gibt. Falls doch, können wir mit einem groben Datumsstempel feststellen, wann die Änderung vorgenommen wurde. Mit der richtigen Kodierung können alle Konfigurationsaspekte von Microsoft Teams mit der PowerShell im Laufe der Zeit überwacht werden, sodass sich die Administratoren auf andere Aufgaben konzentrieren können. 

 

 

Good2know

Dein unverzichtbares Microsoft Teams PowerShell Cheat Sheet

Vereinfache und automatisiere deine Microsoft Teams-Verwaltung mit unserem 8-seitigen PowerShell Cheat Sheet für Microsoft Teams. Dieser praktische Leitfaden bietet dir Quick-Reference-Cmdlets und Codeschnipsel zur einfachen Verwaltung von Benutzern, Kanälen, Richtlinien und mehr. Ideal sowohl für Anfänger als auch für erfahrene Administratoren.

 Teams-Cheat-Sheet2024

 

Dein ultimatives PowerShell Cheat Sheet

Hole dir auch das andere CheatSheet und entfalte das volle Potential von PowerShell mit unserem praktischen Poster. Egal ob Anfänger oder erfahrener Profi, dieses Cheat Sheet ist darauf ausgelegt, dein Anlaufpunkt für die wichtigsten und am häufigsten verwendeten Cmdlets zu sein.

Das Poster gibt es zum Download und in Papierform.

 

Hol dir hier dein Poster!

 

 

Weiterführende Links

Zusammenhängende Posts

14 min read

Privacy Management mit PowerShell – hier kommen die wichtigsten Funktionen von Priva auf einen Blick

Kennst du Priva? Datenschutzmanagement, Datenschutzrichtlinien, Regeln und Subjektrechte-Anfragen (data subject rights...

5 min read

Happy System Administrator Appreciation Day!

Jeden letzten Freitag im Juli wird der System Administrator Appreciation Day gefeiert, einen besonderen Tag, der den...

8 min read

PowerShell 7: Was spricht für, was gegen den Umstieg?

Windows PowerShell 5.1 ist in der Regel vorinstalliert und der Standard – lohnt sich ein Wechsel auf PowerShell 7, oder...

Über den Autor: