Using POSH-SSH in a scheduled task

This topic contains 5 replies, has 4 voices, and was last updated by  Mark Hammonds 1 year, 10 months ago.

  • Author
    Posts
  • #32701

    Mark MacLachlan
    Participant

    I have a script that connects in to an SFTP site using stored credentials. It copies a file locally, then disconnects from the site and connects to a second SFTP site and uploads the file to that site.

    The code works perfectly when I execute it as myself logged into the server as a domain admin.

    I have the script setup to run as a scheduled task. When the task runs it starts the script. The problem I am experiencing is that the script seems to be unable to establish the remote server session via SFTP. I added code to the script to send me an email when it starts, and had it grab module information to verify that the POSH-SSH module was properly running and it checks out OK. So I added code to send me the session.host name. This comes back as blank, so it seems the issue is when running as a scheduled task the session cannot establish. Can anyone let me know if they see a problem in the code?

    $ErrorActionPreference = "SilenetlyContinue"
    #==========================================================================
    #
    # NAME: SFTPCopy.ps1
    #
    # AUTHOR: Mark D. MacLachlan, Element Payment Services
    # DATE : 11/30/2015 10:29:51
    #
    # This code is copyright (c) 2015 Element Payment Services.
    #
    # All rights reserved.
    #
    # THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
    # ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
    # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
    # PARTICULAR PURPOSE.
    #
    # IN NO EVENT SHALL ELEMENT PAYMENT SERVICES AND/OR ITS RESPECTIVE
    # SUPPLIERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES
    # OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
    # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
    # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
    # OF THIS CODE OR INFORMATION.
    #
    # COMMENT:
    # This script requires the PowerShell SFTP Add on available free on GitHub.
    # To install the SFTP Add on run the following command within an elevated PowerShell command.
    # wget https://gist.github.com/darkoperator/6152630/raw/c67de4f7cd780ba367cccbc2593f38d18ce6df89/instposhsshdev | iex
    #
    #==========================================================================

    # Get the ID and security principal of the current user account
    $myWindowsID=[System.Security.Principal.WindowsIdentity]::GetCurrent()
    $myWindowsPrincipal=new-object System.Security.Principal.WindowsPrincipal($myWindowsID)

    # Get the security principal for the Administrator role
    $adminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator
    # Check to see if we are currently running "as Administrator"
    if ($myWindowsPrincipal.IsInRole($adminRole))
    {
    # We are running "as Administrator" - so change the title and background color to indicate this
    $Host.UI.RawUI.WindowTitle = $myInvocation.MyCommand.Definition + "(Elevated)"
    $Host.UI.RawUI.BackgroundColor = "DarkBlue"
    clear-host
    }
    else
    {
    # We are not running "as Administrator" - so relaunch as administrator
    # Create a new process object that starts PowerShell
    $newProcess = new-object System.Diagnostics.ProcessStartInfo "PowerShell";
    # Specify the current script path and name as a parameter
    $newProcess.Arguments = $myInvocation.MyCommand.Definition;
    # Indicate that the process should be elevated
    $newProcess.Verb = "runas";
    # Start the new process
    [System.Diagnostics.Process]::Start($newProcess);
    # Exit from the current, unelevated, process
    exit
    }

    # Run your code that needs to be elevated here

    #Import the SFTP Module & CmdLets
    Set-Location "C:\Program Files\WindowsPowerShell\Modules\"
    Import-Module posh-ssh

    #Get our stored credentials
    $encryptedSource = Get-Content C:\PSScripts\EncryptedELPSSFTP.txt | ConvertTo-SecureString
    $CredSource = New-Object System.Management.Automation.PsCredential("ELPSSFTP", $encryptedSource)

    #Get yesterdays date for our file
    $FileDate = (Get-Date).AddDays(-1)
    $FileDate = $FileDate.ToString("yyyyMMdd")
    #Get date for our file 2 days ago
    $FileDate2 = (Get-Date).AddDays(-2)
    $FileDate2 = $FileDate2.ToString("yyyyMMdd")
    #Get date for our file 3 days ago
    $FileDate3 = (Get-Date).AddDays(-3)
    $FileDate3 = $FileDate3.ToString("yyyyMMdd")

    #Create a session to get the files
    $Session = New-SFTPSession -ComputerName "mmm.ftpsvr.com" -Credential $CredSource -AcceptKey

    #Send an email the process has started
    #Email the list
    $Body = "SFTP Script Started `r`n $Session.Host"
    $Subject = "SFTP Upload Started"
    $SMTP = "phx1util01.company.prod"
    $To = "mmaclachlan@company.com"
    $From = "SFTP@company.com"
    Send-MailMessage -To $To -From $From -SmtpServer $SMTP -BodyAsHTML $Body -Subject $Subject

    #Download the files
    Get-SFTPFile -SFTPSession $Session -RemoteFile "/Inbox/FOTO_P0BCD71D_$FileDate" -LocalPath "C:\Temp\SFTP\"
    Get-SFTPFile -SFTPSession $Session -RemoteFile "/Inbox/FOTO_P0BCD71D_$FileDate2" -LocalPath "C:\Temp\SFTP\"
    Get-SFTPFile -SFTPSession $Session -RemoteFile "/Inbox/FOTO_P0BCD71D_$FileDate3" -LocalPath "C:\Temp\SFTP\"

    #Remove the session
    Get-SFTPsession | Remove-SFTPSession

    #Create a session to put our file up
    $encryptedDest = Get-Content C:\PSScripts\EncryptedCoreCMS_SFTP.txt | ConvertTo-SecureString
    $CredDest = New-Object System.Management.Automation.PsCredential("corecms", $encryptedDest)
    $Session2 = New-SFTPSession -ComputerName phx1sftp01.company.prod -Credential $CredDest -AcceptKey -Port 2222

    #Specify the local files
    Set-Location "C:\Temp\SFTP\"
    $LocalFiles = Get-ChildItem "C:\Temp\SFTP\"

    #Now copy the files up
    ForEach ($LocalFile in $LocalFiles)
    {
    Set-SFTPFile -SessionId 0 -LocalFile "$LocalFile" -RemotePath "/1020380/"
    }

    #Create a list of uploaded files
    $Files = (Get-SFTPChildItem -SessionId 0 -Path /1020380) | Select FullName | Sort-Object FullName
    #Email the list
    $Body = $Files.FullName -Join "`r`n"
    $Subject = "$FileDate SFTP Upload Report"
    Send-MailMessage -To $To -From $From -SmtpServer $SMTP -BodyAsHTML $Body -Subject $Subject

    #Remove the session
    Get-SFTPsession | Remove-SFTPSession

    #Remove the local files
    ForEach ($LocalFile in $LocalFiles)
    {
    Remove-Item $LocalFile -Force
    }

  • #32702

    Don Jones
    Keymaster

    Well, it's probably not the script if it works fine when run interactively. Basic troubleshooting: you've more or less eliminated the script as a problem, since it works fine in one scenario.

    So what's different between the scenarios? Credentials. Is the scheduled task running as a domain admin? Because you're manually retrieving principles – something the System account, which Task Scheduler normally uses, isn't necessarily allowed to do.

  • #32704

    Christian Sandfeld
    Participant

    My first thought goes to the encrypted password. Did you check that the RunAs account executing the script, can successfully decrypt it?

  • #32705

    Mark MacLachlan
    Participant

    You may be on to something there. Going to check the rights to that folder. Thanks

  • #32706

    Mark MacLachlan
    Participant

    Thanks guys you have both put me on the right track. I tested code to decode the encrypted password and I am able to do it as me, but the service account doesn't do it. I made sure the service account has rights to read the saved credential file and the folder they exist in, still no joy.

  • #32707

    Mark Hammonds
    Participant

    I think I read some were if you don't supply a key the encryption is tied to the account that encrypted it

    Try providing a key https://technet.microsoft.com/en-us/library/hh849818.aspx when you encrypt and decrypt it. I know I have done this before when I get to work tomorrow I will post what I have done.

    Article

    To recap my last blog, part 1 of Encrypting Credentials, when you use ConvertTo-SecureString and ConvertFrom-SecureString without a Key or SecureKey, Powershell will use Windows Data Protection API (DPAPI) to encrypt/decrypt your strings. This means that it will only work for the same user on the same computer.

You must be logged in to reply to this topic.