ansibleumask

Change ownership of parent directory chain recursively


I have a target linux node with default umask=0077. When I run a playbook

- name: Create folder for app
  ansible.builtin.file:
    path: "{{ item }}"
    state: directory
    owner: app_user
    mode: 0755
  with_items:
    - "/opt/app/folder1/bin"
    - "/etc/program/folder2"

parameter "mode" is applicable only to the last folder(bin and folder2). All parent directories got strict rights, according umask.

How can I set required permission to parent directories (not for all /opt or /etc, only for chains):

  1. /opt, /opt/app, /opt/app/folder1, /opt/app/folder1/bin
  2. /etc, /etc/program, /etc/program/folder2

Solution

  • Q: "Change rights on all intermediate parent folders."

    Short answer: The module file doesn't know where to start changing the permissions when all subdirectories exist.

    Details: For example, given the paths, declare depth where you want to start changing the rights. In this case, depth=1 is the root directory and depth=2 is /tmp9

      path1: /tmp9/a/b/c
      path2: /tmp9/x/y/z
      depth: 2
    

    Create a file with the loop that incrementally changes the subdirectories

    shell> cat subdirs.yml
    - file:
        path: "{{ root }}/{{ subs[:ansible_loop.index] | join('/') }}"
        state: directory
        owner: admin
        mode: 0755
      loop: "{{ subs }}"
      loop_control:
        extended: true
      vars:
        dirs: "{{ outer_item | split('/') }}"
        root: "{{ dirs[:depth] | join('/') }}"
        subs: "{{ dirs[depth:] }}"
    

    Include this task in a loop

        - include_tasks: subdirs.yml
          loop:
            - "{{ path1 }}"
            - "{{ path2 }}"
          loop_control:
            loop_var: outer_item
    

    Given the below tree, the task is idempotent

    shell> tree -pu /tmp9
    [drwxr-xr-x root    ]  /tmp9
    ├── [drwxr-xr-x admin   ]  a
    │   └── [drwxr-xr-x admin   ]  b
    │       └── [drwxr-xr-x admin   ]  c
    └── [drwxr-xr-x admin   ]  x
        └── [drwxr-xr-x admin   ]  y
            └── [drwxr-xr-x admin   ]  z
    

    If you change the mode

        mode: 0700
    

    the task changes the permissions

    shell> tree -pu /tmp9
    [drwxr-xr-x root    ]  /tmp9
    ├── [drwx------ admin   ]  a
    │   └── [drwx------ admin   ]  b
    │       └── [drwx------ admin   ]  c
    └── [drwx------ admin   ]  x
        └── [drwx------ admin   ]  y
            └── [drwx------ admin   ]  z
    

    Example of a complete playbook for testing

    - hosts: localhost
      become: true
    
      vars:
    
        path1: /tmp9/a/b/c
        path2: /tmp9/x/y/z
        depth: 2
    
      tasks:
    
        - include_tasks: subdirs.yml
          loop:
            - "{{ path1 }}"
            - "{{ path2 }}"
          loop_control:
            loop_var: outer_item
    

    The module file works as expected. Quoting:

    If `directory', all intermediate subdirectories will be created if they do not exist. Since Ansible 1.7 they will be created with the supplied permissions.

    For example, given the empty directory

    shell> tree -pu /tmp9
    [drwxr-xr-x root    ]  /tmp9
    

    the play

    - hosts: localhost
      become: true
    
      vars:
    
        path1: /tmp9/a/b/c
        path2: /tmp9/x/y/z
    
      tasks:
    
        - file:
            path: "{{ item }}"
            state: directory
            owner: admin
            mode: 0755
          loop:
            - "{{ path1 }}"
            - "{{ path2 }}"
    

    creates the tree

    shell> tree -pu /tmp9
    [drwxr-xr-x root    ]  /tmp9
    ├── [drwxr-xr-x admin   ]  a
    │   └── [drwxr-xr-x admin   ]  b
    │       └── [drwxr-xr-x admin   ]  c
    └── [drwxr-xr-x admin   ]  x
        └── [drwxr-xr-x admin   ]  y
            └── [drwxr-xr-x admin   ]  z
    

    , but changing the mode

            mode: 0700
    

    changes the last subdirectory permissions only

    shell> tree -pu /tmp9
    [drwxr-xr-x root    ]  /tmp9
    ├── [drwxr-xr-x admin   ]  a
    │   └── [drwxr-xr-x admin   ]  b
    │       └── [drwx------ admin   ]  c
    └── [drwxr-xr-x admin   ]  x
        └── [drwxr-xr-x admin   ]  y
            └── [drwx------ admin   ]  z