Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -264,3 +264,46 @@
run: |
source test/ci/test-onboarding-config.sh
cleanup

test-rv-bypass:
name: Test RV bypass (skip TO1)
runs-on: ubuntu-latest
steps:
- name: Install golang
uses: actions/setup-go@v5
with:
go-version: "1.25"

- name: Check out server repository code
uses: actions/checkout@v4
with:
path: go-fdo-server

# TODO: Update to upstream once RV bypass PR is merged in go-fdo-client

Check notice

Code scanning / devskim

A "TODO" or similar was left in source code, possibly indicating incomplete functionality Note

Suspicious comment
# Tracking: https://github.com/fido-device-onboard/go-fdo-client/pull/38
- name: Check out client repository code with RV bypass support
uses: actions/checkout@v4
with:
repository: sarmahaj/go-fdo-client
ref: pr20-rv-bypass-fixes
path: go-fdo-client

- name: Test RV bypass functionality
run: |
cd go-fdo-server
source test/ci/test-rv-bypass.sh
run_test

- name: Get manufacturer and owner server logs
if: always()
run: |
cd go-fdo-server
source test/ci/test-rv-bypass.sh
get_logs

- name: Cleanup the environment
if: always()
run: |
cd go-fdo-server
source test/ci/test-rv-bypass.sh
cleanup
44 changes: 44 additions & 0 deletions .github/workflows/containers.yml
Original file line number Diff line number Diff line change
Expand Up @@ -250,3 +250,47 @@
run: |
source test/container/test-onboarding-config.sh
cleanup

test-container-rv-bypass:
name: Test RV bypass (skip TO1)
runs-on: ubuntu-latest
steps:

- name: Install golang
uses: actions/setup-go@v5
with:
go-version: "1.25"

- name: Check out server repository code
uses: actions/checkout@v4
with:
path: go-fdo-server

# TODO: Update to upstream once RV bypass PR is merged in go-fdo-client

Check notice

Code scanning / devskim

A "TODO" or similar was left in source code, possibly indicating incomplete functionality Note

Suspicious comment
# Tracking: https://github.com/fido-device-onboard/go-fdo-client/pull/38
- name: Check out client repository code with RV bypass support
uses: actions/checkout@v4
with:
repository: sarmahaj/go-fdo-client
ref: pr20-rv-bypass-fixes
path: go-fdo-client

- name: Test RV bypass functionality
run: |
cd go-fdo-server
source test/container/test-rv-bypass.sh
run_test

- name: Get manufacturer and owner server logs
if: always()
run: |
cd go-fdo-server
source test/container/test-rv-bypass.sh
get_logs

- name: Cleanup the environment
if: always()
run: |
cd go-fdo-server
source test/container/test-rv-bypass.sh
cleanup
20 changes: 20 additions & 0 deletions deployments/compose/client/fdo-client-rv-bypass.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
services:
go-fdo-client:
container_name: go-fdo-client
hostname: go-fdo-client
image: go-fdo-client
# Build from local go-fdo-client directory with RV bypass support
# Path is relative to this compose file: deployments/compose/client/
# ../../../ goes to project root, then ../go-fdo-client to sibling dir
build: ../../../../go-fdo-client
working_dir: ${container_working_dir:-/workdir}/device-credentials
user: "${container_user}"
networks:
- fdo
volumes:
- ${base_dir:-./test/workdir}:${container_working_dir:-/workdir}
restart: no
networks:
fdo:
name: fdo
external: true
66 changes: 66 additions & 0 deletions deployments/compose/server/fdo-rv-bypass-servers.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
include:
- fdo-networks.yaml
services:
manufacturer:
container_name: manufacturer
hostname: manufacturer
image: manufacturer
build: ../../..
environment:
TZ: Europe/Madrid
user: ${container_user}
command:
- --db-type=sqlite
- --db-dsn=file:${container_working_dir:-/workdir}/manufacturer.db
- --log-level=debug
- manufacturing
- manufacturer:8038
- --manufacturing-key=${container_working_dir:-/workdir}/certs/manufacturer.key
- --owner-cert=${container_working_dir:-/workdir}/certs/owner.crt
- --device-ca-cert=${container_working_dir:-/workdir}/certs/device_ca.crt
- --device-ca-key=${container_working_dir:-/workdir}/certs/device_ca.key
working_dir: ${container_working_dir:-/workdir}
volumes:
- ${base_dir:-./test/workdir}:${container_working_dir:-/workdir}
networks:
- fdo
ports:
- 8038:8038
restart: unless-stopped
healthcheck:
test: [ "CMD", "curl --silent --output /dev/null --fail http://manufacturer:8038/health" ]
interval: 5s
timeout: 30s
retries: 5
start_period: 5s

owner:
container_name: owner
hostname: owner
image: owner
build: ../../..
environment:
TZ: Europe/Madrid
user: ${container_user}
command:
- --db-type=sqlite
- --db-dsn=file:${container_working_dir:-/workdir}/owner.db
- --log-level=debug
- owner
- owner:8043
- --owner-key=${container_working_dir:-/workdir}/certs/owner.key
- --device-ca-cert=${container_working_dir:-/workdir}/certs/device_ca.crt
working_dir: ${container_working_dir:-/workdir}
volumes:
- ${base_dir:-./test/workdir}:${container_working_dir:-/workdir}
networks:
- fdo
ports:
- 8043:8043
restart: unless-stopped
healthcheck:
test: [ "CMD", "curl --silent --output /dev/null --fail http://owner:8043/health" ]
interval: 5s
timeout: 30s
retries: 5
start_period: 5s
6 changes: 4 additions & 2 deletions scripts/fdo-utils.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ set_rendezvous_info () {
local rendezvous_ip=$3
local rendezvous_port=$4
local rendezvous_protocol=$5
local rendezvous_info="[{\"dns\": \"${rendezvous_dns}\", \"device_port\": \"${rendezvous_port}\", \"protocol\": \"${rendezvous_protocol}\", \"ip\": \"${rendezvous_ip}\", \"owner_port\": \"${rendezvous_port}\"}]"
local rv_bypass=$([[ "${6}" == "true" ]] && echo true || echo false)
local rendezvous_info="[{\"dns\": \"${rendezvous_dns}\", \"device_port\": \"${rendezvous_port}\", \"protocol\": \"${rendezvous_protocol}\", \"ip\": \"${rendezvous_ip}\", \"owner_port\": \"${rendezvous_port}\", \"rv_bypass\": ${rv_bypass}}]"
curl --fail --verbose --silent --insecure \
--request POST \
--header 'Content-Type: text/plain' \
Expand All @@ -28,7 +29,8 @@ update_rendezvous_info () {
local rendezvous_ip=$3
local rendezvous_port=$4
local rendezvous_protocol=$5
local rendezvous_info="[{\"dns\": \"${rendezvous_dns}\", \"device_port\": \"${rendezvous_port}\", \"protocol\": \"${rendezvous_protocol}\", \"ip\": \"${rendezvous_ip}\", \"owner_port\": \"${rendezvous_port}\"}]"
local rv_bypass=$([[ "${6}" == "true" ]] && echo true || echo false)
local rendezvous_info="[{\"dns\": \"${rendezvous_dns}\", \"device_port\": \"${rendezvous_port}\", \"protocol\": \"${rendezvous_protocol}\", \"ip\": \"${rendezvous_ip}\", \"owner_port\": \"${rendezvous_port}\", \"rv_bypass\": ${rv_bypass}}]"
curl --fail --verbose --silent --insecure \
--request PUT \
--header 'Content-Type: text/plain' \
Expand Down
99 changes: 99 additions & 0 deletions test/ci/test-rv-bypass.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#! /usr/bin/env bash
# RV bypass test: Device skips TO1 by getting Owner address directly from voucher (TO0 not needed)

set -euo pipefail

source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)/utils.sh"

verify_rv_bypass_behavior() {
local guid="$1"
local device_log="${logs_dir}/onboarding-device-${guid}.log"

echo " 🔍 Checking device onboard log for bypass indicators..."

# Device onboarding completed successfully
if grep -q "FIDO Device Onboard Complete" "${device_log}" || grep -q "Credential Reuse Protocol" "${device_log}"; then
echo " ✅ Device onboarding completed"
else
echo " ❌ Device onboarding did not complete"
cat "${device_log}"
return 1
fi

# Rendezvous service was NOT contacted (device skips TO1, no TO0 needed)
if [ -f "${rendezvous_log}" ]; then
echo " ❌ Rendezvous log exists but should not with RV bypass!"
return 1
fi
echo " ✅ Rendezvous service was not used (device skipped TO1)"

# Owner received TO2 directly (msg/60)
find_in_log_or_fail "${owner_log}" 'msg/60'
echo " ✅ Owner received TO2 protocol messages (direct connection)"

# Owner completed TO2 (msg/70)
find_in_log_or_fail "${owner_log}" 'msg/70'
echo " ✅ Owner completed TO2 protocol"

echo " 🎉 RV bypass behavior verified successfully!"
}

run_test() {

echo "⭐ Creating directories"
create_directories

echo "⭐ Cleaning up any old log files"
rm -f "${logs_dir}"/*.log

echo "⭐ Generating service certificates"
generate_service_certs

echo "⭐ Build and install 'go-fdo-client' binary"
install_client

echo "⭐ Build and install 'go-fdo-server' binary"
install_server

echo "⭐ Adding hostnames to /etc/hosts"
set_hostnames

echo "⭐ Start Manufacturing and Owner services (NO Rendezvous with bypass!)"
start_service "${manufacturer_service_name}"
start_service "${owner_service_name}"

echo "⭐ Wait for the services to be ready:"
wait_for_service_ready "${manufacturer_service_name}"
wait_for_service_ready "${owner_service_name}"

echo "⭐ Setting Rendezvous Info with RV BYPASS flag"
set_or_update_rendezvous_info "${manufacturer_url}" "${owner_service_name}" "${owner_dns}" "${owner_port}" "http" "true"

echo "⭐ Run Device Initialization"
run_device_initialization

guid=$(get_device_guid)
echo "⭐ Device initialized with GUID: ${guid}"

echo "⭐ Sending Ownership Voucher to the Owner"
send_manufacturer_ov_to_owner "${manufacturer_url}" "${guid}" "${owner_url}"

echo "⭐ Setting or updating Owner Redirect Info (RVTO2Addr)"
set_or_update_owner_redirect_info "${owner_url}" "${owner_service_name}" "${owner_dns}" "${owner_port}"

echo "⭐ SKIPPING TO0 (no need - device will skip TO1 via RV bypass)"

echo "⭐ Running FIDO Device Onboard with RV bypass"
run_fido_device_onboard --debug

echo "⭐ Saving container logs (no-op for binary tests)"
save_logs

echo "⭐ Verifying RV bypass behavior in logs"
verify_rv_bypass_behavior "${guid}"

echo "⭐ Success! ✅"
}

# Allow running directly
[[ "${BASH_SOURCE[0]}" != "$0" ]] || { run_test; cleanup; }
22 changes: 19 additions & 3 deletions test/ci/utils.sh
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,16 @@ stop_services() {
}

install_client() {
go install github.com/fido-device-onboard/go-fdo-client@latest
# Build from local clone with RV bypass support (pr20-rv-bypass-fixes branch)
# TODO: Change to @latest once RV bypass is merged to upstream main
# Tracking: https://github.com/fido-device-onboard/go-fdo-client/pull/38
local client_dir="../go-fdo-client"
if [ -d "${client_dir}" ]; then
(cd "${client_dir}" && git checkout pr20-rv-bypass-fixes && go build -o "$(go env GOPATH)/bin/go-fdo-client")
else
echo "WARNING: Local go-fdo-client not found, falling back to @latest (RV bypass not supported)" >&2
go install github.com/fido-device-onboard/go-fdo-client@latest
fi
}

uninstall_client() {
Expand Down Expand Up @@ -446,16 +455,17 @@ set_or_update_rendezvous_info() {
local rendezvous_dns=$3
local rendezvous_port=$4
local rendezvous_protocol=${5:-http}
local rv_bypass=${6:-false}

local real_rendezvous_ip
real_rendezvous_ip="$(get_real_ip "${rendezvous_service_name}")"
log_info "Checking if 'RendezvousInfo' is configured on manufacturer side (${manufacturer_url})"
if [ -z "$(get_rendezvous_info "${manufacturer_url}")" ]; then
log_warn "'RendezvousInfo' not found, creating it"
set_rendezvous_info "${manufacturer_url}" "${rendezvous_dns}" "${real_rendezvous_ip}" "${rendezvous_port}" "${rendezvous_protocol}"
set_rendezvous_info "${manufacturer_url}" "${rendezvous_dns}" "${real_rendezvous_ip}" "${rendezvous_port}" "${rendezvous_protocol}" "${rv_bypass}"
else
log_info "'RendezvousInfo' found, updating it"
update_rendezvous_info "${manufacturer_url}" "${rendezvous_dns}" "${real_rendezvous_ip}" "${rendezvous_port}" "${rendezvous_protocol}"
update_rendezvous_info "${manufacturer_url}" "${rendezvous_dns}" "${real_rendezvous_ip}" "${rendezvous_port}" "${rendezvous_protocol}" "${rv_bypass}"
fi
echo
}
Expand Down Expand Up @@ -541,6 +551,12 @@ remove_files() {
rm -vrf "${base_dir:?}"/*
}

save_logs() {
# No-op in binary tests (logs already go to files)
# Overridden in container tests to save Docker logs to files
:
}

cleanup() {
stop_services
unset_hostnames
Expand Down
12 changes: 12 additions & 0 deletions test/container/test-rv-bypass.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#! /usr/bin/env bash

set -euo pipefail

source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)/../ci/test-rv-bypass.sh"
source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)/utils.sh"

client_compose_file="deployments/compose/client/fdo-client-rv-bypass.yaml"
servers_compose_file="deployments/compose/server/fdo-rv-bypass-servers.yaml"

# Allow running directly
[[ "${BASH_SOURCE[0]}" != "$0" ]] || { run_test; cleanup; }
4 changes: 2 additions & 2 deletions test/container/utils.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ get_real_ip() {

set_hostnames() {
for service_name in $(docker compose -f ${servers_compose_file} config --services | grep -v db); do
service_dns="$(docker inspect "${service_name}" --format='{{index .NetworkSettings.Networks.fdo.Aliases 0}}')"
service_dns="$(docker inspect "${service_name}" --format='{{index .NetworkSettings.Networks.fdo.Aliases 0}}' 2>/dev/null || true)"
[ -n "${service_dns}" ] || service_dns="${service_name}"
set_hostname "$service_dns" "127.0.0.1"
done
Expand All @@ -34,7 +34,7 @@ set_hostnames() {
unset_hostnames() {
log_info "Removing hostnames from '/etc/hosts'"
for service_name in $(docker compose -f ${servers_compose_file} config --services "{{.Name}}" | grep -v db); do
service_dns="$(docker inspect "${service_name}" --format='{{index .NetworkSettings.Networks.fdo.Aliases 0}}')"
service_dns="$(docker inspect "${service_name}" --format='{{index .NetworkSettings.Networks.fdo.Aliases 0}}' 2>/dev/null || true)"
[ -n "${service_dns}" ] || service_dns="${service_name}"
unset_hostname "$service_dns" "127.0.0.1"
done
Expand Down
Loading