debconf: idempotency for password question (#81484)

* Gather value of password using debconf-get-selections command,
  use this information for idempotency.

Fixes: #47676

Signed-off-by: Abhijeet Kasurde <akasurde@redhat.com>
pull/81559/head
Abhijeet Kasurde 2 years ago committed by GitHub
parent 6627ba9ace
commit 863e2571db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,3 @@
---
bugfixes:
- debconf - idempotency in questions with type 'password' (https://github.com/ansible/ansible/issues/47676).

@ -27,11 +27,11 @@ attributes:
platforms: debian
notes:
- This module requires the command line debconf tools.
- A number of questions have to be answered (depending on the package).
- Several questions have to be answered (depending on the package).
Use 'debconf-show <package>' on any Debian or derivative with the package
installed to see questions/settings available.
- Some distros will always record tasks involving the setting of passwords as changed. This is due to debconf-get-selections masking passwords.
- It is highly recommended to add C(no_log=True) to task while handling sensitive information using this module.
- It is highly recommended to add C(no_log=True) to the task while handling sensitive information using this module.
- The debconf module does not reconfigure packages, it just updates the debconf database.
An additional step is needed (typically with C(notify) if debconf makes a change)
to reconfigure the package and apply the changes.
@ -46,7 +46,7 @@ notes:
- The main issue is that the C(<package>.config reconfigure) step for many packages
will first reset the debconf database (overriding changes made by this module) by
checking the on-disk configuration. If this is the case for your package then
dpkg-reconfigure will effectively ignore changes made by debconf.
dpkg-reconfigure will effectively ignore changes made by debconf.
- However as dpkg-reconfigure only executes the C(<package>.config) step if the file
exists, it is possible to rename it to C(/var/lib/dpkg/info/<package>.config.ignore)
before executing C(dpkg-reconfigure -f noninteractive <package>) and then restore it.
@ -128,6 +128,28 @@ from ansible.module_utils.common.text.converters import to_text
from ansible.module_utils.basic import AnsibleModule
def get_password_value(module, pkg, question, vtype):
getsel = module.get_bin_path('debconf-get-selections', True)
cmd = [getsel]
rc, out, err = module.run_command(cmd)
if rc != 0:
module.fail_json(msg="Failed to get the value '%s' from '%s'" % (question, pkg))
desired_line = None
for line in out.split("\n"):
if line.startswith(pkg):
desired_line = line
break
if not desired_line:
module.fail_json(msg="Failed to find the value '%s' from '%s'" % (question, pkg))
(dpkg, dquestion, dvtype, dvalue) = desired_line.split()
if dquestion == question and dvtype == vtype:
return dvalue
return ''
def get_selections(module, pkg):
cmd = [module.get_bin_path('debconf-show', True), pkg]
rc, out, err = module.run_command(' '.join(cmd))
@ -151,10 +173,7 @@ def set_selection(module, pkg, question, vtype, value, unseen):
cmd.append('-u')
if vtype == 'boolean':
if value == 'True':
value = 'true'
elif value == 'False':
value = 'false'
value = value.lower()
data = ' '.join([pkg, question, vtype, value])
return module.run_command(cmd, data=data)
@ -193,7 +212,6 @@ def main():
if question not in prev:
changed = True
else:
existing = prev[question]
# ensure we compare booleans supplied to the way debconf sees them (true/false strings)
@ -201,6 +219,9 @@ def main():
value = to_text(value).lower()
existing = to_text(prev[question]).lower()
if vtype == 'password':
existing = get_password_value(module, pkg, question, vtype)
if value != existing:
changed = True
@ -215,12 +236,12 @@ def main():
prev = {question: prev[question]}
else:
prev[question] = ''
diff_dict = {}
if module._diff:
after = prev.copy()
after.update(curr)
diff_dict = {'before': prev, 'after': after}
else:
diff_dict = {}
module.exit_json(changed=changed, msg=msg, current=curr, previous=prev, diff=diff_dict)

@ -33,4 +33,44 @@
- 'debconf_test0.current is defined'
- '"tzdata/Zones/Etc" in debconf_test0.current'
- 'debconf_test0.current["tzdata/Zones/Etc"] == "UTC"'
when: ansible_distribution in ('Ubuntu', 'Debian')
- name: install debconf-utils
apt:
name: debconf-utils
state: present
register: debconf_utils_deb_install
- name: Check if password is set
debconf:
name: ddclient
question: ddclient/password
value: "MySecretValue"
vtype: password
register: debconf_test1
- name: validate results for test 1
assert:
that:
- debconf_test1.changed
- name: Change password again
debconf:
name: ddclient
question: ddclient/password
value: "MySecretValue"
vtype: password
no_log: yes
register: debconf_test2
- name: validate results for test 1
assert:
that:
- not debconf_test2.changed
always:
- name: uninstall debconf-utils
apt:
name: debconf-utils
state: absent
when: debconf_utils_deb_install is changed
when: ansible_distribution in ('Ubuntu', 'Debian')
Loading…
Cancel
Save