Sql-Server-2014

以管理員身份從代理執行 Powershell 腳本

  • September 7, 2019

當 SQL Server 服務啟動時,我需要在我的伺服器上的 IIS 中回收 AppPool。

我正在採取的路線是有一個啟動儲存過程,它執行一個具有 Powershell 作業步驟的代理作業。

我已經創建/從網際網路上抓取了一個回收應用程序池的 Powershell 腳本:

# Load IIS module:
Import-Module WebAdministration
# Set a name of the site we want to recycle the pool for:
$site = "Default Web Site"
# Get pool name by the site name:
$pool = (Get-Item "IIS:\Sites\$site"| Select-Object applicationPool).applicationPool
# Recycle the application pool:
Restart-WebAppPool $pool

這適用於作業系統級別,但僅當 Powershell 以管理員身份執行時(即使我在 Admin 組中登錄到 Windows 的帳戶也是如此)

果然,如果我使用包含上述程式碼的 Powershell 步驟在代理中創建作業,執行時會出現錯誤

作業步驟在 PowerShell 腳本的第 6 行收到錯誤。對應的行是 ‘$pool = (Get-Item “IIS:\Sites $ site”| Select-Object applicationPool).applicationPool ‘。更正腳本並重新安排作業。PowerShell 返回的錯誤資訊是:‘無法檢索 cmdlet 的動態參數。文件名:redirection.config 錯誤:由於權限不足,無法讀取配置文件’。處理退出程式碼-1。步驟失敗。

所以我需要一種從 SQL Server 代理“以管理員身份執行”的方法

我在作業系統級別成功創建了一個新腳本,該腳本以提升的權限執行原始腳本:

If (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator))
{
 # Relaunch as an elevated process:
 Start-Process powershell.exe "-File",('"{0}"' -f $MyInvocation.MyCommand.Path) -Verb RunAs
 exit
}
# Now running elevated so launch the script:
& "d:\path\to\my\script.ps1"

這允許我從非提升的 CMD 提示符或非提升的 Powershell 提示符執行新腳本。但是,當我嘗試從代理作為 Powershell 步驟或 CMD 步驟執行時,我得到

機器預設權限設置不會將 CLSID {longguidhere} 和 APPID {longguidhere} 的 COM 伺服器應用程序的本地啟動權限授予來自應用程序容器中執行的地址 LocalHost(使用 LRPC)的使用者 NT SERVICE\SQLSERVERAGENT SID (longguidhere)不可用的 SID(不可用)。可以使用組件服務管理工具修改此安全權限。

我也試過

Start-Process powershell -Verb runAs -FilePath "d:\path\to\my\script.ps1"

再次,在作業系統級別工作,但從代理執行時給我同樣的錯誤。

我怎樣才能得到

a:無需提升權限即可回收應用程序池

或者

b:執行腳本以從 SQL Server 代理回收具有提升權限的應用程序池?

這是一個冗長的工作,但我設法做到瞭如下:

  • 在 Windows 任務計劃程序中創建計劃任務以執行回收應用程序池的 Powershell 腳本文件。確保將其標記為“以最高權限執行”
  • 使用管理員憑據創建憑據
  • 創建代理帳戶並與 CMD 子系統關聯
  • 創建執行計劃任務的 CMD 代理作業(確保作業步驟作為代理帳戶執行)
  • 創建一個執行作業的啟動過程。我必須添加一個 while 循環來檢查代理是否正在執行,如果沒有,則等待 5 秒鐘並再次嘗試啟動作業

在 SQL Server 代理中創建一個 PowerShell 代理,該代理通過 SQL Server 憑據使用特權 Windows 帳戶。

創建憑證文件。

如何創建代理

這將允許您以管理員身份直接從 SQL Server 執行 PowerShell。

創建憑證是第一步,包括執行如下 T-SQL 語句:

CREATE CREDENTIAL MyPowerShellCredential   
WITH IDENTITY = 'DOMAIN\AdministratorAccount'  
   , SECRET = 'AdministratorAccountPassword'  

創建憑據後,您需要創建 SQL Server PowerShell 代理。這應該有效:

USE msdb;
EXEC dbo.sp_add_proxy @proxy_name = N'MyPowerShellProxy'
   , @enabled=1
   , @description = N'Proxy used to run PowerShell as an administrator'
   , @credential_name = N'MyPowerShellCredential';

創建代理後,您需要啟用它以供 PowerShell 子系統使用。這段程式碼做到了:

USE msdb;
EXEC dbo.sp_grant_proxy_to_subsystem @proxy_name = N'MyPowerShellProxy'  
    , @subsystem_name = N'PowerShell'

創建代理後,您需要配置 SQL Server Agent Jobstep 以執行 PowerShell,這將自動使用 PowerShell 代理。

這是一個範例 SQL Server 代理作業,它將執行您的程式碼:

USE [msdb]
GO
DECLARE @jobId binary(16);

EXEC  msdb.dbo.sp_add_job @job_name = N'ResetAppPool'
       , @enabled = 1
       , @notify_level_eventlog = 0
       , @notify_level_email = 2
       , @notify_level_page = 2
       , @delete_level = 0
       , @category_name = N'[Uncategorized (Local)]'
       , @owner_login_name = N'sa'
       , @job_id = @jobId OUTPUT;

EXEC msdb.dbo.sp_add_jobserver @job_name = N'ResetAppPool'
   , @server_name = N'(LOCAL)';

EXEC msdb.dbo.sp_add_jobstep @job_name = N'ResetAppPool'
   , @step_name = N'Step1'
   , @step_id = 1
   , @cmdexec_success_code = 0
   , @on_success_action = 1
   , @on_fail_action = 2
   , @retry_attempts = 0
   , @retry_interval = 0
   , @os_run_priority = 0
   , @subsystem = N'PowerShell'
   , @command = N'# Load IIS module:
Import-Module WebAdministration
# Set a name of the site we want to recycle the pool for:
$site = "Default Web Site"
# Get pool name by the site name:
$pool = (Get-Item "IIS:\Sites\$site"| Select-Object applicationPool).applicationPool
# Recycle the application pool:
Restart-WebAppPool $pool'
   , @database_name = N'master'
   , @flags = 0;

EXEC msdb.dbo.sp_update_job @job_name = N'ResetAppPool'
   , @enabled = 1
   , @start_step_id = 1
   , @notify_level_eventlog = 0
   , @notify_level_email = 2
   , @notify_level_page = 2
   , @delete_level = 0
   , @description = N''
   , @category_name = N'[Uncategorized (Local)]'
   , @owner_login_name = N'sa'
   , @notify_email_operator_name = N''
   , @notify_page_operator_name = N''
GO

您可以修改作業以在它執行時向您發送電子郵件,以便您知道它有效。

關於您看到的此錯誤:

機器預設權限設置不會將 CLSID {longguidhere} 和 APPID {longguidhere} 的 COM 伺服器應用程序的本地啟動權限授予來自應用程序容器中執行的地址 LocalHost(使用 LRPC)的使用者 NT SERVICE\SQLSERVERAGENT SID (longguidhere)不可用的 SID(不可用)。可以使用組件服務管理工具修改此安全權限。

這表明使用者帳戶控制正在管理員批准模式下執行,要求每個需要提升權限的操作都徵得使用者同意。由於 SQL Server 代理作為服務執行,因此提升提示沒有機會執行,因此失敗。您可以通過控制面板中的組件服務小程序分配NT SERVICE\SQLSERVERAGENT帳戶權限以在提升模式下本地啟動 PowerShell,而無需提示。

或者,您可以配置 Windows,使其永遠不需要提升本地管理員組的成員。通過本地安全策略小程序執行此操作。設置以下設置:

  1. 打開Security Settings\Local Policies\Security Options文件夾。
  2. 將“使用者帳戶控制:內置管理員帳戶的管理員批准模式”設置為“禁用”
  3. 將“使用者帳戶控制:管理員批准模式下管理員的提升提示行為”設置為“不提示提升”
  4. 將“使用者帳戶控制:以管理員批准模式執行所有管理員”設置為“禁用”

引用自:https://dba.stackexchange.com/questions/235153