From baf5b6d6f9befa9ce2877814f2169f348c6239bf Mon Sep 17 00:00:00 2001 From: Sachin Jain Date: Mon, 1 Jun 2026 18:06:59 +0530 Subject: [PATCH] fix: use appbundler and habitat scan fixes Mirror chef/chef-cli#341 changes in Ohai (excluding dependency updates). - Simplify Habitat install script usage in Buildkite artifact test - Update habitat plans to use appbundler-generated binstubs and runtime wrapper - Remove vendored .github directories to reduce scanner false positives - Generalize lockfile cleanup and add binstub patch helper Signed-off-by: Sachin Jain --- .../buildkite/artifact.habitat.test.ps1 | 22 +--- binstub_patch.rb | 4 + cleanup_lint_roller.rb | 19 ++-- habitat/plan.ps1 | 3 + habitat/plan.sh | 102 +++++++++++------- 5 files changed, 87 insertions(+), 63 deletions(-) create mode 100644 binstub_patch.rb diff --git a/.expeditor/buildkite/artifact.habitat.test.ps1 b/.expeditor/buildkite/artifact.habitat.test.ps1 index 9e0121a96..ce036db88 100755 --- a/.expeditor/buildkite/artifact.habitat.test.ps1 +++ b/.expeditor/buildkite/artifact.habitat.test.ps1 @@ -9,7 +9,6 @@ $env:HAB_BLDR_CHANNEL = 'base-2025' $env:HAB_REFRESH_CHANNEL = "base-2025" $env:CHEF_LICENSE = 'accept-no-persist' $env:HAB_LICENSE = 'accept-no-persist' -$HabitatVersion = if ($env:HAB_VERSION) { $env:HAB_VERSION } else { '1.6.1245' } $Plan = 'ohai' Write-Host "--- system details" @@ -28,20 +27,8 @@ function Stop-HabProcess { # Installing Habitat function Install-Habitat { - param( - [Parameter(Mandatory = $true)] - [string]$Version - ) - Write-Host "Downloading and installing Habitat version $Version..." - $installScriptUrl = 'https://raw.githubusercontent.com/habitat-sh/habitat/main/components/hab/install.ps1' - $installScriptPath = Join-Path $env:TEMP "hab-install-$Version.ps1" - Invoke-WebRequest -Uri $installScriptUrl -OutFile $installScriptPath - try { - & $installScriptPath -Version $Version - } - finally { - Remove-Item $installScriptPath -Force -ErrorAction SilentlyContinue - } + Write-Host "Downloading and installing Habitat..." + Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/habitat-sh/habitat/main/components/hab/install.ps1')) } try { @@ -64,7 +51,7 @@ catch { } } - Install-Habitat -Version $HabitatVersion + Install-Habitat Write-Host "******************************************************************" Write-Host "** What is My Hab Version after installation? $(hab --version)" Write-Host "******************************************************************" @@ -81,9 +68,6 @@ Write-Host "--- Generating fake origin key" hab origin key generate $env:HAB_ORIGIN Write-Host "--- Building $Plan" -Write-Host "******************************************************************" -Write-Host "** What is My Project Root as determined by git rev? $(git rev-parse --show-toplevel)" -Write-Host "******************************************************************" $project_root = "$(git rev-parse --show-toplevel)" Set-Location $project_root diff --git a/binstub_patch.rb b/binstub_patch.rb new file mode 100644 index 000000000..00599425f --- /dev/null +++ b/binstub_patch.rb @@ -0,0 +1,4 @@ +unless ENV["APPBUNDLER_ALLOW_RVM"] + ENV["APPBUNDLER_ALLOW_RVM"] = "true" + ENV["GEM_PATH"] = [File.expand_path(File.join(__dir__, "..", "vendor")), ENV["GEM_PATH"]].compact.join(File::PATH_SEPARATOR) +end diff --git a/cleanup_lint_roller.rb b/cleanup_lint_roller.rb index b29fba503..314b91d3b 100644 --- a/cleanup_lint_roller.rb +++ b/cleanup_lint_roller.rb @@ -1,12 +1,15 @@ #!/usr/bin/env ruby -# Removes stray Gemfile.lock shipped inside the lint_roller gem to appease scanners. +# Removes stray Gemfile.lock shipped inside gems to appease scanners. require "rubygems" -def cleanup_lint_roller_lockfile - puts "Cleaning up lint_roller Gemfile.lock..." - specs = Gem::Specification.find_all_by_name("lint_roller") +# List of gems that ship with Gemfile.lock files that should be removed +GEMS_WITH_LOCKFILES = %w{lint_roller stackprof-webnav ohai}.freeze + +def cleanup_gem_lockfile(gem_name) + puts "Cleaning up #{gem_name} Gemfile.lock..." + specs = Gem::Specification.find_all_by_name(gem_name) if specs.empty? - puts " No lint_roller gem installed" + puts " No #{gem_name} gem installed" return end @@ -15,13 +18,13 @@ def cleanup_lint_roller_lockfile if File.exist?(gemfile_lock_path) puts " Removing #{gemfile_lock_path}" File.delete(gemfile_lock_path) - puts " Successfully removed lint_roller Gemfile.lock" + puts " Successfully removed #{gem_name} Gemfile.lock" else puts " No Gemfile.lock found in #{spec.gem_dir}" end end rescue StandardError => e - warn " Warning: Failed to clean up lint_roller Gemfile.lock: #{e.message}" + warn " Warning: Failed to clean up #{gem_name} Gemfile.lock: #{e.message}" end -cleanup_lint_roller_lockfile +GEMS_WITH_LOCKFILES.each { |gem_name| cleanup_gem_lockfile(gem_name) } diff --git a/habitat/plan.ps1 b/habitat/plan.ps1 index 1ecbff6e6..47299d532 100644 --- a/habitat/plan.ps1 +++ b/habitat/plan.ps1 @@ -108,4 +108,7 @@ function Invoke-After { # Remove the byproducts of compiling gems with extensions Get-ChildItem $pkg_prefix/vendor/gems -Include @("gem_make.out", "mkmf.log", "Makefile") -File -Recurse ` | Remove-Item -Force + # Remove .github directories from vendored gems to avoid CVE false positives + Get-ChildItem $pkg_prefix/vendor/gems -Filter ".github" -Directory -Recurse ` + | Remove-Item -Recurse -Force } diff --git a/habitat/plan.sh b/habitat/plan.sh index e7dbd00ae..36c0e8804 100644 --- a/habitat/plan.sh +++ b/habitat/plan.sh @@ -19,41 +19,51 @@ pkg_deps=(${ruby_pkg} core/coreutils) pkg_svc_user=root do_setup_environment() { - build_line 'Setting GEM_HOME="$pkg_prefix/vendor"' - export GEM_HOME="$pkg_prefix/vendor" + push_runtime_env GEM_PATH "${pkg_prefix}/vendor" - build_line "Setting GEM_PATH=$GEM_HOME" - export GEM_PATH="$GEM_HOME" + set_runtime_env APPBUNDLER_ALLOW_RVM "true" # prevent appbundler from clearing out the carefully constructed runtime GEM_PATH + set_runtime_env LANG "en_US.UTF-8" + set_runtime_env LC_CTYPE "en_US.UTF-8" +} + +do_prepare() { + if [[ ! -f /usr/bin/env ]]; then + ln -s "$(pkg_interpreter_for core/coreutils bin/env)" /usr/bin/env + fi } pkg_version() { cat "$SRC_PATH/VERSION" } + do_before() { update_pkg_version } + do_unpack() { mkdir -pv "$HAB_CACHE_SRC_PATH/$pkg_dirname" cp -RT "$PLAN_CONTEXT"/.. "$HAB_CACHE_SRC_PATH/$pkg_dirname/" } + do_build() { - export GEM_HOME="$pkg_prefix/vendor" - - build_line "Setting GEM_PATH=$GEM_HOME" - export GEM_PATH="$GEM_HOME" - bundle config --local without integration deploy maintenance development debug - bundle config --local jobs 4 - bundle config --local retry 5 - bundle config --local silence_root_warning 1 - bundle install - ruby ./cleanup_lint_roller.rb - ruby ./post-bundle-install.rb - gem build ohai.gemspec + export GEM_HOME="$pkg_prefix/vendor" + + build_line "Setting GEM_PATH=$GEM_HOME" + export GEM_PATH="$GEM_HOME" + bundle config --local without integration deploy maintenance development debug + bundle config --local jobs 4 + bundle config --local retry 5 + bundle config --local silence_root_warning 1 + bundle install + ruby ./cleanup_lint_roller.rb + ruby ./post-bundle-install.rb + gem build ohai.gemspec } + do_install() { - # Copy NOTICE.TXT to the package directory + # Copy NOTICE to the package directory if [[ -f "$PLAN_CONTEXT/../NOTICE" ]]; then build_line "Copying NOTICE to package directory" cp "$PLAN_CONTEXT/../NOTICE" "$pkg_prefix/" @@ -66,33 +76,53 @@ do_install() { build_line "Setting GEM_PATH=$GEM_HOME" export GEM_PATH="$GEM_HOME" gem install ohai-*.gem --no-document - set_runtime_env "GEM_PATH" "${pkg_prefix}/vendor" - wrap_ruby_bin - rm -rf $GEM_PATH/bundler - rm -rf $GEM_PATH/cache - rm -rf $GEM_PATH/doc -} -wrap_ruby_bin() { - local bin="$pkg_prefix/bin/$pkg_name" - local real_bin="$GEM_HOME/gems/ohai-${pkg_version}/bin/ohai" - build_line "Adding wrapper $bin to $real_bin" - cat < "$bin" + ruby ./cleanup_lint_roller.rb + + build_line "** fixing binstub shebangs" + fix_interpreter "${pkg_prefix}/vendor/bin/*" "$ruby_pkg" bin/ruby + + build_line "** generating binstubs for ohai with precise version pins" + "${pkg_prefix}/vendor/bin/appbundler" . "$pkg_prefix/bin" ohai + + build_line "** patching binstubs to allow running directly" + for binstub in ${pkg_prefix}/bin/*; do + sed -i "/require \"rubygems\"/r ${PLAN_CONTEXT}/../binstub_patch.rb" "$binstub" + done + + build_line "** creating wrapper for runtime environment" + mkdir -p "$pkg_prefix/libexec" + mv "$pkg_prefix/bin/ohai" "$pkg_prefix/libexec/ohai" + cat < "$pkg_prefix/bin/ohai" #!$(pkg_path_for core/bash)/bin/bash set -e -# Set binary path that allows Ohai to use non-Hab pkg binaries -export PATH="/sbin:/usr/sbin:/usr/local/sbin:/usr/local/bin:/usr/bin:/bin:\$PATH" - -# Set Ruby paths defined from 'do_setup_environment()' - export GEM_HOME="$pkg_prefix/vendor" - export GEM_PATH="$GEM_PATH" +export PATH="$(pkg_path_for ${ruby_pkg})/bin:/sbin:/usr/sbin:/usr/local/sbin:/usr/local/bin:/usr/bin:/bin:\$PATH" +export LD_LIBRARY_PATH="$(pkg_path_for core/libarchive)/lib:\$LD_LIBRARY_PATH" +export GEM_HOME="$pkg_prefix/vendor" +export GEM_PATH="$pkg_prefix/vendor" -exec $(pkg_path_for ${ruby_pkg})/bin/ruby $real_bin \$@ +exec $(pkg_path_for ${ruby_pkg})/bin/ruby $pkg_prefix/libexec/ohai "\$@" EOF - chmod -v 755 "$bin" + chmod -v 755 "$pkg_prefix/bin/ohai" + + rm -rf $GEM_PATH/cache/ + rm -rf $GEM_PATH/bundler + rm -rf $GEM_PATH/doc } +do_after() { + build_line "Removing .github directories from vendored gems..." + find "$pkg_prefix/vendor/gems" -type d -name ".github" \ + | while read github_dir; do rm -rf "$github_dir"; done +} do_strip() { return 0 } + +do_end() { + if [[ "$(readlink /usr/bin/env)" = "$(pkg_interpreter_for core/coreutils bin/env)" ]]; then + build_line "Removing the symlink we created for '/usr/bin/env'" + rm /usr/bin/env + fi +}