Website-Suche

Verwendung der Microsoft Graph-API mit Powershell


Mit der Microsoft Graph-API haben Sie die Möglichkeit, über einen einzigen Endpunkt mit den sich ständig weiterentwickelnden Azure-Diensten zu interagieren: https://graph.microsoft.com. Wir werden mit Powershell, OAuth 2.0 und REST eine Verbindung zu Graph herstellen.

Registrieren Sie Ihre App

Um mit Graph interagieren zu können, müssen wir unsere App registrieren. Gehen Sie zu https://portal.azure.com/#blade/Microsoft_AAD_RegisteredApps/ApplicationsListBlade, um zu beginnen. Melden Sie sich mit Ihrem Konto an, das Ihrem Mieter zugeordnet ist. Fügen Sie eine neue App hinzu und geben Sie die folgenden Details ein:

  • Name > Geben Sie ihm einfach einen Namen

  • Anwendungstyp > Web-App/-API

  • Anmelde-URL > Spielt keine Rolle, also gehen wir zu: http://localhost:8000

Wählen Sie dann Ihre neu erstellte App aus und gehen Sie zu Erforderliche Berechtigungen. Hier fügen wir die Graph-API-Berechtigung hinzu. Je nachdem, worauf Sie zugreifen möchten, müssen Sie unterschiedliche Berechtigungen auswählen. Sie können dies später ändern, also klicken wir zunächst oben auf „Hinzufügen“, wählen „Microsoft Graph“ aus und wählen in Schritt 2 einfach „Lese- und Schreibzugriff auf das Benutzerprofil“ aus.

Der letzte Schritt besteht darin, einen Schlüssel zu erstellen, zu Schlüssel zu gehen, eine Schlüsselbeschreibung einzugeben und die Dauer auf festzulegen Läuft nie ab. Wenn Sie auf „Speichern“ klicken, wird der Wert (ClientSecret) nur einmal angezeigt, also schreiben Sie ihn „Fertig“, wenn er angezeigt wird.

Werden Sie ein ethischer Hacker, der Computersysteme wie Black-Hat-Hacker hacken und wie Sicherheitsexperten sichern kann.

Authentifizierung und Autorisierung

Um auf die Graph-API zugreifen zu können, benötigen wir einen Zugangscode. Wenn Sie zum ersten Mal mit der Rest- und Graph-API arbeiten, sollten Sie einige Dinge beachten:

  1. Um ein Zugriffstoken zu erhalten, benötigen Sie einen Autorisierungscode. Der Code ist nur 1 Stunde gültig, aber solange Ihr Aktualisierungstoken gültig ist, müssen Sie ihn nur alle 90 Tage erneuern.

  2. Das Zugriffstoken, das bei jeder Anfrage verwendet wird, ist nur 1 Stunde lang gültig. Sie können es mit dem Refresh-Token erneuern.

  3. Der Refresh-Token ist 14 Tage lang gültig.

Der erste Schritt besteht also darin, den Authentifizierungscode zu erhalten. Wir verwenden hierfür das folgende Skript. Führen Sie die Skripte aus mit:

GraphAPIGetAuthCode.ps1 -ClientId <clientId> -ClientSecret <clientSecret> -RedirectUrl <redirectUrl>

Der Authentifizierungscode wird in einer Textdatei am Stammverzeichnis des Skripts gespeichert. Auf diese Weise können wir später problemlos darauf zugreifen.

[CmdletBinding()]
PARAM(
	[parameter(ValueFromPipeline=$true,
				ValueFromPipelineByPropertyName=$true,
				Mandatory=$true)]
	[string]$ClientId,

	[parameter(ValueFromPipeline=$true,
				ValueFromPipelineByPropertyName=$true,
				Mandatory=$true)]
	[string]$ClientSecret,

	[parameter(ValueFromPipeline=$true,
				ValueFromPipelineByPropertyName=$true,
				Mandatory=$true)]
	[string]$RedirectUrl
)
BEGIN
{
	$ResourceUrl = "https://graph.microsoft.com"
}
PROCESS
{
	Function Get-AuthCode {
		Add-Type -AssemblyName System.Windows.Forms

		$form = New-Object -TypeName System.Windows.Forms.Form -Property @{Width=440;Height=640}
		$web  = New-Object -TypeName System.Windows.Forms.WebBrowser -Property @{Width=420;Height=600;Url=($url -f ($Scope -join "%20")) }

		$DocComp  = {
			$Global:uri = $web.Url.AbsoluteUri        
			if ($Global:uri -match "error=[^&]*|code=[^&]*") {$form.Close() }
		}
		$web.ScriptErrorsSuppressed = $true
		$web.Add_DocumentCompleted($DocComp)
		$form.Controls.Add($web)
		$form.Add_Shown({$form.Activate()})
		$form.ShowDialog() | Out-Null

		$queryOutput = [System.Web.HttpUtility]::ParseQueryString($web.Url.Query)
		$output = @{}
		foreach($key in $queryOutput.Keys){
			$output["$key"] = $queryOutput[$key]
		}

		$output
	}

	# UrlEncode the ClientID and ClientSecret and URL's for special characters 
	$clientIDEncoded = [System.Web.HttpUtility]::UrlEncode($ClientId)
	$clientSecretEncoded = [System.Web.HttpUtility]::UrlEncode($ClientSecret)
	$redirectUrlEncoded =  [System.Web.HttpUtility]::UrlEncode($RedirectUrl)
	$resourceUrlEncoded = [System.Web.HttpUtility]::UrlEncode($ResourceUrl)
	$scopeEncoded = [System.Web.HttpUtility]::UrlEncode("https://outlook.office.com/user.readwrite.all")

	# Get AuthCode
	$url = "https://login.microsoftonline.com/common/oauth2/authorize?response_type=code&redirect_uri=$redirectUrlEncoded&client_id=$clientID&resource=$resourceUrlEncoded&prompt=admin_consent&scope=$scopeEncoded"

	Get-AuthCode
	
	# Extract Access token from the returned URI
	$regex = '(?<=code=)(.*)(?=&)'
	$authCode = ($uri | Select-string -pattern $regex).Matches[0].Value

	# Store AuthCode
	Set-Content "$PSScriptRoot\AuthCode.txt" $authCode
}

Vielen Dank an Darren Robinson: https://gist.github.com/darrenjrobinson/b74211f98c507c4acb3cdd81ce205b4f#file-ps2graphapi-ps1

Holen Sie sich das Zugriffs- und Aktualisierungstoken

Mit dem Authentifizierungscode können wir das wichtige Zugriffstoken und das dringend benötigte Aktualisierungstoken erhalten. Da das Zugriffstoken nur 1 Stunde gültig ist, müssen wir sein Alter überprüfen und mit dem Aktualisierungstoken ein neues anfordern, wenn es abgelaufen ist.

Das folgende Skript speichert das Zugriffs- und Aktualisierungstoken in Textdateien im Stammverzeichnis des Skripts. Sie können es jederzeit ändern, um es nur in Variablen zu speichern. Beachten Sie jedoch, dass beim Schließen der Shell alles verschwunden ist und Sie mit dem Autorisierungscode erneut beginnen müssen.

Die Skripte prüfen den Zeitpunkt der letzten Änderung der Datei „accesstoken.txt“. Wenn sie älter als eine Stunde ist, fordern sie mit dem Aktualisierungstoken ein neues Zugriffstoken an. Wenn dies fehlschlägt, wird ein neuer Autorisierungscode angefordert und von vorne begonnen.

Ich verwende eine config.json-Datei, um meine ClientId, ClientSecret und RedirectUrl zu speichern, sodass Sie sie einfach ändern können.

Config.json

{
  "AppId": {
    "ClientId": "fa9d9d34-7a2a-****-****-************",
    "ClientSecret": "J/WDSKLjE+XC9G0+ASDHUen31/***********=",
    "RedirectUrl": "https://localhost:8000",
    "ResourceUrl": "https://graph.microsoft.com"
  }
}

ConnectTo-Graph

#----------------------------------------------------------[Declarations]----------------------------------------------------------

#Get the config file
$config = Get-Content $PSScriptRoot"\config.json" -Raw | ConvertFrom-Json

# Add System Web Assembly to encode ClientSecret
Add-Type -AssemblyName System.Web

# Encode ClientSecret
$clientSecretEncoded = [System.Web.HttpUtility]::UrlEncode($config.AppId.ClientSecret) 

# Get the accessToken
If ((Test-Path -Path $PSScriptRoot"\accessToken.txt") -ne $false) {
	$accessToken = Get-Content $PSScriptRoot"\accessToken.txt"
}

#---------------------------------------------------------[Initialisations]--------------------------------------------------------

# Check if the AccessToken is not older then 1 hour
If (($accessToken -eq $null) -or ((get-date) - (get-item $PSScriptRoot"\accessToken.txt").LastWriteTime).TotalHours -gt 1) {

	# Get the refreshToken
	$refreshToken = Get-Content $PSScriptRoot"\refreshToken.txt"

	$clientId = $config.AppId.ClientId
	$clientSecret = $config.AppId.clientSecret
	$redirectUrl = $config.AppId.RedirectUrl
	$resourceUrl = $config.AppId.ResourceUrl
	
	Try {
		$refreshBody = "grant_type=refresh_token&redirect_uri=$redirectUrl&client_id=$clientId&client_secret=$clientSecretEncoded&refresh_token=$refreshToken&resource=$resourceUrl"

		$Authorization = Invoke-RestMethod https://login.microsoftonline.com/common/oauth2/token `
			-Method Post -ContentType "application/x-www-form-urlencoded" `
			-Body $refreshBody `
			-UseBasicParsing
	}
	Catch {
		$webResponse = $_.Exception.Response
	}

	If ($webResponse -ne $null) {
		# Get Authorization code
		GraphAPIGetAuthCode.ps1 -ClientId $clientId -ClientSecret $clientSecret -RedirectUrl $redirectUrl   

		$authCode = get-content $PSScriptRoot"\authCode.txt"
		$body = "grant_type=authorization_code&redirect_uri=$redirectUrl&client_id=$clientId&client_secret=$clientSecretEncoded&code=$authCode&resource=$resourceUrl"

		$Authorization = Invoke-RestMethod https://login.microsoftonline.com/common/oauth2/token `
			-Method Post -ContentType "application/x-www-form-urlencoded" `
			-Body $body `
			-UseBasicParsing
	}

	# Store refreshToken
	Set-Content $PSScriptRoot"\refreshToken.txt" $Authorization.refresh_token

	# Store accessToken
	$accessToken = $Authorization.access_token
	Set-Content $PSScriptRoot"\accessToken.txt" $accessToken
} 

Aktuelles Datum mit Invoke-RestMethod aus Graph abrufen

Nachdem alles erledigt ist, können wir wie folgt mit Graph interagieren:

Invoke-RestMethod -Headers @{Authorization = "Bearer $accessToken"} `
                  -Uri  https://graph.microsoft.com/v1.0/me `
                  -Method Get

Sie können die Skripte hier herunterladen: https://github.com/ruudmens/SysAdminScripts/tree/master/Graph

Verwandte Artikel