mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
Add option missing to passwordstore lookup (#2500)
Add ability to ignore error on missing pass file to allow processing the output further via another filters (mainly the default filter) without updating the pass file itself. It also contains the option to create the pass file, like the option create=true does. Finally, it also allows to issue a warning only, if the pass file is not found.
This commit is contained in:
parent
da7e4e1dc2
commit
350380ba8c
3 changed files with 85 additions and 5 deletions
|
@ -0,0 +1,3 @@
|
|||
minor_changes:
|
||||
- passwordstore lookup - add option ``missing`` to choose what to do if the password file is missing
|
||||
(https://github.com/ansible-collections/community.general/pull/2500).
|
|
@ -25,9 +25,9 @@ DOCUMENTATION = '''
|
|||
env:
|
||||
- name: PASSWORD_STORE_DIR
|
||||
create:
|
||||
description: Create the password if it does not already exist.
|
||||
description: Create the password if it does not already exist. Takes precedence over C(missing).
|
||||
type: bool
|
||||
default: 'no'
|
||||
default: false
|
||||
overwrite:
|
||||
description: Overwrite the password if it does already exist.
|
||||
type: bool
|
||||
|
@ -60,6 +60,22 @@ DOCUMENTATION = '''
|
|||
description: use alphanumeric characters.
|
||||
type: bool
|
||||
default: 'no'
|
||||
missing:
|
||||
description:
|
||||
- List of preference about what to do if the password file is missing.
|
||||
- If I(create=true), the value for this option is ignored and assumed to be C(create).
|
||||
- If set to C(error), the lookup will error out if the passname does not exist.
|
||||
- If set to C(create), the passname will be created with the provided length I(length) if it does not exist.
|
||||
- If set to C(empty) or C(warn), will return a C(none) in case the passname does not exist.
|
||||
When using C(lookup) and not C(query), this will be translated to an empty string.
|
||||
version_added: 3.1.0
|
||||
type: str
|
||||
default: error
|
||||
choices:
|
||||
- error
|
||||
- warn
|
||||
- empty
|
||||
- create
|
||||
'''
|
||||
EXAMPLES = """
|
||||
# Debug is used for examples, BAD IDEA to show passwords on screen
|
||||
|
@ -67,12 +83,28 @@ EXAMPLES = """
|
|||
ansible.builtin.debug:
|
||||
msg: "{{ lookup('community.general.passwordstore', 'example/test')}}"
|
||||
|
||||
- name: Basic lookup. Warns if example/test does not exist and returns empty string
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ lookup('community.general.passwordstore', 'example/test missing=warn')}}"
|
||||
|
||||
- name: Create pass with random 16 character password. If password exists just give the password
|
||||
ansible.builtin.debug:
|
||||
var: mypassword
|
||||
vars:
|
||||
mypassword: "{{ lookup('community.general.passwordstore', 'example/test create=true')}}"
|
||||
|
||||
- name: Create pass with random 16 character password. If password exists just give the password
|
||||
ansible.builtin.debug:
|
||||
var: mypassword
|
||||
vars:
|
||||
mypassword: "{{ lookup('community.general.passwordstore', 'example/test missing=create')}}"
|
||||
|
||||
- name: Prints 'abc' if example/test does not exist, just give the password otherwise
|
||||
ansible.builtin.debug:
|
||||
var: mypassword
|
||||
vars:
|
||||
mypassword: "{{ lookup('community.general.passwordstore', 'example/test missing=empty') | default('abc', true) }}"
|
||||
|
||||
- name: Different size password
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ lookup('community.general.passwordstore', 'example/test create=true length=42')}}"
|
||||
|
@ -111,10 +143,13 @@ import yaml
|
|||
from distutils import util
|
||||
from ansible.errors import AnsibleError, AnsibleAssertionError
|
||||
from ansible.module_utils._text import to_bytes, to_native, to_text
|
||||
from ansible.utils.display import Display
|
||||
from ansible.utils.encrypt import random_password
|
||||
from ansible.plugins.lookup import LookupBase
|
||||
from ansible import constants as C
|
||||
|
||||
display = Display()
|
||||
|
||||
|
||||
# backhacked check_output with input for python 2.7
|
||||
# http://stackoverflow.com/questions/10103551/passing-data-to-subprocess-check-output
|
||||
|
@ -178,12 +213,17 @@ class LookupModule(LookupBase):
|
|||
self.paramvals[key] = util.strtobool(self.paramvals[key])
|
||||
except (ValueError, AssertionError) as e:
|
||||
raise AnsibleError(e)
|
||||
if self.paramvals['missing'] not in ['error', 'warn', 'create', 'empty']:
|
||||
raise AnsibleError("{0} is not a valid option for missing".format(self.paramvals['missing']))
|
||||
if not isinstance(self.paramvals['length'], int):
|
||||
if self.paramvals['length'].isdigit():
|
||||
self.paramvals['length'] = int(self.paramvals['length'])
|
||||
else:
|
||||
raise AnsibleError("{0} is not a correct value for length".format(self.paramvals['length']))
|
||||
|
||||
if self.paramvals['create']:
|
||||
self.paramvals['missing'] = 'create'
|
||||
|
||||
# Collect pass environment variables from the plugin's parameters.
|
||||
self.env = os.environ.copy()
|
||||
|
||||
|
@ -224,9 +264,11 @@ class LookupModule(LookupBase):
|
|||
if e.returncode != 0 and 'not in the password store' in e.output:
|
||||
# if pass returns 1 and return string contains 'is not in the password store.'
|
||||
# We need to determine if this is valid or Error.
|
||||
if not self.paramvals['create']:
|
||||
raise AnsibleError('passname: {0} not found, use create=True'.format(self.passname))
|
||||
if self.paramvals['missing'] == 'error':
|
||||
raise AnsibleError('passwordstore: passname {0} not found and missing=error is set'.format(self.passname))
|
||||
else:
|
||||
if self.paramvals['missing'] == 'warn':
|
||||
display.warning('passwordstore: passname {0} not found'.format(self.passname))
|
||||
return False
|
||||
else:
|
||||
raise AnsibleError(e)
|
||||
|
@ -294,6 +336,7 @@ class LookupModule(LookupBase):
|
|||
'userpass': '',
|
||||
'length': 16,
|
||||
'backup': False,
|
||||
'missing': 'error',
|
||||
}
|
||||
|
||||
for term in terms:
|
||||
|
@ -304,6 +347,9 @@ class LookupModule(LookupBase):
|
|||
else:
|
||||
result.append(self.get_passresult())
|
||||
else: # password does not exist
|
||||
if self.paramvals['create']:
|
||||
if self.paramvals['missing'] == 'create':
|
||||
result.append(self.generate_password())
|
||||
else:
|
||||
result.append(None)
|
||||
|
||||
return result
|
||||
|
|
|
@ -61,6 +61,37 @@
|
|||
that:
|
||||
- readpass == newpass
|
||||
|
||||
- name: Create a password using missing=create
|
||||
set_fact:
|
||||
newpass: "{{ lookup('community.general.passwordstore', 'test-missing-create missing=create length=8') }}"
|
||||
|
||||
- name: Fetch password from an existing file
|
||||
set_fact:
|
||||
readpass: "{{ lookup('community.general.passwordstore', 'test-missing-create') }}"
|
||||
|
||||
- name: Verify password
|
||||
assert:
|
||||
that:
|
||||
- readpass == newpass
|
||||
|
||||
- name: Fetch password from existing file using missing=empty
|
||||
set_fact:
|
||||
readpass: "{{ lookup('community.general.passwordstore', 'test-missing-create missing=empty') }}"
|
||||
|
||||
- name: Verify password
|
||||
assert:
|
||||
that:
|
||||
- readpass == newpass
|
||||
|
||||
- name: Fetch password from non-existing file using missing=empty
|
||||
set_fact:
|
||||
readpass: "{{ query('community.general.passwordstore', 'test-missing-pass missing=empty') }}"
|
||||
|
||||
- name: Verify password
|
||||
assert:
|
||||
that:
|
||||
- readpass == [ none ]
|
||||
|
||||
# As inserting multiline passwords on the commandline would require something
|
||||
# like expect, simply create it by using default gpg on a file with the correct
|
||||
# structure.
|
||||
|
|
Loading…
Reference in a new issue