Skip to content

Commit dedb665

Browse files
committed
x
Signed-off-by: Antonio Murdaca <antoniomurdaca@gmail.com>
1 parent 434b1ba commit dedb665

4 files changed

Lines changed: 643 additions & 0 deletions

File tree

Lines changed: 317 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,317 @@
1+
#! /usr/bin/env bash
2+
# Cross-version API compatibility test: Verify that the V1 and V2 management
3+
# APIs are interoperable. Configures the server using one API version and
4+
# verifies the data is correctly accessible via the other API version.
5+
# Then runs full onboarding to confirm the server works regardless of
6+
# which API version was used for setup.
7+
8+
set -euo pipefail
9+
10+
source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)/utils.sh"
11+
12+
# We do NOT source mgmt-api-v1.sh or mgmt-api-v2.sh here because we need
13+
# both API versions simultaneously. Instead we define prefixed wrappers that
14+
# call the specific API endpoints directly.
15+
16+
# ── V1 API helpers ──────────────────────────────────────────────────────────
17+
18+
v1_set_rendezvous_info() {
19+
local manufacturer_url=$1
20+
local rendezvous_info_json=$2
21+
curl --fail --verbose --silent --insecure \
22+
--request POST \
23+
--header 'Content-Type: application/json' \
24+
--data-raw "${rendezvous_info_json}" \
25+
"${manufacturer_url}/api/v1/rvinfo"
26+
}
27+
28+
v1_get_rendezvous_info() {
29+
local manufacturer_url=$1
30+
curl --fail --verbose --silent --insecure \
31+
--request GET \
32+
--header 'Content-Type: text/plain' \
33+
"${manufacturer_url}/api/v1/rvinfo"
34+
}
35+
36+
v1_set_rvto2addr() {
37+
local owner_url=$1
38+
local ip=$2
39+
local dns=$3
40+
local port=$4
41+
local protocol=$5
42+
local rvto2addr="[{\"ip\": \"${ip}\", \"dns\": \"${dns}\", \"port\": \"${port}\", \"protocol\": \"${protocol}\"}]"
43+
curl --fail --verbose --silent --insecure \
44+
--request POST \
45+
--header 'Content-Type: text/plain' \
46+
--data-raw "${rvto2addr}" \
47+
"${owner_url}/api/v1/owner/redirect"
48+
}
49+
50+
v1_get_rvto2addr() {
51+
local owner_url=$1
52+
curl --fail --verbose --silent --insecure \
53+
--header 'Content-Type: text/plain' \
54+
"${owner_url}/api/v1/owner/redirect"
55+
}
56+
57+
v1_get_ov_from_manufacturer() {
58+
local manufacturer_url=$1
59+
local guid=$2
60+
local output=$3
61+
curl --fail --verbose --silent --insecure \
62+
"${manufacturer_url}/api/v1/vouchers/${guid}" -o "${output}"
63+
}
64+
65+
v1_send_ov_to_owner() {
66+
local owner_url=$1
67+
local output=$2
68+
curl --fail --verbose --silent --insecure \
69+
--request POST \
70+
--data-binary "@${output}" \
71+
"${owner_url}/api/v1/owner/vouchers"
72+
}
73+
74+
v1_add_device_ca_cert() {
75+
local url=$1
76+
local crt=$2
77+
curl --fail --verbose --silent --insecure \
78+
--request POST \
79+
--header 'Content-Type: application/x-pem-file' \
80+
--data-binary @"${crt}" \
81+
"${url}/api/v1/device-ca"
82+
}
83+
84+
# ── V2 API helpers ──────────────────────────────────────────────────────────
85+
86+
v2_set_rendezvous_info() {
87+
local manufacturer_url=$1
88+
local rendezvous_info_json=$2
89+
curl --fail --verbose --silent --insecure \
90+
--request PUT \
91+
--header 'Content-Type: application/json' \
92+
--data-raw "${rendezvous_info_json}" \
93+
"${manufacturer_url}/api/v2/rvinfo"
94+
}
95+
96+
v2_get_rendezvous_info() {
97+
local manufacturer_url=$1
98+
curl --fail --verbose --silent --insecure \
99+
--header 'Accept: application/json' \
100+
--request GET \
101+
"${manufacturer_url}/api/v2/rvinfo"
102+
}
103+
104+
v2_set_rvto2addr() {
105+
local owner_url=$1
106+
local ip=$2
107+
local dns=$3
108+
local port=$4
109+
local protocol=$5
110+
local rvto2addr="[{\"ip\": \"${ip}\", \"dns\": \"${dns}\", \"port\": ${port}, \"protocol\": \"${protocol}\"}]"
111+
curl --fail --verbose --silent --insecure \
112+
--request PUT \
113+
--header 'Accept: application/json' \
114+
--header 'Content-Type: application/json' \
115+
--data-raw "${rvto2addr}" \
116+
"${owner_url}/api/v2/rvto2addr"
117+
}
118+
119+
v2_get_rvto2addr() {
120+
local owner_url=$1
121+
curl --fail --verbose --silent --insecure \
122+
--header 'Accept: application/json' \
123+
"${owner_url}/api/v2/rvto2addr"
124+
}
125+
126+
v2_get_ov_from_manufacturer() {
127+
local manufacturer_url=$1
128+
local guid=$2
129+
local output=$3
130+
curl --fail --verbose --silent --insecure \
131+
--header 'Accept: application/x-pem-file' \
132+
"${manufacturer_url}/api/v2/vouchers/${guid}" -o "${output}"
133+
}
134+
135+
v2_send_ov_to_owner() {
136+
local owner_url=$1
137+
local output=$2
138+
curl --fail --verbose --silent --insecure \
139+
--request POST \
140+
--header 'Content-Type: application/x-pem-file' \
141+
--data-binary "@${output}" \
142+
"${owner_url}/api/v2/vouchers"
143+
}
144+
145+
v2_add_device_ca_cert() {
146+
local url=$1
147+
local crt=$2
148+
curl --fail --verbose --silent --insecure \
149+
--header 'Content-Type: application/x-pem-file' \
150+
--data-binary @"${crt}" \
151+
"${url}/api/v2/device-ca"
152+
}
153+
154+
# ── RV info in both API formats ────────────────────────────────────────────
155+
156+
rv_info_v1="[{\"dns\": \"${rendezvous_dns}\", \"device_port\": \"${rendezvous_port}\", \"protocol\": \"${rendezvous_protocol}\", \"ip\": \"${rendezvous_ip}\", \"owner_port\": \"${rendezvous_port}\"}]"
157+
rv_info_v2="[[{\"dns\": \"${rendezvous_dns}\"}, {\"device_port\": ${rendezvous_port}}, {\"protocol\": \"${rendezvous_protocol}\"}, {\"ip\": \"${rendezvous_ip}\"}, {\"owner_port\": ${rendezvous_port}}]]"
158+
159+
# ── Test helpers ────────────────────────────────────────────────────────────
160+
161+
send_manufacturer_ov_to_owner_v1() {
162+
local manufacturer_url=$1
163+
local guid=$2
164+
local owner_url=$3
165+
local ov_dir="${base_dir}/ovs"
166+
mkdir -p "${ov_dir}"
167+
local ov_file="${ov_dir}/${guid}.ov"
168+
v1_get_ov_from_manufacturer "${manufacturer_url}" "${guid}" "${ov_file}"
169+
v1_send_ov_to_owner "${owner_url}" "${ov_file}"
170+
log_info "Waiting '${to0_wait_seconds}' seconds for TO0"
171+
sleep "${to0_wait_seconds}"
172+
}
173+
174+
send_manufacturer_ov_to_owner_v2() {
175+
local manufacturer_url=$1
176+
local guid=$2
177+
local owner_url=$3
178+
local ov_dir="${base_dir}/ovs"
179+
mkdir -p "${ov_dir}"
180+
local ov_file="${ov_dir}/${guid}.ov"
181+
v2_get_ov_from_manufacturer "${manufacturer_url}" "${guid}" "${ov_file}"
182+
v2_send_ov_to_owner "${owner_url}" "${ov_file}"
183+
log_info "Waiting '${to0_wait_seconds}' seconds for TO0"
184+
sleep "${to0_wait_seconds}"
185+
}
186+
187+
run_test() {
188+
189+
log_info "Setting the error trap handler"
190+
trap on_failure EXIT
191+
192+
log_info "Environment variables"
193+
show_env
194+
195+
log_info "Creating directories"
196+
create_directories
197+
198+
log_info "Generating service certificates"
199+
generate_service_certs
200+
201+
log_info "Build and install 'go-fdo-client' binary"
202+
install_client
203+
204+
log_info "Build and install 'go-fdo-server' binary"
205+
install_server
206+
207+
log_info "Configuring services"
208+
configure_services
209+
210+
log_info "Configure DNS and start services"
211+
start_services
212+
213+
log_info "Wait for the services to be ready:"
214+
wait_for_services_ready
215+
216+
# ── Phase 1: Configure with V1 API, verify with V2 API ──────────────────
217+
218+
log_info "=== Phase 1: Configure via V1 API, verify via V2 API ==="
219+
220+
log_info "Setting RendezvousInfo via V1 API"
221+
v1_set_rendezvous_info "${manufacturer_url}" "${rv_info_v1}"
222+
223+
log_info "Reading back RendezvousInfo via V2 API"
224+
v2_rv_result=$(v2_get_rendezvous_info "${manufacturer_url}")
225+
log_info "V2 API returned: ${v2_rv_result}"
226+
[ -n "${v2_rv_result}" ] || log_error "V2 API returned empty RendezvousInfo"
227+
[ "${v2_rv_result}" != "null" ] || log_error "V2 API returned null RendezvousInfo"
228+
log_success "V1->V2 RendezvousInfo cross-read succeeded"
229+
230+
log_info "Adding Device CA certificate via V1 API to rendezvous"
231+
v1_add_device_ca_cert "${rendezvous_url}" "${device_ca_crt}" | jq -r -M .
232+
233+
log_info "Setting RVTO2Addr via V1 API"
234+
real_owner_ip="$(get_real_ip "${owner_service_name}")"
235+
v1_set_rvto2addr "${owner_url}" "${real_owner_ip}" "${owner_dns}" "${owner_port}" "${owner_protocol}"
236+
237+
log_info "Reading back RVTO2Addr via V2 API"
238+
v2_redirect=$(v2_get_rvto2addr "${owner_url}")
239+
log_info "V2 API returned: ${v2_redirect}"
240+
[ -n "${v2_redirect}" ] || log_error "V2 API returned empty RVTO2Addr"
241+
[ "${v2_redirect}" != "null" ] || log_error "V2 API returned null RVTO2Addr"
242+
log_success "V1->V2 RVTO2Addr cross-read succeeded"
243+
244+
log_info "Run Device Initialization (Phase 1)"
245+
guid1=$(run_device_initialization)
246+
log_info "Device initialized with GUID: ${guid1}"
247+
248+
log_info "Sending Ownership Voucher to Owner via V1 API"
249+
send_manufacturer_ov_to_owner_v1 "${manufacturer_url}" "${guid1}" "${owner_url}"
250+
251+
log_info "Running FIDO Device Onboard (V1 setup)"
252+
run_fido_device_onboard "${guid1}" --debug || log_error "Onboarding after V1 setup failed!"
253+
log_success "Phase 1 (V1 setup) onboarding succeeded"
254+
255+
# ── Phase 2: Configure with V2 API, verify with V1 API ──────────────────
256+
257+
log_info "=== Phase 2: Configure via V2 API, verify via V1 API ==="
258+
259+
log_info "Setting RendezvousInfo via V2 API"
260+
v2_set_rendezvous_info "${manufacturer_url}" "${rv_info_v2}"
261+
262+
log_info "Reading back RendezvousInfo via V1 API"
263+
v1_rv_result=$(v1_get_rendezvous_info "${manufacturer_url}")
264+
log_info "V1 API returned: ${v1_rv_result}"
265+
[ -n "${v1_rv_result}" ] || log_error "V1 API returned empty RendezvousInfo"
266+
[ "${v1_rv_result}" != "null" ] || log_error "V1 API returned null RendezvousInfo"
267+
log_success "V2->V1 RendezvousInfo cross-read succeeded"
268+
269+
log_info "Setting RVTO2Addr via V2 API"
270+
v2_set_rvto2addr "${owner_url}" "${real_owner_ip}" "${owner_dns}" "${owner_port}" "${owner_protocol}"
271+
272+
log_info "Reading back RVTO2Addr via V1 API"
273+
v1_redirect=$(v1_get_rvto2addr "${owner_url}")
274+
log_info "V1 API returned: ${v1_redirect}"
275+
[ -n "${v1_redirect}" ] || log_error "V1 API returned empty RVTO2Addr"
276+
[ "${v1_redirect}" != "null" ] || log_error "V1 API returned null RVTO2Addr"
277+
log_success "V2->V1 RVTO2Addr cross-read succeeded"
278+
279+
log_info "Run Device Initialization (Phase 2)"
280+
guid2=$(run_device_initialization)
281+
log_info "Device initialized with GUID: ${guid2}"
282+
283+
log_info "Sending Ownership Voucher to Owner via V2 API"
284+
send_manufacturer_ov_to_owner_v2 "${manufacturer_url}" "${guid2}" "${owner_url}"
285+
286+
log_info "Running FIDO Device Onboard (V2 setup)"
287+
run_fido_device_onboard "${guid2}" --debug || log_error "Onboarding after V2 setup failed!"
288+
log_success "Phase 2 (V2 setup) onboarding succeeded"
289+
290+
# ── Phase 3: Mixed V1/V2 setup ──────────────────────────────────────────
291+
292+
log_info "=== Phase 3: Mixed API setup (V2 rvinfo, V1 voucher) ==="
293+
294+
log_info "Setting RendezvousInfo via V2 API"
295+
v2_set_rendezvous_info "${manufacturer_url}" "${rv_info_v2}"
296+
297+
log_info "Run Device Initialization (Phase 3)"
298+
guid3=$(run_device_initialization)
299+
log_info "Device initialized with GUID: ${guid3}"
300+
301+
log_info "Sending Ownership Voucher to Owner via V1 API (mixed)"
302+
send_manufacturer_ov_to_owner_v1 "${manufacturer_url}" "${guid3}" "${owner_url}"
303+
304+
log_info "Running FIDO Device Onboard (mixed V1/V2 setup)"
305+
run_fido_device_onboard "${guid3}" --debug || log_error "Onboarding after mixed V1/V2 setup failed!"
306+
log_success "Phase 3 (mixed V1/V2) onboarding succeeded"
307+
308+
log_info "Unsetting the error trap handler"
309+
trap - EXIT
310+
test_pass
311+
}
312+
313+
# Allow running directly
314+
[[ "${BASH_SOURCE[0]}" != "$0" ]] || {
315+
run_test
316+
cleanup
317+
}

0 commit comments

Comments
 (0)