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
146 changes: 129 additions & 17 deletions snap/hooks/prepare-device
Original file line number Diff line number Diff line change
@@ -1,23 +1,135 @@
#!/bin/sh
# NOTE:
# -----
# This hook is intentionally commented out and provided for reference only.
#
# It documents an OpenSSL-based implementation of the device-side secure
# onboarding flow, but is NOT enabled by default.
#
# This avoids changing runtime behavior while making the reference
# implementation available for review, discussion, and future activation.
#
# To enable this hook, uncomment the script contents and ensure the hook
# is marked executable.

# This file is included for reference purposes. If MODEL_APIKEY is not set
# in snapcraft.yaml (as is the default), it is a no-op. For more about how
# to use this script to connect a device to an IoT App Store, see
# - https://ubuntu.com/core/services/guide/serial-vault-overview
# - https://ubuntu.com/core/services/guide/connecting-devices
# - https://snapcraft.io/docs/gadget-snap#heading--prepare

set -eu

if [ -z "$MODEL_APIKEY" ] ; then
exit 0
fi
# #!/bin/sh

exec >> $SNAP_COMMON/prepare-device-hook.log 2>&1
# # This hook implements the device-side portions of the Ubuntu Core secure
# # onboarding flow.
# #
# # Responsibilities:
# # - Optionally configure the device-service endpoint and authentication
# # headers when MODEL_APIKEY is provided (e.g. for Serial Vault or a
# # private Brand Store). If MODEL_APIKEY is not set, this part is a no-op
# # and snapd defaults are used.
# # - Generate and persist a hardware identity keypair (RSA-2048) using
# # OpenSSL. The private key is stored in SNAP_SAVE_DATA and is generated
# # only once per device.
# #
# # This hook intentionally does NOT:
# # - Perform any network operations
# # - Contact the device service directly
# # - Sign request-ids or construct registration payloads
# #
# # Cryptographic proof of identity is handled later by the
# # prepare-serial-request hook, which signs the request-id issued by snapd
# # using the hardware identity private key generated here.
# #
# # This implementation follows the Ubuntu Core secure onboarding design
# # # #
# # The OpenSSL-based hardware identity is compatible with the standard
# # RSA-SHA256 verification performed by the Model / Device Service.

# If you are forking and building your own gadget:
# implement your preferred way of generating a serial number for this device here
snapctl set registration.proposed-serial="\"$(date -u)\""

snapctl set device-service.url="https://serial-vault-partners.canonical.com/v1/"
snapctl set device-service.headers="{\"api-key\": \"$MODEL_APIKEY\"}"

# set -eu

# TAG="prepare-device"

# log_info() {
# printf "%s\n" "$1" | systemd-cat -t "$TAG" -p info
# }

# log_error() {
# printf "%s\n" "$1" | systemd-cat -t "$TAG" -p err
# }

# log_info "prepare-device: starting"

# # ----------------------------------------------------------------------
# # Resolve SNAP_DATA and SNAP_SAVE_DATA
# # ----------------------------------------------------------------------
# if [ -z "${SNAP_DATA:-}" ]; then
# log_error "SNAP_DATA is not set"
# exit 1
# fi

# if [ -z "${SNAP_SAVE_DATA:-}" ]; then
# SNAP_SAVE_DATA="$SNAP_DATA"
# fi

# LOG_FILE="$SNAP_DATA/prepare-device.log"

# echo "prepare-device: started" >> "$LOG_FILE"
# echo "SNAP_DATA=$SNAP_DATA" >> "$LOG_FILE"
# echo "SNAP_SAVE_DATA=$SNAP_SAVE_DATA" >> "$LOG_FILE"

# log_info "SNAP_DATA=$SNAP_DATA"
# log_info "SNAP_SAVE_DATA=$SNAP_SAVE_DATA"

# mkdir -p "$SNAP_SAVE_DATA"

# # ----------------------------------------------------------------------
# # OPTIONAL: Device-service / API configuration
# # ----------------------------------------------------------------------
# # This is a no-op unless MODEL_APIKEY is provided via snapcraft.yaml
# # ----------------------------------------------------------------------

# if [ -n "${MODEL_APIKEY:-}" ]; then
# log_info "MODEL_APIKEY provided — configuring device service"
# echo "MODEL_APIKEY provided" >> "$LOG_FILE"

# # Proposed serial MUST be a JSON string
# snapctl set registration.proposed-serial="\"$(date -u)\""

# # Serial / model service endpoint
# snapctl set device-service.url="https://serial-vault-partners.canonical.com/v1/"

# # API authentication header
# snapctl set device-service.headers="{\"api-key\":\"$MODEL_APIKEY\"}"
# else
# log_info "MODEL_APIKEY not set — skipping device-service configuration"
# echo "MODEL_APIKEY not set" >> "$LOG_FILE"
# fi

# # ----------------------------------------------------------------------
# # Generate hardware identity keypair (OpenSSL)
# # ----------------------------------------------------------------------
# KEY_PRIV="$SNAP_SAVE_DATA/hardware-id"
# KEY_PUB="$SNAP_SAVE_DATA/hardware-id.pub"

# if [ ! -f "$KEY_PRIV" ]; then
# log_info "Generating RSA-2048 hardware identity keypair"
# echo "Generating keypair at $KEY_PRIV" >> "$LOG_FILE"

# if ! openssl genrsa -out "$KEY_PRIV" 2048 >/dev/null 2>&1; then
# log_error "Failed to generate private key"
# exit 1
# fi

# if ! openssl rsa -in "$KEY_PRIV" -pubout -out "$KEY_PUB" >/dev/null 2>&1; then
# log_error "Failed to extract public key"
# exit 1
# fi

# log_info "Keypair created"
# echo "Keypair created" >> "$LOG_FILE"
# else
# log_info "hardware-id keypair already exists"
# echo "hardware-id exists" >> "$LOG_FILE"
# fi

# log_info "prepare-device: finished"
# echo "prepare-device: finished" >> "$LOG_FILE"
# exit 0
142 changes: 142 additions & 0 deletions snap/hooks/prepare-serial-request
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
# #!/bin/sh

# # This hook implements the device-side step of the
# # Ubuntu Core secure onboarding flow.
# #
# # Responsibilities:
# # - Retrieve the request-id issued by snapd for device registration
# # - Sign the request-id using the persistent hardware identity private
# # key generated by the prepare-device hook
# # - Construct the registration request payload (registration.body)
# # expected by snapd and the Model / Device Service
# #
# # The registration payload contains:
# # - The hardware identity public key (base64-encoded PEM)
# # - The SHA256 fingerprint of the public key
# # - The RSA-SHA256 signature of the request-id
# # - The signature hash algorithm identifier
# #
# # This hook intentionally does NOT:
# # - Generate or manage hardware identity keys
# # - Perform any network operations
# # - Contact the device service directly
# # - Configure device-service endpoints or authentication
# #
# # Hardware identity generation and optional device-service configuration
# # are handled by the prepare-device hook. This hook is executed only after
# # snapd has obtained a request-id from the configured device service.
# #
# # The cryptographic operations are implemented using OpenSSL and produce
# # RSA-SHA256 signatures compatible with standard Model / Device Service
# # verification.
# #
# # This implementation follows the Ubuntu Core secure onboarding design
# #



# set -eu

# TAG="prepare-serial-request"

# log_info() {
# printf "%s\n" "$1" | systemd-cat -t "$TAG" -p info
# }

# log_error() {
# printf "%s\n" "$1" | systemd-cat -t "$TAG" -p err
# }

# log_info "prepare-serial-request: starting"

# # ----------------------------------------------------------------------
# # Resolve SNAP_DATA + SNAP_SAVE_DATA
# # ----------------------------------------------------------------------
# if [ -z "${SNAP_DATA:-}" ]; then
# log_error "SNAP_DATA is not set"
# exit 1
# fi

# if [ -z "${SNAP_SAVE_DATA:-}" ]; then
# SNAP_SAVE_DATA="$SNAP_DATA"
# fi

# LOG_FILE="$SNAP_DATA/prepare-serial.log"
# echo "prepare-serial-request: started" >> "$LOG_FILE"

# # ----------------------------------------------------------------------
# # Get request-id
# # ----------------------------------------------------------------------
# RID="$(snapctl get registration.request-id 2>/dev/null || true)"

# if [ -z "$RID" ] && [ -f "$SNAP_DATA/request-id.txt" ]; then
# RID="$(cat "$SNAP_DATA/request-id.txt")"
# fi

# RID="$(printf "%s" "$RID")"

# if [ -z "$RID" ]; then
# log_error "No request-id"
# exit 1
# fi

# log_info "Using request-id: $RID"
# echo "request-id=$RID" >> "$LOG_FILE"

# # ----------------------------------------------------------------------
# # Key locations
# # ----------------------------------------------------------------------
# KEY_PRIV="$SNAP_SAVE_DATA/hardware-id"
# KEY_PUB="$SNAP_SAVE_DATA/hardware-id.pub"

# if [ ! -f "$KEY_PRIV" ]; then
# log_error "Missing hardware-id private key"
# exit 1
# fi

# # ----------------------------------------------------------------------
# # Prepare working directory
# # ----------------------------------------------------------------------
# WORK_DIR="$SNAP_SAVE_DATA/prepare-serial"
# mkdir -p "$WORK_DIR"

# PAYLOAD="$WORK_DIR/request-id.txt"
# printf "%s" "$RID" > "$PAYLOAD"

# # ----------------------------------------------------------------------
# # Sign request-id
# # ----------------------------------------------------------------------
# SIG_BIN="$WORK_DIR/sig.bin"
# SIG_B64="$WORK_DIR/sig.b64"

# openssl dgst -sha256 -sign "$KEY_PRIV" -out "$SIG_BIN" "$PAYLOAD"
# base64 < "$SIG_BIN" | tr -d '\n' > "$SIG_B64"

# # ----------------------------------------------------------------------
# # Base64 public key
# # ----------------------------------------------------------------------
# PUB_B64="$WORK_DIR/pub.b64"
# base64 < "$KEY_PUB" | tr -d '\n' > "$PUB_B64"

# # ----------------------------------------------------------------------
# # SHA256(pubkey)
# # ----------------------------------------------------------------------
# PUB_SHA="$WORK_DIR/pub.sha256"
# openssl dgst -sha256 "$KEY_PUB" | awk '{print $2}' > "$PUB_SHA"

# # ----------------------------------------------------------------------
# # Construct JSON for snapd
# # ----------------------------------------------------------------------
# OUT="$SNAP_DATA/registration.body"

# printf \
# '{"hardware-id-key":"%s","hardware-id-key-sha256":"%s","signature-hash-algorithm":"sha256","request-id-signature":"%s"}' \
# "$(cat "$PUB_B64")" \
# "$(cat "$PUB_SHA")" \
# "$(cat "$SIG_B64")" \
# > "$OUT"

# log_info "registration.body written"
# echo "registration.body written to $OUT" >> "$LOG_FILE"

# exit 0