Skip to content

Instantly share code, notes, and snippets.

@ericksond
Created April 9, 2014 19:14
Show Gist options
  • Save ericksond/10304575 to your computer and use it in GitHub Desktop.
Save ericksond/10304575 to your computer and use it in GitHub Desktop.
python module for secureftp with mget, mput and pgp support
import os, subprocess, shlex
class pgp(object):
def __init__(self, xfile):
self.xfile = xfile
def encrypt(self, recipient):
cmd = "gpg -e --trust-model always --yes -o "+ self.xfile +".pgp -r "+ recipient +" "+ self.xfile
try:
p = subprocess.Popen(shlex.split(cmd), shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = p.communicate()
if err:
return 'Failed'
else:
return 'Success'
except Exception, e:
return 'Failed'
print e
def decrypt(self):
cmd = "gpg -d -o "+ self.xfile.replace('.pgp','') +" "+ self.xfile
try:
p = subprocess.Popen(shlex.split(cmd), shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = p.communicate()
if err:
return 'Failed'
else:
return 'Success'
except Exception, e:
return 'Failed'
print e
import paramiko, os, re, glob, pgp, md5
from os import path, access, R_OK
class sftpconn(object):
rsa_private_key = r'/path/to/your/rsa.key'
def __init__(self, logfile, username, password, host, port, ssh_key):
paramiko.util.log_to_file(logfile)
print 'Establishing SSH connection to:', host, port, '...'
self.transport = paramiko.Transport((host, int(port)))
if ssh_key == True:
sshkey = paramiko.RSAKey.from_private_key_file(self.rsa_private_key)
self.transport.connect(username = username, pkey = sshkey)
else:
self.transport.connect(username = username, password = password)
self.sftp = paramiko.SFTPClient.from_transport(self.transport)
# check if the file exists
def check_file(self, PATH):
if path.exists(PATH) and path.isfile(PATH) and access(PATH, R_OK):
return 0
else:
return 1
# this function will allow the use of wildcards in between underscores, eg: file_*_name.txt
def is_match(self, a, b):
aa = a.split('_')
bb = b.split('_')
if len(aa) != len(bb): return False
for x, y in zip(aa, bb):
if not (x == y or x == '*' or y == '*'): return False
return True
def put(self, file_formats, local_dir, remote_dir, encrypt, pgp_recipient, remove_source):
actual_files = []
summary = ''
errors = 0
try:
for file_format in file_formats:
base_file_format = local_dir+file_format
# isolate global wildcards
m_globs = re.search("\*", file_format)
if m_globs:
for x in glob.glob(local_dir+file_format):
actual_files.append(x)
if len(actual_files) == 0:
summary += '[GLOBAL] No files matched the following format: ' + base_file_format + "\n"
errors += 1
else:
if self.check_file(base_file_format) == 0:
actual_files.append(base_file_format)
else:
summary += '[non-GLOBAL] Either file is missing or inaccessible: ' + base_file_format + "\n"
errors += 1
for actual_file in actual_files:
base_file = actual_file.replace(local_dir, '')
if encrypt == 1:
p = pgp.pgp(actual_file)
p.encrypt(pgp_recipient)
actual_file = actual_file + '.pgp'
base_file = base_file + '.pgp'
self.sftp.put(actual_file, remote_dir + base_file)
if remove_source == 1:
os.remove(actual_file.replace('.pgp', ''))
except Exception, e:
print e
if str(e) == '[Errno 2] No such file':
print e
else:
summary = summary + 'Error: ' + str(e)
errors += 1
if errors > 0:
return [summary, "This transaction failed with "+ str(errors) +" error/s:\n\n" + summary, 'Failed']
else:
return [summary, "File/s copied: " + str(actual_files), 'Success']
def get(self, file_formats, local_dir, remote_dir, encrypt, pgp_recipient):
files_copied = 0
errors = 0
summary = ''
actual_files = []
remote_files = []
try:
for f in self.sftp.listdir(remote_dir):
remote_files.append(f)
for file_format in file_formats:
print 'file_format:', file_format
base_file_format = remote_dir+file_format
m_globs = re.search("\*", file_format) # Check if file has global wildcard
if m_globs:
for f in remote_files:
if self.is_match(file_format, f):
actual_files.append(remote_dir+f)
else:
if file_format in remote_files:
actual_files.append(remote_dir+file_format)
else:
summary = '[non-GLOBAL] Either file is missing or inaccessible: ' + base_file_format
errors += 1
for actual_file in actual_files:
print 'actual_file:', actual_file
base_file = actual_file.replace(remote_dir, '')
self.sftp.get(actual_file, local_dir + base_file)
if encrypt == 1:
p = pgp.pgp(local_dir + base_file)
p.decrypt()
files_copied += 1
summary += "[Copied] " + local_dir + base_file + '\n'
if errors > 0 or files_copied == 0:
print 'summary:', summary
if files_copied == 0:
return [summary, "No files available for transfer.", 'No Files']
else:
return [summary, "This transaction failed with "+ str(errors) +" error/s:\n\n" + summary, 'Failed']
else:
return [summary, "Total file/s copied: %s. Summary: %s" % (str(files_copied), summary), 'Success']
except Exception, e:
print 'exception:', e
return [summary, "Error while copying file : " + str(e), 'Failed']
def mput(self, local, remote):
files_copied = 0
summary = ''
try:
for root, dirs, files in os.walk(local):
print files
for name in sorted(files):
filename = os.path.join(root, name)
self.sftp.put(filename, remote + name)
files_copied += 1
summary = summary + "Copied: " + remote + name + "\n"
return [summary, "Total file/s copied: " + str(files_copied), 'Success']
except Exception, e:
return [summary, "Error: " + str(e), 'Failed']
def mget(self, local, remote):
files_copied = 0
summary = ''
try:
for f in self.sftp.listdir(remote):
print f
self.sftp.get(remote+f, local+f)
files_copied += 1
summary = summary + "Copied: " + remote + f + "\n"
print summary
return [summary, "Total file/s copied: " + str(files_copied), 'Success']
except Exception, e:
print e
return [summary, "Error: " + str(e), 'Failed']
def chdir(self, dir):
self.sftp.chdir(dir)
def ls(self, remote):
return self.sftp.listdir(remote)
def close(self):
if self.transport.is_active():
self.sftp.close()
self.transport.close()
def __enter__(self):
return self
def __exit__(self, type, value, tb):
self.close()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment