ansible-collections / ansible.posix

Ansible Collection for Posix
Other
159 stars 153 forks source link

authorized_key module always reports 'changed' when using key_options #327

Open cudevmaxwell opened 2 years ago

cudevmaxwell commented 2 years ago
SUMMARY

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

ISSUE TYPE
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.

nlvw commented 2 years ago

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: tester@example.com
    key: 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILiChtXZDvU1G5oCwaoDHXoecnfMo7ff8w6k4zoG8OK6'
    exclusive: yes
    state: present
saito-hideki commented 2 years ago

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.

cudevmaxwell commented 2 years ago

@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.

saito-hideki commented 2 years ago

@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 :)