Skip to content

Commit 3261669

Browse files
committed
tests: add fips.enable.tls
To verify that using TLS works in FIPS mode by having Ignition fetch a remote resource over HTTPS with FIPS compatible algorithms. tests/containers: build the container based on `nginx-126:10.1`. See Timothee's comment #4477 (comment) Fixes https://issues.redhat.com/browse/COS-3487
1 parent 8d815ea commit 3261669

4 files changed

Lines changed: 218 additions & 0 deletions

File tree

mantle/kola/tests/fips/fips.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,70 @@ func init() {
140140
}
141141
}`),
142142
})
143+
// Test that using TLS works in FIPS mode by having Ignition fetch
144+
// a remote resource over HTTPS with FIPS compatible algorithms.
145+
// See https://issues.redhat.com/browse/COS-3487
146+
// Note that 34.172.244.189, running RHCOS 9.6 (build 20260312-0) on
147+
// Google Cloud Platform, provides HTTPS services using nginx-126:10.1.
148+
register.RegisterTest(&register.Test{
149+
Run: fipsEnableTestTLS,
150+
ClusterSize: 1,
151+
Name: `fips.enable.tls`,
152+
Description: "Verify that fips enabled works if fetching a remote resource over HTTPS with FIPS compatible algorithms.",
153+
Flags: []register.Flag{},
154+
Tags: []string{kola.NeedsInternetTag},
155+
Distros: []string{"rhcos"},
156+
Platforms: []string{"qemu"},
157+
ExcludeArchitectures: []string{"s390x", "ppc64le", "aarch64"}, // only test on x86_64
158+
UserData: conf.Ignition(`{
159+
"ignition": {
160+
"config": {
161+
"replace": {
162+
"source": null,
163+
"verification": {}
164+
}
165+
},
166+
"security": {
167+
"tls": {
168+
"certificateAuthorities": [
169+
{
170+
"compression": "gzip",
171+
"source": "data:;base64,H4sIAAAAAAAC/2SUTdN7yhbF5z7FnaduIUEY/AfdNFoQ2luYeUkkSLwk0fj0t57nnsk5Zw9/u2rV3lVrrf/+DEQGdv+jIhJiHasgRL+UcTBGVqOqoJdqQDEENY4q7G3jjqz64bkgmSjY2p8qKY3Gm0w1P7VOfYbvc+kCH9kM9AE1N1Q58G0APkKA0oi0nR+tMAp1p46NeKtUGGYXa59dMDXvpes0KXU2tHc0Z2PcBgjJD9x+4fYDf1kDbg7hqEFTLfZ9TYPECGIYYp04P+LZxeWw7nZM+cq68ueFHP/zPAh9oNW14QFNVUHaq3VtQHBWT5t93FhwWUnrFkyamb0KudwI1bgZ+jV86+TQaPrgrd/RvQRx+Xqx6lfffdnAi9FQTRw82PZ8HHM7Gt6IeaTV10vepwcr0iU/QLV250dMAquRsMi/rIJevXRV71auDPfnyVnHiD9UX4ukfUm5cGJkdr29FkGZ/DU58SQxrnjd9p/yAu+cgNL7JXq3j0oxd16NyiU3z+5bYyH5HK6NhTg5Y9J7labtJrhbee+zXBdD+7LGb42PLOOCbqoyfBp/93jvZBIBj6gGXwvCEsjE6q5o2iSGNe/EjLESWAdPw71i2EmRnCO22Y1k0i41HjGZaQLzaiM8r4kbDH3xewJdNBjhfh0ZGpTmt67ZfuLOYdjxwPJt4dh9RN/3Ba9LV78JzkjK0+rrV97xHamGieTUaRcqNVNxYdgPp5tRKtgt0PSg+wglmZ7obbN+cfNuR1JkJPLMJSx2tO1Pb+jtxnCJCpR3W8EOiGWaC8LlXZ9nT0nEJyeJm2iwTzRW/Km6Yrn189YdH5Y3Fy2K1OJT+VgDPoA939NEA2cG1m5s+jIENxlB4KgwB1SvUy0mXAd8k4WAUrVO8YmmEPqRCSiiGv3dEwhqysC+RHjcuDkE1f/FBKTXfpSRh97WU19wD/tV3W6NMRK2z0HSvf/mWOYnUX9ZFgI7MvEKKldoWtHGxSRxfLc9bbQrzSORUfLm2t2J3Bw42QVnTblbl4ww4DnmpaGN6OOuxKL79dTj7LqlPtcfH3vqK2XBC93VVzwavjTN+hnskvauGroj3Z4z442peDVjPXB4urDVFX8qsv924b7x7fuXaytdrbqyy53RL0r5my2udheyLWPJcHh6t5yZi5zjnEAxTRgeh+oRDpwkhnOunL/pQRjchO3LaPwaSuLkDs/HhqodOno6JA9BZsPYZ9BgdPPgKB9l1z/H9X3L8uU11Hv/6gSTZXpsGxm4Ts/24SbbT1pehxgCjh7XYY1Dc5KYqyh5tBYH/bk/vtbDHLgW/+yt83gTr1McTwczY08UWFIvfchVldSHYixka6XAN4lyEZinOkjjINfRNRpa3iuUs77t94NcgU8U7j6FtV0TCWTp7Qym5jn1jvupgkCKYuqEyhlhpig1gy0fs7mEuCi8ERNxt1R5+hHP5SZPX1AH1evyXCuzfZeP5uRVbNLbXbZ8UBvIw5tZtt1wqIKDRXA81H/+ML9ljVzt3wX+vwAAAP//bBEEnd0FAAA="
172+
}
173+
]
174+
}
175+
},
176+
"timeouts": {},
177+
"version": "3.4.0"
178+
},
179+
"passwd": {},
180+
"storage": {
181+
"files": [
182+
{
183+
"group": {
184+
"name": "root"
185+
},
186+
"overwrite": true,
187+
"path": "/etc/ignition-machine-config-encapsulated.json",
188+
"user": {
189+
"name": "root"
190+
},
191+
"contents": {
192+
"source": "data:,%7B%22metadata%22%3A%7B%22name%22%3A%22rendered-worker-1cc576110e0cf8396831ce4016f63900%22%2C%22selfLink%22%3A%22%2Fapis%2Fmachineconfiguration.openshift.io%2Fv1%2Fmachineconfigs%2Frendered-worker-1cc576110e0cf8396831ce4016f63900%22%2C%22uid%22%3A%2248871c03-899d-4332-a5f5-bef94e54b23f%22%2C%22resourceVersion%22%3A%224168%22%2C%22generation%22%3A1%2C%22creationTimestamp%22%3A%222019-11-04T15%3A54%3A08Z%22%2C%22annotations%22%3A%7B%22machineconfiguration.openshift.io%2Fgenerated-by-controller-version%22%3A%22bd846958bc95d049547164046a962054fca093df%22%7D%2C%22ownerReferences%22%3A%5B%7B%22apiVersion%22%3A%22machineconfiguration.openshift.io%2Fv1%22%2C%22kind%22%3A%22MachineConfigPool%22%2C%22name%22%3A%22worker%22%2C%22uid%22%3A%223d0dee9e-c9d6-4656-a4a9-81785b9ab01a%22%2C%22controller%22%3Atrue%2C%22blockOwnerDeletion%22%3Atrue%7D%5D%7D%2C%22spec%22%3A%7B%22osImageURL%22%3A%22registry.svc.ci.openshift.org%2Focp%2F4.3-2019-11-04-125204%40sha256%3A8a344c5b157bd01c3ca1abfcef0004fc39f5d69cac1cdaad0fd8dd332ad8e272%22%2C%22config%22%3A%7B%22ignition%22%3A%7B%22config%22%3A%7B%7D%2C%22security%22%3A%7B%22tls%22%3A%7B%7D%7D%2C%22timeouts%22%3A%7B%7D%2C%22version%22%3A%223.0.0%22%7D%2C%22networkd%22%3A%7B%7D%2C%22passwd%22%3A%7B%7D%2C%22storage%22%3A%7B%7D%2C%22systemd%22%3A%7B%7D%7D%2C%22kernelArguments%22%3A%5B%5D%2C%22fips%22%3Atrue%7D%7D",
193+
"verification": {}
194+
},
195+
"mode": 420
196+
},
197+
{
198+
"path": "/var/resource/https-fips",
199+
"contents": {
200+
"source": "https://34.172.244.189:8443/index.html"
201+
}
202+
}
203+
]
204+
}
205+
}`),
206+
})
143207
}
144208

145209
// Test: Run basic FIPS test
@@ -148,3 +212,9 @@ func fipsEnableTest(c cluster.TestCluster) {
148212
c.AssertCmdOutputContains(m, `cat /proc/sys/crypto/fips_enabled`, "1")
149213
c.AssertCmdOutputContains(m, `update-crypto-policies --show`, "FIPS")
150214
}
215+
216+
func fipsEnableTestTLS(c cluster.TestCluster) {
217+
fipsEnableTest(c)
218+
m := c.Machines()[0]
219+
c.AssertCmdOutputContains(m, `cat /var/resource/https-fips`, "This file was served from an RHCOS FIPS-hardened server.")
220+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
FROM registry.redhat.io/rhel10/nginx-126:10.1
2+
3+
ADD nginx.conf "${NGINX_CONF_PATH}"
4+
5+
COPY index.html /usr/share/nginx/html/index.html
6+
7+
# TLS material
8+
USER 0
9+
COPY tls/ /etc/nginx/tls/
10+
RUN chown -R 1001:0 /etc/nginx/tls
11+
USER 1001
12+
13+
CMD ["nginx", "-g", "daemon off;"]
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# fips-nginx Container
2+
3+
This is used by the `fips.enable.https` test to verify that using
4+
TLS works in FIPS mode by having Ignition fetch a remote resource
5+
over HTTPS with FIPS compatible algorithms.
6+
7+
See https://catalog.redhat.com/en/software/containers/rhel10/nginx-126/677d3718e58b5a1ae5598058#overview
8+
9+
To build the container using command:
10+
`./build.sh <IP>`
11+
12+
To run the container image using command:
13+
`podman run -d -p 8443:8443 --name fips-nginx fips-nginx`
14+
15+
Remember to create firewall-rules to allow port 8443:
16+
```
17+
gcloud compute firewall-rules create allow-nginx-fips-8443 \
18+
--action ALLOW \
19+
--direction INGRESS \
20+
--rules tcp:8443 \
21+
--source-ranges 0.0.0.0/0 \
22+
--target-tags nginx-fips-server \
23+
--description "Allow FIPS test access to nginx on port 8443"
24+
25+
gcloud compute instances add-tags rhcos-fips-test \
26+
--zone us-central1-a \
27+
--tags nginx-fips-server
28+
```
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
#!/usr/bin/env bash
2+
3+
# Run the image using command:
4+
# podman run -d --name fips-nginx -p 8443:8443 fips-nginx
5+
set -euo pipefail
6+
7+
# Check if argument is provided
8+
if [ $# -eq 0 ]; then
9+
echo "Error: Missing IP address argument"
10+
echo "Usage: $0 <ip-address>"
11+
exit 1
12+
fi
13+
14+
ip="$1"
15+
16+
tmpdir="$(mktemp -d)"
17+
cp Containerfile ${tmpdir}
18+
cd ${tmpdir}
19+
20+
# Prepare index.html
21+
cat <<EOF > index.html
22+
This file was served from an RHCOS FIPS-hardened server.
23+
EOF
24+
25+
# Prepare nginx.conf
26+
cat <<EOF > nginx.conf
27+
events {}
28+
29+
http {
30+
server {
31+
listen 8443 ssl;
32+
server_name _;
33+
34+
# ---- FIPS-only TLS ----
35+
ssl_protocols TLSv1.2;
36+
ssl_prefer_server_ciphers on;
37+
38+
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256;
39+
40+
ssl_certificate /etc/nginx/tls/fips-server.crt;
41+
ssl_certificate_key /etc/nginx/tls/fips-server.key;
42+
43+
location / {
44+
root /usr/share/nginx/html;
45+
index index.html;
46+
}
47+
}
48+
}
49+
EOF
50+
51+
mkdir -p tls
52+
pushd tls/
53+
# Prepare openssl.cnf
54+
# The IP must point to an nginx server configured with FIPS-compliant ciphers
55+
cat <<SSLEOF > openssl.cnf
56+
[ req ]
57+
default_bits = 3072
58+
distinguished_name = dn
59+
prompt = no
60+
string_mask = utf8only
61+
req_extensions = req_ext
62+
63+
[ dn ]
64+
CN = FIPS TLS Test Server
65+
66+
[ req_ext ]
67+
keyUsage = critical, digitalSignature, keyEncipherment
68+
extendedKeyUsage = critical, serverAuth
69+
subjectAltName = @alt_names
70+
71+
[ alt_names ]
72+
IP.1 = ${ip}
73+
SSLEOF
74+
75+
# Prepare key and crt
76+
## Generate the private key (FIPS-approved)
77+
openssl genpkey \
78+
-algorithm RSA \
79+
-pkeyopt rsa_keygen_bits:3072 \
80+
-out fips-server.key
81+
82+
## Generate CSR (still FIPS-only)
83+
openssl req -new -key fips-server.key -out fips-server.csr -config openssl.cnf
84+
85+
## Self-sign the certificate (TLS-compatible + FIPS)
86+
openssl x509 -req \
87+
-in fips-server.csr \
88+
-signkey fips-server.key \
89+
-out fips-server.crt \
90+
-days 3650 \
91+
-sha256 \
92+
-extfile openssl.cnf \
93+
-extensions req_ext
94+
95+
# Verify SAN present
96+
openssl x509 -in fips-server.crt -noout -text | grep -A2 "Subject Alternative Name"
97+
98+
openssl verify \
99+
-provider fips \
100+
-CAfile fips-server.crt \
101+
fips-server.crt
102+
103+
rm fips-server.csr openssl.cnf
104+
105+
popd
106+
107+
podman build -t fips-nginx .

0 commit comments

Comments
 (0)