介紹如何讓 MS SQL 的 Job 可以使用 PowerShell,並以 TLS 1.2 協定來存取服務。
前言
小弟公司的系統有一個需求是透過 SQL Server Agent
建立一隻 job 並且透過 ActiveX Script
呼叫 Web Service 達成某些任務。
Service 端系統的安全協定是 SSL 3.0
,一直以來都沒什麼問題,直到某天更新至 TLS 1.2
,然後 job 就跟著全部死光光了。
var ret = "";
var xml = CreateObject("msxml2.serverxmlhttp.5.1");
xml.setOption(2, 13056);
xml.setTimeouts(10000,10000,6000000,6000000);
xml.open("POST", "URL", false);
xml.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xml.send();
xml = null;
由於在 Microsoft SQL Server 2017 以及之後的版本都會取消 ActiveX Script 這項功能,所以解決方式就規劃以 PowerShell Script 來取代。
PowerShell 請求 Web 服務的範例
使用 System.Net.HttpWebRequest
對服務發出請求。
$webRequest = [System.Net.HttpWebRequest]::Create("URL")
$webRequest.Method = "GET";
$webRequest.GetResponse()
也可以加上此段來查看返回的結果,甚至存入 txt 檔。
$stream = $response.GetResponseStream()
$reader = New-Object System.IO.BinaryReader($stream)
$bytes = New-Object System.Byte[] $response.ContentLength
for ($read = 0; $read -ne $bytes.Length; $read += $reader.Read($bytes,$read,$bytes.Length - $read) ){ }
[System.IO.File]::WriteAllBytes("c:temp.txt",$bytes);
SQL Server Job 中 Type 的替换
只要將 type 更換為 PowerShell
即可,就可以將 PowerShell Script 放到這裡來讓 job 運行。
配合服務方升級 TLS 1.2 協定
PowerShell 底層是以 .NET Framewrk 為核心,要到 .NET 4.5 版開始才會有支援 TLS 1.2,且 .NET 為了要和較舊的系統相容,預設還是為 SSL 3.0
與 TLS 1.0
。
所以如果是直接請求服務,則會出現 無法建立 SSL/TLS 的安全通道
的錯誤訊息。
這時就需要新增以下兩行來設定 SecurityProtocol 。
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
而我遇到的環境是使用 .Net Framework 2.0 並且有需要使用 TLS 1.2,在這種情況需要指派 3072 作為 SecurityProtocolType 的屬性、
$p = [Enum]::ToObject([System.Net.SecurityProtocolType], 3072);
[System.Net.ServicePointManager]::SecurityProtocol = $p;