diff --git a/changelogs/fragments/4065-onepassword-config.yml b/changelogs/fragments/4065-onepassword-config.yml new file mode 100644 index 0000000000..9d58a0e57f --- /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 9f97a90e71..e0be0cd27e 100644 --- a/plugins/lookup/onepassword.py +++ b/plugins/lookup/onepassword.py @@ -45,8 +45,8 @@ DOCUMENTATION = ''' 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.plugins.lookup import LookupBase 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): - 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 @@ class OnePass(object): 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 @@ class LookupModule(LookupBase): 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 0000000000..3a86e22e16 --- /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 7170a33aed..6621092303 100644 --- a/plugins/modules/identity/onepassword_info.py +++ b/plugins/modules/identity/onepassword_info.py @@ -166,6 +166,8 @@ from subprocess import Popen, PIPE 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 @@ class OnePasswordInfo(object): 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 @@ class OnePasswordInfo(object): 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: