Ejemplo n.º 1
0
def vault_encrypt(plaintext, secret):
    """
    Vault encrypt a piece of data.
    """
    try:
        vault = VaultLib()
        secret_file = get_file_vault_secret(filename=secret,
                                            loader=DataLoader())
        secret_file.load()
        vault.secrets = [('default', secret_file)]

        return vault.encrypt(plaintext)
    except AnsibleError as exc:
        LOGGER.critical('Cannot encrypt string: %s', exc)
        sys.exit(1)
Ejemplo n.º 2
0
    def test_file(self):
        password = '******'

        tmp_file = tempfile.NamedTemporaryFile(delete=False)
        tmp_file.write(to_bytes(password))
        tmp_file.close()

        fake_loader = DictDataLoader({tmp_file.name: 'sdfadf'})

        secret = vault.get_file_vault_secret(filename=tmp_file.name, loader=fake_loader)
        secret.load()

        os.unlink(tmp_file.name)

        self.assertEqual(secret.bytes, to_bytes(password))
Ejemplo n.º 3
0
def vault_encrypt(plaintext, secret):
    '''
    Vault encrypt a piece of data.
    '''
    try:
        vault = VaultLib()
        secret_file = get_file_vault_secret(filename=secret,
                                            loader=DataLoader())
        secret_file.load()
        vault.secrets = [('default', secret_file)]

        return vault.encrypt(plaintext)
    except AnsibleError as e:
        logger.critical(f"Cannot encrypt string: {e}")
        sys.exit(1)
Ejemplo n.º 4
0
def vault_encrypt(plaintext, secret):
    """
    Vault encrypt a piece of data.
    """
    try:
        vault = VaultLib()
        secret_file = get_file_vault_secret(filename=secret,
                                            loader=DataLoader())
        secret_file.load()
        vault.secrets = [("default", secret_file)]

        return vault.encrypt(plaintext)
    except AnsibleError as e:
        logger.critical("Cannot encrypt string: {}".format(e))
        sys.exit(1)
Ejemplo n.º 5
0
    def test_file(self):
        password = '******'

        tmp_file = tempfile.NamedTemporaryFile(delete=False)
        tmp_file.write(to_bytes(password))
        tmp_file.close()

        fake_loader = DictDataLoader({tmp_file.name: 'sdfadf'})

        secret = vault.get_file_vault_secret(filename=tmp_file.name, loader=fake_loader)
        secret.load()

        os.unlink(tmp_file.name)

        self.assertEqual(secret.bytes, to_bytes(password))
Ejemplo n.º 6
0
def decrypt(secrets_file_path, decrypted_file_path):

    try:
        vault_password_file = os.environ["ANSIBLE_VAULT_PASSWORD_FILE"]
    except KeyError:
        sys.exit(3)

    with open(vault_password_file, 'r') as vpf:
        vault_password = vpf.read().replace('\n', '')

    # Load vault password and prepare secrets for decryption
    loader = DataLoader()
    secret = vault.get_file_vault_secret(filename=vault_password_file, loader=loader)
    secret.load()
    vault_secrets = [('default', secret)]
    _vault = vault.VaultLib(vault_secrets)

    # Load encrypted yml for processing
    with codecs.open(secrets_file_path, 'r', encoding='utf-8') as f:
        loaded_yaml = AnsibleLoader(f, vault_secrets=_vault.secrets).get_single_data()

    # Define decrypted file params
    flags = (os.O_CREAT | os.O_EXCL | os.O_WRONLY)
    mode = stat.S_IRUSR | stat.S_IWUSR  # 0o600 in octal
    umask = os.umask(0)  # Save current umask to prevent downgrading to 0

    # Delete and replace decrypted secrets to ensure file permissions
    try:
        os.remove(decrypted_file_path)
    except OSError:
        pass

    # Open the file descriptor
    umask_original = os.umask(umask)
    try:
        decrypted_file_fd = os.open(decrypted_file_path, flags, mode)
    finally:
        os.umask(umask_original)

    # Open file handle and write the decrypted file
    decrypted_file_out = os.fdopen(decrypted_file_fd, 'w')
    for k, v in loaded_yaml.items():
        line = "export " + str(k) + "=" + str(v) + "\n"
        decrypted_file_out.write(line)
    decrypted_file_out.close()
    print("secrets decrypted")
Ejemplo n.º 7
0
def load_yaml(yaml_file, vault_secret=None):
    """
    Load a YAML file into a python dictionary.

    The YAML file can be fully encrypted by Ansible-Vault or can contain
    multiple inline Ansible-Vault encrypted values. Ansible Vault
    encryption is ideal to store passwords or encrypt the entire file
    with sensitive data if required.
    """
    vault = VaultLib()

    if vault_secret:
        secret_file = get_file_vault_secret(filename=vault_secret,
                                            loader=DataLoader())
        secret_file.load()
        vault.secrets = [('default', secret_file)]

    data = None
    if os.path.isfile(yaml_file):
        with open(yaml_file, 'r') as stream:
            # Render environment variables using jinja templates
            contents = stream.read()
            template = Template(contents)
            stream = StringIO(template.render(env_var=os.environ))
            try:
                if is_encrypted_file(stream):
                    file_data = stream.read()
                    data = yaml.load(vault.decrypt(file_data, None))
                else:
                    loader = AnsibleLoader(stream, None, vault.secrets)
                    try:
                        data = loader.get_single_data()
                    except Exception as exc:
                        raise Exception(
                            f'Error when loading YAML config at {yaml_file} {exc}'
                        )
                    finally:
                        loader.dispose()
            except yaml.YAMLError as exc:
                raise Exception(
                    f'Error when loading YAML config at {yaml_file} {exc}')
    else:
        LOGGER.debug('No file at %s', yaml_file)

    return data
Ejemplo n.º 8
0
    def _load_file_vault_secrets(self, password_file_path=None):
        if password_file_path is None:
            password_file_path = self._config.get_config_value(
                "DEFAULT_VAULT_PASSWORD_FILE")

        password_file = Path(password_file_path)

        if password_file.name in self._file_vault_secrets:
            return

        if not password_file.is_file():
            raise FileNotFoundError(password_file)

        self._file_vault_secrets[password_file.name] = get_file_vault_secret(
            filename=password_file, loader=self._loader)
        self._file_vault_secrets[password_file.name].load()
        self._loader.set_vault_secrets([
            (password_file.name, self._file_vault_secrets[password_file.name])
        ])
Ejemplo n.º 9
0
def load_yaml(yaml_file, vault_secret=None):
    '''
    Load a YAML file into a python dictionary.

    The YAML file can be fully encrypted by Ansible-Vault or can contain
    multiple inline Ansible-Vault encrypted values. Ansible Vault
    encryption is ideal to store passwords or encrypt the entire file
    with sensitive data if required.
    '''
    vault = VaultLib()

    if vault_secret:
        secret_file = get_file_vault_secret(filename=vault_secret,
                                            loader=DataLoader())
        secret_file.load()
        vault.secrets = [('default', secret_file)]

    data = None
    if os.path.isfile(yaml_file):
        with open(yaml_file, 'r') as stream:
            try:
                if is_encrypted_file(stream):
                    file_data = stream.read()
                    data = yaml.load(vault.decrypt(file_data, None))
                else:
                    loader = AnsibleLoader(stream, None, vault.secrets)
                    try:
                        data = loader.get_single_data()
                    except Exception as exc:
                        raise Exception(
                            "Error when loading YAML config at {} {}".format(
                                yaml_file, exc))
                    finally:
                        loader.dispose()
            except yaml.YAMLError as exc:
                raise Exception(
                    "Error when loading YAML config at {} {}".format(
                        yaml_file, exc))
    else:
        logger.debug("No file at {}".format(yaml_file))

    return data
Ejemplo n.º 10
0
    def __init__(
            self,
            ansibleinventory,
            ansible_vault_password_file,
            moleculeenv):
        # Leverage the ansible python api
        # to run a playbook against a molecule host.
        #
        # see: ansible python api
        # https://docs.ansible.com/ansible/latest/dev_guide/developing_api.html

        self._moleculeenv = moleculeenv

        context.CLIARGS = ImmutableDict(
            connection='local',
            module_path=[''],
            forks=10,
            become=None,
            become_method=None,
            become_user=None,
            check=False,
            diff=False)

        loader = DataLoader()

        # Load ansible vault secrets if environment variable is set
        if ansible_vault_password_file:
            vault_id_name = 'default'
            file_vault_secret = get_file_vault_secret(
                filename=ansible_vault_password_file,
                vault_id=vault_id_name,
                loader=loader)
            file_vault_secret.load()
            loader.set_vault_secrets(
                [(ansible_vault_password_file, file_vault_secret)])

        self._loader = loader
        self._inventory = ansibleinventory
        self._variable_manager = VariableManager(
            loader=loader,
            inventory=ansibleinventory)
def main():
    vault_file = '~/.vaultpass'
    in_file = "variables.yml"

    target_env = 'test'
    external_system_name = 'blabla'
    external_system_password = '******'

    # Load vault password and prepare secrets for decryption
    loader = DataLoader()
    secret = vault.get_file_vault_secret(filename=vault_file, loader=loader)
    secret.load()
    vault_secrets = [('default', secret)]
    _vault = vault.VaultLib(vault_secrets)

    # Load encrypted yml for processing
    with codecs.open(in_file, 'r', encoding='utf-8') as f:
        loaded_yaml = AnsibleLoader(
            f, vault_secrets=_vault.secrets).get_single_data()

    # Modify yml with new encrypted values
    new_encrypted_variable = objects.AnsibleVaultEncryptedUnicode.from_plaintext(
        external_system_password, _vault, vault_secrets[0][1])

    loaded_yaml[target_env]['credentials'][external_system_name][
        'password'] = new_encrypted_variable

    # Write a new encrypted yml
    with open('new_variables.yml', 'w') as fd:
        yaml.dump(loaded_yaml,
                  fd,
                  Dumper=AnsibleDumper,
                  encoding=None,
                  default_flow_style=False)

    print(loaded_yaml)
Ejemplo n.º 12
0
    def setup_vault_secrets(loader,
                            vault_ids,
                            vault_password_files=None,
                            ask_vault_pass=None,
                            create_new_password=False,
                            auto_prompt=True):
        # list of tuples
        vault_secrets = []

        # Depending on the vault_id value (including how --ask-vault-pass / --vault-password-file create a vault_id)
        # we need to show different prompts. This is for compat with older Towers that expect a
        # certain vault password prompt format, so 'promp_ask_vault_pass' vault_id gets the old format.
        prompt_formats = {}

        # If there are configured default vault identities, they are considered 'first'
        # so we prepend them to vault_ids (from cli) here

        vault_password_files = vault_password_files or []
        if C.DEFAULT_VAULT_PASSWORD_FILE:
            vault_password_files.append(C.DEFAULT_VAULT_PASSWORD_FILE)

        if create_new_password:
            prompt_formats['prompt'] = [
                'New vault password (%(vault_id)s): ',
                'Confirm vew vault password (%(vault_id)s): '
            ]
            # 2.3 format prompts for --ask-vault-pass
            prompt_formats['prompt_ask_vault_pass'] = [
                'New Vault password: '******'Confirm New Vault password: '******'prompt'] = ['Vault password (%(vault_id)s): ']
            # The format when we use just --ask-vault-pass needs to match 'Vault password:\s*?$'
            prompt_formats['prompt_ask_vault_pass'] = ['Vault password: '******'prompt', 'prompt_ask_vault_pass']:

                # prompts cant/shouldnt work without a tty, so dont add prompt secrets
                if not sys.stdin.isatty():
                    continue

                # --vault-id some_name@prompt_ask_vault_pass --vault-id other_name@prompt_ask_vault_pass will be a little
                # confusing since it will use the old format without the vault id in the prompt
                built_vault_id = vault_id_name or C.DEFAULT_VAULT_IDENTITY

                # choose the prompt based on --vault-id=prompt or --ask-vault-pass. --ask-vault-pass
                # always gets the old format for Tower compatibility.
                # ie, we used --ask-vault-pass, so we need to use the old vault password prompt
                # format since Tower needs to match on that format.
                prompted_vault_secret = PromptVaultSecret(
                    prompt_formats=prompt_formats[vault_id_value],
                    vault_id=built_vault_id)

                # a empty or invalid password from the prompt will warn and continue to the next
                # without erroring globablly
                try:
                    prompted_vault_secret.load()
                except AnsibleError as exc:
                    display.warning('Error in vault password prompt (%s): %s' %
                                    (vault_id_name, exc))
                    raise

                vault_secrets.append((built_vault_id, prompted_vault_secret))

                # update loader with new secrets incrementally, so we can load a vault password
                # that is encrypted with a vault secret provided earlier
                loader.set_vault_secrets(vault_secrets)
                continue

            # assuming anything else is a password file
            display.vvvvv('Reading vault password file: %s' % vault_id_value)
            # read vault_pass from a file
            file_vault_secret = get_file_vault_secret(filename=vault_id_value,
                                                      vault_id=vault_id_name,
                                                      loader=loader)

            # an invalid password file will error globally
            try:
                file_vault_secret.load()
            except AnsibleError as exc:
                display.warning(
                    'Error in vault password file loading (%s): %s' %
                    (vault_id_name, exc))
                raise

            if vault_id_name:
                vault_secrets.append((vault_id_name, file_vault_secret))
            else:
                vault_secrets.append(
                    (C.DEFAULT_VAULT_IDENTITY, file_vault_secret))

            # update loader with as-yet-known vault secrets
            loader.set_vault_secrets(vault_secrets)

        return vault_secrets
Ejemplo n.º 13
0
    def setup_vault_secrets(loader, vault_ids, vault_password_files=None,
                            ask_vault_pass=None, create_new_password=False,
                            auto_prompt=True):
        # list of tuples
        vault_secrets = []

        # Depending on the vault_id value (including how --ask-vault-pass / --vault-password-file create a vault_id)
        # we need to show different prompts. This is for compat with older Towers that expect a
        # certain vault password prompt format, so 'promp_ask_vault_pass' vault_id gets the old format.
        prompt_formats = {}

        # If there are configured default vault identities, they are considered 'first'
        # so we prepend them to vault_ids (from cli) here

        vault_password_files = vault_password_files or []
        if C.DEFAULT_VAULT_PASSWORD_FILE:
            vault_password_files.append(C.DEFAULT_VAULT_PASSWORD_FILE)

        if create_new_password:
            prompt_formats['prompt'] = ['New vault password (%(vault_id)s): ',
                                        'Confirm vew vault password (%(vault_id)s): ']
            # 2.3 format prompts for --ask-vault-pass
            prompt_formats['prompt_ask_vault_pass'] = ['New Vault password: '******'Confirm New Vault password: '******'prompt'] = ['Vault password (%(vault_id)s): ']
            # The format when we use just --ask-vault-pass needs to match 'Vault password:\s*?$'
            prompt_formats['prompt_ask_vault_pass'] = ['Vault password: '******'prompt', 'prompt_ask_vault_pass']:

                # --vault-id some_name@prompt_ask_vault_pass --vault-id other_name@prompt_ask_vault_pass will be a little
                # confusing since it will use the old format without the vault id in the prompt
                built_vault_id = vault_id_name or C.DEFAULT_VAULT_IDENTITY

                # choose the prompt based on --vault-id=prompt or --ask-vault-pass. --ask-vault-pass
                # always gets the old format for Tower compatibility.
                # ie, we used --ask-vault-pass, so we need to use the old vault password prompt
                # format since Tower needs to match on that format.
                prompted_vault_secret = PromptVaultSecret(prompt_formats=prompt_formats[vault_id_value],
                                                          vault_id=built_vault_id)

                # a empty or invalid password from the prompt will warn and continue to the next
                # without erroring globablly
                try:
                    prompted_vault_secret.load()
                except AnsibleError as exc:
                    display.warning('Error in vault password prompt (%s): %s' % (vault_id_name, exc))
                    raise

                vault_secrets.append((built_vault_id, prompted_vault_secret))

                # update loader with new secrets incrementally, so we can load a vault password
                # that is encrypted with a vault secret provided earlier
                loader.set_vault_secrets(vault_secrets)
                continue

            # assuming anything else is a password file
            display.vvvvv('Reading vault password file: %s' % vault_id_value)
            # read vault_pass from a file
            file_vault_secret = get_file_vault_secret(filename=vault_id_value,
                                                      vault_id=vault_id_name,
                                                      loader=loader)

            # an invalid password file will error globally
            try:
                file_vault_secret.load()
            except AnsibleError as exc:
                display.warning('Error in vault password file loading (%s): %s' % (vault_id_name, exc))
                raise

            if vault_id_name:
                vault_secrets.append((vault_id_name, file_vault_secret))
            else:
                vault_secrets.append((C.DEFAULT_VAULT_IDENTITY, file_vault_secret))

            # update loader with as-yet-known vault secrets
            loader.set_vault_secrets(vault_secrets)

        return vault_secrets
