#! /bin/bash harmony-ve-opnsense-img-src()( set -eu [ "${1:-}" != "-d" ] || { set -x ; shift ; } trap '[ "$?" = "0" ] || >&2 echo ABNORMAL TERMINATION' EXIT SCRIPTS_DIR=$(readlink -f "$(dirname "${BASH_SOURCE}")") . "${SCRIPTS_DIR}/common" OPNSENSE_SRC_BASE_URL=https://pkg.opnsense.org/releases ALT1_SRC_BASE_URL=https://mirror.vraphim.com/opnsense/releases ALT2_SRC_BASE_URL=https://mirror.winsub.kr/opnsense/releases DEFAULT_KVM_IMG_DIR=$HOME/.harmony-ve/img-src KVM_IMG_DIR=${KVM_IMG_DIR:-$DEFAULT_KVM_IMG_DIR} [ -d "$KVM_IMG_DIR" ] || mkdir -p "${KVM_IMG_DIR}" _short_help(){ cat <<-EOM NAME harmony-ve-opnsense-img-src DESCRIPTION Manage opnsense source images needed by Harmony Virtual Execution Environment SYNOPSYS harmony-vee-opnsense-img-src [GLOBAL_OPTIONS] COMMAND [OPTIONS] harmony-vee-opnsense-img-src list [--remote] harmony-vee-opnsense-img-src download [VERSION] harmony-vee-opnsense-img-src check [VERSION] harmony-vee-opnsense-img-src delete [VERSION] EOM } _extra_help(){ cat <<-EOM GLOBAL_OPTIONS -d Debug mode. WARNINGS This script is experimetal. Use with caution. DETAILS - for 'list', show local images available - for 'list --remote', show available upstream images - for 'download', when no VERSION is specified, use the latest - for 'delete', when no VERSION is specified, delete all image - use the 'nano' flavor EOM } # Implement functions _parse_version_from_image_file_string(){ #https://pkg.opnsense.org/releases/25.7/OPNsense-25.7-nano-amd64.img.bz2 echo "$1" | cut -d '/' -f 5 } _list_local_images(){ ls "${KVM_IMG_DIR}" | grep "OPNsense-" | grep "\-nano\-amd64\.img" | cut -d'-' -f 2 | sort -u -r } _list_remote_images(){ curl -L -s "${OPNSENSE_SRC_BASE_URL}" | sed 's/' -f 2 | cut -d '/' -f 1 | sort -r } _latest_version(){ _list_remote_images | head -n 1 } _is_downloaded(){ version=$1 name="${KVM_IMG_DIR}/OPNsense-${version}-nano-amd64.img" [ -f "$name" ] && return 0 || return 1 } _is_valid_version(){ version=${1} matched_version=$(_list_remote_images | grep "$version") [ "$matched_version" != "" ] && return 0 || return 1 } _download_img(){ version=$1 _download_crypto_files $version pushd "${KVM_IMG_DIR}" name="OPNsense-${version}-nano-amd64.img" compressed_name=$name.bz2 _is_downloaded $version && { _warn "Image '$name' is already downloaded" } || { url=$OPNSENSE_SRC_BASE_URL/$version/$compressed_name >&2 echo DOWNLOAD $url wget -q -c "${url}" _verify_image_checksum $version >&2 echo DECOMPRESS $url bzip2 -d $compressed_name } popd } _compare_files_checksum(){ file1=$1 file2=$2 sha256_1=$(openssl sha256 $file1 | cut -d" " -f2) sha256_2=$(openssl sha256 $file2 | cut -d" " -f2) [ "$sha256_1" = "$sha256_2" ] || return 1 } _download_crypto_files(){ # see: https://docs.opnsense.org/manual/install.html#download-and-verification version=$1 pushd "${KVM_IMG_DIR}" # download multiple pubkeys from different server pubkey="OPNsense-${version}.pub" rm -f $pubkey $pubkey.sig $pubkey.alt1 $pubkey.alt2 url=$OPNSENSE_SRC_BASE_URL/$version/$pubkey wget -q -c "${url}" # failing: wget -q -c "${url}.sig" rm -f /tmp/file.sig openssl base64 -d -in $pubkey.sig -out /tmp/file.sig openssl dgst -sha256 -verify $pubkey -signature /tmp/file.sig $pubkey || _fatal "Can't verify the signature of the public key" url_alt1=$ALT1_SRC_BASE_URL/$version/$pubkey wget -q -c -O "$pubkey.alt1" "${url_alt1}" url_alt2=$ALT2_SRC_BASE_URL/$version/$pubkey wget -q -c -O "$pubkey.alt2" "${url_alt2}" _compare_files_checksum $pubkey $pubkey.alt1 || { popd && _fatal "Fail to compare pubkeys" ; } _compare_files_checksum $pubkey $pubkey.alt2 || { popd && _fatal "Fail to compare pubkeys" ; } img_sig="OPNsense-${version}-nano-amd64.img.sig" sha256_name="OPNsense-${version}-checksums-amd64.sha256" sha256_sig=$sha256_name.sig [ ! -f "$img_sig" ] || rm $img_sig [ ! -f "$sha256_name" ] || rm $sha256_name [ ! -f "$sha256_sig" ] || rm $sha256_sig for file in $img_sig $sha256_name $sha256_sig; do url=$OPNSENSE_SRC_BASE_URL/$version/$file wget -q -c "${url}" done rm -f /tmp/file.sig openssl base64 -d -in $sha256_sig -out /tmp/file.sig openssl dgst -sha256 -verify $pubkey -signature /tmp/file.sig $sha256_name || _fatal "Can't verify the signature of the checksum file" popd } _download(){ version=${1:-} [ "${version:-}" != "" ] || _fatal "Must pass a VERSION for downloading" _is_valid_version $version || _fatal "'$version' is not a valid version number" _download_img ${version} } _verify_image_checksum(){ failed=1 version=$1 name="OPNsense-${version}-nano-amd64.img.bz2" sha256_file="OPNsense-${version}-checksums-amd64.sha256" pushd "${KVM_IMG_DIR}" sha256=$(cat $sha256_file | grep "$name" | cut -d'=' -f 2 | tr -s [:space:]) echo "$sha256 $name" | sha256sum -c || failed=0 popd [ "$failed" = "1" ] || _fatal "Checksum failed for '$name'" } _verify_image_signature(){ version=$1 pushd "${KVM_IMG_DIR}" # download multiple pubkeys from different server pubkey="OPNsense-${version}.pub" img_name="OPNsense-${version}-nano-amd64.img" img_sig="${img_name}.sig" rm -f /tmp/file.sig openssl base64 -d -in $img_sig -out /tmp/file.sig openssl dgst -sha256 -verify $pubkey -signature /tmp/file.sig $img_name || _fatal "Can't verify image signature" } _check(){ version=${1:-} if [ "${version:-}" = "" ] ; then for version in $(_list_local_images); do >&2 echo check $version _download_crypto_files $version _verify_image_signature $version done else _download_crypto_files $version _verify_image_signature $version fi } _delete(){ version=${1:-} if [ -z "${version:-1}" ]; then _clear pushd "${KVM_IMG_DIR}" rm -f *.img popd else pushd "${KVM_IMG_DIR}" rm -f *$version*.img popd fi } _clear(){ pushd "${KVM_IMG_DIR}" rm -f *.pub *.sig *.bz2 *.alt1 *.alt2 *.sha256 popd } case "${1:-}" in "") _short_help ;; -h|--help) _short_help _extra_help ;; ls|list) if [ "${2:-}" == "" ]; then _list_local_images elif [ "${2:-}" == "--remote" ]; then _list_remote_images else _warn "Unknown option '$2'" fi ;; download) _download "${2:-"$(_latest_version)"}" ;; delete) _delete "${@:2}" ;; check) _check "${@:2}" ;; show) ls $KVM_IMG_DIR | cat ;; clear) _clear "${@:2}" ;; *) _warn "Unknown COMMAND '$1'" exit 1 ;; esac ) [ "$0" != "${BASH_SOURCE}" ] || harmony-ve-opnsense-img-src "${@}" # todo: refactor # todo: enhance output management