Skip to content

Commit

Permalink
Build OpenSSL 3.0.9 with FIPS (1.0.2zi for Windows)
Browse files Browse the repository at this point in the history
* add FIPS validation for Windows and non-Windows
* add tests for openssl and FIPS

Signed-off-by: Thomas Powell <[email protected]>
  • Loading branch information
tpowell-progress committed May 24, 2024
1 parent 48daca2 commit 81d1b23
Show file tree
Hide file tree
Showing 11 changed files with 246 additions and 22 deletions.
4 changes: 3 additions & 1 deletion .expeditor/release.omnibus.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ test-path-windows: omnibus-test.ps1
fips-platforms:
- el-*-x86_64
- el-*-ppc64*
- ubuntu-*-x86_64
- el-*-aarch*
- ubuntu-*
- windows-*
- amazon-2023-*
skip-artifactory-platforms:
- freebsd-13-amd64
windows-64-msystem: UCRT64
Expand Down
4 changes: 4 additions & 0 deletions .expeditor/run_linux_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ export LANG=C.UTF-8 LANGUAGE=C.UTF-8

echo "--- bundle install"

if [ "$OMNIBUS_FIPS_MODE" = "true" ]; then
export OPENSSL_FIPS=1
fi

bundle config --local path vendor/bundle
bundle config set --local without development
bundle install --jobs=7 --retry=3
Expand Down
8 changes: 7 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@ gem "artifactory"

gem "pedump"

gem "chefstyle"
gem "cookstyle"

# This is to help patch in openssl for Ruby 3.0.x, since Ruby 3.0 uses OpenSSL <3.0
# unless you build without and reintroduce it manually.
# Remove once we're no longer supporting Ruby 3.0.x.
# Also, fips_mode may need it
gem "openssl", "= 3.2.0"

# This development group is installed by default when you run `bundle install`,
# but if you are using Omnibus in a CI-based infrastructure, you do not need
Expand Down
23 changes: 13 additions & 10 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ GEM
net-sftp (>= 2.1.2, < 5.0)
ohai (~> 18.0)
plist (~> 3.2)
proxifier2 (~> 1.1)
proxifier (~> 1.0)
syslog-logger (~> 1.6)
train-core (~> 3.10)
train-rest (>= 0.4.1)
Expand Down Expand Up @@ -172,13 +172,13 @@ GEM
rack (~> 2.0, >= 2.0.6)
uuidtools (~> 2.1)
webrick
chefstyle (2.2.3)
rubocop (= 1.25.1)
citrus (3.0.2)
cleanroom (1.0.0)
coderay (1.1.3)
concurrent-ruby (1.2.0)
contracts (0.16.1)
cookstyle (7.32.8)
rubocop (= 1.25.1)
corefoundation (0.3.13)
ffi (>= 1.15.0)
date (3.3.3)
Expand Down Expand Up @@ -324,9 +324,11 @@ GEM
plist (~> 3.1)
train-core
wmi-lite (~> 1.0)
openssl (3.2.0)
parallel (1.22.1)
parser (3.2.1.0)
parser (3.3.0.5)
ast (~> 2.4.1)
racc
parslet (1.8.2)
pastel (0.8.0)
tty-color (~> 0.5)
Expand All @@ -338,15 +340,15 @@ GEM
zhexdump (>= 0.0.2)
plist (3.6.0)
proxifier (1.0.3)
proxifier2 (1.1.0)
pry (0.14.2)
coderay (~> 1.1)
method_source (~> 1.0)
public_suffix (5.0.1)
racc (1.7.3)
rack (2.2.6.2)
rainbow (3.1.1)
rake (13.1.0)
regexp_parser (2.7.0)
regexp_parser (2.9.0)
rest-client (2.1.0)
http-accept (>= 1.7.0, < 2.0)
http-cookie (>= 1.0.2, < 2.0)
Expand Down Expand Up @@ -391,8 +393,8 @@ GEM
rubocop-ast (>= 1.15.1, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 3.0)
rubocop-ast (1.26.0)
parser (>= 3.2.1.0)
rubocop-ast (1.31.2)
parser (>= 3.3.0.4)
ruby-progressbar (1.11.0)
ruby2_keywords (0.0.5)
rubyntlm (0.6.3)
Expand Down Expand Up @@ -475,7 +477,7 @@ GEM
vault (0.17.0)
aws-sigv4
webrick (1.8.1)
win32-api (1.10.1-universal-mingw32)
win32-api (1.10.1)
win32-certstore (0.6.15)
chef-powershell (>= 1.0.12)
ffi
Expand Down Expand Up @@ -529,10 +531,11 @@ PLATFORMS
DEPENDENCIES
artifactory
berkshelf (>= 8.0)
chefstyle
cookstyle
kitchen-vagrant (>= 1.3.1)
omnibus!
omnibus-software!
openssl (= 3.2.0)
pedump
rake
test-kitchen (>= 1.23)
Expand Down
26 changes: 20 additions & 6 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
require "chefstyle"
require "rubocop/rake_task"
desc " Run ChefStyle"
RuboCop::RakeTask.new(:chefstyle) do |task|
task.options << "--display-cop-names"
task.options << "config"
# not loaded on msys devkit
unless RUBY_PLATFORM.include?('mingw')
require "rubocop/rake_task"
require "cookstyle/chefstyle"

