Add yaml support to passwordstore. (#1681)
Co-authored-by: Florian Bergmann <Florian.Bergmann@datev.de>pull/1693/head
parent
5a52b573fe
commit
f955a85848
|
@ -0,0 +1,2 @@
|
||||||
|
breaking_changes:
|
||||||
|
- "passwordstore lookup plugin - now parsing a password store entry as YAML if possible, skipping the first line (which by convention only contains the password and nothing else). If it cannot be parsed as YAML, the old ``key: value`` parser will be used to process the entry. Can break backwards compatibility if YAML formatted code was parsed in a non-YAML interpreted way, e.g. ``foo: [bar, baz]`` will become a list with two elements in the new version, but a string ``'[bar, baz]'`` in the old (https://github.com/ansible-collections/community.general/issues/1673)."
|
|
@ -105,6 +105,8 @@ _raw:
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import time
|
import time
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
|
||||||
from distutils import util
|
from distutils import util
|
||||||
from ansible.errors import AnsibleError, AnsibleAssertionError
|
from ansible.errors import AnsibleError, AnsibleAssertionError
|
||||||
|
@ -209,10 +211,15 @@ class LookupModule(LookupBase):
|
||||||
).splitlines()
|
).splitlines()
|
||||||
self.password = self.passoutput[0]
|
self.password = self.passoutput[0]
|
||||||
self.passdict = {}
|
self.passdict = {}
|
||||||
for line in self.passoutput[1:]:
|
try:
|
||||||
if ':' in line:
|
values = yaml.safe_load('\n'.join(self.passoutput[1:]))
|
||||||
name, value = line.split(':', 1)
|
for key, item in values.items():
|
||||||
self.passdict[name.strip()] = value.strip()
|
self.passdict[key] = item
|
||||||
|
except (yaml.YAMLError, AttributeError):
|
||||||
|
for line in self.passoutput[1:]:
|
||||||
|
if ':' in line:
|
||||||
|
name, value = line.split(':', 1)
|
||||||
|
self.passdict[name.strip()] = value.strip()
|
||||||
except (subprocess.CalledProcessError) as e:
|
except (subprocess.CalledProcessError) as e:
|
||||||
if e.returncode != 0 and 'not in the password store' in e.output:
|
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.'
|
# if pass returns 1 and return string contains 'is not in the password store.'
|
||||||
|
|
|
@ -60,3 +60,63 @@
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- readpass == newpass
|
- readpass == newpass
|
||||||
|
|
||||||
|
# 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.
|
||||||
|
- name: Create the YAML password content
|
||||||
|
copy:
|
||||||
|
dest: "~/.password-store/test-yaml-pass"
|
||||||
|
content: |
|
||||||
|
testpassword
|
||||||
|
key: |
|
||||||
|
multi
|
||||||
|
line
|
||||||
|
|
||||||
|
- name: Read .gpg-id from .password-store
|
||||||
|
set_fact:
|
||||||
|
gpgid: "{{ lookup('file', '~/.password-store/.gpg-id') }}"
|
||||||
|
|
||||||
|
- name: Encrypt the file using the gpg key
|
||||||
|
command: "{{ gpg2_bin }} --batch --encrypt -r {{ gpgid }} ~/.password-store/test-yaml-pass"
|
||||||
|
|
||||||
|
- name: Fetch a password with YAML subkey
|
||||||
|
set_fact:
|
||||||
|
readyamlpass: "{{ lookup('community.general.passwordstore', 'test-yaml-pass subkey=key') }}"
|
||||||
|
|
||||||
|
- name: Read a yaml subkey
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- readyamlpass == 'multi\nline'
|
||||||
|
|
||||||
|
- name: Create a non-YAML multiline file
|
||||||
|
copy:
|
||||||
|
dest: "~/.password-store/test-multiline-pass"
|
||||||
|
content: |
|
||||||
|
testpassword
|
||||||
|
random additional line
|
||||||
|
|
||||||
|
- name: Read .gpg-id from .password-store
|
||||||
|
set_fact:
|
||||||
|
gpgid: "{{ lookup('file', '~/.password-store/.gpg-id') }}"
|
||||||
|
|
||||||
|
- name: Encrypt the file using the gpg key
|
||||||
|
command: "{{ gpg2_bin }} --batch --encrypt -r {{ gpgid }} ~/.password-store/test-multiline-pass"
|
||||||
|
|
||||||
|
- name: Fetch password from multiline file
|
||||||
|
set_fact:
|
||||||
|
readyamlpass: "{{ lookup('community.general.passwordstore', 'test-multiline-pass') }}"
|
||||||
|
|
||||||
|
- name: Multiline pass only returns first line
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- readyamlpass == 'testpassword'
|
||||||
|
|
||||||
|
- name: Fetch all from multiline file
|
||||||
|
set_fact:
|
||||||
|
readyamlpass: "{{ lookup('community.general.passwordstore', 'test-multiline-pass returnall=yes') }}"
|
||||||
|
|
||||||
|
- name: Multiline pass returnall returns everything in the file
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- readyamlpass == 'testpassword\nrandom additional line'
|
||||||
|
|
Loading…
Reference in New Issue