Skip to content

external_node_v2.rb weirdness with Rubygems 2.7.3 #611

Closed
@antaflos

Description

Something changed sometime between Rubygems 2.4.5 and 2.7.3 in the way require works with regards to the current working directory. This leads to the following error when running external_node_v2.rb --push-facts when the current working directory is /root under Rubygems 2.7.3:

Could not generate facts for Foreman: Permission denied @ dir_chdir - /root

This is usually the case when the external_node_v2.rb script is started from Cron. We run Puppet 5 so the facter Gem is usually not available in the regular, system-wide Ruby/Gem environment. The script trips up when trying to require 'facter'; this should normally fail with a LoadError that is then rescued, but another exception from rubygems/util.rb occurs (with the above error message) that is not rescued.

Here is a test script with the relevant parts external_node_v2.rb from that reproduces the problem:

#!/usr/bin/env ruby

require 'etc'

puppetuser = 'puppet'

begin
  Process::GID.change_privilege(Etc.getgrnam(puppetuser).gid) unless Etc.getpwuid.name == puppetuser
  Process::UID.change_privilege(Etc.getpwnam(puppetuser).uid) unless Etc.getpwuid.name == puppetuser
  # Facter (in thread_count) tries to read from $HOME, which is still /root after the UID change
  ENV['HOME'] = Etc.getpwnam(puppetuser).dir
rescue
  $stderr.puts "cannot switch to user #{puppetuser}, continuing as '#{Etc.getpwuid.name}'"
end

begin
  require 'facter'
  puts "facter: " + Facter.value(:fqdn).to_s
rescue LoadError
  puts "no facter: " + `hostname -f`.strip
end

Run this script as root with Rubygems 2.7.3 while residing in the /root directory and the problem surfaces like this:

root@host01 [/root] # ./test.rb 
/usr/local/lib/site_ruby/2.3.0/rubygems/util.rb:117:in `chdir': Permission denied @ dir_chdir - /root (Errno::EACCES)
        from /usr/local/lib/site_ruby/2.3.0/rubygems/util.rb:117:in `block in traverse_parents'
        from /usr/local/lib/site_ruby/2.3.0/rubygems/util.rb:116:in `loop'
        from /usr/local/lib/site_ruby/2.3.0/rubygems/util.rb:116:in `traverse_parents'
        from /usr/local/lib/site_ruby/2.3.0/rubygems/bundler_version_finder.rb:93:in `lockfile_contents'
        from /usr/local/lib/site_ruby/2.3.0/rubygems/bundler_version_finder.rb:81:in `lockfile_version'
        from /usr/local/lib/site_ruby/2.3.0/rubygems/bundler_version_finder.rb:29:in `bundler_version_with_reason'
        from /usr/local/lib/site_ruby/2.3.0/rubygems/bundler_version_finder.rb:12:in `bundler_version'
        from /usr/local/lib/site_ruby/2.3.0/rubygems/bundler_version_finder.rb:46:in `compatible?'
        from /usr/local/lib/site_ruby/2.3.0/rubygems/specification.rb:1059:in `block in find_by_path'
        from /usr/local/lib/site_ruby/2.3.0/rubygems/specification.rb:1058:in `each'
        from /usr/local/lib/site_ruby/2.3.0/rubygems/specification.rb:1058:in `find'
        from /usr/local/lib/site_ruby/2.3.0/rubygems/specification.rb:1058:in `find_by_path'
        from /usr/local/lib/site_ruby/2.3.0/rubygems.rb:213:in `try_activate'
        from /usr/local/lib/site_ruby/2.3.0/rubygems/core_ext/kernel_require.rb:128:in `rescue in require'
        from /usr/local/lib/site_ruby/2.3.0/rubygems/core_ext/kernel_require.rb:40:in `require'
        from ./test.rb:15:in `<main>'

The problem does not occur with Rubygems 2.4.5. I haven't tested other versions yet.

I don't know if this is a bug in Rubygems that should be addressed there but external_node_v2.rb can be fixed easily by adding the line Dir.chdir ENV['HOME'] after setting ENV['HOME']. I think this should be done anyway, regardless of any change in Rubygems' behaviour, to be on the safe side.

I'll submit a PR for this.

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions