1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2024-09-14 20:13:21 +02:00

onepassword - Get first found config file (#4640)

* Get first found configuration file

There are three valid places to get the configuration.

https://developer.1password.com/docs/cli/about-biometric-unlock#remove-old-account-information

* Use common config class

* Add changelog fragment

* Explicitly use new style classes for Python 2.7 compatibility

This shouldn’t matter for lookups, but does matter for module_utils
and modules since Python 2.7 is still supported on the managed node.

* Update changelogs/fragments/4065-onepassword-config.yml

Co-authored-by: Felix Fontein <felix@fontein.de>
This commit is contained in:
Sam Doran 2022-05-09 01:24:35 -04:00 committed by GitHub
parent bca7f09b71
commit 9e1af2d1bc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 44 additions and 7 deletions

View file

@ -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).

View file

@ -45,8 +45,8 @@ DOCUMENTATION = '''
description: Vault containing the item to retrieve (case-insensitive). If absent will search all vaults. description: Vault containing the item to retrieve (case-insensitive). If absent will search all vaults.
notes: notes:
- This lookup will use an existing 1Password session if one exists. If not, and you have already - 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. performed an initial sign in (meaning C(~/.op/config), C(~/.config/op/config) or C(~/.config/.op/config) exists), then only the
You may optionally specify C(subdomain) in this scenario, otherwise the last used subdomain will be used by C(op). 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). - 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 - 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 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.errors import AnsibleLookupError
from ansible.module_utils.common.text.converters import to_bytes, to_text 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'): def __init__(self, path='op'):
self.cli_path = path self.cli_path = path
self.config_file_path = os.path.expanduser('~/.op/config')
self.logged_in = False self.logged_in = False
self.token = None self.token = None
self.subdomain = None self.subdomain = None
@ -119,9 +119,11 @@ class OnePass(object):
self.secret_key = None self.secret_key = None
self.master_password = None self.master_password = None
self._config = OnePasswordConfig()
def get_token(self): def get_token(self):
# If the config file exists, assume an initial signin has taken place and try basic sign in # 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: if not self.master_password:
raise AnsibleLookupError('Unable to sign in to 1Password. master_password is required.') raise AnsibleLookupError('Unable to sign in to 1Password. master_password is required.')
@ -281,4 +283,5 @@ class LookupModule(LookupBase):
values = [] values = []
for term in terms: for term in terms:
values.append(op.get_field(term, field, section, vault)) values.append(op.get_field(term, field, section, vault))
return values return values

View file

@ -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

View file

@ -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.common.text.converters import to_bytes, to_native
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
from ansible_collections.community.general.plugins.module_utils.onepassword import OnePasswordConfig
class AnsibleModuleError(Exception): class AnsibleModuleError(Exception):
def __init__(self, results): def __init__(self, results):
@ -179,7 +181,6 @@ class OnePasswordInfo(object):
def __init__(self): def __init__(self):
self.cli_path = module.params.get('cli_path') self.cli_path = module.params.get('cli_path')
self.config_file_path = '~/.op/config'
self.auto_login = module.params.get('auto_login') self.auto_login = module.params.get('auto_login')
self.logged_in = False self.logged_in = False
self.token = None self.token = None
@ -187,6 +188,8 @@ class OnePasswordInfo(object):
terms = module.params.get('search_terms') terms = module.params.get('search_terms')
self.terms = self.parse_search_terms(terms) self.terms = self.parse_search_terms(terms)
self._config = OnePasswordConfig()
def _run(self, args, expected_rc=0, command_input=None, ignore_errors=False): def _run(self, args, expected_rc=0, command_input=None, ignore_errors=False):
if self.token: if self.token:
# Adds the session token to all commands if we're logged in. # Adds the session token to all commands if we're logged in.
@ -299,7 +302,7 @@ class OnePasswordInfo(object):
def get_token(self): def get_token(self):
# If the config file exists, assume an initial signin has taken place and try basic sign in # 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: if self.auto_login is not None: