ansible / ansible

Ansible is a radically simple IT automation platform that makes your applications and systems easier to deploy and maintain. Automate everything from code deployment to network configuration to cloud management, in a language that approaches plain English, using SSH, with no agents to install on remote systems. https://docs.ansible.com.
https://www.ansible.com/
GNU General Public License v3.0
63.01k stars 23.92k forks source link

Ansible fails to recursively change attributes when directory contains symlinks #74918

Open new-sashok724 opened 3 years ago

new-sashok724 commented 3 years ago

Summary

When i try to use file module to unset the immutable attribute on all files in directory, Ansible gives an error if there symlinks in the directory

Issue Type

Bug Report

Component Name

file

Ansible Version

ansible [core 2.11.1] 
  config file = /home/sashok724/Documents/Projects/Ansible/ansible.cfg
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.9/site-packages/ansible
  ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/bin/ansible
  python version = 3.9.5 (default, May 24 2021, 12:50:35) [GCC 11.1.0]
  jinja version = 3.0.1
  libyaml = True

Configuration

ANY_ERRORS_FATAL(/home/sashok724/Documents/Projects/Ansible/ansible.cfg) = True
DEFAULT_FORKS(/home/sashok724/Documents/Projects/Ansible/ansible.cfg) = 10
DEFAULT_TIMEOUT(/home/sashok724/Documents/Projects/Ansible/ansible.cfg) = 15
INTERPRETER_PYTHON(/home/sashok724/Documents/Projects/Ansible/ansible.cfg) = auto_silent
INVENTORY_UNPARSED_IS_FAILED(/home/sashok724/Documents/Projects/Ansible/ansible.cfg) = True

OS / Environment

Arch Linux x86_64

Steps to Reproduce

- file: path=/root/testdir/ state=directory
- file: path=/root/testdir/innerdir/ state=directory
- file: dest=/root/testdir/innerdirsymlink src=innerdir state=link
- copy: dest=/root/testdir/immutablefile content='' attr=i
- file: path=/root/testdir/ state=directory attr=-i recurse=true follow=false # <--- fails here

Expected Results

Playbook completes without errors, after playbook completion immutable attribute is not set on any files in the directory

Actual Results

TASK [testrole : file] *******************************************************************************************************************************************************************************************************************************************************************************************************
task path: /home/sashok724/Documents/Projects/Ansible/roles/testrole/tasks/main.yml:5
<localhost> ESTABLISH LOCAL CONNECTION FOR USER: root
<localhost> EXEC /bin/sh -c 'echo ~root && sleep 0'
<localhost> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /root/.ansible/tmp `"&& mkdir "` echo /root/.ansible/tmp/ansible-tmp-1622975254.2169983-549979-245538434772484 `" && echo ansible-tmp-1622975254.2169983-549979-245538434772484="` echo /root/.ansible/tmp/ansible-tmp-1622975254.2169983-549979-245538434772484 `" ) && sleep 0'
Using module file /usr/lib/python3.9/site-packages/ansible/modules/file.py
<localhost> PUT /root/.ansible/tmp/ansible-local-549632xlhb73xa/tmp69oty30n TO /root/.ansible/tmp/ansible-tmp-1622975254.2169983-549979-245538434772484/AnsiballZ_file.py
<localhost> EXEC /bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-tmp-1622975254.2169983-549979-245538434772484/ /root/.ansible/tmp/ansible-tmp-1622975254.2169983-549979-245538434772484/AnsiballZ_file.py && sleep 0'
<localhost> EXEC /bin/sh -c '/usr/bin/python /root/.ansible/tmp/ansible-tmp-1622975254.2169983-549979-245538434772484/AnsiballZ_file.py && sleep 0'
<localhost> EXEC /bin/sh -c 'rm -f -r /root/.ansible/tmp/ansible-tmp-1622975254.2169983-549979-245538434772484/ > /dev/null 2>&1 && sleep 0'
The full traceback is:
Traceback (most recent call last):
  File "/tmp/ansible_file_payload_y93w2yx_/ansible_file_payload.zip/ansible/module_utils/basic.py", line 998, in set_attributes_if_different
    raise Exception("Error while setting attributes: %s" % (out + err))
Exception: Error while setting attributes: /usr/bin/chattr: Operation not supported while reading flags on /root/testdir/innerdirsymlink

fatal: [localhost]: FAILED! => {
    "changed": false,
    "details": "Error while setting attributes: /usr/bin/chattr: Operation not supported while reading flags on /root/testdir/innerdirsymlink\n",
    "gid": 0,
    "group": "root",
    "invocation": {
        "module_args": {
            "_diff_peek": null,
            "_original_basename": null,
            "access_time": null,
            "access_time_format": "%Y%m%d%H%M.%S",
            "attr": "-i",
            "attributes": "-i",
            "follow": false,
            "force": false,
            "group": null,
            "mode": null,
            "modification_time": null,
            "modification_time_format": "%Y%m%d%H%M.%S",
            "owner": null,
            "path": "/root/testdir/",
            "recurse": true,
            "selevel": null,
            "serole": null,
            "setype": null,
            "seuser": null,
            "src": null,
            "state": "directory",
            "unsafe_writes": false
        }
    },
    "mode": "0777",
    "msg": "chattr failed",
    "owner": "root",
    "path": "/root/testdir/innerdirsymlink",
    "size": 8,
    "state": "link",
    "uid": 0
}

Code of Conduct

ansibot commented 3 years ago

Files identified in the description:

If these files are incorrect, please update the component name section of the description or use the !component bot command.

click here for bot help

hargut commented 2 years ago

The cazy part with permission changes and the file module is that follow is by default true. This leads to ansible trying to change permissions on files that chown/chmod and others would not touch in recursive mode.

In case eg. a user creates a symlink to /etc/passwd in its /home ansibles file module will happily switch the permissions of the symlink destination when trying to fix permissions in the users home.

This default contrary to other standard tools is totally unexpected and can cause severe damage in any case where the task runs with elevated permissions.