API'nizi PowerShell Graph API'sine dönüştürme
Microsoft Graph API, Azure AD ve Office 365'in neredeyse her yönünü tek bir REST API uç noktası altında okumanıza, değiştirmenize ve yönetmenize olanak tanıyan bir hizmettir. Bu makalede API'nizi PowerShell Graph API'sine nasıl dönüştüreceğinizi öğrenin.
Önkoşullar
Bu makaleyi benimle birlikte takip etmek istiyorsanız öncelikle aşağıdaki kriterleri karşıladığınızdan emin olun:
- Windows PowerShell 5.1 çalıştırma (Bu, test ettiğim sürümdür. Diğer sürümler çalışabilir ancak garanti edilmez)
- Azure kiracısı
- Abonelikte genel yönetici izinlerine veya uygulama kayıt izinlerine sahip bir hesapla ve uygulama kayıt isteklerinizi kabul edecek genel bir yöneticiyle Azure'da kimliği doğrulanmıştır.
Microsoft Graph API için Uygulama Kimliği Oluşturma
Microsoft Graph API'ye erişmek için öncelikle bir OAuth belirteci almak üzere bir kimliğe ihtiyacınız vardır. Bu öncelikle Azure Portal'da oluşturabileceğiniz bir uygulama kimliğiyle yapılır. Azure portalı aracılığıyla bir uygulama kimliği oluşturabilirsiniz. Böyle yaparak:
- Azure Portal'a gidin ve Azure Active Directory'ye gidin.
- Soldaki menüdeki Yönet altında Uygulama Kayıtları'nı tıklayın ve Yeni kayıt düğmesini tıklayın.
- Uygulamanız için bir ad girin ve Kaydol'u tıklayın.
- Uygulama Kimliği kılavuzunu daha sonra kullanmak üzere kopyalayın.
Microsoft Graph API'si için Gizli Diziler Oluşturma
Graph API'de iki ana yöntemle kimlik doğrulaması yapabilirsiniz: AppId/Secret ve sertifika tabanlı kimlik doğrulama. PowerShell ile grafik API'sine bağlanırken kimlik doğrulamanız gerekecektir.
Her iki yöntemle de kimlik doğrulamanın nasıl yapılacağını ele alalım.
Uygulama Kimliği/Gizli
Bir uygulama kimliği/sırrı, normal bir kullanıcı adı/şifre gibidir. Uygulama kimliği, kullanıcı adı yerine bir GUID'den oluşur ve parola yalnızca rastgele bir dizedir.
Bir sır oluşturmak için soldaki menüde Sertifikalar ve sırlar'ı tıklayın ve Yeni müşteri sırrı'na basın.
Sır için bir açıklama girin ve süresinin ne zaman dolmasını istediğinizi seçin. Artık istediğiniz verilere erişebilmeniz için izin istemeniz yeterli.
Sertifika
Kendinden imzalı bir sertifika oluşturma ve bunun ortak anahtarını Azure'a yükleme olanağı vardır. Bu, kimlik doğrulamanın tercih edilen ve daha güvenli yoludur.
Öncelikle kendinden imzalı bir sertifika oluşturmanız gerekir. Neyse ki bu PowerShell ile kolayca yapılabilir.
# Your tenant name (can something more descriptive as well)
$TenantName = "contoso.onmicrosoft.com"
# Where to export the certificate without the private key
$CerOutputPath = "C:\Temp\PowerShellGraphCert.cer"
# What cert store you want it to be in
$StoreLocation = "Cert:\CurrentUser\My"
# Expiration date of the new certificate
$ExpirationDate = (Get-Date).AddYears(2)
# Splat for readability
$CreateCertificateSplat = @{
FriendlyName = "AzureApp"
DnsName = $TenantName
CertStoreLocation = $StoreLocation
NotAfter = $ExpirationDate
KeyExportPolicy = "Exportable"
KeySpec = "Signature"
Provider = "Microsoft Enhanced RSA and AES Cryptographic Provider"
HashAlgorithm = "SHA256"
}
# Create certificate
$Certificate = New-SelfSignedCertificate @CreateCertificateSplat
# Get certificate path
$CertificatePath = Join-Path -Path $StoreLocation -ChildPath $Certificate.Thumbprint
# Export certificate without private key
Export-Certificate -Cert $CertificatePath -FilePath $CerOutputPath | Out-NullŞimdi, $CerOutputPath'e aktardığınız kendinden imzalı sertifikayı, sol menüdeki Sertifikalar ve sırlar'a tıklayıp Sertifika yükle'ye basarak Azure Uygulamanıza yükleyin. .
Uygulamaya izinler ekleme
Uygulamaya uygun izinlerin verilmesi yalnızca uygulamanızın işlevselliği açısından değil aynı zamanda güvenlik açısından da önemlidir. Bununla ilgili bilgi ve Microsoft Graph API'sindeki (neredeyse) diğer her şey belgelerde bulunabilir.
Bu kurulumu tamamladıktan sonra tüm güvenlik olaylarını kiracımdan toplayacağım. Bunu yapabilmem için minimum izin olarak SecurityEvents.Read.All'e ihtiyacım var. Bununla İmkansız Seyahat olaylarını, VPN/TOR aracılığıyla bağlanan kullanıcıları vb. toplayıp bunlar hakkında harekete geçebiliyorum.
SecurityEvents.Read.All'i uygulamanıza eklemek için - API İzinleri'ni ve ardından İzin Ekle'yi tıklayın. Bu size yalnızca Graph API'yi değil aynı zamanda Azure'daki bir sürü başka uygulamayı da sunacaktır. Microsoft Graph API'sine nasıl bağlanacağınızı öğrendikten sonra bu uygulamaların çoğuna bağlanmak kolaydır.
Microsoft Graph > Uygulama İzinleri > Güvenlik Olayları'nı tıklayın ve SecurityEvents.Read.All'i kontrol edin. Bundan sonra İzin Ekle düğmesine basın.
Bu izinde Yönetici izni gerekli sütununun Evet olarak ayarlandığını gördünüz mü? Bu, izin uygulamaya eklenmeden önce kiracı yöneticisinin onaylaması gerektiği anlamına gelir.
Genel yöneticiyseniz Yönetici izni ver seçeneğine basın veya Genel Yöneticiden bunu onaylamasını isteyin. Yalnızca okuma/yazma iznini ayarlamak için yönetici yerine kullanıcıdan izin istemek, OAuth kimlik doğrulamasının büyük bir parçasıdır. Ancak bu, Microsoft Graph'taki çoğu izin için bunu atlamamıza olanak tanır.
Muhtemelen bunu Facebook'ta veya Google'da zaten görmüşsünüzdür: "X uygulamasının profilinize erişmesine izin veriyor musunuz?"
Artık hazırsınız; hadi giriş yapıp biraz veri alalım!
Erişim Belirteci Edinme (Uygulama Kimliği ve Sırrı)
Bunun için bir Microsoft Graph OAuth uç noktasından erişim belirteci almak üzere bir istek göndermemiz gerekecek. Ve bu talebin metninde şunları sağlamamız gerekiyor:
client_id- Uygulama Kimliğiniz - url kodluclient_secret- Uygulamanızın sırrı - url kodlukapsam- Neye erişmek istediğinizi belirten URL kodlu bir URLgrant_type- Hangi kimlik doğrulama yöntemini kullanıyorsunuz?
Uç noktanın URL'si https://login.microsoftonline.com/
# Define AppId, secret and scope, your tenant name and endpoint URL
$AppId = '2d10909e-0396-49f2-ba2f-854b77c1e45b'
$AppSecret = 'abcdefghijklmnopqrstuv12345'
$Scope = "https://graph.microsoft.com/.default"
$TenantName = "contoso.onmicrosoft.com"
$Url = "https://login.microsoftonline.com/$TenantName/oauth2/v2.0/token"
# Add System.Web for urlencode
Add-Type -AssemblyName System.Web
# Create body
$Body = @{
client_id = $AppId
client_secret = $AppSecret
scope = $Scope
grant_type = 'client_credentials'
}
# Splat the parameters for Invoke-Restmethod for cleaner code
$PostSplat = @{
ContentType = 'application/x-www-form-urlencoded'
Method = 'POST'
# Create string by joining bodylist with '&'
Body = $Body
Uri = $Url
}
# Request the token!
$Request = Invoke-RestMethod @PostSplatErişim Jetonu Alın (Sertifika Kullanarak)
Sertifikayla Microsoft Graph API'sinin kimlik doğrulaması, normal AppId/Secret akışından biraz farklıdır. Sertifika kullanarak erişim belirteci almak için şunları yapmanız gerekir:
- Bir Java Web Token (JWT) başlığı oluşturun.
- Bir JWT yükü oluşturun.
- JWT üstbilgisini VE yükünü önceden oluşturulan kendinden imzalı sertifikayla imzalayın. Bu, Microsoft Graph erişim belirteci istemek için kullanılan, kendi kendine oluşturulmuş bir erişim belirteci oluşturacaktır.
- Aşağıdakileri içeren bir istek gövdesi oluşturun:
client_id=<application id>client_assertion=<the JWT>client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearerscope=<URLEncoded scope>grant_type=client_credentials- Başlığında
Authorization=ile gövde ile oauth uç noktasına bir gönderi isteği yapın.
Bunun nasıl yapılacağı Microsoft'un belgelerinde açık değildi ancak işte bunu gerçekleştirmek için PowerShell betiği:
$TenantName = "<your tenant name>.onmicrosoft.com"
$AppId = "<your application id"
$Certificate = Get-Item Cert:\CurrentUser\My\<self signed and uploaded cert thumbprint>
$Scope = "https://graph.microsoft.com/.default"
# Create base64 hash of certificate
$CertificateBase64Hash = [System.Convert]::ToBase64String($Certificate.GetCertHash())
# Create JWT timestamp for expiration
$StartDate = (Get-Date "1970-01-01T00:00:00Z" ).ToUniversalTime()
$JWTExpirationTimeSpan = (New-TimeSpan -Start $StartDate -End (Get-Date).ToUniversalTime().AddMinutes(2)).TotalSeconds
$JWTExpiration = [math]::Round($JWTExpirationTimeSpan,0)
# Create JWT validity start timestamp
$NotBeforeExpirationTimeSpan = (New-TimeSpan -Start $StartDate -End ((Get-Date).ToUniversalTime())).TotalSeconds
$NotBefore = [math]::Round($NotBeforeExpirationTimeSpan,0)
# Create JWT header
$JWTHeader = @{
alg = "RS256"
typ = "JWT"
# Use the CertificateBase64Hash and replace/strip to match web encoding of base64
x5t = $CertificateBase64Hash -replace '\+','-' -replace '/','_' -replace '='
}
# Create JWT payload
$JWTPayLoad = @{
# What endpoint is allowed to use this JWT
aud = "https://login.microsoftonline.com/$TenantName/oauth2/token"
# Expiration timestamp
exp = $JWTExpiration
# Issuer = your application
iss = $AppId
# JWT ID: random guid
jti = [guid]::NewGuid()
# Not to be used before
nbf = $NotBefore
# JWT Subject
sub = $AppId
}
# Convert header and payload to base64
$JWTHeaderToByte = [System.Text.Encoding]::UTF8.GetBytes(($JWTHeader | ConvertTo-Json))
$EncodedHeader = [System.Convert]::ToBase64String($JWTHeaderToByte)
$JWTPayLoadToByte = [System.Text.Encoding]::UTF8.GetBytes(($JWTPayload | ConvertTo-Json))
$EncodedPayload = [System.Convert]::ToBase64String($JWTPayLoadToByte)
# Join header and Payload with "." to create a valid (unsigned) JWT
$JWT = $EncodedHeader + "." + $EncodedPayload
# Get the private key object of your certificate
$PrivateKey = $Certificate.PrivateKey
# Define RSA signature and hashing algorithm
$RSAPadding = [Security.Cryptography.RSASignaturePadding]::Pkcs1
$HashAlgorithm = [Security.Cryptography.HashAlgorithmName]::SHA256
# Create a signature of the JWT
$Signature = [Convert]::ToBase64String(
$PrivateKey.SignData([System.Text.Encoding]::UTF8.GetBytes($JWT),$HashAlgorithm,$RSAPadding)
) -replace '\+','-' -replace '/','_' -replace '='
# Join the signature to the JWT with "."
$JWT = $JWT + "." + $Signature
# Create a hash with body parameters
$Body = @{
client_id = $AppId
client_assertion = $JWT
client_assertion_type = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"
scope = $Scope
grant_type = "client_credentials"
}
$Url = "https://login.microsoftonline.com/$TenantName/oauth2/v2.0/token"
# Use the self-generated JWT as Authorization
$Header = @{
Authorization = "Bearer $JWT"
}
# Splat the parameters for Invoke-Restmethod for cleaner code
$PostSplat = @{
ContentType = 'application/x-www-form-urlencoded'
Method = 'POST'
Body = $Body
Uri = $Url
Headers = $Header
}
$Request = Invoke-RestMethod @PostSplatErişim Jetonu Çıkışını İstemeyi Anlama
Uygulama kimliği/gizli dizi veya sertifika aracılığıyla bir erişim belirteci aldıktan sonra dört özelliğe sahip bir nesne görmelisiniz.
token_type- Ne tür bir jeton?expires_in- Erişim belirtecinin geçerli olduğu saniye cinsinden süreext_expires_in-expires_ingibi ancak belirteç hizmeti kesintisi durumunda esneklik içinaccess_token- Ne için geldik?
Daha sonra token_type ve access_token kullanarak bir başlık oluşturacak ve PowerShell ile Microsoft Graph API'sine istekte bulunmaya başlayacaksınız.
Microsoft Graph API'sine İstekte Bulunma
Şimdi API'ye bazı isteklerde bulunmaya başlayın.
Örneğimize göre, öncelikle güvenlik uyarılarını listelemek için URL'ye ihtiyacınız olacak. Neyin gerekli olduğunu görmek için Microsoft Graph API belgelerini kullanmayı unutmayın.
Bu durumda, Authorization=Bearer içeren bir başlığa ve Graph API Alerts uç noktasına yönelik bir GET isteğine ihtiyacınız vardır. Bunu PowerShell ile nasıl yapacağınız aşağıda açıklanmıştır.
# Create header
$Header = @{
Authorization = "$($Request.token_type) $($Request.access_token)"
}
$Uri = "https://graph.microsoft.com/v1.0/security/alerts"
# Fetch all security alerts
$SecurityAlertsRequest = Invoke-RestMethod -Uri $Uri -Headers $Header -Method Get -ContentType "application/json"
$SecurityAlerts = $SecurityAlertsRequest.ValueArtık $SecurityAlerts değişkeninde herhangi bir güvenlik uyarınız varsa, bunun şöyle görünmesi gerekir:
$SecurityAlerts | select eventDateTime,Title
eventDateTime title
------------- -----
2019-08-05T17:59:47.6271981Z Atypical travel
2019-08-05T08:23:01.7325708Z Anonymous IP address
2019-08-05T08:23:55.5000456Z Anonymous IP address
2019-08-04T22:06:51.063797Z Anonymous IP address
2019-08-04T21:56:10.981437Z Anonymous IP address
2019-08-08T09:30:00Z Creation of forwarding/redirect rule
2019-07-19T13:30:00Z eDiscovery search started or exported
2019-07-19T08:00:00Z eDiscovery search started or exportedTek bir güvenlik uyarısını JSON olarak incelemek şu şekilde görünecektir:
"id": "censored",
"azureTenantId": "censored",
"azureSubscriptionId": "censored",
"riskScore": null,
"tags": [
],
"activityGroupName": null,
"assignedTo": null,
"category": "AnonymousLogin",
"closedDateTime": null,
"comments": [
],
"confidence": null,
"createdDateTime": "2019-08-08T09:46:59.65722253Z",
"description": "Sign-in from an anonymous IP address (e.g. Tor browser, anonymizer VPNs)",
"detectionIds": [
],
"eventDateTime": "2019-08-08T09:46:59.65722253Z",
"feedback": null,
"lastModifiedDateTime": "2019-08-08T09:54:30.7256251Z",
"recommendedActions": [
],
"severity": "medium",
"sourceMaterials": [
],
"status": "newAlert",
"title": "Anonymous IP address",
"vendorInformation": {
"provider": "IPC",
"providerVersion": null,
"subProvider": null,
"vendor": "Microsoft"
},
"cloudAppStates": [
],
"fileStates": [
],
"hostStates": [
],
"historyStates": [
],
"malwareStates": [
],
"networkConnections": [
],
"processes": [
],
"registryKeyStates": [
],
"triggers": [
],
"userStates": [
{
"aadUserId": "censored",
"accountName": "john.doe",
"domainName": "contoso.com",
"emailRole": "unknown",
"isVpn": null,
"logonDateTime": "2019-08-08T09:45:59.6174156Z",
"logonId": null,
"logonIp": "censored",
"logonLocation": "Denver, Colorado, US",
"logonType": null,
"onPremisesSecurityIdentifier": null,
"riskScore": null,
"userAccountType": null,
"userPrincipalName": "[email "
}
],
"vulnerabilityStates": [
]
}API Çıkış Sayfalamayı Anlama ve Yönetme
Microsoft Graph API'nin, işlev başına kaç öğe döndüreceğine ilişkin bir sınırı vardır. Bu sınır fonksiyon başınadır ancak 1000 öğe diyelim. Bu, isteğinizde yalnızca maksimum 1000 öğe alabileceğiniz anlamına gelir.
Bu sınıra ulaşıldığında, geri kalan öğeleri teslim etmek için çağrıyı kullanacaktır. Bunu isteğinizin cevabına @odata.nextLink özelliğini ekleyerek yapar. @odata.nextLink, isteğinizin sonraki sayfasına ulaşmak için arayabileceğiniz bir URL içerir.
Bu özelliği kontrol ederek ve bir döngü kullanarak tüm öğeleri okuyabilirsiniz:
$Uri = "https://graph.microsoft.com/v1.0/auditLogs/signIns"
# Fetch all security alerts
$AuditLogRequest = Invoke-RestMethod -Uri $Uri -Headers $Header -Method Get -ContentType "application/json"
$AuditLogs = @()
$AuditLogs+=$AuditLogRequest.value
while($AuditLogRequest.'@odata.nextLink' -ne $null) {
$AuditLogRequest += Invoke-RestMethod -Uri $AuditLogRequest.'@odata.nextLink' -Headers $Header -Method Get -ContentType "application/json"
}Çözüm
Graph API'de nasıl kimlik doğrulaması yapacağınızı öğrendikten sonra ondan veri toplamak oldukça kolaydır. Olması gerekenden çok daha az kullanılan güçlü bir hizmettir.
Neyse ki Microsoft Graph API'yi kullanmak için halihazırda birçok modül var ancak kendi ihtiyaçlarınızı karşılamak için kendi modülünüzü oluşturmanız gerekebilir. Bu makalede öğrendiğiniz becerileri kullanarak yolunuza devam etmelisiniz.
Office 365'te misafir erişimini kontrol etme hakkında daha fazla bilgi için blogumda detaylı bir makale yazdım, göz atmanızı tavsiye ederim.