我正在使用 .Net Framework 4.7.2 在 Windows Server 2019 上测试 ASP.NET 应用程序。 IIS 应用程序设置为模拟没有管理权限的用户。
应用程序在尝试创建新源之前调用 EventLog.SourceExists
来检查事件日志源是否存在。据我所知,此方法需要管理权限才能搜索现有事件日志的来源 [1]。实现此目的的另一种方法是,我明确授予用户对注册表项 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog
和所有子项的读取权限。
这适用于 Windows Server 2019 之前的版本(2016、2012 R2、2018)。
测试时,同一应用程序在 Windows Server 2019 上失败,但出现异常。
The source was not found, but some or all event logs could not be searched. Inaccessible logs: State.
运行 procmon 时,尝试打开“状态”事件日志的注册表项时,我看到访问被拒绝 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\State
“State”注册表项对于 Windows Server 2019 来说是新的。它也受到保护 - 它由 SYSTEM 拥有,管理员仅限于只读。当我尝试授予我的用户读取权限时,我收到“访问被拒绝”的消息。因此,在调用 EventLog.SourceExists 时,以非管理员用户身份运行的应用程序会失败,并显示 Inaccessible logs: State
。
我意识到我可以取得 State
注册表项的所有权并添加我的用户。不过,在执行此操作之前,我想看看是否有人了解 Windows Server 2019 中的这个新注册表项(事件日志)。
谢谢。
最佳答案
根本原因:
HKLM\SYSTEM\CCS\Services\EventLog 树中的“状态”配置单元具有奇怪的安全配置。因此,任何尝试枚举事件源的应用程序最终都会遇到“访问被拒绝”异常并退出。
默认权限是:
- 系统(完全控制)
- 事件日志(完全控制)
- 管理员(读取 key )
它们不是继承的,就像“安全”配置单元一样。 相反,名为“Parameters”的第二个新配置单元继承权限。
枚举通常在应用程序中完成,如下所示:
[System.Diagnostics.EventLog]::SourceExists("Source Name")
即使您尝试使用 PowerShell 进行枚举,也会遇到“访问被拒绝”的情况
PS C:\> (gci -Recurse HKLM:\System\CurrentControlSet\services\eventlog).Name
虽然我不知道“状态”配置单元到底在做什么(微软对此不是很详细),但我找到了解决这个问题的方法。
解决方案:
交互式解决方案,使用 REGEDIT:
a) 使用“PSexec”以系统身份运行 REGEDIT 并 b) 使用 REGEDIT 的 UI,向 IIS_IUSRS 的“状态”配置单元或您的服务或 IIS 应用程序池运行的任意帐户授予读取权限
使用 PowerShell 的脚本方法:
a) 使用“PSexec”以系统身份运行 PowerShell 并 b) 使用“Get-ACL”/“Set-ACL”cmdlet,向 IIS_IUSRS 或您的服务或 IIS 应用程序池运行的任意帐户的“状态”配置单元授予读取权限
以 SYSTEM 用户身份运行应用程序的最佳方式是使用 PSexec,可以从 Microsoft SysInternals 站点 ( https://learn.microsoft.com/en-us/sysinternals/downloads/psexec ) 免费下载 PSexec
PS C:\> PSexec.exe -accepteula -d -i -s powershell.exe
这将打开一个以 NT AUTHORITY\System 身份运行的 PowerShell 窗口。 从此处,使用 REGEDIT 更改“状态”配置单元上的服务用户帐户或 IIS 应用程序池用户的权限。或者,使用 Get-ACL/Set-ACL cmdlet 以脚本化方式执行相同操作。 “读取 key ”权限足够;不需要“完全控制”。
PS C:\> $hive = HKLM:\System\CurrentControlSet\services\eventlog\state; $acl = Get-ACL $hive; $rule = New-Object System.Security.AccessControl.RegistryAccessRule ("IIS_IUSRS","ReadKey","ContainerInherit","None","Allow"); $acl.SetAccessRule($rule); $acl |Set-ACL $hive
您的应用程序现在应该能够枚举其运行的计算机上的所有事件源,并创建事件源(如果枚举未找到)。
关于.net - EventLog.SourceExists 在 Windows Server 2019 上失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54874695/