diff --git a/changelogs/fragments/4065-onepassword-config.yml b/changelogs/fragments/4065-onepassword-config.yml new file mode 100644 index 00000000000..9d58a0e57f6 --- /dev/null +++ b/changelogs/fragments/4065-onepassword-config.yml @@ -0,0 +1,2 @@ +bugfixes: + - onepassword - search all valid configuration locations and use the first found (https://github.com/ansible-collections/community.general/pull/4640). diff --git a/plugins/lookup/onepassword.py b/plugins/lookup/onepassword.py index 9f97a90e71a..e0be0cd27e2 100644 --- a/plugins/lookup/onepassword.py +++ b/plugins/lookup/onepassword.py @@ -45,8 +45,8 @@ description: Vault containing the item to retrieve (case-insensitive). If absent will search all vaults. notes: - This lookup will use an existing 1Password session if one exists. If not, and you have already - performed an initial sign in (meaning C(~/.op/config exists)), then only the C(master_password) is required. - You may optionally specify C(subdomain) in this scenario, otherwise the last used subdomain will be used by C(op). + performed an initial sign in (meaning C(~/.op/config), C(~/.config/op/config) or C(~/.config/.op/config) exists), then only the + C(master_password) is required. You may optionally specify C(subdomain) in this scenario, otherwise the last used subdomain will be used by C(op). - This lookup can perform an initial login by providing C(subdomain), C(username), C(secret_key), and C(master_password). - Due to the B(very) sensitive nature of these credentials, it is B(highly) recommended that you only pass in the minimal credentials needed at any given time. Also, store these credentials in an Ansible Vault using a key that is equal to or greater in strength @@ -105,12 +105,12 @@ from ansible.errors import AnsibleLookupError from ansible.module_utils.common.text.converters import to_bytes, to_text +from ansible_collections.community.general.plugins.module_utils.onepassword import OnePasswordConfig -class OnePass(object): +class OnePass(object): def __init__(self, path='op'): self.cli_path = path - self.config_file_path = os.path.expanduser('~/.op/config') self.logged_in = False self.token = None self.subdomain = None @@ -119,9 +119,11 @@ def __init__(self, path='op'): self.secret_key = None self.master_password = None + self._config = OnePasswordConfig() + def get_token(self): # If the config file exists, assume an initial signin has taken place and try basic sign in - if os.path.isfile(self.config_file_path): + if os.path.isfile(self._config.config_file_path): if not self.master_password: raise AnsibleLookupError('Unable to sign in to 1Password. master_password is required.') @@ -281,4 +283,5 @@ def run(self, terms, variables=None, **kwargs): values = [] for term in terms: values.append(op.get_field(term, field, section, vault)) + return values diff --git a/plugins/module_utils/onepassword.py b/plugins/module_utils/onepassword.py new file mode 100644 index 00000000000..3a86e22e16e --- /dev/null +++ b/plugins/module_utils/onepassword.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +# Simplified BSD License (see licenses/simplified_bsd.txt or https://opensource.org/licenses/BSD-2-Clause) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type + +import os + + +class OnePasswordConfig(object): + _config_file_paths = ( + "~/.op/config", + "~/.config/op/config", + "~/.config/.op/config", + ) + + def __init__(self): + self._config_file_path = "" + + @property + def config_file_path(self): + if self._config_file_path: + return self._config_file_path + + for path in self._config_file_paths: + realpath = os.path.expanduser(path) + if os.path.exists(realpath): + self._config_file_path = realpath + return self._config_file_path diff --git a/plugins/modules/identity/onepassword_info.py b/plugins/modules/identity/onepassword_info.py index 7170a33aed8..66210923033 100644 --- a/plugins/modules/identity/onepassword_info.py +++ b/plugins/modules/identity/onepassword_info.py @@ -166,6 +166,8 @@ from ansible.module_utils.common.text.converters import to_bytes, to_native from ansible.module_utils.basic import AnsibleModule +from ansible_collections.community.general.plugins.module_utils.onepassword import OnePasswordConfig + class AnsibleModuleError(Exception): def __init__(self, results): @@ -179,7 +181,6 @@ class OnePasswordInfo(object): def __init__(self): self.cli_path = module.params.get('cli_path') - self.config_file_path = '~/.op/config' self.auto_login = module.params.get('auto_login') self.logged_in = False self.token = None @@ -187,6 +188,8 @@ def __init__(self): terms = module.params.get('search_terms') self.terms = self.parse_search_terms(terms) + self._config = OnePasswordConfig() + def _run(self, args, expected_rc=0, command_input=None, ignore_errors=False): if self.token: # Adds the session token to all commands if we're logged in. @@ -299,7 +302,7 @@ def full_login(self): def get_token(self): # If the config file exists, assume an initial signin has taken place and try basic sign in - if os.path.isfile(self.config_file_path): + if os.path.isfile(self._config.config_file_path): if self.auto_login is not None: