Skip to content

Commit 3a28ce4

Browse files
committed
tuftool: add manual testing steps for FIPS tuf repos
Add instructions and resources for manually testing tuftool's FIPS feature to allow for easily repeatable testing. The instructions walk through creating a local TUF repo, serving the TUF repo via a Docker container, and downloading the repo via tuftool. Signed-off-by: Gavin Inglis <giinglis@amazon.com>
1 parent c0d27ad commit 3a28ce4

File tree

8 files changed

+343
-0
lines changed

8 files changed

+343
-0
lines changed

tuftool/fips-test/.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Ignore artifacts created during test.
2+
test-fips-tough/
3+
test-keys/
4+
test-tuf-repo/

tuftool/fips-test/Dockerfile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
FROM public.ecr.aws/nginx/nginx:latest
2+
3+
RUN apt update && apt upgrade -y
4+
RUN mkdir -p /etc/pki/tls/certs
5+
RUN mkdir -p /etc/pki/tls/private

tuftool/fips-test/README.md

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# Testing tough FIPS feature
2+
3+
The following are steps to take to test FIPS support with `tough` and `tuftool`.
4+
Steps will walk through creating a TUF repo, hosting the repo via Docker containers running nginx, and testing `tuftool download` against servers using FIPS and non-FIPS ciphers.
5+
6+
## Install tuftool
7+
8+
```sh
9+
# From latest release
10+
$ cargo install --force tuftool --all-features
11+
```
12+
13+
```sh
14+
# From local changes
15+
$ cargo install --path ../../tuftool --all-features
16+
```
17+
18+
## Create TUF repo
19+
20+
```sh
21+
$ mkdir -p test-tuf-repo test-keys
22+
$ ./scripts/create-tuf-repo.sh
23+
```
24+
25+
This will create the repo under the "test-tuf-repo" directory and a key for signing the TUF repo under "test-keys".
26+
27+
## Create keys
28+
29+
```sh
30+
$ ./scripts/create-server-keys.sh
31+
```
32+
33+
Trust the generated server Certificate Authority on your host:
34+
35+
```sh
36+
sudo trust anchor --store ./test-keys/ca.crt
37+
```
38+
39+
## Build the tough-fips-testing container
40+
41+
```sh
42+
docker build . -t tough-fips-testing:latest
43+
```
44+
45+
## Run the server with FIPS
46+
47+
```sh
48+
docker run --rm -p 8080:443 \
49+
-v ./configs/nginx-fips.conf:/etc/nginx/nginx.conf \
50+
-v ./test-tuf-repo/out/metadata:/usr/share/nginx/html/metadata \
51+
-v ./test-tuf-repo/out/targets:/usr/share/nginx/html/targets \
52+
--mount type=bind,src=./test-keys/server.crt,dst=/etc/pki/tls/certs/domain.crt \
53+
--mount type=bind,src=./test-keys/server.key,dst=/etc/pki/tls/private/domain.key \
54+
tough-fips-testing:latest
55+
```
56+
57+
Test repo download:
58+
59+
```sh
60+
tuftool download -r ./test-tuf-repo/1.root.json \
61+
--targets-url https://localhost:8080/targets \
62+
--metadata-url https://localhost:8080/metadata \
63+
test-fips-tough
64+
```
65+
66+
Should succeed with:
67+
68+
```
69+
Downloading targets to "test-fips-tough"
70+
```
71+
72+
Clean up the downloaded repo:
73+
74+
```sh
75+
rm -rf test-fips-tough/
76+
```
77+
78+
**Stop the Docker container.**
79+
80+
## Run the server with non-FIPS ciphers
81+
82+
```sh
83+
docker run --rm -p 8080:443 \
84+
-v ./configs/nginx.conf:/etc/nginx/nginx.conf \
85+
-v ./test-tuf-repo/out/metadata:/usr/share/nginx/html/metadata \
86+
-v ./test-tuf-repo/out/targets:/usr/share/nginx/html/targets \
87+
--mount type=bind,src=./test-keys/server.crt,dst=/etc/pki/tls/certs/domain.crt \
88+
--mount type=bind,src=./test-keys/server.key,dst=/etc/pki/tls/private/domain.key \
89+
tough-fips-testing:latest
90+
```
91+
92+
Test repo download:
93+
94+
```sh
95+
tuftool download -r ./test-tuf-repo/1.root.json \
96+
--targets-url https://localhost:8080/targets \
97+
--metadata-url https://localhost:8080/metadata \
98+
test-fips-tough
99+
```
100+
101+
Expect failure:
102+
103+
```
104+
Failed to load repository: Failed to fetch https://localhost:8080/metadata/2.root.json: Transport 'other' error fetching 'https://localhost:8080/metadata/2.root.json': error sending request for url (https://localhost:8080/metadata/2.root.json)
105+
```
106+
107+
# Clean up
108+
109+
```
110+
rm -rf test-tuf-repo/
111+
rm -rf test-keys/
112+
rm -rf test-fips-tough/
113+
```

