PowerShell“审核”
style="letter-spacing: 0px; text-transform: unset; background-color:透明;">审核不是内置功能,更改跟踪必须手动完成,我们都知道使用 PowerShell。 style="letter-spacing: 0px;text-transform: unset;background-color:transparent;">本文的目的是演练一些场景,其中使用多种方式进行适当级别的审核技术来处理这个问题。提供的解决方案不会针对特定场景,而是根据需要进行定制。审核是本文将要介绍的内容的广义术语。简而言之,下面的脚本代码将重要的信息导出到文本文件以供以后使用。
创建这些文本文件时,我们可以使用 Out-File cmdlet,它允许将信息放入文件中。我们可以通过提供标题行,然后使用逗号分隔值为每个 CSV 输出提供一行来构建简单的 CSV 文件。以下是 CSV 的示例:
日志文件创建
在我们讨论任一场景之前,让我们创建基本日志文件以用于跟踪和审核目的。首先,我们需要为这些报告文件建立基础。为此,我们将使用变量 ($BasePath) 来存储当前路径。对于日志文件,名为“Reports”的文件夹将用作任何日志文件的目标。
$BasePath = (Get-Item -Path ".\" -Verbose).FullName
$Path = $BasePath+"\"+"Reports"
在在此文件夹中存储任何文件之前,我们将检查该文件夹是否存在。如果它不存在,我们创建它:
if(Test-Path $Path -ErrorAction SilentlyContinue){
Write-Host "'nLogging directory exists - $($Path)'n"
}
else{
New-Item -ItemType Directory -Path $Path -Force
}此外,我们将设置 PowerShell 会话窗口的宽度,因为这使得记录长行变得更容易。
$Host.UI.RawUI.BufferSize = New-Object Management.Automation.Host.Size (500, 9999)为了帮助跟踪事件发生的时间,我们将使用一个变量来存储单行代码以根据需要调用:
$Date = { Get-Date -Format "MM.dd.yyyy-hh.mm" }最后,我们将建立日志文件名:
$LogFileName = "ScriptExecutionLog.txt"
$LogDestination = $Path+"\"+$LogFileName好的。进入场景!
场景一
对于我们的第一个场景,我们有一家大公司正在从本地迁移到 Microsoft 365。环境中是域和林方面的基本 Active Directory 配置 - 一个和一个 - 林和域级别都设置为 Windows 2012 R2。就规模而言,我们正在研究环境中超过 40,000 个用户以及数千个组。
在迁移之前,决定将其主 SMTP 地址与其用户主体名称 (UPN) 相匹配,以提供良好的用户体验。经过一番审查,我们发现 14,000 多个帐户不匹配,我们需要进行更改。通过小道消息,我们还听说有些应用程序可能会使用不正确的信息重新标记帐户(请阅读 UPN 更改)。没有应用程序被识别为依赖于 UPN 登录,但我们希望跟踪所有更改,以防需要逆转。
首先,我们需要输入脚本开始的时间戳(请注意,日期格式对于美国来说很常见,国际读者可能需要不同的格式):
$Line = ' ' | Out-File $Destination -Append
$Line = "### START @ $($Date.Invoke()) ###" | Out-File $LogDestination -Append
$Line = ' ' | Out-File $LogDestination -AppendOut-File 是将值写入我们之前定义的日志文件的 cmdlet。
记录初始值
对于日志的第一部分,我们定义新的日志文件和文件的标题行(想想 CSV 中的列标题):
$BeforeFileName = "BeforeChanges.txt"
$BeforeDestination = $Path+"\"+$BeforeFileName
$FileHeader = 'DisplayName,Alias,PrimarySMTPAddress,UPN' | Out-File $BeforeDestination
然后,对于每个用户,我们获取用户的显示名称、用户别名、主 SMTP 地址和用户主体名称 (UPN) 的属性值:
$Line = "$DisplayName,$Alias,$PrimarySMTPAddress,$UPN" | Out-File $BeforeDestination -Append请注意,该行已附加到文件中,因为我们将每一行添加到文件中并且不想覆盖该文件。我们还可以更全面地记录每个处理的用户:
$Output = "The mailbox $DisplayName was processed." | Out-File $LogDestination -Append** 请注意,使用的变量($Output 或 $Line)并不重要,因为我们可以根据需要选择任何可接受的 PowerShell 变量名称。
日志更改和故障
在此代码中,我们有一段代码用于处理更改用户的 UPN。该代码设置为 Try {} Catch {} 块,以便我们可以记录好的更改(在 Try {} 块中)或失败(Catch {} 块)。
If ($UPN -ne $PrimarySMTP) {
Try {
Set-Mailbox $User -UserPrincipalName $NewUPN -ErrorAction STOP
$Line = "$($Date.Invoke()),Successfully changed the UPN to $PrimarySMTPto the correct matching value for the $User." | Out-File $LogDestination -Append
} Catch {
$Line = "$($Date.Invoke()) , Failed to set the UPN to $PrimarySMTP to the correct matching value for the $User." | Out-File $LogDestination -Append
$Line = "$($Date.Invoke()) , Error message - $_.Exception.Message" | Out-File $LogDestination -Append
}
} Else {
$Line = "$($Date.Invoke()) , UPN for $User is correct, no change needed." | Out-File $LogDestination -Append
}在中间,请注意 $_.Exception.Message 变量。这使我们能够捕获通常会显示的任何 PowerShell 错误,并且现在将这些错误复制到日志文件中以供将来检查。
记录更改值
此代码看起来与我们用于记录初始设置的部分完全相同,只是我们的目标文件会有所不同,因为我们需要一个之前和之后的文件:
$AfterFileName = "AfterChanges.txt"
$AfterDestination = $Path+"\"+$AfterFileName
$FileHeader = 'DisplayName,Alias,PrimarySMTPAddress,UPN' | Out-File $AfterDestination
$Line = "$DisplayName,$Alias,$PrimarySMTPAddress,$UPN" | Out-File $AfterDestination -Append跑步结束
最后,我们将再次为脚本结尾添加时间戳。
$Line = ' ' | Out-File $LogDestination -Append
$Line = "### END @ $($Date.Invoke()) ###" | Out-File $LogDestination -Append
$Line = ' ' | Out-File $LogDestination -Append下面是一个示例日志文件,其中包含开始/结束时间戳以及中间的事件日志:
开始和结束时间戳
进入下一个场景!
场景二
对于此方案,我们进行了 Exchange 到 Exchange Online 迁移,将 10,000 多个邮箱从多个地理区域迁移到单个 Exchange Online 租户。在移动这些用户时,我们有一个脚本(如之前在此处和此处编写的脚本),管理员可以使用该脚本进行迁移。为了进一步增强此脚本,我们可以使用 PowerShell 为脚本中的关键项目生成日志。
这是我们可以执行的日志记录的摘要:
将发生的每个操作以及脚本执行的开始和停止日期写入日志。
记录错误 - 捕获 PowerShell 在屏幕上生成的错误。
脚本开始 - 文件的适当标头以启动脚本:
$FileName = "MailboxMoveAdministrationLogging.txt"
$Destination = $Path+"\"+$FileName
$FileCheck = Test-Path $Destination
If (-not($FileCheck)) {
$Line = "This file logs all changes made to move requests in this script" | Out-File $Destination
$Line = "---------------------------------------------------------------" | Out-File $Destination -Append
$Line = " " | Out-File $Destination -Append
}
$Line = ' ' | Out-File $Destination -Append
$Line = "### START @ $($Date.Invoke()) ###" | Out-File $Destination -Append
$Line = ' ' | Out-File $Destination -Append详细的搬迁报告
对于此功能,日志记录只是导出整个报告值,该值提供了邮箱移动到云的详细分析,并用于确定移动失败或暂停的原因。下面,我们获取邮箱的主 smtp 地址,指定一个输出文件(特定于我们正在查询的邮箱移动),获取邮箱的报告,然后将整个报告导出到我们在第 2 行中指定的文件中:
$Mailbox = $MoveRequest.PrimarySMTPAddress
$OutputFile ="$Path"+"\"+"$Mailbox"+"-Report.txt"
$Report = (Get-MoveRequestStatistics -Identity $Mailbox -IncludeReport).Report
$Report.Entries | Ft | Out-File -FilePath $OutputFile记录邮箱移动
对于脚本的这一部分,我们再次使用 Try {} Catch {} 块创建一个用于邮箱迁移的新移动请求。如果创建成功,则会记录此情况,如果失败,也会记录错误消息:
$Mailbox = $User.PrimarySMTPAddress
If ($Null -eq (Get-MoveRequest $Mailbox -ErrorAction Silentlycontinue)){
Try {
$Creation = New-MoveRequest -Identity $Mailbox -Remote -RemoteHostName $Endpoint -TargetDeliveryDomain $TargetDomain -RemoteCredential $OPCred -SuspendWhenReadyToComplete -ErrorAction STOP
$Line = "The mailbox move for $Mailbox was successfully created." | Out-File $Destination -Append
} Catch {
$Line = "The mailbox move for $Mailbox was NOT successfully created." | Out-File $Destination -Append
$Line = "$($Date.Invoke()) , Error message - $_.Exception.Message" | Out-File $Destination -Append
}
}删除移动请求,最后一个示例
在此代码部分中,我们有一个代码块将删除移动请求,可能是因为用户需要等待或由于他们离开公司而被从当前的移动集中删除。此过程类似于前面所示的新移动请求,我们有这部分代码:
Write-host "Removing move request for " -ForegroundColor White -NoNewline
Write-host "$SMTPAddress....." -ForegroundColor Yellow
Try {
Remove-MoveRequest $SMTPAddress -Confirm:$False -ErrorAction STOP
$Line = "$($Date.Invoke()) , Remove move request for $SMTPAddress succeeded." | Out-File $Destination -Append
} Catch {
$Line = "$($Date.Invoke()) , Remove request for $SMTPAddress failed." | Out-File $Destination -Append
$Line = "$($Date.Invoke()) , Error message - $_.Exception.Message" | Out-File $Destination -Append
}示例日志文件条目
记录了开始、结束和操作的日志文件
包含 START、END 的日志文件,在本例中还记录了错误
其他场景?
你能想到什么场景?您会为好结果和坏结果创建单独的日志吗? Out-File 的另一个可能用途是文档,例如 Exchange Online 中所有用户的每日邮箱统计信息。换句话说,我们有很多可能性,因此可以继续记录、审计或使用 PowerShell。
重要的提示
10,000 这个数字在这两种情况下都很重要。 PowerShell 使用 1,000 个结果限制。由于这两个环境都很大,因此对某些 cmdlet 使用 -ResultSize Unlimited 是获取结果的唯一方法。大型环境的另一个性能提示是,如果 cmdlet 具有“Filter”参数,请在使用“Where”过滤结果之前使用该参数。在大型环境中使用“Where”可以显着增加脚本的处理时间。




