PowerShell - MS SQL Job 使用 TLS 1.2 協定

介紹如何讓 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;