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:
parent
bca7f09b71
commit
9e1af2d1bc
4 changed files with 44 additions and 7 deletions
2
changelogs/fragments/4065-onepassword-config.yml
Normal file
2
changelogs/fragments/4065-onepassword-config.yml
Normal 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).
|
|
@ -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
|
||||||
|
|
29
plugins/module_utils/onepassword.py
Normal file
29
plugins/module_utils/onepassword.py
Normal 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
|
|
@ -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:
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue