Last active
February 24, 2023 18:44
-
-
Save yacn/15256fbfd7a4ec19568f009e4a0255c7 to your computer and use it in GitHub Desktop.
Patch for Ruby's Etc module to avoid using C-extensions on modern hosts in GCE with oslogin enabled. Provided as-is, without warranty, express or implied.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# monkey patch Etc module to work around the segfault that occurs using when | |
# oslogin is enabled on newer systems (Debian 11+, Ubuntu 20.04+) | |
# https://github.com/chef/chef/issues/12993 | |
module PatchedEtc | |
def _getent(db, key, regex, schema, struct_klass, error_word = db) | |
info = `getent #{db} #{key}`.chomp | |
raise(ArgumentError, "can't find #{error_word} for #{key}") unless $?.success? | |
fn_schema = schema.map { |k, v| v.class == Class ? [k, _to_class_fn(v)] : [k, v] }.to_h | |
matches = info.match(regex) | |
init_vars = fn_schema.map { |k, fn| fn.call(matches[k]) } | |
struct_klass.new(*init_vars) | |
end | |
def _getent_passwd(key) | |
r = /(?<name>.+):(?<passwd>.+):(?<uid>\d+):(?<gid>\d+):(?<gecos>.+)?:(?<dir>.+):(?<shell>.+)/ | |
schema = { name: String, passwd: String, uid: Integer, gid: Integer, gecos: String, dir: String, shell: String } | |
_getent('passwd', key, r, schema, Etc::Passwd, 'user') | |
end | |
def _to_class_fn(klass) | |
->(v) { v.is_a?(klass) ? v : Object.send(klass.to_s.to_sym, v) } | |
end | |
def _getent_group(key) | |
r = /(?<name>.+):(?<passwd>.+):(?<gid>\d+):(?<mem>.+)?/ | |
schema = { | |
name: String, passwd: String, gid: Integer, | |
mem: ->(v) { v ? v.split(',') : [] }, | |
} | |
_getent('group', key, r, schema, Etc::Group) | |
end | |
def getgrgid(group_id) | |
_getent_group(group_id) | |
end | |
def getgrnam(name) | |
_getent_group(name) | |
end | |
def getlogin | |
ENV['USER'] | |
end | |
def getpwnam(name) | |
_getent_passwd(name) | |
end | |
def getpwuid(user_id) | |
_getent_passwd(user_id) | |
end | |
end | |
# gce_metadata is just a helper function to query the instance's metadata | |
# implementation is left as an exercise for the reader 😉 | |
def oslogin_enabled? | |
r = gce_metadata('attributes/enable-oslogin') | |
return false unless r | |
r.downcase == 'true' | |
end | |
module Etc | |
class << self | |
prepend PatchedEtc if Kernel.send(:oslogin_enabled?) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment