Repository: ansible/ansible

Issue:
Custom module using arguments file: permission denied to read arguments
**Ansible version**
ansible 1.3.2

**Steps to reproduce**
1. Create a custom ansible module that uses the arguments file
2. Run the module with sudo_user other than root and default ssh user

**Expected result**
The custom module should read the arguments file and do its work.

**Actual result**
The custom module won't be able to read the arguments file because it is set with 'rw' permissions only for the default ssh user and not the user the module is run with (as specified in the sudo_user parameter of the task)

**Verbose output of execution**:

<pre>
<192.168.111.222> ESTABLISH CONNECTION FOR USER: vagrant
<192.168.111.222> EXEC ['ssh', '-tt', '-vvv', '-o', 'ControlMaster=auto', '-o', 'ControlPersist=60s', '-o', 'ControlPath=/home/diego/.ansible/cp/ansible-ssh-%h-%p-%r', '-o', 'Port=22', '-o', 'KbdInteractiveAuthentication=no', '-o', 'PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey', '-o', 'PasswordAuthentication=no', '-o', 'User=vagrant', '-o', 'ConnectTimeout=10', '192.168.111.222', "/bin/sh -c 'mkdir -p /tmp/ansible-1381435783.27-235893717192946 && chmod a+rx /tmp/ansible-1381435783.27-235893717192946 && echo /tmp/ansible-1381435783.27-235893717192946'"]
<192.168.111.222> REMOTE_MODULE st_settings console_dir="/mnt/tracpoint/dev/staging/app"
env="prod"
debug="false"
setting="bundles:CommonBundle:database"
debug=false
<192.168.111.222> PUT /tmp/tmpBb03sb TO /tmp/ansible-1381435783.27-235893717192946/st_settings
<192.168.111.222> EXEC ['ssh', '-tt', '-vvv', '-o', 'ControlMaster=auto', '-o', 'ControlPersist=60s', '-o', 'ControlPath=/home/diego/.ansible/cp/ansible-ssh-%h-%p-%r', '-o', 'Port=22', '-o', 'KbdInteractiveAuthentication=no', '-o', 'PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey', '-o', 'PasswordAuthentication=no', '-o', 'User=vagrant', '-o', 'ConnectTimeout=10', '192.168.111.222', "/bin/sh -c 'chmod a+r /tmp/ansible-1381435783.27-235893717192946/st_settings'"]
<192.168.111.222> PUT /tmp/tmpkc11R_ TO /tmp/ansible-1381435783.27-235893717192946/arguments
<192.168.111.222> EXEC ['ssh', '-tt', '-vvv', '-o', 'ControlMaster=auto', '-o', 'ControlPersist=60s', '-o', 'ControlPath=/home/diego/.ansible/cp/ansible-ssh-%h-%p-%r', '-o', 'Port=22', '-o', 'KbdInteractiveAuthentication=no', '-o', 'PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey', '-o', 'PasswordAuthentication=no', '-o', 'User=vagrant', '-o', 'ConnectTimeout=10', '192.168.111.222', '/bin/sh -c \'sudo -k && sudo -H -S -p "[sudo via ansible, key=ebywpaaxjlugsexdhbqnocepzcembzzh] password: " -u tracpoint /bin/sh -c \'"\'"\'/usr/bin/php /tmp/ansible-1381435783.27-235893717192946/st_settings /tmp/ansible-1381435783.27-235893717192946/arguments\'"\'"\'\'']
</pre>




Discussion:
Can you supply a trivial hello world custom module that reproduces this problem?

Also, can we see the playbook you are using?

Sure:

**inventory**

<pre>
[vagrant]
192.168.111.222 ansible_ssh_user=vagrant
</pre>

**playbooks/arguments.yml**

<pre>
---
- hosts: vagrant
  sudo: yes
  sudo_user: tracpoint
  tasks:
    - name: "Test custom module"
      my_custom_module: first="1" second="2"
</pre>

**library/my_custom_module**