Ejemplo n.º 14
0
    def setup_vault_secrets(loader,
                            vault_ids,
                            vault_password_files=None,
                            ask_vault_pass=None,
                            create_new_password=False):
        # list of tuples
        vault_secrets = []

        # Depending on the vault_id value (including how --ask-vault-pass / --vault-password-file create a vault_id)
        # we need to show different prompts. This is for compat with older Towers that expect a
        # certain vault password prompt format, so 'promp_ask_vault_pass' vault_id gets the old format.
        prompt_formats = {}

        vault_password_files = vault_password_files or []
        if C.DEFAULT_VAULT_PASSWORD_FILE:
            vault_password_files.append(C.DEFAULT_VAULT_PASSWORD_FILE)

        if create_new_password:
            prompt_formats['prompt'] = [
                'New vault password (%(vault_id)s): ',
                'Confirm vew vault password (%(vault_id)s): '
            ]
        else:
            prompt_formats['prompt'] = ['Vault password (%(vault_id)s): ']
            # The format when we use just --ask-vault-pass needs to match 'Vault password:\s*?$'
            prompt_formats['prompt_ask_vault_pass'] = ['Vault password: '******'prompt', 'prompt_ask_vault_pass']:

                # --vault-id some_name@prompt_ask_vault_pass --vault-id other_name@prompt_ask_vault_pass will be a little
                # confusing since it will use the old format without the vault id in the prompt
                if vault_id_name:
                    prompted_vault_secret = PromptVaultSecret(
                        prompt_formats=prompt_formats[vault_id_value],
                        vault_id=vault_id_name)
                    prompted_vault_secret.load()
                    vault_secrets.append(
                        (vault_id_name, prompted_vault_secret))
                else:
                    # ie, we used --ask-vault-pass, so we need to use the old vault password prompt
                    # format since Tower needs to match on that format.
                    prompted_vault_secret = PromptVaultSecret(
                        prompt_formats=prompt_formats[vault_id_value],
                        vault_id=C.DEFAULT_VAULT_IDENTITY)
                    prompted_vault_secret.load()
                    vault_secrets.append(
                        (C.DEFAULT_VAULT_IDENTITY, prompted_vault_secret))

                # update loader with new secrets incrementally, so we can load a vault password
                # that is encrypted with a vault secret provided earlier
                loader.set_vault_secrets(vault_secrets)
                continue

            # assuming anything else is a password file
            display.vvvvv('Reading vault password file: %s' % vault_id_value)
            # read vault_pass from a file
            file_vault_secret = get_file_vault_secret(
                filename=vault_id_value,
                vault_id_name=vault_id_name,
                loader=loader)
            file_vault_secret.load()
            if vault_id_name:
                vault_secrets.append((vault_id_name, file_vault_secret))
            else:
                vault_secrets.append(
                    (C.DEFAULT_VAULT_IDENTITY, file_vault_secret))

            # update loader with as-yet-known vault secrets
            loader.set_vault_secrets(vault_secrets)

        return vault_secrets
Ejemplo n.º 15
0
    def setup_vault_secrets(loader,
                            vault_ids,
                            vault_password_files=None,
                            ask_vault_pass=None,
                            create_new_password=False):
        # list of tuples
        vault_secrets = []

        if create_new_password:
            prompt_formats = [
                'New vault password (%s): ',
                'Confirm vew vault password (%s): '
            ]
        else:
            prompt_formats = ['Vault password (%s): ']

        vault_ids = CLI.build_vault_ids(vault_ids, vault_password_files,
                                        ask_vault_pass)

        for index, vault_id_slug in enumerate(vault_ids):
            vault_id_name, vault_id_value = CLI.split_vault_id(vault_id_slug)
            if vault_id_value == 'prompt':
                # TODO: we could assume --vault-id=prompt implies --ask-vault-pass
                #       if not, we need to 'if ask_vault_pass' here
                if vault_id_name:
                    prompted_vault_secret = PromptVaultSecret(
                        prompt_formats=prompt_formats, vault_id=vault_id_name)
                    prompted_vault_secret.load()
                    vault_secrets.append(
                        (vault_id_name, prompted_vault_secret))
                else:
                    prompted_vault_secret = PromptVaultSecret(
                        prompt_formats=prompt_formats,
                        vault_id=C.DEFAULT_VAULT_IDENTITY)
                    prompted_vault_secret.load()
                    vault_secrets.append(
                        (C.DEFAULT_VAULT_IDENTITY, prompted_vault_secret))

                # update loader with new secrets incrementally, so we can load a vault password
                # that is encrypted with a vault secret provided earlier
                loader.set_vault_secrets(vault_secrets)
                continue

            # assuming anything else is a password file
            display.vvvvv('Reading vault password file: %s' % vault_id_value)
            # read vault_pass from a file
            file_vault_secret = get_file_vault_secret(
                filename=vault_id_value,
                vault_id_name=vault_id_name,
                loader=loader)
            file_vault_secret.load()
            if vault_id_name:
                vault_secrets.append((vault_id_name, file_vault_secret))
            else:
                vault_secrets.append(
                    (C.DEFAULT_VAULT_IDENTITY, file_vault_secret))

            # update loader with as-yet-known vault secrets
            loader.set_vault_secrets(vault_secrets)

        return vault_secrets