desc "Run ChefStyle"
RuboCop::RakeTask.new(:chefstyle) do |task|
task.options << "--display-cop-names"
task.options << "config"
end
end

require "rake/testtask"

desc "Run tests"
Rake::TestTask.new do |t|
t.libs << "test"
t.test_files = FileList["test/**/*_test.rb"]
t.warning = true
t.verbose = false
end
75 changes: 75 additions & 0 deletions omnibus-test.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ $ErrorActionPreference = "Stop"
# We don't want to add the embedded bin dir to the main PATH as this
# could mask issues in our binstub shebangs.
$embedded_bin_dir = "C:\opscode\chef\embedded\bin"
$embedded_dir = "C:\opscode\chef\embedded"

# FIXME: we should really use Bundler.with_unbundled_env in the caller instead of re-inventing it here
Remove-Item Env:_ORIGINAL_GEM_PATH -ErrorAction SilentlyContinue
Expand All @@ -20,11 +21,85 @@ Remove-Item Env:RUBY_VERSION -ErrorAction SilentlyContinue
Remove-Item Env:BUNDLER_VERSION -ErrorAction SilentlyContinue

# Exercise various packaged tools to validate binstub shebangs
Write-Host ":ruby: Validating Ruby can run"
& $embedded_bin_dir\ruby --version
If ($lastexitcode -ne 0) { Throw $lastexitcode }

Write-Host ":gem: Validating RubyGems can run"
& $embedded_bin_dir\gem.bat --version
If ($lastexitcode -ne 0) { Throw $lastexitcode }

Write-Host ":bundler: Validating Bundler can run"
& $embedded_bin_dir\bundle.bat --version
If ($lastexitcode -ne 0) { Throw $lastexitcode }

Write-Host ":lock: Validating OpenSSL can run"
$version=(&"$embedded_bin_dir\openssl.exe" version)
If ($lastexitcode -ne 0) { Throw $lastexitcode }

Write-Host ":lock: Validating OpenSSL executable"
Start-Process -NoNewWindow -Wait "$embedded_bin_dir\openssl.exe" -ArgumentList "sha3-512" -RedirectStandardInput ".\LICENSE" -PassThru
If ($lastexitcode -ne 0) {
Write-Host "sha3 failed"
Throw $lastexitcode
}
If ($end:OMNIBUS_FIPS_MODE -eq $true) {
$env:OPENSSL_FIPS = "1"
}

& $embedded_bin_dir\bundle install --jobs=2 --retry=3

If ($env:OMNIBUS_FIPS_MODE -eq $true) {
$fips_errors=@()
Write-Host "FIPS is enabled for this environment"
Write-Host ":closed_lock_with_key: Validating FIPS"

Start-Process -NoNewWindow -Wait "$embedded_bin_dir\openssl.exe" -ArgumentList "md5" -RedirectStandardInput ".\LICENSE" -PassThru
If ($lastexitcode -eq 0) {
# the md5 hash _should_ error
Write-Host "openssl executable still allow md5"

#Get-ChildItem $embedded_dir -Name 'openssl.cnf' -recurse | ForEach-Object {
# Write-Host "[[[start dump of $embedded_dir/$_"
# Get-Content $embedded_dir/$_
# Write-Host "end dump of $embedded_dir/$_ ]]]"
#}
}

If ($version.Contains("OpenSSL 3")) {
Get-ChildItem "$embedded_dir\ssl\fipsmodule.cnf"
}

Write-Host "Listing openssl providers"
Start-Process -NoNewWindow -Wait "$embedded_bin_dir\openssl.exe" -ArgumentList "list", "-providers" -PassThru

Write-Host "Checking if FIPS is accessible via the Ruby OpenSSL bindings"
& $embedded_bin_dir/ruby.exe -v -e "require 'openssl'; puts OpenSSL::OPENSSL_VERSION_NUMBER.to_s(16); puts OpenSSL::OPENSSL_LIBRARY_VERSION; OpenSSL.fips_mode = 1; puts 'OpenSSL FIPS validated for ' + RUBY_VERSION"
If ($lastexitcode -ne 0) {
$fips_errors += "Ruby FIPS loading failed"
}

Write-Host "Checking that MD5 digest is not allowed"
# catch OpenSSL::Digest::MD5 and reraise, rescue anything else
& $embedded_bin_dir/ruby.exe -v -e "require 'openssl'; begin;OpenSSL.fips_mode=1;OpenSSL::Digest::MD5.new('hi');rescue OpenSSL::Digest::DigestError => e;puts 'MD5 through an error as expected';rescue => e;raise 'Unexpected error with MD5 digest';puts e.inspect;end"

If ($lastexitcode -ne 0) {
$fips_errors += "Ruby FIPS MD5 validation failed"
}

If ($fips_errors.length -gt 0) {
Write-Host "FIPS validation had $($fips_errors.length) errors:"
Write-Host ($fips_errors -join "`n")
Throw "FIPS validation had $($fips_errors.length) errors:"
}

} else {
Write-Host "FIPS is disabled for this environment"
}

If ((Get-Command "openssl.exe").Source -ne "$embedded_bin_dir\openssl.exe") {
Write-Host "The default openssl.exe is at: $((Get-Command "openssl.exe").Source),"
Write-Host "which has version $((Get-Command "openssl.exe").FileVersionInfo.FileVersion)"
}

Start-Process -NoNewWindow -Wait "$embedded_bin_dir\rake.bat" -ArgumentList "test", "-v" -PassThru
52 changes: 51 additions & 1 deletion omnibus-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,58 @@ do
done

# Exercise various packaged tools to validate binstub shebangs
echo ":ruby: Validating Ruby can run"
"$EMBEDDED_BIN_DIR/ruby" --version
echo ":gem: Validating RubyGems can run"
"$EMBEDDED_BIN_DIR/gem" --version
echo ":bundler: Checking Bundler version"
"$EMBEDDED_BIN_DIR/bundle" --version
echo ":carpentry_saw: Checking nokogiri version"
"$EMBEDDED_BIN_DIR/nokogiri" --version
"$EMBEDDED_BIN_DIR/ruby" -r openssl -e 'puts "Ruby can load OpenSSL"'

"$EMBEDDED_BIN_DIR/ruby" -r openssl -e 'puts "Ruby can load OpenSSL"'

echo ":lock: Checking OpenSSL version"
"$EMBEDDED_BIN_DIR/openssl" version # ensure openssl command works

echo "Validating that OpenSSL does not error with SHA3"
"$EMBEDDED_BIN_DIR/openssl" sha3-512 < ./LICENSE

export PATH=$EMBEDDED_BIN_DIR:$PATH
if [ "$OMNIBUS_FIPS_MODE" = "true" ]
then
export OPENSSL_FIPS=1
fi

"$EMBEDDED_BIN_DIR/bundle" install --jobs=2 --retry=3

if [ "$OMNIBUS_FIPS_MODE" = "true" ]
then

echo "the ruby we _expect_ to be using"
echo "--------------------------------"
echo "Checking $EMBEDDED_BIN_DIR/ruby"
sum $EMBEDDED_BIN_DIR/ruby
"$EMBEDDED_BIN_DIR/ruby" -v -e "require 'openssl'; puts OpenSSL::OPENSSL_VERSION_NUMBER.to_s(16); puts OpenSSL::OPENSSL_LIBRARY_VERSION; OpenSSL.fips_mode = 1; puts 'OpenSSL FIPS validated for ' + RUBY_VERSION"

echo "FIPS is enabled, checking FIPS mode"
ls -l /opt/chef/embedded/ssl/fipsmodule.cnf

echo "Listing openssl providers"
"$EMBEDDED_BIN_DIR/openssl" list -providers # fips should be a provider here

echo ":closed_lock_with_key: Checking FIPS mode"
"$EMBEDDED_BIN_DIR/openssl" md5 < ./LICENSE

if [ $? -eq 0 ]
then
ret_code=$?
echo "openssl executable still allows md5"
# exit $?
fi

else
echo "FIPS is not enabled, skipping FIPS mode functionality test"
fi

"$EMBEDDED_BIN_DIR/rake" test -v
6 changes: 5 additions & 1 deletion omnibus.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,8 @@
# local_software_dirs ['/path/to/local/software']

fatal_transitive_dependency_licensing_warnings true
fips_mode (ENV["OMNIBUS_FIPS_MODE"] || "").casecmp("true") >= 0
fips_mode (ENV["OMNIBUS_FIPS_MODE"] || "").casecmp("true") == 0

puts "<<<DEBUG>>>"
puts "OMNNBUS_FIPS_MODE: #{ENV["OMNIBUS_FIPS_MODE"]}"
puts "FIPS_MODE: #{(ENV["OMNIBUS_FIPS_MODE"] || "").casecmp("true") == 0}"
9 changes: 7 additions & 2 deletions omnibus_overrides.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,14 @@
override "makedepend", version: "1.0.5"
override "ncurses", version: "6.3"
override "nokogiri", version: "1.13.6"
override "openssl", version: "3.0.9"
# if you need to calculate openssl environment
openssl_version_default = windows? ? "1.0.2zi" : "3.0.9"

# set OPENSSL_OVERRIDE variable to a different openssl version to test
# builds for other versions in omnibus_software
override "openssl", version: ENV.fetch("OPENSSL_OVERRIDE", openssl_version_default)
override "pkg-config-lite", version: "0.28-1"
override :ruby, version: aix? ? "3.0.3" : "3.1.2", openssl_gem: "3.0.0"
override :ruby, version: aix? ? "3.0.3" : "3.1.2", openssl_gem: "3.2.0"
override "ruby-windows-devkit-bash", version: "3.1.23-4-msys-1.0.18"
override "ruby-msys2-devkit", version: "3.1.2-1"
override "util-macros", version: "1.19.0"
Expand Down
33 changes: 33 additions & 0 deletions test/fips_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# frozen_string_literal: true
require 'minitest/autorun'
require 'openssl'

class FipsTest < Minitest::Test
def test_sha256
sha256 = OpenSSL::Digest.new('SHA256')
sha256 << 'test'

# just invoke the digest method to make sure it doesn't crash
sha256.digest
end

def make_md5
md5 = OpenSSL::Digest.new('MD5')
md5 << 'test'
md5.digest
end
def test_md5
if ENV['OMNIBUS_FIPS_MODE'].to_s.casecmp('true').zero?
# this will raise an exception if FIPS mode support not available
OpenSSL.fips_mode = true

assert_raises OpenSSL::Digest::DigestError do
make_md5
end
end

OpenSSL.fips_mode = false
# if md5 raises an exception with FIPS off, then something's wrong
make_md5
end
end
Loading

0 comments on commit 81d1b23

Please sign in to comment.