```
#!/usr/bin/php
<?php    
$argsFilename = $argv[1];

// Check that arguments file exists and is readable
$errorMsg = '';
if (!file_exists($argsFilename)) {
    $errorMsg = "arguments file $argsFilename does not exist";
}
elseif (!is_readable($argsFilename)) {
    $errorMsg = "could not read arguments file $argsFilename";
}

if ($errorMsg) {
    $result = array(
        "failed" => true,
        "msg" => $errorMsg
    );
    echo json_encode($result);
    exit(1);
}

// Success, return arguments
$arguments = file_get_contents($argv[1]);
$arguments = explode("\n", $arguments);

$result = array(
  'changed' => false,
  'passed_arguments' => $arguments
);

echo json_encode($result);
```

**To execute**

<pre>
 ansible-playbook playbooks/arguments.yml -i inventory
</pre>

**debug output**

<pre>
TASK: [Test custom module] **************************************************** 
<192.168.111.222> ESTABLISH CONNECTION FOR USER: vagrant
<192.168.111.222> EXEC ['ssh', '-tt', '-vvv', '-o', 'ControlMaster=auto', '-o', 'ControlPersist=60s', '-o', 'ControlPath=/home/diego/.ansible/cp/ansible-ssh-%h-%p-%r', '-o', 'Port=22', '-o', 'KbdInteractiveAuthentication=no', '-o', 'PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey', '-o', 'PasswordAuthentication=no', '-o', 'User=vagrant', '-o', 'ConnectTimeout=10', '192.168.111.222', "/bin/sh -c 'mkdir -p /tmp/ansible-1381453289.29-66873817793813 && chmod a+rx /tmp/ansible-1381453289.29-66873817793813 && echo /tmp/ansible-1381453289.29-66873817793813'"]
<192.168.111.222> REMOTE_MODULE my_custom_module first="1" second="2"
<192.168.111.222> PUT /tmp/tmpDSwR8O TO /tmp/ansible-1381453289.29-66873817793813/my_custom_module
<192.168.111.222> EXEC ['ssh', '-tt', '-vvv', '-o', 'ControlMaster=auto', '-o', 'ControlPersist=60s', '-o', 'ControlPath=/home/diego/.ansible/cp/ansible-ssh-%h-%p-%r', '-o', 'Port=22', '-o', 'KbdInteractiveAuthentication=no', '-o', 'PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey', '-o', 'PasswordAuthentication=no', '-o', 'User=vagrant', '-o', 'ConnectTimeout=10', '192.168.111.222', "/bin/sh -c 'chmod a+r /tmp/ansible-1381453289.29-66873817793813/my_custom_module'"]
<192.168.111.222> PUT /tmp/tmpNMGunA TO /tmp/ansible-1381453289.29-66873817793813/arguments
<192.168.111.222> EXEC ['ssh', '-tt', '-vvv', '-o', 'ControlMaster=auto', '-o', 'ControlPersist=60s', '-o', 'ControlPath=/home/diego/.ansible/cp/ansible-ssh-%h-%p-%r', '-o', 'Port=22', '-o', 'KbdInteractiveAuthentication=no', '-o', 'PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey', '-o', 'PasswordAuthentication=no', '-o', 'User=vagrant', '-o', 'ConnectTimeout=10', '192.168.111.222', '/bin/sh -c \'sudo -k && sudo -H -S -p "[sudo via ansible, key=ajcyfcfumpazqkmtwonkygwefcbxgrnd] password: " -u tracpoint /bin/sh -c \'"\'"\'/usr/bin/php /tmp/ansible-1381453289.29-66873817793813/my_custom_module /tmp/ansible-1381453289.29-66873817793813/arguments\'"\'"\'\'']
failed: [192.168.111.222] => {"failed": true}
msg: could not read arguments file /tmp/ansible-1381453289.29-66873817793813/arguments
FATAL: all hosts have already failed -- aborting
</pre>

**Arguments file permissions**

<pre>
-rw------- 1 vagrant vagrant 20 Oct 10 17:53 /tmp/ansible-1381453289.29-66873817793813/arguments
</pre>

