def setUp(self): self.cwd = os.getcwd() self.local_project_testdir = "build-tests/remote-project/build" self.local_proj_zip_key = "zip_key.yaml" # executed from the same directory # remove all contents of the build directory and build directory path from prior test run if dir_exists('build-tests/remote-project/build'): shutil.rmtree('build-tests/remote-project/build') self.assertFalse(dir_exists('build-tests/remote-project/build')) # create the build directory path os.makedirs('build-tests/remote-project/build') self.assertTrue(dir_exists('build-tests/remote-project/build')) # move the key into the build directory fr_key = FileReader('build-tests/remote-project/zip_key.yaml') zip_key_data = fr_key.read() fw_key = FileWriter('build-tests/remote-project/build/zip_key.yaml') fw_key.write(zip_key_data) # confirm that the build files are present self.assertTrue(file_exists('build-tests/remote-project/build/zip_key.yaml')) # get the expected text for outfile write assertions self.fourohfour_text = FileReader('standards/404.html').read() self.indexhtml_text = FileReader('standards/index.html').read() self.jquery_text = FileReader('standards/jquery.js').read() self.normalize_text = FileReader('standards/normalize-min.css').read()
def setUp(self): self.cwd = os.getcwd() self.remote_packagerepo_testdir = "build-tests/remote-package-repo/build" self.package_repo_keypath = "build-tests/remote-package-repo/key.yaml" self.package_repo_missing_keypath = "build-tests/remote-package-repo/key_missingpackage.yaml" # remove all contents of the build directory and build directory path from prior test run if dir_exists(self.remote_packagerepo_testdir): shutil.rmtree(self.remote_packagerepo_testdir) self.assertFalse(dir_exists(self.remote_packagerepo_testdir)) # create the build directory path with empty directory os.makedirs(self.remote_packagerepo_testdir) self.assertTrue(dir_exists(self.remote_packagerepo_testdir)) # move the key with good file path into the build directory fr_key = FileReader('build-tests/remote-package-repo/key.yaml') key_data = fr_key.read() fw_key = FileWriter('build-tests/remote-package-repo/build/key.yaml') fw_key.write(key_data) # confirm that the build files are present self.assertTrue(file_exists('build-tests/remote-package-repo/build/key.yaml'))
def setUp(self): self.cwd = os.getcwd() self.test_dir = "pull-tests/remotefiles" self.test_text_file_dict = {"testfile.txt": "https://raw.githubusercontent.com/bit-store/testfiles/master/doxx/testfile.txt"} self.test_text_file_two_dict = {"testfile": "https://raw.githubusercontent.com/bit-store/testfiles/master/doxx/testfile"} self.test_text_file_three_dict = {"existdir/testfile.txt": "https://raw.githubusercontent.com/bit-store/testfiles/master/doxx/testfile.txt"} self.test_text_file_four_dict = {"nonexistdir/testfile.txt": "https://raw.githubusercontent.com/bit-store/testfiles/master/doxx/testfile.txt"} self.test_multi_text_files_dict = {"testfile.txt": "https://raw.githubusercontent.com/bit-store/testfiles/master/doxx/testfile.txt", "testfile": "https://raw.githubusercontent.com/bit-store/testfiles/master/doxx/testfile"} self.test_multi_text_files_two_dict = {"existdir/testfile.txt": "https://raw.githubusercontent.com/bit-store/testfiles/master/doxx/testfile.txt", "nonexistdir/testfile": "https://raw.githubusercontent.com/bit-store/testfiles/master/doxx/testfile"} self.test_bad_text_file_dict = {"testfile.txt": "https://raw.githubusercontent.com/bit-store/testfiles/master/doxx/nonexistenttextfile.txt"} # remove test files and directories if they exist from last test if file_exists("pull-tests/remotefiles/testfile.txt"): os.remove("pull-tests/remotefiles/testfile.txt") self.assertFalse(file_exists("pull-tests/remotefiles/testfile.txt")) if file_exists("pull-tests/remotefiles/existdir/testfile.txt"): os.remove("pull-tests/remotefiles/existdir/testfile.txt") self.assertFalse(file_exists("pull-tests/remotefiles/existdir/testfile.txt")) if dir_exists("pull-tests/nonexistdir"): shutil.rmtree("pull-tests/nonexistdir") self.assertFalse(dir_exists("pull-tests/nonexistdir"))
def test_crypto_untar_multitar_archives_cwd(self): shutil.copyfile(self.subdirs_encrypted_archive_sourcepath, self.subdirs_encrypted_archive_destpath) shutil.copyfile(self.singlefile_encrypted_archive_sourcepath, self.singlefile_encrypted_archive_destpath) # execute with testdir not working directory try: os.chdir(self.testdir) command = "decrypto subdirs.tar.crypt singlefile.tar.crypt" child = self.submit_same_passphrase(command) # directory writes occur in the proper spot self.assertTrue(dir_exists('subdirs')) self.assertTrue(dir_exists('singlefile')) # unpacked decrypted singlefile directory contains single file self.assertTrue(file_exists(os.path.join('singlefile', 'test.txt'))) # the tar archive is deleted, encrypted file is not self.assertFalse(file_exists('singlefile.tar')) self.assertTrue(file_exists('singlefile.tar.crypt')) # unpacked decrypted subdirs directory contains unpacked subdirectories self.assertTrue(dir_exists(os.path.join('subdirs', 'dir1'))) self.assertTrue(dir_exists(os.path.join('subdirs', 'dir2'))) # unpacked decrypted subdirs directory contains the correct path for unpacked file in subdirectory self.assertTrue(file_exists(os.path.join('subdirs', 'dir1', 'test.txt'))) # the tar archive is deleted, encrypted file is not self.assertFalse(file_exists('subdirs.tar')) self.assertTrue(file_exists('subdirs.tar.crypt')) child.close() # cleanup shutil.rmtree('subdirs') shutil.rmtree('singlefile') os.remove('subdirs.tar.crypt') os.remove('singlefile.tar.crypt') os.chdir(self.cwd) except Exception as e: os.chdir(self.cwd) raise e
def setUp(self): self.cwd = os.getcwd() self.test_dir = "pull-tests/ghrepo" self.repo_shortcode_master = "bit-store/testfiles" self.repo_shortcode_version = "bit-store/testfiles:v1.1" self.repo_shortcode_master_cherry_file = "bit-store/testfiles+doxx/testfile.txt" self.repo_shortcode_master_cherry_file_no_ext = "bit-store/testfiles+doxx/testfile" self.repo_shortcode_branch_cherry_file = "bit-store/testfiles:v1.1+doxx/testfile.txt" self.repo_shortcode_branch_cherry_file_no_ext = "bit-store/testfiles:v1.1+doxx/testfile" # error shortcodes self.error_plus_char_wrong_position = "bit-store+test.txt/testfiles" # plus symbol found after user, not repo self.error_colon_char_wrong_position = "bit-store:v1.1/testfiles" # colon symbol found after user, not repo self.error_plus_char_wrong_position_branch = "bit-store+test.txt/testfiles:v1.1" # plus symbol wrong position, non-master branch self.error_colon_char_wrong_position_branch = "bit-store:v1.1/testfiles:v1.1" # colon symbol wrong position, non-master branch self.error_missing_user = "******" # user doesn't exist on GH self.error_missing_repo = "bit-store/verybogus" # repo doesn't exist for actual GH user self.error_missing_branch = "bit-store/testfiles:v100.100.100" # missing branch number self.error_missing_file = "bit-store/testfiles+nonexistent.txt" # missing file in repo self.error_missing_dir = "bit-store/testfiles+baddir" # missing directory in repo self.error_deep_path = "bit-store/testfiles+" # remove any previous testing directories if dir_exists(os.path.join(self.test_dir, 'testfiles')): shutil.rmtree(os.path.join(self.test_dir, 'testfiles-master')) if dir_exists(os.path.join(self.test_dir, 'testfiles-1.1')): shutil.rmtree(os.path.join(self.test_dir, 'testfiles-1.1')) if dir_exists(os.path.join(self.test_dir, "doxx")): shutil.rmtree(os.path.join(self.test_dir, "doxx"))
def setUp(self): self.cwd = os.getcwd() self.targz_pull_dir = "pull-tests/targz" self.zip_pull_dir = "pull-tests/zip" self.gzip_pull_dir = "pull-tests/gzip" self.text_pull_dir = "pull-tests/text" if dir_exists(self.targz_pull_dir): if file_exists(os.path.join(self.targz_pull_dir, 'key.yaml')): os.remove(os.path.join(self.targz_pull_dir, 'key.yaml')) if file_exists(os.path.join(self.targz_pull_dir, 'test.doxt')): os.remove(os.path.join(self.targz_pull_dir, 'test.doxt')) if file_exists(os.path.join(self.targz_pull_dir, 'test2.doxt')): os.remove(os.path.join(self.targz_pull_dir, 'test2.doxt')) if dir_exists(self.zip_pull_dir): if file_exists(os.path.join(self.zip_pull_dir, 'key.yaml')): os.remove(os.path.join(self.zip_pull_dir, 'key.yaml')) if file_exists(os.path.join(self.zip_pull_dir, 'test.doxt')): os.remove(os.path.join(self.zip_pull_dir, 'test.doxt')) if file_exists(os.path.join(self.zip_pull_dir, 'test2.doxt')): os.remove(os.path.join(self.zip_pull_dir, 'test2.doxt')) if dir_exists(self.gzip_pull_dir): if file_exists(os.path.join(self.gzip_pull_dir, 'mit.doxt')): os.remove(os.path.join(self.gzip_pull_dir, 'mit.doxt')) if dir_exists(self.text_pull_dir): if file_exists(os.path.join(self.text_pull_dir, 'mit.doxt')): os.remove(os.path.join(self.text_pull_dir, 'mit.doxt'))
def test_doxx_github_shortcode_errors(self): try: os.chdir(self.test_dir) # + char in wrong position master branch pulls with self.assertRaises(SystemExit): run_pull(self.error_plus_char_wrong_position) # : char in wrong position master branch pulls with self.assertRaises(SystemExit): run_pull(self.error_colon_char_wrong_position) # + char in wrong position non-master branch pulls with self.assertRaises(SystemExit): run_pull(self.error_plus_char_wrong_position_branch) # : char in wrong position non-master branch pulls with self.assertRaises(SystemExit): run_pull(self.error_colon_char_wrong_position_branch) # bad username/org name in request with self.assertRaises(SystemExit): run_pull(self.error_missing_user) # bad repo name in request for an actual user/org with self.assertRaises(SystemExit): run_pull(self.error_missing_repo) # bad branch name for actual repository with self.assertRaises(SystemExit): run_pull(self.error_missing_branch) # cleanup if dir_exists('testfiles-master'): shutil.rmtree('testfiles-master') # bad file path for actual repository with self.assertRaises(SystemExit): run_pull(self.error_missing_file) # cleanup if dir_exists('testfiles_master'): shutil.rmtree('testfiles-master') # bad directory path for actual repository with self.assertRaises(SystemExit): run_pull(self.error_missing_dir) # cleanup if dir_exists('testfiles-master'): shutil.rmtree('testfiles-master') os.chdir(self.cwd) except Exception as e: os.chdir(self.cwd) raise e
def test_escape_tar_encrypt(self): try: # change to the sub test directory for tar tests os.chdir("testdir11") command = "crypto --tar testtar" child = self.submit_same_esc_passphrase(command) self.assertTrue(file_exists("testtar.tar.crypt")) # test new encrypted archive exists child.close() shutil.move('testtar', 'testtar_temp') decrypt_command = "decrypto testtar.tar.crypt" child = self.submit_same_esc_passphrase(decrypt_command) self.assertTrue(dir_exists(make_path("testtar"))) # test decrypted tar archive exists self.assertTrue(file_exists(make_path("testtar", "esc_test.txt"))) self.assertTrue(file_exists(make_path("testtar", "esc_test2.txt"))) child.close() # cleanup os.remove(make_path("testtar.tar.crypt")) # remove encrypted archive shutil.rmtree(make_path("testtar")) # remove the decrypted, unpacked directory shutil.move('testtar_temp', 'testtar') # move the original tar testing dir back to original path except Exception as e: # return to top level testing directory os.chdir(self.cwd) raise e finally: # return to top level testing directory os.chdir(self.cwd)
def test_crypto_untar_multifile_archive_cwd(self): shutil.copyfile(self.multifile_encrypted_archive_sourcepath, self.multifile_encrypted_archive_destpath) # execute with testdir as the working directory try: os.chdir(self.testdir) command = "decrypto multifile.tar.crypt" child = self.submit_same_passphrase(command) # directory write occurs in the proper spot self.assertTrue(dir_exists('multifile')) # unpacked decrypted directory contains correct multiple files self.assertTrue(file_exists(os.path.join('multifile', 'test.txt'))) self.assertTrue(file_exists(os.path.join('multifile', 'test2.txt'))) self.assertTrue(file_exists(os.path.join('multifile', 'test3.txt'))) # the tar archive is deleted, encrypted file is not self.assertFalse(file_exists('multifile.tar')) self.assertTrue(file_exists('multifile.tar.crypt')) child.close() # cleanup shutil.rmtree('multifile') os.remove('multifile.tar.crypt') os.chdir(self.cwd) except Exception as e: os.chdir(self.cwd) raise e
def _create_dirs(file_path): """Creates a recursive directory path to the requested file name if it does not exist. [file_path] must have correct OS path separators as they are not checked in this function""" dir_path = os.path.dirname(file_path) if dir_exists(dir_path): pass else: os.makedirs(dir_path)
def _is_testdir_at_this_level(self): if file_exists('setup.py'): if dir_exists('tests'): return True else: return False else: return False
def test_crypto_tar_commandline_multidir_and_file(self): command = "crypto --tar testdir9/tar_dir testdir9/tar_dir_two testdir9/nontar.txt" child = pexpect.spawn(command) child.expect("Please enter your passphrase: ") child.sendline("test") child.expect("Please enter your passphrase again: ") child.sendline("test") child.expect( "\r\ntestdir9/nontar.txt.crypt was generated from testdir9/nontar.txt\r\n" ) child.expect( "testdir9/tar_dir.tar.crypt was generated from testdir9/tar_dir.tar\r\n" ) child.expect( "testdir9/tar_dir_two.tar.crypt was generated from testdir9/tar_dir_two.tar\r\n" ) self.assertTrue(file_exists(make_path('testdir9', 'tar_dir.tar.crypt')) ) # confirm that the encrypted tar file is there self.assertFalse(file_exists( make_path('testdir9', 'tar_dir.tar'))) # confirm that the tar file is removed self.assertTrue(dir_exists(make_path( 'testdir9', 'tar_dir'))) # confirm that the test directory is not removed self.assertTrue( file_exists(make_path('testdir9', 'tar_dir_two.tar.crypt')) ) # confirm that the encrypted tar file is there self.assertFalse(file_exists(make_path( 'testdir9', 'tar_dir_two.tar'))) # confirm that the tar file is removed self.assertTrue(dir_exists(make_path( 'testdir9', 'tar_dir_two'))) # confirm that the test directory is not removed self.assertTrue(file_exists(make_path('testdir9', 'nontar.txt.crypt'))) self.assertTrue(file_exists( make_path('testdir9', 'nontar.txt'))) # confirm that the file was not removed child.close() os.remove('testdir9/tar_dir.tar.crypt') os.remove('testdir9/tar_dir_two.tar.crypt') os.remove('testdir9/nontar.txt.crypt')
def _is_testdir_at_this_level(self): if file_exists('setup.py'): if dir_exists('tests'): return True else: return False #found setup.py but no tests directory else: return False # setup.py not at this level
def test_crypto_untar_nofile_archive_notcwd(self): shutil.copyfile(self.nofile_encrypted_archive_sourcepath, self.nofile_encrypted_archive_destpath) # execute with testdir not working directory command = "decrypto testdir10/nofile.tar.crypt" child = self.submit_same_passphrase(command) # directory write occurs in the proper spot self.assertTrue(dir_exists('testdir10/nofile')) # the tar archive is deleted, encrypted file is not self.assertFalse(file_exists('testdir10/nofile.tar')) self.assertTrue(file_exists('testdir10/nofile.tar.crypt')) # there is no directory written to the current working directory self.assertFalse(dir_exists('nofile')) child.close() # cleanup shutil.rmtree('testdir10/nofile') os.remove(os.path.join('testdir10', 'nofile.tar.crypt'))
def test_local_project_zip_build(self): try: # make the build directory the CWD os.chdir(self.local_project_testdir) # run the project build b = Builder(self.local_proj_zip_key) b.run() # confirm directory unpacked with correct directory structure self.assertTrue(dir_exists('html-initializr-master')) self.assertTrue(dir_exists('html-initializr-master/css')) self.assertTrue(dir_exists('html-initializr-master/js/vendor')) self.assertTrue(dir_exists('html-initializr-master/templates')) # confirm presence of files self.assertTrue(file_exists('html-initializr-master/index.html')) self.assertTrue(file_exists('html-initializr-master/404.html')) self.assertTrue(file_exists('html-initializr-master/pkey.yaml')) self.assertTrue(file_exists('html-initializr-master/project.yaml')) self.assertTrue(file_exists('html-initializr-master/js/vendor/jquery-1.11.1.min.js')) self.assertTrue(file_exists('html-initializr-master/js/vendor/modernizr-2.6.2.min.js')) self.assertTrue(file_exists('html-initializr-master/css/normalize.min.css')) # confirm that the project archive file was removed during build self.assertFalse(file_exists('initializr.zip')) # confirm that the key file still present in the directory after the build self.assertTrue(file_exists('zip_key.yaml')) # read the new outfiles that were generated from templates rendered_fourohfour = FileReader('html-initializr-master/404.html').read() rendered_index = FileReader('html-initializr-master/index.html').read() rendered_jquery = FileReader('html-initializr-master/js/vendor/jquery-1.11.1.min.js').read() rendered_normalize = FileReader('html-initializr-master/css/normalize.min.css').read() # assert correct contents of the files developed from templates self.assertEqual(self.fourohfour_text, rendered_fourohfour) self.assertEqual(self.indexhtml_text, rendered_index) self.assertEqual(self.jquery_text, rendered_jquery) self.assertEqual(self.normalize_text, rendered_normalize) os.chdir(self.cwd) except Exception as e: os.chdir(self.cwd) raise e
def setUp(self): self.pre_tardir_path = "testdir9/tar_dir" self.post_tardir_path = "testdir9/tar_dir.tar" self.pre_tardir2_path = "testdir9/tar_dir_two" self.post_tardir2_path = "testdir9/tar_dir_two.tar" self.pre_tardir_file_path = "testdir9/tar_dir/test.txt" self.pre_tardir2_file_path = "testdir9/tar_dir_two/test.txt" self.testdir_good_list = [self.pre_tardir_path] self.testdir_good_multidir_list = [ self.pre_tardir_path, self.pre_tardir2_path ] if not dir_exists(self.pre_tardir_path): stderr( "missing test directory for the CryptoTarArchiveTest in test_tar-archive.py test module", exit=1) if not file_exists(self.pre_tardir_file_path): stderr( "missing test file for the CryptoTarArchiveTest in the test_tar-archive.py test module", exit=1) if not dir_exists(self.pre_tardir2_path): stderr( "missing test directory for the CryptoTarArchiveTest in test_tar-archive.py test module", exit=1) if not file_exists(self.pre_tardir2_file_path): stderr( "missing test file for the CryptoTarArchiveTest in the test_tar-archive.py test module", exit=1) # cleanup files from old tests if still around if file_exists(self.post_tardir_path): os.remove(self.post_tardir_path) if file_exists(self.post_tardir2_path): os.remove(self.post_tardir2_path) if file_exists(self.post_tardir_path) or file_exists( self.post_tardir2_path): stderr( "unable to delete testfile in setup for CryptoTarArchiveTest in the test_tar-archive.py test module", exit=1)
def setUp(self): self.cwd = os.getcwd() self.key_pull_dir = "pull-tests/key" self.pulled_key_file = "key.yaml" if dir_exists(self.key_pull_dir): if file_exists(os.path.join(self.key_pull_dir, self.pulled_key_file)): os.remove(os.path.join(self.key_pull_dir, self.pulled_key_file)) # remove the file from the last test else: os.mkdir(self.key_pull_dir)
def test_crypto_untar_singlefile_archive_notcwd(self): shutil.copyfile(self.singlefile_encrypted_archive_sourcepath, self.singlefile_encrypted_archive_destpath) # execute with testdir not working directory command = "decrypto testdir10/singlefile.tar.crypt" child = self.submit_same_passphrase(command) # directory write occurs in the proper spot self.assertTrue(dir_exists('testdir10/singlefile')) # unpacked decrypted directory contains single file self.assertTrue(file_exists(os.path.join('testdir10', 'singlefile', 'test.txt'))) # the tar archive is deleted, encrypted file is not self.assertFalse(file_exists('testdir10/singlefile.tar')) self.assertTrue(file_exists('testdir10/singlefile.tar.crypt')) # there is no directory written to the current working directory self.assertFalse(dir_exists('singlefile')) child.close() # cleanup shutil.rmtree('testdir10/singlefile') os.remove(os.path.join('testdir10', 'singlefile.tar.crypt'))
def test_doxx_github_shortcode_branch(self): try: os.chdir(self.test_dir) run_pull(self.repo_shortcode_version) self.assertTrue(dir_exists("testfiles-1.1")) self.assertTrue(dir_exists("testfiles-1.1/doxx")) self.assertTrue(dir_exists("testfiles-1.1/doxx/templates")) self.assertTrue(file_exists("testfiles-1.1/doxx/testfile")) self.assertTrue(file_exists("testfiles-1.1/doxx/testfile.txt")) # execute the command again and confirm that it overwrites the directory with same name run_pull(self.repo_shortcode_version) #cleanup shutil.rmtree("testfiles-1.1") os.chdir(self.cwd) except Exception as e: os.chdir(self.cwd) raise e
def test_doxx_github_shortcode_master(self): try: os.chdir(self.test_dir) run_pull(self.repo_shortcode_master) self.assertTrue(dir_exists("testfiles-master")) self.assertTrue(dir_exists("testfiles-master/doxx")) self.assertTrue(dir_exists("testfiles-master/doxx/templates")) self.assertTrue(file_exists("testfiles-master/doxx/testfile")) self.assertTrue(file_exists("testfiles-master/doxx/testfile.txt")) # execute the command a second time and confirm that the repository overwrites the testfiles directory without exception run_pull(self.repo_shortcode_master) # cleanup shutil.rmtree("testfiles-master") os.chdir(self.cwd) except Exception as e: os.chdir(self.cwd) raise e
def test_crypto_untar_overwrite_switch_performs_overwrite(self): shutil.copyfile(self.singlefile_encrypted_archive_sourcepath, self.singlefile_encrypted_archive_destpath) # execute first time to generate a decrypted, unpacked archive command = "decrypto testdir10/singlefile.tar.crypt" child = self.submit_same_passphrase(command) # confirm that the archive was unpacked self.assertTrue(dir_exists(os.path.join('testdir10', 'singlefile'))) self.assertTrue(file_exists(os.path.join('testdir10', 'singlefile', 'test.txt'))) child.close() # execute the command again and overwrite existing files, assert that does not raise error command = "decrypto --overwrite testdir10/singlefile.tar.crypt" child = self.submit_same_passphrase(command) # confirm that the directory and file are there self.assertTrue(dir_exists(os.path.join('testdir10', 'singlefile'))) self.assertTrue(file_exists(os.path.join('testdir10', 'singlefile', 'test.txt'))) child.close() # cleanup shutil.rmtree(os.path.join('testdir10', 'singlefile')) os.remove(os.path.join('testdir10', 'singlefile.tar.crypt'))
def _remove_doxt(): # check main directory cwd_doxt_list = list_filter_files_cwd(".doxt") # check for a templates directory if dir_exists('templates'): templates_dir_doxt_list = list_filter_files(".doxt", "templates") else: templates_dir_doxt_list = [] # remove template files from the working directory if len(cwd_doxt_list) > 0: for doxt_file in cwd_doxt_list: try: remove(doxt_file) stdout("[-] doxx: -- " + doxt_file + " ... removed") except Exception as e: stderr("[!] doxx: Unable to remove the file " + doxt_file + "'. Error: " + str(e), exit=0) # remove any template files from the templates directory if len(templates_dir_doxt_list) > 0: for doxt_file in templates_dir_doxt_list: new_doxt_path = make_path('templates', doxt_file) remove(new_doxt_path) stdout("[-] doxx: -- " + new_doxt_path + " ... removed") # if there are files still remaining in the templates directory, leave it # otherwise, remove the templates directory as well if dir_exists('templates'): remaining_template_file_list = list_all_files('templates') # get the remaining non-.doxt files in the directory if len(remaining_template_file_list) > 0: pass # do nothing, skip the removal of the 'templates' directory from the project because other files are present in it else: try: rmtree('templates') stdout("[-] doxx: -- templates (directory) ... removed") except Exception as e: stderr("[!] doxx: Unable to remove the 'templates' directory. Error: " + str(e), exit=1)
def test_crypto_untar_multitar_archives_notcwd(self): shutil.copyfile(self.subdirs_encrypted_archive_sourcepath, self.subdirs_encrypted_archive_destpath) shutil.copyfile(self.singlefile_encrypted_archive_sourcepath, self.singlefile_encrypted_archive_destpath) # execute with testdir not working directory command = "decrypto testdir10/subdirs.tar.crypt testdir10/singlefile.tar.crypt" child = self.submit_same_passphrase(command) # directory writes occur in the proper spot self.assertTrue(dir_exists('testdir10/subdirs')) # write occurs in testdir10 self.assertTrue(dir_exists('testdir10/singlefile')) self.assertFalse(dir_exists('subdirs')) # not in cwd self.assertFalse(dir_exists('singlefile')) # unpacked decrypted singlefile directory contains single file self.assertTrue(file_exists(os.path.join('testdir10', 'singlefile', 'test.txt'))) # the tar archive is deleted, encrypted file is not self.assertFalse(file_exists('testdir10/singlefile.tar')) self.assertTrue(file_exists('testdir10/singlefile.tar.crypt')) # unpacked decrypted subdirs directory contains unpacked subdirectories self.assertTrue(dir_exists(os.path.join('testdir10', 'subdirs', 'dir1'))) self.assertTrue(dir_exists(os.path.join('testdir10', 'subdirs', 'dir2'))) # unpacked decrypted subdirs directory contains the correct path for unpacked file in subdirectory self.assertTrue(file_exists(os.path.join('testdir10', 'subdirs', 'dir1', 'test.txt'))) # the tar archive is deleted, encrypted file is not self.assertFalse(file_exists('testdir10/subdirs.tar')) self.assertTrue(file_exists('testdir10/subdirs.tar.crypt')) child.close() # cleanup shutil.rmtree('testdir10/subdirs') shutil.rmtree('testdir10/singlefile') os.remove('testdir10/subdirs.tar.crypt') os.remove('testdir10/singlefile.tar.crypt')
def replace_test_files(self): """replace the erased test files in the test directories""" # replace the files in the with-only-templates directory # make the directory if not dir_exists(make_path(self.onlytemplates_dir, 'templates')): os.makedirs(make_path(self.onlytemplates_dir, 'templates')) with_only_templates_files = ['key.yaml', 'pkey.yaml', 'project.yaml', 'templates/404.doxt', 'templates/index.doxt', 'templates/normalize.doxt'] for the_file in with_only_templates_files: fw = FileWriter(make_path(self.onlytemplates_dir, the_file)) fw.write("unimportant text") # replace the files in the with-templates-other-files directory # make the directory if not present if not dir_exists(make_path(self.otherfiles_dir, 'templates')): os.makedirs(make_path(self.otherfiles_dir, 'templates')) with_other_files = ['key.yaml', 'pkey.yaml', 'project.yaml', 'templates/404.doxt', 'templates/index.doxt', 'templates/normalize.doxt', 'templates/dontdeleteme.txt'] for the_file in with_other_files: fw = FileWriter(make_path(self.otherfiles_dir, the_file)) fw.write("unimportant text")
def test_crypto_untar_subdirs_archive_notcwd(self): shutil.copyfile(self.subdirs_encrypted_archive_sourcepath, self.subdirs_encrypted_archive_destpath) # execute with testdir not working directory command = "decrypto testdir10/subdirs.tar.crypt" child = self.submit_same_passphrase(command) # directory write occurs in the proper spot self.assertTrue(dir_exists('testdir10/subdirs')) # unpacked decrypted directory contains unpacked subdirectories self.assertTrue(dir_exists(os.path.join('testdir10', 'subdirs', 'dir1'))) self.assertTrue(dir_exists(os.path.join('testdir10', 'subdirs', 'dir2'))) # unpacked decrypted directory contains the correct path for unpacked file in subdirectory self.assertTrue(file_exists(os.path.join('testdir10', 'subdirs', 'dir1', 'test.txt'))) # the tar archive is deleted, encrypted file is not self.assertFalse(file_exists('testdir10/subdirs.tar')) self.assertTrue(file_exists('testdir10/subdirs.tar.crypt')) # there is no directory written to the current working directory self.assertFalse(dir_exists('subdirs')) child.close() # cleanup shutil.rmtree('testdir10/subdirs') os.remove(os.path.join('testdir10', 'subdirs.tar.crypt'))
def test_crypto_untar_no_untar_when_nountar_switch(self): shutil.copyfile(self.singlefile_encrypted_archive_sourcepath, self.singlefile_encrypted_archive_destpath) # execute with testdir not working directory command = "decrypto --nountar testdir10/singlefile.tar.crypt" child = self.submit_same_passphrase(command) # confirm that the tar archive is not unpacked self.assertTrue(file_exists(os.path.join('testdir10', 'singlefile.tar'))) self.assertFalse(dir_exists(os.path.join('testdir10', 'singlefile'))) child.close() # cleanup os.remove(os.path.join('testdir10', 'singlefile.tar')) os.remove(os.path.join('testdir10', 'singlefile.tar.crypt'))
def generate_tar_files(directory_list): """Public function that reads a list of local directories and generates tar archives from them""" tar_file_list = [] for directory in directory_list: if dir_exists(directory): _generate_tar(directory) # create the tar archive tar_file_list.append(directory + '.tar') # append the tar archive filename to the returned tar_file_list list else: stderr("The directory '" + directory + "' does not exist and a tar archive could not be created from it.", exit=1) return tar_file_list
def generate_tar_files(directory_list): """Public function that reads a list of local directories and generates tar archives from them""" tar_file_list = [] for directory in directory_list: if dir_exists(directory): _generate_tar(directory) # create the tar archive tar_file_list.append( directory + '.tar' ) # append the tar archive filename to the returned tar_file_list list else: stderr( "The directory '" + directory + "' does not exist and a tar archive could not be created from it.", exit=1) return tar_file_list
def test_make_project(self): try: os.chdir(self.test_dir) response = muterun('doxx make project') if not response.exitcode == 0: stderr("Error with 'doxx make project' command. Error: " + response.stderr, exit=1) else: self.assertTrue(file_exists(self.pkey_file_path)) # confirm that the pkey.yaml file was made self.assertTrue(file_exists(self.projyaml_file_path)) # confirm that the project.yaml file was made self.assertTrue(file_exists(self.template_file_path)) # confirm that the template file was made self.assertTrue(dir_exists(self.templates_dir)) # confirm that the 'templates' directory was made os.remove(self.pkey_file_path) # remove the test key file after the test os.remove(self.projyaml_file_path) os.remove(self.template_file_path) # remove the test template file shutil.rmtree(self.templates_dir) # remove the templates directory os.chdir(self.cwd) except Exception as e: os.chdir(self.cwd) raise e
def test_crypto_untar_no_file_archive_cwd(self): shutil.copyfile(self.nofile_encrypted_archive_sourcepath, self.nofile_encrypted_archive_destpath) # execute with testdir as the working directory try: os.chdir(self.testdir) command = "decrypto nofile.tar.crypt" child = self.submit_same_passphrase(command) # directory write occurs in the proper spot self.assertTrue(dir_exists('nofile')) # the tar archive is deleted, encrypted file is not self.assertFalse(file_exists('nofile.tar')) self.assertTrue(file_exists('nofile.tar.crypt')) child.close() # cleanup shutil.rmtree('nofile') os.remove('nofile.tar.crypt') os.chdir(self.cwd) except Exception as e: os.chdir(self.cwd) raise e
def test_crypto_untar_overwrite_fails_without_overwrite_switch(self): shutil.copyfile(self.singlefile_encrypted_archive_sourcepath, self.singlefile_encrypted_archive_destpath) # execute first time to generate a decrypted, unpacked archive command = "decrypto testdir10/singlefile.tar.crypt" child = self.submit_same_passphrase(command) # confirm that the archive was unpacked self.assertTrue(dir_exists(os.path.join('testdir10', 'singlefile'))) self.assertTrue(file_exists(os.path.join('testdir10', 'singlefile', 'test.txt'))) child.close() # execute the command again and confirm that it raises error message, no file overwrite command = "decrypto testdir10/singlefile.tar.crypt" child = pexpect.spawn(command) child.expect("Please enter your passphrase: ") child.sendline("test") child.expect("Please enter your passphrase again: ") child.sendline("test") child.expect("Failed to unpack the file 'testdir10/singlefile/test.txt'. File already exists. Use the --overwrite flag to replace existing files.") child.close() # cleanup shutil.rmtree(os.path.join('testdir10', 'singlefile')) os.remove(os.path.join('testdir10', 'singlefile.tar.crypt'))
def test_doxx_clean_other_files_in_templates_directory(self): try: os.chdir('clean-tests/with-templates-other-files') # confirm files present before clean is executed self.assertTrue(file_exists('key.yaml')) self.assertTrue(file_exists('pkey.yaml')) self.assertTrue(file_exists('project.yaml')) self.assertTrue(file_exists('templates/404.doxt')) self.assertTrue(file_exists('templates/index.doxt')) self.assertTrue(file_exists('templates/normalize.doxt')) # execute clean run_clean() # confirm that the files are now gone self.assertFalse(file_exists('key.yaml')) self.assertFalse(file_exists('pkey.yaml')) self.assertFalse(file_exists('project.yaml')) self.assertFalse(file_exists('templates/404.doxt')) self.assertFalse(file_exists('templates/index.doxt')) self.assertFalse(file_exists('templates/normalize.doxt')) # confirm that the templates directory is still present self.assertTrue(dir_exists('templates')) # and that the non-doxx file that was present in it is still there self.assertTrue(file_exists('templates/dontdeleteme.txt')) # confirm that the other project files are still present self.assertTrue(file_exists('crossdomain.xml')) self.assertTrue(file_exists('index.html')) self.assertTrue(file_exists('humans.txt')) self.assertTrue(file_exists('robots.txt')) # return to the testing working directory os.chdir(self.cwd) except Exception as e: os.chdir(self.cwd) # make sure that the CWD is re-established before rasing the exception raise e
def setUp(self): self.cwd = os.getcwd() self.test_dir = "make-tests" self.template_file = "stub.doxt" self.templates_dir = "templates" # paths (with test_dir as root directory) self.template_file_path = os.path.join(self.templates_dir, self.template_file) self.key_file_path = "key.yaml" self.pkey_file_path = "pkey.yaml" self.projyaml_file_path = "project.yaml" # clean up directory from last test run (if any files left over) # remove key file if file_exists(os.path.join(self.test_dir, self.key_file_path)): os.remove(os.path.join(self.test_dir, self.key_file_path)) if file_exists(os.path.join(self.test_dir, self.key_file_path)): stderr("Unable to remove test file '" + os.path.join(self.test_dir, self.key_file_path) + "' for make command tests") # remove template file if file_exists(os.path.join(self.test_dir, self.template_file_path)): os.remove(os.path.join(self.test_dir, self.template_file_path)) if file_exists(os.path.join(self.test_dir, self.template_file_path)): stderr("Unable to remove test file '" + os.path.join(self.test_dir, self.template_file_path) + "' for make command tests") if file_exists(os.path.join(self.test_dir, self.pkey_file_path)): os.remove(os.path.join(self.test_dir, self.pkey_file_path)) if file_exists(os.path.join(self.test_dir, self.pkey_file_path)): stderr("Unable to remove test file '" + os.path.join(self.test_dir, self.pkey_file_path) + "' for make command tests") if file_exists(os.path.join(self.test_dir, self.projyaml_file_path)): os.remove(os.path.join(self.test_dir, self.projyaml_file_path)) if file_exists(os.path.join(self.test_dir, self.projyaml_file_path)): stderr("Unable to remove test file '" + os.path.join(self.test_dir, self.projyaml_file_path) + "' for make command tests") # remove templates directory and any files in the directory if dir_exists(os.path.join(self.test_dir, self.templates_dir)): shutil.rmtree(os.path.join(self.test_dir, self.templates_dir))
def make_project(self): try: # project.yaml file write fw_projyaml = FileWriter('project.yaml') fw_projyaml.write(project_yaml_stub) # pkey.yaml file write fw_pkey = FileWriter('pkey.yaml') fw_pkey.write(key_stub) # templates directory write if not dir_exists('templates'): os.mkdir('templates') # template.doxt file in templates directory template_stub_path = os.path.join('templates', 'stub.doxt') fw_template = FileWriter(template_stub_path) fw_template.write(template_stub) # confirm for user if file_exists('project.yaml'): stdout("[+] doxx: 'project.yaml' ... check") else: stderr("[!] doxx: There was an error writing the 'project.yaml' key file to your project directory") if file_exists('pkey.yaml'): stdout("[+] doxx: 'pkey.yaml' ... check") else: stderr("[!] doxx: There was an error writing the 'pkey.yaml' key file to your project directory") if file_exists(template_stub_path): stdout("[+] doxx: '" + template_stub_path + "' ... check") else: stderr("[!] doxx: There was an error writing the '" + template_stub_path + "' template file to your project directory") except Exception as e: stderr("[!] doxx: Unable to write project files to disk. Error: " + str(e), exit=1)
def test_sys_dir_exists_missing_dir(self): """Test for existence of a directory that does not exist""" self.assertEqual( False, system.dir_exists(os.path.join("bogusdir", "anotherdir")))
def _is_lib_at_this_level(self): if dir_exists('lib'): return True else: return False
def main(): import os import sys from time import sleep import getpass import tarfile from Naked.commandline import Command from Naked.toolshed.shell import execute, muterun from Naked.toolshed.system import dir_exists, file_exists, list_all_files, make_path, stdout, stderr, is_dir from shellescape import quote # ------------------------------------------------------------------------------------------ # [ Instantiate command line object ] # used for all subsequent conditional logic in the CLI application # ------------------------------------------------------------------------------------------ c = Command(sys.argv[0], sys.argv[1:]) # ------------------------------------------------------------------------------------------ # [ VALIDATION LOGIC ] - early validation of appropriate command syntax # Test that user entered at least one argument to the executable, print usage if not # ------------------------------------------------------------------------------------------ if not c.command_suite_validates(): from Crypto.settings import usage as crypto_usage print(crypto_usage) sys.exit(1) # ------------------------------------------------------------------------------------------ # [ HELP, VERSION, USAGE LOGIC ] # Naked framework provides default help, usage, and version commands for all applications # --> settings for user messages are assigned in the lib/Crypto/settings.py file # ------------------------------------------------------------------------------------------ if c.help(): # User requested Crypto help information from Crypto.settings import help as crypto_help print(crypto_help) sys.exit(0) elif c.usage(): # User requested Crypto usage information from Crypto.settings import usage as crypto_usage print(crypto_usage) sys.exit(0) elif c.version(): # User requested Crypto version information from Crypto.settings import app_name, major_version, minor_version, patch_version version_display_string = app_name + ' ' + major_version + '.' + minor_version + '.' + patch_version print(version_display_string) sys.exit(0) # ------------------------------------------------------------------------------------------ # [ APPLICATION LOGIC ] # # ------------------------------------------------------------------------------------------ elif c.argc > 1: # code for multi-file processing and commands that include options use_standard_output = False # print to stdout flag use_file_overwrite = False # overwrite existing file untar_archives = True # untar decrypted tar archives, true by default # set user option flags if c.option('--stdout') or c.option('-s'): use_standard_output = True if c.option('--overwrite') or c.option('-o'): use_file_overwrite = True if c.option('--nountar'): untar_archives = False directory_list = [ ] # directory paths included in the user entered paths from the command line file_list = [ ] # file paths included in the user entered paths from the command line (and inside directories entered) for argument in c.argv: if file_exists( argument ): # user included a file, add it to the file_list for decryption if argument.endswith('.crypt'): file_list.append( argument ) # add .crypt files to the list of files for decryption elif argument.endswith('.gpg'): file_list.append(argument) elif argument.endswith('.asc'): file_list.append(argument) elif argument.endswith('.pgp'): file_list.append(argument) else: # cannot identify as an encrypted file, give it a shot anyways but warn user file_list.append(argument) stdout( "Could not confirm that '" + argument + "' is encrypted based upon the file type. Attempting decryption. Keep your fingers crossed..." ) elif dir_exists( argument ): # user included a directory, add it to the directory_list directory_list.append(argument) else: if argument[0] == "-": pass # if it is an option, do nothing else: stderr( "'" + argument + "' does not appear to be an existing file or directory. Aborting decryption attempt for this request." ) # unroll the contained directory files into the file_list IF they are encrypted file types if len(directory_list) > 0: for directory in directory_list: directory_file_list = list_all_files(directory) for contained_file in directory_file_list: if contained_file.endswith('.crypt'): file_list.append( make_path(directory, contained_file) ) # include the file with a filepath 'directory path/contained_file path' elif contained_file.endswith('.gpg'): file_list.append(make_path(directory, contained_file)) elif contained_file.endswith('asc'): file_list.append(make_path(directory, contained_file)) elif contained_file.endswith('.pgp'): file_list.append(make_path(directory, contained_file)) # confirm that there are files for decryption, if not abort if len(file_list) == 0: stderr("Could not identify files for decryption") sys.exit(1) # get passphrase used to symmetrically decrypt the file passphrase = getpass.getpass("Please enter your passphrase: ") if len(passphrase) == 0: # confirm that user entered a passphrase stderr( "You did not enter a passphrase. Please repeat your command and try again." ) sys.exit(1) passphrase_confirm = getpass.getpass( "Please enter your passphrase again: ") if passphrase == passphrase_confirm: # begin decryption of each requested file. the directory path was already added to the file path above for encrypted_file in file_list: # create the decrypted file name decrypted_filename = "" if encrypted_file.endswith('.crypt'): decrypted_filename = encrypted_file[0:-6] elif encrypted_file.endswith( '.gpg') or encrypted_file.endswith( '.asc') or encrypted_file.endswith('.pgp'): decrypted_filename = encrypted_file[0:-4] else: decrypted_filename = encrypted_file + '.decrypt' # if it was a file without a known encrypted file type, add the .decrypt suffix # determine whether file overwrite will take place with the decrypted file skip_file = False # flag that indicates this file should not be encrypted created_tmp_files = False if not use_standard_output: # if not writing a file, no need to check for overwrite if file_exists(decrypted_filename): if use_file_overwrite: # rename the existing file to temp file which will be erased or replaced (on decryption failures) below tmp_filename = decrypted_filename + '.tmp' os.rename(decrypted_filename, tmp_filename) created_tmp_files = True else: stdout( "The file path '" + decrypted_filename + "' already exists. This file was not decrypted." ) skip_file = True # begin decryption if not skip_file: if use_standard_output: # using --quiet flag to suppress stdout messages from gpg, just want the file data in stdout stream system_command = "gpg --batch --quiet --passphrase " + quote( passphrase) + " -d " + quote(encrypted_file) successful_execution = execute( system_command ) # use naked execute function to directly push to stdout, rather than return stdout if not successful_execution: stderr( "Unable to decrypt file '" + encrypted_file + "'", 0) if created_tmp_files: # restore the moved tmp file to original if decrypt failed tmp_filename = decrypted_filename + '.tmp' if file_exists(tmp_filename): os.rename(tmp_filename, decrypted_filename) else: # decryption successful but we are in stdout flag so do not include any other output from decrypto pass else: system_command = "gpg --batch -o " + quote( decrypted_filename) + " --passphrase " + quote( passphrase) + " -d " + quote(encrypted_file) response = muterun(system_command) if response.exitcode == 0: stdout("'" + encrypted_file + "' decrypted to '" + decrypted_filename + "'") else: # failed decryption if created_tmp_files: # restore the moved tmp file to original if decrypt failed tmp_filename = decrypted_filename + '.tmp' if file_exists(tmp_filename): os.rename(tmp_filename, decrypted_filename) # report the error stderr(response.stderr) stderr("Decryption failed for " + encrypted_file) # cleanup: remove the tmp file if created_tmp_files: tmp_filename = decrypted_filename + '.tmp' if file_exists(tmp_filename): os.remove(tmp_filename) # untar/extract any detected archive file(s) if untar_archives is True: if decrypted_filename.endswith( '.tar') and tarfile.is_tarfile(decrypted_filename): untar_path_tuple = os.path.split(decrypted_filename) untar_path = untar_path_tuple[0] if use_file_overwrite: with tarfile.open(decrypted_filename) as tar: if len(untar_path) > 0: tar.extractall( path=untar_path ) # use dir path from the decrypted_filename if not CWD stdout( "'" + decrypted_filename + "' unpacked in the directory path '" + untar_path + "'") else: tar.extractall() # else use CWD stdout( "'" + decrypted_filename + "' unpacked in the current working directory" ) else: with tarfile.TarFile(decrypted_filename, 'r', errorlevel=1) as tar: for tarinfo in tar: t_file = tarinfo.name if len(untar_path) > 0: t_file_path = os.path.join( untar_path, t_file) else: t_file_path = t_file if not os.path.exists(t_file_path): try: if len(untar_path) > 0: tar.extract( t_file, path=untar_path ) # write to the appropriate dir else: tar.extract( t_file) # write to CWD except IOError as e: stderr( "Failed to unpack the file '" + t_file_path + "' [" + str(e) + "]") elif is_dir(t_file_path): pass # do nothing if it exists and is a directory, no need to warn else: # it is a file and it already exists, provide user error message stderr( "Failed to unpack the file '" + t_file_path + "'. File already exists. Use the --overwrite flag to replace existing files." ) # remove the decrypted tar archive file os.remove(decrypted_filename) # overwrite the entered passphrases after file decryption is complete for all files passphrase = "" passphrase_confirm = "" # add a short pause to hinder brute force pexpect style password attacks with decrypto sleep(0.2) # 200ms pause else: # passphrases did not match passphrase = "" passphrase_confirm = "" stderr( "The passphrases did not match. Please enter your command again." ) sys.exit(1) elif c.argc == 1: # simple single file or directory processing with default settings path = c.arg0 if file_exists(path): # SINGLE FILE check_existing_file = False # check for a file with the name of new decrypted filename in the directory if path.endswith('.crypt'): decrypted_filename = path[0:-6] # remove the .crypt suffix check_existing_file = True elif path.endswith('.gpg') or path.endswith( '.pgp') or path.endswith('.asc'): decrypted_filename = path[0:-4] check_existing_file = True else: decrypted_filename = path + ".decrypt" # if there is not a standard file type, then add a .decrypt suffix to the decrypted file name stdout( "Could not confirm that the requested file is encrypted based upon the file type. Attempting decryption. Keep your fingers crossed..." ) # confirm that the decrypted path does not already exist, if so abort with warning message to user if check_existing_file is True: if file_exists(decrypted_filename): stderr( "Your file will be decrypted to '" + decrypted_filename + "' and this file path already exists. Please move the file or use the --overwrite option with your command if you intend to replace the current file." ) sys.exit(1) # get passphrase used to symmetrically decrypt the file passphrase = getpass.getpass("Please enter your passphrase: ") if len(passphrase) == 0: # confirm that user entered a passphrase stderr( "You did not enter a passphrase. Please repeat your command and try again." ) sys.exit(1) passphrase_confirm = getpass.getpass( "Please enter your passphrase again: ") # confirm that the passphrases match if passphrase == passphrase_confirm: system_command = "gpg --batch -o " + quote( decrypted_filename) + " --passphrase " + quote( passphrase) + " -d " + quote(path) response = muterun(system_command) if response.exitcode == 0: # unpack tar archive generated from the decryption, if present if decrypted_filename.endswith( '.tar') and tarfile.is_tarfile(decrypted_filename): untar_path_tuple = os.path.split(decrypted_filename) untar_path = untar_path_tuple[0] with tarfile.TarFile(decrypted_filename, 'r', errorlevel=1) as tar: for tarinfo in tar: t_file = tarinfo.name if len(untar_path) > 0: t_file_path = os.path.join( untar_path, t_file) else: t_file_path = t_file if not os.path.exists(t_file_path): try: if len(untar_path) > 0: tar.extract( t_file, path=untar_path ) # write to the appropriate dir else: tar.extract(t_file) # write to CWD except IOError as e: stderr("Failed to unpack the file '" + t_file_path + "' [" + str(e) + "]") elif is_dir(t_file_path): pass # do nothing if it exists and is a directory, no need to warn else: # it is a file and it already exists, provide user error message stderr( "Failed to unpack the file '" + t_file_path + "'. File already exists. Use the --overwrite flag to replace existing files." ) # remove the decrypted tar archive os.remove(decrypted_filename) stdout("Decryption complete") # overwrite user entered passphrases passphrase = "" passphrase_confirm = "" sys.exit(0) else: stderr(response.stderr) stderr("Decryption failed") # overwrite user entered passphrases passphrase = "" passphrase_confirm = "" # add a short pause to hinder brute force pexpect style password attacks with decrypto sleep(0.2) # 200ms pause sys.exit(1) else: stderr( "The passphrases did not match. Please enter your command again." ) sys.exit(1) elif dir_exists(path): # SINGLE DIRECTORY dirty_directory_file_list = list_all_files(path) directory_file_list = [ x for x in dirty_directory_file_list if (x.endswith('.crypt') or x.endswith('.gpg') or x.endswith('.pgp') or x.endswith('.asc')) ] # if there are no encrypted files found, warn and abort if len(directory_file_list) == 0: stderr("There are no encrypted files in the directory") sys.exit(1) # prompt for the passphrase passphrase = getpass.getpass("Please enter your passphrase: ") if len(passphrase) == 0: # confirm that user entered a passphrase stderr( "You did not enter a passphrase. Please repeat your command and try again." ) sys.exit(1) passphrase_confirm = getpass.getpass( "Please enter your passphrase again: ") if passphrase == passphrase_confirm: # decrypt all of the encypted files in the directory for filepath in directory_file_list: absolute_filepath = make_path( path, filepath ) # combine the directory path and file name into absolute path # remove file suffix from the decrypted file path that writes to disk if absolute_filepath.endswith('.crypt'): decrypted_filepath = absolute_filepath[ 0:-6] # remove the .crypt suffix elif absolute_filepath.endswith( '.gpg') or absolute_filepath.endswith( '.pgp') or absolute_filepath.endswith('.asc'): decrypted_filepath = absolute_filepath[0:-4] # confirm that the file does not already exist if file_exists(decrypted_filepath): stdout( "The file path '" + decrypted_filepath + "' already exists. This file was not decrypted.") else: system_command = "gpg --batch -o " + quote( decrypted_filepath) + " --passphrase " + quote( passphrase) + " -d " + quote(absolute_filepath) response = muterun(system_command) if response.exitcode == 0: stdout("'" + absolute_filepath + "' decrypted to '" + decrypted_filepath + "'") else: stderr(response.stderr) stderr("Decryption failed for " + absolute_filepath) # overwrite user entered passphrases passphrase = "" passphrase_confirm = "" # add a short pause to hinder brute force pexpect style password attacks with decrypto sleep(0.2) # 200ms pause else: # overwrite user entered passphrases passphrase = "" passphrase_confirm = "" stderr( "The passphrases did not match. Please enter your command again." ) sys.exit(1) else: # error message, not a file or directory. user entry error stderr( "The path that you entered does not appear to be an existing file or directory. Please try again." ) sys.exit(1) # ------------------------------------------------------------------------------------------ # [ DEFAULT MESSAGE FOR MATCH FAILURE ] # Message to provide to the user when all above conditional logic fails to meet a true condition # ------------------------------------------------------------------------------------------ else: print("Could not complete your request. Please try again.") sys.exit(1)
def main(): import sys import getpass from Naked.commandline import Command from Naked.toolshed.shell import muterun from Naked.toolshed.system import dir_exists, directory, filename, file_exists, list_all_files, make_path, stdout, stderr #------------------------------------------------------------------------------------------ # [ Instantiate command line object ] # used for all subsequent conditional logic in the CLI application #------------------------------------------------------------------------------------------ c = Command(sys.argv[0], sys.argv[1:]) #------------------------------------------------------------------------------------------ # [ VALIDATION LOGIC ] - early validation of appropriate command syntax # Test that user entered at least one argument to the executable, print usage if not #------------------------------------------------------------------------------------------ if not c.command_suite_validates(): from crypto.settings import usage as crypto_usage print(crypto_usage) sys.exit(1) #------------------------------------------------------------------------------------------ # [ HELP, VERSION, USAGE LOGIC ] # Naked framework provides default help, usage, and version commands for all applications # --> settings for user messages are assigned in the lib/crypto/settings.py file #------------------------------------------------------------------------------------------ if c.help(): # User requested crypto help information from crypto.settings import help as crypto_help print(crypto_help) sys.exit(0) elif c.usage(): # User requested crypto usage information from crypto.settings import usage as crypto_usage print(crypto_usage) sys.exit(0) elif c.version(): # User requested crypto version information from crypto.settings import app_name, major_version, minor_version, patch_version version_display_string = app_name + ' ' + major_version + '.' + minor_version + '.' + patch_version print(version_display_string) sys.exit(0) #------------------------------------------------------------------------------------------ # [ APPLICATION LOGIC ] # #------------------------------------------------------------------------------------------ elif c.argc > 1: # code for multi-file processing and commands that include options ## ASCII ARMOR SWITCH ascii_armored = False if c.option('--armor') or c.option('-a'): ascii_armored = True ## MAX COMPRESS / COMPRESS ALL SWITCH max_compress = False if c.option('--space'): max_compress = True ## NO COMPRESSION SWITCH no_compress = False if c.option('--speed'): no_compress = True ## SECURE HASH DIGEST REPORT SWITCH report_checksum = False if c.option('--hash'): report_checksum = True path_list = [] # user entered paths from command line directory_list = [ ] # directory paths included in the user entered paths from the command line file_list = [ ] # file paths included in the user entered paths from the command line (and inside directories entered) # dot and .crypt file flags for exclusion testing contained_dot_file = False contained_crypt_file = False # determine if argument is an existing file or directory for argument in c.argv: if file_exists(argument): if argument.endswith( '.crypt'): # do not include previously encrypted files contained_crypt_file = True else: file_list.append( argument ) # add appropriate file paths to the file_list elif dir_exists(argument): directory_list.append( argument ) # if it is a directory, add path to the directory_list # add all file paths from user specified directories to the file_list if len(directory_list) > 0: for directory in directory_list: directory_file_list = list_all_files(directory) for contained_file in directory_file_list: if contained_file[0] == ".": contained_dot_file = True # change the flag + is not included in file_list intentionally (no dot files) elif contained_file.endswith('.crypt'): contained_crypt_file = True # change the flag + is not included in file_list intentionally (no previously encrypted files) else: # otherwise add to the list for encryption contained_file_path = make_path( directory, contained_file) file_list.append(contained_file_path) # confirm that there are files to be encrypted, if not warn user if len(file_list) == 0: if contained_dot_file == True or contained_crypt_file == True: stderr( "There were no files identified for encryption. crypto does not encrypt dot files or previously encrypted '.crypt' files." ) sys.exit(1) else: stderr("Unable to identify files for encryption") sys.exit(1) else: # file_list should contain all filepaths from either user specified file paths or contained in top level of directory, encrypt them passphrase = getpass.getpass("Please enter your passphrase: ") if len(passphrase) == 0: # confirm that user entered a passphrase stderr( "You did not enter a passphrase. Please repeat your command and try again." ) sys.exit(1) passphrase_confirm = getpass.getpass( "Please enter your passphrase again: ") if passphrase == passphrase_confirm: from crypto.library.cryptor import Cryptor the_cryptor = Cryptor(passphrase) # run encryption based upon any passed switches if ascii_armored: if max_compress: the_cryptor.encrypt_files(file_list, force_nocompress=False, force_compress=True, armored=True, checksum=report_checksum) elif no_compress: the_cryptor.encrypt_files(file_list, force_nocompress=True, force_compress=False, armored=True, checksum=report_checksum) else: the_cryptor.encrypt_files(file_list, force_nocompress=False, force_compress=False, armored=True, checksum=report_checksum) else: if max_compress: the_cryptor.encrypt_files(file_list, force_nocompress=False, force_compress=True, armored=False, checksum=report_checksum) elif no_compress: the_cryptor.encrypt_files(file_list, force_nocompress=True, force_compress=False, armored=False, checksum=report_checksum) else: the_cryptor.encrypt_files(file_list, force_nocompress=False, force_compress=False, armored=False, checksum=report_checksum) # overwrite user entered passphrases passphrase = "" passphrase_confirm = "" the_cryptor.cleanup() else: # passphrases did not match, report to user and abort # overwrite user entered passphrases passphrase = "" passphrase_confirm = "" stderr( "The passphrases did not match. Please enter your command again." ) sys.exit(1) elif c.argc == 1: # simple single file or directory processing with default settings path = c.arg0 if file_exists(path): # it is a file, encrypt the single file with default settings # confirm that it is not already encrypted, abort if so if path.endswith('.crypt'): stderr( "You are attempting to encrypt an encrypted file. Please delete the .crypt file and repeat encryption with the original file if this is your intent." ) sys.exit(1) # if passes test above, obtain passphrase from the user passphrase = getpass.getpass("Please enter your passphrase: ") if len(passphrase) == 0: # confirm that user entered a passphrase stderr( "You did not enter a passphrase. Please repeat your command and try again." ) sys.exit(1) passphrase_confirm = getpass.getpass( "Please enter your passphrase again: ") if passphrase == passphrase_confirm: from crypto.library.cryptor import Cryptor the_cryptor = Cryptor(passphrase) the_cryptor.encrypt_file(path) the_cryptor.cleanup() else: stderr( "The passphrases did not match. Please enter your command again." ) sys.exit(1) elif dir_exists(path): # it is a directory, encrypt all top level files with default settings dirty_directory_file_list = list_all_files(path) # remove dot files and previously encrypted files (with .crypt suffix) from the list of directory files clean_directory_file_list = [ x for x in dirty_directory_file_list if x[0] != "." and x.endswith(".crypt") == False ] # remove dotfiles and .crypt files # confirm that there are still files in the list after the dot files and encrypted files are removed if len(clean_directory_file_list) == 0: stderr("There are no unencrypted files in the directory.") sys.exit(1) # create relative file paths for each file in the clean_directory_file_list clean_directory_file_list_relpaths = [] for clean_file in clean_directory_file_list: new_file_path = make_path(path, clean_file) clean_directory_file_list_relpaths.append(new_file_path) #prompt for the passphrase passphrase = getpass.getpass("Please enter your passphrase: ") if len(passphrase) == 0: # confirm that user entered a passphrase stderr( "You did not enter a passphrase. Please repeat your command and try again." ) sys.exit(1) passphrase_confirm = getpass.getpass( "Please enter your passphrase again: ") if passphrase == passphrase_confirm: from crypto.library.cryptor import Cryptor the_cryptor = Cryptor(passphrase) the_cryptor.encrypt_files( clean_directory_file_list_relpaths ) #encrypt the list of directory files the_cryptor.cleanup() else: # passphrases do not match # overwrite user entered passphrases passphrase = "" passphrase_confirm = "" stderr( "The passphrases did not match. Please enter your command again." ) sys.exit(1) else: # error message, not a file or directory. user entry error stderr( "The path that you entered does not appear to be an existing file or directory. Please try again." ) sys.exit(1) #------------------------------------------------------------------------------------------ # [ DEFAULT MESSAGE FOR MATCH FAILURE ] # Message to provide to the user when all above conditional logic fails to meet a true condition #------------------------------------------------------------------------------------------ else: print("Could not complete your request. Please try again.") sys.exit(1)
def setUp(self): self.cwd = os.getcwd() self.testdir = 'testdir10' self.sourcedir = os.path.join(self.testdir, 'sourcedir') self.nofile_encrypted_archive_sourcepath = os.path.join(self.sourcedir, 'nofile.tar.crypt') self.nofile_encrypted_archive_destpath = os.path.join(self.testdir, 'nofile.tar.crypt') self.singlefile_encrypted_archive_sourcepath = os.path.join(self.sourcedir, 'singlefile.tar.crypt') self.singlefile_encrypted_archive_destpath = os.path.join(self.testdir, 'singlefile.tar.crypt') self.multifile_encrypted_archive_sourcepath = os.path.join(self.sourcedir, 'multifile.tar.crypt') self.multifile_encrypted_archive_destpath = os.path.join(self.testdir, 'multifile.tar.crypt') self.subdirs_encrypted_archive_sourcepath = os.path.join(self.sourcedir, 'subdirs.tar.crypt') self.subdirs_encrypted_archive_destpath = os.path.join(self.testdir, 'subdirs.tar.crypt') # cleanup old test files if they are present if file_exists(self.nofile_encrypted_archive_destpath): os.remove(self.nofile_encrypted_archive_destpath) if file_exists(self.singlefile_encrypted_archive_destpath): os.remove(self.singlefile_encrypted_archive_destpath) if file_exists(self.multifile_encrypted_archive_destpath): os.remove(self.multifile_encrypted_archive_destpath) if file_exists(self.subdirs_encrypted_archive_destpath): os.remove(self.subdirs_encrypted_archive_destpath) if file_exists(os.path.join(self.testdir, 'nofile.tar')): os.remove(os.path.join(self.testdir, 'nofile.tar')) if file_exists(os.path.join(self.testdir, 'nofile.tar.crypt')): os.remove(os.path.join(self.testdir, 'nofile.tar.crypt')) if dir_exists(os.path.join(self.testdir, 'nofile')): shutil.rmtree(os.path.join(self.testdir, 'nofile')) if file_exists(os.path.join(self.testdir, 'singlefile.tar')): os.remove(os.path.join(self.testdir, 'singlefile.tar')) if file_exists(os.path.join(self.testdir, 'singlefile.tar.crypt')): os.remove(os.path.join(self.testdir, 'singlefile.tar.crypt')) if dir_exists(os.path.join(self.testdir, 'singlefile')): shutil.rmtree(os.path.join(self.testdir, 'singlefile')) if file_exists(os.path.join(self.testdir, 'multifile.tar')): os.remove(os.path.join(self.testdir, 'multifile.tar')) if file_exists(os.path.join(self.testdir, 'multifile.tar.crypt')): os.remove(os.path.join(self.testdir, 'multifile.tar.crypt')) if dir_exists(os.path.join(self.testdir, 'multifile')): shutil.rmtree(os.path.join(self.testdir, 'multifile')) if file_exists(os.path.join(self.testdir, 'subdirs.tar')): os.remove(os.path.join(self.testdir, 'subdirs.tar')) if file_exists(os.path.join(self.testdir, 'subdirs.tar.crypt')): os.remove(os.path.join(self.testdir, 'subdirs.tar.crypt')) if dir_exists(os.path.join(self.testdir, 'subdirs')): shutil.rmtree(os.path.join(self.testdir, 'subdirs'))
def run_pull(url): # URL pulls for project archive packages, gzip files, text files if is_url(url): file_name = get_file_name(url) if len(file_name) == 0: file_name = "pullfile" # begin file pull stdout("[*] doxx: Pulling file...") if is_tar_gz_archive(file_name): root_dir = None try: pull_binary_file(url, file_name) # pull remote file except Exception as e: stderr("[!] doxx: Unable to pull the tar.gz project. Error: " + str(e), exit=1) stdout("[*] doxx: Unpacking...") try: root_dir = unpack_archive(file_name) # unpack archive and define the root directory except Exception as e: stderr("[!] doxx: Unable to unpack the compressed project file. Error: " + str(e), exit=1) if file_exists(file_name): remove_file(file_name) # remove the archive file if file_exists('pkey.yaml'): if not file_exists('key.yaml'): rename('pkey.yaml', 'key.yaml') # change name of pkey.yaml to key.yaml if there is not already a key.yaml file return root_dir # return the root directory path for calling code that needs it elif is_zip_archive(file_name): root_dir = None try: pull_binary_file(url, file_name) # pull remote file except Exception as e: stderr("[!] doxx: Unable to pull the .zip project. Error: " + str(e), exit=1) stdout("[*] doxx: Unpacking...") try: root_dir = unpack_archive(file_name) # unpack archive and define the root directory except Exception as e: stderr("[!] doxx: Unable to unpack the compressed project file. Error: " + str(e), exit=1) if file_exists(file_name): remove_file(file_name) # remove the arhcive file if file_exists('pkey.yaml'): if not file_exists('key.yaml'): rename('pkey.yaml', 'key.yaml') # change name of pkey.yaml to key.yaml if there is not already a key.yaml file return root_dir # return the root directory path for calling code that needs it elif is_gzip_file(file_name): try: pull_binary_file(url, file_name) # pull the remote gzip file except Exception as e: stderr("[!] doxx: Unable to pull the compressed file. Error: " + str(e), exit=1) stdout("[!] doxx: Decompressing...") try: decompress_gzip(file_name) # decompress the file text except Exception as e: stderr("[!] doxx: Unable to decompress the gzip file. Error: " + str(e), exit=1) if file_exists(file_name): remove_file(file_name) # remove the gzip compressed file and leave the decompressed text file else: try: pull_text_file(url, file_name) # it is assumed to be a plain text template or key file, pull the text except Exception as e: stderr("[!] doxx: Unable to pull the requested file. Error: " + str(e), exit=1) else: # SHORT CODE PULL REQUESTS for Github repository, CDNJS, etc if "/" in url: short_code = url if short_code.startswith('cdnjs:'): pass # add code for cdnjs pulls (syntax: 'cdnjs:/project') else: # default to Github repository shortcode keep_a_file_or_dir = False # indicator for user request to maintain single file or dir from repository # cherry-pick file or directory request if "+" in short_code: # user requested single directory or file from the repository short_code_keep = short_code.split("+") short_code = short_code_keep[0] # split on the + char and eliminate it from the request argument at this point keep_path = short_code_keep[1] # the file or dir path to cherry pick keep_a_file_or_dir = True # switch the indicator short_code_parts = short_code.split('/') if len(short_code_parts) == 2: if ":" in short_code_parts[1]: # non-master branch request (syntax: `user/repo:branch`) user = short_code_parts[0] if ":" in user or "+" in user: stderr("[!] doxx: your short code for a Github repository does not have the proper format") stderr("[!] doxx: the syntax is `user/repository[:branch][+cherrypick_path]`", exit=1) repo_parts = short_code_parts[1].split(':') repo = repo_parts[0] branch = repo_parts[1] targz_filename = repo + "-" + branch + ".tar.gz" url = "https://github.com/{{user}}/{{repository}}/archive/{{branch}}.tar.gz" url = url.replace("{{user}}", user) url = url.replace("{{repository}}", repo) url = url.replace("{{branch}}", branch) user_message = "[*] doxx: Pulling branch '" + branch + "' of Github repository '" + user + "/" + repo + "'..." else: # master branch request (default- syntax: `user/repo`) user = short_code_parts[0] if ":" in user or "+" in user: stderr("[!] doxx: the short code for Github repositories does not have the proper format") stderr("[!] doxx: the syntax is `user/repository[:branch][+cherrypick_path]`", exit=1) repo = short_code_parts[1] targz_filename = repo + "-master.tar.gz" url = "https://github.com/{{user}}/{{repository}}/archive/master.tar.gz" url = url.replace("{{user}}", user) url = url.replace("{{repository}}", repo) user_message = "[*] doxx: Pulling master branch of Github repository '" + user + "/" + repo + "'..." # notify user of the pull stdout(user_message) try: pull_binary_file(url, targz_filename) # pull the archive file except Exception as e: stderr("[!] doxx: Unable to pull the Github repository. Error: " + str(e), exit=1) if file_exists(targz_filename): try: # Unpack and remove the archive file targz_basename = unpack_archive(targz_filename) # unpack the archive locally remove(targz_filename) # remove the archive file except Exception as e: stderr("[!] doxx: Unable to unpack the pulled Github repository. Error: " + str(e), exit=1) try: # Did user request keep of a specific file or directory path? if keep_a_file_or_dir is True: # is this a multilevel path request? # if so, make OS dependent file path from the user argument (keep path argument syntax uses POSIX path style on all platforms) if "/" in keep_path: keep_path_parts = keep_path.split('/') keep_path_depth = len(keep_path_parts) if keep_path_depth > 3: stderr("[!] doxx: doxx supports up to 3 levels of depth in the cherry pick shortcode path. Your request exceeded that level and the requested file or directory was not cherry picked from the repository.", exit=1) # make the OS dependent paths if keep_path_depth == 2: path_part_one = keep_path_parts[0] path_part_two = keep_path_parts[1] keep_path = join(path_part_one, path_part_two) elif keep_path_depth == 3: path_part_one = keep_path_parts[0] path_part_two = keep_path_parts[1] path_part_three = keep_path_parts[2] keep_path = join(path_part_one, path_part_two, path_part_three) else: keep_path_depth = 1 # need to have a definition of depth of file/dir keep for mkdirs code below joined_keep_path = join(targz_basename, keep_path) # the path to the local version of the file or directory following pull if dir_exists(joined_keep_path): stdout("[*] doxx: Cherry picking the directory '" + keep_path + "'") if dir_exists(keep_path): new_dir_path = keep_path + "-new" if dir_exists(new_dir_path): shutil.rmtree(new_dir_path) stdout("[*] doxx: The requested directory already exists locally. Writing to '" + new_dir_path + "' instead.") shutil.copytree(joined_keep_path, new_dir_path) # write to `dir-new` instead of existing `dir` shutil.rmtree(targz_basename) # remove the pulled repository file else: shutil.copytree(joined_keep_path, keep_path) # write to the requested dir path shutil.rmtree(targz_basename) # remove the pulled repository file elif file_exists(joined_keep_path): stdout("[*] doxx: Cherry picking the file '" + keep_path + "'") local_filepath = basename(keep_path) # outfile write path (filename to root directory where user pulled) ## NEW # handle file path if the file already exists to avoid overwrite if file_exists(local_filepath): # the file already exists in the local directory if '.' in local_filepath: file_name_parts = local_filepath.split('.') file_name_parts[0] = file_name_parts[0] + "-new" # add '-new' to the basename of the file, not extension local_filepath = '.'.join(file_name_parts) else: local_filepath = local_filepath + "-new" # add '-new' to the filename (that does not have an extension) stdout("[*] doxx: The requested file already exists in the working directory. Writing the new file to '" + local_filepath + "' instead.") # write the file shutil.copy2(joined_keep_path, local_filepath) # remove the tar.gz archive file shutil.rmtree(targz_basename) else: # could not find the file or dir in the pulled repo stderr("[!] doxx: '" + joined_keep_path + "' does not appear to be a file or directory in the pulled repository. The entire pulled repository was left in the working directory for review.", exit=1) except Exception as e: stderr("[!] doxx: Unable to process the requested keep file or directory path. Error" + str(e), exit=1) else: # archive file not found locally stderr("[!] doxx: The Github repository pull did not complete successfully. Please try again.") else: # length of short_code_parts > 2 stderr("[!] doxx: Short code syntax for Github repository pulls:", exit=0) stderr(" $ doxx pull user/repository") stderr("[!] doxx: with an optional branch or release:") stderr(" $ doxx pull user/repository[:branch]") stderr("[!] doxx: with an optional branch or release AND optional cherry pick file or directory path:") stderr(" $ doxx pull user/repository[:branch][+cherrypick_path]", exit=1) # PROJECT PACKAGES - official repository package pulls else: from doxx.datatypes.package import OfficialPackage package_name = url package = OfficialPackage() package_url = package.get_package_targz_url(package_name) package_archive_name = package_name + ".tar.gz" root_dir = None # pull the package archive file stdout("[*] doxx: Pulling package '" + package_name + "'...") try: pull_binary_file(package_url, package_archive_name) except Exception as e: stderr("[!] doxx: Unable to pull the doxx repository package. Error: " + str(e), exit=1) # unpack the archive file stdout("[*] doxx: Unpacking...") try: root_dir = unpack_archive(package_archive_name) # unpack archive and define the root directory except Exception as e: stderr("[!] doxx: Unable to unpack the project package. Error: " + str(e), exit=1) # remove the archive file if file_exists(package_archive_name): remove_file(package_archive_name) # remove the archive file if file_exists('pkey.yaml'): if not file_exists('key.yaml'): rename('pkey.yaml', 'key.yaml') # change name of pkey.yaml to key.yaml if there is not already a key.yaml file return root_dir # return the root directory path for calling code that needs it
def test_sys_dir_exists(self): """Test for existence of a directory that exists""" self.assertEqual(True, system.dir_exists(self.sysdirpath))