Windows 工作排程執行身分設定與存取權限研究
5 | 12,455 |
這篇來說說 Windows 工作排程設定的執行身分,不同設定有什麼影響。
排程的執行身分有幾個選項。主選項是「只有使用者登入時才執行」或「不論使用者登入與否均執行」,前者使用者必須在登入狀態才會執行,後者則不限使用者是否登入,但需輸入使用者帳號及密碼,它還有一個附加選項「不要儲存密碼。工作將只有本機電腦資源的存取權」(Do not store password. The task will only have access to local computer resources.);除此之外,還有一個獨立選項「以最高權限執行」,可配合前述三個選項使用。
上面說的選項實際會對映到 Task Scheduler / LogonType (principalType) Element 屬性,有以下設定:
- Interactive:使用者必須已登入,排程將在當下的互動 Session 執行,排程執行時視窗會出現在桌面
- Password:儲存密碼,另起 Session 執行
- S4U:Service for User,不需提供密碼,可存取本機資源,不能存取網路資源及加密檔案
Interactive 跟 Password 很直覺,分別對映「只有使用者登入時才執行」及「不論使用者登入與否均執行」,而 S4U 對映的是「不要儲存密碼。工作將只有本機電腦資源的存取權」,需要花點時間了解。S4U 源自 S4U Kerberos Extensions,是一種伺服器不需提供密碼就代替使用者登入取得 Service Ticket 的做法,後續可依藉此判斷使用者是否有權限存取該伺服器資源。參考:S4U2Self
我們可以透過 PowerShell 觀察不同設定對映的屬性變化,重點放在 Principal.LogonType 及 Principal.RunLevel。
RunLevel 一般為 Limited,勾選「以最高權限執行」後會變成 Highest。LogonType 對映如下:
- 只有使用者登入時才執行:Interactive
- 不論使用者登入與否均執行:Password
- 不要儲存密碼。工作將只有本機電腦資源的存取權:S4U
我寫了一個 PowerShell 驗證不同設定下的存取權限,測試以下動作:
- 查詢 IIS AppPool (需要最高權限)
- Invoke-WebRequest 取得 Google HTML (證明 S4U 的網路指的是 AD 網域遠端資源,不是一般 TCP/IP)
- 查詢本機 UNC 網路分享 (驗證是否能讀取本機資源)
- 查詢 AD DC NetLogon 分享 (驗證是否能讀取遠端網域資源)
程式碼如下:
$curUserName = [Security.Principal.WindowsIdentity]::GetCurrent().Name
$task = Get-ScheduledTask -TaskName '排程身分測試'
$principle = $task.Principal
$logonType = $principle.LogonType
$runLevel = $principle.RunLevel
try {
$appPoolCnt = (Get-IISAppPool).Count
$adminTest = "Pass ($appPoolCnt)"
}
catch {
$adminTest = "Fail"
}
try {
$htmlLen = (Invoke-WebRequest -Uri "http://www.google.com").Content.Length
$curlTest = "Pass ($htmlLen)"
}
catch {
$curlTest = "Fail"
}
try {
$dirCnt = (Get-ChildItem \\LocalComputerName\C$\Lab -ErrorAction Stop).Count
$localUncTest = "Pass ($dirCnt)"
}
catch {
$localUncTest = "Fail"
}
try {
$dirCnt = (Get-ChildItem \\WIN-LP5NBDSS0UJ\NetLogon -ErrorAction Stop).Count
$remoteUncTest = "Pass ($dirCnt)"
}
catch {
$remoteUncTest = "Fail"
}
@"
LogonType: $logonType / RunLvel: $runLevel / Current User: $curUserName
* Admin Test: $adminTest
* curl Test: $curlTest
* Local UNC Test: $localUncTest
* Remote UNC Test: $remoteUncTest
"@ | Out-File -FilePath "$PSScriptRoot\trace.log" -Append
實測結果:
// 只有使用者登入時才執行
LogonType: Interactive / RunLvel: Limited / Current User: UTOPIA\jeffrey
* Admin Test: Fail // 無權限
* curl Test: Pass (50088)
* Local UNC Test: Pass (3)
* Remote UNC Test: Pass (1)
// 不論使用者登入與否均執行
LogonType: Password / RunLvel: Limited / Current User: UTOPIA\jeffrey
* Admin Test: Pass (5)
* curl Test: Pass (47896)
* Local UNC Test: Pass (3)
* Remote UNC Test: Pass (1)
// 不要儲存密碼。工作將只有本機電腦資源的存取權
LogonType: S4U / RunLvel: Limited / Current User: UTOPIA\jeffrey
* Admin Test: Pass (5)
* curl Test: Pass (50067)
* Local UNC Test: Pass (3)
* Remote UNC Test: Fail // 無權限
// 只有使用者登入時才執行 + 以最高權限執行
LogonType: Interactive / RunLvel: Highest / Current User: UTOPIA\jeffrey
* Admin Test: Pass (5) // 成功
* curl Test: Pass (50072)
* Local UNC Test: Pass (3)
* Remote UNC Test: Pass (1)
// 不論使用者登入與否均執行 + 以最高權限執行
LogonType: Password / RunLvel: Highest / Current User: UTOPIA\jeffrey
* Admin Test: Pass (5)
* curl Test: Pass (47956)
* Local UNC Test: Pass (3)
* Remote UNC Test: Pass (1)
// 不要儲存密碼。工作將只有本機電腦資源的存取權 + 以最高權限執行
LogonType: S4U / RunLvel: Highest / Current User: UTOPIA\jeffrey
* Admin Test: Pass (5)
* curl Test: Pass (47956)
* Local UNC Test: Pass (3)
* Remote UNC Test: Fail // 無權限
【小結】
- Get-IISAppPool 這種需要管理者權限執行的動作,在互動 Session 下會失敗,需靠勾選「以最高權限執行」克服
- Invoke-WebRequest 存取網路及存取本機資源不受影響,全部設定下都成功
- 勾選「不要儲存密碼。工作將只有本機電腦資源的存取權」時無法存取網域的遠端主機
Comments
# by Jerrymow
請問我有一個排程,單獨執行程式是可以正常執行,但是透過排程呼叫(排程與手動)都會無法正常產出執行結果,有執行卻不正確 設定了 "不論使用者登入與否均執行 + 以最高權限執行" 及 改用 local admin 執行都一樣 請教這可能是哪一個地方的權限出了問題? 感謝
# by Jeffrey
to Jerrymow,單由描述很難推測原因,可能要由錯誤訊息、埋 Log 或試試用 ProcMon 抓原因。
# by Jerrymow
Hi Jeffrey, 謝謝您的說明,目前先埋 log 察看是哪一個階段造成錯誤,再來追查可能是什麼權限的差異
# by Albert
我也有一個排程,單獨執行程式(vba or python)是可以正常執行,但是透過排程呼叫(排程與手動)都會無法正常產出執行結果,都卡在建立outlook這一步驟,請問如何解決?
# by Jeffrey
to Alert,Office 是前景程式,搬到背景問題多多,但我只處理過 Excel/Word,沒試過 Outlook。 https://blog.darkthread.net/blog/run-excel-in-scheduled-task https://blog.darkthread.net/blog/word-run-under-windows-service/