I found an issue in ansible 2.4.2.0.  This may have existed in previous 
versions.

[defaults]
callback_whitelist = timer
fact_caching = jsonfile
fact_caching_connection = ./.fact_cache
gathering = smart
host_key_checking = False
inventory = ./inventories
log_path = /tmp/ansible.${USER}.log
roles_path = ./roles

The issue revolves around the cache file not being invalidated when 
different parameters are used to fetch the facts.

In the example below, the root_fact will not be printed and an error is 
raised.

- hosts: example_host
  gather_facts: true
  tasks:
  - debug:
      msg: "user_fact:  {{ user_fact }}"

- hosts: example_host
  gather_facts: true
  become: true      # fetch privileged facts
  tasks:
  - debug:
      msg: "root_fact:  {{ root_fact }}"

The reason is the first play fetched the facts and primed the cache with 
non-privileged results.  Subsequent privileged fact lookups will use the 
cache file, but the privileged facts aren't in the cache.

I consider this a bug.

And the inverse is also true; if privileged facts are obtained first then 
subsequent plays will use the cache results and those subsequent plays will 
have access to privileged facts.  In the example below, "root_fact_nonpriv" 
will be printed.

- hosts: example_host
  gather_facts: true
  become: true      # fetch privileged facts
  tasks:
  - debug:
      msg: "root_fact:  {{ root_fact }}"

- hosts: example_host
  gather_facts: true
  tasks:
  - debug:
      msg: "root_fact_nonpriv:  {{ root_fact }}"

I don't know whether I consider this a security bug, but it smells.

In both cases, subtle bugs can be introduced that can be hard to track down.

It seems to me the cache file needs to store the conditions in which it was 
retrieved.  A simple approach would be appending 'privileged' to the cache 
file and using the appropriate cache file based on whether 'become=true' is 
set.  Example:

.fact_cache/example_host             # non-privileged facts
.fact_cache/example_host.privileged  # privileged facts

In summary, a fact cache file obviously needs to continue to check whether 
it's stale or not by comparing age of the file to the cache timeout.

In addition, I would argue that ansible also needs to know whether the 
cache file is privileged or not when considering whether it's stale or not.

BTW, using meta: clear_facts is a workaround not really a solution.

Thoughts?

-- 
You received this message because you are subscribed to the Google Groups 
"Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to ansible-project+unsubscr...@googlegroups.com.
To post to this group, send email to ansible-project@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/ansible-project/85e987d1-ceb0-498a-8296-73dc951d1f08%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to