diff --git a/examples/opnsense/scripts/common b/examples/opnsense/scripts/common index e0b4424..f1d5119 100644 --- a/examples/opnsense/scripts/common +++ b/examples/opnsense/scripts/common @@ -7,3 +7,11 @@ _fatal(){ >&2 echo stopping... exit 1 } + +pushd () { + command pushd "$@" > /dev/null +} + +popd () { + command popd "$@" > /dev/null +} diff --git a/examples/opnsense/scripts/harmony-ve-opnsense-img-src b/examples/opnsense/scripts/harmony-ve-opnsense-img-src index dd8fb68..3aeab83 100755 --- a/examples/opnsense/scripts/harmony-ve-opnsense-img-src +++ b/examples/opnsense/scripts/harmony-ve-opnsense-img-src @@ -11,12 +11,13 @@ harmony-ve-opnsense-img-src()( SCRIPTS_DIR=$(readlink -f "$(dirname "${BASH_SOURCE}")") . "${SCRIPTS_DIR}/common" - OPNSENSE_SRC_BASE_URL=https://pkg.opnsense.org/releases/ - DEFAULT_KVM_IMG_DIR=/var/lib/libvirt/images + 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 @@ -34,8 +35,8 @@ harmony-ve-opnsense-img-src()( harmony-vee-opnsense-img-src [GLOBAL_OPTIONS] COMMAND [OPTIONS] harmony-vee-opnsense-img-src list [--remote] - harmony-vee-opnsense-img-src check [VERSION] harmony-vee-opnsense-img-src download [VERSION] + harmony-vee-opnsense-img-src check [VERSION] harmony-vee-opnsense-img-src delete [VERSION] EOM @@ -58,7 +59,7 @@ EOM - for 'list', show local images available - for 'list --remote', show available upstream images - - for 'check' and 'download', when no VERSION is specified, use the latest + - 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 @@ -67,6 +68,223 @@ 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 @@ -77,7 +295,31 @@ case "${1:-}" in _short_help _extra_help ;; - # Commands entrypoints + 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 @@ -89,3 +331,6 @@ esac [ "$0" != "${BASH_SOURCE}" ] || harmony-ve-opnsense-img-src "${@}" + +# todo: refactor +# todo: enhance output management