**It works with if sudo_user=vagrant**
**playbooks/arguments.yml**

<pre>
---
- hosts: vagrant
  sudo: yes
  sudo_user: vagrant
  tasks:
    - name: "Test custom module"
      my_custom_module: first="1" second="2"
</pre>

_Result_

<pre>
TASK: [Test custom module] **************************************************** 
<192.168.111.222> ESTABLISH CONNECTION FOR USER: vagrant
<192.168.111.222> EXEC ['ssh', '-tt', '-vvv', '-o', 'ControlMaster=auto', '-o', 'ControlPersist=60s', '-o', 'ControlPath=/home/diego/.ansible/cp/ansible-ssh-%h-%p-%r', '-o', 'Port=22', '-o', 'KbdInteractiveAuthentication=no', '-o', 'PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey', '-o', 'PasswordAuthentication=no', '-o', 'User=vagrant', '-o', 'ConnectTimeout=10', '192.168.111.222', "/bin/sh -c 'mkdir -p /tmp/ansible-1381453612.59-222777789515699 && chmod a+rx /tmp/ansible-1381453612.59-222777789515699 && echo /tmp/ansible-1381453612.59-222777789515699'"]
<192.168.111.222> REMOTE_MODULE my_custom_module first="1" second="2"
<192.168.111.222> PUT /tmp/tmpS8eUQO TO /tmp/ansible-1381453612.59-222777789515699/my_custom_module
<192.168.111.222> EXEC ['ssh', '-tt', '-vvv', '-o', 'ControlMaster=auto', '-o', 'ControlPersist=60s', '-o', 'ControlPath=/home/diego/.ansible/cp/ansible-ssh-%h-%p-%r', '-o', 'Port=22', '-o', 'KbdInteractiveAuthentication=no', '-o', 'PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey', '-o', 'PasswordAuthentication=no', '-o', 'User=vagrant', '-o', 'ConnectTimeout=10', '192.168.111.222', "/bin/sh -c 'chmod a+r /tmp/ansible-1381453612.59-222777789515699/my_custom_module'"]
<192.168.111.222> PUT /tmp/tmpoyZIN_ TO /tmp/ansible-1381453612.59-222777789515699/arguments
<192.168.111.222> EXEC ['ssh', '-tt', '-vvv', '-o', 'ControlMaster=auto', '-o', 'ControlPersist=60s', '-o', 'ControlPath=/home/diego/.ansible/cp/ansible-ssh-%h-%p-%r', '-o', 'Port=22', '-o', 'KbdInteractiveAuthentication=no', '-o', 'PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey', '-o', 'PasswordAuthentication=no', '-o', 'User=vagrant', '-o', 'ConnectTimeout=10', '192.168.111.222', '/bin/sh -c \'sudo -k && sudo -H -S -p "[sudo via ansible, key=qjxrnercragwdooejcuspxmtgqqnjkwr] password: " -u vagrant /bin/sh -c \'"\'"\'/usr/bin/php /tmp/ansible-1381453612.59-222777789515699/my_custom_module /tmp/ansible-1381453612.59-222777789515699/arguments\'"\'"\'\'']
ok: [192.168.111.222] => {"changed": false, "passed_arguments": ["first=\"1\" second=\"2\""]}
</pre>


Resolving patch:
diff --git a/lib/ansible/runner/__init__.py b/lib/ansible/runner/__init__.py
--- a/lib/ansible/runner/__init__.py
+++ b/lib/ansible/runner/__init__.py
@@ -320,6 +320,11 @@ def _execute_module(self, conn, tmp, module_name, args,
             else:
                 argsfile = self._transfer_str(conn, tmp, 'arguments', args)
 
+            if self.sudo and self.sudo_user != 'root':
+                # deal with possible umask issues once sudo'ed to other user
+                cmd_args_chmod = "chmod a+r %s" % argsfile
+                self._low_level_exec_command(conn, cmd_args_chmod, tmp, sudoable=False)
+
             if async_jid is None:
                 cmd = "%s %s" % (remote_module_path, argsfile)
             else:


Test patch: