diff --git a/bitwardenBackup.py b/bitwardenBackup.py index 85fa505..9382ef1 100644 --- a/bitwardenBackup.py +++ b/bitwardenBackup.py @@ -308,20 +308,27 @@ if __name__ == "__main__": parser = argparse.ArgumentParser( usage="{} [options]".format(os.path.basename(__file__)), description="Run Bitwarden backup opteration. This will produce an encrypted zip/tar with exported CSV, JSON, and attachements.") - parser.add_argument( + parser.add_argument ( "-a", "--accounts", nargs="+", dest="accounts_to_backup", help="Accounts to backup instead of all accounts." ) - parser.add_argument( + parser.add_argument ( "-c", "--config", action="store_true", dest="config", help="Edit Bitwarden account configuration." ) + parse.add_argument ( + "-t", + "--test", + action="store_true", + dest="test", + help="Test Bitwarden account login and unlock." + ) parser.add_argument ( "-v", "--verbose", @@ -482,58 +489,59 @@ if __name__ == "__main__": if bitwarden_session_key: # logger.debug("Session key: {}".format(bitwarden_session_key)) logger.info("Successfully unlocked vault") - os.environ["BW_SESSION"] = bitwarden_session_key + if not opts.test: + os.environ["BW_SESSION"] = bitwarden_session_key - # export to csv and json - logger.info("Exporting vault to both CSV and JSON files") - logger.debug("Exporting vault to CSV") - file_name = 'Bitwarden {} Export {}'.format(email, datetime_string) - logger.debug((subprocess.run([bitwarden_cli_executable, 'export', '--output', os.path.join(working_directory, '{}.csv'.format(file_name)) , '--format', 'csv'], capture_output=True).stdout).decode()) - time.sleep(1) - logger.debug("Exporting vault to JSON") - logger.debug((subprocess.run([bitwarden_cli_executable, 'export', '--output', os.path.join(working_directory, '{}.json'.format(file_name)), '--format', 'json'], capture_output=True).stdout).decode()) - time.sleep(1) - - # looking for Organizations - # look for organizations - logger.info("Looking for Organizations") - bitwarden_organizations = json.loads(((subprocess.run([bitwarden_cli_executable, 'list', 'organizations'], capture_output=True)).stdout).decode()) - - logger.info("Found {} Organiztaions.".format(len(bitwarden_organizations))) - - for organization in bitwarden_organizations: - logger.info("Exporting organization {} vault to both CSV and JSON files".format(organization['name'])) - logger.debug("Exporting organization vault to CSV") - file_name = 'Bitwarden Organization {} Export {}'.format(organization['name'], datetime_string) - logger.debug((subprocess.run([bitwarden_cli_executable, 'export', '--organizationid', '{}'.format(organization['id']), '--output', os.path.join(working_directory, '{}.csv'.format(file_name)), '--format', 'csv'], capture_output=True).stdout).decode()) + # export to csv and json + logger.info("Exporting vault to both CSV and JSON files") + logger.debug("Exporting vault to CSV") + file_name = 'Bitwarden {} Export {}'.format(email, datetime_string) + logger.debug((subprocess.run([bitwarden_cli_executable, 'export', '--output', os.path.join(working_directory, '{}.csv'.format(file_name)) , '--format', 'csv'], capture_output=True).stdout).decode()) time.sleep(1) - logger.debug("Exporting organization vault to JSON") - logger.debug((subprocess.run([bitwarden_cli_executable, 'export', '--organizationid', '{}'.format(organization['id']), '--output', os.path.join(working_directory, '{}.json'.format(file_name)), '--format', 'json'], capture_output=True).stdout).decode()) + logger.debug("Exporting vault to JSON") + logger.debug((subprocess.run([bitwarden_cli_executable, 'export', '--output', os.path.join(working_directory, '{}.json'.format(file_name)), '--format', 'json'], capture_output=True).stdout).decode()) time.sleep(1) - logger.info("Downlading attachments...") - bitwarden_items = json.loads(((subprocess.run([bitwarden_cli_executable, 'list', 'items'], capture_output=True)).stdout).decode()) - for item in bitwarden_items: - logger.debug("Working on item {} ({})".format(item['name'], item['id'])) - if "attachments" in item: - logger.debug("Found {} attachments".format(len(item['attachments']))) - attachment_folder_name = os.path.join(working_directory, "attachments", item['name']) - for attachment in item['attachments']: - logger.debug("Downloading attachment ({}) with name {} to folder {}".format(attachment['id'], attachment['fileName'], attachment_folder_name)) - logger.info((subprocess.run([bitwarden_cli_executable, 'get', 'attachment', attachment['id'], '--itemid', item['id'], '--output', os.path.join(attachment_folder_name, attachment['fileName'])], capture_output=True).stdout).decode()) - time.sleep(1) + # looking for Organizations + # look for organizations + logger.info("Looking for Organizations") + bitwarden_organizations = json.loads(((subprocess.run([bitwarden_cli_executable, 'list', 'organizations'], capture_output=True)).stdout).decode()) + + logger.info("Found {} Organiztaions.".format(len(bitwarden_organizations))) + + for organization in bitwarden_organizations: + logger.info("Exporting organization {} vault to both CSV and JSON files".format(organization['name'])) + logger.debug("Exporting organization vault to CSV") + file_name = 'Bitwarden Organization {} Export {}'.format(organization['name'], datetime_string) + logger.debug((subprocess.run([bitwarden_cli_executable, 'export', '--organizationid', '{}'.format(organization['id']), '--output', os.path.join(working_directory, '{}.csv'.format(file_name)), '--format', 'csv'], capture_output=True).stdout).decode()) + time.sleep(1) + logger.debug("Exporting organization vault to JSON") + logger.debug((subprocess.run([bitwarden_cli_executable, 'export', '--organizationid', '{}'.format(organization['id']), '--output', os.path.join(working_directory, '{}.json'.format(file_name)), '--format', 'json'], capture_output=True).stdout).decode()) + time.sleep(1) + + logger.info("Downlading attachments...") + bitwarden_items = json.loads(((subprocess.run([bitwarden_cli_executable, 'list', 'items'], capture_output=True)).stdout).decode()) + for item in bitwarden_items: + logger.debug("Working on item {} ({})".format(item['name'], item['id'])) + if "attachments" in item: + logger.debug("Found {} attachments".format(len(item['attachments']))) + attachment_folder_name = os.path.join(working_directory, "attachments", item['name']) + for attachment in item['attachments']: + logger.debug("Downloading attachment ({}) with name {} to folder {}".format(attachment['id'], attachment['fileName'], attachment_folder_name)) + logger.info((subprocess.run([bitwarden_cli_executable, 'get', 'attachment', attachment['id'], '--itemid', item['id'], '--output', os.path.join(attachment_folder_name, attachment['fileName'])], capture_output=True).stdout).decode()) + time.sleep(1) + else: + logger.debug("Item has no attachments") + logger.info("Done downloading attachments") + logger.info("Zipping everything together...") + zip_filename = os.path.join(exports_directory, email,"Bitwarden Backup {} {}".format(email, datetime_string)) + shutil.make_archive(zip_filename, format="zip", root_dir=working_directory) + + if not opts.no_encrypt: + logger.info("Encrypting zip file...") + logger.debug((subprocess.run([gpg_executable, '--no-options', '--batch', '--passphrase', vault_password, '--symmetric', '--cipher-algo', 'AES256', '--digest-algo', 'SHA512', '--compression-algo', 'Uncompressed', '--output', zip_filename + '.zip.gpg', zip_filename + '.zip'], capture_output=True).stdout).decode()) else: - logger.debug("Item has no attachments") - logger.info("Done downloading attachments") - logger.info("Zipping everything together...") - zip_filename = os.path.join(exports_directory, email,"Bitwarden Backup {} {}".format(email, datetime_string)) - shutil.make_archive(zip_filename, format="zip", root_dir=working_directory) - - if not opts.no_encrypt: - logger.info("Encrypting zip file...") - logger.debug((subprocess.run([gpg_executable, '--no-options', '--batch', '--passphrase', vault_password, '--symmetric', '--cipher-algo', 'AES256', '--digest-algo', 'SHA512', '--compression-algo', 'Uncompressed', '--output', zip_filename + '.zip.gpg', zip_filename + '.zip'], capture_output=True).stdout).decode()) - else: - logger.warning("You passed in --no-encryption option, not encrypting zip file") + logger.warning("You passed in --no-encryption option, not encrypting zip file") else: logger.error((bitwarden_unlock_output.stderr).decode())