def shred(f): ''' Securely erases f with shred ''' process = subprocess.Popen(['shred', '-fuz', f], shell=False) if process.wait() == 0: # wait for shred to complete, check return code LOG.info("Shredded %s" % f) else: # some kind of error occurred; log LOG.error("Shredding %s failed: shred returned %s" % (f, process.returncode))
def encrypt(source_file, destination_dir=TEMPORARY_DIR, key=PUBLIC_KEY_ID): ''' GPG-encrypts source_file with key, saving encrypted file to destination_dir source_file -- absolute path of file to encrypt destination_dir -- absolute path of directory to save encrypted file in key -- keyid of public key to use; must be in gpg keyring Returns path to the encrypted file ''' # Init GPG gpg = gnupg.GPG() # Defaults to current user's $HOME/.gnupg public_keys = gpg.list_keys() assert key in [k['keyid'] for k in public_keys], \ "Could not find PUBLIC_KEY_ID in keyring" # Build encrypted filename and path e_filename = source_file.split("/")[-1] + ".gpg" ef_path = os.path.join(destination_dir, e_filename) # Might be easier just to do this with subprocess # p = subprocess.Popen( # ["gpg", "--output", ef_path, "--recipient", key, source_file], # shell=False # ) # if p.wait() == 0: ... # or use subprocess.call, .check_call, .check_output, etc try: fp = open(source_file, 'rb') encrypted_data = gpg.encrypt_file( fp, # file object to encrypt key, # public key of recipient output=ef_path # path to encrypted file ) fp.close() except IOError as e: LOG.error(e) # Hack - unfortunately, when GPG fails to encrypt a file, it prints an # error message to the console but does not provide a specific error # that python-gnupg can use. So we need to double check. assert os.path.exists(ef_path), \ "GPG encryption failed -- check the public key." LOG.info("Encrypted %s -> %s" % (source_file, ef_path)) return ef_path
def archive(*paths): """ *paths is an arbitrary number of absolute paths to files Returns the path to the archive file """ # Name based on the SHA256 sum of the first file archive_name = sha256(paths[0])[:16] + ".zip" archive_path = os.path.join(TEMPORARY_DIR, archive_name) zf = zipfile.ZipFile(archive_path, mode='w') try: for p in paths: if os.path.isfile(p): zf.write(p, arcname=p.split("/")[-1]) else: LOG.warning( "Tried to archive %s, which is not a file. Skipping." % p ) except Exception, err: LOG.error("Error from archive(): %s", err)
def main(): ''' Takes command line args as absolute paths to files to handle ''' if len(sys.argv) < 2: # program name is first arg sys.exit("Must provide at least one file to process") filenames = sys.argv[1:] try: # Write summary file sf_path = write_summary_file(filenames[0], filenames[1]) # Write noise file nf_path = write_noise_file() # Archive the files archive_path = archive(filenames[0], sf_path, nf_path) # Encrypt the archive ea_path = encrypt(archive_path) # Upload to S3 upload_to_s3(ea_path) # Shred everything for fn in filenames: shred(fn) shred(sf_path) shred(nf_path) shred(archive_path) shred(ea_path) except Exception, err: LOG.error(err)