Example #1
0
    def __init__(self):
        super(HashiVaultPlugin, self).__init__()

        self.helper = HashiVaultHelper()
        self._options_adapter = HashiVaultOptionAdapter.from_ansible_plugin(
            self)
        self.connection_options = HashiVaultConnectionOptions(
            self._options_adapter)
Example #2
0
    def __init__(self, connection_options, adapter, **kwargs):
        # taking adapter during transition period
        self.adapter = adapter
        self.connection_options = connection_options

        self.options = kwargs

        self.helper = HashiVaultHelper()

        # check early that auth method is actually available
        self.auth_function = 'auth_' + self.options['auth_method']
        if not (hasattr(self, self.auth_function) and callable(getattr(self, self.auth_function))):
            raise AnsibleError(
                "Authentication method '%s' is not implemented. ('%s' member function not found)" % (self.options['auth_method'], self.auth_function)
            )

        client_args = self.connection_options.get_hvac_connection_options()

        self.client = self.helper.get_vault_client(**client_args)
    def __init__(self):
        super(HashiVaultPlugin, self).__init__()

        self.helper = HashiVaultHelper()
        self._options_adapter = HashiVaultOptionAdapter.from_ansible_plugin(
            self)
        self.connection_options = HashiVaultConnectionOptions(
            self._options_adapter, self._generate_retry_callback)
        self.authenticator = HashiVaultAuthenticator(self._options_adapter,
                                                     display.warning)
    def __init__(self, *args, **kwargs):
        if 'hashi_vault_custom_retry_callback' in kwargs:
            callback = kwargs.pop('hashi_vault_custom_retry_callback')
        else:
            callback = self._generate_retry_callback

        super(HashiVaultModule, self).__init__(*args, **kwargs)

        self.helper = HashiVaultHelper()
        self.adapter = HashiVaultOptionAdapter.from_dict(self.params)
        self.connection_options = HashiVaultConnectionOptions(
            option_adapter=self.adapter, retry_callback_generator=callback)
        self.authenticator = HashiVaultAuthenticator(
            option_adapter=self.adapter, warning_callback=self.warn)
