最近由于疫情嘛,你们伙都在家里工做。老板隔三差五的让我给他一些报告,好比最近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