diff --git a/.expeditor/buildkite/artifact.habitat.test.ps1 b/.expeditor/buildkite/artifact.habitat.test.ps1 index 9e8d6465..f657b666 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 = 'chef-cli' 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 00000000..00599425 --- /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/chef-cli.gemspec b/chef-cli.gemspec index 0a473c9c..99c65a4d 100644 --- a/chef-cli.gemspec +++ b/chef-cli.gemspec @@ -45,7 +45,7 @@ Gem::Specification.new do |gem| gem.add_dependency "minitar", "~> 1.0" gem.add_dependency "chef", ">= 18.0", "< 20.0" gem.add_dependency "solve", "> 2.0", "< 5.0" - gem.add_dependency "addressable", ">= 2.3.5", "< 2.9" + gem.add_dependency "addressable", ">= 2.9.0", "< 3.0" gem.add_dependency "cookbook-omnifetch", "~> 0.5" gem.add_dependency "diff-lcs", "~> 1.6" # Newer verions of chef-client require diff-lcs ~> 1.6 gem.add_dependency "pastel", "~> 0.7" # used for policyfile differ diff --git a/cleanup_lint_roller.rb b/cleanup_lint_roller.rb index dff36480..6d68f411 100644 --- a/cleanup_lint_roller.rb +++ b/cleanup_lint_roller.rb @@ -3,7 +3,7 @@ require "rubygems" # List of gems that ship with Gemfile.lock files that should be removed -GEMS_WITH_LOCKFILES = %w{lint_roller stackprof-webnav}.freeze +GEMS_WITH_LOCKFILES = %w{lint_roller stackprof-webnav chef-cli}.freeze def cleanup_gem_lockfile(gem_name) puts "Cleaning up #{gem_name} Gemfile.lock..." diff --git a/habitat/plan.ps1 b/habitat/plan.ps1 index 9850ed15..e33cf9ed 100644 --- a/habitat/plan.ps1 +++ b/habitat/plan.ps1 @@ -110,4 +110,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 } \ No newline at end of file diff --git a/habitat/plan.sh b/habitat/plan.sh index f7fdde12..198be56b 100644 --- a/habitat/plan.sh +++ b/habitat/plan.sh @@ -5,35 +5,41 @@ pkg_origin=chef ruby_pkg="core/ruby3_4" pkg_deps=(${ruby_pkg} core/coreutils core/libarchive) pkg_build_deps=( - core/make - core/sed - core/gcc - core/git - ) + core/make + core/sed + core/gcc + core/git +) pkg_bin_dirs=(bin) 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() { - ln -sf "$(pkg_interpreter_for core/ruby3_4 bin/ruby)" "$(pkg_interpreter_for core/coreutils bin/env)" + 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() { +do_build() { export GEM_HOME="$pkg_prefix/vendor" build_line "Setting GEM_PATH=$GEM_HOME" @@ -48,9 +54,10 @@ do_build() { ruby ./cleanup_lint_roller.rb ruby ./post-bundle-install.rb } + 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/" @@ -58,42 +65,58 @@ do_install() { build_line "Warning: NOTICE not found at $PLAN_CONTEXT/../NOTICE" fi - export GEM_HOME="$pkg_prefix/vendor" + export GEM_HOME="$pkg_prefix/vendor" build_line "Setting GEM_PATH=$GEM_HOME" export GEM_PATH="$GEM_HOME" gem install chef-cli-*.gem --no-document - set_runtime_env "GEM_PATH" "${pkg_prefix}/vendor" - wrap_ruby_bin - rm -rf $GEM_PATH/cache/ - rm -rf $GEM_PATH/bundler - rm -rf $GEM_PATH/doc -} -wrap_ruby_bin() { - local bin="$pkg_prefix/bin/$pkg_name" - local real_bin="$GEM_HOME/gems/chef-cli-${pkg_version}/bin/chef-cli" - 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 chef-cli with precise version pins" + "${pkg_prefix}/vendor/bin/appbundler" . "$pkg_prefix/bin" chef-cli + + 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/chef-cli" "$pkg_prefix/libexec/chef-cli" + cat < "$pkg_prefix/bin/chef-cli" #!$(pkg_path_for core/bash)/bin/bash set -e -# Set binary path that allows InSpec to use non-Hab pkg binaries -# Include Ruby bin directory so chef-cli exec can find gem, etc. export PATH="$(pkg_path_for ${ruby_pkg})/bin:/sbin:/usr/sbin:/usr/local/sbin:/usr/local/bin:/usr/bin:/bin:$pkg_prefix/vendor/bin:\$PATH" - -# Set library path for FFI-based gems (ffi-libarchive) to find native libraries 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" -# Set Ruby paths defined from 'do_setup_environment()' - export GEM_HOME="$pkg_prefix/vendor" - export GEM_PATH="$GEM_PATH" - -exec $(pkg_path_for ${ruby_pkg})/bin/ruby $real_bin \$@ +exec $(pkg_path_for ${ruby_pkg})/bin/ruby $pkg_prefix/libexec/chef-cli "\$@" EOF - chmod -v 755 "$bin" + chmod -v 755 "$pkg_prefix/bin/chef-cli" + + 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 -} \ No newline at end of file +} + +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 +}