def test_create_file(self, mock_editor_shell_command): def sc_side_effect(filename): return ['touch', filename] mock_editor_shell_command.side_effect = sc_side_effect tmp_file = tempfile.NamedTemporaryFile() os.unlink(tmp_file.name) _secrets = self._secrets('ansible') ve = self._vault_editor(_secrets) ve.create_file(tmp_file.name, vault.match_encrypt_secret(_secrets)[1]) self.assertTrue(os.path.exists(tmp_file.name))
def test_wrong_password(self): plaintext = u"Ansible" bob_password = "******" bobs_secret = TextVaultSecret(bob_password) bobs_secrets = [('default', bobs_secret)] bobs_vault = vault.VaultLib(bobs_secrets) ciphertext = bobs_vault.encrypt(plaintext, vault.match_encrypt_secret(bobs_secrets)[1]) try: self.vault.decrypt(ciphertext) except Exception as e: self.assertIsInstance(e, errors.AnsibleError) self.assertEqual(e.message, 'Decryption failed (no vault secrets were found that could decrypt)')
def test_wrong_password(self): plaintext = u"Ansible" bob_password = "******" bobs_secret = TextVaultSecret(bob_password) bobs_secrets = [('default', bobs_secret)] bobs_vault = vault.VaultLib(bobs_secrets) ciphertext = bobs_vault.encrypt(plaintext, vault.match_encrypt_secret(bobs_secrets)[1]) try: self.vault.decrypt(ciphertext) except Exception as e: self.assertIsInstance(e, errors.AnsibleError) self.assertEqual(e.message, 'Decryption failed (no vault secrets would found that could decrypt)')
def test_rekey_file(self): self._test_dir = self._create_test_dir() src_file_contents = to_bytes("some info in a file\nyup.") src_file_path = self._create_file(self._test_dir, 'src_file', content=src_file_contents) ve = self._vault_editor() ve.encrypt_file(src_file_path, self.vault_secret) # FIXME: update to just set self._secrets or just a new vault secret id new_password = '******' new_vault_secret = TextVaultSecret(new_password) new_vault_secrets = [('default', new_vault_secret)] ve.rekey_file(src_file_path, vault.match_encrypt_secret(new_vault_secrets)[1]) # FIXME: can just update self._secrets here new_ve = vault.VaultEditor(VaultLib(new_vault_secrets)) self._assert_file_is_encrypted(new_ve, src_file_path, src_file_contents)
def run(self): loader = DataLoader() vault_ids = self.options.vault_ids default_vault_ids = C.DEFAULT_VAULT_IDENTITY_LIST vault_ids = default_vault_ids + vault_ids encrypt_vault_id = None vault_secrets = self.setup_vault_secrets(loader, vault_ids=vault_ids, vault_password_files=self.options.vault_password_files, vault_pass=self.options.vault_pass) encrypt_secret = match_encrypt_secret(vault_secrets, encrypt_vault_id=encrypt_vault_id) self.encrypt_vault_id = encrypt_secret[0] self.encrypt_secret = encrypt_secret[1] loader.set_vault_secrets(vault_secrets) vault = VaultLib(vault_secrets) self.editor = VaultEditor(vault)
def run(self): super().run() self.loader = DataLoader() vault_ids = C.DEFAULT_VAULT_IDENTITY_LIST + list( context.CLIARGS['vault_ids']) vault_secrets = self.setup_vault_secrets( self.loader, vault_ids=vault_ids, vault_password_files=list(context.CLIARGS['vault_password_files']), ask_vault_pass=context.CLIARGS['ask_vault_pass']) if not vault_secrets: raise AnsibleOptionsError( "A vault password is required to use ansible-vault") encrypt_vault_id = context.CLIARGS.get( 'encrypt_vault_id') or C.DEFAULT_VAULT_ENCRYPT_IDENTITY if len(vault_secrets) > 1 and not encrypt_vault_id: raise AnsibleOptionsError( "Use '--encrypt-vault-id id' to choose one of the following vault ids to use for encryption: %s" % ','.join([x[0] for x in vault_secrets])) encrypt_secret = match_encrypt_secret( vault_secrets, encrypt_vault_id=encrypt_vault_id) self.encrypt_vault_id = encrypt_secret[0] self.encrypt_secret = encrypt_secret[1] self.loader.set_vault_secrets(vault_secrets) self.vault = VaultLib(vault_secrets) if len(context.CLIARGS['args']) != 1: raise AnsibleOptionsError( "Exactly one inventory file must be specified") self.file = os.path.expanduser(context.CLIARGS['args'][0]) old_umask = os.umask(0o077) self.execute() os.umask(old_umask)
def test_rekey_migration(self): v10_file = tempfile.NamedTemporaryFile(delete=False) with v10_file as f: f.write(to_bytes(v10_data)) ve = self._vault_editor(self._secrets("ansible")) # make sure the password functions for the cipher error_hit = False new_secrets = self._secrets("ansible2") try: ve.rekey_file(v10_file.name, vault.match_encrypt_secret(new_secrets)[1]) except errors.AnsibleError: raise error_hit = True # verify decrypted content f = open(v10_file.name, "rb") fdata = f.read() f.close() assert error_hit is False, "error rekeying 1.0 file to 1.1" # ensure filedata can be decrypted, is 1.1 and is AES256 vl = VaultLib(new_secrets) dec_data = None error_hit = False try: dec_data = vl.decrypt(fdata) except errors.AnsibleError: raise error_hit = True os.unlink(v10_file.name) self.assertIn(b'AES256', fdata, 'AES256 was not found in vault file %s' % to_text(fdata)) assert error_hit is False, "error decrypting migrated 1.0 file" assert dec_data.strip( ) == b"foo", "incorrect decryption of rekeyed/migrated file: %s" % dec_data
def test_rekey_migration(self): v10_file = tempfile.NamedTemporaryFile(delete=False) with v10_file as f: f.write(to_bytes(v10_data)) ve = self._vault_editor(self._secrets("ansible")) # make sure the password functions for the cipher error_hit = False new_secrets = self._secrets("ansible2") try: ve.rekey_file(v10_file.name, vault.match_encrypt_secret(new_secrets)[1]) except errors.AnsibleError: error_hit = True # verify decrypted content f = open(v10_file.name, "rb") fdata = f.read() f.close() assert error_hit is False, "error rekeying 1.0 file to 1.1" # ensure filedata can be decrypted, is 1.1 and is AES256 vl = VaultLib(new_secrets) dec_data = None error_hit = False try: dec_data = vl.decrypt(fdata) except errors.AnsibleError: error_hit = True os.unlink(v10_file.name) self.assertIn(b'AES256', fdata, 'AES256 was not found in vault file %s' % to_text(fdata)) assert error_hit is False, "error decrypting migrated 1.0 file" assert dec_data.strip() == b"foo", "incorrect decryption of rekeyed/migrated file: %s" % dec_data
def run(self): super(VaultCLI, self).run() loader = DataLoader() # set default restrictive umask old_umask = os.umask(0o077) vault_ids = list(context.CLIARGS['vault_ids']) # there are 3 types of actions, those that just 'read' (decrypt, view) and only # need to ask for a password once, and those that 'write' (create, encrypt) that # ask for a new password and confirm it, and 'read/write (rekey) that asks for the # old password, then asks for a new one and confirms it. default_vault_ids = C.DEFAULT_VAULT_IDENTITY_LIST vault_ids = default_vault_ids + vault_ids action = context.CLIARGS['action'] # TODO: instead of prompting for these before, we could let VaultEditor # call a callback when it needs it. if action in ['decrypt', 'view', 'rekey', 'edit']: vault_secrets = self.setup_vault_secrets(loader, vault_ids=vault_ids, vault_password_files=list(context.CLIARGS['vault_password_files']), ask_vault_pass=context.CLIARGS['ask_vault_pass']) if not vault_secrets: raise AnsibleOptionsError("A vault password is required to use Ansible's Vault") if action in ['encrypt', 'encrypt_string', 'create']: encrypt_vault_id = None # no --encrypt-vault-id context.CLIARGS['encrypt_vault_id'] for 'edit' if action not in ['edit']: encrypt_vault_id = context.CLIARGS['encrypt_vault_id'] or C.DEFAULT_VAULT_ENCRYPT_IDENTITY vault_secrets = None vault_secrets = \ self.setup_vault_secrets(loader, vault_ids=vault_ids, vault_password_files=list(context.CLIARGS['vault_password_files']), ask_vault_pass=context.CLIARGS['ask_vault_pass'], create_new_password=True) if len(vault_secrets) > 1 and not encrypt_vault_id: raise AnsibleOptionsError("The vault-ids %s are available to encrypt. Specify the vault-id to encrypt with --encrypt-vault-id" % ','.join([x[0] for x in vault_secrets])) if not vault_secrets: raise AnsibleOptionsError("A vault password is required to use Ansible's Vault") encrypt_secret = match_encrypt_secret(vault_secrets, encrypt_vault_id=encrypt_vault_id) # only one secret for encrypt for now, use the first vault_id and use its first secret # TODO: exception if more than one? self.encrypt_vault_id = encrypt_secret[0] self.encrypt_secret = encrypt_secret[1] if action in ['rekey']: encrypt_vault_id = context.CLIARGS['encrypt_vault_id'] or C.DEFAULT_VAULT_ENCRYPT_IDENTITY # print('encrypt_vault_id: %s' % encrypt_vault_id) # print('default_encrypt_vault_id: %s' % default_encrypt_vault_id) # new_vault_ids should only ever be one item, from # load the default vault ids if we are using encrypt-vault-id new_vault_ids = [] if encrypt_vault_id: new_vault_ids = default_vault_ids if context.CLIARGS['new_vault_id']: new_vault_ids.append(context.CLIARGS['new_vault_id']) new_vault_password_files = [] if context.CLIARGS['new_vault_password_file']: new_vault_password_files.append(context.CLIARGS['new_vault_password_file']) new_vault_secrets = \ self.setup_vault_secrets(loader, vault_ids=new_vault_ids, vault_password_files=new_vault_password_files, ask_vault_pass=context.CLIARGS['ask_vault_pass'], create_new_password=True) if not new_vault_secrets: raise AnsibleOptionsError("A new vault password is required to use Ansible's Vault rekey") # There is only one new_vault_id currently and one new_vault_secret, or we # use the id specified in --encrypt-vault-id new_encrypt_secret = match_encrypt_secret(new_vault_secrets, encrypt_vault_id=encrypt_vault_id) self.new_encrypt_vault_id = new_encrypt_secret[0] self.new_encrypt_secret = new_encrypt_secret[1] loader.set_vault_secrets(vault_secrets) # FIXME: do we need to create VaultEditor here? its not reused vault = VaultLib(vault_secrets) self.editor = VaultEditor(vault) context.CLIARGS['func']() # and restore umask os.umask(old_umask)
def run(self): super(VaultCLI, self).run() loader = DataLoader() # set default restrictive umask old_umask = os.umask(0o077) vault_ids = self.options.vault_ids # there are 3 types of actions, those that just 'read' (decrypt, view) and only # need to ask for a password once, and those that 'write' (create, encrypt) that # ask for a new password and confirm it, and 'read/write (rekey) that asks for the # old password, then asks for a new one and confirms it. default_vault_ids = C.DEFAULT_VAULT_IDENTITY_LIST vault_ids = default_vault_ids + vault_ids # TODO: instead of prompting for these before, we could let VaultEditor # call a callback when it needs it. if self.action in ['decrypt', 'view', 'rekey', 'edit']: vault_secrets = self.setup_vault_secrets(loader, vault_ids=vault_ids, vault_password_files=self.options.vault_password_files, ask_vault_pass=self.options.ask_vault_pass) if not vault_secrets: raise AnsibleOptionsError("A vault password is required to use Ansible's Vault") if self.action in ['encrypt', 'encrypt_string', 'create']: if len(vault_ids) > 1: raise AnsibleOptionsError("Only one --vault-id can be used for encryption") vault_secrets = None vault_secrets = \ self.setup_vault_secrets(loader, vault_ids=vault_ids, vault_password_files=self.options.vault_password_files, ask_vault_pass=self.options.ask_vault_pass, create_new_password=True) if not vault_secrets: raise AnsibleOptionsError("A vault password is required to use Ansible's Vault") encrypt_secret = match_encrypt_secret(vault_secrets) # only one secret for encrypt for now, use the first vault_id and use its first secret # self.encrypt_vault_id = list(vault_secrets.keys())[0] # self.encrypt_secret = vault_secrets[self.encrypt_vault_id][0] self.encrypt_vault_id = encrypt_secret[0] self.encrypt_secret = encrypt_secret[1] if self.action in ['rekey']: new_vault_ids = [] if self.options.new_vault_id: new_vault_ids.append(self.options.new_vault_id) new_vault_secrets = \ self.setup_vault_secrets(loader, vault_ids=new_vault_ids, vault_password_files=self.options.new_vault_password_files, ask_vault_pass=self.options.ask_vault_pass, create_new_password=True) if not new_vault_secrets: raise AnsibleOptionsError("A new vault password is required to use Ansible's Vault rekey") # There is only one new_vault_id currently and one new_vault_secret new_encrypt_secret = match_encrypt_secret(new_vault_secrets) self.new_encrypt_vault_id = new_encrypt_secret[0] self.new_encrypt_secret = new_encrypt_secret[1] loader.set_vault_secrets(vault_secrets) # FIXME: do we need to create VaultEditor here? its not reused vault = VaultLib(vault_secrets) self.editor = VaultEditor(vault) self.execute() # and restore umask os.umask(old_umask)
def _from_plaintext(self, seq): id_secret = vault.match_encrypt_secret(self.good_vault_secrets) return objects.AnsibleVaultEncryptedUnicode.from_plaintext( seq, vault=self.vault, secret=id_secret[1])
def run(self): super(VaultCLI, self).run() loader = DataLoader() # set default restrictive umask old_umask = os.umask(0o077) vault_ids = self.options.vault_ids # there are 3 types of actions, those that just 'read' (decrypt, view) and only # need to ask for a password once, and those that 'write' (create, encrypt) that # ask for a new password and confirm it, and 'read/write (rekey) that asks for the # old password, then asks for a new one and confirms it. default_vault_ids = C.DEFAULT_VAULT_IDENTITY_LIST vault_ids = default_vault_ids + vault_ids # TODO: instead of prompting for these before, we could let VaultEditor # call a callback when it needs it. if self.action in ['decrypt', 'view', 'rekey', 'edit']: vault_secrets = self.setup_vault_secrets(loader, vault_ids=vault_ids, vault_password_files=self.options.vault_password_files, ask_vault_pass=self.options.ask_vault_pass) if not vault_secrets: raise AnsibleOptionsError("A vault password is required to use Ansible's Vault") if self.action in ['encrypt', 'encrypt_string', 'create']: if len(vault_ids) > 1: raise AnsibleOptionsError("Only one --vault-id can be used for encryption") vault_secrets = None vault_secrets = \ self.setup_vault_secrets(loader, vault_ids=vault_ids, vault_password_files=self.options.vault_password_files, ask_vault_pass=self.options.ask_vault_pass, create_new_password=True) if len(vault_secrets) > 1: raise AnsibleOptionsError("Only one --vault-id can be used for encryption. This includes passwords from configuration and cli.") if not vault_secrets: raise AnsibleOptionsError("A vault password is required to use Ansible's Vault") encrypt_secret = match_encrypt_secret(vault_secrets) # only one secret for encrypt for now, use the first vault_id and use its first secret # self.encrypt_vault_id = list(vault_secrets.keys())[0] # self.encrypt_secret = vault_secrets[self.encrypt_vault_id][0] self.encrypt_vault_id = encrypt_secret[0] self.encrypt_secret = encrypt_secret[1] if self.action in ['rekey']: new_vault_ids = [] if self.options.new_vault_id: new_vault_ids.append(self.options.new_vault_id) new_vault_secrets = \ self.setup_vault_secrets(loader, vault_ids=new_vault_ids, vault_password_files=self.options.new_vault_password_files, ask_vault_pass=self.options.ask_vault_pass, create_new_password=True) if not new_vault_secrets: raise AnsibleOptionsError("A new vault password is required to use Ansible's Vault rekey") # There is only one new_vault_id currently and one new_vault_secret new_encrypt_secret = match_encrypt_secret(new_vault_secrets) self.new_encrypt_vault_id = new_encrypt_secret[0] self.new_encrypt_secret = new_encrypt_secret[1] loader.set_vault_secrets(vault_secrets) # FIXME: do we need to create VaultEditor here? its not reused vault = VaultLib(vault_secrets) self.editor = VaultEditor(vault) self.execute() # and restore umask os.umask(old_umask)
def vault_secret(self): return vault.match_encrypt_secret(self.vault_secrets)[1]
def run(self): super(VaultCLI, self).run() loader = DataLoader() # set default restrictive umask old_umask = os.umask(0o077) vault_ids = self.options.vault_ids # there are 3 types of actions, those that just 'read' (decrypt, view) and only # need to ask for a password once, and those that 'write' (create, encrypt) that # ask for a new password and confirm it, and 'read/write (rekey) that asks for the # old password, then asks for a new one and confirms it. default_vault_ids = C.DEFAULT_VAULT_IDENTITY_LIST vault_ids = default_vault_ids + vault_ids # TODO: instead of prompting for these before, we could let VaultEditor # call a callback when it needs it. if self.action in ['decrypt', 'view', 'rekey', 'edit']: vault_secrets = self.setup_vault_secrets(loader, vault_ids=vault_ids, vault_password_files=self.options.vault_password_files, ask_vault_pass=self.options.ask_vault_pass) if not vault_secrets: raise AnsibleOptionsError("A vault password is required to use Ansible's Vault") if self.action in ['encrypt', 'encrypt_string', 'create']: encrypt_vault_id = None # no --encrypt-vault-id self.options.encrypt_vault_id for 'edit' if self.action not in ['edit']: encrypt_vault_id = self.options.encrypt_vault_id or C.DEFAULT_VAULT_ENCRYPT_IDENTITY vault_secrets = None vault_secrets = \ self.setup_vault_secrets(loader, vault_ids=vault_ids, vault_password_files=self.options.vault_password_files, ask_vault_pass=self.options.ask_vault_pass, create_new_password=True) if len(vault_secrets) > 1 and not encrypt_vault_id: raise AnsibleOptionsError("The vault-ids %s are available to encrypt. Specify the vault-id to encrypt with --encrypt-vault-id" % ','.join([x[0] for x in vault_secrets])) if not vault_secrets: raise AnsibleOptionsError("A vault password is required to use Ansible's Vault") encrypt_secret = match_encrypt_secret(vault_secrets, encrypt_vault_id=encrypt_vault_id) # only one secret for encrypt for now, use the first vault_id and use its first secret # TODO: exception if more than one? self.encrypt_vault_id = encrypt_secret[0] self.encrypt_secret = encrypt_secret[1] if self.action in ['rekey']: encrypt_vault_id = self.options.encrypt_vault_id or C.DEFAULT_VAULT_ENCRYPT_IDENTITY # print('encrypt_vault_id: %s' % encrypt_vault_id) # print('default_encrypt_vault_id: %s' % default_encrypt_vault_id) # new_vault_ids should only ever be one item, from # load the default vault ids if we are using encrypt-vault-id new_vault_ids = [] if encrypt_vault_id: new_vault_ids = default_vault_ids if self.options.new_vault_id: new_vault_ids.append(self.options.new_vault_id) new_vault_password_files = [] if self.options.new_vault_password_file: new_vault_password_files.append(self.options.new_vault_password_file) new_vault_secrets = \ self.setup_vault_secrets(loader, vault_ids=new_vault_ids, vault_password_files=new_vault_password_files, ask_vault_pass=self.options.ask_vault_pass, create_new_password=True) if not new_vault_secrets: raise AnsibleOptionsError("A new vault password is required to use Ansible's Vault rekey") # There is only one new_vault_id currently and one new_vault_secret, or we # use the id specified in --encrypt-vault-id new_encrypt_secret = match_encrypt_secret(new_vault_secrets, encrypt_vault_id=encrypt_vault_id) self.new_encrypt_vault_id = new_encrypt_secret[0] self.new_encrypt_secret = new_encrypt_secret[1] loader.set_vault_secrets(vault_secrets) # FIXME: do we need to create VaultEditor here? its not reused vault = VaultLib(vault_secrets) self.editor = VaultEditor(vault) self.execute() # and restore umask os.umask(old_umask)
def vault_secret(self): return match_encrypt_secret(self.vault_secrets)[1]
def _from_plaintext(self, seq): id_secret = vault.match_encrypt_secret(self.good_vault_secrets) return objects.AnsibleVaultEncryptedUnicode.from_plaintext(seq, vault=self.vault, secret=id_secret[1])