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 test/run
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ test_node_cmd_development_init_wrapper_true
test_init_wrapper_false_development
"

TEST_LIST_FIPS="\
test_nodejs_fips_mode
test_run_fips_app_application
"
source "${THISDIR}/test-lib.sh"
source "${THISDIR}/test-lib-nodejs.sh"

Expand Down Expand Up @@ -160,3 +164,12 @@ evaluate_build_result $? "proxy"
TEST_SET=${TESTS:-$TEST_LIST_HW} ct_run_tests_from_testset "hw"

cleanup

echo "Testing fips mode"
prepare fips
check_prep_result $? fips || exit
echo "Testing the production image build for fips"
run_s2i_build_fips
evaluate_build_result $? "default"

TEST_SET=${TESTS:-$TEST_LIST_FIPS} ct_run_tests_from_testset "fips"
4 changes: 4 additions & 0 deletions test/test-fips/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
node-echo
=========

node.js echo server, tests fips functionality.
27 changes: 27 additions & 0 deletions test/test-fips/iisnode.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# For documentation see https://github.com/tjanczuk/iisnode/blob/master/src/samples/configuration/iisnode.yml

# loggingEnabled: false
# debuggingEnabled: false
# devErrorsEnabled: false
node_env: production
# nodeProcessCountPerApplication: 1
# maxConcurrentRequestsPerProcess: 1024
# maxNamedPipeConnectionRetry: 24
# namedPipeConnectionRetryDelay: 250
# maxNamedPipeConnectionPoolSize: 512
# maxNamedPipePooledConnectionAge: 30000
# asyncCompletionThreadCount: 0
# initialRequestBufferSize: 4096
# maxRequestBufferSize: 65536
watchedFiles: iisnode.yml;node_modules\*;*.js
# uncFileChangesPollingInterval: 5000
# gracefulShutdownTimeout: 60000
# logDirectoryNameSuffix: logs
# debuggerPortRange: 5058-6058
# debuggerPathSegment: debug
# maxLogFileSizeInKB: 128
# appendToExistingLog: false
# logFileFlushInterval: 5000
# flushResponse: false
# enableXFF: false
# promoteServerVars:
32 changes: 32 additions & 0 deletions test/test-fips/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"name": "node-echo",
"version": "0.0.1",
"description": "node-echo",
"main": "server.js",
"dependencies": {
},
"devDependencies": {
"nodemon": "*"
},
"engine": {
"node": "*",
"npm": "*"
},
"scripts": {
"dev": "nodemon --ignore node_modules/ server.js",
"start": "node server.js"
},
"repository": {
"type": "git",
"url": "http://github.com/bettiolo/node-echo.git"
},
"keywords": [
"Echo"
],
"author": "Marco Bettiolo <marco@bettiolo.it>",
"license": "",
"bugs": {
"url": "http://github.com/bettiolo/node-echo/issues"
},
"homepage": "http://apilb.com"
}
88 changes: 88 additions & 0 deletions test/test-fips/server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
const crypto = require('crypto');
var http = require('http');
var port = process.env.PORT || process.env.port || process.env.OPENSHIFT_NODEJS_PORT || 8080;
var ip = process.env.OPENSHIFT_NODEJS_IP || '0.0.0.0';
var server = http.createServer(function (req, res) {
const fipsMode = getFipsMode();

res.writeHead(200, {'Content-Type': 'text/plain'});
verifySupportedHash(fipsMode);
res.write('Hash generation succesfully verified\n');
verifySupportedCiphers(fipsMode);
res.write('Cipher generation succesfully verified\n');
res.end('\n');

});
server.listen(port);
console.log('Server running on ' + ip + ':' + port);

/*
* Return boolean value
* True if FIPS is enabled
* False if Disabled
*/
function getFipsMode () {
return !!crypto.getFips();
}

/*
* Verify usage of FIPS supported hash algs
* sha256 is FIPS supported
* MLD isn't FIPS supported
*/
function verifySupportedHash(fipsMode) {
try {
const hashSha256 = crypto.createHash('sha256').update('FIPS test').digest('hex');
} catch (e) {
console.error("Error: SHA256 generation should be supported with FIPS.");
exit.process(1);
}
try {
crypto.createHash('md5').update('MD5 test').digest('hex');
if (fipsMode) {
console.error('Error: MD5 generation should not be suscessfull with FIPS enabled.');
exit.process(1);
}
} catch (e) {
if (!fipsMode) {
console.error('Error: MD5 generation should pass without FIPS mode.');
exit.process(1);
}
}
}

/*
* Verify usage of FIPS supported ciphers
* AES is FIPS supported
* 3DES with only two keys isn't FIPS supported
*/
function verifySupportedCiphers(fipsMode) {
try {
const key = crypto.randomBytes(32);
const iv = crypto.randomBytes(16);
const plaintext = 'Test of AES encryption.';
const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
let encrypted = cipher.update(plaintext, 'utf8', 'hex');
encrypted += cipher.final('hex');
} catch (e) {
console.error('Error: AES-256 generation should be supported with FIPS');
process.exit(1);
}
try {
const key = crypto.randomBytes(16);
const iv = crypto.randomBytes(8);
crypto.createCipheriv('des-ede-cbc', key, iv);

if (fipsMode) {
console.error("Error: 3DES generation shoud not be succesfull with FIPS mode.")
process.exit(1);
}
} catch (e) {
if (!fipsMode) {
console.error('Error: 3DES generation should be successfull without FIPS mode.',e.message);
process.exit(1);
}
}


}
17 changes: 17 additions & 0 deletions test/test-fips/web.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<configuration>
<system.webServer>
<handlers>
<add name="iisnode" path="server.js" verb="*" modules="iisnode" />
</handlers>
<iisnode loggingEnabled="false" />

<rewrite>
<rules>
<rule name="myapp">
<match url="/*" />
<action type="Rewrite" url="server.js" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
52 changes: 49 additions & 3 deletions test/test-lib-nodejs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ run_s2i_build() {
ct_s2i_build_as_df file://${test_dir}/test-app ${IMAGE_NAME} ${IMAGE_NAME}-testapp ${s2i_args} $(ct_build_s2i_npm_variables) $1
}

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

run_s2i_build_proxy() {
ct_s2i_build_as_df file://${test_dir}/test-hw ${IMAGE_NAME} ${IMAGE_NAME}-testhw ${s2i_args} $(ct_build_s2i_npm_variables) -e HTTP_PROXY=$1 -e http_proxy=$1 -e HTTPS_PROXY=$2 -e https_proxy=$2
}
Expand Down Expand Up @@ -130,7 +134,7 @@ prepare() {
case "$1" in
# TODO: STI build require the application is a valid 'GIT' repository, we
# should remove this restriction in the future when a file:// is used.
app|hw|express-webapp|binary)
app|hw|fips|express-webapp|binary)
pushd "${test_dir}/test-${1}" >/dev/null
prepare_dummy_git_repo
popd >/dev/null
Expand All @@ -153,7 +157,7 @@ prepare() {

run_test_application() {
case "$1" in
app|hw|express-webapp|binary)
app|fips|hw|express-webapp|binary)
cid_file=$CID_FILE_DIR/$(mktemp -u -p . --suffix=.cid)
docker run -d --user=100001 $(ct_mount_ca_file) --rm --cidfile=${cid_file} $2 ${IMAGE_NAME}-test$1
;;
Expand All @@ -166,7 +170,7 @@ run_test_application() {

run_test_application_with_quoted_args() {
case "$1" in
app | hw | express-webapp | binary)
app | fips | hw | express-webapp | binary)
cid_file=$CID_FILE_DIR/$(mktemp -u -p . --suffix=.cid)
docker run -d --user=100001 $(ct_mount_ca_file) --rm --cidfile=${cid_file} "$2" ${IMAGE_NAME}-test$1
;;
Expand Down Expand Up @@ -478,6 +482,29 @@ function test_nodemon_present() {
ct_check_testcase_result "$?"
}

function test_nodejs_fips_mode() {
# Test that nodejs behaves as expected in fips mode
local is_fips_enabled

# Read fips mode from host in case exists
if [[ -f /proc/sys/crypto/fips_enabled ]]; then
is_fips_enabled=$(cat /proc/sys/crypto/fips_enabled)
else
is_fips_enabled="0"
fi
if [[ "$is_fips_enabled" == "0" ]]; then
# FIPS disabled -- crypto.getFips() should return 0
echo "Fips should be disabled"
docker run --rm ${IMAGE_NAME}-testfips /bin/bash -c "node -e 'const crypto = require(\"crypto\"); process.exit(crypto.getFips());'"
ct_check_testcase_result "$?"
else
# FIPS enabled -- crypto.getFips() should return 1
echo "Fips should be enabled"
docker run --rm ${IMAGE_NAME}-testfips /bin/bash -c "! node -e 'const crypto = require(\"crypto\"); process.exit(crypto.getFips());'"
ct_check_testcase_result "$?"
fi
}

function test_npm_cache_cleared() {
# Test that the npm cache has been cleared
cache_loc=$(docker run --rm ${IMAGE_NAME}-testapp /bin/bash -c "npm config get cache")
Expand Down Expand Up @@ -548,6 +575,25 @@ function test_run_app_application() {
wait_for_cid
}

function test_run_fips_app_application() {
local is_fips_enabled

# Read fips mode from host in case exists
if [[ -f /proc/sys/crypto/fips_enabled ]]; then
is_fips_enabled=$(cat /proc/sys/crypto/fips_enabled)
else
is_fips_enabled="0"
fi
if [[ "$is_fips_enabled" == "1" ]]; then
# Verify that the HTTP connection can be established to test application container
run_test_application fips
# Wait for the container to write it's CID file
wait_for_cid
ct_check_testcase_result $?
kill_test_application
fi
}

function test_run_hw_application() {
# Verify that the HTTP connection can be established to test application container
run_test_application hw
Expand Down