Fips test
---
Copy fromhttps://github.com/coreos/coreos-assembler/pull/4477#issuecomment-4156120051
Do a test that verifies that attempting to use algorithms that aren't FIPS compliant will make the connection fail. For example, attempting to use the ChaCha20-Poly1305 cipher, or the X25519 key exchange method should not yield a successful connection. Of course in the context of TLS, which is a negotating protocol, you typically won't see a failure until you change the configuration to only support those.
On server side (none FIPS):
* Build nginx container, add `ssl_ecdh_curve X25519` in nginx.conf, that means: When a client connects, I want to use the X25519 curve to negotiate the encryption keys (that is none FIPS-compliant).
```
#!/usr/bin/env bash
# Run the image using command:
# podman run -d --name nginx -p 8443:8443 nginx
set -euo pipefail
# Check if argument is provided
if [ $# -eq 0 ]; then
echo "Error: Missing IP address argument"
echo "Usage: $0 <ip-address>"
exit 1
fi
IP="$1"
tmpdir="$(mktemp -d)"
cp Containerfile ${tmpdir}
cd ${tmpdir}
# Prepare index.html
cat <<EOF > index.html
This file was for testing.
EOF
# Prepare nginx.conf
cat <<EOF > nginx.conf
events {}
http {
server {
listen 8443 ssl;
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
ssl_ecdh_curve X25519; -----> add here
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
}
EOF
mkdir -p ssl
pushd ssl/
# Prepare openssl.cnf
cat <<SSLEOF > openssl.cnf
[ req ]
distinguished_name = dn
prompt = no
[ dn ]
CN = Test Server
[ req_ext ]
subjectAltName = IP:${IP}
SSLEOF
# Prepare key and crt
## Generate the private key
openssl genpkey \
-algorithm RSA \
-out server.key
## Generate CSR
openssl req -new -key server.key -out server.csr -config openssl.cnf
## Self-sign the certificate
openssl x509 -req \
-in server.csr \
-signkey server.key \
-out server.crt \
-days 365 \
-extfile openssl.cnf \
-extensions req_ext
rm server.csr openssl.cnf
popd
podman build -t nginx .
```
Containerfile
```
FROM registry.redhat.io/rhel10/nginx-126:10.1
ADD nginx.conf "${NGINX_CONF_PATH}"
COPY index.html /usr/share/nginx/html/index.html
# TLS material
USER 0
COPY ssl/ /etc/nginx/ssl/
RUN chown -R 1001:0 /etc/nginx/ssl
USER 1001
CMD ["nginx", "-g", "daemon off;"]
```
* Run nginx
`podman run -d --name nginx -p 8443:8443 localhost/nginx:latest`
On client:
* Start with FIPS enabled, use ignition to fetch file from server failed
```
[ 12.981770] ignition[1123]: files: createFilesystemsFiles: createFiles: op(4): GET https://192.168.122.149:8443/index.html: attempt #1
[ 13.030651] ignition[1123]: files: createFilesystemsFiles: createFiles: op(4): GET error: Get "https://192.168.122.149:8443/index.html": remote error: tls: handshake failure
```
#### client config: enabled FIPS
```
variant: fcos
version: 1.5.0
passwd:
users:
- name: core
ssh_authorized_keys:
- ssh-rsa xxx
groups:
- wheel
- sudo
ignition:
security:
tls:
certificate_authorities:
- inline: |
-----BEGIN CERTIFICATE-----
server.crt
-----END CERTIFICATE-----
storage:
files:
- path: /etc/ignition-machine-config-encapsulated.json
mode: 0644
overwrite: true
contents:
inline: |
{
"spec": { "fips": true }
}
- path: /var/resource/https
contents:
source: https://192.168.122.152:8443/index.html
```
-------
-------
**ignore!!!**
The tests confirm that Ignition can successfully fetch resources over HTTPS regardless of whether the client or server has FIPS mode active. Both client and server are using rhcos-9.8.20260314-0-qemu.x86_64.qcow2
Test Summary Results
```
Server (FIPS) Client (FIPS) Result
Enabled Enabled OK
Enabled Disabled OK
Disabled Enabled OK
```
Test server enabled FIPS and client disabled FIPS
* Start server with FIPs enabled
```
IGNITION_CONFIG="/home/fedora/data/ign/fips-enable.ign"
virt-install --connect="qemu:///system" --name=rhcos1 --vcpus=2 --memory=2048 \
--os-variant="rhel9-unknown" --import --graphics=none \
--disk=size=16,backing_store=/home/fedora/data/rhcos-9.8.20260314-0-qemu.x86_64.qcow2 \
--network network=default,mac=52:54:00:ab:ef:6a --qemu-commandline="-fw_cfg name=opt/com.coreos/config,file=${IGNITION_CONFIG}"
[core@localhost ~]$ cat /proc/sys/crypto/fips_enabled
1
```
1. Create cert and run nginx on server
```
podman run -d --name nginx -p 8443:8443 localhost/nginx:latest
```
2. Start client none FIPs with igintion to fetch the file successfully
```
IGNITION_CONFIG="/home/fedora/data/ign/non-fips.ign"
virt-install --connect="qemu:///system" --name=rhcos2 --vcpus=2 --memory=2048 \
--os-variant="rhel9-unknown" --import --graphics=none \
--disk=size=16,backing_store=/home/fedora/data/rhcos-9.8.20260314-0-qemu.x86_64.qcow2 \
--network network=default,mac=52:54:00:7b:55:63 --qemu-commandline="-fw_cfg name=opt/com.coreos/config,file=${IGNITION_CONFIG}"
[core@localhost ~]$ cat /proc/sys/crypto/fips_enabled
0
[core@localhost ~]$ cat /var/resource/https
This file was for testing.
```
---
Test server disabled FIPS and client enabled FIPS
* Start server with none FIPs
```
IGNITION_CONFIG="/home/fedora/data/ign/ssh.ign"
virt-install --connect="qemu:///system" --name=rhcos1 --vcpus=2 --memory=2048 \
--os-variant="rhel9-unknown" --import --graphics=none \
--disk=size=16,backing_store=/home/fedora/data/rhcos-9.8.20260314-0-qemu.x86_64.qcow2 \
--network network=default,mac=52:54:00:ab:ef:6a --qemu-commandline="-fw_cfg name=opt/com.coreos/config,file=${IGNITION_CONFIG}"
[core@localhost ~]$ cat /proc/sys/crypto/fips_enabled
0
```
1. Create cert and run nginx on server
```
podman run -d --name nginx -p 8443:8443 localhost/nginx:latest
```
2. Start client enabled FIPs with igintion to fetch the file successfully
```
IGNITION_CONFIG="/home/fedora/data/ign/fips-comp.ign"
virt-install --connect="qemu:///system" --name=rhcos2 --vcpus=2 --memory=2048 \
--os-variant="rhel9-unknown" --import --graphics=none \
--disk=size=16,backing_store=/home/fedora/data/rhcos-9.8.20260314-0-qemu.x86_64.qcow2 \
--network network=default,mac=52:54:00:7b:55:63 --qemu-commandline="-fw_cfg name=opt/com.coreos/config,file=${IGNITION_CONFIG}"
[core@localhost ~]$ cat /proc/sys/crypto/fips_enabled
1
[core@localhost ~]$ cat /var/resource/https
This file was for testing.
```
----
Run butane to translate the config to ign
```
butane -p fips.bu -o fips.ign
```
Create cert and build nginx (with default setting)
```
#!/usr/bin/env bash
# Run the image using command:
# podman run -d --name nginx -p 8443:8443 nginx
set -euo pipefail
# Check if argument is provided
if [ $# -eq 0 ]; then
echo "Error: Missing IP address argument"
echo "Usage: $0 <ip-address>"
exit 1
fi
IP="$1"
tmpdir="$(mktemp -d)"
cp Containerfile ${tmpdir}
cd ${tmpdir}
# Prepare index.html
cat <<EOF > index.html
This file was for testing.
EOF
# Prepare nginx.conf
cat <<EOF > nginx.conf
events {}
http {
server {
listen 8443 ssl;
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
}
EOF
mkdir -p ssl
pushd ssl/
# Prepare openssl.cnf
cat <<SSLEOF > openssl.cnf
[ req ]
distinguished_name = dn
prompt = no
[ dn ]
CN = Test Server
[ req_ext ]
subjectAltName = IP:${IP}
SSLEOF
# Prepare key and crt
## Generate the private key
openssl genpkey \
-algorithm RSA \
-out server.key
## Generate CSR
openssl req -new -key server.key -out server.csr -config openssl.cnf
## Self-sign the certificate
openssl x509 -req \
-in server.csr \
-signkey server.key \
-out server.crt \
-days 365 \
-extfile openssl.cnf \
-extensions req_ext
rm server.csr openssl.cnf
popd
podman build -t nginx .
```