4

I am running an ansible script on localhost to copy a folder to another location. However,

- name: Copy Network
  become: yes
  become_user: root
  copy:
    src: /d/
    dest: "/dest/d/"
    mode: 0644
  tags: [network]

is giving me [Errno 13] Permission denied: b'd/f1'. I was expecting become_user will make the command execute as root, didn't work. The permission of this file is 0600(root:root).

Can you please give me pointers to get access to this file to copy it using ansible?

Note:

  • sudo ansible-playbook p.yml works perfectly however, I don't want to use sudo with ansible command if it's not required and ansible has a trick for it.

  • command: cp -r /d/ /dest/d/ works without appending sudo to the ansible command (ansible-playbook p.yml). However, I don't want to use command if I can help it because of idempotence & copy module has mode option required for the task.

0

3 Answers 3

9

Update: If you can escalate the privilege to root on localhost master the solution is to set remote_src: true (credit @ivandov)

- copy:
    src: /d/
    dest: /dest/d/
    mode: '0644'
    remote_src: true
  become: true
  become_user: root

The below details describe the case when you're not able to escalate to root on localhost. Given the file on localhost

shell> ll /tmp/test/d/f1
-rw-r----- 1 root root 0 Aug 25 23:23 /tmp/test/d/f1

the module copy works as expected

- copy:
    src: /tmp/test/d/
    dest: /tmp/test/dest/
  become: true
  become_user: root

First, it tries to read the file and fails

fatal: [localhost]: FAILED! => msg: 'an error occurred while trying to read the file ''/tmp/test/d/f1'': [Errno 13] Permission denied: b''/tmp/test/d/f1''. [Errno 13] Permission denied: b''/tmp/test/d/f1'''

By default, module copy copies files from src (local path to a file to copy to the remote server) to dest (remote absolute path where the file should be copied to). In this case, become: true means Ansible escalates privilege on the remote host, but not on the localhost master. Despite the fact that the task is running on localhost, i.e. both master and the remote host are localhost, without remote_src: true the setting become: true applies only to writing the file not to reading it. If you can't escalate to root on the localhost setting remote_src: true

- copy:
    src: /tmp/test/d/
    dest: /tmp/test/dest/
    remote_src: true
  become: true
  become_user: root

will fail

fatal: [localhost]: FAILED! => changed=false ansible_facts: discovered_interpreter_python: /usr/bin/python3 module_stderr: |- sudo: a password is required module_stdout: '' msg: |- MODULE FAILURE See stdout/stderr for the exact error rc: 1


Q: "Is there any workaround for it?"

A: Without the escalation to the root, there is no workaround. It would violate the ownership and permissions of the files. For example, given the file at the controller

shell> ll f1
-rw-rw---- 1 root root 0 Sep 13 18:17 f1

The playbook below was started by an unprivileged user

shell> cat playbook.yml
- hosts: test_01
  become: true
  tasks:
    - copy:
        src: f1
        dest: /tmp

will crash

TASK [copy] ****
fatal: [test_01]: FAILED! => 
  msg: 'an error occurred while trying to read the file ''/scratch/f1'':
       [Errno 13] Permission denied: b''/scratch/f1'''

If you can't escalate to root on the localhost master the solution is to make the file readable for the user running the playbook.

9
  • I see, thanks for the explanation. Is there any workaround for it?
    – atb00ker
    Commented Feb 5, 2020 at 15:59
  • 2
    You're welcome. There shouldn't be any workaround to access root files without root permission. Commented Feb 5, 2020 at 16:03
  • @VladimirBotka This makes sense. But I also don't want all my other tasks to run as sudo (by running the playbook as sudo). Only those that have become: yes. So IIUC my options to 1. Change src file permissions or ownership with some become: yes task before the copy task (and restore original state again). 2. Specify for all other tasks to run as non-sudo somehow and run the playbook as sudo?
    – Carolus
    Commented Sep 13, 2020 at 13:22
  • and 3. Use the command module as explained by OP.
    – Carolus
    Commented Sep 13, 2020 at 13:29
  • @Carolus: only option 1 will work. I've updated the answer. Feel free to test other options and post your answer, or question with the code. Commented Sep 13, 2020 at 16:41
1

Building off of Vladimir's answer, there actually IS a simple workaround!

The comment below (and the emphasis I added in bold) was the key.

In the module copy, become: yes applies only to writing the file not to reading it.

Just use remote_src: true, even though you're copying the file locally. This causes the become to escalate privilege correctly when reading the src file/dir from the local machine because it treats the src as a remote machine and properly applies privilege escalation.

- name: Copy Network
  become: yes
  become_user: root
  copy:
    src: /d/
    dest: "/dest/d/"
    remote_src: true  # this allows become to work as expected
    mode: 0644
  tags: [network]
0

tl;dr - Ansible's become: root applies to the target machine, not to the Ansible host running the playbook. Workarounds are possible.

I wrote an answer here to address this problem for a single file: The Ansible host running the playbook doesn't raise it's own permissions to root with become: root; this only applies to the target machine. In the original question both are localhost but I think this behaviour still applies, think of it as a non-root-privileged 'source' and a root-privileged target.

The solution uses delegate_to: localhost to slurp the required file into memory - the delegate_to: enables become: root to work its magic locally, then write out the saved file to the target machine.

The original question asks about doing this for directories however: slurping directories has also been discussed here which should provide a suitable starting point when combined with the per-file slurp solution, esp. note @guzmonne's comment on that answer re. constructing a list of files to slurp before using the per-file workaround (which isn't great but may be preferable to altering file/directory permissions).

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .