diff --git a/.github/BOTMETA.yml b/.github/BOTMETA.yml index 4b10d2e91f..5041a7e688 100644 --- a/.github/BOTMETA.yml +++ b/.github/BOTMETA.yml @@ -94,9 +94,6 @@ files: maintainers: amigus $lookups/dsv.py: maintainers: amigus - $lookups/hashi_vault.py: - labels: hashi_vault - maintainers: briantist $lookups/manifold.py: maintainers: galanoff labels: manifold diff --git a/changelogs/fragments/1024-vault-skip-verify-support.yml b/changelogs/fragments/1024-vault-skip-verify-support.yml deleted file mode 100644 index fe275bcfd0..0000000000 --- a/changelogs/fragments/1024-vault-skip-verify-support.yml +++ /dev/null @@ -1,3 +0,0 @@ ---- -minor_changes: - - hashi_vault - support ``VAULT_SKIP_VERIFY`` environment variable for determining if to verify certificates (in addition to the ``validate_certs=`` flag supported today) (https://github.com/ansible-collections/community.general/pull/1024). diff --git a/changelogs/fragments/1138-hashi_vault_fix_approle_authentication_without_secret_id.yml b/changelogs/fragments/1138-hashi_vault_fix_approle_authentication_without_secret_id.yml deleted file mode 100644 index 840e10d4a9..0000000000 --- a/changelogs/fragments/1138-hashi_vault_fix_approle_authentication_without_secret_id.yml +++ /dev/null @@ -1,2 +0,0 @@ -bugfixes: -- hashi_vault - fix approle authentication without ``secret_id`` (https://github.com/ansible-collections/community.general/pull/1138). diff --git a/changelogs/fragments/1213-hashi_vault-jwt-auth-support.yaml b/changelogs/fragments/1213-hashi_vault-jwt-auth-support.yaml deleted file mode 100644 index 15444c3352..0000000000 --- a/changelogs/fragments/1213-hashi_vault-jwt-auth-support.yaml +++ /dev/null @@ -1,2 +0,0 @@ -minor_changes: - - hashi_vault lookup plugin - add support for JWT authentication (https://github.com/ansible-collections/community.general/pull/1213). diff --git a/changelogs/fragments/897-lookup-plugin-hashivault-add-approle-mount-point.yaml b/changelogs/fragments/897-lookup-plugin-hashivault-add-approle-mount-point.yaml deleted file mode 100644 index cd2f449bd0..0000000000 --- a/changelogs/fragments/897-lookup-plugin-hashivault-add-approle-mount-point.yaml +++ /dev/null @@ -1,3 +0,0 @@ ---- -bugfixes: - - hashi_vault - add missing ``mount_point`` parameter for approle auth (https://github.com/ansible-collections/community.general/pull/897). diff --git a/changelogs/fragments/902-hashi_vault-token-path.yml b/changelogs/fragments/902-hashi_vault-token-path.yml deleted file mode 100644 index 5233b3d105..0000000000 --- a/changelogs/fragments/902-hashi_vault-token-path.yml +++ /dev/null @@ -1,5 +0,0 @@ -minor_changes: - - hashi_vault lookup - add ``VAULT_TOKEN_PATH`` as env option to specify ``token_path`` param (https://github.com/ansible-collections/community.general/issues/373). - - hashi_vault lookup - add ``VAULT_TOKEN_FILE`` as env option to specify ``token_file`` param (https://github.com/ansible-collections/community.general/issues/373). -bugfixes: - - hashi_vault lookup - ``token_path`` in config file overridden by env ``HOME`` (https://github.com/ansible-collections/community.general/issues/373). diff --git a/changelogs/fragments/929-vault-namespace-support.yml b/changelogs/fragments/929-vault-namespace-support.yml deleted file mode 100644 index bf22978aff..0000000000 --- a/changelogs/fragments/929-vault-namespace-support.yml +++ /dev/null @@ -1,3 +0,0 @@ ---- -minor_changes: - - hashi_vault - support ``VAULT_NAMESPACE`` environment variable for namespaced lookups against Vault Enterprise (in addition to the ``namespace=`` flag supported today) (https://github.com/ansible-collections/community.general/pull/929). diff --git a/changelogs/fragments/hashi_vault-migration-removal.yml b/changelogs/fragments/hashi_vault-migration-removal.yml new file mode 100644 index 0000000000..f0ccd52ee1 --- /dev/null +++ b/changelogs/fragments/hashi_vault-migration-removal.yml @@ -0,0 +1,14 @@ +removed_features: +- | + The ``hashi_vault`` lookup plugin has been removed from this collection. + It has been migrated to the `community.hashi_vault `_ collection. + If you use ansible-base 2.10 or newer, redirections have been provided. + + If you use Ansible 2.9 and installed this collection, you need to adjust the FQCNs (``community.general.hashi_vault`` → ``community.hashi_vault.hashi_vault``) and make sure to install the community.hashi_vault collection. +breaking_changes: +- | + If you use Ansible 2.9 and the ``hashi_vault`` lookup plugin from this collections, community.general 2.0.0 results in errors when trying to use the Hashi Vault content by FQCN, like ``community.general.hashi_vault``. + Since Ansible 2.9 is not able to use redirections, you will have to adjust your inventories, variable files, playbooks and roles manually to use the new FQCN (``community.hashi_vault.hashi_vault``) and to make sure that you have ``community.hashi_vault`` installed. + + If you use ansible-base 2.10 or newer and did not install Ansible 3.0.0, but installed (and/or upgraded) community.general manually, you need to make sure to also install ``community.hashi_vault`` if you are using the ``hashi_vault`` plugin. + While ansible-base 2.10 or newer can use the redirects that community.general 2.0.0 adds, the collection they point to (community.hashi_vault) must be installed for them to work. diff --git a/meta/runtime.yml b/meta/runtime.yml index 446524482d..a6b2c83b5c 100644 --- a/meta/runtime.yml +++ b/meta/runtime.yml @@ -42,6 +42,8 @@ plugin_routing: lookup: gcp_storage_file: redirect: community.google.gcp_storage_file + hashi_vault: + redirect: community.hashi_vault.hashi_vault modules: ali_instance_facts: deprecation: diff --git a/plugins/lookup/hashi_vault.py b/plugins/lookup/hashi_vault.py deleted file mode 100644 index a4da243a3c..0000000000 --- a/plugins/lookup/hashi_vault.py +++ /dev/null @@ -1,650 +0,0 @@ -# (c) 2020, Brian Scholer (@briantist) -# (c) 2015, Jonathan Davila -# (c) 2017 Ansible Project -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -from __future__ import (absolute_import, division, print_function) -__metaclass__ = type - -DOCUMENTATION = """ - lookup: hashi_vault - author: - - Jonathan Davila (!UNKNOWN) - - Brian Scholer (@briantist) - short_description: Retrieve secrets from HashiCorp's Vault - requirements: - - hvac (python library) - - hvac 0.7.0+ (for namespace support) - - hvac 0.9.6+ (to avoid all deprecation warnings) - - botocore (only if inferring aws params from boto) - - boto3 (only if using a boto profile) - description: - - Retrieve secrets from HashiCorp's Vault. - notes: - - Due to a current limitation in the HVAC library there won't necessarily be an error if a bad endpoint is specified. - - As of community.general 0.2.0, only the latest version of a secret is returned when specifying a KV v2 path. - - As of community.general 0.2.0, all options can be supplied via term string (space delimited key=value pairs) or by parameters (see examples). - - As of community.general 0.2.0, when C(secret) is the first option in the term string, C(secret=) is not required (see examples). - options: - secret: - description: Vault path to the secret being requested in the format C(path[:field]). - required: True - token: - description: - - Vault token. If using token auth and no token is supplied, explicitly or through env, then the plugin will check - - for a token file, as determined by C(token_path) and C(token_file). - env: - - name: VAULT_TOKEN - token_path: - description: If no token is specified, will try to read the token file from this path. - env: - - name: VAULT_TOKEN_PATH - version_added: 1.2.0 - ini: - - section: lookup_hashi_vault - key: token_path - version_added: '0.2.0' - token_file: - description: If no token is specified, will try to read the token from this file in C(token_path). - env: - - name: VAULT_TOKEN_FILE - version_added: 1.2.0 - ini: - - section: lookup_hashi_vault - key: token_file - default: '.vault-token' - version_added: '0.2.0' - url: - description: URL to the Vault service. - env: - - name: VAULT_ADDR - ini: - - section: lookup_hashi_vault - key: url - version_added: '0.2.0' - default: 'http://127.0.0.1:8200' - username: - description: Authentication user name. - password: - description: Authentication password. - role_id: - description: Vault Role ID. Used in approle and aws_iam_login auth methods. - env: - - name: VAULT_ROLE_ID - ini: - - section: lookup_hashi_vault - key: role_id - version_added: '0.2.0' - secret_id: - description: Secret ID to be used for Vault AppRole authentication. - env: - - name: VAULT_SECRET_ID - auth_method: - description: - - Authentication method to be used. - - C(userpass) is added in Ansible 2.8. - - C(aws_iam_login) is added in community.general 0.2.0. - - C(jwt) is added in community.general 1.3.0. - env: - - name: VAULT_AUTH_METHOD - ini: - - section: lookup_hashi_vault - key: auth_method - version_added: '0.2.0' - choices: - - token - - userpass - - ldap - - approle - - aws_iam_login - - jwt - default: token - return_format: - description: - - Controls how multiple key/value pairs in a path are treated on return. - - C(dict) returns a single dict containing the key/value pairs (same behavior as before community.general 0.2.0). - - C(values) returns a list of all the values only. Use when you don't care about the keys. - - C(raw) returns the actual API result, which includes metadata and may have the data nested in other keys. - choices: - - dict - - values - - raw - default: dict - aliases: [ as ] - version_added: '0.2.0' - mount_point: - description: Vault mount point, only required if you have a custom mount point. Does not apply to token authentication. - jwt: - description: The JSON Web Token (JWT) to use for JWT authentication to Vault. - env: - - name: ANSIBLE_HASHI_VAULT_JWT - version_added: 1.3.0 - ca_cert: - description: Path to certificate to use for authentication. - aliases: [ cacert ] - validate_certs: - description: - - Controls verification and validation of SSL certificates, mostly you only want to turn off with self signed ones. - - Will be populated with the inverse of C(VAULT_SKIP_VERIFY) if that is set and I(validate_certs) is not explicitly - provided (added in community.general 1.3.0). - - Will default to C(true) if neither I(validate_certs) or C(VAULT_SKIP_VERIFY) are set. - type: boolean - namespace: - description: - - Vault namespace where secrets reside. This option requires HVAC 0.7.0+ and Vault 0.11+. - - Optionally, this may be achieved by prefixing the authentication mount point and/or secret path with the namespace - (e.g C(mynamespace/secret/mysecret)). - env: - - name: VAULT_NAMESPACE - version_added: 1.2.0 - aws_profile: - description: The AWS profile - type: str - aliases: [ boto_profile ] - env: - - name: AWS_DEFAULT_PROFILE - - name: AWS_PROFILE - version_added: '0.2.0' - aws_access_key: - description: The AWS access key to use. - type: str - aliases: [ aws_access_key_id ] - env: - - name: EC2_ACCESS_KEY - - name: AWS_ACCESS_KEY - - name: AWS_ACCESS_KEY_ID - version_added: '0.2.0' - aws_secret_key: - description: The AWS secret key that corresponds to the access key. - type: str - aliases: [ aws_secret_access_key ] - env: - - name: EC2_SECRET_KEY - - name: AWS_SECRET_KEY - - name: AWS_SECRET_ACCESS_KEY - version_added: '0.2.0' - aws_security_token: - description: The AWS security token if using temporary access and secret keys. - type: str - env: - - name: EC2_SECURITY_TOKEN - - name: AWS_SESSION_TOKEN - - name: AWS_SECURITY_TOKEN - version_added: '0.2.0' - region: - description: The AWS region for which to create the connection. - type: str - env: - - name: EC2_REGION - - name: AWS_REGION - version_added: '0.2.0' -""" - -EXAMPLES = """ -- ansible.builtin.debug: - msg: "{{ lookup('community.general.hashi_vault', 'secret=secret/hello:value token=c975b780-d1be-8016-866b-01d0f9b688a5 url=http://myvault:8200') }}" - -- name: Return all secrets from a path - ansible.builtin.debug: - msg: "{{ lookup('community.general.hashi_vault', 'secret=secret/hello token=c975b780-d1be-8016-866b-01d0f9b688a5 url=http://myvault:8200') }}" - -- name: Vault that requires authentication via LDAP - ansible.builtin.debug: - msg: "{{ lookup('community.general.hashi_vault', 'secret/hello:value auth_method=ldap mount_point=ldap username=myuser password=mypas') }}" - -- name: Vault that requires authentication via username and password - ansible.builtin.debug: - msg: "{{ lookup('community.general.hashi_vault', 'secret=secret/hello:value auth_method=userpass username=myuser password=psw url=http://myvault:8200') }}" - -- name: Connect to Vault using TLS - ansible.builtin.debug: - msg: "{{ lookup('community.general.hashi_vault', 'secret=secret/hola:value token=c975b780-d1be-8016-866b-01d0f9b688a5 validate_certs=False') }}" - -- name: using certificate auth - ansible.builtin.debug: - msg: "{{ lookup('community.general.hashi_vault', 'secret/hi:value token=xxxx url=https://myvault:8200 validate_certs=True cacert=/cacert/path/ca.pem') }}" - -- name: Authenticate with a Vault app role - ansible.builtin.debug: - msg: "{{ lookup('community.general.hashi_vault', 'secret=secret/hello:value auth_method=approle role_id=myroleid secret_id=mysecretid') }}" - -- name: Return all secrets from a path in a namespace - ansible.builtin.debug: - msg: "{{ lookup('community.general.hashi_vault', 'secret=secret/hello token=c975b780-d1be-8016-866b-01d0f9b688a5 namespace=teama/admins') }}" - -# When using KV v2 the PATH should include "data" between the secret engine mount and path (e.g. "secret/data/:path") -# see: https://www.vaultproject.io/api/secret/kv/kv-v2.html#read-secret-version -- name: Return latest KV v2 secret from path - ansible.builtin.debug: - msg: "{{ lookup('community.general.hashi_vault', 'secret=secret/data/hello token=my_vault_token url=http://myvault_url:8200') }}" - -# The following examples work in collection releases after community.general 0.2.0 - -- name: secret= is not required if secret is first - ansible.builtin.debug: - msg: "{{ lookup('community.general.hashi_vault', 'secret/data/hello token= url=http://myvault_url:8200') }}" - -- name: options can be specified as parameters rather than put in term string - ansible.builtin.debug: - msg: "{{ lookup('community.general.hashi_vault', 'secret/data/hello', token=my_token_var, url='http://myvault_url:8200') }}" - -# return_format (or its alias 'as') can control how secrets are returned to you -- name: return secrets as a dict (default) - ansible.builtin.set_fact: - my_secrets: "{{ lookup('community.general.hashi_vault', 'secret/data/manysecrets', token=my_token_var, url='http://myvault_url:8200') }}" -- ansible.builtin.debug: - msg: "{{ my_secrets['secret_key'] }}" -- ansible.builtin.debug: - msg: "Secret '{{ item.key }}' has value '{{ item.value }}'" - loop: "{{ my_secrets | dict2items }}" - -- name: return secrets as values only - ansible.builtin.debug: - msg: "A secret value: {{ item }}" - loop: "{{ query('community.general.hashi_vault', 'secret/data/manysecrets', token=my_token_var, url='http://myvault_url:8200', return_format='values') }}" - -- name: return raw secret from API, including metadata - ansible.builtin.set_fact: - my_secret: "{{ lookup('community.general.hashi_vault', 'secret/data/hello:value', token=my_token_var, url='http://myvault_url:8200', as='raw') }}" -- ansible.builtin.debug: - msg: "This is version {{ my_secret['metadata']['version'] }} of hello:value. The secret data is {{ my_secret['data']['data']['value'] }}" - -# AWS IAM authentication method -# uses Ansible standard AWS options - -- name: authenticate with aws_iam_login - ansible.builtin.debug: - msg: "{{ lookup('community.general.hashi_vault', 'secret/hello:value', auth_method='aws_iam_login', role_id='myroleid', profile=my_boto_profile) }}" - -# The following examples work in collection releases after community.general 1.3.0 - -- name: Authenticate with a JWT - ansible.builtin.debug: - msg: "{{ lookup('community.general.hashi_vault', 'secret/hello:value', auth_method='jwt', role_id='myroleid', jwt='myjwt', url='https://myvault:8200')}}" -""" - -RETURN = """ -_raw: - description: - - secrets(s) requested - type: list - elements: dict -""" - -import os - -from ansible.errors import AnsibleError -from ansible.plugins.lookup import LookupBase -from ansible.utils.display import Display -from ansible.module_utils.parsing.convert_bool import boolean - -HAS_HVAC = False -try: - import hvac - HAS_HVAC = True -except ImportError: - HAS_HVAC = False - -HAS_BOTOCORE = False -try: - # import boto3 - import botocore - HAS_BOTOCORE = True -except ImportError: - HAS_BOTOCORE = False - -HAS_BOTO3 = False -try: - import boto3 - # import botocore - HAS_BOTO3 = True -except ImportError: - HAS_BOTO3 = False - - -class HashiVault: - 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, **kwargs): - self.options = kwargs - - # 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 = { - 'url': self.options['url'], - 'verify': self.options['ca_cert'] - } - - if self.options.get('namespace'): - client_args['namespace'] = self.options['namespace'] - - # this is the only auth_method-specific thing here, because if we're using a token, we need it now - if self.options['auth_method'] == 'token': - client_args['token'] = self.options.get('token') - - self.client = hvac.Client(**client_args) - - # Check for old version, before auth_methods class (added in 0.7.0): - # https://github.com/hvac/hvac/releases/tag/v0.7.0 - # - # hvac is moving auth methods into the auth_methods class - # which lives in the client.auth member. - # - # 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 - self.hvac_has_auth_methods = hasattr(self.client, 'auth') - - # We've already checked to ensure a method exists for a particular auth_method, of the form: - # - # auth_ - # - def authenticate(self): - 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 to the LookupModule, which is responsible for validating - # that it has the necessary options and whatever else it needs. - # - # 2. Add a new auth_ 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. - # - # 3. Update the avail_auth_methods list in the LookupModules auth_methods() method (for now this is static). - # - def auth_token(self): - if 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') - if self.hvac_has_auth_methods and hasattr(self.client.auth.userpass, 'login'): - self.client.auth.userpass.login(**params) - else: - 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') -# not hasattr(self.client, 'auth') - if self.hvac_has_auth_methods and hasattr(self.client.auth.ldap, 'login'): - self.client.auth.ldap.login(**params) - else: - 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') - self.client.auth_approle(**params) - - def auth_aws_iam_login(self): - params = self.options['iam_login_credentials'] - if self.hvac_has_auth_methods and hasattr(self.client.auth.aws, 'iam_login'): - self.client.auth.aws.iam_login(**params) - else: - 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 self.hvac_has_auth_methods and hasattr(self.client.auth, 'jwt') and hasattr(self.client.auth.jwt, 'jwt_login'): - 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'] - else: - raise AnsibleError("JWT authentication requires HVAC version 0.10.5 or higher.") - - # end auth implementation methods - - -class LookupModule(LookupBase): - def run(self, terms, variables=None, **kwargs): - if not HAS_HVAC: - raise AnsibleError("Please pip install hvac to use the hashi_vault lookup module.") - - ret = [] - - for term in terms: - opts = kwargs.copy() - opts.update(self.parse_term(term)) - self.set_options(direct=opts) - self.process_options() - # FUTURE: Create one object, authenticate once, and re-use it, - # for gets, for better use during with_ loops. - client = HashiVault(**self._options) - client.authenticate() - ret.extend(client.get()) - - return ret - - def parse_term(self, term): - '''parses a term string into options''' - param_dict = {} - - for i, param in enumerate(term.split()): - try: - key, value = param.split('=', 1) - except ValueError: - if (i == 0): - # allow secret to be specified as value only if it's first - key = 'secret' - value = param - else: - raise AnsibleError("hashi_vault lookup plugin needs key=value pairs, but received %s" % term) - param_dict[key] = value - return param_dict - - def process_options(self): - '''performs deep validation and value loading for options''' - - # ca_cert to verify - self.boolean_or_cacert() - - # auth methods - self.auth_methods() - - # secret field splitter - self.field_ops() - - # begin options processing methods - - def boolean_or_cacert(self): - # This is needed because of this (https://hvac.readthedocs.io/en/stable/source/hvac_v1.html): - # - # # verify (Union[bool,str]) - Either a boolean to indicate whether TLS verification should - # # be performed when sending requests to Vault, or a string pointing at the CA bundle to use for verification. - # - '''' return a bool or cacert ''' - ca_cert = self.get_option('ca_cert') - - validate_certs = self.get_option('validate_certs') - - if validate_certs is None: - # Validate certs option was not explicitly set - - # Check if VAULT_SKIP_VERIFY is set - vault_skip_verify = os.environ.get('VAULT_SKIP_VERIFY') - - if vault_skip_verify is not None: - # VAULT_SKIP_VERIFY is set - try: - # Check that we have a boolean value - vault_skip_verify = boolean(vault_skip_verify) - # Use the inverse of VAULT_SKIP_VERIFY - validate_certs = not vault_skip_verify - except TypeError: - # Not a boolean value fallback to default value (True) - validate_certs = True - else: - validate_certs = True - - if not (validate_certs and ca_cert): - self.set_option('ca_cert', validate_certs) - - def field_ops(self): - # split secret and field - secret = self.get_option('secret') - - s_f = secret.rsplit(':', 1) - self.set_option('secret', s_f[0]) - if len(s_f) >= 2: - field = s_f[1] - else: - field = None - self.set_option('secret_field', field) - - def auth_methods(self): - # enforce and set the list of available auth methods - # TODO: can this be read from the choices: field in documentation? - avail_auth_methods = ['token', 'approle', 'userpass', 'ldap', 'aws_iam_login', 'jwt'] - self.set_option('avail_auth_methods', avail_auth_methods) - auth_method = self.get_option('auth_method') - - if auth_method not in avail_auth_methods: - raise AnsibleError( - "Authentication method '%s' not supported. Available options are %r" % (auth_method, avail_auth_methods) - ) - - # run validator if available - auth_validator = 'validate_auth_' + auth_method - if hasattr(self, auth_validator) and callable(getattr(self, auth_validator)): - getattr(self, auth_validator)(auth_method) - - # end options processing methods - - # begin auth method validators - - def validate_by_required_fields(self, auth_method, *field_names): - missing = [field for field in field_names if not self.get_option(field)] - - if missing: - raise AnsibleError("Authentication method %s requires options %r to be set, but these are missing: %r" % (auth_method, field_names, missing)) - - def validate_auth_userpass(self, auth_method): - self.validate_by_required_fields(auth_method, 'username', 'password') - - def validate_auth_ldap(self, auth_method): - self.validate_by_required_fields(auth_method, 'username', 'password') - - def validate_auth_approle(self, auth_method): - self.validate_by_required_fields(auth_method, 'role_id') - - def validate_auth_token(self, auth_method): - if auth_method == 'token': - if not self.get_option('token_path'): - # generally we want env vars defined in the spec, but in this case we want - # the env var HOME to have lower precedence than any other value source, - # including ini, so we're doing it here after all other processing has taken place - self.set_option('token_path', os.environ.get('HOME')) - if not self.get_option('token') and self.get_option('token_path'): - token_filename = os.path.join( - self.get_option('token_path'), - self.get_option('token_file') - ) - if os.path.exists(token_filename): - with open(token_filename) as token_file: - self.set_option('token', token_file.read().strip()) - - if not self.get_option('token'): - raise AnsibleError("No Vault Token specified or discovered.") - - def validate_auth_aws_iam_login(self, auth_method): - params = { - 'access_key': self.get_option('aws_access_key'), - 'secret_key': self.get_option('aws_secret_key') - } - - if self.get_option('role_id'): - params['role'] = self.get_option('role_id') - - if self.get_option('region'): - params['region'] = self.get_option('region') - - if not (params['access_key'] and params['secret_key']): - profile = self.get_option('aws_profile') - if profile: - # try to load boto profile - if not HAS_BOTO3: - raise AnsibleError("boto3 is required for loading a boto profile.") - session_credentials = boto3.session.Session(profile_name=profile).get_credentials() - else: - # try to load from IAM credentials - if not HAS_BOTOCORE: - raise AnsibleError("botocore is required for loading IAM role credentials.") - session_credentials = botocore.session.get_session().get_credentials() - - if not session_credentials: - raise AnsibleError("No AWS credentials supplied or available.") - - params['access_key'] = session_credentials.access_key - params['secret_key'] = session_credentials.secret_key - if session_credentials.token: - params['session_token'] = session_credentials.token - - self.set_option('iam_login_credentials', params) - - def validate_auth_jwt(self, auth_method): - self.validate_by_required_fields(auth_method, 'role_id', 'jwt') - - # end auth method validators diff --git a/tests/integration/targets/lookup_hashi_vault/aliases b/tests/integration/targets/lookup_hashi_vault/aliases deleted file mode 100644 index dcc12d7915..0000000000 --- a/tests/integration/targets/lookup_hashi_vault/aliases +++ /dev/null @@ -1,7 +0,0 @@ -shippable/posix/group2 -destructive -needs/target/setup_openssl -needs/file/tests/utils/constraints.txt -skip/aix -skip/python2.6 # lookups are controller only, and we no longer support Python 2.6 on the controller -skip/macos # FIXME seems to be always unstable diff --git a/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/defaults/main.yml b/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/defaults/main.yml deleted file mode 100644 index 73f6915ce6..0000000000 --- a/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/defaults/main.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -vault_gen_path: 'gen/testproject' -vault_kv1_path: 'kv1/testproject' -vault_kv2_path: 'kv2/data/testproject' -vault_kv2_multi_path: 'kv2/data/testmulti' diff --git a/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/files/jwt_private.pem b/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/files/jwt_private.pem deleted file mode 100644 index 61056a5498..0000000000 --- a/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/files/jwt_private.pem +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEogIBAAKCAQEAnzyis1ZjfNB0bBgKFMSvvkTtwlvBsaJq7S5wA+kzeVOVpVWw -kWdVha4s38XM/pa/yr47av7+z3VTmvDRyAHcaT92whREFpLv9cj5lTeJSibyr/Mr -m/YtjCZVWgaOYIhwrXwKLqPr/11inWsAkfIytvHWTxZYEcXLgAXFuUuaS3uF9gEi -NQwzGTU1v0FqkqTBr4B8nW3HCN47XUu0t8Y0e+lf4s4OxQawWD79J9/5d3Ry0vbV -3Am1FtGJiJvOwRsIfVChDpYStTcHTCMqtvWbV6L11BWkpzGXSW4Hv43qa+GSYOD2 -QU68Mb59oSk2OB+BtOLpJofmbGEGgvmwyCI9MwIDAQABAoIBACiARq2wkltjtcjs -kFvZ7w1JAORHbEufEO1Eu27zOIlqbgyAcAl7q+/1bip4Z/x1IVES84/yTaM8p0go -amMhvgry/mS8vNi1BN2SAZEnb/7xSxbflb70bX9RHLJqKnp5GZe2jexw+wyXlwaM -+bclUCrh9e1ltH7IvUrRrQnFJfh+is1fRon9Co9Li0GwoN0x0byrrngU8Ak3Y6D9 -D8GjQA4Elm94ST3izJv8iCOLSDBmzsPsXfcCUZfmTfZ5DbUDMbMxRnSo3nQeoKGC -0Lj9FkWcfmLcpGlSXTO+Ww1L7EGq+PT3NtRae1FZPwjddQ1/4V905kyQFLamAA5Y -lSpE2wkCgYEAy1OPLQcZt4NQnQzPz2SBJqQN2P5u3vXl+zNVKP8w4eBv0vWuJJF+ -hkGNnSxXQrTkvDOIUddSKOzHHgSg4nY6K02ecyT0PPm/UZvtRpWrnBjcEVtHEJNp -bU9pLD5iZ0J9sbzPU/LxPmuAP2Bs8JmTn6aFRspFrP7W0s1Nmk2jsm0CgYEAyH0X -+jpoqxj4efZfkUrg5GbSEhf+dZglf0tTOA5bVg8IYwtmNk/pniLG/zI7c+GlTc9B -BwfMr59EzBq/eFMI7+LgXaVUsM/sS4Ry+yeK6SJx/otIMWtDfqxsLD8CPMCRvecC -2Pip4uSgrl0MOebl9XKp57GoaUWRWRHqwV4Y6h8CgYAZhI4mh4qZtnhKjY4TKDjx -QYufXSdLAi9v3FxmvchDwOgn4L+PRVdMwDNms2bsL0m5uPn104EzM6w1vzz1zwKz -5pTpPI0OjgWN13Tq8+PKvm/4Ga2MjgOgPWQkslulO/oMcXbPwWC3hcRdr9tcQtn9 -Imf9n2spL/6EDFId+Hp/7QKBgAqlWdiXsWckdE1Fn91/NGHsc8syKvjjk1onDcw0 -NvVi5vcba9oGdElJX3e9mxqUKMrw7msJJv1MX8LWyMQC5L6YNYHDfbPF1q5L4i8j -8mRex97UVokJQRRA452V2vCO6S5ETgpnad36de3MUxHgCOX3qL382Qx9/THVmbma -3YfRAoGAUxL/Eu5yvMK8SAt/dJK6FedngcM3JEFNplmtLYVLWhkIlNRGDwkg3I5K -y18Ae9n7dHVueyslrb6weq7dTkYDi3iOYRW8HRkIQh06wEdbxt0shTzAJvvCQfrB -jg/3747WSsf/zBTcHihTRBdAv6OmdhV4/dD5YBfLAkLrd+mX7iE= ------END RSA PRIVATE KEY----- diff --git a/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/files/jwt_public.pem b/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/files/jwt_public.pem deleted file mode 100644 index 12301e0110..0000000000 --- a/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/files/jwt_public.pem +++ /dev/null @@ -1,9 +0,0 @@ ------BEGIN PUBLIC KEY----- -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnzyis1ZjfNB0bBgKFMSv -vkTtwlvBsaJq7S5wA+kzeVOVpVWwkWdVha4s38XM/pa/yr47av7+z3VTmvDRyAHc -aT92whREFpLv9cj5lTeJSibyr/Mrm/YtjCZVWgaOYIhwrXwKLqPr/11inWsAkfIy -tvHWTxZYEcXLgAXFuUuaS3uF9gEiNQwzGTU1v0FqkqTBr4B8nW3HCN47XUu0t8Y0 -e+lf4s4OxQawWD79J9/5d3Ry0vbV3Am1FtGJiJvOwRsIfVChDpYStTcHTCMqtvWb -V6L11BWkpzGXSW4Hv43qa+GSYOD2QU68Mb59oSk2OB+BtOLpJofmbGEGgvmwyCI9 -MwIDAQAB ------END PUBLIC KEY----- diff --git a/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/files/token.jwt b/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/files/token.jwt deleted file mode 100644 index e38d1040b8..0000000000 --- a/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/files/token.jwt +++ /dev/null @@ -1 +0,0 @@ -eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJ0ZXN0Iiwic3ViIjoiaGFzaGlfdmF1bHRAdGVzdC5hbnNpYmxlLmNvbSIsIm5iZiI6MTYwNDgzNTEwMCwiZXhwIjozMjQ5OTA1MTM1OX0.NEWQR_Eicw8Fa9gU9HPY2M9Rp1czNTUKrICwKe7l1edaZNtgxhMGdyqnBsPrHL_dw1ZIwdvwVAioi8bEyIDEWICls0lzHwM169rrea3WEFrB5CP17A6DkvYL0cnOnGutbwUrXInPCRUfvRogIKEI-w8X-ris9LX2FBPKhXX1K3U0D8uYi5_9t8YWywTe0NkYvY-nTzMugK1MXMoBJ3fCksweJiDp6BOo3v9OU03MLgwgri2UdsqVb7WSk4XvWG-lmbiiSAWVf9BI3mecVDUHpYxbEqjv1HDG_wdX8zy1ZlAFbjp3kIpMlDVK1Q5nu_VPDzQrEvPdTnOzU36LE4UF-w diff --git a/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/files/token_invalid.jwt b/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/files/token_invalid.jwt deleted file mode 100644 index aa608e6c49..0000000000 --- a/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/files/token_invalid.jwt +++ /dev/null @@ -1 +0,0 @@ -eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiIxMjM0IiwidXNlcl9jbGFpbSI6InVzZXJfY2xhaW0iLCJuYmYiOjE2MDQ4MzUxMDAsImV4cCI6MzI0OTkwNTEzNTl9.etc2WSH7kR3fHFlVt4wlBYFKNn7Z4DQcRVXUK4gGF-Q diff --git a/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/meta/main.yml b/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/meta/main.yml deleted file mode 100644 index 5438ced5c3..0000000000 --- a/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/meta/main.yml +++ /dev/null @@ -1,2 +0,0 @@ -dependencies: - - setup_pkg_mgr diff --git a/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/tasks/approle_secret_id_less_setup.yml b/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/tasks/approle_secret_id_less_setup.yml deleted file mode 100644 index 34758813ab..0000000000 --- a/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/tasks/approle_secret_id_less_setup.yml +++ /dev/null @@ -1,19 +0,0 @@ -- name: 'Create an approle policy' - shell: "echo '{{ policy }}' | {{ vault_cmd }} policy write approle-policy-2 -" - vars: - policy: | - path "auth/approle/login" { - capabilities = [ "create", "read" ] - } - -- name: 'Enable the AppRole auth method' - command: '{{ vault_cmd }} auth enable approle' - register: enable_approle - failed_when: "enable_approle.rc!=0 and 'path is already in use' not in enable_approle.stderr" - -- name: 'Create a named role without secret id' - command: '{{ vault_cmd }} write auth/approle/role/test-role-2 policies="test-policy,approle-policy-2" bind_secret_id=false secret_id_bound_cidrs="0.0.0.0/0"' - -- name: 'Fetch the RoleID of the AppRole' - command: '{{ vault_cmd }} read -field=role_id auth/approle/role/test-role-2/role-id' - register: role_id_cmd_2 diff --git a/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/tasks/approle_secret_id_less_test.yml b/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/tasks/approle_secret_id_less_test.yml deleted file mode 100644 index f78a12f0e0..0000000000 --- a/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/tasks/approle_secret_id_less_test.yml +++ /dev/null @@ -1,44 +0,0 @@ -- vars: - role_id: '{{ role_id_cmd_2.stdout }}' - block: - - name: 'Fetch secrets using "hashi_vault" lookup' - set_fact: - secret1: "{{ lookup('community.general.hashi_vault', conn_params ~ 'secret=' ~ vault_kv2_path ~ '/secret1 auth_method=approle role_id=' ~ role_id) }}" - secret2: "{{ lookup('community.general.hashi_vault', conn_params ~ 'secret=' ~ vault_kv2_path ~ '/secret2 auth_method=approle role_id=' ~ role_id) }}" - - - name: 'Check secret values' - fail: - msg: 'unexpected secret values' - when: secret1['value'] != 'foo1' or secret2['value'] != 'foo2' - - - name: 'Failure expected when erroneous credentials are used' - vars: - secret_wrong_cred: "{{ lookup('community.general.hashi_vault', conn_params ~ 'secret=' ~ vault_kv2_path ~ '/secret2 auth_method=approle role_id=foobar') }}" - debug: - msg: 'Failure is expected ({{ secret_wrong_cred }})' - register: test_wrong_cred - ignore_errors: true - - - name: 'Failure expected when unauthorized secret is read' - vars: - secret_unauthorized: "{{ lookup('community.general.hashi_vault', conn_params ~ 'secret=' ~ vault_kv2_path ~ '/secret3 auth_method=approle role_id=' ~ role_id) }}" - debug: - msg: 'Failure is expected ({{ secret_unauthorized }})' - register: test_unauthorized - ignore_errors: true - - - name: 'Failure expected when inexistent secret is read' - vars: - secret_inexistent: "{{ lookup('community.general.hashi_vault', conn_params ~ 'secret=' ~ vault_kv2_path ~ '/non_existent_secret4 auth_method=approle role_id=' ~ role_id) }}" - debug: - msg: 'Failure is expected ({{ secret_inexistent }})' - register: test_inexistent - ignore_errors: true - - - name: 'Check expected failures' - assert: - msg: "an expected failure didn't occur" - that: - - test_wrong_cred is failed - - test_unauthorized is failed - - test_inexistent is failed diff --git a/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/tasks/approle_setup.yml b/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/tasks/approle_setup.yml deleted file mode 100644 index 9f4ce2da91..0000000000 --- a/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/tasks/approle_setup.yml +++ /dev/null @@ -1,21 +0,0 @@ -- name: 'Create an approle policy' - command: - cmd: '{{ vault_cmd }} policy write approle-policy -' - stdin: | - path "auth/approle/login" { - capabilities = [ "create", "read" ] - } - -- name: 'Enable the AppRole auth method' - command: '{{ vault_cmd }} auth enable approle' - -- name: 'Create a named role' - command: '{{ vault_cmd }} write auth/approle/role/test-role policies="test-policy,approle-policy"' - -- name: 'Fetch the RoleID of the AppRole' - command: '{{ vault_cmd }} read -field=role_id auth/approle/role/test-role/role-id' - register: role_id_cmd - -- name: 'Get a SecretID issued against the AppRole' - command: '{{ vault_cmd }} write -field=secret_id -f auth/approle/role/test-role/secret-id' - register: secret_id_cmd diff --git a/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/tasks/approle_test.yml b/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/tasks/approle_test.yml deleted file mode 100644 index 7bb0d83d4a..0000000000 --- a/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/tasks/approle_test.yml +++ /dev/null @@ -1,45 +0,0 @@ -- vars: - role_id: '{{ role_id_cmd.stdout }}' - secret_id: '{{ secret_id_cmd.stdout }}' - block: - - name: 'Fetch secrets using "hashi_vault" lookup' - set_fact: - secret1: "{{ lookup('community.general.hashi_vault', conn_params ~ 'secret=' ~ vault_kv2_path ~ '/secret1 auth_method=approle secret_id=' ~ secret_id ~ ' role_id=' ~ role_id) }}" - secret2: "{{ lookup('community.general.hashi_vault', conn_params ~ 'secret=' ~ vault_kv2_path ~ '/secret2 auth_method=approle secret_id=' ~ secret_id ~ ' role_id=' ~ role_id) }}" - - - name: 'Check secret values' - fail: - msg: 'unexpected secret values' - when: secret1['value'] != 'foo1' or secret2['value'] != 'foo2' - - - name: 'Failure expected when erroneous credentials are used' - vars: - secret_wrong_cred: "{{ lookup('community.general.hashi_vault', conn_params ~ 'secret=' ~ vault_kv2_path ~ '/secret2 auth_method=approle secret_id=toto role_id=' ~ role_id) }}" - debug: - msg: 'Failure is expected ({{ secret_wrong_cred }})' - register: test_wrong_cred - ignore_errors: true - - - name: 'Failure expected when unauthorized secret is read' - vars: - secret_unauthorized: "{{ lookup('community.general.hashi_vault', conn_params ~ 'secret=' ~ vault_kv2_path ~ '/secret3 auth_method=approle secret_id=' ~ secret_id ~ ' role_id=' ~ role_id) }}" - debug: - msg: 'Failure is expected ({{ secret_unauthorized }})' - register: test_unauthorized - ignore_errors: true - - - name: 'Failure expected when inexistent secret is read' - vars: - secret_inexistent: "{{ lookup('community.general.hashi_vault', conn_params ~ 'secret=' ~ vault_kv2_path ~ '/non_existent_secret4 auth_method=approle secret_id=' ~ secret_id ~ ' role_id=' ~ role_id) }}" - debug: - msg: 'Failure is expected ({{ secret_inexistent }})' - register: test_inexistent - ignore_errors: true - - - name: 'Check expected failures' - assert: - msg: "an expected failure didn't occur" - that: - - test_wrong_cred is failed - - test_unauthorized is failed - - test_inexistent is failed diff --git a/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/tasks/jwt_setup.yml b/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/tasks/jwt_setup.yml deleted file mode 100644 index 68cc7ad9b7..0000000000 --- a/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/tasks/jwt_setup.yml +++ /dev/null @@ -1,18 +0,0 @@ -- name: 'Enable the JWT auth method' - command: '{{ vault_cmd }} auth enable jwt' - -- name: 'Configure the JWT auth method' - command: '{{ vault_cmd }} write auth/jwt/config jwt_validation_pubkeys={{ jwt_public_key | quote }}' - vars: - jwt_public_key: '{{ lookup("file", "jwt_public.pem") }}' - -- name: 'Create a named role' - command: - cmd: '{{ vault_cmd }} write auth/jwt/role/test-role -' - stdin: | - { - "role_type": "jwt", - "policies": "test-policy", - "user_claim": "sub", - "bound_audiences": "test" - } diff --git a/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/tasks/jwt_test.yml b/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/tasks/jwt_test.yml deleted file mode 100644 index 262b4e74eb..0000000000 --- a/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/tasks/jwt_test.yml +++ /dev/null @@ -1,46 +0,0 @@ -- vars: - role_id: test-role - jwt: '{{ lookup("file", "token.jwt") }}' - jwt_invalid: '{{ lookup("file", "token_invalid.jwt") }}' - block: - - name: 'Fetch secrets using "hashi_vault" lookup' - set_fact: - secret1: "{{ lookup('community.general.hashi_vault', conn_params ~ 'secret=' ~ vault_kv2_path ~ '/secret1 auth_method=jwt jwt=' ~ jwt ~ ' role_id=' ~ role_id) }}" - secret2: "{{ lookup('community.general.hashi_vault', conn_params ~ 'secret=' ~ vault_kv2_path ~ '/secret2 auth_method=jwt jwt=' ~ jwt ~ ' role_id=' ~ role_id) }}" - - - name: 'Check secret values' - fail: - msg: 'unexpected secret values' - when: secret1['value'] != 'foo1' or secret2['value'] != 'foo2' - - - name: 'Failure expected when erroneous credentials are used' - vars: - secret_wrong_cred: "{{ lookup('community.general.hashi_vault', conn_params ~ 'secret=' ~ vault_kv2_path ~ '/secret2 auth_method=jwt jwt=' ~ jwt_invalid ~ ' role_id=' ~ role_id) }}" - debug: - msg: 'Failure is expected ({{ secret_wrong_cred }})' - register: test_wrong_cred - ignore_errors: true - - - name: 'Failure expected when unauthorized secret is read' - vars: - secret_unauthorized: "{{ lookup('community.general.hashi_vault', conn_params ~ 'secret=' ~ vault_kv2_path ~ '/secret3 auth_method=jwt jwt=' ~ jwt ~ ' role_id=' ~ role_id) }}" - debug: - msg: 'Failure is expected ({{ secret_unauthorized }})' - register: test_unauthorized - ignore_errors: true - - - name: 'Failure expected when non-existent secret is read' - vars: - secret_inexistent: "{{ lookup('community.general.hashi_vault', conn_params ~ 'secret=' ~ vault_kv2_path ~ '/non_existent_secret4 auth_method=jwt jwt=' ~ jwt ~ ' role_id=' ~ role_id) }}" - debug: - msg: 'Failure is expected ({{ secret_inexistent }})' - register: test_inexistent - ignore_errors: true - - - name: 'Check expected failures' - assert: - msg: "an expected failure didn't occur" - that: - - test_wrong_cred is failed - - test_unauthorized is failed - - test_inexistent is failed diff --git a/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/tasks/main.yml b/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/tasks/main.yml deleted file mode 100644 index 9d0eee1885..0000000000 --- a/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/tasks/main.yml +++ /dev/null @@ -1,188 +0,0 @@ ---- -#################################################################### -# WARNING: These are designed specifically for Ansible tests # -# and should not be used as examples of how to write Ansible roles # -#################################################################### - -- name: Install Hashi Vault on controlled node and test - vars: - vault_version: '0.11.0' - vault_uri: 'https://ansible-ci-files.s3.amazonaws.com/test/integration/targets/lookup_hashi_vault/vault_{{ vault_version }}_{{ ansible_system | lower }}_{{ vault_arch }}.zip' - vault_cmd: '{{ local_temp_dir }}/vault' - block: - - name: Create a local temporary directory - tempfile: - state: directory - register: tempfile_result - - - set_fact: - local_temp_dir: '{{ tempfile_result.path }}' - - - when: pyopenssl_version.stdout is version('0.15', '>=') - block: - - name: Generate privatekey - community.crypto.openssl_privatekey: - path: '{{ local_temp_dir }}/privatekey.pem' - - - name: Generate CSR - community.crypto.openssl_csr: - path: '{{ local_temp_dir }}/csr.csr' - privatekey_path: '{{ local_temp_dir }}/privatekey.pem' - subject: - commonName: localhost - - - name: Generate selfsigned certificate - community.crypto.openssl_certificate: - path: '{{ local_temp_dir }}/cert.pem' - csr_path: '{{ local_temp_dir }}/csr.csr' - privatekey_path: '{{ local_temp_dir }}/privatekey.pem' - provider: selfsigned - selfsigned_digest: sha256 - register: selfsigned_certificate - - - name: 'Install unzip' - package: - name: unzip - when: ansible_distribution != "MacOSX" # unzip already installed - - - assert: - # Linux: x86_64, FreeBSD: amd64 - that: ansible_architecture in ['i386', 'x86_64', 'amd64'] - - set_fact: - vault_arch: '386' - when: ansible_architecture == 'i386' - - set_fact: - vault_arch: amd64 - when: ansible_architecture in ['x86_64', 'amd64'] - - - name: 'Download vault binary' - unarchive: - src: '{{ vault_uri }}' - dest: '{{ local_temp_dir }}' - remote_src: true - - - environment: - # used by vault command - VAULT_DEV_ROOT_TOKEN_ID: '47542cbc-6bf8-4fba-8eda-02e0a0d29a0a' - block: - - name: 'Create configuration file' - template: - src: vault_config.hcl.j2 - dest: '{{ local_temp_dir }}/vault_config.hcl' - - - name: 'Start vault service' - environment: - VAULT_ADDR: 'http://localhost:8200' - block: - - name: 'Start vault server (dev mode enabled)' - shell: 'nohup {{ vault_cmd }} server -dev -config {{ local_temp_dir }}/vault_config.hcl /dev/null 2>&1 &' - - - name: 'Create generic secrets engine' - command: '{{ vault_cmd }} secrets enable -path=gen generic' - - - name: 'Create KV v1 secrets engine' - command: '{{ vault_cmd }} secrets enable -path=kv1 -version=1 kv' - - - name: 'Create KV v2 secrets engine' - command: '{{ vault_cmd }} secrets enable -path=kv2 -version=2 kv' - - - name: 'Create a test policy' - command: - cmd: '{{ vault_cmd }} policy write test-policy -' - stdin: | - path "{{ vault_gen_path }}/secret1" { - capabilities = ["read"] - } - path "{{ vault_gen_path }}/secret2" { - capabilities = ["read", "update"] - } - path "{{ vault_gen_path }}/secret3" { - capabilities = ["deny"] - } - path "{{ vault_kv1_path }}/secret1" { - capabilities = ["read"] - } - path "{{ vault_kv1_path }}/secret2" { - capabilities = ["read", "update"] - } - path "{{ vault_kv1_path }}/secret3" { - capabilities = ["deny"] - } - path "{{ vault_kv2_path }}/secret1" { - capabilities = ["read"] - } - path "{{ vault_kv2_path }}/secret2" { - capabilities = ["read", "update"] - } - path "{{ vault_kv2_path }}/secret3" { - capabilities = ["deny"] - } - path "{{ vault_kv2_multi_path }}/secrets" { - capabilities = ["read"] - } - path "{{ vault_kv2_path }}/secret4" { - capabilities = ["read", "update"] - } - - - name: 'Create generic secrets' - command: '{{ vault_cmd }} write {{ vault_gen_path }}/secret{{ item }} value=foo{{ item }}' - loop: [1, 2, 3] - - - name: 'Create KV v1 secrets' - command: '{{ vault_cmd }} kv put {{ vault_kv1_path }}/secret{{ item }} value=foo{{ item }}' - loop: [1, 2, 3] - - - name: 'Create KV v2 secrets' - command: '{{ vault_cmd }} kv put {{ vault_kv2_path | regex_replace("/data") }}/secret{{ item }} value=foo{{ item }}' - loop: [1, 2, 3, 4] - - - name: 'Update KV v2 secret4 with new value to create version' - command: '{{ vault_cmd }} kv put {{ vault_kv2_path | regex_replace("/data") }}/secret4 value=foo5' - - - name: 'Create multiple KV v2 secrets under one path' - command: '{{ vault_cmd }} kv put {{ vault_kv2_multi_path | regex_replace("/data") }}/secrets value1=foo1 value2=foo2 value3=foo3' - - - name: setup approle auth - import_tasks: approle_setup.yml - when: ansible_distribution != 'RedHat' or ansible_distribution_major_version is version('7', '>') - - - name: setup approle secret_id_less auth - import_tasks: approle_secret_id_less_setup.yml - when: ansible_distribution != 'RedHat' or ansible_distribution_major_version is version('7', '>') - - - name: setup token auth - import_tasks: token_setup.yml - - - name: setup jwt auth - import_tasks: jwt_setup.yml - when: ansible_distribution != 'RedHat' or ansible_distribution_major_version is version('7', '>') - - - import_tasks: tests.yml - vars: - auth_type: approle - when: ansible_distribution != 'RedHat' or ansible_distribution_major_version is version('7', '>') - - - import_tasks: tests.yml - vars: - auth_type: approle_secret_id_less - when: ansible_distribution != 'RedHat' or ansible_distribution_major_version is version('7', '>') - - - import_tasks: tests.yml - vars: - auth_type: token - - - import_tasks: tests.yml - vars: - auth_type: jwt - when: ansible_distribution != 'RedHat' or ansible_distribution_major_version is version('7', '>') - - always: - - name: 'Kill vault process' - shell: "kill $(cat {{ local_temp_dir }}/vault.pid)" - ignore_errors: true - - always: - - name: 'Delete temp dir' - file: - path: '{{ local_temp_dir }}' - state: absent diff --git a/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/tasks/tests.yml b/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/tasks/tests.yml deleted file mode 100644 index 53ec682719..0000000000 --- a/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/tasks/tests.yml +++ /dev/null @@ -1,76 +0,0 @@ -- name: 'test {{ auth_type }} auth without SSL (lookup parameters)' - include_tasks: '{{ auth_type }}_test.yml' - vars: - conn_params: 'url=http://localhost:8200 ' - -- name: 'test {{ auth_type }} auth without SSL (environment variable)' - include_tasks: '{{ auth_type }}_test.yml' - args: - apply: - vars: - conn_params: '' - environment: - VAULT_ADDR: 'http://localhost:8200' - -- when: pyopenssl_version.stdout is version('0.15', '>=') - block: - - name: 'test {{ auth_type }} auth with certs (validation enabled, lookup parameters)' - include_tasks: '{{ auth_type }}_test.yml' - vars: - conn_params: 'url=https://localhost:8201 ca_cert={{ local_temp_dir }}/cert.pem validate_certs=True ' - - - name: 'test {{ auth_type }} auth with certs (validation enabled, environment variables)' - include_tasks: '{{ auth_type }}_test.yml' - args: - apply: - vars: - conn_params: '' - environment: - VAULT_ADDR: 'https://localhost:8201' - VAULT_CACERT: '{{ local_temp_dir }}/cert.pem' - - - name: 'test {{ auth_type }} auth with certs (validation disabled, lookup parameters)' - include_tasks: '{{ auth_type }}_test.yml' - vars: - conn_params: 'url=https://localhost:8201 validate_certs=False ' - - - name: 'test {{ auth_type }} auth with certs (validation using env VAR, lookup parameters)' - include_tasks: '{{ auth_type }}_test.yml' - args: - apply: - vars: - conn_params: '' - environment: - VAULT_ADDR: 'https://localhost:8201' - VAULT_SKIP_VERIFY: 1 - - - name: 'test {{ auth_type }} auth with certs (validation using env VAR (True), lookup parameters)' - include_tasks: '{{ auth_type }}_test.yml' - args: - apply: - vars: - conn_params: '' - environment: - VAULT_ADDR: 'https://localhost:8201' - VAULT_SKIP_VERIFY: True - - - name: 'test {{ auth_type }} auth with certs (validation using env VAR (y), lookup parameters)' - include_tasks: '{{ auth_type }}_test.yml' - args: - apply: - vars: - conn_params: '' - environment: - VAULT_ADDR: 'https://localhost:8201' - VAULT_SKIP_VERIFY: y - - - name: 'test {{ auth_type }} auth with certs (precedence of validate_certs over env VAR, lookup parameters)' - include_tasks: '{{ auth_type }}_test.yml' - args: - apply: - vars: - conn_params: 'validate_certs=False ' - environment: - VAULT_ADDR: 'https://localhost:8201' - VAULT_SKIP_VERIFY: False - \ No newline at end of file diff --git a/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/tasks/token_setup.yml b/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/tasks/token_setup.yml deleted file mode 100644 index d5ce280346..0000000000 --- a/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/tasks/token_setup.yml +++ /dev/null @@ -1,3 +0,0 @@ -- name: 'Create a test credentials (token)' - command: '{{ vault_cmd }} token create -policy test-policy -field token' - register: user_token_cmd diff --git a/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/tasks/token_test.yml b/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/tasks/token_test.yml deleted file mode 100644 index 8ad9c6660c..0000000000 --- a/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/tasks/token_test.yml +++ /dev/null @@ -1,88 +0,0 @@ -- vars: - user_token: '{{ user_token_cmd.stdout }}' - block: - - name: 'Fetch secrets using "hashi_vault" lookup' - set_fact: - gen_secret1: "{{ lookup('community.general.hashi_vault', conn_params ~ 'secret=' ~ vault_gen_path ~ '/secret1 auth_method=token token=' ~ user_token) }}" - gen_secret2: "{{ lookup('community.general.hashi_vault', conn_params ~ 'secret=' ~ vault_gen_path ~ '/secret2 token=' ~ user_token) }}" - kv1_secret1: "{{ lookup('community.general.hashi_vault', conn_params ~ 'secret=' ~ vault_kv1_path ~ '/secret1 auth_method=token token=' ~ user_token) }}" - kv1_secret2: "{{ lookup('community.general.hashi_vault', conn_params ~ 'secret=' ~ vault_kv1_path ~ '/secret2 token=' ~ user_token) }}" - kv2_secret1: "{{ lookup('community.general.hashi_vault', conn_params ~ 'secret=' ~ vault_kv2_path ~ '/secret1 auth_method=token token=' ~ user_token) }}" - kv2_secret2: "{{ lookup('community.general.hashi_vault', conn_params ~ 'secret=' ~ vault_kv2_path ~ '/secret2 token=' ~ user_token) }}" - kv2_secret4: "{{ lookup('community.general.hashi_vault', conn_params ~ 'secret=' ~ vault_kv2_path ~ '/secret4?version=2 token=' ~ user_token) }}" - kv2_secret2_as_raw: "{{ lookup('community.general.hashi_vault', vault_kv2_path ~ '/secret2 ' ~ conn_params, auth_method='token', token=user_token, return_format='raw') }}" - kv2_secrets_as_dict: "{{ lookup('community.general.hashi_vault', vault_kv2_multi_path ~ '/secrets ' ~ conn_params, auth_method='token', token=user_token) }}" - kv2_secrets_as_values: "{{ query('community.general.hashi_vault', vault_kv2_multi_path ~ '/secrets ' ~ conn_params, auth_method='token', token=user_token, return_format='values') }}" - - - name: 'Check secret generic values' - fail: - msg: 'unexpected secret values' - when: gen_secret1['value'] != 'foo1' or gen_secret2['value'] != 'foo2' - - - name: 'Check secret kv1 values' - fail: - msg: 'unexpected secret values' - when: kv1_secret1['value'] != 'foo1' or kv1_secret2['value'] != 'foo2' - - - name: 'Check secret kv2 values' - fail: - msg: 'unexpected secret values' - when: kv2_secret1['value'] != 'foo1' or kv2_secret2['value'] != 'foo2' or kv2_secret4['value'] != 'foo5' - - - name: 'Check kv2 secret raw return value' - fail: - msg: - when: >- - 'data' not in kv2_secret2_as_raw - or 'data' not in kv2_secret2_as_raw['data'] - or 'metadata' not in kv2_secret2_as_raw['data'] - - - name: "Check multiple secrets as dict" - fail: - msg: 'Return value was not dict or items do not match.' - when: (kv2_secrets_as_dict | type_debug != 'dict') or (kv2_secrets_as_dict['value{{ item }}'] != 'foo{{ item }}') - loop: [1, 2, 3] - - - name: "Check multiple secrets as values" - fail: - msg: 'Return value was not list or items do not match.' - when: (kv2_secrets_as_values | type_debug != 'list') or ('foo{{ item }}' not in kv2_secrets_as_values) - loop: [1, 2, 3] - - - name: "Check multiple secrets as dict" - fail: - msg: 'Return value was not dict or items do not match.' - when: (kv2_secrets_as_dict | type_debug != 'dict') or (kv2_secrets_as_dict['value{{ item }}'] != 'foo{{ item }}') - loop: [1, 2, 3] - - - name: 'Failure expected when erroneous credentials are used' - vars: - secret_wrong_cred: "{{ lookup('community.general.hashi_vault', conn_params ~ 'secret=' ~ vault_kv2_path ~ '/secret2 auth_method=token token=wrong_token') }}" - debug: - msg: 'Failure is expected ({{ secret_wrong_cred }})' - register: test_wrong_cred - ignore_errors: true - - - name: 'Failure expected when unauthorized secret is read' - vars: - secret_unauthorized: "{{ lookup('community.general.hashi_vault', conn_params ~ 'secret=' ~ vault_kv2_path ~ '/secret3 token=' ~ user_token) }}" - debug: - msg: 'Failure is expected ({{ secret_unauthorized }})' - register: test_unauthorized - ignore_errors: true - - - name: 'Failure expected when inexistent secret is read' - vars: - secret_inexistent: "{{ lookup('community.general.hashi_vault', conn_params ~ 'secret=' ~ vault_kv2_path ~ '/non_existent_secret4 token=' ~ user_token) }}" - debug: - msg: 'Failure is expected ({{ secret_inexistent }})' - register: test_inexistent - ignore_errors: true - - - name: 'Check expected failures' - assert: - msg: "an expected failure didn't occur" - that: - - test_wrong_cred is failed - - test_unauthorized is failed - - test_inexistent is failed diff --git a/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/templates/vault_config.hcl.j2 b/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/templates/vault_config.hcl.j2 deleted file mode 100644 index effc90ba90..0000000000 --- a/tests/integration/targets/lookup_hashi_vault/lookup_hashi_vault/templates/vault_config.hcl.j2 +++ /dev/null @@ -1,10 +0,0 @@ -# {{ ansible_managed }} -pid_file = "{{ local_temp_dir }}/vault.pid" -{% if pyopenssl_version.stdout is version('0.15', '>=') %} -listener "tcp" { - tls_key_file = "{{ local_temp_dir }}/privatekey.pem" - tls_cert_file = "{{ local_temp_dir }}/cert.pem" - tls_disable = false - address = "localhost:8201" -} -{% endif %} diff --git a/tests/integration/targets/lookup_hashi_vault/playbooks/install_dependencies.yml b/tests/integration/targets/lookup_hashi_vault/playbooks/install_dependencies.yml deleted file mode 100644 index d4c7e9a6be..0000000000 --- a/tests/integration/targets/lookup_hashi_vault/playbooks/install_dependencies.yml +++ /dev/null @@ -1,19 +0,0 @@ -- hosts: localhost - tasks: - - name: Install openssl - import_role: - name: setup_openssl - - - name: "RedHat <= 7, select last version compatible with request 2.6.0 (this version doesn't support approle or jwt auth)" - set_fact: - hvac_package: 'hvac==0.2.5' - when: ansible_distribution == 'RedHat' and ansible_distribution_major_version is version('7', '<=') - - - name: 'CentOS < 7, select last version compatible with Python 2.6' - set_fact: - hvac_package: 'hvac==0.5.0' - when: ansible_distribution == 'CentOS' and ansible_distribution_major_version is version('7', '<') - - - name: 'Install hvac Python package' - pip: - name: "{{ hvac_package|default('hvac') }}" diff --git a/tests/integration/targets/lookup_hashi_vault/playbooks/test_lookup_hashi_vault.yml b/tests/integration/targets/lookup_hashi_vault/playbooks/test_lookup_hashi_vault.yml deleted file mode 100644 index 8d3f320103..0000000000 --- a/tests/integration/targets/lookup_hashi_vault/playbooks/test_lookup_hashi_vault.yml +++ /dev/null @@ -1,9 +0,0 @@ -- hosts: localhost - tasks: - - name: register pyOpenSSL version - command: "{{ ansible_python.executable }} -c 'import OpenSSL; print(OpenSSL.__version__)'" - register: pyopenssl_version - - - name: Test lookup hashi_vault - import_role: - name: lookup_hashi_vault/lookup_hashi_vault diff --git a/tests/integration/targets/lookup_hashi_vault/runme.sh b/tests/integration/targets/lookup_hashi_vault/runme.sh deleted file mode 100755 index e5e0df347f..0000000000 --- a/tests/integration/targets/lookup_hashi_vault/runme.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env bash - -set -eux - -# First install pyOpenSSL, then test lookup in a second playbook in order to -# workaround this error which occurs on OS X 10.11 only: -# -# TASK [lookup_hashi_vault : test token auth with certs (validation enabled, lookup parameters)] *** -# included: lookup_hashi_vault/tasks/token_test.yml for testhost -# -# TASK [lookup_hashi_vault : Fetch secrets using "hashi_vault" lookup] *** -# From cffi callback : -# Traceback (most recent call last): -# File "/usr/local/lib/python2.7/site-packages/OpenSSL/SSL.py", line 309, in wrapper -# _lib.X509_up_ref(x509) -# AttributeError: 'module' object has no attribute 'X509_up_ref' -# fatal: [testhost]: FAILED! => { "msg": "An unhandled exception occurred while running the lookup plugin 'hashi_vault'. Error was a , original message: HTTPSConnectionPool(host='localhost', port=8201): Max retries exceeded with url: /v1/auth/token/lookup-self (Caused by SSLError(SSLError(\"bad handshake: Error([('SSL routines', 'ssl3_get_server_certificate', 'certificate verify failed')],)\",),))"} - -ANSIBLE_ROLES_PATH=../ \ - ansible-playbook playbooks/install_dependencies.yml -v "$@" - -ANSIBLE_ROLES_PATH=../ \ - ansible-playbook playbooks/test_lookup_hashi_vault.yml -v "$@"