Team Endeavour.
See the parent task for what to do.
—
Analysis:
This consists of the following workflows which need to be considered separately:
- ssh
- ssh-async
- pull
- cockpit
- setup on host registration
- UI and API
1), 2) and 4) don't use TLS, they use SSH. Pull mode uses a TLS connection.
Key setup on host registration also falls here. However, for testing just KEX, key shouldn't play a role and registration itself is a standalone component so from POV of this ticket, registration is N/A and thus ready. After all, in all the four workflows, the host needs to be registered first so it will be tested as well.
UI and API just needs verification that WebUI and API endpoints use ML-KEM when accessed by curl.
—
Verdict:
Ready WITH MINOR CHANGES
1) Doesn't use TLS -> nothing to do, READY (note that SSH requires version 9.9 for ML-KEM and Satellite runs on RHEL 9 which only has SSH version 8.7 so Satellite needs to be migrated to RHEL 10 for SSH to be PQC KEX ready)
2) Doesn't use TLS -> nothing to do, READY (note that SSH requires version 9.9 for ML-KEM and Satellite runs on RHEL 9 which only has SSH version 8.7 so Satellite needs to be migrated to RHEL 10 for SSH to be PQC KEX ready)
3) Uses MQTT over TLS. See steps for details. NOT READY, requires minor changes. Yggdrasil package needs to be compiled with Go >= 1.24.
4) Doesn't use TLS -> nothing to do, READY (note that SSH requires version 9.9 for ML-KEM and Satellite runs on RHEL 9 which only has SSH version 8.7 so Satellite needs to be migrated to RHEL 10 for SSH to be PQC KEX ready)
5) Host registration -> READY, nothing to do
6) UI and API -> READY
=>
—
Steps:
3) pull
Have a Satellite with manifest, RHEL repos (incl. client) synced, and run:
# cat <<EOF >>/etc/yum.repos.d/rhel97.repo [rhel97-baseos] name = RHEL 9.7 BaseOS baseurl = https://<DOWNLOAD>/rhel-9/nightly/RHEL-9/latest-RHEL-9.7/compose/BaseOS/x86_64/os/ metadata_expire = 1 enabled = 1 gpgcheck = 0[rhel97-appstream] name = RHEL 9.7 AppStream baseurl = https://<DOWNLOAD>/rhel-9/nightly/RHEL-9/latest-RHEL-9.7/compose/AppStream/x86_64/os/ metadata_expire = 1 enabled = 1 gpgcheck = 0 EOF # satellite-maintain packages unlock; dnf install -y openssl crypto-policies curl wireshark-cli; satellite-maintain packages lock # update-crypto-policies --set DEFAULT:PQ # reboot # satellite-installer --foreman-proxy-plugin-remote-execution-script-mode=pull-mqtt # firewall-cmd --add-service=mqtt # firewall-cmd --runtime-to-permanent
From Hosts -> Register, get a registration command and run on the host:
# set -o pipefail && curl --silent --show-error --insecure 'https://<FQDN>/register?activation_keys=testak9&download_utility=curl&location_id=2&organization_id=1&update_packages=false' --header 'Authorization: Bearer <TOKEN>' | bash # cat <<EOF >>/etc/yum.repos.d/rhel97.repo [rhel97-baseos] name = RHEL 9.7 BaseOS baseurl = https://<DOWNLOAD>/rhel-9/nightly/RHEL-9/latest-RHEL-9.7/compose/BaseOS/x86_64/os/ metadata_expire = 1 enabled = 1 gpgcheck = 0[rhel97-appstream] name = RHEL 9.7 AppStream baseurl = https://<DOWNLOAD>/rhel-9/nightly/RHEL-9/latest-RHEL-9.7/compose/AppStream/x86_64/os/ metadata_expire = 1 enabled = 1 gpgcheck = 0 EOF # dnf install -y openssl crypto-policies curl # update-crypto-policies --set DEFAULT:PQ # reboot # dnf install katello-pull-transport-migrate
On server:
tshark -f "tcp port 1883" -i any -w /tmp/test.pcap
Open the pcap file in Wireshark. Click the MQTT packet -> Protocol preferences -> MQTT -> Disable MQTT (so wireshark doesn't try to interpret the TLS encrypted communication as plain MQTT).
See that X25519 has been used which is NOT post-quantum.
=> Not ready
Let's try with s_client:
# openssl s_client -connect <FQDN>:1883 | grep Negotiated Negotiated TLS1.3 group: X25519MLKEM768
So server side (Mosquitto) actually supports ML-KEM (it uses OpenSSL https://github.com/eclipse-mosquitto/mosquitto ).
Let's see how yggdrasil implements TLS: https://github.com/search?q=repo%3ARedHatInsights%2Fyggdrasil+crypto%2Ftls&type=code
It doesn't use OpenSSL, it uses Go's own implementation. That actually supports ML-KEM, but only since version 1.24: https://github.com/golang/go/issues/69985 . Note that you can check with which Go version a binary has been compiled using `go version -m <binary>`.
How to fix it?
Ok, let's compile our own yggdrasil. Clone its git repo, checkout the commit tagged for the version of yggdrasil that's currently installed. Update golang package to 1.24 and then run `go get go@1.24.0` (see https://github.com/golang/go/issues/75453 for why that's necessary). Run the build steps from readme, ending with `make install`. Then through systemctl, stop service yggdrasil (that's the packaged version).
Then on the server:
# tshark -f "tcp port 1883" -i any -w /tmp/test.pcap
And on the client:
# systemctl start yggd
... and on the Satellite, start some REX job against that host.
Note that yggd is the version you compiled, as opposed to the old yggdrasild.
Open the captured .pcap file in Wireshark. In the TLS packets (for both Client and Server side handshake), see that X25519MLKEM768 (group 4588) has been used.
=> This is fixable by using newer Go to compile yggdrasil.
Just to be extra sure there is no other communication except this MQTT over TLS, let's:
# tshark -f "tcp port 443" -i any -w /tmp/test.pcap
Note port 443.
... and run some REX job against the host, I ran script `echo $(date) >> /tmp/test.txt`
Verify that the job actually ran (there's date in /tmp/test.txt).
Open the captured .pcap file in Wireshark and using filter "ip.addr == 10.0.168.220", verify that there was no communication between the host and the Satellite (there are no packets shown).
6) UI and API
# openssl s_client -connect <FQDN>:443 | grep Negotiated Negotiated TLS1.3 group: X25519MLKEM768 Negotiated TLS1.3 group: X25519MLKEM768
=> Ready, Apache uses OpenSSL and supports ML-KEM out of the box when enabled in crypto-policies. To be extra sure:
# tshark -f "tcp port 443" -i any -w /tmp/test.pcap
In another terminal:
For WebUI:
# curl https://<FQDN> <html><body>You are being <a href="https://<FQDN>/users/login">redirected</a>.</body></html>
For API:
# curl https://<FQDN>/api/v2/hosts -uadmin:changeme
For Hammer:
# hammer user list
In either case, open the .pcap file in Wireshark and inspect the handshake, see X25519MLKEM768 has been used.