ansible.posix icon indicating copy to clipboard operation
ansible.posix copied to clipboard

authorized_key module always reports 'changed' when using key_options

Open cudevmaxwell opened this issue 2 years ago • 4 comments

SUMMARY

When using the authorized_key module, tasks which use the key_options parameter always fire 'changed'.

ISSUE TYPE
  • Bug Report
COMPONENT NAME

authorized_key

ANSIBLE VERSION
ansible 2.9.27
COLLECTION VERSION

CONFIGURATION

OS / ENVIRONMENT

Linux - Fedora release 35 (Thirty Five)

STEPS TO REPRODUCE
# Not a real key below
- name: Add key to authorized_keys file
  authorized_key:
    user: "borg-user"
    state: present
    key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIP9Z7HlUQ0Dk+nDmedLG7I9DYDcHN6iv/nuCDViFOEYr Borg backup key"
    key_options: "command=\"borg serve --append-only --restrict-to-path /home/borg-user/backup\",restrict "
EXPECTED RESULTS

Initial run shows changed, next run shows not changed.

ACTUAL RESULTS

Initial run shows changed, next run shows changed, even though authorized_keys file did not change.

cudevmaxwell avatar Feb 18 '22 20:02 cudevmaxwell

I get this same behaviour even when I use a default(omit) jinja value.

- name: set authorized keys
  authorized_key:
    user: "{{ item.user }}"
    state: "{{ item.state | default('present') }}"
    key: "{{ item.key }}"
    key_options: "{{ item.key_options | default(omit) }}"
    comment: "{{ item.comment | default(omit) }} "
    exclusive: "{{ item.exclusive | default(omit) }}"
    manage_dir: "{{ item.manage_dir | default(omit) }}"
    path: "{{ item.path | default(omit) }}"
    validate_certs: "{{ item.validate_certs | default(omit) }}"
  with_items: "{{ users_merged_authkeys }}"
  when:
    - (item.user is defined) and (item.user | length > 0)
    - (item.key is defined) and (item.key | length > 0)

With list item:

 - user: tester
    comment: [email protected]
    key: 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILiChtXZDvU1G5oCwaoDHXoecnfMo7ff8w6k4zoG8OK6'
    exclusive: yes
    state: present

nlvw avatar Feb 20 '22 02:02 nlvw

Hi @cudevmaxwell @nlvw, thank you for reporting this issue. I tested the example playbook from @cudevmaxwell and replicated the problem that the result of the task is always "changed": true.

By the way, if I remove the trailing white-space like ...snip...,restrict", the task result of the second run is "changed": false.

saito-hideki avatar Mar 10 '22 12:03 saito-hideki

@saito-hideki Good catch, can confirm that the trailing whitespace on key_options is causing the bug in my example.

In plugins/modules/authorized_key.py, the existing keys are parsed using the shlex module with whitespace_split == True. That removes the trailing whitespace from the command portion of the key. When processing the new keys, the key_options option is parsed using a regex which preserves the trailing whitespace. The difference between the two command portions (one with whitespace stripped out, one with whitespace preserved) causes the keys to not match, so a write is performed.

Whitespace isn't significant AFAIK, so parseoptions could first .strip() options before processing them further.

Or I can just remove the trailing whitespace and we can close this ticket haha.

Unfortunately, I don't have an explanation for what @nlvw is seeing. It's similar but I don't think this minor whtespace bug should impact the behavior of the the default(omit) filter. If the option is omitted completely, change should definitely not be firing.

cudevmaxwell avatar Mar 10 '22 15:03 cudevmaxwell

@cudevmaxwell thanks for the checking!

I can just remove the trailing whitespace and we can close this ticket haha.

haha, the handling part of whitespace may need to be improved including the documentation. I have labeled this issue as a bug :)

saito-hideki avatar Mar 10 '22 23:03 saito-hideki