Skip to content

external_node_v2.rb weirdness with Rubygems 2.7.3 #611

Closed
@antaflos

Description

@antaflos

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

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