예제 #1
0
 def test_parse_vaulttext_envelope_crlf(self):
     b_vaulttext = b"$ANSIBLE_VAULT;9.9;TEST\r\nansible"
     b_ciphertext, b_version, cipher_name, vault_id = vault.parse_vaulttext_envelope(b_vaulttext)
     b_lines = b_ciphertext.split(b'\n')
     self.assertEqual(b_lines[0], b"ansible", msg="Payload was not properly split from the header")
     self.assertEqual(cipher_name, u'TEST', msg="cipher name was not properly set")
     self.assertEqual(b_version, b"9.9", msg="version was not properly set")
예제 #2
0
    def test_format_vaulttext_envelope(self):
        cipher_name = "TEST"
        b_ciphertext = b"ansible"
        b_vaulttext = vault.format_vaulttext_envelope(b_ciphertext,
                                                      cipher_name,
                                                      version=self.v.b_version,
                                                      vault_id='default')
        b_lines = b_vaulttext.split(b'\n')
        self.assertGreater(len(b_lines), 1, msg="failed to properly add header")

        b_header = b_lines[0]
        # self.assertTrue(b_header.endswith(b';TEST'), msg="header does not end with cipher name")

        b_header_parts = b_header.split(b';')
        self.assertEqual(len(b_header_parts), 4, msg="header has the wrong number of parts")
        self.assertEqual(b_header_parts[0], b'$ANSIBLE_VAULT', msg="header does not start with $ANSIBLE_VAULT")
        self.assertEqual(b_header_parts[1], self.v.b_version, msg="header version is incorrect")
        self.assertEqual(b_header_parts[2], b'TEST', msg="header does not end with cipher name")

        # And just to verify, lets parse the results and compare
        b_ciphertext2, b_version2, cipher_name2, vault_id2 = \
            vault.parse_vaulttext_envelope(b_vaulttext)
        self.assertEqual(b_ciphertext, b_ciphertext2)
        self.assertEqual(self.v.b_version, b_version2)
        self.assertEqual(cipher_name, cipher_name2)
        self.assertEqual('default', vault_id2)
예제 #3
0
    def render_POST(self, request):

        request.setHeader("Content-Type", "application/json; charset=utf-8")
        version, cipher, vault_id = '1.1', 'AES256', ''
        is_source_encrypted = True
        try:
            body = json.loads(request.content.read())
        except:
            request.setResponseCode(400)
            return json.dumps({"value": "bad input object"}).encode('utf-8')

        if body.get("password"):
            secret = VaultSecret(
                to_bytes(body["password"], "utf-8", errors='strict'))

            source = body.get("source", "")
            source = to_bytes(source, "utf-8", errors='strict')
            try:
                (payload, version, cipher,
                 vault) = parse_vaulttext_envelope(source)
            except ansible.errors.AnsibleError:
                # maybe not encrypted
                is_source_encrypted = False
                payload = source

            try:
                this_cipher = CIPHER_MAPPING[cipher]()
            except Exception as e:
                request.setResponseCode(400)
                response_text = e.message
                return json.dumps({
                    "value": "error in %s" % response_text
                }).encode('utf-8')

            try:
                if is_source_encrypted:
                    response_text = this_cipher.decrypt(payload, secret=secret)
                else:
                    response_text = format_vaulttext_envelope(
                        this_cipher.encrypt(payload, secret=secret), cipher,
                        version, vault_id).strip()
            except ansible.errors.AnsibleError as e:
                request.setResponseCode(400)
                response_text = e.message
                return json.dumps({"value": response_text}).encode('utf-8')

        else:
            request.setResponseCode(400)
            response_text = b"password not specified"

        return json.dumps({
            "value": response_text.decode('utf-8')
        }).encode('utf-8')
예제 #4
0
    def _decrypt_if_vault_data(self, b_vault_data, b_file_name=None):
        '''Decrypt b_vault_data if encrypted and return b_data and the show_content flag'''

        if not is_encrypted(b_vault_data):
            show_content = True
            return b_vault_data, show_content

        b_ciphertext, b_version, cipher_name, vault_id = parse_vaulttext_envelope(b_vault_data)
        b_data = self._vault.decrypt(b_vault_data, filename=b_file_name)

        show_content = False
        return b_data, show_content
