[PUP-7375] Puppet does not change file to directory when selinux is enabled Created: 2017/03/20  Updated: 2018/07/23

Status: Accepted
Project: Puppet
Component/s: None
Affects Version/s: None
Fix Version/s: PUP 5.y

Type: Bug Priority: Normal
Reporter: Martin Alfke Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: file, linux, selinux, type_and_provider
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

Fresh installation (no upgrade) of PE 2017.1.0 running on CentOS 7


Attachments: Text File puppet_apply_debug.txt    
Template:
Acceptance Criteria:

Puppet changes file to a directory

Team: Platform OS
QA Risk Assessment: Needs Assessment

 Description   

When having a file on the system (touch /tmp/foo)
and mananging this file from puppet as a directory, puppet will not convert the file to a directory.
e.g.

class demo {
  File {
    owner => 'root',
    group => 'root',
    mode  => '0644',
  }
  file { '/tmp/foo':
    ensure => directory,
  }
  file { '/tmp/foo/bar':
    ensure => file,
  }
}



 Comments   
Comment by Josh Cooper [ 2017/03/20 ]

Hi Martin Alfke, I'm not able to reproduce:

# puppet --version
4.9.4
# touch /tmp/foo
# cat manifest.pp
  File {
    owner => 'root',
    group => 'root',
    mode  => '0644',
  }
  file { '/tmp/foo':
    ensure => directory,
  }
  file { '/tmp/foo/bar':
    ensure => file,
  }
# puppet apply manifest.pp
Notice: Compiled catalog for XXX.puppetlabs.net in environment production in 0.08 seconds
Notice: /Stage[main]/Main/File[/tmp/foo]/ensure: ensure changed 'file' to 'directory'
Notice: /Stage[main]/Main/File[/tmp/foo/bar]/ensure: created
Notice: Applied catalog in 0.08 seconds
# ls -la /tmp/foo/
total 4
drwxr-xr-x  2 root root   16 Mar 20 19:02 .
drwxrwxrwt. 9 root root 4096 Mar 20 19:02 ..
-rw-r--r--  1 root root    0 Mar 20 19:02 bar

Is SELinux enabled? Is /tmp a local filesystem or mounted specially?

Comment by Martin Alfke [ 2017/03/20 ]

selinux is enabled:

[root@puppet ~]# selinuxenabled
[root@puppet ~]# echo $?
0

/tmp is on / filesystem

[root@puppet ~]# mount -v | grep /tmp
[root@puppet ~]# mount -v | grep 'on / '
/dev/mapper/VolGroup00-LogVol00 on / type xfs (rw,relatime,seclabel,attr2,inode64,noquota)

stat utility shows the following information for /tmp/foo:

stat /tmp/foo
  File: ‘/tmp/foo’
  Size: 0         	Blocks: 0          IO Block: 4096   regular empty file
Device: fd00h/64768d	Inode: 101504842   Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Context: unconfined_u:object_r:user_tmp_t:s0
Access: 2017-03-20 06:34:42.247636602 +0100
Modify: 2017-03-20 01:48:20.234467721 +0100
Change: 2017-03-20 01:48:20.234467721 +0100
 Birth: -

Comment by Martin Alfke [ 2017/03/20 ]

puppet.conf file:

# This file can be used to override the default puppet settings.
# See the following links for more details on what settings are available:
# - https://docs.puppetlabs.com/puppet/latest/reference/config_important_settings.html
# - https://docs.puppetlabs.com/puppet/latest/reference/config_about_settings.html
# - https://docs.puppetlabs.com/puppet/latest/reference/config_file_main.html
# - https://docs.puppetlabs.com/puppet/latest/reference/configuration.html
 
[main]
certname = puppet.pe.psick.io
server = puppet.pe.psick.io
user = pe-puppet
group = pe-puppet
environment_timeout = 0
app_management = true
module_groups = base+pe_only
 
[agent]
graph = true
 
[master]
node_terminus = classifier
storeconfigs = true
storeconfigs_backend = puppetdb
reports = puppetdb
certname = puppet.pe.psick.io
always_cache_features = true

Comment by Martin Alfke [ 2017/03/20 ]

[root@puppet ~]# cat /etc/sysconfig/selinux
 
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
SELINUX=enforcing
# SELINUXTYPE= can take one of three two values:
#     targeted - Targeted processes are protected,
#     minimum - Modification of targeted policy. Only selected processes are protected.
#     mls - Multi Level Security protection.
SELINUXTYPE=targeted

Comment by Martin Alfke [ 2017/03/20 ]

Output from puppet apply --debug --color=no

Comment by Josh Cooper [ 2017/03/20 ]

I can reproduce as well with selinux enabled. I don't believe anything has changed recently in this area, so probably has been an issue for a few releases. I'll try to bisect, but for now here's what I get:

# selinuxenabled
# echo $?
0
# cat /etc/sysconfig/selinux
 
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
SELINUX=enforcing
# SELINUXTYPE= can take one of three two values:
#     targeted - Targeted processes are protected,
#     minimum - Modification of targeted policy. Only selected processes are protected.
#     mls - Multi Level Security protection.
SELINUXTYPE=targeted
 
# puppet --version
4.9.4
# touch /tmp/foo
# cat manifest.pp
  File {
    owner => 'root',
    group => 'root',
    mode  => '0644',
  }
  file { '/tmp/foo':
    ensure => directory,
  }
  file { '/tmp/foo/bar':
    ensure => file,
  }
# puppet apply manifest.pp --trace
Notice: Compiled catalog for XXX.puppetlabs.net in environment production in 0.08 seconds
Error: Not a directory @ rb_file_s_lstat - /tmp/foo/bar
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/file_system/file_impl.rb:144:in `lstat'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/file_system/file_impl.rb:144:in `lstat'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/file_system.rb:317:in `lstat'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/util/selinux.rb:219:in `file_lstat'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/util/selinux.rb:45:in `get_selinux_default_context'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/type/file/selcontext.rb:40:in `retrieve_default_context'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/type/file/selcontext.rb:86:in `block (2 levels) in <module:Puppet>'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/type.rb:834:in `set_default'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/type.rb:2493:in `block in set_parameters'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/type.rb:2492:in `each'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/type.rb:2492:in `set_parameters'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/type.rb:2389:in `initialize'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/type/file.rb:491:in `initialize'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/resource.rb:488:in `new'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/resource.rb:488:in `to_ral'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/resource/catalog.rb:640:in `block in to_catalog'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/resource/catalog.rb:632:in `each'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/resource/catalog.rb:632:in `to_catalog'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/resource/catalog.rb:513:in `to_ral'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/application/apply.rb:263:in `block in main'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/context.rb:65:in `override'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet.rb:293:in `override'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/application/apply.rb:225:in `main'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/application/apply.rb:170:in `run_command'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/application.rb:344:in `block in run'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/util.rb:541:in `exit_on_fail'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/application.rb:344:in `run'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/util/command_line.rb:132:in `run'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/util/command_line.rb:72:in `execute'

Comment by Martin Alfke [ 2017/03/20 ]

trace output:

Notice: Compiled catalog for puppet.pe.psick.io in environment production in 0.26 seconds
Error: Not a directory @ rb_file_s_lstat - /tmp/foo/bar
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/file_system/file_impl.rb:144:in `lstat'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/file_system/file_impl.rb:144:in `lstat'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/file_system.rb:317:in `lstat'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/util/selinux.rb:219:in `file_lstat'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/util/selinux.rb:45:in `get_selinux_default_context'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/type/file/selcontext.rb:40:in `retrieve_default_context'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/type/file/selcontext.rb:86:in `block (2 levels) in <module:Puppet>'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/type.rb:834:in `set_default'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/type.rb:2493:in `block in set_parameters'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/type.rb:2492:in `each'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/type.rb:2492:in `set_parameters'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/type.rb:2389:in `initialize'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/type/file.rb:491:in `initialize'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/resource.rb:488:in `new'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/resource.rb:488:in `to_ral'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/resource/catalog.rb:640:in `block in to_catalog'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/resource/catalog.rb:632:in `each'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/resource/catalog.rb:632:in `to_catalog'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/resource/catalog.rb:513:in `to_ral'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/application/apply.rb:263:in `block in main'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/context.rb:65:in `override'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet.rb:293:in `override'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/application/apply.rb:225:in `main'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/application/apply.rb:170:in `run_command'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/application.rb:344:in `block in run'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/util.rb:541:in `exit_on_fail'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/application.rb:344:in `run'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/util/command_line.rb:132:in `run'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/util/command_line.rb:72:in `execute'
/opt/puppetlabs/puppet/bin/puppet:5:in `<main>'

Note: disabling selinux gives the expected result!

Comment by Josh Cooper [ 2017/03/20 ]

I am not able to reproduce when using ruby 2.1.9 installed via rbenv:

# yum install -y git-core zlib zlib-devel gcc-c++ patch readline readline-devel libyaml-devel libffi-devel openssl-devel make bzip2 autoconf automake libtool bison curl sqlite-devel
# cd
# git clone git://github.com/sstephenson/rbenv.git .rbenv
# echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
# echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
# source ~/.bash_profile
# git clone git://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
# echo 'export PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"' >> ~/.bash_profile
# source ~/.bash_profile
# rbenv install -v 2.1.9
...
# rbenv local 2.1.9
# ruby --version
ruby 2.1.9p490 (2016-03-30 revision 54437) [x86_64-linux]
# gem install --no-ri --no-rdoc bundler
# git clone git://github.com/puppetlabs/puppet
# cd puppet
# git checkout 4.9.4
# bundle install --path .bundle --without development extra
# rm -rf /tmp/foo/
# touch /tmp/foo
# bundle exec puppet apply ../manifest.pp
Notice: Compiled catalog for XXX.puppetlabs.net in environment production in 0.09 seconds
Notice: /Stage[main]/Main/File[/tmp/foo]/ensure: ensure changed 'file' to 'directory'
Notice: /Stage[main]/Main/File[/tmp/foo/bar]/ensure: created
Notice: Applied catalog in 0.05 seconds

But

# rm -rf /tmp/foo/
# touch /tmp/foo
# /opt/puppetlabs/puppet/bin/puppet apply ../manifest.pp
Notice: Compiled catalog for kj2yriin8cxx02i.delivery.puppetlabs.net in environment production in 0.08 seconds
Error: Not a directory @ rb_file_s_lstat - /tmp/foo/bar

Comment by Josh Cooper [ 2017/03/20 ]

This is a regression from puppet-agent 1.8.3:

# which puppet
/opt/puppetlabs/bin/puppet
# puppet --version
4.8.2
# /opt/puppetlabs/puppet/bin/ruby --version
ruby 2.1.9p490 (2016-03-30 revision 54437) [x86_64-linux]
# rm -rf /tmp/foo/
# touch /tmp/foo
# cat manifest.pp
 File {
    owner => 'root',
    group => 'root',
    mode  => '0644',
  }
  file { '/tmp/foo':
    ensure => directory,
  }
  file { '/tmp/foo/bar':
    ensure => file,
  }
# puppet apply manifest.pp
Notice: Compiled catalog for XXX.puppetlabs.net in environment production in 0.08 seconds
Notice: /Stage[main]/Main/File[/tmp/foo]/ensure: ensure changed 'file' to 'directory'
Notice: /Stage[main]/Main/File[/tmp/foo/bar]/ensure: created
Notice: Applied catalog in 0.05 seconds

Comment by Sean McDonald [ 2017/03/20 ]

After investigating further, it turns out this functionality is actually broken for every agent back to 1.0.1 0.2.4

Comment by Melissa Stone [ 2018/06/20 ]

I was able to reproduce this with puppet-agent 5.5.3.260.ge0ad970 and the included ruby 2.4.4

[root@bi040qter7lkjw5 ~]# selinuxenabled ; echo $?
0
[root@bi040qter7lkjw5 ~]# sestatus
SELinux status:                 enabled
SELinuxfs mount:                /sys/fs/selinux
SELinux root directory:         /etc/selinux
Loaded policy name:             targeted
Current mode:                   enforcing
Mode from config file:          enforcing
Policy MLS status:              enabled
Policy deny_unknown status:     allowed
Max kernel policy version:      31
[root@bi040qter7lkjw5 ~]# cat /etc/sysconfig/selinux
 
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
SELINUX=enforcing
# SELINUXTYPE= can take one of three two values:
#     targeted - Targeted processes are protected,
#     minimum - Modification of targeted policy. Only selected processes are protected.
#     mls - Multi Level Security protection.
SELINUXTYPE=targeted
 
 
[root@bi040qter7lkjw5 ~]# puppet --version
6.0.0
[root@bi040qter7lkjw5 ~]# /opt/puppetlabs/puppet/bin/ruby --version
ruby 2.4.4p296 (2018-03-28 revision 63013) [x86_64-linux]
[root@bi040qter7lkjw5 ~]# stat /tmp/foo
  File: ‘/tmp/foo’
  Size: 0         	Blocks: 0          IO Block: 4096   regular empty file
Device: fd00h/64768d	Inode: 101596055   Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Context: unconfined_u:object_r:user_tmp_t:s0
Access: 2018-06-20 16:49:24.252725530 +0000
Modify: 2018-06-20 16:49:24.252725530 +0000
Change: 2018-06-20 16:49:24.252725530 +0000
 Birth: -
[root@bi040qter7lkjw5 ~]# cat manifest.pp
  File {
    owner => 'root',
    group => 'root',
    mode  => '0644',
  }
  file { '/tmp/foo':
    ensure => directory,
  }
  file { '/tmp/foo/bar':
    ensure => file,
  }
[root@bi040qter7lkjw5 ~]# puppet apply manifest.pp --trace
Notice: Compiled catalog for bi040qter7lkjw5.delivery.puppetlabs.net in environment production in 0.02 seconds
Error: Not a directory @ rb_file_s_lstat - /tmp/foo/bar
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/file_system/file_impl.rb:144:in `lstat'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/file_system/file_impl.rb:144:in `lstat'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/file_system.rb:317:in `lstat'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/util/selinux.rb:261:in `file_lstat'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/util/selinux.rb:45:in `get_selinux_default_context'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/type/file/selcontext.rb:45:in `retrieve_default_context'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/type/file/selcontext.rb:103:in `block (2 levels) in <module:Puppet>'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/type.rb:835:in `set_default'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/type.rb:2508:in `block in set_parameters'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/type.rb:2507:in `each'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/type.rb:2507:in `set_parameters'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/type.rb:2396:in `initialize'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/type/file.rb:490:in `initialize'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/resource.rb:461:in `new'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/resource.rb:461:in `to_ral'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/resource/catalog.rb:643:in `block in to_catalog'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/resource/catalog.rb:635:in `each'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/resource/catalog.rb:635:in `to_catalog'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/resource/catalog.rb:516:in `to_ral'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/application/apply.rb:269:in `block in main'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/context.rb:65:in `override'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet.rb:251:in `override'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/application/apply.rb:233:in `main'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/application/apply.rb:174:in `run_command'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/application.rb:382:in `block in run'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/util.rb:666:in `exit_on_fail'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/application.rb:382:in `run'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/util/command_line.rb:137:in `run'
/opt/puppetlabs/puppet/lib/ruby/vendor_ruby/puppet/util/command_line.rb:73:in `execute'
/opt/puppetlabs/puppet/bin/puppet:5:in `<main>'

Generated at Fri Oct 18 21:10:35 PDT 2019 using JIRA 7.7.1#77002-sha1:e75ca93d5574d9409c0630b81c894d9065296414.