Add nodejs fips test
Add two test cases to verify that if:
- Container is in fips mode, node is also using fips mode.
- Container isnt in fips mode, node also isnt using fips mode.
Nodejs fips state is verified with: node -e 'const crypto = require("crypto"); return crypto.getFips(); which should return the same value (1 for enabled, 0 for disabled) as cat "/proc/sys/crypto/fips_enabled".
Let's try first set of shots
[test]
Testing Farm results
| name | compose | arch | status | started (UTC) | time | logs |
|---|---|---|---|---|---|---|
| Fedora - 22-minimal | Fedora-latest | x86_64 | ✅ passed | 26.06.2025 08:28:24 | 7min 35s | test pipeline |
| CentOS Stream 9 - 20-minimal | CentOS-Stream-9 | x86_64 | ✅ passed | 26.06.2025 08:28:22 | 7min 25s | test pipeline |
| Fedora - 22 | Fedora-latest | x86_64 | ✅ passed | 26.06.2025 08:28:25 | 9min | test pipeline |
| Fedora - 20 | Fedora-latest | x86_64 | ✅ passed | 26.06.2025 08:36:47 | 9min 22s | test pipeline |
| CentOS Stream 10 - 22-minimal | CentOS-Stream-10 | x86_64 | ✅ passed | 26.06.2025 08:28:35 | 7min 37s | test pipeline |
| CentOS Stream 9 - 20 | CentOS-Stream-9 | x86_64 | ✅ passed | 26.06.2025 08:36:59 | 9min 8s | test pipeline |
| CentOS Stream 10 - 22 | CentOS-Stream-10 | x86_64 | ✅ passed | 26.06.2025 08:28:36 | 8min 53s | test pipeline |
| RHEL9 - FIPS Enabled - 22-minimal | RHEL-9.6.0-Nightly | x86_64 | ✅ passed | 26.06.2025 10:50:43 | 24min 1s | test pipeline |
| RHEL9 - FIPS Enabled - 20 | RHEL-9.6.0-Nightly | x86_64 | ❌ error | 26.06.2025 08:28:24 | 16min 21s | test pipeline |
| RHEL10 - 22-minimal | RHEL-10-Nightly | x86_64 | ✅ passed | 26.06.2025 08:28:23 | 14min 42s | test pipeline |
| RHEL8 - 22 | RHEL-8.10.0-Nightly | x86_64 | ✅ passed | 26.06.2025 08:36:37 | 20min 20s | test pipeline |
| RHEL10 - 22 | RHEL-10-Nightly | x86_64 | ✅ passed | 26.06.2025 08:28:51 | 17min 17s | test pipeline |
| RHEL8 - 22-minimal | RHEL-8.10.0-Nightly | x86_64 | ✅ passed | 26.06.2025 08:28:25 | 17min 25s | test pipeline |
| RHEL10 - FIPS Enabled - 22-minimal | RHEL-10-Nightly | x86_64 | ❌ error | 26.06.2025 12:20:26 | 17min 18s | test pipeline |
| RHEL9 - FIPS Enabled - 20-minimal | RHEL-9.6.0-Nightly | x86_64 | ✅ passed | 26.06.2025 10:50:43 | 22min 54s | test pipeline |
| RHEL10 - FIPS Enabled - 22 | RHEL-10-Nightly | x86_64 | ❌ error | 26.06.2025 11:51:42 | 16min 17s | test pipeline |
| RHEL9 - FIPS Enabled - 22 | RHEL-9.6.0-Nightly | x86_64 | ✅ passed | 26.06.2025 10:50:44 | 25min 54s | test pipeline |
| RHEL9 - 22-minimal | RHEL-9.4.0-Nightly | x86_64 | ✅ passed | 25.06.2025 12:25:56 | 57min 56s | test pipeline |
| RHEL8 - 20-minimal | RHEL-8.10.0-Nightly | x86_64 | ✅ passed | 26.06.2025 08:28:35 | 18min 2s | test pipeline |
| RHEL8 - 20 | RHEL-8.10.0-Nightly | x86_64 | ✅ passed | 26.06.2025 08:28:33 | 18min 5s | test pipeline |
| RHEL9 - 20-minimal | RHEL-9.6.0-Nightly | x86_64 | ✅ passed | 26.06.2025 08:28:25 | 18min 40s | test pipeline |
| RHEL9 - 22 | RHEL-9.6.0-Nightly | x86_64 | ✅ passed | 26.06.2025 08:38:47 | 20min 29s | test pipeline |
| Fedora - 20-minimal | Fedora-latest | x86_64 | ✅ passed | 26.06.2025 08:28:25 | 8min 5s | test pipeline |
| RHEL9 - 20 | RHEL-9.6.0-Nightly | x86_64 | ✅ passed | 26.06.2025 08:28:24 | 20min 56s | test pipeline |
@tjuhaszrh The error is here:
Running test test_nodejs_fips_mode_off (starting at 2025-06-19 07:27:56+00:00) ...
-----------------------------------------------
[eval]:1
(crypto=>{{const crypto = require(crypto); return crypto.getFips();}})(require('node:crypto'))
^
ReferenceError: Cannot access 'crypto' before initialization
at [eval]:1:35
at [eval]:1:71
at runScriptInThisContext (node:internal/vm:209:10)
at node:internal/process/execution:449:12
at [eval]-wrapper:6:24
at runScriptInContext (node:internal/process/execution:447:60)
at evalFunction (node:internal/process/execution:87:30)
at evalScript (node:internal/process/execution:99:3)
at node:internal/main/eval_string:74:3
Node.js v22.15.0
@tjuhaszrh Thanks for this pull request. I have several question regarding nodeJs.
What do you thinkg about this code?
function test_nodejs_fips_mode_off() {
local ret_val
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
# Set to 0 if not exists
is_fips_enabled="0"
fi
if [[ "$is_fips_enabled" == "0" ]]; then
echo "FIPS is disabled on host"
echo "What is expected output in case disabled fips???"
fips=$(docker run --rm ${IMAGE_NAME}-testapp /bin/bash -c "! node -e 'const crypto = require("crypto"); return crypto.getFips();'")
echo "FIPS from app: '$fips'" # For me $fips is empty...
if [[ "$fips" == "" ]]; then
ct_check_testcase_result "0"
else
ct_check_testcase_result "$retval"
fi
else
# What is expected behavior here in case FIPS is enabled and we test for fips is disabled. Does it make sense either?
# Check fips mode in container as well
if docker run --rm ${IMAGE_NAME}-testapp /bin/bash -c "cat /proc/sys/crypto/fips_enabled | grep -q 0"; then
fips=$(docker run --rm ${IMAGE_NAME}-testapp /bin/bash -c "node -e 'const crypto = require("crypto"); return crypto.getFips();'")
echo "FIPS from app: '$fips'"
ct_check_testcase_result "$?"
fi
fi
}
[test]
Sorry I think the issue was caused just by messy string nesting in require("crypto") .
Adding backslash seems to have fixed it.
➜ test git:(fips-nodejs) fips=$(podman run --rm localhost/node-app:latest /bin/bash -c "! node -e 'const crypto = require("crypto"); return crypto.getFips();'")
[eval]:1
(crypto=>{{const crypto = require(crypto); return crypto.getFips();}})(require('node:crypto'))
^
ReferenceError: Cannot access 'crypto' before initialization
at [eval]:1:35
at [eval]:1:71
at runScriptInThisContext (node:internal/vm:209:10)
at node:internal/process/execution:118:14
at [eval]-wrapper:6:24
at runScript (node:internal/process/execution:101:62)
at evalScript (node:internal/process/execution:133:3)
at node:internal/main/eval_string:51:3
Node.js v20.19.2
➜ test git:(fips-nodejs) fips=$(podman run --rm localhost/node-app:latest /bin/bash -c "! node -e 'const crypto = require(\"crypto\"); return crypto.getFips();'")
➜ test git:(fips-nodejs)
@tjuhaszrh Thanks for this pull request. I have several question regarding nodeJs.
What do you thinkg about this code?
function test_nodejs_fips_mode_off() { local ret_val 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 # Set to 0 if not exists is_fips_enabled="0" fi if [[ "$is_fips_enabled" == "0" ]]; then echo "FIPS is disabled on host" echo "What is expected output in case disabled fips???" fips=$(docker run --rm ${IMAGE_NAME}-testapp /bin/bash -c "! node -e 'const crypto = require("crypto"); return crypto.getFips();'") echo "FIPS from app: '$fips'" # For me $fips is empty... if [[ "$fips" == "" ]]; then ct_check_testcase_result "0" else ct_check_testcase_result "$retval" fi else # What is expected behavior here in case FIPS is enabled and we test for fips is disabled. Does it make sense either? # Check fips mode in container as well if docker run --rm ${IMAGE_NAME}-testapp /bin/bash -c "cat /proc/sys/crypto/fips_enabled | grep -q 0"; then fips=$(docker run --rm ${IMAGE_NAME}-testapp /bin/bash -c "node -e 'const crypto = require("crypto"); return crypto.getFips();'") echo "FIPS from app: '$fips'" ct_check_testcase_result "$?" fi fi }
My understanding is that crypto.getFips(); returns exactly the same values as cat /proc/sys/crypto/fips_enabled (so 1 for enabled, 0 for disabled fips).
My usage of the fips variable was also wrong since I only care about the $? value and it doesn't store anything, I got slightly to inspired by the nodemon test.
So I think:
if [[ "$is_fips_enabled" == "0" ]]; then echo "FIPS is disabled on host" echo "What is expected output in case disabled fips???" fips=$(docker run --rm ${IMAGE_NAME}-testapp /bin/bash -c "! node -e 'const crypto = require("crypto"); return crypto.getFips();'") echo "FIPS from app: '$fips'" # For me $fips is empty... if [[ "$fips" == "" ]]; then ct_check_testcase_result "0" else ct_check_testcase_result "$retval" fi
this would probably always pass.
Adjustments:
- removed unused variable fips.
- moved the logic into one function that verifies both states of fips mode.
- added check for presence of
/proc/sys/crypto/fips_enabledfile.
Great to see this test being added
[test]
Great to see this test being added
Hi @mhdawson , does it make sense to test also some a simple app, like we have in directory test-app (https://github.com/sclorg/s2i-nodejs-container/tree/master/test/test-app) also for FIPS mode? But may be with different name, like test-fips? What do you think?
[test]
@phracek a simple test application would be a good idea as well.
@tjuhaszrh Add to this pull request also fips https://github.com/sclorg/s2i-nodejs-container/blob/master/test/test-lib-nodejs.sh#L133 The code should be like
app|hw|fips|express-webapp|binary)
pushd "${test_dir}/test-${1}" >/dev/null
prepare_dummy_git_repo
popd >/dev/null
;;
Add there also function like is here https://github.com/sclorg/s2i-nodejs-container/blob/master/test/test-lib-nodejs.sh#L44
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
}
Added a simple app that in the context of a server verifies what kind of Hash algorithms and Ciphers are allowed to be used under FIPS.
- Allowed: SHA256, AES
- Not allowed: MLD, 3DES with only two keys.
Rebased against upstream. Fixing some tests.
[test]
Let's tests one more time
[test]