Repository: ansible/ansible

Issue:
validate does not set user/group on temp file
<!---
Verify first that your issue/request is not already reported on GitHub.
Also test if the latest release, and devel branch are affected too.
Always add information AFTER of these html comments.
-->

##### ISSUE TYPE
<!--- Pick one below and delete the rest -->
 - Bug Report

##### COMPONENT NAME
<!---
Insert below this comment the name of the module, plugin, task or feature.
Do not include extra details here, e.g. "vyos_command" not "the network module vyos_command" or the full path
-->
copy

##### ANSIBLE VERSION
<!--- Paste verbatim output from "ansible --version" between quotes below -->
```
ansible 2.4.2.0
  config file = /home/bbrzezinski@pracuj.local/ansible/ansible.cfg
  configured module search path = [u'/home/bbrzezinski@pracuj.local/ansible/custom_modules']
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.5 (default, Aug  4 2017, 00:39:18) [GCC 4.8.5 20150623 (Red Hat 4.8.5-16)]
```
##### CONFIGURATION
<!---
If using Ansible 2.4 or above, paste the results of "ansible-config dump --only-changed"
Otherwise, mention any settings you have changed/added/removed in ansible.cfg
(or using the ANSIBLE_* environment variables).
-->
```
DEFAULT_ASK_VAULT_PASS = True
DEFAULT_CALLBACK_WHITELIST = ['profile_tasks']
RETRY_FILES_ENABLED = False
```
##### OS / ENVIRONMENT
<!---
Mention the OS you are running Ansible from, and the OS you are
managing, or say "N/A" for anything that is not platform-specific.
Also mention the specific version of what you are trying to control,
e.g. if this is a network bug the version of firmware on the network device.
-->
N/A, reproductible on any version of Ansible
##### SUMMARY
<!--- Explain the problem briefly -->
This is similar to #3319 - validate in template module does not set user/group on temporary templated file, it's owned by the user ansible is run as. If validating command expects different user/group than the ansible user, such command will fail. 

This is rather easy to fix, I'll create PR shortly.
##### STEPS TO REPRODUCE
<!---
For bugs, show exactly how to reproduce the problem, using a minimal test-case.
For new features, show how the feature would be used.
-->
Run ansible as non-root and non-filebeat user.
<!--- Paste example playbooks or commands between quotes below -->
```yaml
- name: "Template filebeat config"
  template:
    src: "filebeat.yml.j2"
    dest: "/etc/filebeat/filebeat.yml"
    owner: root
    group: root
    validate: "/usr/share/filebeat/bin/filebeat -configtest -c %s"
```

<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->
Templated file gets validated.
##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->
Validating binary complains about file ownership.
<!--- Paste verbatim command output between quotes below -->
```
Exiting: error loading config file: config file ("filebeat.yml") must be
owned by the beat user (uid=501) or root
```

validate does not set user/group on temp file
<!---
Verify first that your issue/request is not already reported on GitHub.
Also test if the latest release, and devel branch are affected too.
Always add information AFTER of these html comments.
-->

##### ISSUE TYPE
<!--- Pick one below and delete the rest -->
 - Bug Report

##### COMPONENT NAME
<!---
Insert below this comment the name of the module, plugin, task or feature.
Do not include extra details here, e.g. "vyos_command" not "the network module vyos_command" or the full path
-->
copy

##### ANSIBLE VERSION
<!--- Paste verbatim output from "ansible --version" between quotes below -->
```
ansible 2.4.2.0
  config file = /home/bbrzezinski@pracuj.local/ansible/ansible.cfg
  configured module search path = [u'/home/bbrzezinski@pracuj.local/ansible/custom_modules']
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.5 (default, Aug  4 2017, 00:39:18) [GCC 4.8.5 20150623 (Red Hat 4.8.5-16)]
```
##### CONFIGURATION
<!---
If using Ansible 2.4 or above, paste the results of "ansible-config dump --only-changed"
Otherwise, mention any settings you have changed/added/removed in ansible.cfg
(or using the ANSIBLE_* environment variables).
-->
```
DEFAULT_ASK_VAULT_PASS = True
DEFAULT_CALLBACK_WHITELIST = ['profile_tasks']
RETRY_FILES_ENABLED = False
```
##### OS / ENVIRONMENT
<!---
Mention the OS you are running Ansible from, and the OS you are
managing, or say "N/A" for anything that is not platform-specific.
Also mention the specific version of what you are trying to control,
e.g. if this is a network bug the version of firmware on the network device.
-->
N/A, reproductible on any version of Ansible
##### SUMMARY
<!--- Explain the problem briefly -->
This is similar to #3319 - validate in template module does not set user/group on temporary templated file, it's owned by the user ansible is run as. If validating command expects different user/group than the ansible user, such command will fail. 

This is rather easy to fix, I'll create PR shortly.
##### STEPS TO REPRODUCE
<!---
For bugs, show exactly how to reproduce the problem, using a minimal test-case.
For new features, show how the feature would be used.
-->
Run ansible as non-root and non-filebeat user.
<!--- Paste example playbooks or commands between quotes below -->
```yaml
- name: "Template filebeat config"
  template:
    src: "filebeat.yml.j2"
    dest: "/etc/filebeat/filebeat.yml"
    owner: root
    group: root
    validate: "/usr/share/filebeat/bin/filebeat -configtest -c %s"
```

<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->
Templated file gets validated.
##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->
Validating binary complains about file ownership.
<!--- Paste verbatim command output between quotes below -->
```
Exiting: error loading config file: config file ("filebeat.yml") must be
owned by the beat user (uid=501) or root
```



Discussion:
Files identified in the description:
* [lib/ansible/modules/files/copy.py](https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/files/copy.py)

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

[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->
Files identified in the description:
* [lib/ansible/modules/files/copy.py](https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/files/copy.py)

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

[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->

Resolving patch:
diff --git a/lib/ansible/modules/files/copy.py b/lib/ansible/modules/files/copy.py
--- a/lib/ansible/modules/files/copy.py
+++ b/lib/ansible/modules/files/copy.py
@@ -302,6 +302,9 @@ def main():
     original_basename = module.params.get('original_basename', None)
     validate = module.params.get('validate', None)
     follow = module.params['follow']
+    mode = module.params['mode']
+    owner = module.params['owner']
+    group = module.params['group']
     remote_src = module.params['remote_src']
     checksum = module.params['checksum']
 
@@ -397,9 +400,12 @@ def main():
                 if validate:
                     # if we have a mode, make sure we set it on the temporary
                     # file source as some validations may require it
-                    # FIXME: should we do the same for owner/group here too?
                     if mode is not None:
                         module.set_mode_if_different(src, mode, False)
+                    if owner is not None:
+                        module.set_owner_if_different(src, owner, False)
+                    if group is not None:
+                        module.set_group_if_different(src, group, False)
                     if "%s" not in validate:
                         module.fail_json(msg="validate must contain %%s: %s" % (validate))
                     (rc, out, err) = module.run_command(validate % src)


Test patch: