- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
I encountered a situation where the SSH protocol algorithms (specifically SHA-1-based Exchange and MAC algorithms) were deprecated across my organization due to updated security policies. As a result, existing file transfer integrations—such as Export Sets and Scheduled Jobs that pushed data to an SFTP server—were no longer functioning. Given a very limited time window to resolve the issue, I needed a solution that would restore functionality with minimal changes to our existing transfer mechanisms.
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
If you're working on a project that involves extracting data from ServiceNow and transferring it via SFTP, you may encounter issues due to deprecated Exchange and MAC algorithms—specifically those using SHA-1 (SSH: sha-1), which are increasingly unsupported due to security concerns. Even if you have an existing solution in place, you may begin to experience security-related errors that prevent successful SFTP transactions.
ServiceNow provides a couple of out-of-the-box (OOB) options to address this: a configurable system property or a built-in flow. However, these standard solutions may not meet your specific requirements or may be incompatible with your setup.
This article outlines an alternative approach: leveraging a MID Server and PowerShell scripts to handle SFTP transfers using modern, supported encryption algorithms. This method allows for greater flexibility and ensures compliance with current security standards where native ServiceNow solutions fall short.
The MID Server must have network connectivity to the target SFTP server. If your current solution already involves a MID Server, you can reuse it for this purpose. Otherwise, you’ll need to coordinate with your network team to ensure the necessary ports are open and that the MID Server can successfully connect to the SFTP endpoint.
While you're working on establishing connectivity, you’ll also need to prepare the data for transfer from the ServiceNow instance where it resides—such as CIs, incidents, assets, and more. To facilitate this, you may need to create scheduled jobs that extract the relevant data (e.g., "Extract Assets," "Extract Incidents," etc.) at predefined intervals.
One of the use cases covered by the solution described in this article involves extracting data and generating Excel files based on that data (though they could also be text or CSV files, such as those produced by an export set operation). These files are stored on the MID Server, where another process compresses (zips) them. If you're interested in that part of the workflow, I’d be happy to cover it in a separate article.
Finally, the zipped file is transferred to the SFTP server using PowerShell. PowerShell supports modern security algorithms, and in this solution, I used the Posh-SSH library to handle the file transfer. I can also provide a separate guide on how to install and configure the Posh-SSH module, if you’re interested.
Now, below you can find the code that will trigger the actual file transfer. It is located inside a scheduled job (system definition > scheduled job). This job will create a ECC queue (ecc_queue) entry for the mid server to find it and process it:
//Below code will call the Powershell script
var aux = "powershell .\\scripts\\PowerShell\\SFTPCommon Script.ps1" + " -originalfilename " + originalfilename + " -finalfilename " + finalfilename + " -sftpHost " + sftpHost + " -sftpUser " + sftpUser + " -sftpPassw " + sftpPassw + " -localFilePath " + localFilePath + " -remoteFilePath " + remoteFilePath;
var payloadp = '<?xml version="1.0" encoding="UTF-8"?><parameters><parameter name="name" value="' + aux + '"/><parameter name="skip_sensor" value="true"/></parameters>';
//It will create a record in the Ecc queue
var grg = new GlideRecord("ecc_queue");
grg.initialize();
grg.agent = "mid.server." + mscomsftp;
grg.topic = "Command";
grg.name = "SFTP_PS_DLC";
grg.payload = payloadp;
grg.queue = "output";
grg.state = "ready";
grg.insert();
As you can see the previous job places the call to the Powershell script ( var aux = "powershell .\\scripts\\PowerShell\\SFTPCommon Script.ps1" + " -originalfilename " + originalfilename + " -finalfilename " + finalfilename + " -sftpHost " + sftpHost + " -sftpUser " + sftpUser + " -sftpPassw " + sftpPassw + " -localFilePath " + localFilePath + " -remoteFilePath " + remoteFilePath;).
After the script name, you can provide a list of parameters to the PowerShell script as long it is prepared to read and process them.
The script (SFTPCommonScript) should be placed under Mid server > script files and this is the actual code:
#Multipurpose script
#Doing a regular SFTP file transfer. You can not move and delete file. if both are true, the file will be moved over
#Requires -Version 5.1
# Install the Posh-SSH module if it's not already installed
[cmdletbinding()]
Param(
[string]$originalfilename,
#[string]$finalfilename,
[string]$sftpHost,
[string]$sftpUser,
[string]$sftpPassw,
[string]$localFilePath,
[string]$remoteFilePath,
[string]$sftpPort,
[string]$deleteFile,
[string]$moveFile,
[string]$localFilePathBkp
)
#{
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
try {
Get-Module -Name Posh-SSH -listavailable -ErrorAction Stop
Import-module -Name Posh-SSh -Force
}
catch {
Install-Module -Name Posh-SSH -Scope CurrentUser -Force
Import-module -Name Posh-SSh -Force
Get-Module -Name Posh-SSH -listavailable -ErrorAction Stop
}
# Set SFTP connection parameters
#If not coming, you can use this part when doing initial testing
$localFilePathFile =$localFilePath +$originalfilename
Write-Host "incoming values original path and file: '$localFilePathFile' "
$credSplat = @{
TypeName = 'System.Management.Automation.PSCredential'
ArgumentList = $sftpUser,($sftpPassw | ConvertTo-SecureString -AsPlainText -Force)
}
$Credential = New-Object @credSplat
#Establish SFTP connection and execute command
try {
#$localFilePath=$localFilePath+$finalfilename;
$auxfilename= $localFilePath+$finalfilename
}
catch{
Write-Error "An error occurred when renaming the file '$localFilePathFile': $($_.Exception.Message)"
}
try{
Write-Host "Connecting to SFTP server '$sftpHost'..."
$sftpSession = New-SFTPSession -ComputerName $sftpHost -Credential $Credential -Port $sftpPort -AcceptKey
Write-Host "Successfully connected to SFTP server."
}
catch{
Write-Error "An error occurred when connecting to the server: $($_.Exception.Message)"
}
Start-Sleep -Seconds 2
Try{
# Upload a file
Write-Host "Uploading file '$localFilePathFile'... to '$remoteFilePath' "
Set-SFTPItem -SessionId $sftpSession.SessionId -Path $localFilePathFile -Destination $remoteFilePath -Force
Write-Host "File uploaded successfully."
}
catch{
Write-Error "An error occurred when SFTPing the file '$localFilePathFile': $($_.Exception.Message)"
}
finally {
# Close the SFTP session
if ($sftpSession) {
Remove-SFTPSession -SessionId $sftpSession.SessionId
Write-Host "SFTP session closed."
#Delete the file
if ($moveFile -eq "true"){
write-host "Moving the file '$localFilePathFile' to '$localFilePathBkp'"
Move-Item $localFilePathFile -Destination $localFilePathBkp
}
else{
if ($deleteFile -eq "true"){
Remove-Item -Path $localFilePathFile
Write-Host "Delete the file: '$localFilePathFile'"
}
}
}
}
A brief description of key points:
1-A set of parameters is required like file name, path, target SFTP folder and others.
Param(
[string]$originalfilename,
#[string]$finalfilename,
[string]$sftpHost,
[string]$sftpUser,
[string]$sftpPassw,
[string]$localFilePath,
[string]$remoteFilePath,
[string]$sftpPort,
[string]$deleteFile,
[string]$moveFile,
[string]$localFilePathBkp
)
2- Next section checks Powershell libraries which are used in the script:
#{
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
try {
Get-Module -Name Posh-SSH -listavailable -ErrorAction Stop
Import-module -Name Posh-SSh -Force
}
catch {
Install-Module -Name Posh-SSH -Scope CurrentUser -Force
Import-module -Name Posh-SSh -Force
Get-Module -Name Posh-SSH -listavailable -ErrorAction Stop
}
3- Followed by a section that opens the connection to the SFTP server.
try{
Write-Host "Connecting to SFTP server '$sftpHost'..."
$sftpSession = New-SFTPSession -ComputerName $sftpHost -Credential $Credential -Port $sftpPort -AcceptKey
Write-Host "Successfully connected to SFTP server."
}
catch{
Write-Error "An error occurred when connecting to the server: $($_.Exception.Message)"
}
4- Later the actual transfer takes place.
Try{
# Upload a file
Write-Host "Uploading file '$localFilePathFile'... to '$remoteFilePath' "
Set-SFTPItem -SessionId $sftpSession.SessionId -Path $localFilePathFile -Destination $remoteFilePath -Force
Write-Host "File uploaded successfully."
}
catch{
Write-Error "An error occurred when SFTPing the file '$localFilePathFile': $($_.Exception.Message)"
}
5- Then a verification to confirm the transfer took place or if there was an error.
finally {
# Close the SFTP session
if ($sftpSession) {
Remove-SFTPSession -SessionId $sftpSession.SessionId
Write-Host "SFTP session closed."
#Delete the file
if ($moveFile -eq "true"){
write-host "Moving the file '$localFilePathFile' to '$localFilePathBkp'"
Move-Item $localFilePathFile -Destination $localFilePathBkp
}
else{
if ($deleteFile -eq "true"){
Remove-Item -Path $localFilePathFile
Write-Host "Delete the file: '$localFilePathFile'"
}
}
}
}
The ECC queue will store the output results of the Powershell script which can be helpful while you are validating or troubleshooting the script (normally the scheduled job will trigger the SFTP transaction). You can locate these by filtering entries based on topic and name ( grg.topic = "Command"; grg.name = "SFTP_PS_DLC";). Once the script is executed you should see an “input” message in the ECC queue that looks like this after processing:
<?xml version="1.0" encoding="UTF-8"?><results probe_time="9227"><result command="powershell .\scripts\PowerShell\SFTPCommonScript.ps1 -originalfilename multiCompressed.zip -finalfilename DeviceOrders_202508291305.zip -sftpHost prod.ef.company.com -sftpUser PDSMTOFCF -sftpPassw YLKPtYK2PESHbR7GUeIgfbcVdz -localFilePath E:/ServiceNow/MID6/agent/export/DCL/ -remoteFilePath /Altaris/SENDING/"><stdout>
Directory: C:\Users\itladm01\Documents\WindowsPowerShell\Modules
ModuleType Version Name ExportedCommands
---------- ------- ---- ----------------
Manifest 3.2.4 Posh-SSH {Get-SCPItem, Get-SFTPItem, New-SFTPSession, New-SSHSessio...
incoming values original path and file: 'E:/ServiceNow/MID6/agent/export/DCL/multiCompressed.zip'
Renaming file to 'DeviceOrders_202508291305.zip'
Connecting to SFTP server 'prod.ef.company.com'...
Successfully connected to SFTP server.
Uploading file 'E:/ServiceNow/MID6/agent/export/DCL/DeviceOrders_202508291305.zip'... to '/Altaris/SENDING/'
File uploaded successfully.
Moving the file
True
SFTP session closed.
</stdout><stderr/></result><parameters><parameter name="agent" value="mid.server.p1070573_mid1_las_prod_integ"/><parameter name="signature" value=""/><parameter name="response_to" value=""/><parameter name="from_sys_id" value=""/><parameter name="source" value=""/><parameter name="priority" value="2"/><parameter name="agent_correlator" value=""/><parameter name="skip_sensor" value="true"/><parameter name="processed" value=""/><parameter name="error_string" value=""/><parameter name="sys_id" value="4978c86b976fead025fa75271153afe0"/><parameter name="sequence" value="198f70178af0000001"/><parameter name="from_host" value=""/><parameter name="sys_created_on" value="2025-08-29 18:05:25"/><parameter name="sys_domain" value="global"/><parameter name="name" value="powershell .
The previous message includes both the output from the actual file transfer and any auxiliary messages you choose to send from within your PowerShell script.
Hopefully, you find this approach useful. You can create as many PowerShell scripts as needed to meet your specific requirements, it’s a highly flexible and powerful solution!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
If you're working on a project that involves extracting data from ServiceNow and transferring it via SFTP, you may encounter issues due to deprecated Exchange and MAC algorithms—specifically those using SHA-1 (SSH: sha-1), which are increasingly unsupported due to security concerns. Even if you have an existing solution in place, you may begin to experience security-related errors that prevent successful SFTP transactions.
ServiceNow provides a couple of out-of-the-box (OOB) options to address this: a configurable system property or a built-in flow. However, these standard solutions may not meet your specific requirements or may be incompatible with your setup.
This article outlines an alternative approach: leveraging a MID Server and PowerShell scripts to handle SFTP transfers using modern, supported encryption algorithms. This method allows for greater flexibility and ensures compliance with current security standards where native ServiceNow solutions fall short.
The MID Server must have network connectivity to the target SFTP server. If your current solution already involves a MID Server, you can reuse it for this purpose. Otherwise, you’ll need to coordinate with your network team to ensure the necessary ports are open and that the MID Server can successfully connect to the SFTP endpoint.
While you're working on establishing connectivity, you’ll also need to prepare the data for transfer from the ServiceNow instance where it resides—such as CIs, incidents, assets, and more. To facilitate this, you may need to create scheduled jobs that extract the relevant data (e.g., "Extract Assets," "Extract Incidents," etc.) at predefined intervals.
One of the use cases covered by the solution described in this article involves extracting data and generating Excel files based on that data (though they could also be text or CSV files, such as those produced by an export set operation). These files are stored on the MID Server, where another process compresses (zips) them. If you're interested in that part of the workflow, I’d be happy to cover it in a separate article.
Finally, the zipped file is transferred to the SFTP server using PowerShell. PowerShell supports modern security algorithms, and in this solution, I used the Posh-SSH library to handle the file transfer. I can also provide a separate guide on how to install and configure the Posh-SSH module, if you’re interested.
Now, below you can find the code that will trigger the actual file transfer. It is located inside a scheduled job (system definition > scheduled job). This job will create a ECC queue (ecc_queue) entry for the mid server to find it and process it:
//Below code will call the Powershell script
var aux = "powershell .\\scripts\\PowerShell\\SFTPCommon Script.ps1" + " -originalfilename " + originalfilename + " -finalfilename " + finalfilename + " -sftpHost " + sftpHost + " -sftpUser " + sftpUser + " -sftpPassw " + sftpPassw + " -localFilePath " + localFilePath + " -remoteFilePath " + remoteFilePath;
var payloadp = '<?xml version="1.0" encoding="UTF-8"?><parameters><parameter name="name" value="' + aux + '"/><parameter name="skip_sensor" value="true"/></parameters>';
//It will create a record in the Ecc queue
var grg = new GlideRecord("ecc_queue");
grg.initialize();
grg.agent = "mid.server." + mscomsftp;
grg.topic = "Command";
grg.name = "SFTP_PS_DLC";
grg.payload = payloadp;
grg.queue = "output";
grg.state = "ready";
grg.insert();
As you can see the previous job places the call to the Powershell script ( var aux = "powershell .\\scripts\\PowerShell\\SFTPCommon Script.ps1" + " -originalfilename " + originalfilename + " -finalfilename " + finalfilename + " -sftpHost " + sftpHost + " -sftpUser " + sftpUser + " -sftpPassw " + sftpPassw + " -localFilePath " + localFilePath + " -remoteFilePath " + remoteFilePath;).
After the script name, you can provide a list of parameters to the PowerShell script as long it is prepared to read and process them.
The script (SFTPCommonScript) should be placed under Mid server > script files and this is the actual code:
#Multipurpose script
#Doing a regular SFTP file transfer. You can not move and delete file. if both are true, the file will be moved over
#Requires -Version 5.1
# Install the Posh-SSH module if it's not already installed
[cmdletbinding()]
Param(
[string]$originalfilename,
#[string]$finalfilename,
[string]$sftpHost,
[string]$sftpUser,
[string]$sftpPassw,
[string]$localFilePath,
[string]$remoteFilePath,
[string]$sftpPort,
[string]$deleteFile,
[string]$moveFile,
[string]$localFilePathBkp
)
#{
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
try {
Get-Module -Name Posh-SSH -listavailable -ErrorAction Stop
Import-module -Name Posh-SSh -Force
}
catch {
Install-Module -Name Posh-SSH -Scope CurrentUser -Force
Import-module -Name Posh-SSh -Force
Get-Module -Name Posh-SSH -listavailable -ErrorAction Stop
}
# Set SFTP connection parameters
#If not coming, you can use this part when doing initial testing
$localFilePathFile =$localFilePath +$originalfilename
Write-Host "incoming values original path and file: '$localFilePathFile' "
$credSplat = @{
TypeName = 'System.Management.Automation.PSCredential'
ArgumentList = $sftpUser,($sftpPassw | ConvertTo-SecureString -AsPlainText -Force)
}
$Credential = New-Object @credSplat
#Establish SFTP connection and execute command
try {
#$localFilePath=$localFilePath+$finalfilename;
$auxfilename= $localFilePath+$finalfilename
}
catch{
Write-Error "An error occurred when renaming the file '$localFilePathFile': $($_.Exception.Message)"
}
try{
Write-Host "Connecting to SFTP server '$sftpHost'..."
$sftpSession = New-SFTPSession -ComputerName $sftpHost -Credential $Credential -Port $sftpPort -AcceptKey
Write-Host "Successfully connected to SFTP server."
}
catch{
Write-Error "An error occurred when connecting to the server: $($_.Exception.Message)"
}
Start-Sleep -Seconds 2
Try{
# Upload a file
Write-Host "Uploading file '$localFilePathFile'... to '$remoteFilePath' "
Set-SFTPItem -SessionId $sftpSession.SessionId -Path $localFilePathFile -Destination $remoteFilePath -Force
Write-Host "File uploaded successfully."
}
catch{
Write-Error "An error occurred when SFTPing the file '$localFilePathFile': $($_.Exception.Message)"
}
finally {
# Close the SFTP session
if ($sftpSession) {
Remove-SFTPSession -SessionId $sftpSession.SessionId
Write-Host "SFTP session closed."
#Delete the file
if ($moveFile -eq "true"){
write-host "Moving the file '$localFilePathFile' to '$localFilePathBkp'"
Move-Item $localFilePathFile -Destination $localFilePathBkp
}
else{
if ($deleteFile -eq "true"){
Remove-Item -Path $localFilePathFile
Write-Host "Delete the file: '$localFilePathFile'"
}
}
}
}
A brief description of key points:
1-A set of parameters is required like file name, path, target SFTP folder and others.
Param(
[string]$originalfilename,
#[string]$finalfilename,
[string]$sftpHost,
[string]$sftpUser,
[string]$sftpPassw,
[string]$localFilePath,
[string]$remoteFilePath,
[string]$sftpPort,
[string]$deleteFile,
[string]$moveFile,
[string]$localFilePathBkp
)
2- Next section checks Powershell libraries which are used in the script:
#{
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
try {
Get-Module -Name Posh-SSH -listavailable -ErrorAction Stop
Import-module -Name Posh-SSh -Force
}
catch {
Install-Module -Name Posh-SSH -Scope CurrentUser -Force
Import-module -Name Posh-SSh -Force
Get-Module -Name Posh-SSH -listavailable -ErrorAction Stop
}
3- Followed by a section that opens the connection to the SFTP server.
try{
Write-Host "Connecting to SFTP server '$sftpHost'..."
$sftpSession = New-SFTPSession -ComputerName $sftpHost -Credential $Credential -Port $sftpPort -AcceptKey
Write-Host "Successfully connected to SFTP server."
}
catch{
Write-Error "An error occurred when connecting to the server: $($_.Exception.Message)"
}
4- Later the actual transfer takes place.
Try{
# Upload a file
Write-Host "Uploading file '$localFilePathFile'... to '$remoteFilePath' "
Set-SFTPItem -SessionId $sftpSession.SessionId -Path $localFilePathFile -Destination $remoteFilePath -Force
Write-Host "File uploaded successfully."
}
catch{
Write-Error "An error occurred when SFTPing the file '$localFilePathFile': $($_.Exception.Message)"
}
5- Then a verification to confirm the transfer took place or if there was an error.
finally {
# Close the SFTP session
if ($sftpSession) {
Remove-SFTPSession -SessionId $sftpSession.SessionId
Write-Host "SFTP session closed."
#Delete the file
if ($moveFile -eq "true"){
write-host "Moving the file '$localFilePathFile' to '$localFilePathBkp'"
Move-Item $localFilePathFile -Destination $localFilePathBkp
}
else{
if ($deleteFile -eq "true"){
Remove-Item -Path $localFilePathFile
Write-Host "Delete the file: '$localFilePathFile'"
}
}
}
}
The ECC queue will store the output results of the Powershell script which can be helpful while you are validating or troubleshooting the script (normally the scheduled job will trigger the SFTP transaction). You can locate these by filtering entries based on topic and name ( grg.topic = "Command"; grg.name = "SFTP_PS_DLC";). Once the script is executed you should see an “input” message in the ECC queue that looks like this after processing:
<?xml version="1.0" encoding="UTF-8"?><results probe_time="9227"><result command="powershell .\scripts\PowerShell\SFTPCommonScript.ps1 -originalfilename multiCompressed.zip -finalfilename DeviceOrders_202508291305.zip -sftpHost prod.ef.company.com -sftpUser PDSMTOFCF -sftpPassw YLKPtYK2PESHbR7GUeIgfbcVdz -localFilePath E:/ServiceNow/MID6/agent/export/DCL/ -remoteFilePath /Altaris/SENDING/"><stdout>
Directory: C:\Users\itladm01\Documents\WindowsPowerShell\Modules
ModuleType Version Name ExportedCommands
---------- ------- ---- ----------------
Manifest 3.2.4 Posh-SSH {Get-SCPItem, Get-SFTPItem, New-SFTPSession, New-SSHSessio...
incoming values original path and file: 'E:/ServiceNow/MID6/agent/export/DCL/multiCompressed.zip'
Renaming file to 'DeviceOrders_202508291305.zip'
Connecting to SFTP server 'prod.ef.company.com'...
Successfully connected to SFTP server.
Uploading file 'E:/ServiceNow/MID6/agent/export/DCL/DeviceOrders_202508291305.zip'... to '/Altaris/SENDING/'
File uploaded successfully.
Moving the file
True
SFTP session closed.
</stdout><stderr/></result><parameters><parameter name="agent" value="mid.server.p1070573_mid1_las_prod_integ"/><parameter name="signature" value=""/><parameter name="response_to" value=""/><parameter name="from_sys_id" value=""/><parameter name="source" value=""/><parameter name="priority" value="2"/><parameter name="agent_correlator" value=""/><parameter name="skip_sensor" value="true"/><parameter name="processed" value=""/><parameter name="error_string" value=""/><parameter name="sys_id" value="4978c86b976fead025fa75271153afe0"/><parameter name="sequence" value="198f70178af0000001"/><parameter name="from_host" value=""/><parameter name="sys_created_on" value="2025-08-29 18:05:25"/><parameter name="sys_domain" value="global"/><parameter name="name" value="powershell .
The previous message includes both the output from the actual file transfer and any auxiliary messages you choose to send from within your PowerShell script.
Hopefully, you find this approach useful. You can create as many PowerShell scripts as needed to meet your specific requirements, it’s a highly flexible and powerful solution!