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 . ```