Example #5
0
class HashiVault:
    # NOTE: the HashiVault class here is in the process of being removed, as functionality moves to shared classes

    def get_options(self, *option_names, **kwargs):
        ret = {}
        include_falsey = kwargs.get('include_falsey', False)
        for option in option_names:
            val = self.options.get(option)
            if val or include_falsey:
                ret[option] = val
        return ret

    def __init__(self, connection_options, adapter, **kwargs):
        # taking adapter during transition period
        self.adapter = adapter
        self.connection_options = connection_options

        self.options = kwargs

        self.helper = HashiVaultHelper()

        # check early that auth method is actually available
        self.auth_function = 'auth_' + self.options['auth_method']
        if not (hasattr(self, self.auth_function) and callable(getattr(self, self.auth_function))):
            raise AnsibleError(
                "Authentication method '%s' is not implemented. ('%s' member function not found)" % (self.options['auth_method'], self.auth_function)
            )

        client_args = self.connection_options.get_hvac_connection_options()

        self.client = self.helper.get_vault_client(**client_args)

    def authenticate(self):
        # We've already checked to ensure a method exists for a particular auth_method, of the form:
        #
        # auth_<method_name>
        #
        # so just call it
        getattr(self, self.auth_function)()

    def get(self):
        '''gets a secret. should always return a list'''
        secret = self.options['secret']
        field = self.options['secret_field']
        return_as = self.options['return_format']

        try:
            data = self.client.read(secret)
        except hvac.exceptions.Forbidden:
            raise AnsibleError("Forbidden: Permission Denied to secret '%s'." % secret)

        if data is None:
            raise AnsibleError("The secret '%s' doesn't seem to exist." % secret)

        if return_as == 'raw':
            return [data]

        # Check response for KV v2 fields and flatten nested secret data.
        # https://vaultproject.io/api/secret/kv/kv-v2.html#sample-response-1
        try:
            # sentinel field checks
            check_dd = data['data']['data']
            check_md = data['data']['metadata']
            # unwrap nested data
            data = data['data']
        except KeyError:
            pass

        if return_as == 'values':
            return list(data['data'].values())

        # everything after here implements return_as == 'dict'
        if not field:
            return [data['data']]

        if field not in data['data']:
            raise AnsibleError("The secret %s does not contain the field '%s'. for hashi_vault lookup" % (secret, field))

        return [data['data'][field]]

    # begin auth implementation methods
    #
    # To add new backends, 3 things should be added:
    #
    # 1. Add a new validate_auth_<method_name> method to the LookupModule, which is responsible for validating
    #    that it has the necessary options and whatever else it needs.
    #
    # 2. Update the avail_auth_methods list in the LookupModule's auth_methods() method (for now this is static).
    #
    # 3. Add a new auth_<method_name> method to this class. These implementations are faily minimal as they should
    #    already have everything they need. This is also the place to check for deprecated auth methods as hvac
    #    continues to move backends into the auth_methods class.
    #
    #    hvac is moving auth methods into the auth_methods class (added in 0.7.0)
    #    which lives in the client.auth member.
    #    https://github.com/hvac/hvac/releases/tag/v0.7.0
    #
    #    Attempting to find which backends were moved into the class when (this is primarily for warnings):
    #    0.7.0 -- github, ldap, mfa, azure?, gcp
    #    0.7.1 -- okta
    #    0.8.0 -- kubernetes
    #    0.9.0 -- azure?, radius
    #    0.9.3 -- aws
    #    0.9.6 -- userpass
    #    0.10.5 -- jwt (new)
    #    0.10.6 -- approle
    #
    def auth_token(self):
        if self.options['auth_method'] == 'token':
            self.client.token = self.options.get('token')

        if self.options.get('token_validate') and not self.client.is_authenticated():
            raise AnsibleError("Invalid Hashicorp Vault Token Specified for hashi_vault lookup.")

    def auth_userpass(self):
        params = self.get_options('username', 'password', 'mount_point')
        try:
            response = self.client.auth.userpass.login(**params)
            # must manually set the client token with userpass login
            # see https://github.com/hvac/hvac/issues/644
            self.client.token = response['auth']['client_token']
        except (NotImplementedError, AttributeError):
            display.warning("HVAC should be updated to version 0.9.6 or higher. Deprecated method 'auth_userpass' will be used.")
            self.client.auth_userpass(**params)

    def auth_ldap(self):
        params = self.get_options('username', 'password', 'mount_point')
        try:
            self.client.auth.ldap.login(**params)
        except (NotImplementedError, AttributeError):
            display.warning("HVAC should be updated to version 0.7.0 or higher. Deprecated method 'auth_ldap' will be used.")
            self.client.auth_ldap(**params)

    def auth_approle(self):
        params = self.get_options('role_id', 'secret_id', 'mount_point')
        try:
            self.client.auth.approle.login(**params)
        except (NotImplementedError, AttributeError):
            display.warning("HVAC should be updated to version 0.10.6 or higher. Deprecated method 'auth_approle' will be used.")
            self.client.auth_approle(**params)

    def auth_aws_iam_login(self):
        params = self.options['_auth_aws_iam_login_params']
        try:
            self.client.auth.aws.iam_login(**params)
        except (NotImplementedError, AttributeError):
            display.warning("HVAC should be updated to version 0.9.3 or higher. Deprecated method 'auth_aws_iam' will be used.")
            self.client.auth_aws_iam(**params)

    def auth_jwt(self):
        params = self.get_options('role_id', 'jwt', 'mount_point')
        params['role'] = params.pop('role_id')

        if 'mount_point' in params:
            params['path'] = params.pop('mount_point')

        try:
            response = self.client.auth.jwt.jwt_login(**params)
            # must manually set the client token with JWT login
            # see https://github.com/hvac/hvac/issues/644
            self.client.token = response['auth']['client_token']
        except (NotImplementedError, AttributeError):
            raise AnsibleError("JWT authentication requires HVAC version 0.10.5 or higher.")
def hashi_vault_helper():
    return HashiVaultHelper()