How to use include_vars with a file needing elevated privileges

Let’s suppose I run a playbook as a non-root user and one task needs to include a vars file with only root permissions.
The ansible.builtin.include_vars official doc states that:the ‘become’ attribute is not supported but “Is usable alongside become keywords”, which seems to contradict the fact that it is unsupported.
I tried to use the become vars but that does not work either:

  • name: Including vars issue
    hosts: all
    gather_facts: false
    tasks:

  • name: Creating a file with root-only permissions
    vars:
    ansible_become: yes
    ansible_become_method: sudo
    ansible_become_user: root
    file:
    group: ‘root’
    mode: ‘0640’
    owner: ‘root’
    path: “…/files/restricted_file”
    state: touch

  • name: Including vars with root-only permissions
    vars:
    ansible_become: yes
    ansible_become_method: sudo
    ansible_become_user: root
    include_vars: “…/files/restricted_file”
    ignore_errors: true

  • name: Including vars with non-root user permissions
    vars:
    ansible_become: yes
    ansible_become_method: sudo
    ansible_become_user: admin
    include_vars: “…/files/capabilities.json”

leads to:

It seems to be a tricky one.
I am using ansible core 2.12.3.

Does @Brian Coca have any suggestion?

The “become” bits have to do with privilege escalation for Ansible tasks that run on the target hosts.
Including/importing vars and friends happen on the Ansible controller, not the target hosts.

It doesn’t matter that your target host and your Ansible controller are the same host. Controller bits aren’t privilege escalated.

Are you implying that it is not possible to include a vars file on the controller that require higher privileges than the user’s permissions running the playbook?

Also, what does “Is usable alongside become keywords” mean?

Yes, I implied exactly that. I should have stated it explicitly. (Also, I think it’s true, but Ansible has surprised me more than once before.)

“Is usable alongside become keywords” is a description of the “becomes” attribute. The key point for your case is the red “none” in the “Support” column, which together means that no amount of “become” shenanigans is going to affect the behavior of include_vars.

Interpretation of the “Attributes” table is a bit obscure and error prone from users’ perspectives, IMHO. I believe it’s showing a peek under the covers of how modules are implemented. It appears there’s a fairly standard set of attributes, which are influenced by various keywords, config file settings, environment variables, and runtime conditions, and these attributes may influence to various degrees different aspects of modules’ operation. “Become” for example influences include_vars not at all.

Although your initial post amply demonstrates the problem you ran into, we can surmise that what you’re trying to accomplish is more interesting. Can we step back a bit and maybe up to a higher level and explore your actual use case? (I have a feeling the answer is going to involve ansible-vault. You’ve got me curious.)

The 'usable' part is badly phrased, it won't error (yet) with become
settings (from config/cli/keywords or vars) but it ignores them

Are you implying that it is not possible to include a vars file on the controller that require higher privileges than the user's permissions running the playbook?

This is exactly the case

One workaround, use a slurp task (with become) task to get the
original file and dump it into a variable (or a file and then
include_vars if you cannot use the container variable).

@uto@gmail.com
I just need to let the user running the playbook access files which cannot be accessed to any other user (except root of course).I’m very surprised that this limitation exist with that module.

@Brian Coca
I just don’t understand why the ansible team has decided that become keywords cannot affect include_vars. It’s just a module that always runs on the controller, but what’s the difference with all other modules which are affected by become keywords but are delegated on the localhost? It just does not make any sense to me. Or maybe I’m missing a fundamental piece of the inner workings.

This slurp worked for me:

    - name: Slurp the file
      vars:
            ansible_become: yes
            ansible_become_method: sudo
            ansible_become_user: root
      slurp:
        src: "{{ restricted_file }}"
      delegate_to: "{{ controller_host }}"
      register: slop
        
    - name: Set a fact
      set_fact:
        slick: "{{ slop.content | b64decode | from_yaml }}"

I’m still curious, though, why there would be root-only vars files on your controller.

As to “why the ansible team has decided that become keywords cannot affect include_vars”, I rather doubt it’s ever come up before.

Internally, Ansible does lots of including/importing vars files. I imagine it evolved as a simple way to let the user pick some snowflake that wasn’t one of the 20 or so sources of variables that Ansible already pulled in. For reasons I don’t see, you’ve got an extraordinary quirk (root-only access) on an already unusual case.

Another approach you could try: Whatever rootly process that currently creates that file could end with an “ansible-vault encrypt …” operation on it (or a copy) that your controller process could be allowed to read. Or some variation on that theme.

Good luck!

@jean-chistophe manicot

I just don't understand why the ansible team has decided that become keywords cannot affect include_vars. It's just a module that always runs on the controller, but what's the difference with all other modules which are affected by become keywords but are delegated on the localhost? It just does not make any sense to me. Or maybe I'm missing a fundamental piece of the inner workings.

It was not as much a 'decision' as a 'consequence', include_vars is
NOT a module, it is an action plugin, both types work as 'task
actions' but action plugins execute inside the ansible process on the
controller while modules execute on a remote machine. We mostly hide
this distinction from the user but it creates several issues like
'become doesn't affect action plugins', also why we recently added
'attributes' to inform people of long standing behaviors that were not
noticed/ignored unless you hit a corner case like this.

So yes, you were missing a piece of the inner workings, one that was
purposefully hidden from users. 99% of the time this does not matter
much, but this case ended up being in the 1%.

one reason that this is an 'action' and not a module is that modules
are not allowed to change the normal variables, only 'return facts',
other actions like debug/includes/imports/add_host/group_by also
modify 'ansilbe internal data' which for many reasons, security being
just one, we don't allow modules to do.