mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
passwordstore lookup: allow to pass options as lookup options (#5444)
* Allow to pass options as lookup options. * Adjust tests.
This commit is contained in:
parent
5cb9a9e4f0
commit
faf4ec7fa6
4 changed files with 53 additions and 43 deletions
2
changelogs/fragments/5444-passwordstore-options.yml
Normal file
2
changelogs/fragments/5444-passwordstore-options.yml
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
minor_changes:
|
||||||
|
- "passwordstore lookup plugin - allow options to be passed lookup options instead of being part of the term strings (https://github.com/ansible-collections/community.general/pull/5444)."
|
|
@ -21,17 +21,15 @@ DOCUMENTATION = '''
|
||||||
_terms:
|
_terms:
|
||||||
description: query key.
|
description: query key.
|
||||||
required: true
|
required: true
|
||||||
passwordstore:
|
|
||||||
description:
|
|
||||||
- Location of the password store.
|
|
||||||
- 'The value is decided by checking the following in order:'
|
|
||||||
- If set, this value is used.
|
|
||||||
- If C(directory) is set, that value will be used.
|
|
||||||
- If I(backend=pass), then C(~/.password-store) is used.
|
|
||||||
- If I(backend=gopass), then the C(path) field in C(~/.config/gopass/config.yml) is used,
|
|
||||||
falling back to C(~/.local/share/gopass/stores/root) if not defined.
|
|
||||||
directory:
|
directory:
|
||||||
description: The directory of the password store.
|
description:
|
||||||
|
- The directory of the password store.
|
||||||
|
- If I(backend=pass), the default is C(~/.password-store) is used.
|
||||||
|
- If I(backend=gopass), then the default is the C(path) field in C(~/.config/gopass/config.yml),
|
||||||
|
falling back to C(~/.local/share/gopass/stores/root) if C(path) is not defined in the gopass config.
|
||||||
|
type: path
|
||||||
|
vars:
|
||||||
|
- name: passwordstore
|
||||||
env:
|
env:
|
||||||
- name: PASSWORD_STORE_DIR
|
- name: PASSWORD_STORE_DIR
|
||||||
create:
|
create:
|
||||||
|
@ -55,9 +53,11 @@ DOCUMENTATION = '''
|
||||||
default: false
|
default: false
|
||||||
subkey:
|
subkey:
|
||||||
description: Return a specific subkey of the password. When set to C(password), always returns the first line.
|
description: Return a specific subkey of the password. When set to C(password), always returns the first line.
|
||||||
|
type: str
|
||||||
default: password
|
default: password
|
||||||
userpass:
|
userpass:
|
||||||
description: Specify a password to save, instead of a generated one.
|
description: Specify a password to save, instead of a generated one.
|
||||||
|
type: str
|
||||||
length:
|
length:
|
||||||
description: The length of the generated password.
|
description: The length of the generated password.
|
||||||
type: integer
|
type: integer
|
||||||
|
@ -67,7 +67,7 @@ DOCUMENTATION = '''
|
||||||
type: bool
|
type: bool
|
||||||
default: false
|
default: false
|
||||||
nosymbols:
|
nosymbols:
|
||||||
description: use alphanumeric characters.
|
description: Use alphanumeric characters.
|
||||||
type: bool
|
type: bool
|
||||||
default: false
|
default: false
|
||||||
missing:
|
missing:
|
||||||
|
@ -129,6 +129,8 @@ DOCUMENTATION = '''
|
||||||
- pass
|
- pass
|
||||||
- gopass
|
- gopass
|
||||||
version_added: 5.2.0
|
version_added: 5.2.0
|
||||||
|
notes:
|
||||||
|
- The lookup supports passing all options as lookup parameters since community.general 6.0.0.
|
||||||
'''
|
'''
|
||||||
EXAMPLES = """
|
EXAMPLES = """
|
||||||
ansible.cfg: |
|
ansible.cfg: |
|
||||||
|
@ -136,7 +138,7 @@ ansible.cfg: |
|
||||||
lock=readwrite
|
lock=readwrite
|
||||||
locktimeout=45s
|
locktimeout=45s
|
||||||
|
|
||||||
playbook.yml: |
|
tasks.yml: |
|
||||||
---
|
---
|
||||||
|
|
||||||
# Debug is used for examples, BAD IDEA to show passwords on screen
|
# Debug is used for examples, BAD IDEA to show passwords on screen
|
||||||
|
@ -146,45 +148,49 @@ playbook.yml: |
|
||||||
|
|
||||||
- name: Basic lookup. Warns if example/test does not exist and returns empty string
|
- name: Basic lookup. Warns if example/test does not exist and returns empty string
|
||||||
ansible.builtin.debug:
|
ansible.builtin.debug:
|
||||||
msg: "{{ lookup('community.general.passwordstore', 'example/test missing=warn')}}"
|
msg: "{{ lookup('community.general.passwordstore', 'example/test', missing='warn')}}"
|
||||||
|
|
||||||
- name: Create pass with random 16 character password. If password exists just give the password
|
- name: Create pass with random 16 character password. If password exists just give the password
|
||||||
ansible.builtin.debug:
|
ansible.builtin.debug:
|
||||||
var: mypassword
|
var: mypassword
|
||||||
vars:
|
vars:
|
||||||
mypassword: "{{ lookup('community.general.passwordstore', 'example/test create=true')}}"
|
mypassword: "{{ lookup('community.general.passwordstore', 'example/test', create=true)}}"
|
||||||
|
|
||||||
- name: Create pass with random 16 character password. If password exists just give the password
|
- name: Create pass with random 16 character password. If password exists just give the password
|
||||||
ansible.builtin.debug:
|
ansible.builtin.debug:
|
||||||
var: mypassword
|
var: mypassword
|
||||||
vars:
|
vars:
|
||||||
mypassword: "{{ lookup('community.general.passwordstore', 'example/test missing=create')}}"
|
mypassword: "{{ lookup('community.general.passwordstore', 'example/test', missing='create')}}"
|
||||||
|
|
||||||
- name: Prints 'abc' if example/test does not exist, just give the password otherwise
|
- name: Prints 'abc' if example/test does not exist, just give the password otherwise
|
||||||
ansible.builtin.debug:
|
ansible.builtin.debug:
|
||||||
var: mypassword
|
var: mypassword
|
||||||
vars:
|
vars:
|
||||||
mypassword: "{{ lookup('community.general.passwordstore', 'example/test missing=empty') | default('abc', true) }}"
|
mypassword: >-
|
||||||
|
{{ lookup('community.general.passwordstore', 'example/test', missing='empty')
|
||||||
|
| default('abc', true) }}
|
||||||
|
|
||||||
- name: Different size password
|
- name: Different size password
|
||||||
ansible.builtin.debug:
|
ansible.builtin.debug:
|
||||||
msg: "{{ lookup('community.general.passwordstore', 'example/test create=true length=42')}}"
|
msg: "{{ lookup('community.general.passwordstore', 'example/test', create=true, length=42)}}"
|
||||||
|
|
||||||
- name: Create password and overwrite the password if it exists. As a bonus, this module includes the old password inside the pass file
|
- name: >-
|
||||||
|
Create password and overwrite the password if it exists.
|
||||||
|
As a bonus, this module includes the old password inside the pass file
|
||||||
ansible.builtin.debug:
|
ansible.builtin.debug:
|
||||||
msg: "{{ lookup('community.general.passwordstore', 'example/test create=true overwrite=true')}}"
|
msg: "{{ lookup('community.general.passwordstore', 'example/test', create=true, overwrite=true)}}"
|
||||||
|
|
||||||
- name: Create an alphanumeric password
|
- name: Create an alphanumeric password
|
||||||
ansible.builtin.debug:
|
ansible.builtin.debug:
|
||||||
msg: "{{ lookup('community.general.passwordstore', 'example/test create=true nosymbols=true') }}"
|
msg: "{{ lookup('community.general.passwordstore', 'example/test', create=true, nosymbols=true) }}"
|
||||||
|
|
||||||
- name: Return the value for user in the KV pair user, username
|
- name: Return the value for user in the KV pair user, username
|
||||||
ansible.builtin.debug:
|
ansible.builtin.debug:
|
||||||
msg: "{{ lookup('community.general.passwordstore', 'example/test subkey=user')}}"
|
msg: "{{ lookup('community.general.passwordstore', 'example/test', subkey='user')}}"
|
||||||
|
|
||||||
- name: Return the entire password file content
|
- name: Return the entire password file content
|
||||||
ansible.builtin.set_fact:
|
ansible.builtin.set_fact:
|
||||||
passfilecontent: "{{ lookup('community.general.passwordstore', 'example/test returnall=true')}}"
|
passfilecontent: "{{ lookup('community.general.passwordstore', 'example/test', returnall=true)}}"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
RETURN = """
|
RETURN = """
|
||||||
|
@ -320,7 +326,7 @@ class LookupModule(LookupBase):
|
||||||
raise AnsibleError('Passwordstore directory \'{0}\' does not exist'.format(self.paramvals['directory']))
|
raise AnsibleError('Passwordstore directory \'{0}\' does not exist'.format(self.paramvals['directory']))
|
||||||
|
|
||||||
# Set PASSWORD_STORE_UMASK if umask is set
|
# Set PASSWORD_STORE_UMASK if umask is set
|
||||||
if 'umask' in self.paramvals:
|
if self.paramvals.get('umask') is not None:
|
||||||
if len(self.paramvals['umask']) != 3:
|
if len(self.paramvals['umask']) != 3:
|
||||||
raise AnsibleError('Passwordstore umask must have a length of 3.')
|
raise AnsibleError('Passwordstore umask must have a length of 3.')
|
||||||
elif int(self.paramvals['umask'][0]) > 3:
|
elif int(self.paramvals['umask'][0]) > 3:
|
||||||
|
@ -435,8 +441,7 @@ class LookupModule(LookupBase):
|
||||||
unit_to_seconds = {"s": 1, "m": 60, "h": 3600}
|
unit_to_seconds = {"s": 1, "m": 60, "h": 3600}
|
||||||
self.lock_timeout = int(timeout[:-1]) * unit_to_seconds[timeout[-1]]
|
self.lock_timeout = int(timeout[:-1]) * unit_to_seconds[timeout[-1]]
|
||||||
|
|
||||||
directory = variables.get('passwordstore', os.environ.get('PASSWORD_STORE_DIR', None))
|
directory = self.get_option('directory')
|
||||||
|
|
||||||
if directory is None:
|
if directory is None:
|
||||||
if self.backend == 'gopass':
|
if self.backend == 'gopass':
|
||||||
try:
|
try:
|
||||||
|
@ -448,16 +453,17 @@ class LookupModule(LookupBase):
|
||||||
directory = os.path.expanduser('~/.password-store')
|
directory = os.path.expanduser('~/.password-store')
|
||||||
|
|
||||||
self.paramvals = {
|
self.paramvals = {
|
||||||
'subkey': 'password',
|
'subkey': self.get_option('subkey'),
|
||||||
'directory': directory,
|
'directory': directory,
|
||||||
'create': False,
|
'create': self.get_option('create'),
|
||||||
'returnall': False,
|
'returnall': self.get_option('returnall'),
|
||||||
'overwrite': False,
|
'overwrite': self.get_option('overwrite'),
|
||||||
'nosymbols': False,
|
'nosymbols': self.get_option('nosymbols'),
|
||||||
'userpass': '',
|
'userpass': self.get_option('userpass') or '',
|
||||||
'length': 16,
|
'length': self.get_option('length'),
|
||||||
'backup': False,
|
'backup': self.get_option('backup'),
|
||||||
'missing': 'error',
|
'missing': self.get_option('missing'),
|
||||||
|
'umask': self.get_option('umask'),
|
||||||
}
|
}
|
||||||
|
|
||||||
def run(self, terms, variables, **kwargs):
|
def run(self, terms, variables, **kwargs):
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
- name: Create a password ({{ backend }})
|
- name: Create a password ({{ backend }})
|
||||||
set_fact:
|
set_fact:
|
||||||
newpass: "{{ lookup('community.general.passwordstore', 'test-pass length=8 create=yes', backend=backend) }}"
|
newpass: "{{ lookup('community.general.passwordstore', 'test-pass', length=8, create=true, backend=backend) }}"
|
||||||
|
|
||||||
- name: Fetch password from an existing file ({{ backend }})
|
- name: Fetch password from an existing file ({{ backend }})
|
||||||
set_fact:
|
set_fact:
|
||||||
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
- name: Create a password with equal sign ({{ backend }})
|
- name: Create a password with equal sign ({{ backend }})
|
||||||
set_fact:
|
set_fact:
|
||||||
newpass: "{{ lookup('community.general.passwordstore', 'test-pass-equal userpass=SimpleSample= create=yes', backend=backend) }}"
|
newpass: "{{ lookup('community.general.passwordstore', 'test-pass-equal userpass=SimpleSample= create=true', backend=backend) }}"
|
||||||
|
|
||||||
- name: Fetch a password with equal sign ({{ backend }})
|
- name: Fetch a password with equal sign ({{ backend }})
|
||||||
set_fact:
|
set_fact:
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
|
|
||||||
- name: Create a password using missing=create ({{ backend }})
|
- name: Create a password using missing=create ({{ backend }})
|
||||||
set_fact:
|
set_fact:
|
||||||
newpass: "{{ lookup('community.general.passwordstore', 'test-missing-create missing=create length=8', backend=backend) }}"
|
newpass: "{{ lookup('community.general.passwordstore', 'test-missing-create', missing='create', length=8, backend=backend) }}"
|
||||||
|
|
||||||
- name: Fetch password from an existing file ({{ backend }})
|
- name: Fetch password from an existing file ({{ backend }})
|
||||||
set_fact:
|
set_fact:
|
||||||
|
@ -44,7 +44,7 @@
|
||||||
|
|
||||||
- name: Fetch password from existing file using missing=empty ({{ backend }})
|
- name: Fetch password from existing file using missing=empty ({{ backend }})
|
||||||
set_fact:
|
set_fact:
|
||||||
readpass: "{{ lookup('community.general.passwordstore', 'test-missing-create missing=empty', backend=backend) }}"
|
readpass: "{{ lookup('community.general.passwordstore', 'test-missing-create', missing='empty', backend=backend) }}"
|
||||||
|
|
||||||
- name: Verify password ({{ backend }})
|
- name: Verify password ({{ backend }})
|
||||||
assert:
|
assert:
|
||||||
|
@ -53,7 +53,7 @@
|
||||||
|
|
||||||
- name: Fetch password from non-existing file using missing=empty ({{ backend }})
|
- name: Fetch password from non-existing file using missing=empty ({{ backend }})
|
||||||
set_fact:
|
set_fact:
|
||||||
readpass: "{{ query('community.general.passwordstore', 'test-missing-pass missing=empty', backend=backend) }}"
|
readpass: "{{ query('community.general.passwordstore', 'test-missing-pass', missing='empty', backend=backend) }}"
|
||||||
|
|
||||||
- name: Verify password ({{ backend }})
|
- name: Verify password ({{ backend }})
|
||||||
assert:
|
assert:
|
||||||
|
@ -71,7 +71,7 @@
|
||||||
|
|
||||||
- name: Fetch a password with YAML subkey ({{ backend }})
|
- name: Fetch a password with YAML subkey ({{ backend }})
|
||||||
set_fact:
|
set_fact:
|
||||||
readyamlpass: "{{ lookup('community.general.passwordstore', 'test-yaml-pass subkey=key', backend=backend) }}"
|
readyamlpass: "{{ lookup('community.general.passwordstore', 'test-yaml-pass', subkey='key', backend=backend) }}"
|
||||||
|
|
||||||
- name: Read a yaml subkey ({{ backend }})
|
- name: Read a yaml subkey ({{ backend }})
|
||||||
assert:
|
assert:
|
||||||
|
@ -96,7 +96,7 @@
|
||||||
|
|
||||||
- name: Fetch all from multiline file ({{ backend }})
|
- name: Fetch all from multiline file ({{ backend }})
|
||||||
set_fact:
|
set_fact:
|
||||||
readyamlpass: "{{ lookup('community.general.passwordstore', 'test-multiline-pass returnall=yes', backend=backend) }}"
|
readyamlpass: "{{ lookup('community.general.passwordstore', 'test-multiline-pass', returnall='yes', backend=backend) }}"
|
||||||
|
|
||||||
- name: Multiline pass returnall returns everything in the file ({{ backend }})
|
- name: Multiline pass returnall returns everything in the file ({{ backend }})
|
||||||
assert:
|
assert:
|
||||||
|
@ -105,7 +105,7 @@
|
||||||
|
|
||||||
- name: Create a password in a folder ({{ backend }})
|
- name: Create a password in a folder ({{ backend }})
|
||||||
set_fact:
|
set_fact:
|
||||||
newpass: "{{ lookup('community.general.passwordstore', 'folder/test-pass length=8 create=yes', backend=backend) }}"
|
newpass: "{{ lookup('community.general.passwordstore', 'folder/test-pass', length=8, create=true, backend=backend) }}"
|
||||||
|
|
||||||
- name: Fetch password from folder ({{ backend }})
|
- name: Fetch password from folder ({{ backend }})
|
||||||
set_fact:
|
set_fact:
|
||||||
|
|
|
@ -125,7 +125,9 @@
|
||||||
that:
|
that:
|
||||||
- eval_error is failed
|
- eval_error is failed
|
||||||
- >-
|
- >-
|
||||||
"Passwordstore directory 'somenonexistentplace' does not exist" in eval_error.msg
|
"Passwordstore directory '" in eval_error.msg
|
||||||
|
- >-
|
||||||
|
"/somenonexistentplace' does not exist" in eval_error.msg
|
||||||
|
|
||||||
- name: Test pass compatibility shim detection
|
- name: Test pass compatibility shim detection
|
||||||
block:
|
block:
|
||||||
|
|
Loading…
Reference in a new issue