def _handle_kubernetes(self): #################################################################### """This function creates a file containing kube secrets""" #################################################################### k_conf = self.args["populate"]["kubernetes"] plaintext = {} for password in k_conf["needed"]: pwentry = PasswordEntry() pwentry.read_password_data( path.join(self.args["pwstore"], password)) plaintext_pw = self._decrypt_password_entry(pwentry) plaintext[password] = plaintext_pw if "output" in k_conf: if self.args["pwstore"] in k_conf["output"]: raise CliArgumentError( "Kubernetes output file should not exist in password store" ) if path.isfile(k_conf["output"]): remove(k_conf["output"]) for args in k_conf["passwords"]: data = self._kubernetes_match_loop(args, plaintext) kube_map = { "kind": "Secret", "apiVersion": args["apiVersion"], "metadata": args["metadata"], "data": data, "type": args["type"], } if self.args["value"] or "output" not in k_conf: yield f"---\n{dump(kube_map)}" else: with open(k_conf["output"], "a", encoding="ASCII") as fname: print(f"---\n{dump(kube_map)}", file=fname)
def _run_command_execution(self): #################################################################### """Run function for class.""" #################################################################### safe, owner = self.safety_check() if safe and owner: orig_pass = self.args["pwname"] self.args["pwname"] = self.args["rename"] resafe, reowner = self.safety_check() self.args["pwname"] = orig_pass if resafe or self.args["overwrite"]: password = PasswordEntry() password.read_password_data( os.path.join(self.args["pwstore"], self.args["pwname"])) plaintext_pw = password.decrypt_entry( identity=self.identity, passphrase=self.passphrase, card_slot=self.args["card_slot"], ) self._confirmation(plaintext_pw) else: raise NotThePasswordOwnerError(self.args["identity"], reowner, self.args["rename"]) else: raise NotThePasswordOwnerError(self.args["identity"], owner, self.args["pwname"])
def _run_command_execution(self): """ Run function for class. """ #################################################################### password = PasswordEntry() password.read_password_data(path.join( self.args['pwstore'], self.args['pwname'])) safe, owner = self.safety_check() if safe or self.args['overwrite']: self.recipient_list = password['recipients'].keys() print("The following list of users are the current distribution list:") print(", ".join(util.sort(self.recipient_list))) correct_distribution = input("Is this list correct? (y/N) ") if not correct_distribution or correct_distribution.lower()[0] == 'n': self._new_distribution() self._validate_identities(self.recipient_list) password1 = getpass.getpass("Enter updated password: "******"": raise BlankPasswordError password2 = getpass.getpass("Enter updated password again: ") if password1 != password2: raise PasswordMismatchError # This is due to a poor naming convention; we don't want to go through the # create or update, because we are not updating a single record in the yaml # we are burning it to the ground and redoing the entire thing self.create_pass(password1, password['metadata']['description'], password['metadata']['authorizer'], self.recipient_list) else: raise NotThePasswordOwnerError(self.args['identity'], owner, self.args['pwname'])
def update_pass(self, pass_value): ################################################################## """Fully updated a password record""" ################################################################## pass_entry = PasswordEntry() pass_entry.read_password_data( path.join(self.args["pwstore"], self.args["pwname"]) ) swap_pass = PasswordEntry() swap_pass.add_recipients( secret=pass_value, distributor=self.args["identity"], recipients=[self.args["identity"]], session=self.session, passphrase=self.passphrase, card_slot=self.args["card_slot"], escrow_users=self.args["escrow_users"], minimum=self.args["min_escrow"], pwstore=self.args["pwstore"], ) pass_entry["recipients"][self.args["identity"]] = swap_pass["recipients"][ self.args["identity"] ] pass_entry.write_password_data( path.join(self.args["pwstore"], self.args["pwname"]), overwrite=self.args["overwrite"], )
def _yaml_file(self, passwords): """This function handles the yaml format of pkpass""" myidentity = self.identities.iddb[self.args['identity']] uid = myidentity['uid'] pwstore = self.args['pwstore'] db_len = len(passwords) i = 1 for password in passwords: plaintext_str = passwords[password]['recipients'][uid][ 'encrypted_secret'] full_path = os.path.join(pwstore, password) self.args['pwname'] = password self.args['overwrite'] = True plist = list(passwords[password]['recipients']) if os.path.isfile(full_path): existing_password = PasswordEntry() existing_password.read_password_data(full_path) self.args['overwrite'] = False passwords[password]['metadata'] = existing_password['metadata'] plist += list(existing_password['recipients']) description = passwords[password]['metadata']['description'] authorizer = passwords[password]['metadata']['authorizer'] self.create_or_update_pass(plaintext_str, description, authorizer, plist) self.progress_bar(i, db_len) i += 1 print("")
def _run_command_execution(self): #################################################################### """Run function for class.""" #################################################################### # currently only support puppet pop_type = self.args["type"] if pop_type not in ["puppet_eyaml", "kubernetes"]: raise CliArgumentError( f"'{pop_type}' is an unsupported population type") if pop_type == "kubernetes": yield from self._handle_kubernetes() elif self.args["all"]: for password in self.args["populate"][pop_type]["passwords"].keys( ): pwentry = PasswordEntry() self._decrypt_wrapper(self.args["pwstore"], pwentry, password, pop_type) elif (self.args["pwname"] not in self.args["populate"][pop_type]["passwords"].keys()): raise CliArgumentError( f"'{self.args['pwname']}' doesn't have a mapping in {pop_type}" ) else: password = PasswordEntry() yield from self._decrypt_wrapper(self.args["pwstore"], password, self.args["pwname"], pop_type)
def _run_command_execution(self): """ Run function for class. """ #################################################################### safe, owner = self.safety_check() if safe and owner: orig_pass = self.args['pwname'] self.args['pwname'] = self.args['rename'] resafe, reowner = self.safety_check() self.args['pwname'] = orig_pass if resafe or self.args['overwrite']: myidentity = self.identities.iddb[self.args['identity']] password = PasswordEntry() password.read_password_data( os.path.join(self.args['pwstore'], self.args['pwname'])) plaintext_pw = password.decrypt_entry( identity=myidentity, passphrase=self.passphrase, card_slot=self.args['card_slot']) self._confirmation(plaintext_pw) else: raise NotThePasswordOwnerError(self.args['identity'], reowner, self.args['rename']) else: raise NotThePasswordOwnerError(self.args['identity'], owner, self.args['pwname'])
def _run_command_execution(self): """ Run function for class. """ #################################################################### password = PasswordEntry() password.read_password_data( path.join(self.args['pwstore'], self.args['pwname'])) # Metadata print(self.color_print("Metadata:", "first_level")) for key, value in password.metadata.items(): print(" %s: %s" % (self.color_print(key.capitalize(), "second_level"), value)) # Escrow if password.escrow: print(self.color_print("\nEscrow Groups:", "first_level")) for group_key, group_value in password.escrow.items(): print(" %s:" % self.color_print(group_key, "second_level")) for key, value in group_value['metadata'].items(): print(" %s %s" % (self.color_print( key + ":", "third_level"), str(value))) print(" %s %s" % (self.color_print("Share Holders:", "third_level"), ', '.join(list(group_value['recipients'].keys())))) print(" %s %s" % (self.color_print("Total Group Share Holders:", "third_level"), len(list(group_value['recipients'].keys())))) timestamp_list = [ x['timestamp'] for x in list(group_value['recipients'].values()) if 'timestamp' in x ] if timestamp_list: timestamp = int(round(float(min(timestamp_list)))) timestamp = datetime.fromtimestamp(timestamp).strftime( '%Y-%m-%d %H:%M:%S') print(" %s %s" % (self.color_print( "Group creation time:", "third_level"), timestamp)) # Recipients print("%s %s" % (self.color_print("\nRecipients:", "first_level"), ', '.join(list(password.recipients.keys())))) print("%s %s" % (self.color_print("Total Recipients:", "first_level"), len(list(password.recipients.keys())))) rec_timestamp = int( round( float( min([ x['timestamp'] for x in list(password.recipients.values()) if 'timestamp' in x ])))) rec_timestamp = datetime.fromtimestamp(rec_timestamp).strftime( '%Y-%m-%d %H:%M:%S') print("%s %s" % (self.color_print("Earliest distribute timestamp:", "first_level"), rec_timestamp))
def safety_check(self): """ This provides a sanity check that you are the owner of a password.""" ################################################################## try: password = PasswordEntry() password.read_password_data(path.join(self.args['pwstore'], self.args['pwname'])) return (self.args['identity'] in password['recipients'].keys(), password['metadata']['creator']) except PasswordIOError: return (True, None)
def _run_command_execution(self): #################################################################### """Run function for class.""" #################################################################### yield from self._confirm_pdb() self.recipient_list.append(str(self.args["identity"])) self.recipient_list = list(set(self.recipient_list)) yield from self._confirm_recipients() for dist_pass, _ in tqdm(self.filtered_pdb.items()): password = PasswordEntry() password.read_password_data(dist_pass) if self.args["identity"] in password.recipients.keys(): # we shouldn't modify escrow on distribute self.args["min_escrow"] = None self.args["escrow_users"] = None plaintext_pw = password.decrypt_entry( self.identity, passphrase=self.passphrase, card_slot=self.args["card_slot"], ) password.add_recipients( secret=plaintext_pw, distributor=self.args["identity"], recipients=self.recipient_list, session=self.session, passphrase=self.passphrase, card_slot=self.args["card_slot"], pwstore=self.args["pwstore"], ) password.write_password_data(dist_pass)
def test_create_encrypt_decrypt(self): """create a password entry""" passwordentry = PasswordEntry(name='testcreate', description=self.textblob, creator='r1', authorizer='r1') passwordentry.add_recipients(secret=self.secret, distributor='r1', recipients=self.idobj.recipient_list, identitydb=self.idobj)
def test_create_encrypt_decrypt(self): """create a password entry""" passwordentry = PasswordEntry(name="testcreate", description=self.textblob, creator="r1", authorizer="r1") passwordentry.add_recipients( secret=self.secret, distributor="r1", recipients=self.idobj.recipient_list, session=self.session, )
def _run_command_execution(self): #################################################################### """Run function for class.""" #################################################################### password = PasswordEntry() password.read_password_data( path.join(self.args["pwstore"], self.args["pwname"])) # Metadata yield self.color_print("Metadata:", "first_level") for key, value in password.metadata.items(): yield f" {self.color_print(key.capitalize(), 'second_level')}: {value}" # Escrow if password.escrow: yield self.color_print("\nEscrow Groups:", "first_level") for group_key, group_value in password.escrow.items(): yield f" {self.color_print(group_key, 'second_level')}:" for key, value in group_value["metadata"].items(): yield f" {self.color_print(key + ':', 'third_level')} {str(value)}" yield f" {self.color_print('Share Holders:', 'third_level')} {', '.join(list(group_value['recipients'].keys()))}" yield f" {self.color_print('Total Group Share Holders:', 'third_level')} {len(list(group_value['recipients'].keys()))}" timestamp_list = [ x["timestamp"] for x in list(group_value["recipients"].values()) if "timestamp" in x ] if timestamp_list: timestamp = int(round(float(min(timestamp_list)))) timestamp = datetime.fromtimestamp(timestamp).strftime( "%Y-%m-%d %H:%M:%S") yield f" {self.color_print('Group creation time:', 'third_level')} {timestamp}" # Recipients yield f"{self.color_print(linesep + 'Recipients:', 'first_level')} {', '.join(list(password.recipients.keys()))}" yield f"{self.color_print('Total Recipients:', 'first_level')} {len(list(password.recipients.keys()))}" rec_timestamp = int( round( float( min([ x["timestamp"] for x in list(password.recipients.values()) if "timestamp" in x ])))) rec_timestamp = datetime.fromtimestamp(rec_timestamp).strftime( "%Y-%m-%d %H:%M:%S") yield f"{self.color_print('Earliest distribute timestamp:', 'first_level')} {rec_timestamp}"
def safety_check(self): ################################################################## """This provides a sanity check that you are the owner of a password.""" ################################################################## try: password = PasswordEntry() password.read_password_data( path.join(self.args["pwstore"], self.args["pwname"]) ) return ( self.args["identity"] in password["recipients"], password["metadata"]["creator"], ) except PasswordIOError: return (True, None)
def update_pass(self, pass_value): pass_entry = PasswordEntry() pass_entry.read_password_data(os.path.join(self.args['pwstore'], self.args['pwname'])) swap_pass = PasswordEntry() swap_pass.add_recipients(secret=pass_value, distributor=self.args['identity'], recipients=[self.args['identity']], identitydb=self.identities, passphrase=self.passphrase, card_slot=self.args['card_slot'], pwstore=self.args['pwstore'] ) pass_entry['recipients'][self.args['identity']] = swap_pass['recipients'][self.args['identity']] pass_entry.write_password_data(os.path.join(self.args['pwstore'], self.args['pwname']), overwrite=self.args['overwrite'])
def _run_command_execution(self): """ Run function for class. """ #################################################################### password = PasswordEntry() myidentity = self.identities.iddb[self.args['identity']] if 'behalf' in self.args and self.args['behalf']: self._behalf_prep(password, myidentity) else: self._show_wrapper(password, myidentity)
def _run_command_execution(self): #################################################################### """Run function for class.""" #################################################################### password = PasswordEntry() if "behalf" in self.args and self.args["behalf"]: yield from self._behalf_prep(password) else: yield from self._show_wrapper(password)
def create_pass(self, password1, description, authorizer, recipient_list=None): ################################################################## """This writes password data to a file.""" ################################################################## password_metadata = {} password_metadata["description"] = description password_metadata["authorizer"] = authorizer password_metadata["creator"] = self.args["identity"] password_metadata["name"] = self.args["pwname"] if self.args["noescrow"]: self.args["min_escrow"] = None self.args["escrow_users"] = None if recipient_list is None: recipient_list = [self.args["identity"]] password = PasswordEntry(**password_metadata) password.add_recipients( secret=password1, distributor=self.args["identity"], recipients=recipient_list, session=self.session, passphrase=self.passphrase, card_slot=self.args["card_slot"], escrow_users=self.args["escrow_users"], minimum=self.args["min_escrow"], pwstore=self.args["pwstore"], ) password.write_password_data( path.join(self.args["pwstore"], self.args["pwname"]), overwrite=self.args["overwrite"], )
def create_pass(self, password1, description, authorizer, recipient_list=None): """ This writes password data to a file.""" ################################################################## password_metadata = {} password_metadata['description'] = description password_metadata['authorizer'] = authorizer password_metadata['creator'] = self.args['identity'] password_metadata['name'] = self.args['pwname'] if self.args['noescrow']: self.args['min_escrow'] = None self.args['escrow_users'] = None if recipient_list is None: recipient_list = [self.args['identity']] password = PasswordEntry(**password_metadata) password.add_recipients(secret=password1, distributor=self.args['identity'], recipients=recipient_list, identitydb=self.identities, passphrase=self.passphrase, card_slot=self.args['card_slot'], escrow_users=self.args['escrow_users'], minimum=self.args['min_escrow'], pwstore=self.args['pwstore'] ) password.write_password_data(path.join(self.args['pwstore'], self.args['pwname']), overwrite=self.args['overwrite'])
def _run_command_execution(self): #################################################################### """ Run function for class. """ #################################################################### password = PasswordEntry() password.read_password_data( os.path.join(self.args['pwstore'], self.args['pwname'])) myidentity = self.identities.iddb[self.args['identity']] plaintext_pw = password.decrypt_entry(identity=myidentity, passphrase=self.passphrase, card_slot=self.args["card_slot"]) if not self.args['noverify']: result = password.verify_entry(myidentity['uid'], self.identities) if not result['sigOK']: print( "Warning: Could not verify that '%s' correctly signed your password entry." % result['distributor']) if not result['certOK']: print( "Warning: Could not verify the certificate authenticity of user '%s'." % result['distributor']) oldclip = pyperclip.paste() try: pyperclip.copy(plaintext_pw) print("Password copied into paste buffer for %s seconds" % self.args['time']) time.sleep(self.args['time']) finally: pyperclip.copy(oldclip)
def _run_command_execution(self): #################################################################### """ Run function for class. """ #################################################################### passworddb = PasswordDB() passworddb.load_from_directory(self.args['pwstore']) filtered_pdb = util.dictionary_filter( os.path.join(self.args['pwstore'], self.args['pwname']), passworddb.pwdb, [self.args['identity'], 'recipients']) print("The following password files have matched:") print(*filtered_pdb.keys(), sep="\n") correct_distribution = input("Is this list correct? (y/N) ") if correct_distribution and correct_distribution.lower()[0] == 'y': passworddb.pwdb = filtered_pdb db_len = len(passworddb.pwdb.keys()) i = 0 self.progress_bar(i, db_len) for dist_pass, _ in passworddb.pwdb.items(): password = PasswordEntry() password.read_password_data(dist_pass) if self.args['identity'] in password.recipients.keys(): # we shouldn't modify escrow on distribute self.args['min_escrow'] = None self.args['escrow_users'] = None plaintext_pw = password.decrypt_entry( self.identities.iddb[self.args['identity']], passphrase=self.passphrase, card_slot=self.args['card_slot']) password.add_recipients(secret=plaintext_pw, distributor=self.args['identity'], recipients=self.recipient_list, identitydb=self.identities, passphrase=self.passphrase, card_slot=self.args['card_slot'], pwstore=self.args['pwstore']) password.write_password_data(dist_pass) i += 1 self.progress_bar(i, db_len) # format the progress bar appropriately after the loop print("") else: print("Exiting due to wrong password list")
def _yaml_file(self, password): #################################################################### """This function handles the yaml format of pkpass""" #################################################################### uid = self.identity["name"] pwstore = self.args["pwstore"] self.args["pwname"] = password["metadata"]["name"] plaintext_str = password["recipients"][uid]["encrypted_secret"] full_path = os.path.join(pwstore, password["metadata"]["name"]) self.args["overwrite"] = True plist = list(password["recipients"]) if os.path.isfile(full_path): existing_password = PasswordEntry() existing_password.read_password_data(full_path) self.args["overwrite"] = False password["metadata"] = existing_password["metadata"] plist += list(existing_password["recipients"]) description = password["metadata"]["description"] authorizer = password["metadata"]["authorizer"] self.create_or_update_pass(plaintext_str, description, authorizer, plist)
def test_read_write(self): """Read and write password entry data""" passwordentry = PasswordEntry() passwordentry.read_password_data(self.file1) passwordentry.write_password_data(self.file2, overwrite=True) with open(self.file1, 'r') as file1: with open(self.file2, 'r') as file2: self.assertTrue(file1.read() == file2.read())
def _run_command_execution(self): """ Run function for class. """ #################################################################### password = PasswordEntry() myidentity = self.identities.iddb[self.args['identity']] if self.args['all']: try: self._walk_dir(self.args['pwstore'], password, myidentity, self.args['ignore_decrypt']) except DecryptionError as err: raise err elif self.args['pwname'] is None: raise PasswordIOError("No password supplied") else: self._decrypt_wrapper(self._resolve_directory_path(), password, myidentity, self.args['pwname'])
def read_password_data_from_file(self, filename): """ Open a password file, load passwords and read metadata """ ############################################################################## try: with open(filename, 'r') as fname: password_data = yaml.safe_load(fname) password_entry = PasswordEntry() password_entry.metadata = password_data['metadata'] password_entry.recipients = password_data['recipients'] if 'escrow' in password_data: password_entry.escrow = password_data['escrow'] password_entry.validate() return password_entry except (OSError, IOError, TypeError): raise PasswordIOError( "Error reading '%s' perhaps a path error for the db, or malformed file" % filename)
def _run_command_execution(self): #################################################################### """Run function for class.""" #################################################################### full_path = path.join(self.args["pwstore"], self.args["pwname"]) password = PasswordEntry() password.read_password_data(full_path) editable = ["authorizer", "description"] for key, value in password["metadata"].items(): if key in editable: yield f"""{self.color_print(f"Current value for '{key}':", "first_level")} {value}""" password["metadata"][key] = input(f"New Value for {key}: ") password.write_password_data(full_path)
def _run_command_execution(self): """ Run function for class. """ #################################################################### full_path = path.join(self.args['pwstore'], self.args['pwname']) password = PasswordEntry() password.read_password_data(full_path) editable = ['authorizer', 'description'] for key, value in password['metadata'].items(): if key in editable: print("%s %s" % (self.color_print( "Current value for '%s':" % key, "first_level"), value)) password['metadata'][key] = input("New Value for %s: " % key) password.write_password_data(full_path)
def rename_pass(self): """This renames a password that the user has created""" ################################################################## oldpath = path.join(self.args['pwstore'], self.args['pwname']) newpath = path.join(self.args['pwstore'], self.args['rename']) try: rename(oldpath, newpath) password = PasswordEntry() password.read_password_data(newpath) password['metadata']['name'] = self.args['rename'] password.write_password_data(newpath) except OSError: raise PasswordIOError("Password '%s' not found" % self.args['pwname'])
def read_password_data_from_file(self, filename): #################################################################### """Open a password file, load passwords and read metadata""" #################################################################### try: with open(filename, "r", encoding="ASCII") as fname: password_data = safe_load(fname) password_entry = PasswordEntry() password_entry.metadata = password_data["metadata"] password_entry.recipients = password_data["recipients"] if "escrow" in password_data: password_entry.escrow = password_data["escrow"] password_entry.validate() return password_entry except (OSError, IOError, TypeError) as err: raise PasswordIOError( f"Error reading '{filename}' perhaps a path error for the db, or malformed file" ) from err
def rename_pass(self): ################################################################## """This renames a password that the user has created""" ################################################################## oldpath = path.join(self.args["pwstore"], self.args["pwname"]) newpath = path.join(self.args["pwstore"], self.args["rename"]) try: rename(oldpath, newpath) password = PasswordEntry() password.read_password_data(newpath) password["metadata"]["name"] = self.args["rename"] password.write_password_data(newpath) except OSError as err: raise PasswordIOError( f"Password '{self.args['pwname']}' not found" ) from err