tuftool/fips-test/configs/csr.conf.in

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
[ req ]
2+
default_bits = 2048
3+
prompt = no
4+
default_md = sha256
5+
distinguished_name = dn
6+
req_extensions = req_ext
7+
8+
[ dn ]
9+
C = US
10+
ST = WASHINGTON
11+
L = Seattle
12+
O = Bottlerocket
13+
OU = Bottlerocket Dev
14+
15+
[ req_ext ]
16+
subjectAltName = @alt_names
17+
18+
[ alt_names ]
19+
DNS.1 = localhost
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# For more information on configuration, see:
2+
# * Official English Documentation: http://nginx.org/en/docs/
3+
# * Official Russian Documentation: http://nginx.org/ru/docs/
4+
5+
user nginx;
6+
worker_processes auto;
7+
error_log /var/log/nginx/error.log debug;
8+
pid /run/nginx.pid;
9+
10+
# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
11+
include /usr/share/nginx/modules/*.conf;
12+
13+
events {
14+
worker_connections 1024;
15+
}
16+
17+
http {
18+
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
19+
'$status $body_bytes_sent "$http_referer" '
20+
'"$http_user_agent" "$http_x_forwarded_for"';
21+
22+
access_log /var/log/nginx/access.log main;
23+
24+
sendfile on;
25+
tcp_nopush on;
26+
keepalive_timeout 65;
27+
types_hash_max_size 4096;
28+
29+
include /etc/nginx/mime.types;
30+
default_type application/octet-stream;
31+
# Load modular configuration files from the /etc/nginx/conf.d directory.
32+
# See http://nginx.org/en/docs/ngx_core_module.html#include
33+
# for more information.
34+
include /etc/nginx/conf.d/*.conf;
35+
36+
server {
37+
listen 80;
38+
listen [::]:80;
39+
server_name localhost;
40+
root /usr/share/nginx/html;
41+
42+
# Load configuration files for the default server block.
43+
include /etc/nginx/default.d/*.conf;
44+
}
45+
46+
# Settings for a TLS enabled server.
47+
48+
server {
49+
listen 443 ssl;
50+
listen [::]:443 ssl;
51+
http2 on;
52+
server_name localhost;
53+
root /usr/share/nginx/html;
54+
55+
ssl_certificate "/etc/pki/tls/certs/domain.crt";
56+
ssl_certificate_key "/etc/pki/tls/private/domain.key";
57+
ssl_session_cache shared:SSL:1m;
58+
ssl_session_timeout 10m;
59+
60+
ssl_protocols TLSv1.2 TLSv1.3;
61+
62+
ssl_ciphers 'TLSv1.2+FIPS:kRSA+FIPS:!eNULL:!aNULL';
63+
64+
# Load configuration files for the default server block.
65+
include /etc/nginx/default.d/*.conf;
66+
67+
}
68+
69+
}

tuftool/fips-test/configs/nginx.conf

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# For more information on configuration, see:
2+
# * Official English Documentation: http://nginx.org/en/docs/
3+
# * Official Russian Documentation: http://nginx.org/ru/docs/
4+
5+
user nginx;
6+
worker_processes auto;
7+
error_log /var/log/nginx/error.log debug;
8+
pid /run/nginx.pid;
9+
10+
# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
11+
include /usr/share/nginx/modules/*.conf;
12+
13+
events {
14+
worker_connections 1024;
15+
}
16+
17+
http {
18+
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
19+
'$status $body_bytes_sent "$http_referer" '
20+
'"$http_user_agent" "$http_x_forwarded_for"';
21+
22+
access_log /var/log/nginx/access.log main;
23+
24+
sendfile on;
25+
tcp_nopush on;
26+
keepalive_timeout 65;
27+
types_hash_max_size 4096;
28+
29+
include /etc/nginx/mime.types;
30+
default_type application/octet-stream;
31+
# Load modular configuration files from the /etc/nginx/conf.d directory.
32+
# See http://nginx.org/en/docs/ngx_core_module.html#include
33+
# for more information.
34+
include /etc/nginx/conf.d/*.conf;
35+
36+
server {
37+
listen 80;
38+
listen [::]:80;
39+
server_name localhost;
40+
root /usr/share/nginx/html;
41+
42+
# Load configuration files for the default server block.
43+
include /etc/nginx/default.d/*.conf;
44+
}
45+
46+
# Settings for a TLS enabled server.
47+
48+
server {
49+
listen 443 ssl;
50+
listen [::]:443 ssl;
51+
http2 on;
52+
server_name localhost;
53+
root /usr/share/nginx/html;
54+
55+
ssl_certificate "/etc/pki/tls/certs/domain.crt";
56+
ssl_certificate_key "/etc/pki/tls/private/domain.key";
57+
ssl_session_cache shared:SSL:1m;
58+
ssl_session_timeout 10m;
59+
60+
ssl_protocols TLSv1.2 TLSv1.3;
61+
62+
ssl_conf_command Ciphersuites TLS_CHACHA20_POLY1305_SHA256;
63+
64+
# Load configuration files for the default server block.
65+
include /etc/nginx/default.d/*.conf;
66+
67+
}
68+
69+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/bin/sh
2+
3+
set -e
4+
5+
mkdir -p test-keys
6+
7+
openssl genrsa -out test-keys/server.key 2048
8+
openssl req -new -key test-keys/server.key -out test-keys/server.csr -config ./configs/csr.conf.in
9+
10+
# Generate CA certificate
11+
openssl genrsa -out test-keys/ca.key 2048 \
12+
&& openssl req -x509 -new -nodes -key test-keys/ca.key \
13+
-subj "/CN=bottlerocket/C=US/L=WASHINGTON" -days 1825 -out test-keys/ca.crt
14+
15+
openssl dhparam -out test-keys/dhparam.pem 2098
16+
17+
openssl x509 -req -in test-keys/server.csr -CA test-keys/ca.crt -CAkey test-keys/ca.key \
18+
-CAcreateserial -out test-keys/server.crt -days 10000 -extensions req_ext \
19+
-extfile ./configs/csr.conf.in
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
ALIAS_SUFFIX=$(date "+%Y-%m-%d")
6+
TEST_TUF_REPO_PATH="./test-tuf-repo"
7+
TEST_KEYS_PATH="test-keys"
8+
9+
tuftool root init --version 1 "${TEST_TUF_REPO_PATH}/1.root.json"
10+
11+
tuftool root gen-rsa-key "${TEST_TUF_REPO_PATH}/1.root.json" "${TEST_KEYS_PATH}/root.pem" --role root
12+
13+
expiration_date=$(date -d "${ALIAS_SUFFIX} + 2 weeks" --iso-8601=date -u)T00:00:00+00:00
14+
15+
tuftool root expire "${TEST_TUF_REPO_PATH}/1.root.json" "${expiration_date}"
16+
17+
tuftool root set-threshold "${TEST_TUF_REPO_PATH}/1.root.json" root 1
18+
tuftool root set-threshold "${TEST_TUF_REPO_PATH}/1.root.json" snapshot 1
19+
tuftool root set-threshold "${TEST_TUF_REPO_PATH}/1.root.json" targets 1
20+
tuftool root set-threshold "${TEST_TUF_REPO_PATH}/1.root.json" timestamp 1
21+
22+
# Add keys
23+
tuftool root add-key "${TEST_TUF_REPO_PATH}/1.root.json" \
24+
-k "${TEST_KEYS_PATH}/root.pem" \
25+
-r root
26+
27+
tuftool root add-key "${TEST_TUF_REPO_PATH}/1.root.json" \
28+
-k "${TEST_KEYS_PATH}/root.pem" \
29+
-r snapshot -r targets -r timestamp
30+
31+
tuftool root add-key "${TEST_TUF_REPO_PATH}/1.root.json" \
32+
-k "${TEST_KEYS_PATH}/root.pem" \
33+
-r timestamp
34+
35+
# Sign
36+
tuftool root sign "${TEST_TUF_REPO_PATH}/1.root.json" \
37+
-k "${TEST_KEYS_PATH}/root.pem"
38+
39+
mkdir -p "${TEST_TUF_REPO_PATH}/empty"
40+
tuftool create \
41+
-t "${TEST_TUF_REPO_PATH}/empty" --outdir "${TEST_TUF_REPO_PATH}/out" --root "${TEST_TUF_REPO_PATH}/1.root.json" \
42+
-k "${TEST_KEYS_PATH}/root.pem" \
43+
--snapshot-expires 'in 7 days' --snapshot-version "$(date +%s)" \
44+
--targets-expires 'in 7 days' --targets-version "$(date +%s)" \
45+
--timestamp-expires 'in 7 days' --timestamp-version "$(date +%s)"

0 commit comments

Comments
 (0)