Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions 3.0/test/test-fips/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# frozen_string_literal: true

source 'https://rubygems.org'

gem 'sinatra'

gem 'rackup'

# Use webrick for simple HTTP transport.
# this is not a production grade server, but gets the job done for the
# purpose of just sending something over for a request.
# Additionally there is an option to add SSL later here.
gem 'webrick'
72 changes: 72 additions & 0 deletions 3.0/test/test-fips/app.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
require 'sinatra'
require 'openssl'

set :server, 'webrick'
set :bind, '0.0.0.0'
set :port, 8080

MESSAGE = "My secret text\n".freeze

get '/symmetric/aes-256-cbc' do
fips_state = OpenSSL.fips_mode ? 'enabled' : 'disabled'
# This should pass with and without FIPS.
cipher = OpenSSL::Cipher.new('aes-256-cfb')
cipher.encrypt
cipher.random_key
cipher.random_iv
enc = cipher.update(MESSAGE) + cipher.final
return 200, enc
rescue => e
return 409, "Unexpected failure with aes-256-cbc, fips #{fips_state}, #{e.inspect}\nBacktrace:\n#{e.backtrace}\n"
end

get '/symmetric/des-ede-cbc' do
status = 200
fips_state = OpenSSL.fips_mode ? 'enabled' : 'disabled'

cipher = OpenSSL::Cipher.new('des-ede-cbc')
cipher.encrypt
# This fails in FIPS only once we try to get a key for the 3DES.
cipher.random_key
cipher.random_iv
cipher.update(MESSAGE) + cipher.final
rescue OpenSSL::Cipher::CipherError => e
return status, "Failed with fips #{fips_state} #{e.inspect}\n" if OpenSSL.fips_mode

return 500, "Failed with fips #{fips_state} #{e.inspect}\nBacktrace:\n#{e.backtrace}\n"
rescue => e
return 409, "Unexpected failure with des-ede-cbc, fips #{fips_state}, #{e.inspect}\nBacktrace:\n#{e.backtrace}\n"
end

get '/hash/sha256' do
status = 200

fips_state = OpenSSL.fips_mode ? 'enabled' : 'disabled'
message = "SHA256 succeeded, fips is #{fips_state}"

OpenSSL::Digest.digest('SHA256', MESSAGE)

return status, message
rescue => e
return 409, "Unexpected failure with SHA256, fips #{fips_state}, #{e.inspect}\nBacktrace:\n#{e.backtrace}\n"
end

get '/hash/md5' do
status = 200

fips_state = OpenSSL.fips_mode ? 'enabled' : 'disabled'
message = "MD5 succeeded, fips is #{fips_state}"

OpenSSL::Digest.digest('MD5', MESSAGE)

# FIPS is on, but this passed, that shouldn't be the case.
status = 500 if OpenSSL.fips_mode

return status, message
rescue OpenSSL::Digest::DigestError => e
return status, "Failed with fips #{fips_state} #{e.inspect}\n" if OpenSSL.fips_mode

return 500, "Failed with fips #{fips_state} #{e.inspect}\nBacktrace:\n#{e.backtrace}\n"
rescue => e
return 409, "Unexpected failure with MD5, fips #{fips_state}, #{e.inspect}\nBacktrace:\n#{e.backtrace}\n"
end
2 changes: 2 additions & 0 deletions 3.0/test/test-fips/config.ru
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
require './app'
run Sinatra::Application
13 changes: 13 additions & 0 deletions 3.3/test/test-fips/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# frozen_string_literal: true

source 'https://rubygems.org'

gem 'sinatra'

gem 'rackup'

# Use webrick for simple HTTP transport.
# this is not a production grade server, but gets the job done for the
# purpose of just sending something over for a request.
# Additionally there is an option to add SSL later here.
gem 'webrick'
72 changes: 72 additions & 0 deletions 3.3/test/test-fips/app.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
require 'sinatra'
require 'openssl'

set :server, 'webrick'
set :bind, '0.0.0.0'
set :port, 8080

MESSAGE = "My secret text\n".freeze

get '/symmetric/aes-256-cbc' do
fips_state = OpenSSL.fips_mode ? 'enabled' : 'disabled'
# This should pass with and without FIPS.
cipher = OpenSSL::Cipher.new('aes-256-cfb')
cipher.encrypt
cipher.random_key
cipher.random_iv
enc = cipher.update(MESSAGE) + cipher.final
return 200, enc
rescue => e
return 409, "Unexpected failure with aes-256-cbc, fips #{fips_state}, #{e.inspect}\nBacktrace:\n#{e.backtrace}\n"
end

get '/symmetric/des-ede-cbc' do
status = 200
fips_state = OpenSSL.fips_mode ? 'enabled' : 'disabled'

cipher = OpenSSL::Cipher.new('des-ede-cbc')
cipher.encrypt
# This fails in FIPS only once we try to get a key for the 3DES.
cipher.random_key
cipher.random_iv
cipher.update(MESSAGE) + cipher.final
rescue OpenSSL::Cipher::CipherError => e
return status, "Failed with fips #{fips_state} #{e.inspect}\n" if OpenSSL.fips_mode

return 500, "Failed with fips #{fips_state} #{e.inspect}\nBacktrace:\n#{e.backtrace}\n"
rescue => e
return 409, "Unexpected failure with des-ede-cbc, fips #{fips_state}, #{e.inspect}\nBacktrace:\n#{e.backtrace}\n"
end

get '/hash/sha256' do
status = 200

fips_state = OpenSSL.fips_mode ? 'enabled' : 'disabled'
message = "SHA256 succeeded, fips is #{fips_state}"

OpenSSL::Digest.digest('SHA256', MESSAGE)

return status, message
rescue => e
return 409, "Unexpected failure with SHA256, fips #{fips_state}, #{e.inspect}\nBacktrace:\n#{e.backtrace}\n"
end

get '/hash/md5' do
status = 200

fips_state = OpenSSL.fips_mode ? 'enabled' : 'disabled'
message = "MD5 succeeded, fips is #{fips_state}"

OpenSSL::Digest.digest('MD5', MESSAGE)

# FIPS is on, but this passed, that shouldn't be the case.
status = 500 if OpenSSL.fips_mode

return status, message
rescue OpenSSL::Digest::DigestError => e
return status, "Failed with fips #{fips_state} #{e.inspect}\n" if OpenSSL.fips_mode

return 500, "Failed with fips #{fips_state} #{e.inspect}\nBacktrace:\n#{e.backtrace}\n"
rescue => e
return 409, "Unexpected failure with MD5, fips #{fips_state}, #{e.inspect}\nBacktrace:\n#{e.backtrace}\n"
end
2 changes: 2 additions & 0 deletions 3.3/test/test-fips/config.ru
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
require './app'
run Sinatra::Application
75 changes: 70 additions & 5 deletions test/run
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ test_connection
test_scl_usage
test_npm_functionality
"

TEST_LIST_FIPS="\
test_ruby_fips_mode
test_ruby_fips_s2i_app
"

source "${test_dir}/test-lib.sh"

# Read exposed port from image meta data
Expand All @@ -51,7 +57,8 @@ run_s2i_build() {
}

run_test_application() {
docker run --user=100001 --rm --cidfile=${cid_file} ${IMAGE_NAME}-testapp
local appname=${1:-testapp}
docker run --user=100001 --rm --cidfile=${cid_file} ${IMAGE_NAME}-${appname}
}

test_s2i_usage() {
Expand Down Expand Up @@ -169,10 +176,12 @@ app_cleanup() {
}

function cleanup() {
info "Cleaning up the test application image ${IMAGE_NAME}-testapp"
if image_exists ${IMAGE_NAME}-testapp; then
docker rmi -f ${IMAGE_NAME}-testapp
fi
for image in testapp testfips; do
info "Cleaning up the test application image ${IMAGE_NAME}-${image}"
if image_exists ${IMAGE_NAME}-${image}; then
docker rmi -f ${IMAGE_NAME}-${image}
fi
done
}

# Positive test & non-zero exit status = ERROR.
Expand Down Expand Up @@ -210,6 +219,53 @@ evaluate_build_result() {
return $_ret_code
}

# "0" if system is not FIPS enabled, "1" if it is.
function fips_enabled() {
local is_fips_enabled

# Read fips mode from host in case exists
if [[ -f /proc/sys/crypto/fips_enabled ]]; then
echo "$(cat /proc/sys/crypto/fips_enabled)"
else
echo "0"
fi
}

function run_s2i_build_fips() {
ct_s2i_build_as_df file://${test_dir}/test-fips ${IMAGE_NAME} ${IMAGE_NAME}-testfips ${s2i_args} $1
}

function test_ruby_fips_mode() {
if [[ "$(fips_enabled)" == "0" ]]; then
# FIPS disabled -> OpenSSL#fips_mode returns false
echo "Fips should be disabled"
docker run --rm "$IMAGE_NAME" /bin/bash -c 'ruby -ropenssl -e "exit !OpenSSL.fips_mode"'
ct_check_testcase_result "$?"
else
echo "Fips should be enabled"
# FIPS enabled -> OpenSSL#fips_mode returns true
docker run --rm "$IMAGE_NAME" /bin/bash -c 'ruby -ropenssl -e "exit OpenSSL.fips_mode"'
ct_check_testcase_result "$?"
fi
}

function test_ruby_fips_s2i_app() {
run_s2i_build_fips
evaluate_build_result $? "default"
# Verify that the HTTP connection can be established to test application container
run_test_application testfips &
# Wait for the container to write its CID file
ct_wait_for_cid "${cid_file}"
ct_test_response "http://$(container_ip):8080/symmetric/aes-256-cbc" 200 ""
ct_check_testcase_result $?
ct_test_response "http://$(container_ip):8080/symmetric/des-ede-cbc" 200 ""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on your description in pull request:

  • '/symmetric/aes-256-cbc' -- succeeds under FIPS
  • '/symmetric/des-ede-cbc' -- fails under FIPS - This should fail.
    2 of those test digests:
  • '/hash/sha256' -- succeeds under FIPS
  • '/hash/md5' -- fails under FIPS

test_ruby_fips_s2i_app where is enabled FIPS mode This works the same as for FIPs mode and for None FIPs mode? Like this https://github.com/sclorg/s2i-nodejs-container/blob/master/test/test-lib-nodejs.sh#L587

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is checked in code that it fails under FIPS, an exception is rescued. If an exception does NOT occur under FIPS, then the test fails.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noted it down with those comments that there are ciphers/hashes which are expected to fail and which are expected to pass. If those that should pass raise an exception, that is not expected and the test will fail.

ct_check_testcase_result $?
ct_test_response "http://$(container_ip):8080/hash/sha256" 200 ""
ct_check_testcase_result $?
ct_test_response "http://$(container_ip):8080/hash/md5" 200 ""
ct_check_testcase_result $?
}

# Prepare dependencies for tests
pushd ${test_dir}
# db test dependencies
Expand Down Expand Up @@ -247,3 +303,12 @@ echo "Removing test dependencies"
rm -rf ${test_dir}/db-test-app

app_cleanup

if [[ "$OS" == "rhel8" ]]; then
echo "Not executing fips tests on RHEL 8"
else
echo "Testing fips mode"
TEST_SET=${TESTS:-$TEST_LIST_FIPS} ct_run_tests_from_testset "fips"
echo "Testing the production image build for fips"
cleanup
fi