最近由於疫情嘛,你們夥都在家裏工做。老闆隔三差五的讓我給他一些報告,好比最近SharePoint的用戶使用狀況啦,好比Office365 郵箱的收發頻率啦,還有Azure帳號的risky signin等等,這樣子可讓他更好地瞭解你們的工做強度(有沒有偷懶!)和系統安全性等等。 Azure和Office365都有現成的報表和圖像界面能夠搜索和下載這些資料,可是比較繁瑣,須要拿鼠標點半天,那麼有沒有自動化的可能呢?html
在網上搜了搜,沒有找到現成的PowerShell模塊和函數能夠用的,不過呢,豆子發現咱們能夠直接對Azure Graph 進行查詢獲取結果。 Azure Graph 是一個Azure 的 Rest API 接口,這個接口容許用戶經過http/https 的 get或者post請求能夠對O365,Azure AD,SharePoints,teams,Exchange等等服務直接進行讀寫操做。事實上,不少第三方的軟件,好比Veeam 365的備份功能,好比一些Azure App的 SSO的功能,都是就是經過這個API來和Azure進行互動的。豆子天然也是能夠用PowerShell來進行訪問的。shell
Graph提供了一個接口 https://graph.microsoft.com 來接受 http/https 的get/post 的請求。首先,用戶須要獲取一個有效的受權token來執行相關的操做的權限。簡單的說,爲了獲取這個Token,用戶須要在Azure Portal裏面建立一個application,而後受權相關的api 權限,而後用戶發送一個post請求給微軟的oauth服務,從而得到一個臨時的Token。
api的權限分爲application和 delegation的權限,前者表示我註冊的applciation自己具備的權限,後者表示我在這個application上登錄的用戶的權限,最終的有效權限則是二者的交集。不少常見服務的操做,既能夠經過application進行權限,也能夠經過delegation來受權,可是有些特殊的服務,好比安全方面的報告,Azure明確要求用戶具備P2以上的license才能夠操做,那麼就只能經過delegation來受權。api
關於具體的受權和驗證, Azure提供了多種方式,每種方式都有本身的應用場景,這裏豆子演示一個最經常使用的方式(也是我上面提到的經過delegation給指定用戶來受權)。安全
首先 登錄 Azure Portal,新建一個applicationapp
註冊一個新的 application, redirect url 能夠隨便寫一個,這個主要是取決於驗證方式,若是不用這種驗證方式,能夠不寫ide
註冊以後,記錄一下 Application(Client) ID,這個至關於application的用戶名
函數
咱們再給這個application 建立一個 secrets,這個至關於這個application的密碼post
接下來,在API permissions裏面給這個application受權。他默認只有 Graph的 delegated的User.Read 權限測試
咱們能夠添加新的權限,選擇 Microsoft Graphui
這裏咱們選擇 Delegation ,這樣受權生成Token的時候,他會經過個人用戶的權限進行受權
接下來是重點,到底須要什麼權限呢?這個權限咱們須要查看Graph的API 手冊,他會告訴每個操做對應的權限。好比我想查看安全警告,那麼我搜索 Security的Alert的操做, 原來我須要添加下面的權限
https://docs.microsoft.com/en-us/graph/api/alert-get?view=graph-rest-1.0&tabs=http
添加以後,點擊 Grant admin consent
準備工做就作好了,接下來看看咱們的PowerShell 代碼。
下面代碼會生成對應的Token,替換掉對應的參數便可。這段代碼其實就是把application的用戶名和密碼,個人用戶的用戶名和密碼一塊兒發送出去,獲取到一個臨時權限的Token。
$clientId = "f4b6b7ec-68f3-420a-bd7e-bc6fe5a918d1" $tenantName = "abc.com.au" $clientSecret = "~mFs5EX4Fv9-82OsseQxhH.n0Su8L_Ei-7" $resource = "https://graph.microsoft.com/" $username='admin@test.com' $password='SafeappPassword@' $ReqTokenBody = @{ Grant_Type = "Password" client_Id = $clientID Client_Secret = $clientSecret Username = $Username Password = $Password Scope = "https://graph.microsoft.com/.default" } $TokenResponse = Invoke-RestMethod -Uri "https://login.microsoftonline.com/$TenantName/oauth2/v2.0/token" -Method POST -Body $ReqTokenBody
接下來的操做就很簡單了
我想獲取最新的安全警告,對應的API文檔以下
https://docs.microsoft.com/en-us/graph/api/alert-list?view=graph-rest-1.0&tabs=http
PowerShell 發送請求,得到結果,我過濾一下,輸出結果
$data=(Invoke-RestMethod -uri "https://graph.microsoft.com/v1.0/security/alerts" -Headers @{Authorization = "Bearer $($Tokenresponse.access_token)"} -Method Get) $data.value | Where-Object {$_.severity -notlike '*low*'} | select eventDateTime,Category, severity, title, userStates | ft
再看幾個例子
相似的操做,咱們能夠查看API的手冊,添加對應的application permission,而後執行不一樣請求。
好比 我想查看90天內全部用戶對SharePoint的訪問狀況,先添加Reports.Read.All的權限
而後執行
$data=(Invoke-RestMethod -uri "https://graph.microsoft.com/v1.0/reports/getSharePointActivityUserDetail(period='D90')" -Headers @{Authorization = "Bearer $($Tokenresponse.access_token)"} -Method Get) -replace "", "" $data | ConvertFrom-Csv | ft
再好比,我想查看 全部人的郵箱使用狀況,發送了多少郵件,接受了多少郵件,一樣的先添加權限
而後執行代碼,查看7天內的狀況
$data=(Invoke-RestMethod -uri "https://graph.microsoft.com/v1.0/reports/getEmailActivityUserDetail(period='D7')" -Headers @{Authorization = "Bearer $($Tokenresponse.access_token)"} -Method Get) -replace "", "" $data | ConvertFrom-Csv | out-gridview
有的時候,可能以爲查看API手冊不是太方便,微軟提供了一個更便捷的方式,用戶能夠直接訪問 Graph Explorer。
https://developer.microsoft.com/en-us/graph/graph-explorer
這個界面能夠直接執行對應的API操做,返回結果,還提供了大量的經常使用查詢和須要的權限。這樣子個人操做就更簡單了,能夠在這個網頁進行測試,成功以後,再修改本身的腳本。
最後,附上一個完整的腳本
#獲取Token $clientId = "8d4538e6-b1a5-4c05-b449-54d62ss18413" $tenantName = "test.com" $clientSecret = ".2S_zsp.dVff~~5J_9_cxM1e1TRXrJ94" $resource = "https://graph.microsoft.com/" $username='test@abc.com' $password = '@@222333' $ReqTokenBody = @{ Grant_Type = "Password" client_Id = $clientID Client_Secret = $clientSecret Username = $Username Password = $Password Scope = "https://graph.microsoft.com/.default" } $TokenResponse = Invoke-RestMethod -Uri "https://login.microsoftonline.com/$TenantName/oauth2/v2.0/token" -Method POST -Body $ReqTokenBody # 經過API獲取安全警告 $data=(Invoke-RestMethod -uri "https://graph.microsoft.com/v1.0/security/alerts" -Headers @{Authorization = "Bearer $($Tokenresponse.access_token)"} -Method Get) $all=$data.value | Where-Object {$_.severity -like '*medium*' -or $_.severity -like "*high"} $ret=@() foreach($one in $all){ $obj=$one.userStates $category=$one.category $Severity=$one.severity $title=$one.title $obj | Add-Member -NotePropertyName Category -NotePropertyValue $category $obj | Add-Member -NotePropertyName Severity -NotePropertyValue $Severity $obj | Add-Member -NotePropertyName Title -NotePropertyValue $title $ret+=$obj } $ret #自定義一個CSS界面,用於發送對應的郵件,顯示一個比較好看些的table界面 $style=@" <style> body { color:#333333; font-family:Calibri,Tahoma; font-size: 10pt; } h1 { text-align:center; } h2 { border-top:1px solid #666666; } th { font-weight:bold; color:#eeeeee; background-color:#333333; cursor:pointer; } .odd { background-color:#ffffff; } .even { background-color:#dddddd; } .paginate_enabled_next, .paginate_enabled_previous { cursor:pointer; border:1px solid #222222; background-color:#dddddd; padding:2px; margin:4px; border-radius:2px; } .paginate_disabled_previous, .paginate_disabled_next { color:#666666; cursor:pointer; background-color:#dddddd; padding:2px; margin:4px; border-radius:2px; } .dataTables_info { margin-bottom:4px; } .sectionheader { cursor:pointer; } .sectionheader:hover { color:red; } .grid { width:100% } .red { color:red; font-weight:bold; } .green{ color:green; font-weight:bold; } </style> "@ #發送郵件 $from = "test@abc.com" $to = "aaa@abc.com" $smtp = "smtp.office365.com" $sub = "Security Alerts Lists" $password = Get-Content "C:\temp\password.txt" | ConvertTo-SecureString $mycreds = New-Object System.Management.Automation.PsCredential("xyli@vet.partners",$password) $htmlbody=$ret| select AccountName, DomainName,LogonDateTime, LogonIP, UserPrincipalName, Category, Severity, Title | sort Severity| ConvertTo-Html -Body "<H1> Secuirty Alerts </H1>" -Head $style Send-MailMessage -To $to -From $from -Subject $sub -Body ($htmlbody|Out-String) -Credential $mycreds -SmtpServer $smtp -DeliveryNotificationOption Never -BodyAsHtml -UseSsl -port 587
收到的郵件通知
參考資料:
https://developer.microsoft.com/en-us/graph/graph-explorer
https://adamtheautomator.com/microsoft-graph-api-powershell/
https://docs.microsoft.com/en-us/graph/overview?view=graph-rest-1.0