Nav links

Sunday, 5 August 2012

SFTP in Python

Last week I turned off FTP access to my hosted web pages because FTP is insecure and I already use SFTP in FileZilla for file transfers. A little later I realised that some of my python scripts use FTP, so they would stop working until they were modified. Unfortunately, it wasn't as easy as adding as 'S' to the address in the scripts!

I've always thought of SFTP as being Secure FTP, which it is in effect, though the name is actually an acronym for SSH file transfer protocol. FTP is built into the Python core, but SFTP is not. A bit of googling led to the general consensus that the easiest way to get SFTP capabilities into Python is to use the Paramiko module. Attempting to install this in 64-bit Windows 7 using  pip install paramiko led to error: Unable to find vcvarsall.bat. This is because Paramiko relies upon PyCrypto, a module written in C which needs to be compiled. On non-Windows systems compilers are normally already present so the module is compiled and installed without user intervention. In my case I don't have a compiler handy, and I don't want to install one just for this. Luckily there's an easy solution.

Some kind people have compiled PyCrypto on Windows and provide it via a Windows installer package. If you don't find a package exactly matching your version of Python and your version of Windows then it will refuse to install. I found pycrypto-2.3.win-amd64-py2.7.exe suitable for Python 2.7 in 64-bit Windows.  PyCrypto does work in Python 3 though I couldn't find a compiled version. I should add that you are introducing some risk at this point in relying in precompiled binaries. When compiling the source yourself you can confirm that it's not doing anything nefarious, but you have no such assurance with the precompiled code.  I'm assuming that if it looks like a trustworthy site, and other people trust it, then it's probably okay.

Once PyCrypto was installed Paramiko started working, and I was able to follow this straightforward example of using SFTP in Python to get  my scripts going again. It's a bit of a hassle getting all this set up, but for the added security of encrypting your passwords and data it is certainly worth it.

Finally, a completely different solution is to use an FTP to SFTP bridge, such as the excellent free Bitvise SSH Client. To the Python script I would then add a call to start the bridge just before the SFTP transfer, and use options such as -hide=main -loginonstartup -autoLogout -exitOnLogout to automatically stop the bridge when my transfer was complete. Such a bridge is also handy for software which supports FTP but not SFTP, such as Cobian Backup.