[PUP-8983] validate_cmd creates tmp file with inconsistent permissions Created: 2018/07/05  Updated: 2019/09/30  Resolved: 2019/05/02

Status: Resolved
Project: Puppet
Component/s: Types and Providers
Affects Version/s: None
Fix Version/s: PUP 6.5.0

Type: Bug Priority: Normal
Reporter: john Assignee: Jacob Helwig
Resolution: Fixed Votes: 0
Labels: resolved-issue-added
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Template: PUP Bug Template
Team: Coremunity
Sprint: Platform Core KANBAN
Method Found: Needs Assessment
Release Notes: Bug Fix
Release Notes Summary: If there is a `validate_cmd` for a File resource, the command will be run with the temporary after the temporary file has had the final permissions set (on POSIX platforms).
QA Risk Assessment: Needs Assessment


Puppet Version: 5.5.0
Puppet Server Version: NA
OS Name/Version: Linux & Mc OSX confirmed

When the validate_cmd runs it creates a temporary file however the permissions it assigns to this temporary file are not related to the permissions defined on the file type object. 

Desired Behaviour:

The temporary file used when running the validate command should have the exact same permissions as the file resources it is trying to create.  e.g. 

with a file type of

file {'/tmp/test':
   owner => 'foo',
   group => 'bar',
   mode  => '0555',
   validate_cmd => 'test -x %'

the tmpe file created should have `foo:bar 0555` permissions

Actual Behavior:

I have observed the following behaviour.

  • tmp files are always created with permissions `0600`
  • if the file being managed does not exist the tmp file is owned by root
  • if the file being managed the tmp file uses has the same owner as the file being managed on disk

the following runs a loop to detect the how the tmp file is created.  the tests use the folloing manifest file

file {'/tmp/test/test':
  ensure => file,
  owner => 'jbond',
  group => 'jbond',
  content => 'foobar',
  validate_cmd => '/bin/false ',

output when `/tmp/test/test` doesn't exist

root@dev:~# ls -la /tmp/test/
total 8
drwxr-xr-x  2 root root 4096 Jul  5 16:40 .
drwxrwxrwt 11 root root 4096 Jul  5 16:41 ..
root@dev01.l:~# while true ; do ls -l /tmp/test/ | grep test ; done
-rw------- 1 root root 6 Jul  5 16:41 test20180705-24634-jluwct

output when file exists with correct permissions

root@dev01.l:~# ls -la /tmp/test/test
-rw-r--r-- 1 jbond jbond 0 Jul  5 16:42 /tmp/test/test
root@dev:~# while true ; do ls -l /tmp/test/ | grep test | egrep -v 'test$'; done
-rw------- 1 jbond jbond 6 Jul  5 16:43 test20180705-5929-sdmjsa

output when file exists with correct incorrect permissions

root@dev~# chown nsd:nsd /tmp/test/test
root@dev:~# ls -la !$
ls -la /tmp/test/test
-rw-r--r-- 1 nsd nsd 0 Jul  5 16:42 /tmp/test/test
root@dev:~# while true ; do ls -l /tmp/test/ | grep test | egrep -v 'test$'; done
-rw------- 1 nsd nsd 6 Jul  5 16:43 test20180705-22012-13alhap

This causes problems when the validate command drops previlages or needs to run as a specific user.  An example of this is  using `/usr/lib/quagga/bgpd` to validate quagga files.  The command by default drops privileges to the quagga user before reading the config file.  if the file is owned by anything other then quagga then the validate command fails.  


  • note the bgpd command does take a user parameter so you can run the tests as the root user.  however bgpd still drops privileges to the root user and when it does so it does so without `CAP_DAV_OVERRIDE`.  meaning that even the root user can only validate files owned by root



Comment by john [ 2018/07/05 ]

re-ran the tests specifying a mode on the file type on the results are the same, i.e. the mode of the temp file is not set to the `should` state

file {'/tmp/test/test':
  ensure => file,
  owner => 'jbond',
  group => 'jbond',
  mode => '0555',
  content => 'foobar',
  validate_cmd => '/bin/false ',

root@dev:~# while true ; do ls -l /tmp/test/ | grep test ; done
-rw------- 1 root root 6 Jul  5 18:53 test20180705-18902-1r3rv8u
root@dev:~# touch /tmp/test/test
root@dev:~# chown jbond:jbond !$
chown jbond:jbond /tmp/test/test
root@dev:~# while true ; do ls -l /tmp/test/ | grep test | egrep -v 'test$' ; done
-rw------- 1 root  root  0 Jul  5 18:57 test20180705-27813-1ru0o33
-rw------- 1 jbond jbond 6 Jul  5 18:57 test20180705-27813-1ru0o33
root@dev:~# chown nsd:nsd /tmp/test/test
root@dev:~# while true ; do ls -l /tmp/test/ | grep test | egrep -v 'test$' ; done
-rw------- 1 nsd nsd 6 Jul  5 18:58 test20180705-25855-128546l

Comment by john [ 2018/07/05 ]

I have attempted a fix for this.  It is not a complete fix as the mode is not maintained.  Further the uid/gid of the file on disk still takes preference over the `should` values.

Comment by Josh Cooper [ 2019/05/01 ]

Merged to master in https://github.com/puppetlabs/puppet/commit/eb19bedb221959bd202e598401a3d29ea77950c9

Comment by Mark Nejedlo [ 2019/09/27 ]

Please backport this change to puppet-agent 5.5.x

Comment by Josh Cooper [ 2019/09/30 ]

Mark Nejedlo I filed the backport as PUP-10055

Generated at Sun Sep 27 15:01:18 PDT 2020 using Jira 8.5.2#805002-sha1:a66f9354b9e12ac788984e5d84669c903a370049.