예제 #5
0
    def _decrypt_if_vault_data(self, b_vault_data, b_file_name=None):
        '''Decrypt b_vault_data if encrypted and return b_data and the show_content flag'''

        if not is_encrypted(b_vault_data):
            show_content = True
            return b_vault_data, show_content

        b_ciphertext, b_version, cipher_name, vault_id = parse_vaulttext_envelope(b_vault_data)
        b_data = self._vault.decrypt(b_vault_data, filename=b_file_name)

        show_content = False
        return b_data, show_content
예제 #6
0
    def test_non_hex(self):
        vaulttext_envelope = u'''$ANSIBLE_VAULT;1.1;AES256
3336396J326261303234626463623963633531343539616138316433353830356566396130353436
3562643163366231316662386565383735653432386435610a306664636137376132643732393835
63383038383730306639353234326630666539346233376330303938323639306661313032396437
6233623062366136310a633866373936313238333730653739323461656662303864663666653563
3138'''

        b_vaulttext_envelope = to_bytes(vaulttext_envelope, errors='strict', encoding='utf-8')
        b_vaulttext, b_version, cipher_name, vault_id = vault.parse_vaulttext_envelope(b_vaulttext_envelope)
        self.assertRaisesRegexp(vault.AnsibleVaultFormatError,
                                '.*Vault format unhexlify error.*Non-hexadecimal digit found',
                                vault.parse_vaulttext,
                                b_vaulttext_envelope)
예제 #7
0
    def test(self):
        vaulttext_envelope = u'''$ANSIBLE_VAULT;1.1;AES256
33363965326261303234626463623963633531343539616138316433353830356566396130353436
3562643163366231316662386565383735653432386435610a306664636137376132643732393835
63383038383730306639353234326630666539346233376330303938323639306661313032396437
6233623062366136310a633866373936313238333730653739323461656662303864663666653563
3138'''

        b_vaulttext_envelope = to_bytes(vaulttext_envelope, errors='strict', encoding='utf-8')
        b_vaulttext, b_version, cipher_name, vault_id = vault.parse_vaulttext_envelope(b_vaulttext_envelope)
        res = vault.parse_vaulttext(b_vaulttext)
        self.assertIsInstance(res[0], bytes)
        self.assertIsInstance(res[1], bytes)
        self.assertIsInstance(res[2], bytes)
예제 #8
0
    def test_non_hex(self):
        vaulttext_envelope = u'''$ANSIBLE_VAULT;1.1;AES256
3336396J326261303234626463623963633531343539616138316433353830356566396130353436
3562643163366231316662386565383735653432386435610a306664636137376132643732393835
63383038383730306639353234326630666539346233376330303938323639306661313032396437
6233623062366136310a633866373936313238333730653739323461656662303864663666653563
3138'''

        b_vaulttext_envelope = to_bytes(vaulttext_envelope, errors='strict', encoding='utf-8')
        b_vaulttext, b_version, cipher_name, vault_id = vault.parse_vaulttext_envelope(b_vaulttext_envelope)
        self.assertRaisesRegexp(vault.AnsibleVaultFormatError,
                                '.*Vault format unhexlify error.*Non-hexadecimal digit found',
                                vault.parse_vaulttext,
                                b_vaulttext_envelope)
예제 #9
0
    def test(self):
        vaulttext_envelope = u'''$ANSIBLE_VAULT;1.1;AES256
33363965326261303234626463623963633531343539616138316433353830356566396130353436
3562643163366231316662386565383735653432386435610a306664636137376132643732393835
63383038383730306639353234326630666539346233376330303938323639306661313032396437
6233623062366136310a633866373936313238333730653739323461656662303864663666653563
3138'''

        b_vaulttext_envelope = to_bytes(vaulttext_envelope, errors='strict', encoding='utf-8')
        b_vaulttext, b_version, cipher_name, vault_id = vault.parse_vaulttext_envelope(b_vaulttext_envelope)
        res = vault.parse_vaulttext(b_vaulttext)
        self.assertIsInstance(res[0], bytes)
        self.assertIsInstance(res[1], bytes)
        self.assertIsInstance(res[2], bytes)
예제 #10
0
    def _get_file_contents(self, file_name):
        '''
        Reads the file contents from the given file name

        If the contents are vault-encrypted, it will decrypt them and return
        the decrypted data

        :arg file_name: The name of the file to read.  If this is a relative
            path, it will be expanded relative to the basedir
        :raises AnsibleFileNotFOund: if the file_name does not refer to a file
        :raises AnsibleParserError: if we were unable to read the file
        :return: Returns a byte string of the file contents
        '''
        if not file_name or not isinstance(file_name,
                                           (binary_type, text_type)):
            raise AnsibleParserError("Invalid filename: '%s'" % str(file_name))

        b_file_name = to_bytes(self.path_dwim(file_name))
        # This is what we really want but have to fix unittests to make it pass
        # if not os.path.exists(b_file_name) or not os.path.isfile(b_file_name):
        if not self.path_exists(b_file_name) or not self.is_file(b_file_name):
            raise AnsibleFileNotFound("Unable to retrieve file contents",
                                      file_name=file_name)

        show_content = True
        try:
            with open(b_file_name, 'rb') as f:
                data = f.read()
                if is_encrypted(data):
                    # FIXME: plugin vault selector
                    b_ciphertext, b_version, cipher_name, vault_id = parse_vaulttext_envelope(
                        data)
                    data = self._vault.decrypt(data, filename=b_file_name)
                    show_content = False

            return (data, show_content)

        except (IOError, OSError) as e:
            raise AnsibleParserError(
                "an error occurred while trying to read the file '%s': %s" %
                (file_name, str(e)),
                orig_exc=e)
예제 #11
0
    def test_decrypt_non_default_1_2(self):
        b_expected_plaintext = to_bytes('foo bar\n')
        vaulttext = '''$ANSIBLE_VAULT;1.2;AES256;ansible_devel
65616435333934613466373335363332373764363365633035303466643439313864663837393234
3330656363343637313962633731333237313636633534630a386264363438363362326132363239
39363166646664346264383934393935653933316263333838386362633534326664646166663736
6462303664383765650a356637643633366663643566353036303162386237336233393065393164
6264'''

        vault_secrets = self._vault_secrets_from_password('default', 'ansible')
        v = vault.VaultLib(vault_secrets)

        b_vaulttext = to_bytes(vaulttext)

        b_plaintext = v.decrypt(b_vaulttext)
        self.assertEqual(b_expected_plaintext, b_plaintext)

        b_ciphertext, b_version, cipher_name, vault_id = vault.parse_vaulttext_envelope(b_vaulttext)
        self.assertEqual('ansible_devel', vault_id)
        self.assertEqual(b'1.2', b_version)
예제 #12
0
    def _get_file_contents(self, file_name):
        '''
        Reads the file contents from the given file name

        If the contents are vault-encrypted, it will decrypt them and return
        the decrypted data

        :arg file_name: The name of the file to read.  If this is a relative
            path, it will be expanded relative to the basedir
        :raises AnsibleFileNotFOund: if the file_name does not refer to a file
        :raises AnsibleParserError: if we were unable to read the file
        :return: Returns a byte string of the file contents
        '''
        if not file_name or not isinstance(file_name, (binary_type, text_type)):
            raise AnsibleParserError("Invalid filename: '%s'" % str(file_name))

        b_file_name = to_bytes(self.path_dwim(file_name))
        # This is what we really want but have to fix unittests to make it pass
        # if not os.path.exists(b_file_name) or not os.path.isfile(b_file_name):
        if not self.path_exists(b_file_name) or not self.is_file(b_file_name):
            raise AnsibleFileNotFound("Unable to retrieve file contents", file_name=file_name)

        show_content = True
        try:
            with open(b_file_name, 'rb') as f:
                data = f.read()
                if is_encrypted(data):
                    # FIXME: plugin vault selector
                    b_ciphertext, b_version, cipher_name, vault_id = parse_vaulttext_envelope(data)
                    data = self._vault.decrypt(data, filename=b_file_name)
                    show_content = False

            return (data, show_content)

        except (IOError, OSError) as e:
            raise AnsibleParserError("an error occurred while trying to read the file '%s': %s" % (file_name, str(e)), orig_exc=e)
예제 #13
0
    def run(self, tmp=None, task_vars=None):
        if task_vars is None:
            task_vars = dict()

        result = super(ActionModule, self).run(tmp, task_vars)
        del tmp  # tmp is deprecated

        # If user supplies vault-id and vault-pass, use them.  Otherwise use those that are automatically loaded with the playbook
        if 'vaultpass' in self._task.args:
            oVaultSecret = VaultSecret(
                self._task.args["vaultpass"].encode('utf-8'))
            if 'vaultid' in self._task.args:
                oVaultLib = VaultLib([(self._task.args["vaultid"],
                                       oVaultSecret)])
            else:
                display.v(u'No vault-id supplied, using default identity.')
                oVaultLib = VaultLib([(C.DEFAULT_VAULT_IDENTITY, oVaultSecret)
                                      ])
        else:
            display.v(
                u'No vault-id or vault-pass supplied, using playbook-sourced variables.'
            )
            oVaultLib = self._loader._vault
            if len(self._loader._vault.secrets) == 0:
                display.warning(
                    "No Vault secrets loaded by config and none supplied to plugin.  Vault operations are not possible."
                )

        if self._task.args["action"] == "encrypt":
            if "plaintext" not in self._task.args:
                return {
                    "failed": True,
                    "msg": "'plaintext' is required for encrypt."
                }

            b_vaulttext = oVaultLib.encrypt(self._task.args["plaintext"])
            b_ciphertext, b_version, cipher_name, vault_id = parse_vaulttext_envelope(
                b_vaulttext)

            vaulttext_header = b_vaulttext.decode('utf-8').split('\n', 1)[0]
            ciphertext = b_ciphertext.decode('utf-8')

            if 'multiline_out' in self._task.args and self._task.args[
                    "multiline_out"] == True:
                multiline_length = 80
                ciphertext = '\n'.join([
                    ciphertext[i:i + multiline_length]
                    for i in range(0, len(ciphertext), multiline_length)
                ])

            result['vaulttext'] = vaulttext_header + "\n" + ciphertext
            result['plaintext'] = self._task.args["plaintext"]

        else:
            if "vaulttext" not in self._task.args:
                return {
                    "failed": True,
                    "msg": "'vaulttext' is required for decrypt."
                }

            plaintext = oVaultLib.decrypt(self._task.args["vaulttext"])
            result['vaulttext'] = self._task.args["vaulttext"]
            result['plaintext'] = plaintext

        result['failed'] = False

        return result
예제 #14
0
from cryptography.hazmat.primitives import hashes, padding
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.ciphers import (Cipher as C_Cipher,
                                                    algorithms, modes)

dir = os.path.dirname(__file__)
filename = dir + '/files/OnePointOneStringNoTag.txt'
vault_text = open(filename, 'r').read()

lib = VaultLib(secrets=[['default', VaultSecret("daniel-ness/ansible-vault")]])
print lib.decrypt(vault_text)

plaintext, vault_id, vault_secret = lib.decrypt_and_get_vault_id(vault_text)
print plaintext
print vault_text
b_vaulttext, dummy, cipher_name, vault_id = parse_vaulttext_envelope(
    vault_text)
print b_vaulttext
cipher_text, salt, crypted_hmac = parse_vaulttext(b_vaulttext)

print("Cipher Text: " + hexlify(cipher_text))
print("Salt: " + hexlify(salt))
print("HMAC: " + crypted_hmac)

aes = VaultAES256()
key1, key2, iv = aes._gen_key_initctr("daniel-ness/ansible-vault", salt)

print("Key1: " + hexlify(key1))
print("Key2: " + hexlify(key2))
print("IV: " + hexlify(iv))

print("pre decrypt:")