Bootstrap FreeKB - Ansible - Resolve "Destination not writable"
Ansible - Resolve "Destination not writable"

Updated:   |  Ansible articles

"Destination not writable" is returned when attempting to create, copy, download or move a file to a directory that the user lacks the write permission. There are a number of different modules that are used to create, copy, download or move a file to a directory, such as:

As an example, let's say the file module is being used to create foo.txt in the /etc directory.

- name: "create foo.txt in the /etc directory"
  file:
    path: "/etc/foo.txt"
    state: "touch"

 

Typically, the /etc directory has the following ownership and permissions. Notice only root has the "w" (write) permission to this directory.

drwxr-xr-x. 124 root root 8192 Oct 15 05:59 /etc

 

Using native Linux commands, if a user other than root attempts to write to the /etc directory, "permission denied" would be returned.

[john.doe]$ touch /etc/foo.txt
touch: cannot touch ‘/etc/foo.txt’: Permission denied

 

Likewise, if John Doe (or any user other than root) were to invoke an Ansible playbook that attempted to create, copy, download or move a file to the /etc directory, "Destination not writable" would be returned.

TASKS [create foo.txt in the /etc directory]
fatal: [server1.example.com]: FAILED! => {"changed": false, "checksum": "34949034fz73467b77cdc923aa747b", "msg": "Destination /etc not writable"}

 

Furthermore, the file module could be used to confirm that only root can write to the /etc directory.

- name: "get the stats of the '/etc' directory"
  stat:
    path: "/etc"
  register: out

- name: "output the 'out' variable"
  debug:
    msg: "{{ out }}"

 

Which should return something like this. Notice here the "writeable" is "false".

TASK [output the 'out' variable] 
ok: [server1.example.com] => {
    "msg": {
        "changed": false, 
        "failed": false, 
        "stat": {
            "atime": 1602763108.245787, 
            "attr_flags": "", 
            "attributes": [], 
            "block_size": 4096, 
            "blocks": 24, 
            "charset": "binary", 
            "ctime": 1602762950.0358446, 
            "dev": 64768, 
            "device_type": 0, 
            "executable": true, 
            "exists": true, 
            "gid": 0, 
            "gr_name": "root", 
            "inode": 69, 
            "isblk": false, 
            "ischr": false, 
            "isdir": true, 
            "isfifo": false, 
            "isgid": false, 
            "islnk": false, 
            "isreg": false, 
            "issock": false, 
            "isuid": false, 
            "mimetype": "inode/directory", 
            "mode": "0755", 
            "mtime": 1602762950.0358446, 
            "nlink": 124, 
            "path": "/etc", 
            "pw_name": "root", 
            "readable": true, 
            "rgrp": true, 
            "roth": true, 
            "rusr": true, 
            "size": 8192, 
            "uid": 0, 
            "version": "1862525523", 
            "wgrp": false, 
            "woth": false, 
            "writeable": false, 
            "wusr": true, 
            "xgrp": true, 
            "xoth": true, 
            "xusr": true
        }
    }
}

 

Be aware that a sort of "false positive" situation can occur. Let's say /tmp/foo.txt already exists, and foo.txt is owned by John Doe.

~]$ ls -l /tmp/foo.txt
-rw-r--r--. 1 john.doe  admins 1524 Oct 16 05:23 foo.txt

 

If Jane Doe attempts to create, copy, download or move foo.txt to /tmp/foo.txt, Jane may also get "Destination /etc not writable". For this reason, before you create, copy, download or move a file, it's a good practice to first determine if the file already exists.

- name: "store the statistics of /tmp/foo.txt in the 'foo' variable"
  stat:
    path: "/tmp/foo.txt"
  register: foo

 

The fail module can now be used to cease execution of the playbook if /opt/example.txt does not exist.

- name: "fail when /tmp/foo.txt exists"
  fail: 
   msg: "/tmp/foo.txt already exists"
  when: "foo.stat.exists == true"

 

Assuming the target file does not already exist, there are a few solutions to "Destination not writeable":

  • create, copy, download or move a file to a directory that the is writeable, such as the /tmp directory
  • Invoke the playbook as root
  • Use "become" to become root - of course, this assumes that you have the root password

 




Did you find this article helpful?

If so, consider buying me a coffee over at Buy Me A Coffee



Comments


Add a Comment


Please enter 4949ca in the box below so that we can be sure you are a human.