powershell - 使用 PowerShell 获取用户的数据审计日志报告(Power bi pro)
问题描述
我们编写了一个 PowerShell 脚本,用于为 Power BI Pro 用户提取审核日志数据。以前它工作正常,从一个月开始,我们在运行脚本时遇到了 access dined 错误。我们正在使用正确的凭据,并且还尝试了非 MFA 帐户,同样的问题来了。错误信息如下:
New-PSSession : [outlook.office365.com] 连接到远程服务器 Outlook.office365.com 失败,并显示以下错误消息:访问被拒绝。有关详细信息,请参阅 about_Remote_Troubleshooting 帮助主题。在 E:\location\Folder\Auditreport.ps1:66 char:12
$Session = New-PSSession –ConfigurationName Microsoft.Exchange -Conne ... ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~ CategoryInfo : OpenError: (System.Manageme....RemoteRunspace:RemoteRunspace) [New-PSSession], PSRemotingTransportExceptionfullyQualifiedErrorId : AccessDenied ,PSSessionOpenFailed Import-PSSession:无法验证参数“会话”上的参数。参数为空。为参数提供一个有效值,然后再次尝试运行该命令。在 E:\location\Folder\Auditreport.ps1:70 char:18 Import-PSSession $Session -DisableNameChecking -AllowClobber
Powershell 脚本
cls
Set-ExecutionPolicy RemoteSigned
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
Add-Type -Path (Resolve-Path "$PSScriptRoot\Microsoft.SharePoint.Client.dll")
Add-Type -Path (Resolve-Path "$PSScriptRoot\Microsoft.SharePoint.Client.Runtime.dll")
# getting data from config file
$Data = [Xml] (Get-Content $PSScriptRoot\Config.xml)
$PowerBIUser=$Data.data.record |where {$_.key -eq "PowerBIUser"} | select value
$PowerBIUser=$PowerBIUser.value
$SecurePasswordpath=$Data.data.record |where {$_.key -eq "Securepasswordpath"} | select value
$SecurePasswordpath=$PSScriptRoot+"\"+$SecurePasswordpath.value
$AppId=$Data.data.record |where {$_.key -eq "AppId"} | select value
$AppId=$AppId.value
$AppSecret=$Data.data.record |where {$_.key -eq "AppSecret"} | select value
$AppSecret=$AppSecret.value
$SourceUrl=$Data.data.record |where {$_.key -eq "SourceUrl"} | select value
$SourceUrl=$SourceUrl.value
$SourceListProUsers=$Data.data.record |where {$_.key -eq "SourceListProUsers"} | select value
$SourceListProUsers=$SourceListProUsers.value
$securePassword = Get-Content $SecurePasswordpath | ConvertTo-SecureString
$UserCredential = New-Object System.Management.Automation.PSCredential($PowerBIUser, $securePassword)
Connect-PnPOnline -Url $SourceUrl -ClientId $AppId -ClientSecret $AppSecret
$startDate=(get-date).AddDays(-90)
$endDate=(get-date)
$scriptStart=(get-date)
#Establish session to exchange online and import unified audit log commandlets required for security and compliance audit log search
$Session = New-PSSession –ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $UserCredential -Authentication Basic -AllowRedirection
#Import-PSSession -Session $Session | Out-Null
Import-PSSession $Session -DisableNameChecking -AllowClobber
$ItemsPBIProUsers = Get-PnPListItem -List PBIProUsers
If($ItemsPBIProUsers) {
$ItemsPBIProUsers | ForEach {
$UserEmail=$_['UserPrincipalName'];
#write-host $UserEmail
$sessionName = (get-date -Format 'u')+'pbiauditlog'
# Reset user audit accumulator
$aggregateResults = @()
$i = 0 # Loop counter
Do {
#$currentResults = Search-UnifiedAuditLog -StartDate $startDate -EndDate $enddate -SessionId $sessionName -SessionCommand ReturnLargeSet -ResultSize 1000 -RecordType PowerBI
#$UserEmail="_PowerBiGate@test.com";
$currentResults = Search-UnifiedAuditLog -UserIds $UserEmail -StartDate $startDate -EndDate $enddate -SessionId $sessionName -SessionCommand ReturnLargeSet -ResultSize 1000 -RecordType PowerBI
Write-Host( $UserEmail + "-" + $currentResults.Count);
if ($currentResults.Count -gt 0) {
#Write-Host( $UserEmail + "-" + $currentResults.Count);
#Write-Host (" Finished {3} search #{1}, {2} records: {0} min" -f [math]::Round((New-TimeSpan -Start $scriptStart).TotalMinutes,4), $i, $currentResults.Count, $user.UserPrincipalName )
# Accumulate the data
$aggregateResults += $currentResults
# No need to do another query if the # recs returned <1k - should save around 5-10 sec per user
if ($currentResults.Count -lt 1000) {
$currentResults = @()
} else {
$i++
}
}
} Until ($currentResults.Count -eq 0) # --- End of Session Search Loop --- #
try {
$aggregateResults= $aggregateResults | Sort CreationDate -Descending
if ($aggregateResults.Count -gt 0)
{
$CreationDate=$aggregateResults[0].CreationDate.Date
$_['LastActivityDate'] = $CreationDate
$_.SystemUpdate()
Invoke-PnPQuery
}
}
catch {
$ErrorMessage = $_.Exception.Message
write-host $ErrorMessage
}
}
}
<#
$data=@()
foreach ($auditlogitem in $aggregateResults) {
$datum = New-Object –TypeName PSObject
$d=convertfrom-json $auditlogitem.AuditData
$datum | Add-Member –MemberType NoteProperty –Name Id –Value $d.Id
$datum | Add-Member –MemberType NoteProperty –Name CreationTime –Value $auditlogitem.CreationDate
$datum | Add-Member –MemberType NoteProperty –Name CreationTimeUTC –Value $d.CreationTime
$datum | Add-Member –MemberType NoteProperty –Name RecordType –Value $d.RecordType
$datum | Add-Member –MemberType NoteProperty –Name Operation –Value $d.Operation
$datum | Add-Member –MemberType NoteProperty –Name OrganizationId –Value $d.OrganizationId
$datum | Add-Member –MemberType NoteProperty –Name UserType –Value $d.UserType
$datum | Add-Member –MemberType NoteProperty –Name UserKey –Value $d.UserKey
$datum | Add-Member –MemberType NoteProperty –Name Workload –Value $d.Workload
$datum | Add-Member –MemberType NoteProperty –Name UserId –Value $d.UserId
$datum | Add-Member –MemberType NoteProperty –Name ClientIP –Value $d.ClientIP
$datum | Add-Member –MemberType NoteProperty –Name UserAgent –Value $d.UserAgent
$datum | Add-Member –MemberType NoteProperty –Name Activity –Value $d.Activity
$datum | Add-Member –MemberType NoteProperty –Name ItemName –Value $d.ItemName
$datum | Add-Member –MemberType NoteProperty –Name WorkSpaceName –Value $d.WorkSpaceName
$datum | Add-Member –MemberType NoteProperty –Name DashboardName –Value $d.DashboardName
$datum | Add-Member –MemberType NoteProperty –Name DatasetName –Value $d.DatasetName
$datum | Add-Member –MemberType NoteProperty –Name ReportName –Value $d.ReportName
$datum | Add-Member –MemberType NoteProperty –Name WorkspaceId –Value $d.WorkspaceId
$datum | Add-Member –MemberType NoteProperty –Name ObjectId –Value $d.ObjectId
$datum | Add-Member –MemberType NoteProperty –Name DashboardId –Value $d.DashboardId
$datum | Add-Member –MemberType NoteProperty –Name DatasetId –Value $d.DatasetId
$datum | Add-Member –MemberType NoteProperty –Name ReportId –Value $d.ReportId
$datum | Add-Member –MemberType NoteProperty –Name OrgAppPermission –Value $d.OrgAppPermission
#option to include the below JSON column however for large amounts of data it may be difficult for PBI to parse
#$datum | Add-Member –MemberType NoteProperty –Name Datasets –Value (ConvertTo-Json $d.Datasets)
#below is a poorly constructed PowerShell statemnt to grab one of the entries and place in the DatasetName if any exist
foreach ($dataset in $d.datasets) {
$datum.DatasetName = $dataset.DatasetName
$datum.DatasetId = $dataset.DatasetId
}
$data+=$datum
}
$datestring = $startDate.ToString("yyyyMMdd")
$fileName = ("c:\PBIAuditLogs\" + $datestring + ".csv")
Write-Host (" writing to file {0}" -f $fileName)
$data | Export-csv $fileName
#>
Remove-PSSession -Id $Session.Id
解决方案
拒绝访问响应通常只有3 个原因:
- 您输入了错误的用户名或密码。
- 您尝试使用无权访问 Exchange Online 的帐户登录服务。
- 您在租户中启用了安全默认值。
最可能的原因是该帐户被锁定或您使用了错误的密码,因此请仔细检查Get-Content $SecurePasswordpath
该帐户返回的可用密码。
您可能还为您的组织BasicAuth
禁用了,尽管它不应该在另一个月左右自动发生。您可以检查它是否是通过策略完成的,但如果您的组织使用安全默认值,您可能一无所有。Get-AuthenticationPolicy
我建议更新您的脚本以使用ExchangeOnline V2模块,而不是使用New-PSSession
连接。
推荐阅读
- quarkus - 是否可以在 Quarkus 的 Optaplanner 中将 DRL 与流 ConstraintProvider 混合
- python - 试图根据年龄计算某人需要支付的税额
- node.js - 在 NodeJs 中调用我的合约方法时执行恢复
- python - 如何使用 Discord Bot 将由该机器人创建的 PNG 上传到服务器?
- java - 在 Azure 服务中创建堆转储
- r - 覆盖R中其他包的错误消息
- c# - 如何在datagridview中更改索引列/最左列的宽度
- javascript - JQuery改变兄弟姐妹选择css
- python - 如何在不使用集合类型的情况下计算每个字母在字符串中出现的次数?
- javascript - 在 Java Script 中可检测到具有 CSS 调整大小属性的 DIV