Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

no_log on individual loop items #489

Open
nlvw opened this issue Jun 6, 2023 · 3 comments
Open

no_log on individual loop items #489

nlvw opened this issue Jun 6, 2023 · 3 comments

Comments

@nlvw
Copy link

nlvw commented Jun 6, 2023

A cool, but probably unknown feature, of looping in Ansible is that you can set no_log on a per item basis. Unfortunately ARA doesn't recognize this and discards the entire tasks output instead of just the loop/item marked with no_log.

The benefit of the below is you get logs for loops where no password is specified or a locked/empty password */! is specified. This helps troubleshooting or viewing things like AD user home creations, local accounts without passwords, and so on.

It would be nice if ARA could selective hide loop output based on no_log value the same as ansible.

Ansible Task

- name: set local and adusers users
  ansible.builtin.user:
    name: "{{ item.name }}"
    shell: "{{ item.shell | default('/bin/bash') }}"
    uid: "{{ item.uid | default(omit) }}"
    password: "{{ item.password | default(omit) }}" # result is masked/hidden
    update_password: "{{ item.update_password | default(omit) }}"
    password_lock: "{{ item.password_lock | default(omit) }}"
    home: "{{ item.home | default(omit) }}"
    create_home: "{{ item.create_home | default(omit) }}"
    move_home: "{{ item.move_home | default(omit) }}"
    group: "{{ item.group | default(omit) }}"
    groups: "{{ item.groups | default(omit) }}"
    umask: "{{ item.umask | default(omit) }}"
    system: "{{ item.system | default(omit) }}"
    local: "{{ item.local | default(omit) }}"
    state: "{{ item.state | default('present') }}"
    remove: "{{ item.remove | default(omit) }}"
    expires: "{{ item.expires | default(omit) }}"
  when:
    - item.name is defined
    - item.name | length > 0
  loop: "{{ lookup('community.general.merge_variables', '^users_users($|_.*$)', pattern_type='regex', initial_value=[]) }}"
  loop_control:
    label: "{{ item.name }}"
  no_log: "{{ true if ((item.password is defined) and (item.password != '*') and (item.password != '!')) else false }}"

Console Output (red marked out names displayed correctly and 'None' denotes a no_log item)
image

ARA Task Result:
image

@dmsimard
Copy link
Contributor

Hey @nlvw,

Thanks for the issue and apologies for the delay, I've been away.

I understand what you'd like to achieve and I know troubleshooting with no_log can be tricky.

I must point out that getting ansible callbacks to reliably discard sensitive data has been a challenging topic and the result of security concerns (like ansible/ansible#22505 and https://bugzilla.redhat.com/show_bug.cgi?id=1440912).

If you'd like to experiment with what this looks like from the perspective of the callback interface the current sanitization occurs here I believe:

results = strip_internal_keys(module_response_deepcopy(result._result))
# Round-trip through JSON to sort keys and convert Ansible types
# to standard types
try:
jsonified = json.dumps(results, cls=AnsibleJSONEncoder, ensure_ascii=False, sort_keys=True)
except TypeError:
# Python 3 can't sort non-homogenous keys.
# https://bugs.python.org/issue25457
jsonified = json.dumps(results, cls=AnsibleJSONEncoder, ensure_ascii=False, sort_keys=False)
results = json.loads(jsonified)
(we used dump_results until dce9f3a)

I think the main challenge regarding your use case is that ara doesn't granularly store results for each item of a task and so wouldn't individually consider the value of no_log for each item of a loop.

In other words, when a task runs on a host, it will be stored as a single result whether there is a loop or not.
If there is a loop, there would be a list called results with the results nested inside.

I do not have a good suggestion at this time but let me know if you have any ideas.

@nlvw
Copy link
Author

nlvw commented Jun 20, 2023

@dmsimard Thanks for looking into this. I thought to point this out as the behavior was different compared to the stdout_callback ansible implementation. This is not critical just a nice to have as it may be pretty niche.

For loop tasks semaphore seems to store things as a single task but it has each loop seperately recorded inside that task. You would just need to implement the no_log censorship at the item/loop level instead of the overall task level. Keyword 'just' :).

Feel free to close this unless it's something you want to implement.

@dmsimard
Copy link
Contributor

There is no need to close it, it's something we could do one day.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants